diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs index 53b89fbc90..cd391748b5 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -7845,6 +7845,12 @@ internal Task WriteSqlVariantValue(object value, int length, int offset, TdsPars WriteDateTimeOffset((DateTimeOffset)value, mt.Scale, length, stateObj); break; + #if NET + case TdsEnums.SQLDATE: + WriteDate((DateOnly)value, stateObj); + break; + #endif + default: Debug.Fail("unknown tds type for sqlvariant!"); break; @@ -8016,6 +8022,13 @@ internal Task WriteSqlVariantDataRowValue(object value, TdsParserStateObject sta WriteDateTimeOffset((DateTimeOffset)value, metatype.Scale, 10, stateObj); break; + #if NET + case TdsEnums.SQLDATE: + WriteSqlVariantHeader(5, metatype.TDSType, metatype.PropBytes, stateObj); + WriteDate((DateOnly)value, stateObj); + break; + #endif + default: Debug.Fail("unknown tds type for sqlvariant!"); break; @@ -8189,6 +8202,11 @@ private void WriteDate(DateTime value, TdsParserStateObject stateObj) WritePartialLong(days, 3, stateObj); } +#if NET + private void WriteDate(DateOnly value, TdsParserStateObject stateObj) => + WritePartialLong(value.DayNumber, 3, stateObj); +#endif + private byte[] SerializeTime(TimeSpan value, byte scale, int length) { if (0 > value.Ticks || value.Ticks >= TimeSpan.TicksPerDay) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/DateTimeVariantTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/DateTimeVariantTests.cs index ec9f516260..d68fcb6027 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/DateTimeVariantTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/DateTimeVariantTests.cs @@ -406,6 +406,12 @@ public void TestSqlDataReader_TVP_Type( { value = ((TimeSpan)paramValue).ToString(); } + #if NET + else if (paramValue.GetType() == typeof(DateOnly)) + { + value = ((DateOnly)paramValue).ToString(); + } + #endif else { value = ((DateTime)paramValue).ToString("M/d/yyyy") + " " + ((DateTime)paramValue).TimeOfDay; @@ -475,6 +481,12 @@ public void TestSqlDataReader_TVP_Variant( { value = ((TimeSpan)paramValue).ToString(); } + #if NET + else if (paramValue.GetType() == typeof(DateOnly)) + { + value = ((DateOnly)paramValue).ToString(); + } + #endif else { value = ((DateTime)paramValue).ToString("M/d/yyyy") + " " + ((DateTime)paramValue).TimeOfDay; @@ -541,6 +553,12 @@ public void TestSimpleDataReader_Type( { value = ((TimeSpan)paramValue).ToString(); } + #if NET + else if (paramValue.GetType() == typeof(DateOnly)) + { + value = ((DateOnly)paramValue).ToString(); + } + #endif else { value = ((DateTime)paramValue).ToString("M/d/yyyy") + " " + ((DateTime)paramValue).TimeOfDay; @@ -592,6 +610,12 @@ public void TestSimpleDataReader_Variant( { value = ((TimeSpan)paramValue).ToString(); } + #if NET + else if (paramValue.GetType() == typeof(DateOnly)) + { + value = ((DateOnly)paramValue).ToString(); + } + #endif else { value = ((DateTime)paramValue).ToString("M/d/yyyy") + " " + ((DateTime)paramValue).TimeOfDay; @@ -644,6 +668,12 @@ public void SqlBulkCopySqlDataReader_Type( { value = ((TimeSpan)paramValue).ToString(); } + #if NET + else if (paramValue.GetType() == typeof(DateOnly)) + { + value = ((DateOnly)paramValue).ToString(); + } + #endif else { value = ((DateTime)paramValue).ToString("M/d/yyyy") + " " + ((DateTime)paramValue).TimeOfDay; @@ -711,6 +741,12 @@ public void SqlBulkCopySqlDataReader_Variant( { value = ((TimeSpan)paramValue).ToString(); } + #if NET + else if (paramValue.GetType() == typeof(DateOnly)) + { + value = ((DateOnly)paramValue).ToString(); + } + #endif else { value = ((DateTime)paramValue).ToString("M/d/yyyy") + " " + ((DateTime)paramValue).TimeOfDay; @@ -948,6 +984,66 @@ public void SqlBulkCopyDataRow_Variant( /// public static IEnumerable GetParameterCombinations() { + #if NET + yield return new object[] { DateOnly.MinValue, "date", + new Dictionary { + { TestVariations.TestSimpleParameter_Variant, SqlDateTimeOverflow }, + { TestVariations.TestSqlDataRecordParameterToTVP_Variant, SqlDateTimeOverflow }, + { TestVariations.TestSqlDataReaderParameterToTVP_Variant, SqlDateTimeOverflow }, + { TestVariations.SqlBulkCopyDataTable_Variant, SqlDateTimeOverflow }, + { TestVariations.SqlBulkCopyDataRow_Variant, SqlDateTimeOverflow }}, + new Dictionary() + { + { TestVariations.TestSimpleParameter_Type, new DateTime(0) }, + { TestVariations.TestSimpleParameter_Variant, new DateTime(0) }, + { TestVariations.TestSqlDataRecordParameterToTVP_Type, new DateTime(0) }, + { TestVariations.TestSqlDataRecordParameterToTVP_Variant, new DateTime(0) }, + { TestVariations.TestSqlDataReaderParameterToTVP_Type, new DateTime(0) }, + { TestVariations.TestSqlDataReaderParameterToTVP_Variant, new DateTime(0) }, + { TestVariations.TestSqlDataReader_TVP_Type, new DateTime(0) }, + { TestVariations.TestSqlDataReader_TVP_Variant, new DateTime(0) }, + { TestVariations.TestSimpleDataReader_Type, new DateTime(0) }, + { TestVariations.TestSimpleDataReader_Variant, new DateTime(0) }, + { TestVariations.SqlBulkCopySqlDataReader_Type, new DateTime(0) }, + { TestVariations.SqlBulkCopySqlDataReader_Variant, new DateTime(0) }, + { TestVariations.SqlBulkCopyDataTable_Type, new DateTime(0) }, + { TestVariations.SqlBulkCopyDataTable_Variant, new DateTime(0) }, + { TestVariations.SqlBulkCopyDataRow_Type, new DateTime(0) }, + { TestVariations.SqlBulkCopyDataRow_Variant, new DateTime(0) } + }, + new Dictionary()}; + yield return new object[] { DateOnly.MaxValue, "date", + new Dictionary { + { TestVariations.TestSimpleParameter_Variant, SqlDateTimeOverflow }, + { TestVariations.TestSqlDataRecordParameterToTVP_Variant, SqlDateTimeOverflow }, + { TestVariations.TestSqlDataReaderParameterToTVP_Variant, SqlDateTimeOverflow }, + { TestVariations.SqlBulkCopyDataTable_Variant, SqlDateTimeOverflow }, + { TestVariations.SqlBulkCopyDataRow_Variant, SqlDateTimeOverflow }}, + new Dictionary() + { + { TestVariations.TestSimpleParameter_Type, new DateTime(3155378112000000000) }, + { TestVariations.TestSimpleParameter_Variant, new DateTime(3155378112000000000) }, + { TestVariations.TestSqlDataRecordParameterToTVP_Type, new DateTime(3155378112000000000) }, + { TestVariations.TestSqlDataRecordParameterToTVP_Variant, new DateTime(3155378112000000000) }, + { TestVariations.TestSqlDataReaderParameterToTVP_Type, new DateTime(3155378112000000000) }, + { TestVariations.TestSqlDataReaderParameterToTVP_Variant, new DateTime(3155378112000000000) }, + { TestVariations.TestSqlDataReader_TVP_Type, new DateTime(3155378112000000000) }, + { TestVariations.TestSqlDataReader_TVP_Variant, new DateTime(3155378112000000000) }, + { TestVariations.TestSimpleDataReader_Type, new DateTime(3155378112000000000) }, + { TestVariations.TestSimpleDataReader_Variant, new DateTime(3155378112000000000) }, + { TestVariations.SqlBulkCopySqlDataReader_Type, new DateTime(3155378112000000000) }, + { TestVariations.SqlBulkCopySqlDataReader_Variant, new DateTime(3155378112000000000) }, + { TestVariations.SqlBulkCopyDataTable_Type, new DateTime(3155378112000000000) }, + { TestVariations.SqlBulkCopyDataTable_Variant, new DateTime(3155378112000000000) }, + { TestVariations.SqlBulkCopyDataRow_Type, new DateTime(3155378112000000000) }, + { TestVariations.SqlBulkCopyDataRow_Variant, new DateTime(3155378112000000000) } + }, + new Dictionary() + { + {TestVariations.TestSqlDataRecordParameterToTVP_Variant, "datetime"} + } + }; + #endif yield return new object[] { DateTime.MinValue, "date", new Dictionary { { TestVariations.TestSimpleParameter_Variant, SqlDateTimeOverflow }, @@ -1069,7 +1165,7 @@ public static IEnumerable GetParameterCombinations() new Dictionary(), new Dictionary(), new Dictionary()}; - yield return new object[] { DateTimeOffset.Parse("12/31/1999 23:59:59.9999999 -08:30"), "datetimeoffset", + yield return new object[] { DateTimeOffset.Parse("1999-12-31 23:59:59.9999999 -08:30"), "datetimeoffset", new Dictionary(), new Dictionary(), new Dictionary()};