From a25793df5da352c0b9227d9034b04d3fbb7e3107 Mon Sep 17 00:00:00 2001 From: Giorgi Dalakishvili Date: Thu, 29 Aug 2024 12:53:09 +0400 Subject: [PATCH] Do not require casts for DateOnly and TimeOnly parameters --- DuckDB.NET.Data/Internal/DbTypeMap.cs | 4 +++ DuckDB.NET.Data/Internal/PreparedStatement.cs | 8 ++++++ DuckDB.NET.Test/Parameters/DateTests.cs | 22 ++++++++++++++++ DuckDB.NET.Test/Parameters/TimeTests.cs | 26 +++++++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/DuckDB.NET.Data/Internal/DbTypeMap.cs b/DuckDB.NET.Data/Internal/DbTypeMap.cs index 4bc7096c..681e587b 100644 --- a/DuckDB.NET.Data/Internal/DbTypeMap.cs +++ b/DuckDB.NET.Data/Internal/DbTypeMap.cs @@ -30,6 +30,10 @@ internal static class DbTypeMap {typeof(DateTime), DbType.DateTime}, {typeof(DuckDBDateOnly), DbType.Date}, {typeof(DuckDBTimeOnly), DbType.Time}, +#if NET6_0_OR_GREATER + {typeof(DateOnly), DbType.Date}, + {typeof(TimeOnly), DbType.Time}, + #endif }; diff --git a/DuckDB.NET.Data/Internal/PreparedStatement.cs b/DuckDB.NET.Data/Internal/PreparedStatement.cs index db68cb0a..630ae859 100644 --- a/DuckDB.NET.Data/Internal/PreparedStatement.cs +++ b/DuckDB.NET.Data/Internal/PreparedStatement.cs @@ -209,13 +209,21 @@ private static DuckDBState BindBlob(DuckDBPreparedStatement preparedStatement, l private static DuckDBState BindDateOnly(DuckDBPreparedStatement preparedStatement, long index, object value) { +#if NET6_0_OR_GREATER + var date = NativeMethods.DateTimeHelpers.DuckDBToDate(value is DateOnly dateOnly ? (DuckDBDateOnly)dateOnly : (DuckDBDateOnly)value); +#else var date = NativeMethods.DateTimeHelpers.DuckDBToDate((DuckDBDateOnly)value); +#endif return NativeMethods.PreparedStatements.DuckDBBindDate(preparedStatement, index, date); } private static DuckDBState BindTimeOnly(DuckDBPreparedStatement preparedStatement, long index, object value) { +#if NET6_0_OR_GREATER + var time = NativeMethods.DateTimeHelpers.DuckDBToTime(value is TimeOnly dateOnly ? (DuckDBTimeOnly)dateOnly : (DuckDBTimeOnly)value); +#else var time = NativeMethods.DateTimeHelpers.DuckDBToTime((DuckDBTimeOnly)value); +#endif return NativeMethods.PreparedStatements.DuckDBBindTime(preparedStatement, index, time); } diff --git a/DuckDB.NET.Test/Parameters/DateTests.cs b/DuckDB.NET.Test/Parameters/DateTests.cs index ed66f2c3..ff52aeb5 100644 --- a/DuckDB.NET.Test/Parameters/DateTests.cs +++ b/DuckDB.NET.Test/Parameters/DateTests.cs @@ -95,4 +95,26 @@ public void InsertAndQueryTest(int year, byte mon, byte day) Command.CommandText = "DROP TABLE DateOnlyTestTable;"; Command.ExecuteNonQuery(); } + + [Theory] + [InlineData(1992, 09, 20)] + [InlineData(2022, 05, 04)] + [InlineData(2022, 04, 05)] + public void BindDateOnly(int year, int mon, int day) + { + var expectedValue = new DateOnly(year, mon, day); + + Command.CommandText = "SELECT ?;"; + Command.Parameters.Add(new DuckDBParameter(expectedValue)); + + var scalar = Command.ExecuteScalar(); + + scalar.Should().BeOfType(); + + var dateOnly = (DateOnly)scalar; + + dateOnly.Year.Should().Be(year); + dateOnly.Month.Should().Be((byte)mon); + dateOnly.Day.Should().Be((byte)day); + } } \ No newline at end of file diff --git a/DuckDB.NET.Test/Parameters/TimeTests.cs b/DuckDB.NET.Test/Parameters/TimeTests.cs index 1b2dfa64..8fa77464 100644 --- a/DuckDB.NET.Test/Parameters/TimeTests.cs +++ b/DuckDB.NET.Test/Parameters/TimeTests.cs @@ -159,4 +159,30 @@ public void QueryTimeTzReaderTest(int hour, int minute, int second, int microsec dateTimeOffset.Offset.Should().Be(new TimeSpan(offsetHours, offsetHours >= 0 ? offsetMinutes : -offsetMinutes, 0)); } + + [Theory] + [InlineData(12, 15, 17, 350_000)] + [InlineData(12, 17, 15, 450_000)] + [InlineData(18, 15, 17, 125_000)] + [InlineData(12, 15, 17, 350_300)] + [InlineData(12, 17, 15, 450_500)] + [InlineData(18, 15, 17, 125_700)] + public void BindTimeOnly(int hour, int minute, int second, int microsecond) + { + var expectedValue = new TimeOnly(hour, minute, second,0).Add(TimeSpan.FromMicroseconds(microsecond)); + + Command.CommandText = "SELECT ?;"; + Command.Parameters.Add(new DuckDBParameter(expectedValue)); + + var scalar = Command.ExecuteScalar(); + + scalar.Should().BeOfType(); + + var timeOnly = (TimeOnly)scalar; + + timeOnly.Hour.Should().Be((byte)hour); + timeOnly.Minute.Should().Be((byte)minute); + timeOnly.Second.Should().Be((byte)second); + timeOnly.Ticks.Should().Be(expectedValue.Ticks); + } } \ No newline at end of file