diff --git a/CHANGELOG.md b/CHANGELOG.md index 427c41b..1039078 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/FAnsiSql/Discovery/DiscoveredColumn.cs b/FAnsiSql/Discovery/DiscoveredColumn.cs index a5b85e0..9a6f963 100644 --- a/FAnsiSql/Discovery/DiscoveredColumn.cs +++ b/FAnsiSql/Discovery/DiscoveredColumn.cs @@ -1,5 +1,4 @@ -using System.Diagnostics.CodeAnalysis; -using FAnsi.Discovery.QuerySyntax; +using FAnsi.Discovery.QuerySyntax; using FAnsi.Naming; using TypeGuesser; diff --git a/FAnsiSql/Discovery/DiscoveredServerHelper.cs b/FAnsiSql/Discovery/DiscoveredServerHelper.cs index c4256ab..07eb066 100644 --- a/FAnsiSql/Discovery/DiscoveredServerHelper.cs +++ b/FAnsiSql/Discovery/DiscoveredServerHelper.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Data.Common; -using System.Linq; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using System.Threading; diff --git a/FAnsiSql/Implementations/PostgreSql/PostgreSqlServerHelper.cs b/FAnsiSql/Implementations/PostgreSql/PostgreSqlServerHelper.cs index 6a51bfb..ad2c293 100644 --- a/FAnsiSql/Implementations/PostgreSql/PostgreSqlServerHelper.cs +++ b/FAnsiSql/Implementations/PostgreSql/PostgreSqlServerHelper.cs @@ -34,20 +34,19 @@ public override DbConnectionStringBuilder EnableAsync(DbConnectionStringBuilder 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 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) { @@ -59,10 +58,10 @@ public override Version GetVersion(DiscoveredServer server) public override IEnumerable 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); @@ -83,7 +82,7 @@ public override IEnumerable ListDatabases(DbConnection con) 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 }; diff --git a/Tests/FAnsiTests/CrossPlatformTests.cs b/Tests/FAnsiTests/CrossPlatformTests.cs index dd03e27..050e061 100644 --- a/Tests/FAnsiTests/CrossPlatformTests.cs +++ b/Tests/FAnsiTests/CrossPlatformTests.cs @@ -793,10 +793,13 @@ 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(); try @@ -918,10 +921,9 @@ public void HorribleColumnNames(DatabaseType type,string horribleDatabaseName,st 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); + Assert.That(database.GetRuntimeName(), Is.EqualTo(horribleDatabaseName).IgnoreCase); try { diff --git a/Tests/FAnsiTests/DatabaseTests.cs b/Tests/FAnsiTests/DatabaseTests.cs index c7dd8c3..6c4be06 100644 --- a/Tests/FAnsiTests/DatabaseTests.cs +++ b/Tests/FAnsiTests/DatabaseTests.cs @@ -20,7 +20,7 @@ namespace FAnsiTests; [NonParallelizable] public class DatabaseTests { - protected readonly Dictionary TestConnectionStrings = []; + protected readonly Dictionary TestConnectionStrings = []; private bool _allowDatabaseCreation; private string _testScratchDatabase; @@ -39,11 +39,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}"); @@ -62,13 +62,20 @@ 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 ?? throw new InvalidOperationException()); + TestConnectionStrings.Add(databaseType, constr); + + // Make sure our scratch db exists for PostgreSQL + if (databaseType == DatabaseType.PostgreSql) + { + var server = GetTestServer(DatabaseType.PostgreSql); + if (server.DiscoverDatabases().All(db => db.GetWrappedName()?.Contains(_testScratchDatabase) != true)) server.CreateDatabase(_testScratchDatabase); + } } } catch (Exception exception) @@ -85,19 +92,19 @@ protected IEnumerable 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( @@ -131,7 +138,7 @@ protected DiscoveredDatabase GetTestDatabase(DatabaseType type, bool cleanDataba protected void AssertCanCreateDatabases() { - if(!_allowDatabaseCreation) + if (!_allowDatabaseCreation) Assert.Inconclusive("Test cannot run when AllowDatabaseCreation is false"); } @@ -165,7 +172,7 @@ protected static void AssertAreEqual(DataTable dt1, DataTable dt2) foreach (DataRow row1 in dt1.Rows) { - var match = dt2.Rows.Cast().Any(row2=> dt1.Columns.Cast().All(c => AreBasicallyEquals(row1[c.ColumnName], row2[c.ColumnName]))); + var match = dt2.Rows.Cast().Any(row2 => dt1.Columns.Cast().All(c => AreBasicallyEquals(row1[c.ColumnName], row2[c.ColumnName]))); Assert.That(match, $"Couldn't find match for row:{string.Join(",", row1.ItemArray)}"); } diff --git a/Tests/FAnsiTests/Table/CreateIndexTest.cs b/Tests/FAnsiTests/Table/CreateIndexTest.cs index a323ad4..3f3be98 100644 --- a/Tests/FAnsiTests/Table/CreateIndexTest.cs +++ b/Tests/FAnsiTests/Table/CreateIndexTest.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Data.Common; +using System.Data; using FAnsi; using FAnsi.Discovery; using FAnsi.Exceptions; diff --git a/Tests/FAnsiTests/Table/LongNamesTests.cs b/Tests/FAnsiTests/Table/LongNamesTests.cs index 1d66316..5016005 100644 --- a/Tests/FAnsiTests/Table/LongNamesTests.cs +++ b/Tests/FAnsiTests/Table/LongNamesTests.cs @@ -8,7 +8,7 @@ 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); @@ -16,7 +16,7 @@ public void Test_LongTableName_CreateAndReadBack(DatabaseType 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(() => { @@ -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(); @@ -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(() => { diff --git a/Tests/FAnsiTests/TestDatabases-github.xml b/Tests/FAnsiTests/TestDatabases-github.xml index 1bd3e7e..fffb74e 100644 --- a/Tests/FAnsiTests/TestDatabases-github.xml +++ b/Tests/FAnsiTests/TestDatabases-github.xml @@ -18,6 +18,6 @@ PostgreSql - User ID=postgres;Password=pgpass4291;Host=127.0.0.1;Port=5432 + User ID=postgres;Password=pgpass4291;Host=127.0.0.1;Port=5432;Database=postgres