Skip to content

Conversation

@aashikgowda
Copy link
Contributor

@aashikgowda aashikgowda commented Nov 5, 2025

Checklist

  • I have read the Contributing Guide
  • I have checked to ensure this does not introduce an unintended breaking changes
  • I have considered appropriate testing for my change

Description

  • Added a new function in PostgresqlExtensions which takes in an owner name. The owner username defaults to the username in the connection string if there is no owner name specified.
  • Added a check and throw an exception for owner username if it does not exist
  • CREATE DATABASE sql is now updated to execute WITH OWNER
  • Resolves Allow creating PostgreSQL database "with owner" #3
  • Added missing comments for existing functions to create a database

@droyad droyad requested a review from Copilot November 6, 2025 04:37
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for specifying a database owner when creating PostgreSQL databases and includes code formatting improvements. The key changes include:

  • Adding an optional owner parameter to the PostgresqlDatabase method for database creation with ownership assignment
  • Implementing role validation before database creation
  • Removing obsolete method overloads from the public API
  • Applying consistent code formatting (spacing, indentation)

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/dbup-postgresql/PostgresqlExtensions.cs Added new method overload with owner parameter, implemented role existence validation, updated CREATE DATABASE SQL to include owner clause, and applied formatting fixes
src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs Updated approved public API surface to reflect removal of deprecated methods and addition of new owner parameter overload

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 269 to 275
sqlCommandText = $"select 1 from pg_roles where rolname = \'{owner}\' limit 1;";
// check to see if the owner exists..
using (var command = new NpgsqlCommand(sqlCommandText, connection)
{
CommandType = CommandType.Text
})
{
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SQL injection vulnerability: the owner parameter is interpolated directly into the SQL query using single quotes. Use parameterized queries with NpgsqlParameter to prevent SQL injection attacks.

Suggested change
sqlCommandText = $"select 1 from pg_roles where rolname = \'{owner}\' limit 1;";
// check to see if the owner exists..
using (var command = new NpgsqlCommand(sqlCommandText, connection)
{
CommandType = CommandType.Text
})
{
sqlCommandText = "select 1 from pg_roles where rolname = @owner limit 1;";
// check to see if the owner exists..
using (var command = new NpgsqlCommand(sqlCommandText, connection)
{
CommandType = CommandType.Text
})
{
command.Parameters.AddWithValue("@owner", owner);

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well... it's unlikely SQLi would happen this way, but I don't think it hurts to do it this way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the SQL command to take in parameters instead.

Comment on lines 276 to 279
var results = Convert.ToInt32(command.ExecuteScalar());

// if the owner role does not exist, we throw an exception.
if (results == 0)
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential null reference exception: ExecuteScalar() can return null when no rows are found. The code should handle the null case explicitly before converting to Int32, e.g., var results = command.ExecuteScalar() as int? ?? 0;

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds right based on my SQL Server knowledge. If owner does not exist, no rows are returned (since it doesn't use Count(*).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Convert.ToInt32 can take in a null object and return a zero for null objects.

However, to keep it cleaner, I updated the SQL to return a boolean instead which makes it more readable.

}
}

sqlCommandText = $"create database \"{databaseName}\" with owner = \"{owner}\";";
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SQL injection vulnerability: both databaseName and owner are directly interpolated into the CREATE DATABASE statement. While PostgreSQL doesn't support parameterized DDL, consider validating these identifiers (e.g., checking they only contain alphanumeric characters and underscores) or using identifier quoting functions to prevent injection.

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SQLi via connection string...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed it by formatting using helper functions.

Copy link
Member

@droyad droyad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On change that is breaking that I'd like to avoid. Also some Co-pilot suggestions. The SQLi ones are a stretch though.

Comment on lines 235 to 236
owner = string.IsNullOrWhiteSpace(owner) ? masterConnectionStringBuilder.Username : owner;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to CoPilot

The default owner of the new database is the user executing the CREATE DATABASE command

However

The [user[:password]@] part is optional. If omitted, most PostgreSQL clients will default to using the operating system's current username (the user running the client) for authentication

Confirmed via the docs.

So I think the best approach would be to not do this line and keep the existing statement if owner is null. If it's not null the new check for existance and with owner should be used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The [user[:password]@] part is optional. If omitted, most PostgreSQL clients will default to using the operating system's current username (the user running the client) for authentication

I missed out on this part. Updated as per your suggestion.

@droyad droyad self-assigned this Nov 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow creating PostgreSQL database "with owner"

2 participants