Skip to content

Commit

Permalink
Merge branch 'release/6.0.0' into targetNet8
Browse files Browse the repository at this point in the history
  • Loading branch information
droyad committed Dec 10, 2024
2 parents 00b2fa0 + 49956ad commit 1f95905
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 163 deletions.
125 changes: 62 additions & 63 deletions src/dbup-postgresql/PostgresqlConnectionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,79 +4,78 @@
using DbUp.Engine.Transactions;
using Npgsql;

namespace DbUp.Postgresql
namespace DbUp.Postgresql;

/// <summary>
/// Manages PostgreSQL database connections.
/// </summary>
public class PostgresqlConnectionManager : DatabaseConnectionManager
{
/// <summary>
/// Manages PostgreSQL database connections.
/// Disallow single quotes to be escaped with a backslash (\')
/// </summary>
public bool StandardConformingStrings { get; set; } = true;

/// <summary>
/// Creates a new PostgreSQL database connection.
/// </summary>
public class PostgresqlConnectionManager : DatabaseConnectionManager
/// <param name="connectionString">The PostgreSQL connection string.</param>
public PostgresqlConnectionManager(string connectionString)
: base(new DelegateConnectionFactory(l => new NpgsqlConnection(connectionString)))
{
/// <summary>
/// Disallow single quotes to be escaped with a backslash (\')
/// </summary>
public bool StandardConformingStrings { get; set; } = true;
}

/// <summary>
/// Creates a new PostgreSQL database connection.
/// </summary>
/// <param name="connectionString">The PostgreSQL connection string.</param>
public PostgresqlConnectionManager(string connectionString)
: base(new DelegateConnectionFactory(l => new NpgsqlConnection(connectionString)))
/// <summary>
/// Creates a new PostgreSQL database connection with a certificate.
/// </summary>
/// <param name="connectionString">The PostgreSQL connection string.</param>
/// <param name="certificate">Certificate for securing connection.</param>
public PostgresqlConnectionManager(string connectionString, X509Certificate2 certificate)
: this(connectionString, new PostgresqlConnectionOptions
{
}
ClientCertificate = certificate
})
{
}

/// <summary>
/// Creates a new PostgreSQL database connection with a certificate.
/// </summary>
/// <param name="connectionString">The PostgreSQL connection string.</param>
/// <param name="certificate">Certificate for securing connection.</param>
public PostgresqlConnectionManager(string connectionString, X509Certificate2 certificate)
: this(connectionString, new PostgresqlConnectionOptions
/// <summary>
/// Create a new PostgreSQL database connection
/// </summary>
/// <param name="connectionString">The PostgreSQL connection string.</param>
/// <param name="connectionOptions">Custom options to apply on the created connection</param>
public PostgresqlConnectionManager(string connectionString, PostgresqlConnectionOptions connectionOptions)
: base(new DelegateConnectionFactory(l =>
{
ClientCertificate = certificate
})
{
}

/// <summary>
/// Create a new PostgreSQL database connection
/// </summary>
/// <param name="connectionString">The PostgreSQL connection string.</param>
/// <param name="connectionOptions">Custom options to apply on the created connection</param>
public PostgresqlConnectionManager(string connectionString, PostgresqlConnectionOptions connectionOptions)
: base(new DelegateConnectionFactory(l =>
{
NpgsqlConnection databaseConnection = new NpgsqlConnection(connectionString);
databaseConnection.ApplyConnectionOptions(connectionOptions);
NpgsqlConnection databaseConnection = new NpgsqlConnection(connectionString);
databaseConnection.ApplyConnectionOptions(connectionOptions);

return databaseConnection;
}
))
{
}
return databaseConnection;
}
))
{
}

/// <summary>
/// Creates a new PostgreSQL database connection with a NpgsqlDatasource
/// </summary>
/// <param name="datasource">The PostgreSQL NpgsqlDataSource.</param>
public PostgresqlConnectionManager(NpgsqlDataSource datasource)
: base(new DelegateConnectionFactory(l => datasource.CreateConnection()))
{
}
/// <summary>
/// Creates a new PostgreSQL database connection with a NpgsqlDatasource
/// </summary>
/// <param name="datasource">The PostgreSQL NpgsqlDataSource.</param>
public PostgresqlConnectionManager(NpgsqlDataSource datasource)
: base(new DelegateConnectionFactory(l => datasource.CreateConnection()))
{
}

/// <summary>
/// Splits the statements in the script using the ";" character.
/// </summary>
/// <param name="scriptContents">The contents of the script to split.</param>
public override IEnumerable<string> SplitScriptIntoCommands(string scriptContents)
{
var scriptStatements =
PostgresqlQueryParser.ParseRawQuery(scriptContents, StandardConformingStrings)
.Select(x => x.Trim())
.Where(x => x.Length > 0)
.ToArray();
/// <summary>
/// Splits the statements in the script using the ";" character.
/// </summary>
/// <param name="scriptContents">The contents of the script to split.</param>
public override IEnumerable<string> SplitScriptIntoCommands(string scriptContents)
{
var scriptStatements =
PostgresqlQueryParser.ParseRawQuery(scriptContents, StandardConformingStrings)
.Select(x => x.Trim())
.Where(x => x.Length > 0)
.ToArray();

return scriptStatements;
}
return scriptStatements;
}
}
}
18 changes: 6 additions & 12 deletions src/dbup-postgresql/PostgresqlObjectParser.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
using DbUp.Support;

namespace DbUp.Postgresql
{
/// <summary>
/// Parses Sql Objects and performs quoting functions.
/// </summary>
public class PostgresqlObjectParser : SqlObjectParser
{
public PostgresqlObjectParser() : base("\"", "\"")
{
}
}
}
namespace DbUp.Postgresql;

/// <summary>
/// Parses Sql Objects and performs quoting functions.
/// </summary>
public class PostgresqlObjectParser() : SqlObjectParser("\"", "\"");
19 changes: 9 additions & 10 deletions src/dbup-postgresql/PostgresqlPreprocessor.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
using DbUp.Engine;

namespace DbUp.Postgresql
namespace DbUp.Postgresql;

/// <summary>
/// This preprocessor makes adjustments to your sql to make it compatible with PostgreSQL.
/// </summary>
public class PostgresqlPreprocessor : IScriptPreprocessor
{
/// <summary>
/// This preprocessor makes adjustments to your sql to make it compatible with PostgreSQL.
/// Performs some preprocessing step on a PostgreSQL script.
/// </summary>
public class PostgresqlPreprocessor : IScriptPreprocessor
{
/// <summary>
/// Performs some preprocessing step on a PostgreSQL script.
/// </summary>
public string Process(string contents) => contents;
}
}
public string Process(string contents) => contents;
}
61 changes: 30 additions & 31 deletions src/dbup-postgresql/PostgresqlScriptExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,42 @@
using DbUp.Support;
using Npgsql;

namespace DbUp.Postgresql
namespace DbUp.Postgresql;

/// <summary>
/// An implementation of <see cref="ScriptExecutor"/> that executes against a PostgreSQL database.
/// </summary>
public class PostgresqlScriptExecutor : ScriptExecutor
{
/// <summary>
/// An implementation of <see cref="ScriptExecutor"/> that executes against a PostgreSQL database.
/// Initializes an instance of the <see cref="PostgresqlScriptExecutor"/> class.
/// </summary>
public class PostgresqlScriptExecutor : ScriptExecutor
/// <param name="connectionManagerFactory"></param>
/// <param name="log">The logging mechanism.</param>
/// <param name="schema">The schema that contains the table.</param>
/// <param name="variablesEnabled">Function that returns <c>true</c> if variables should be replaced, <c>false</c> otherwise.</param>
/// <param name="scriptPreprocessors">Script Preprocessors in addition to variable substitution</param>
/// <param name="journalFactory">Database journal</param>
public PostgresqlScriptExecutor(Func<IConnectionManager> connectionManagerFactory, Func<IUpgradeLog> log, string schema, Func<bool> variablesEnabled,
IEnumerable<IScriptPreprocessor> scriptPreprocessors, Func<IJournal> journalFactory)
: base(connectionManagerFactory, new PostgresqlObjectParser(), log, schema, variablesEnabled, scriptPreprocessors, journalFactory)
{
/// <summary>
/// Initializes an instance of the <see cref="PostgresqlScriptExecutor"/> class.
/// </summary>
/// <param name="connectionManagerFactory"></param>
/// <param name="log">The logging mechanism.</param>
/// <param name="schema">The schema that contains the table.</param>
/// <param name="variablesEnabled">Function that returns <c>true</c> if variables should be replaced, <c>false</c> otherwise.</param>
/// <param name="scriptPreprocessors">Script Preprocessors in addition to variable substitution</param>
/// <param name="journalFactory">Database journal</param>
public PostgresqlScriptExecutor(Func<IConnectionManager> connectionManagerFactory, Func<IUpgradeLog> log, string schema, Func<bool> variablesEnabled,
IEnumerable<IScriptPreprocessor> scriptPreprocessors, Func<IJournal> journalFactory)
: base(connectionManagerFactory, new PostgresqlObjectParser(), log, schema, variablesEnabled, scriptPreprocessors, journalFactory)
{
}
}

protected override string GetVerifySchemaSql(string schema) => $"CREATE SCHEMA IF NOT EXISTS {schema}";
protected override string GetVerifySchemaSql(string schema) => $"CREATE SCHEMA IF NOT EXISTS {schema}";

protected override void ExecuteCommandsWithinExceptionHandler(int index, SqlScript script, Action executeCommand)
protected override void ExecuteCommandsWithinExceptionHandler(int index, SqlScript script, Action executeCommand)
{
try
{
executeCommand();
}
catch (PostgresException exception)
{
try
{
executeCommand();
}
catch (PostgresException exception)
{
Log().LogInformation("Npgsql exception has occurred in script: '{0}'", script.Name);
Log().LogError("Script block number: {0}; Block line {1}; Position: {2}; Message: {3}", index, exception.Line, exception.Position, exception.Message);
Log().LogError(exception.ToString());
throw;
}
Log().LogInformation("Npgsql exception has occurred in script: '{0}'", script.Name);
Log().LogError("Script block number: {0}; Block line {1}; Position: {2}; Message: {3}", index, exception.Line, exception.Position, exception.Message);
Log().LogError(exception.ToString());
throw;
}
}
}
}
93 changes: 46 additions & 47 deletions src/dbup-postgresql/PostgresqlTableJournal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,70 +5,69 @@
using DbUp.Engine.Transactions;
using DbUp.Support;

namespace DbUp.Postgresql
namespace DbUp.Postgresql;

/// <summary>
/// An implementation of the <see cref="IJournal"/> interface which tracks version numbers for a
/// PostgreSQL database using a table called SchemaVersions.
/// </summary>
public class PostgresqlTableJournal : TableJournal
{
/// <summary>
/// An implementation of the <see cref="IJournal"/> interface which tracks version numbers for a
/// PostgreSQL database using a table called SchemaVersions.
/// Creates a new PostgreSQL table journal.
/// </summary>
public class PostgresqlTableJournal : TableJournal
/// <param name="connectionManager">The PostgreSQL connection manager.</param>
/// <param name="logger">The upgrade logger.</param>
/// <param name="schema">The name of the schema the journal is stored in.</param>
/// <param name="tableName">The name of the journal table.</param>
public PostgresqlTableJournal(Func<IConnectionManager> connectionManager, Func<IUpgradeLog> logger, string schema, string tableName)
: base(connectionManager, logger, new PostgresqlObjectParser(), schema, tableName)
{
/// <summary>
/// Creates a new PostgreSQL table journal.
/// </summary>
/// <param name="connectionManager">The PostgreSQL connection manager.</param>
/// <param name="logger">The upgrade logger.</param>
/// <param name="schema">The name of the schema the journal is stored in.</param>
/// <param name="tableName">The name of the journal table.</param>
public PostgresqlTableJournal(Func<IConnectionManager> connectionManager, Func<IUpgradeLog> logger, string schema, string tableName)
: base(connectionManager, logger, new PostgresqlObjectParser(), schema, tableName)
{
}
}

protected override IDbCommand GetInsertScriptCommand(Func<IDbCommand> dbCommandFactory, SqlScript script)
{
// EnableSqlRewriting is enabled by default, and needs to be explicitly disabled
bool enableSqlRewriting = !AppContext.TryGetSwitch("Npgsql.EnableSqlRewriting", out bool enabled) || enabled;
protected override IDbCommand GetInsertScriptCommand(Func<IDbCommand> dbCommandFactory, SqlScript script)
{
// EnableSqlRewriting is enabled by default, and needs to be explicitly disabled
bool enableSqlRewriting = !AppContext.TryGetSwitch("Npgsql.EnableSqlRewriting", out bool enabled) || enabled;

if (enableSqlRewriting)
return base.GetInsertScriptCommand(dbCommandFactory, script);
if (enableSqlRewriting)
return base.GetInsertScriptCommand(dbCommandFactory, script);

// Use positional parameters instead of named parameters
var command = dbCommandFactory();
// Use positional parameters instead of named parameters
var command = dbCommandFactory();

var scriptNameParam = command.CreateParameter();
scriptNameParam.Value = script.Name;
command.Parameters.Add(scriptNameParam);
var scriptNameParam = command.CreateParameter();
scriptNameParam.Value = script.Name;
command.Parameters.Add(scriptNameParam);

var appliedParam = command.CreateParameter();
appliedParam.Value = DateTime.Now;
command.Parameters.Add(appliedParam);
var appliedParam = command.CreateParameter();
appliedParam.Value = DateTime.Now;
command.Parameters.Add(appliedParam);

command.CommandText = GetInsertJournalEntrySql("$1", "$2");
command.CommandType = CommandType.Text;
return command;
}
command.CommandText = GetInsertJournalEntrySql("$1", "$2");
command.CommandType = CommandType.Text;
return command;
}

protected override string GetInsertJournalEntrySql(string scriptName, string applied)
{
return $"insert into {FqSchemaTableName} (ScriptName, Applied) values ({scriptName}, {applied})";
}
protected override string GetInsertJournalEntrySql(string scriptName, string applied)
{
return $"insert into {FqSchemaTableName} (ScriptName, Applied) values ({scriptName}, {applied})";
}

protected override string GetJournalEntriesSql()
{
return $"select ScriptName from {FqSchemaTableName} order by ScriptName";
}
protected override string GetJournalEntriesSql()
{
return $"select ScriptName from {FqSchemaTableName} order by ScriptName";
}

protected override string CreateSchemaTableSql(string quotedPrimaryKeyName)
{
return
$@"CREATE TABLE {FqSchemaTableName}
protected override string CreateSchemaTableSql(string quotedPrimaryKeyName)
{
return
$@"CREATE TABLE {FqSchemaTableName}
(
schemaversionsid serial NOT NULL,
scriptname character varying(255) NOT NULL,
applied timestamp without time zone NOT NULL,
CONSTRAINT {quotedPrimaryKeyName} PRIMARY KEY (schemaversionsid)
)";
}
}
}
}

0 comments on commit 1f95905

Please sign in to comment.