Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Postgres DB List Database Mangling #290

Merged
merged 7 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

- Listing databases on Postgres now respects connection string database and timeout

## [3.2.5] - 2024-06-07

- Bugfix for resource lifetime in ListDatabasesAsync, add unit tests
Expand Down
19 changes: 9 additions & 10 deletions FAnsiSql/Implementations/PostgreSql/PostgreSqlServerHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,29 +33,28 @@
public override void CreateDatabase(DbConnectionStringBuilder builder, IHasRuntimeName newDatabaseName)
{
var b = (NpgsqlConnectionStringBuilder)GetConnectionStringBuilder(builder.ConnectionString);
b.Database = null;

using var con = new NpgsqlConnection(b.ConnectionString);
con.Open();
using var cmd = GetCommand($"CREATE DATABASE \"{newDatabaseName.GetRuntimeName()}\"",con);
using var cmd = GetCommand($"CREATE DATABASE \"{newDatabaseName.GetRuntimeName()}\"", con);
cmd.CommandTimeout = CreateDatabaseTimeoutInSeconds;
cmd.ExecuteNonQuery();
}

public override Dictionary<string, string> DescribeServer(DbConnectionStringBuilder builder) => throw new NotImplementedException();

public override string? GetExplicitUsernameIfAny(DbConnectionStringBuilder builder) => ((NpgsqlConnectionStringBuilder) builder).Username;
public override string? GetExplicitUsernameIfAny(DbConnectionStringBuilder builder) => ((NpgsqlConnectionStringBuilder)builder).Username;

public override string? GetExplicitPasswordIfAny(DbConnectionStringBuilder builder) => ((NpgsqlConnectionStringBuilder) builder).Password;
public override string? GetExplicitPasswordIfAny(DbConnectionStringBuilder builder) => ((NpgsqlConnectionStringBuilder)builder).Password;

public override Version? GetVersion(DiscoveredServer server)
{
using var con = server.GetConnection();
con.Open();
using var cmd = server.GetCommand("SHOW server_version",con);
using var cmd = server.GetCommand("SHOW server_version", con);
using var r = cmd.ExecuteReader();
if(r.Read())
return r[0] == DBNull.Value ? null: CreateVersionFromString((string)r[0]);
if (r.Read())
return r[0] == DBNull.Value ? null : CreateVersionFromString((string)r[0]);

return null;
}
Expand All @@ -64,10 +63,10 @@
public override IEnumerable<string> ListDatabases(DbConnectionStringBuilder builder)
{
//create a copy so as not to corrupt the original

var b = new NpgsqlConnectionStringBuilder(builder.ConnectionString)
{
Database = null,
Timeout = 5
Timeout = builder.TryGetValue("Timeout", out var timeout) ? (int)timeout : 5
};

using var con = new NpgsqlConnection(b.ConnectionString);
Expand All @@ -88,13 +87,13 @@

public override DbDataAdapter GetDataAdapter(DbCommand cmd) => new NpgsqlDataAdapter((NpgsqlCommand)cmd);

public override DbCommandBuilder GetCommandBuilder(DbCommand cmd) => new NpgsqlCommandBuilder(new NpgsqlDataAdapter((NpgsqlCommand) cmd));
public override DbCommandBuilder GetCommandBuilder(DbCommand cmd) => new NpgsqlCommandBuilder(new NpgsqlDataAdapter((NpgsqlCommand)cmd));

public override DbParameter GetParameter(string parameterName) => new NpgsqlParameter { ParameterName = parameterName };

public override DbConnection GetConnection(DbConnectionStringBuilder builder) => new NpgsqlConnection(builder.ConnectionString);

protected override DbConnectionStringBuilder GetConnectionStringBuilderImpl(string server, string database,

Check warning on line 96 in FAnsiSql/Implementations/PostgreSql/PostgreSqlServerHelper.cs

View workflow job for this annotation

GitHub Actions / build

Nullability of type of parameter 'database' doesn't match overridden member (possibly because of nullability attributes).

Check warning on line 96 in FAnsiSql/Implementations/PostgreSql/PostgreSqlServerHelper.cs

View workflow job for this annotation

GitHub Actions / build

Nullability of type of parameter 'database' doesn't match overridden member (possibly because of nullability attributes).
string username, string password)
{
var toReturn = new NpgsqlConnectionStringBuilder
Expand Down
8 changes: 5 additions & 3 deletions Tests/FAnsiTests/CrossPlatformTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -793,9 +793,12 @@ public void HorribleDatabaseAndTableNames(DatabaseType type,string horribleDatab
var database = GetTestDatabase(type);

SqlConnection.ClearAllPools();
if (type == DatabaseType.PostgreSql)
database.Server.CreateDatabase(horribleDatabaseName);

database = database.Server.ExpectDatabase(horribleDatabaseName);
database.Create(true);
if(type != DatabaseType.PostgreSql)
database.Create(true);

SqlConnection.ClearAllPools();

Expand Down Expand Up @@ -918,9 +921,8 @@ public void HorribleColumnNames(DatabaseType type, string horribleDatabaseName,
AssertCanCreateDatabases();

var database = GetTestDatabase(type);

database.Server.CreateDatabase(horribleDatabaseName);
database = database.Server.ExpectDatabase(horribleDatabaseName);
database.Create(true);
Assert.That(database.GetRuntimeName(), Is.EqualTo(horribleDatabaseName).IgnoreCase);

try
Expand Down
31 changes: 20 additions & 11 deletions Tests/FAnsiTests/DatabaseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@
using FAnsi.Implementations.MicrosoftSQL;
using FAnsi.Implementations.PostgreSql;
using NUnit.Framework;
using NUnit.Framework.Internal;

namespace FAnsiTests;

[SingleThreaded]
[NonParallelizable]
public class DatabaseTests
{
protected readonly Dictionary<DatabaseType,string> TestConnectionStrings = [];
protected readonly Dictionary<DatabaseType, string> TestConnectionStrings = [];

private bool _allowDatabaseCreation;
private string _testScratchDatabase;
Expand All @@ -39,11 +40,11 @@ public void CheckFiles()

var file = Path.Combine(TestContext.CurrentContext.TestDirectory, TestFilename);

Assert.That(File.Exists(file),"Could not find " + TestFilename);
Assert.That(File.Exists(file), "Could not find " + TestFilename);

var doc = XDocument.Load(file);

var root = doc.Element("TestDatabases")??throw new Exception($"Missing element 'TestDatabases' in {TestFilename}");
var root = doc.Element("TestDatabases") ?? throw new Exception($"Missing element 'TestDatabases' in {TestFilename}");

var settings = root.Element("Settings") ??
throw new Exception($"Missing element 'Settings' in {TestFilename}");
Expand All @@ -62,13 +63,21 @@ public void CheckFiles()
{
var type = element.Element("DatabaseType")?.Value;

if(!Enum.TryParse(type, out DatabaseType databaseType))
if (!Enum.TryParse(type, out DatabaseType databaseType))
throw new Exception($"Could not parse DatabaseType {type}");


var constr = element.Element("ConnectionString")?.Value;

TestConnectionStrings.Add(databaseType,constr);
TestConnectionStrings.Add(databaseType, constr);
}
if (TestConnectionStrings.ContainsKey(DatabaseType.PostgreSql))
{
var server = GetTestServer(DatabaseType.PostgreSql);
if (!server.DiscoverDatabases().ToList().Any(db => db.GetWrappedName().Contains(_testScratchDatabase)))
{
server.CreateDatabase(_testScratchDatabase);
}
}
}
catch (Exception exception)
Expand All @@ -85,19 +94,19 @@ protected IEnumerable<DiscoveredServer> TestServer()
}
protected DiscoveredServer GetTestServer(DatabaseType type)
{
if(!TestConnectionStrings.ContainsKey(type))
if (!TestConnectionStrings.ContainsKey(type))
Assert.Inconclusive("No connection string configured for that server");

return new DiscoveredServer(TestConnectionStrings[type], type);
}

protected DiscoveredDatabase GetTestDatabase(DatabaseType type, bool cleanDatabase=true)
protected DiscoveredDatabase GetTestDatabase(DatabaseType type, bool cleanDatabase = true)
{
var server = GetTestServer(type);
var db = server.ExpectDatabase(_testScratchDatabase);

if(!db.Exists())
if(_allowDatabaseCreation)
if (!db.Exists())
if (_allowDatabaseCreation)
db.Create();
else
Assert.Inconclusive(
Expand Down Expand Up @@ -131,7 +140,7 @@ protected DiscoveredDatabase GetTestDatabase(DatabaseType type, bool cleanDataba

protected void AssertCanCreateDatabases()
{
if(!_allowDatabaseCreation)
if (!_allowDatabaseCreation)
Assert.Inconclusive("Test cannot run when AllowDatabaseCreation is false");
}

Expand Down Expand Up @@ -165,7 +174,7 @@ protected static void AssertAreEqual(DataTable dt1, DataTable dt2)

foreach (DataRow row1 in dt1.Rows)
{
var match = dt2.Rows.Cast<DataRow>().Any(row2=> dt1.Columns.Cast<DataColumn>().All(c => AreBasicallyEquals(row1[c.ColumnName], row2[c.ColumnName])));
var match = dt2.Rows.Cast<DataRow>().Any(row2 => dt1.Columns.Cast<DataColumn>().All(c => AreBasicallyEquals(row1[c.ColumnName], row2[c.ColumnName])));
Assert.That(match, $"Couldn't find match for row:{string.Join(",", row1.ItemArray)}");
}

Expand Down
12 changes: 7 additions & 5 deletions Tests/FAnsiTests/Table/LongNamesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ namespace FAnsiTests.Table;

internal sealed class LongNamesTests : DatabaseTests
{
[TestCaseSource(typeof(All),nameof(All.DatabaseTypes))]
[TestCaseSource(typeof(All), nameof(All.DatabaseTypes))]
public void Test_LongTableName_CreateAndReadBack(DatabaseType dbType)
{
var db = GetTestDatabase(dbType);

var tableName = new StringBuilder(db.Server.GetQuerySyntaxHelper().MaximumTableLength).Append('a', db.Server.GetQuerySyntaxHelper().MaximumTableLength).ToString();
var columnName = new StringBuilder(db.Server.GetQuerySyntaxHelper().MaximumColumnLength).Append('b', db.Server.GetQuerySyntaxHelper().MaximumColumnLength).ToString();

var tbl = db.CreateTable(tableName,[new DatabaseColumnRequest(columnName,new DatabaseTypeRequest(typeof(string),100))]);
var tbl = db.CreateTable(tableName, [new DatabaseColumnRequest(columnName, new DatabaseTypeRequest(typeof(string), 100))]);

Assert.Multiple(() =>
{
Expand All @@ -29,7 +29,7 @@ public void Test_LongTableName_CreateAndReadBack(DatabaseType dbType)
Assert.That(col.GetRuntimeName(), Is.EqualTo(columnName).IgnoreCase);
}

[TestCaseSource(typeof(All),nameof(All.DatabaseTypes))]
[TestCaseSource(typeof(All), nameof(All.DatabaseTypes))]
public void Test_LongDatabaseNames_CreateAndReadBack(DatabaseType dbType)
{
AssertCanCreateDatabases();
Expand All @@ -40,9 +40,11 @@ public void Test_LongDatabaseNames_CreateAndReadBack(DatabaseType dbType)

for (var i = 0; i < db.Server.GetQuerySyntaxHelper().MaximumDatabaseLength; i++)
sb.Append('a');

if (dbType == DatabaseType.PostgreSql)
db.Server.CreateDatabase(sb.ToString());
var db2 = db.Server.ExpectDatabase(sb.ToString());
db2.Create(true);
if (dbType != DatabaseType.PostgreSql)
db2.Create(true);

Assert.Multiple(() =>
{
Expand Down
2 changes: 1 addition & 1 deletion Tests/FAnsiTests/TestDatabases-github.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
</TestDatabase>
<TestDatabase>
<DatabaseType>PostgreSql</DatabaseType>
<ConnectionString>User ID=postgres;Password=pgpass4291;Host=127.0.0.1;Port=5432</ConnectionString>
<ConnectionString>User ID=postgres;Password=pgpass4291;Host=127.0.0.1;Port=5432;Database=postgres</ConnectionString>
</TestDatabase>
</TestDatabases>
Loading