From ce550591209d1f0d4f7f18112a940ffb64a9815d Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 12 May 2026 14:27:38 -0400 Subject: [PATCH 1/8] GH1173: Add FbCommandTests.InsertDateTimeIntoVarChar test. --- .../FbCommandTests.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs index 44ba7c151..e8abb48e4 100644 --- a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs +++ b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Data; using System.Diagnostics; +using System.Globalization; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -361,6 +362,37 @@ public async Task InsertDateTest() } } + [Test] + public async Task InsertDateTimeIntoVarChar() + { + var dtNow = DateTime.Now; + + // FirebirdSql only stores DateTime to tenths of a millisecond. + var dtNormalized = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day, dtNow.Hour, dtNow.Minute, dtNow.Second, dtNow.Millisecond, (dtNow.Microsecond / 100) * 100); + await using (var command = new FbCommand("insert into TEST (int_field, varchar_field) values (1234, @dt)", Connection)) + { + var param = command.CreateParameter(); + + param.DbType = DbType.DateTime; + param.Value = dtNormalized; + param.ParameterName = "@dt"; + + command.Parameters.Add(param); + + var ra = await command.ExecuteNonQueryAsync(); + } + + await using (var command = new FbCommand("select varchar_field from TEST where int_field = 1234", Connection)) + await using (var reader = await command.ExecuteReaderAsync()) + { + reader.Read(); + + var dtThen = reader.GetDateTime(0); + + Assert.AreEqual(dtNormalized, dtThen); + } + } + [Test] public async Task InsertNullTest() { From 7388c818349b57b880593dcf219092376f1889af Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 26 May 2026 12:54:15 -0400 Subject: [PATCH 2/8] GH1173: Add test for inserting and retrieving a DateTime into/from a clob (binary subtype text) field. --- .../FbCommandTests.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs index e8abb48e4..f426a2381 100644 --- a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs +++ b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs @@ -393,6 +393,37 @@ public async Task InsertDateTimeIntoVarChar() } } + [Test] + public async Task InsertDateTimeIntoClob() + { + var dtNow = DateTime.Now; + + // FirebirdSql only stores DateTime to tenths of a millisecond. + var dtNormalized = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day, dtNow.Hour, dtNow.Minute, dtNow.Second, dtNow.Millisecond, (dtNow.Microsecond / 100) * 100); + await using (var command = new FbCommand("insert into TEST (int_field, clob_field) values (1234, @dt)", Connection)) + { + var param = command.CreateParameter(); + + param.DbType = DbType.DateTime; + param.Value = dtNormalized; + param.ParameterName = "@dt"; + + command.Parameters.Add(param); + + var ra = await command.ExecuteNonQueryAsync(); + } + + await using (var command = new FbCommand("select clob_field from TEST where int_field = 1234", Connection)) + await using (var reader = await command.ExecuteReaderAsync()) + { + await reader.ReadAsync(); + + var dtThen = reader.GetDateTime(0); + + Assert.AreEqual(dtNormalized, dtThen); + } + } + [Test] public async Task InsertNullTest() { From aff5840eead81af0c52a9a68978c297c8dc24a62 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 26 May 2026 12:55:40 -0400 Subject: [PATCH 3/8] GH1173: Add test for inserting and retrieving a DateTime into/from a blob field. --- .../FbCommandTests.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs index f426a2381..660d7ceca 100644 --- a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs +++ b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs @@ -424,6 +424,37 @@ public async Task InsertDateTimeIntoClob() } } + [Test] + public async Task InsertDateTimeIntoBlob() + { + var dtNow = DateTime.Now; + + // FirebirdSql only stores DateTime to tenths of a millisecond. + var dtNormalized = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day, dtNow.Hour, dtNow.Minute, dtNow.Second, dtNow.Millisecond, (dtNow.Microsecond / 100) * 100); + await using (var command = new FbCommand("insert into TEST (int_field, blob_field) values (1234, @dt)", Connection)) + { + var param = command.CreateParameter(); + + param.DbType = DbType.DateTime; + param.Value = dtNormalized; + param.ParameterName = "@dt"; + + command.Parameters.Add(param); + + var ra = await command.ExecuteNonQueryAsync(); + } + + await using (var command = new FbCommand("select blob_field from TEST where int_field = 1234", Connection)) + await using (var reader = await command.ExecuteReaderAsync()) + { + await reader.ReadAsync(); + + var dtThen = reader.GetDateTime(0); + + Assert.AreEqual(dtNormalized, dtThen); + } + } + [Test] public async Task InsertNullTest() { From e00bbafe1d602b02bec19de3aaeabe08972de89c Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 26 May 2026 13:42:13 -0400 Subject: [PATCH 4/8] GH1173: Add test for inserting and retrieving a DateTime into/from a varchar field using as an explicit cast. --- .../FbCommandTests.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs index 660d7ceca..2c09f15b8 100644 --- a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs +++ b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs @@ -393,6 +393,37 @@ public async Task InsertDateTimeIntoVarChar() } } + [Test] + public async Task InsertDateTimeIntoVarCharUsingCast() + { + var dtNow = DateTime.Now; + + // FirebirdSql only stores DateTime to tenths of a millisecond. + var dtNormalized = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day, dtNow.Hour, dtNow.Minute, dtNow.Second, dtNow.Millisecond, (dtNow.Microsecond / 100) * 100); + await using (var command = new FbCommand("insert into TEST (int_field, varchar_field) values (1234, CAST(@dt as timestamp))", Connection)) + { + var param = command.CreateParameter(); + + param.DbType = DbType.DateTime; + param.Value = dtNormalized; + param.ParameterName = "@dt"; + + command.Parameters.Add(param); + + var ra = await command.ExecuteNonQueryAsync(); + } + + await using (var command = new FbCommand("select varchar_field from TEST where int_field = 1234", Connection)) + await using (var reader = await command.ExecuteReaderAsync()) + { + reader.Read(); + + var dtThen = reader.GetDateTime(0); + + Assert.AreEqual(dtNormalized, dtThen); + } + } + [Test] public async Task InsertDateTimeIntoClob() { From ef600a5e37182b07416cc39856e0cd4a229b21e6 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 26 May 2026 14:49:57 -0400 Subject: [PATCH 5/8] GH1173: Add test for inserting and retrieving a long (Int64) into/from a clob (binary subtype text) field. --- .../FbCommandTests.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs index 2c09f15b8..83e4f611f 100644 --- a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs +++ b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs @@ -362,6 +362,36 @@ public async Task InsertDateTest() } } + [Test] + public async Task InsertLongIntoClob() + { + var r = new Random(); + var l = r.NextInt64(); + + await using (var command = new FbCommand("insert into TEST (int_field, clob_field) values (1234, @l)", Connection)) + { + var param = command.CreateParameter(); + + param.DbType = DbType.Int64; + param.Value = l; + param.ParameterName = "@l"; + + command.Parameters.Add(param); + + var ra = await command.ExecuteNonQueryAsync(); + } + + await using (var command = new FbCommand("select clob_field from TEST where int_field = 1234", Connection)) + await using (var reader = await command.ExecuteReaderAsync()) + { + await reader.ReadAsync(); + + var m = reader.GetInt64(0); + + Assert.AreEqual(l, m); + } + } + [Test] public async Task InsertDateTimeIntoVarChar() { From f7bc4917c12df2394e8db6e056bddd63fb5c3871 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 26 May 2026 14:51:16 -0400 Subject: [PATCH 6/8] GH1173: Add test for inserting and retrieving a double into/from a varchar field. --- .../FbCommandTests.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs index 83e4f611f..af1940f78 100644 --- a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs +++ b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs @@ -362,6 +362,46 @@ public async Task InsertDateTest() } } + [Test] + public async Task InsertDoubleIntoVarChar() + { + var r = new Random(); + double d = r.NextDouble() * 1e9; + var culture = CultureInfo.CurrentCulture; + + try + { + CultureInfo.CurrentCulture = new CultureInfo("de-DE", false); + + await using (var command = new FbCommand("insert into TEST (int_field, varchar_field) values (1234, @d)", Connection)) + { + var param = command.CreateParameter(); + + param.DbType = DbType.Double; + param.Value = d; + param.ParameterName = "@d"; + + command.Parameters.Add(param); + + var ra = await command.ExecuteNonQueryAsync(); + } + + await using (var command = new FbCommand("select varchar_field from TEST where int_field = 1234", Connection)) + await using (var reader = await command.ExecuteReaderAsync()) + { + await reader.ReadAsync(); + + var j = reader.GetDouble(0); + + Assert.AreEqual(d, j); + } + } + finally + { + CultureInfo.CurrentCulture = culture; + } + } + [Test] public async Task InsertLongIntoClob() { From 5bb4289f0e3bc760086c3f19c4dc9c2de023249e Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 26 May 2026 14:52:23 -0400 Subject: [PATCH 7/8] GH1173: Add test for reading a long (Int64) from a clob containing a non-integral value. --- .../FbCommandTests.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs index af1940f78..ef06b713b 100644 --- a/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs +++ b/src/FirebirdSql.Data.FirebirdClient.Tests/FbCommandTests.cs @@ -402,6 +402,27 @@ public async Task InsertDoubleIntoVarChar() } } + [Test, Description("Verifies that attempting to read an long from a field containing a string fails.")] + public async Task ReadLongFromClobNonIntegralStringThrowsException() + { + string s = "test value"; + + await using (var command = new FbCommand("insert into TEST (int_field, clob_field) values (1234, @s)", Connection)) + { + command.Parameters.AddWithValue("@s", s); + + await command.ExecuteNonQueryAsync(); + } + + await using (var command = new FbCommand("select clob_field from TEST where int_field = 1234", Connection)) + await using (var reader = await command.ExecuteReaderAsync()) + { + await reader.ReadAsync(); + + Assert.Throws(() => reader.GetInt64(0)); + } + } + [Test] public async Task InsertLongIntoClob() { From ec98c0d7db620c03af2b936f82232a412df6cf0f Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Thu, 21 May 2026 13:09:05 -0400 Subject: [PATCH 8/8] fix: Only dispose of the connection if it is still available. --- src/FirebirdSql.Data.TestsBase/FbTestsBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FirebirdSql.Data.TestsBase/FbTestsBase.cs b/src/FirebirdSql.Data.TestsBase/FbTestsBase.cs index 3ceb78968..5a71f1bbf 100644 --- a/src/FirebirdSql.Data.TestsBase/FbTestsBase.cs +++ b/src/FirebirdSql.Data.TestsBase/FbTestsBase.cs @@ -77,7 +77,7 @@ public virtual async Task SetUp() public virtual async Task TearDown() { var cs = BuildConnectionString(ServerType, Compression, WireCrypt); - Connection.Dispose(); + Connection?.Dispose(); if (_insertTestData) { await DeleteAllData(cs);