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

Extend DateOnly/TimeOnly support to include DataTable as structured parameter #2258

Merged
merged 1 commit into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ internal enum ExtendedClrTypeCode
IEnumerableOfSqlDataRecord, // System.Collections.Generic.IEnumerable<Microsoft.Data.SqlClient.Server.SqlDataRecord>
TimeSpan, // System.TimeSpan
DateTimeOffset, // System.DateTimeOffset
#if NET6_0_OR_GREATER
DateOnly, // System.DateOnly
TimeOnly, // System.TimeOnly
#endif
Stream, // System.IO.Stream
TextReader, // System.IO.TextReader
XmlReader, // System.Xml.XmlReader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ internal class MetaDataUtilsSmi
SqlDbType.Structured, // System.Collections.Generic.IEnumerable<Microsoft.Data.SqlClient.Server.SqlDataRecord>
SqlDbType.Time, // System.TimeSpan
SqlDbType.DateTimeOffset, // System.DateTimeOffset
#if NET6_0_OR_GREATER
SqlDbType.Date, // System.DateOnly
SqlDbType.Time, // System.TimeOnly
#endif
};


Expand All @@ -86,7 +90,11 @@ internal class MetaDataUtilsSmi

private static Dictionary<Type, ExtendedClrTypeCode> CreateTypeToExtendedTypeCodeMap()
{
#if NET6_0_OR_GREATER
int Count = 44;
#else
int Count = 42;
#endif
// Keep this initialization list in the same order as ExtendedClrTypeCode for ease in validating!
var dictionary = new Dictionary<Type, ExtendedClrTypeCode>(Count)
{
Expand Down Expand Up @@ -132,6 +140,10 @@ private static Dictionary<Type, ExtendedClrTypeCode> CreateTypeToExtendedTypeCod
{ typeof(IEnumerable<SqlDataRecord>), ExtendedClrTypeCode.IEnumerableOfSqlDataRecord },
{ typeof(TimeSpan), ExtendedClrTypeCode.TimeSpan },
{ typeof(DateTimeOffset), ExtendedClrTypeCode.DateTimeOffset },
#if NET6_0_OR_GREATER
{ typeof(DateOnly), ExtendedClrTypeCode.DateOnly },
{ typeof(TimeOnly), ExtendedClrTypeCode.TimeOnly },
#endif
};
return dictionary;
}
Expand Down Expand Up @@ -244,6 +256,16 @@ Type udtType
extendedCode = ExtendedClrTypeCode.Char;
break;
case SqlDbType.Date:
#if NET6_0_OR_GREATER
if (value.GetType() == typeof(DateOnly))
extendedCode = ExtendedClrTypeCode.DateOnly;
else if (value.GetType() == typeof(DateTime))
ErikEJ marked this conversation as resolved.
Show resolved Hide resolved
extendedCode = ExtendedClrTypeCode.DateTime;
else if (value.GetType() == typeof(SqlDateTime))
extendedCode = ExtendedClrTypeCode.SqlDateTime;

break;
#endif
case SqlDbType.DateTime2:
#if NETFRAMEWORK
if (smiVersion >= SmiContextFactory.Sql2008Version)
Expand Down Expand Up @@ -330,6 +352,14 @@ Type udtType
extendedCode = ExtendedClrTypeCode.Invalid;
}
break;
#if NET6_0_OR_GREATER
case SqlDbType.Time:
if (value.GetType() == typeof(TimeOnly))
extendedCode = ExtendedClrTypeCode.TimeOnly;
else if (value.GetType() == typeof(TimeSpan))
ErikEJ marked this conversation as resolved.
Show resolved Hide resolved
extendedCode = ExtendedClrTypeCode.TimeSpan;
break;
#else
case SqlDbType.Time:
if (value.GetType() == typeof(TimeSpan)
#if NETFRAMEWORK
Expand All @@ -338,6 +368,7 @@ Type udtType
)
extendedCode = ExtendedClrTypeCode.TimeSpan;
break;
#endif
case SqlDbType.DateTimeOffset:
if (value.GetType() == typeof(DateTimeOffset)
#if NETFRAMEWORK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1542,6 +1542,14 @@ value is DataFeed
SetCompatibleValue(sink, setters, ordinal, metaData, charsValue, ExtendedClrTypeCode.CharArray, 0);
break;
}
#if NET6_0_OR_GREATER
case ExtendedClrTypeCode.DateOnly:
SetDateTime_Checked(sink, setters, ordinal, metaData, ((DateOnly)value).ToDateTime(new TimeOnly(0, 0)));
break;
case ExtendedClrTypeCode.TimeOnly:
SetTimeSpan_Checked(sink, (SmiTypedGetterSetter)setters, ordinal, metaData, ((TimeOnly)value).ToTimeSpan());
break;
#endif
case ExtendedClrTypeCode.DateTime:
SetDateTime_Checked(sink, setters, ordinal, metaData, (DateTime)value);
break;
Expand Down Expand Up @@ -2899,6 +2907,10 @@ int length
/*EnSDR*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable<SqlDataRecord>*/
/*TmSpn*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/
/*DTOst*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/
#if NET6_0_OR_GREATER
ErikEJ marked this conversation as resolved.
Show resolved Hide resolved
/*DOnly*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateOnly*/
/*TOnly*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeOnly*/
#endif
/*Strm */{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Stream*/
/*TxRdr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/
/*XmlRd*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/
Expand Down Expand Up @@ -2951,6 +2963,10 @@ int length
/*EnSDR*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable<SqlDataRecord>*/
/*TmSpn*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/
/*DTOst*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/
#if NET6_0_OR_GREATER
ErikEJ marked this conversation as resolved.
Show resolved Hide resolved
/*DOnly*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateOnly*/
/*TOnly*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeOnly*/
#endif
/*Strm */{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Stream*/
/*TxRdr*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/
/*XmlRd*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ public void XmlConstructorWithNullObjectName_Throws()
new object[] {SqlDbType.Bit, new SqlBinary(new byte[] { 1 })},
new object[] {SqlDbType.Decimal, new SqlBytes()},
new object[] {SqlDbType.Char, new TimeSpan(0, 0, 1)},
new object[] {SqlDbType.UniqueIdentifier, new DateTimeOffset(new DateTime(0))},
new object[] {SqlDbType.UniqueIdentifier, new DateTimeOffset(new DateTime(0), TimeSpan.Zero)},
new object[] {SqlDbType.DateTimeOffset, SqlGuid.Null},
new object[] {SqlDbType.Date, new SqlDateTime(DateTime.UtcNow)},
new object[] {SqlDbType.Bit, SqlXml.Null },
Expand Down Expand Up @@ -963,7 +963,7 @@ public void XmlConstructorWithNullObjectName_Throws()
new object[] {SqlDbType.Image, new SqlBinary(new byte[] { 1 })},
new object[] {SqlDbType.Image, new SqlBytes(new byte[] { 1 })},
new object[] {SqlDbType.Time, new TimeSpan(0, 0, 1)},
new object[] {SqlDbType.DateTimeOffset, new DateTimeOffset(new DateTime(0))},
new object[] {SqlDbType.DateTimeOffset, new DateTimeOffset(new DateTime(0), TimeSpan.Zero)},
new object[] {SqlDbType.UniqueIdentifier, SqlGuid.Null},
new object[] {SqlDbType.UniqueIdentifier, Guid.Empty},
};
Expand Down Expand Up @@ -1019,7 +1019,7 @@ public void XmlConstructorWithNullObjectName_Throws()
new object[] {SqlDbType.VarBinary, new byte[8001]},
new object[] {SqlDbType.Time, new TimeSpan(0, 0, 1)},
new object[] {SqlDbType.Time, new TimeSpan(TimeSpan.TicksPerDay - 1)},
new object[] {SqlDbType.DateTimeOffset, new DateTimeOffset(new DateTime(0))},
new object[] {SqlDbType.DateTimeOffset, new DateTimeOffset(new DateTime(0), TimeSpan.Zero)},
ErikEJ marked this conversation as resolved.
Show resolved Hide resolved
new object[] {SqlDbType.DateTimeOffset, new DateTimeOffset(DateTime.Now)},
new object[] {SqlDbType.UniqueIdentifier, SqlGuid.Null},
new object[] {SqlDbType.UniqueIdentifier, Guid.Empty},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
using System.Data.SqlTypes;
using System.Threading;
using Xunit;
#if NET6_0_OR_GREATER
using Microsoft.Data.SqlClient.Server;
#endif

namespace Microsoft.Data.SqlClient.ManualTesting.Tests
{
Expand Down Expand Up @@ -306,6 +309,56 @@ public static void TestParametersWithDatatablesTVPInsert()
}
}

#if NET6_0_OR_GREATER
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
public static void TestDateOnlyTVPDataTable_CommandSP()
{
string tableTypeName = "[dbo]." + DataTestUtility.GetUniqueNameForSqlServer("UDTTTestDateOnlyTVP");
string spName = DataTestUtility.GetUniqueNameForSqlServer("spTestDateOnlyTVP");
SqlConnection connection = new(s_connString);
try
{
connection.Open();
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = $"CREATE TYPE {tableTypeName} AS TABLE ([DateColumn] date NULL, [TimeColumn] time NULL)";
cmd.ExecuteNonQuery();
cmd.CommandText = $"CREATE PROCEDURE {spName} (@dates {tableTypeName} READONLY) AS SELECT COUNT(*) FROM @dates";
cmd.ExecuteNonQuery();
}
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = spName;
cmd.CommandType = CommandType.StoredProcedure;

DataTable dtTest = new();
dtTest.Columns.Add(new DataColumn("DateColumn", typeof(DateOnly)));
dtTest.Columns.Add(new DataColumn("TimeColumn", typeof(TimeOnly)));
var dataRow = dtTest.NewRow();
dataRow["DateColumn"] = new DateOnly(2023, 11, 15);
dataRow["TimeColumn"] = new TimeOnly(12, 30, 45);
dtTest.Rows.Add(dataRow);

cmd.Parameters.Add(new SqlParameter
{
ParameterName = "@dates",
SqlDbType = SqlDbType.Structured,
TypeName = tableTypeName,
Value = dtTest,
});

cmd.ExecuteNonQuery();
}
}
finally
{
DataTestUtility.DropStoredProcedure(connection, spName);
DataTestUtility.DropUserDefinedType(connection, tableTypeName);
}
}
#endif

#region Scaled Decimal Parameter & TVP Test
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))]
[InlineData("CAST(1.0 as decimal(38, 37))", "1.0000000000000000000000000000")]
Expand Down
Loading