diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index e1483a26a8..d088006903 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -391,9 +391,12 @@
Microsoft\Data\SqlClient\Server\SmiEventSink.cs
-
+
Microsoft\Data\SqlClient\Server\SmiEventSink_Default.Common.cs
+
+ Microsoft\Data\SqlClient\Server\MetadataUtilsSmi.cs
+
Microsoft\Data\SqlClient\Reliability\SqlRetryingEventArgs.cs
@@ -531,7 +534,6 @@
System
-
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index a4ecd51c67..37fdb08a36 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -465,6 +465,9 @@
Microsoft\Data\SqlClient\Server\SqlNormalizer.cs
+
+ Microsoft\Data\SqlClient\Server\MetadataUtilsSmi.cs
+
Microsoft\Data\SqlClient\Server\SmiRecordBuffer.cs
@@ -603,7 +606,6 @@
-
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/MetadataUtilsSmi.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/MetadataUtilsSmi.cs
deleted file mode 100644
index 92baf05ff2..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/MetadataUtilsSmi.cs
+++ /dev/null
@@ -1,1067 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Data;
-using System.Data.Common;
-using System.Data.SqlTypes;
-using System.Diagnostics;
-using System.Globalization;
-using System.Reflection;
-using Microsoft.Data.Common;
-
-namespace Microsoft.Data.SqlClient.Server
-{
-
- // Utilities for manipulating smi-related metadata.
- //
- // THIS CLASS IS BUILT ON TOP OF THE SMI INTERFACE -- SMI SHOULD NOT DEPEND ON IT!
- //
- // These are all based off of knowing the clr type of the value
- // as an ExtendedClrTypeCode enum for rapid access (lookup in static array is best, if possible).
- internal class MetaDataUtilsSmi
- {
-
- internal const SqlDbType InvalidSqlDbType = (SqlDbType)(-1);
- internal const long InvalidMaxLength = -2;
-
- // Standard type inference map to get SqlDbType when all you know is the value's type (typecode)
- // This map's index is off by one (add one to typecode locate correct entry) in order
- // support ExtendedSqlDbType.Invalid
- // ONLY ACCESS THIS ARRAY FROM InferSqlDbTypeFromTypeCode!!!
- static readonly SqlDbType[] __extendedTypeCodeToSqlDbTypeMap = {
- InvalidSqlDbType, // Invalid extended type code
- SqlDbType.Bit, // System.Boolean
- SqlDbType.TinyInt, // System.Byte
- SqlDbType.NVarChar, // System.Char
- SqlDbType.DateTime, // System.DateTime
- InvalidSqlDbType, // System.DBNull doesn't have an inferable SqlDbType
- SqlDbType.Decimal, // System.Decimal
- SqlDbType.Float, // System.Double
- InvalidSqlDbType, // null reference doesn't have an inferable SqlDbType
- SqlDbType.SmallInt, // System.Int16
- SqlDbType.Int, // System.Int32
- SqlDbType.BigInt, // System.Int64
- InvalidSqlDbType, // System.SByte doesn't have an inferable SqlDbType
- SqlDbType.Real, // System.Single
- SqlDbType.NVarChar, // System.String
- InvalidSqlDbType, // System.UInt16 doesn't have an inferable SqlDbType
- InvalidSqlDbType, // System.UInt32 doesn't have an inferable SqlDbType
- InvalidSqlDbType, // System.UInt64 doesn't have an inferable SqlDbType
- InvalidSqlDbType, // System.Object doesn't have an inferable SqlDbType
- SqlDbType.VarBinary, // System.ByteArray
- SqlDbType.NVarChar, // System.CharArray
- SqlDbType.UniqueIdentifier, // System.Guid
- SqlDbType.VarBinary, // System.Data.SqlTypes.SqlBinary
- SqlDbType.Bit, // System.Data.SqlTypes.SqlBoolean
- SqlDbType.TinyInt, // System.Data.SqlTypes.SqlByte
- SqlDbType.DateTime, // System.Data.SqlTypes.SqlDateTime
- SqlDbType.Float, // System.Data.SqlTypes.SqlDouble
- SqlDbType.UniqueIdentifier, // System.Data.SqlTypes.SqlGuid
- SqlDbType.SmallInt, // System.Data.SqlTypes.SqlInt16
- SqlDbType.Int, // System.Data.SqlTypes.SqlInt32
- SqlDbType.BigInt, // System.Data.SqlTypes.SqlInt64
- SqlDbType.Money, // System.Data.SqlTypes.SqlMoney
- SqlDbType.Decimal, // System.Data.SqlTypes.SqlDecimal
- SqlDbType.Real, // System.Data.SqlTypes.SqlSingle
- SqlDbType.NVarChar, // System.Data.SqlTypes.SqlString
- SqlDbType.NVarChar, // System.Data.SqlTypes.SqlChars
- SqlDbType.VarBinary, // System.Data.SqlTypes.SqlBytes
- SqlDbType.Xml, // System.Data.SqlTypes.SqlXml
- SqlDbType.Structured, // Microsoft.Data.DataTable
- SqlDbType.Structured, // System.Collections.IEnumerable, used for TVPs it must return IDataRecord
- SqlDbType.Structured, // System.Collections.Generic.IEnumerable
- SqlDbType.Time, // System.TimeSpan
- SqlDbType.DateTimeOffset, // System.DateTimeOffset
- };
-
- // Hash table to map from clr type object to ExtendedClrTypeCodeMap enum
- // ONLY ACCESS THIS HASH TABLE FROM DetermineExtendedTypeCode METHOD!!! (and class ctor for setup)
- static readonly Hashtable __typeToExtendedTypeCodeMap;
-
-
- // class ctor
- static MetaDataUtilsSmi()
- {
- // set up type mapping hash table
- // keep this initialization list in the same order as ExtendedClrTypeCode for ease in validating!
- Hashtable ht = new Hashtable(42);
- ht.Add(typeof(System.Boolean), ExtendedClrTypeCode.Boolean);
- ht.Add(typeof(System.Byte), ExtendedClrTypeCode.Byte);
- ht.Add(typeof(System.Char), ExtendedClrTypeCode.Char);
- ht.Add(typeof(System.DateTime), ExtendedClrTypeCode.DateTime);
- ht.Add(typeof(System.DBNull), ExtendedClrTypeCode.DBNull);
- ht.Add(typeof(System.Decimal), ExtendedClrTypeCode.Decimal);
- ht.Add(typeof(System.Double), ExtendedClrTypeCode.Double);
- // lookup code will have to special-case null-ref anyway, so don't bother adding ExtendedTypeCode.Empty to the table
- ht.Add(typeof(System.Int16), ExtendedClrTypeCode.Int16);
- ht.Add(typeof(System.Int32), ExtendedClrTypeCode.Int32);
- ht.Add(typeof(System.Int64), ExtendedClrTypeCode.Int64);
- ht.Add(typeof(System.SByte), ExtendedClrTypeCode.SByte);
- ht.Add(typeof(System.Single), ExtendedClrTypeCode.Single);
- ht.Add(typeof(System.String), ExtendedClrTypeCode.String);
- ht.Add(typeof(System.UInt16), ExtendedClrTypeCode.UInt16);
- ht.Add(typeof(System.UInt32), ExtendedClrTypeCode.UInt32);
- ht.Add(typeof(System.UInt64), ExtendedClrTypeCode.UInt64);
- ht.Add(typeof(System.Object), ExtendedClrTypeCode.Object);
- ht.Add(typeof(System.Byte[]), ExtendedClrTypeCode.ByteArray);
- ht.Add(typeof(System.Char[]), ExtendedClrTypeCode.CharArray);
- ht.Add(typeof(System.Guid), ExtendedClrTypeCode.Guid);
- ht.Add(typeof(SqlBinary), ExtendedClrTypeCode.SqlBinary);
- ht.Add(typeof(SqlBoolean), ExtendedClrTypeCode.SqlBoolean);
- ht.Add(typeof(SqlByte), ExtendedClrTypeCode.SqlByte);
- ht.Add(typeof(SqlDateTime), ExtendedClrTypeCode.SqlDateTime);
- ht.Add(typeof(SqlDouble), ExtendedClrTypeCode.SqlDouble);
- ht.Add(typeof(SqlGuid), ExtendedClrTypeCode.SqlGuid);
- ht.Add(typeof(SqlInt16), ExtendedClrTypeCode.SqlInt16);
- ht.Add(typeof(SqlInt32), ExtendedClrTypeCode.SqlInt32);
- ht.Add(typeof(SqlInt64), ExtendedClrTypeCode.SqlInt64);
- ht.Add(typeof(SqlMoney), ExtendedClrTypeCode.SqlMoney);
- ht.Add(typeof(SqlDecimal), ExtendedClrTypeCode.SqlDecimal);
- ht.Add(typeof(SqlSingle), ExtendedClrTypeCode.SqlSingle);
- ht.Add(typeof(SqlString), ExtendedClrTypeCode.SqlString);
- ht.Add(typeof(SqlChars), ExtendedClrTypeCode.SqlChars);
- ht.Add(typeof(SqlBytes), ExtendedClrTypeCode.SqlBytes);
- ht.Add(typeof(SqlXml), ExtendedClrTypeCode.SqlXml);
- ht.Add(typeof(DataTable), ExtendedClrTypeCode.DataTable);
- ht.Add(typeof(DbDataReader), ExtendedClrTypeCode.DbDataReader);
- ht.Add(typeof(IEnumerable), ExtendedClrTypeCode.IEnumerableOfSqlDataRecord);
- ht.Add(typeof(System.TimeSpan), ExtendedClrTypeCode.TimeSpan);
- ht.Add(typeof(System.DateTimeOffset), ExtendedClrTypeCode.DateTimeOffset);
- __typeToExtendedTypeCodeMap = ht;
- }
-
-
- internal static bool IsCharOrXmlType(SqlDbType type)
- {
- return IsUnicodeType(type) ||
- IsAnsiType(type) ||
- type == SqlDbType.Xml;
- }
-
- internal static bool IsUnicodeType(SqlDbType type)
- {
- return type == SqlDbType.NChar ||
- type == SqlDbType.NVarChar ||
- type == SqlDbType.NText;
- }
-
- internal static bool IsAnsiType(SqlDbType type)
- {
- return type == SqlDbType.Char ||
- type == SqlDbType.VarChar ||
- type == SqlDbType.Text;
- }
-
- internal static bool IsBinaryType(SqlDbType type)
- {
- return type == SqlDbType.Binary ||
- type == SqlDbType.VarBinary ||
- type == SqlDbType.Image;
- }
-
- // Does this type use PLP format values?
- internal static bool IsPlpFormat(SmiMetaData metaData)
- {
- return metaData.MaxLength == SmiMetaData.UnlimitedMaxLengthIndicator ||
- metaData.SqlDbType == SqlDbType.Image ||
- metaData.SqlDbType == SqlDbType.NText ||
- metaData.SqlDbType == SqlDbType.Text ||
- metaData.SqlDbType == SqlDbType.Udt;
- }
-
-
-
- // If we know we're only going to use this object to assign to a specific SqlDbType back end object,
- // we can save some processing time by only checking for the few valid types that can be assigned to the dbType.
- // This assumes a switch statement over SqlDbType is faster than getting the ClrTypeCode and iterating over a
- // series of if statements, or using a hash table.
- // NOTE: the form of these checks is taking advantage of a feature of the JIT compiler that is supposed to
- // optimize checks of the form '(xxx.GetType() == typeof( YYY ))'. The JIT team claimed at one point that
- // this doesn't even instantiate a Type instance, thus was the fastest method for individual comparisons.
- // Given that there's a known SqlDbType, thus a minimal number of comparisons, it's likely this is faster
- // than the other approaches considered (both GetType().GetTypeCode() switch and hash table using Type keys
- // must instantiate a Type object. The typecode switch also degenerates into a large if-then-else for
- // all but the primitive clr types.
- internal static ExtendedClrTypeCode DetermineExtendedTypeCodeForUseWithSqlDbType(
- SqlDbType dbType,
- bool isMultiValued,
- object value,
- Type udtType,
- ulong smiVersion)
- {
- ExtendedClrTypeCode extendedCode = ExtendedClrTypeCode.Invalid;
-
- // fast-track null, which is valid for all types
- if (null == value)
- {
- extendedCode = ExtendedClrTypeCode.Empty;
- }
- else if (DBNull.Value == value)
- {
- extendedCode = ExtendedClrTypeCode.DBNull;
- }
- else
- {
- switch (dbType)
- {
- case SqlDbType.BigInt:
- if (value.GetType() == typeof(Int64))
- extendedCode = ExtendedClrTypeCode.Int64;
- else if (value.GetType() == typeof(SqlInt64))
- extendedCode = ExtendedClrTypeCode.SqlInt64;
- else if (Type.GetTypeCode(value.GetType()) == TypeCode.Int64)
- extendedCode = ExtendedClrTypeCode.Int64;
- break;
- case SqlDbType.Binary:
- case SqlDbType.VarBinary:
- case SqlDbType.Image:
- case SqlDbType.Timestamp:
- if (value.GetType() == typeof(byte[]))
- extendedCode = ExtendedClrTypeCode.ByteArray;
- else if (value.GetType() == typeof(SqlBinary))
- extendedCode = ExtendedClrTypeCode.SqlBinary;
- else if (value.GetType() == typeof(SqlBytes))
- extendedCode = ExtendedClrTypeCode.SqlBytes;
- else if (value.GetType() == typeof(StreamDataFeed))
- extendedCode = ExtendedClrTypeCode.Stream;
- break;
- case SqlDbType.Bit:
- if (value.GetType() == typeof(bool))
- extendedCode = ExtendedClrTypeCode.Boolean;
- else if (value.GetType() == typeof(SqlBoolean))
- extendedCode = ExtendedClrTypeCode.SqlBoolean;
- else if (Type.GetTypeCode(value.GetType()) == TypeCode.Boolean)
- extendedCode = ExtendedClrTypeCode.Boolean;
- break;
- case SqlDbType.Char:
- case SqlDbType.NChar:
- case SqlDbType.NText:
- case SqlDbType.NVarChar:
- case SqlDbType.Text:
- case SqlDbType.VarChar:
- if (value.GetType() == typeof(string))
- extendedCode = ExtendedClrTypeCode.String;
- if (value.GetType() == typeof(TextDataFeed))
- extendedCode = ExtendedClrTypeCode.TextReader;
- else if (value.GetType() == typeof(SqlString))
- extendedCode = ExtendedClrTypeCode.SqlString;
- else if (value.GetType() == typeof(char[]))
- extendedCode = ExtendedClrTypeCode.CharArray;
- else if (value.GetType() == typeof(SqlChars))
- extendedCode = ExtendedClrTypeCode.SqlChars;
- else if (value.GetType() == typeof(char))
- extendedCode = ExtendedClrTypeCode.Char;
- else if (Type.GetTypeCode(value.GetType()) == TypeCode.Char)
- extendedCode = ExtendedClrTypeCode.Char;
- else if (Type.GetTypeCode(value.GetType()) == TypeCode.String)
- extendedCode = ExtendedClrTypeCode.String;
- break;
- case SqlDbType.Date:
- case SqlDbType.DateTime2:
- if (smiVersion >= SmiContextFactory.Sql2008Version)
- {
- goto case SqlDbType.DateTime;
- }
- break;
- case SqlDbType.DateTime:
- case SqlDbType.SmallDateTime:
- if (value.GetType() == typeof(DateTime))
- extendedCode = ExtendedClrTypeCode.DateTime;
- else if (value.GetType() == typeof(SqlDateTime))
- extendedCode = ExtendedClrTypeCode.SqlDateTime;
- else if (Type.GetTypeCode(value.GetType()) == TypeCode.DateTime)
- extendedCode = ExtendedClrTypeCode.DateTime;
- break;
- case SqlDbType.Decimal:
- if (value.GetType() == typeof(Decimal))
- extendedCode = ExtendedClrTypeCode.Decimal;
- else if (value.GetType() == typeof(SqlDecimal))
- extendedCode = ExtendedClrTypeCode.SqlDecimal;
- else if (Type.GetTypeCode(value.GetType()) == TypeCode.Decimal)
- extendedCode = ExtendedClrTypeCode.Decimal;
- break;
- case SqlDbType.Real:
- if (value.GetType() == typeof(Single))
- extendedCode = ExtendedClrTypeCode.Single;
- else if (value.GetType() == typeof(SqlSingle))
- extendedCode = ExtendedClrTypeCode.SqlSingle;
- else if (Type.GetTypeCode(value.GetType()) == TypeCode.Single)
- extendedCode = ExtendedClrTypeCode.Single;
- break;
- case SqlDbType.Int:
- if (value.GetType() == typeof(Int32))
- extendedCode = ExtendedClrTypeCode.Int32;
- else if (value.GetType() == typeof(SqlInt32))
- extendedCode = ExtendedClrTypeCode.SqlInt32;
- else if (Type.GetTypeCode(value.GetType()) == TypeCode.Int32)
- extendedCode = ExtendedClrTypeCode.Int32;
- break;
- case SqlDbType.Money:
- case SqlDbType.SmallMoney:
- if (value.GetType() == typeof(SqlMoney))
- extendedCode = ExtendedClrTypeCode.SqlMoney;
- else if (value.GetType() == typeof(Decimal))
- extendedCode = ExtendedClrTypeCode.Decimal;
- else if (Type.GetTypeCode(value.GetType()) == TypeCode.Decimal)
- extendedCode = ExtendedClrTypeCode.Decimal;
- break;
- case SqlDbType.Float:
- if (value.GetType() == typeof(SqlDouble))
- extendedCode = ExtendedClrTypeCode.SqlDouble;
- else if (value.GetType() == typeof(Double))
- extendedCode = ExtendedClrTypeCode.Double;
- else if (Type.GetTypeCode(value.GetType()) == TypeCode.Double)
- extendedCode = ExtendedClrTypeCode.Double;
- break;
- case SqlDbType.UniqueIdentifier:
- if (value.GetType() == typeof(SqlGuid))
- extendedCode = ExtendedClrTypeCode.SqlGuid;
- else if (value.GetType() == typeof(Guid))
- extendedCode = ExtendedClrTypeCode.Guid;
- break;
- case SqlDbType.SmallInt:
- if (value.GetType() == typeof(Int16))
- extendedCode = ExtendedClrTypeCode.Int16;
- else if (value.GetType() == typeof(SqlInt16))
- extendedCode = ExtendedClrTypeCode.SqlInt16;
- else if (Type.GetTypeCode(value.GetType()) == TypeCode.Int16)
- extendedCode = ExtendedClrTypeCode.Int16;
- break;
- case SqlDbType.TinyInt:
- if (value.GetType() == typeof(Byte))
- extendedCode = ExtendedClrTypeCode.Byte;
- else if (value.GetType() == typeof(SqlByte))
- extendedCode = ExtendedClrTypeCode.SqlByte;
- else if (Type.GetTypeCode(value.GetType()) == TypeCode.Byte)
- extendedCode = ExtendedClrTypeCode.Byte;
- break;
- case SqlDbType.Variant:
- // SqlDbType doesn't help us here, call general-purpose function
- extendedCode = DetermineExtendedTypeCode(value);
-
- // Some types aren't allowed for Variants but are for the general-purpose function.
- // Match behavior of other types and return invalid in these cases.
- if (ExtendedClrTypeCode.SqlXml == extendedCode)
- {
- extendedCode = ExtendedClrTypeCode.Invalid;
- }
- break;
- case SqlDbType.Udt:
- // Validate UDT type if caller gave us a type to validate against
- if (null == udtType ||
- value.GetType() == udtType
- )
- {
- extendedCode = ExtendedClrTypeCode.Object;
- }
- else
- {
- extendedCode = ExtendedClrTypeCode.Invalid;
- }
- break;
- case SqlDbType.Time:
- if (value.GetType() == typeof(TimeSpan) && smiVersion >= SmiContextFactory.Sql2008Version)
- extendedCode = ExtendedClrTypeCode.TimeSpan;
- break;
- case SqlDbType.DateTimeOffset:
- if (value.GetType() == typeof(DateTimeOffset) && smiVersion >= SmiContextFactory.Sql2008Version)
- extendedCode = ExtendedClrTypeCode.DateTimeOffset;
- break;
- case SqlDbType.Xml:
- if (value.GetType() == typeof(SqlXml))
- extendedCode = ExtendedClrTypeCode.SqlXml;
- if (value.GetType() == typeof(XmlDataFeed))
- extendedCode = ExtendedClrTypeCode.XmlReader;
- else if (value.GetType() == typeof(System.String))
- extendedCode = ExtendedClrTypeCode.String;
- break;
- case SqlDbType.Structured:
- if (isMultiValued)
- {
- if (value is DataTable)
- {
- extendedCode = ExtendedClrTypeCode.DataTable;
- }
- // Order is important, since some of these types are base types of the others.
- // Evaluate from most derived to parent types
- else if (value is IEnumerable)
- {
- extendedCode = ExtendedClrTypeCode.IEnumerableOfSqlDataRecord;
- }
- else if (value is DbDataReader)
- {
- extendedCode = ExtendedClrTypeCode.DbDataReader;
- }
- }
- break;
- default:
- // Leave as invalid
- break;
- }
- }
-
- return extendedCode;
-
- }
-
- // Method to map from Type to ExtendedTypeCode
- static internal ExtendedClrTypeCode DetermineExtendedTypeCodeFromType(Type clrType)
- {
- object result = __typeToExtendedTypeCodeMap[clrType];
-
- ExtendedClrTypeCode resultCode;
- if (null == result)
- {
- resultCode = ExtendedClrTypeCode.Invalid;
- }
- else
- {
- resultCode = (ExtendedClrTypeCode)result;
- }
-
- return resultCode;
- }
-
- // Returns the ExtendedClrTypeCode that describes the given value
- // UNDONE: see if switch on Type.GetTypeCode() + conditionals for object types would be even faster than hash table.
- // something like:
- // Type type = value.GetType();
- // switch( type.GetTypeCode() ) {
- // case Int16: resultCode = ExtendedClrTypeCode.Int16; break;
- // ...
- // case Object: {
- // if ( type == typeof( byte[] ) {
- // resultCode = ExtendedClrTypeCode.ByteArray;
- // }
- // else if ( type == typeof( char[] ) {
- // ...
- static internal ExtendedClrTypeCode DetermineExtendedTypeCode(object value)
- {
- ExtendedClrTypeCode resultCode;
- if (null == value)
- {
- resultCode = ExtendedClrTypeCode.Empty;
- }
- else
- {
- resultCode = DetermineExtendedTypeCodeFromType(value.GetType());
- }
-
- return resultCode;
- }
-
- // returns a sqldbtype for the given type code
- static internal SqlDbType InferSqlDbTypeFromTypeCode(ExtendedClrTypeCode typeCode)
- {
- Debug.Assert(typeCode >= ExtendedClrTypeCode.Invalid && typeCode <= ExtendedClrTypeCode.Last, "Someone added a typecode without adding support here!");
-
- return __extendedTypeCodeToSqlDbTypeMap[(int)typeCode + 1];
- }
-
- // Infer SqlDbType from Type in the general case. 2008-only (or later) features that need to
- // infer types should use InferSqlDbTypeFromType_2008.
- static internal SqlDbType InferSqlDbTypeFromType(Type type)
- {
- ExtendedClrTypeCode typeCode = DetermineExtendedTypeCodeFromType(type);
- SqlDbType returnType;
- if (ExtendedClrTypeCode.Invalid == typeCode)
- {
- returnType = InvalidSqlDbType; // Return invalid type so caller can generate specific error
- }
- else
- {
- returnType = InferSqlDbTypeFromTypeCode(typeCode);
- }
-
- return returnType;
- }
-
- // Inference rules changed for 2008-or-later-only cases. Only features that are guaranteed to be
- // running against 2008 and don't have backward compat issues should call this code path.
- // example: TVP's are a new 2008 feature (no back compat issues) so can infer DATETIME2
- // when mapping System.DateTime from DateTable or DbDataReader. DATETIME2 is better because
- // of greater range that can handle all DateTime values.
- static internal SqlDbType InferSqlDbTypeFromType_2008(Type type)
- {
- SqlDbType returnType = InferSqlDbTypeFromType(type);
- if (SqlDbType.DateTime == returnType)
- {
- returnType = SqlDbType.DateTime2;
- }
- return returnType;
- }
-
- static internal bool IsValidForSmiVersion(SmiExtendedMetaData md, ulong smiVersion)
- {
- if (SmiContextFactory.LatestVersion == smiVersion)
- {
- return true;
- }
- else
- {
- // 2005 doesn't support Structured nor the new time types
- Debug.Assert(SmiContextFactory.Sql2005Version == smiVersion, "Other versions should have been eliminated during link stage");
- return md.SqlDbType != SqlDbType.Structured &&
- md.SqlDbType != SqlDbType.Date &&
- md.SqlDbType != SqlDbType.DateTime2 &&
- md.SqlDbType != SqlDbType.DateTimeOffset &&
- md.SqlDbType != SqlDbType.Time;
- }
- }
-
- static internal SqlMetaData SmiExtendedMetaDataToSqlMetaData(SmiExtendedMetaData source)
- {
- SqlMetaData sqlMetaDataInstance = (SqlMetaData)Activator.CreateInstance(typeof(SqlMetaData), System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance,
- null, new object[] {source.Name, source.SqlDbType,
- source.MaxLength,
- source.Precision,
- source.Scale,
- source.LocaleId,
- source.CompareOptions,
- source.TypeSpecificNamePart1,
- source.TypeSpecificNamePart2,
- source.TypeSpecificNamePart3,
- true,
- source.Type }
- , null);
-
- if (SqlDbType.Xml == source.SqlDbType)
- {
- return sqlMetaDataInstance;
- }
-
- return new SqlMetaData(source.Name,
- source.SqlDbType,
- source.MaxLength,
- source.Precision,
- source.Scale,
- source.LocaleId,
- source.CompareOptions,
- source.Type);
- }
-
- // Convert SqlMetaData instance to an SmiExtendedMetaData instance.
-
- internal static SmiExtendedMetaData SqlMetaDataToSmiExtendedMetaData(SqlMetaData source)
- {
- // now map everything across to the extended metadata object
- string typeSpecificNamePart1 = null;
- string typeSpecificNamePart2 = null;
- string typeSpecificNamePart3 = null;
-
- if (SqlDbType.Xml == source.SqlDbType)
- {
- typeSpecificNamePart1 = source.XmlSchemaCollectionDatabase;
- typeSpecificNamePart2 = source.XmlSchemaCollectionOwningSchema;
- typeSpecificNamePart3 = source.XmlSchemaCollectionName;
- }
- else if (SqlDbType.Udt == source.SqlDbType)
- {
- // Split the input name. UdtTypeName is specified as single 3 part name.
- // NOTE: ParseUdtTypeName throws if format is incorrect
- PropertyInfo serverTypeNameProperty = source.GetType().GetProperty("ServerTypeName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
- MethodInfo getter = serverTypeNameProperty.GetGetMethod(nonPublic: true);
- String typeName = (string)getter.Invoke(source, null);
- if (null != typeName)
- {
- String[] names = SqlParameter.ParseTypeName(typeName, true /* is for UdtTypeName */);
-
- if (1 == names.Length)
- {
- typeSpecificNamePart3 = names[0];
- }
- else if (2 == names.Length)
- {
- typeSpecificNamePart2 = names[0];
- typeSpecificNamePart3 = names[1];
- }
- else if (3 == names.Length)
- {
- typeSpecificNamePart1 = names[0];
- typeSpecificNamePart2 = names[1];
- typeSpecificNamePart3 = names[2];
- }
- else
- {
- throw ADP.ArgumentOutOfRange("typeName");
- }
-
- if ((!ADP.IsEmpty(typeSpecificNamePart1) && TdsEnums.MAX_SERVERNAME < typeSpecificNamePart1.Length)
- || (!ADP.IsEmpty(typeSpecificNamePart2) && TdsEnums.MAX_SERVERNAME < typeSpecificNamePart2.Length)
- || (!ADP.IsEmpty(typeSpecificNamePart3) && TdsEnums.MAX_SERVERNAME < typeSpecificNamePart3.Length))
- {
- throw ADP.ArgumentOutOfRange("typeName");
- }
- }
- }
-
- return new SmiExtendedMetaData(source.SqlDbType,
- source.MaxLength,
- source.Precision,
- source.Scale,
- source.LocaleId,
- source.CompareOptions,
- source.Type,
- source.Name,
- typeSpecificNamePart1,
- typeSpecificNamePart2,
- typeSpecificNamePart3);
-
-
- }
-
-
- // compare SmiMetaData to SqlMetaData and determine if they are compatible.
- static internal bool IsCompatible(SmiMetaData firstMd, SqlMetaData secondMd)
- {
- return firstMd.SqlDbType == secondMd.SqlDbType &&
- firstMd.MaxLength == secondMd.MaxLength &&
- firstMd.Precision == secondMd.Precision &&
- firstMd.Scale == secondMd.Scale &&
- firstMd.CompareOptions == secondMd.CompareOptions &&
- firstMd.LocaleId == secondMd.LocaleId &&
- firstMd.Type == secondMd.Type &&
- firstMd.SqlDbType != SqlDbType.Structured && // SqlMetaData doesn't support Structured types
- !firstMd.IsMultiValued; // SqlMetaData doesn't have a "multivalued" option
- }
-
- static internal long AdjustMaxLength(SqlDbType dbType, long maxLength)
- {
- if (SmiMetaData.UnlimitedMaxLengthIndicator != maxLength)
- {
- if (maxLength < 0)
- {
- maxLength = InvalidMaxLength;
- }
-
- switch (dbType)
- {
- case SqlDbType.Binary:
- if (maxLength > SmiMetaData.MaxBinaryLength)
- {
- maxLength = InvalidMaxLength;
- }
- break;
- case SqlDbType.Char:
- if (maxLength > SmiMetaData.MaxANSICharacters)
- {
- maxLength = InvalidMaxLength;
- }
- break;
- case SqlDbType.NChar:
- if (maxLength > SmiMetaData.MaxUnicodeCharacters)
- {
- maxLength = InvalidMaxLength;
- }
- break;
- case SqlDbType.NVarChar:
- // Promote to MAX type if it won't fit in a normal type
- if (SmiMetaData.MaxUnicodeCharacters < maxLength)
- {
- maxLength = SmiMetaData.UnlimitedMaxLengthIndicator;
- }
- break;
- case SqlDbType.VarBinary:
- // Promote to MAX type if it won't fit in a normal type
- if (SmiMetaData.MaxBinaryLength < maxLength)
- {
- maxLength = SmiMetaData.UnlimitedMaxLengthIndicator;
- }
- break;
- case SqlDbType.VarChar:
- // Promote to MAX type if it won't fit in a normal type
- if (SmiMetaData.MaxANSICharacters < maxLength)
- {
- maxLength = SmiMetaData.UnlimitedMaxLengthIndicator;
- }
- break;
- default:
- break;
- }
- }
-
- return maxLength;
- }
-
- private static CultureInfo GetColumnLocale(DataColumn column)
- {
- PropertyInfo localeProperty = column.GetType().GetProperty("Locale", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
- MethodInfo getter = localeProperty.GetGetMethod(nonPublic: true);
- return (CultureInfo)getter.Invoke(column, null);
- }
-
- // Extract metadata for a single DataColumn
- static internal SmiExtendedMetaData SmiMetaDataFromDataColumn(DataColumn column, DataTable parent)
- {
- SqlDbType dbType = InferSqlDbTypeFromType_2008(column.DataType);
- if (InvalidSqlDbType == dbType)
- {
- throw SQL.UnsupportedColumnTypeForSqlProvider(column.ColumnName, column.DataType.Name);
- }
-
- long maxLength = AdjustMaxLength(dbType, column.MaxLength);
- if (InvalidMaxLength == maxLength)
- {
- throw SQL.InvalidColumnMaxLength(column.ColumnName, maxLength);
- }
-
- byte precision;
- byte scale;
- if (column.DataType == typeof(SqlDecimal))
- {
-
- // Must scan all values in column to determine best-fit precision & scale
- Debug.Assert(null != parent);
- scale = 0;
- byte nonFractionalPrecision = 0; // finds largest non-Fractional portion of precision
- foreach (DataRow row in parent.Rows)
- {
- object obj = row[column];
- if (!(obj is DBNull))
- {
- SqlDecimal value = (SqlDecimal)obj;
- if (!value.IsNull)
- {
- byte tempNonFractPrec = checked((byte)(value.Precision - value.Scale));
- if (tempNonFractPrec > nonFractionalPrecision)
- {
- nonFractionalPrecision = tempNonFractPrec;
- }
-
- if (value.Scale > scale)
- {
- scale = value.Scale;
- }
- }
- }
- }
-
- precision = checked((byte)(nonFractionalPrecision + scale));
-
- if (SqlDecimal.MaxPrecision < precision)
- {
- throw SQL.InvalidTableDerivedPrecisionForTvp(column.ColumnName, precision);
- }
- else if (0 == precision)
- {
- precision = 1;
- }
- }
- else if (dbType == SqlDbType.DateTime2 || dbType == SqlDbType.DateTimeOffset || dbType == SqlDbType.Time)
- {
- // Time types care about scale, too. But have to infer maximums for these.
- precision = 0;
- scale = SmiMetaData.DefaultTime.Scale;
- }
- else if (dbType == SqlDbType.Decimal)
- {
- // Must scan all values in column to determine best-fit precision & scale
- Debug.Assert(null != parent);
- scale = 0;
- byte nonFractionalPrecision = 0; // finds largest non-Fractional portion of precision
- foreach (DataRow row in parent.Rows)
- {
- object obj = row[column];
- if (!(obj is DBNull))
- {
- SqlDecimal value = (SqlDecimal)(Decimal)obj;
- byte tempNonFractPrec = checked((byte)(value.Precision - value.Scale));
- if (tempNonFractPrec > nonFractionalPrecision)
- {
- nonFractionalPrecision = tempNonFractPrec;
- }
-
- if (value.Scale > scale)
- {
- scale = value.Scale;
- }
- }
- }
-
- precision = checked((byte)(nonFractionalPrecision + scale));
-
- if (SqlDecimal.MaxPrecision < precision)
- {
- throw SQL.InvalidTableDerivedPrecisionForTvp(column.ColumnName, precision);
- }
- else if (0 == precision)
- {
- precision = 1;
- }
- }
- else
- {
- precision = 0;
- scale = 0;
- }
-
- CultureInfo locale = GetColumnLocale(column);
- return new SmiExtendedMetaData(
- dbType,
- maxLength,
- precision,
- scale,
- locale.LCID,
- SmiMetaData.DefaultNVarChar.CompareOptions,
- column.DataType,
- false, // no support for multi-valued columns in a TVP yet
- null, // no support for structured columns yet
- null, // no support for structured columns yet
- column.ColumnName,
- null,
- null,
- null);
- }
-
- // Map SmiMetaData from a schema table.
- // DEVNOTE: since we're using SchemaTable, we can assume that we aren't directly using a SqlDataReader
- // so we don't support the Sql-specific stuff, like collation
- static internal SmiExtendedMetaData SmiMetaDataFromSchemaTableRow(DataRow schemaRow)
- {
- // One way or another, we'll need column name, so put it in a local now to shorten code later.
- string colName = "";
- object temp = schemaRow[SchemaTableColumn.ColumnName];
- if (DBNull.Value != temp)
- {
- colName = (string)temp;
- }
-
- // Determine correct SqlDbType.
- temp = schemaRow[SchemaTableColumn.DataType];
- if (DBNull.Value == temp)
- {
- throw SQL.NullSchemaTableDataTypeNotSupported(colName);
- }
- Type colType = (Type)temp;
- SqlDbType colDbType = InferSqlDbTypeFromType_2008(colType);
- if (InvalidSqlDbType == colDbType)
- {
- // Unknown through standard mapping, use VarBinary for columns that are Object typed, otherwise error
- if (typeof(object) == colType)
- {
- colDbType = SqlDbType.VarBinary;
- }
- else
- {
- throw SQL.UnsupportedColumnTypeForSqlProvider(colName, colType.ToString());
- }
- }
-
- // Determine metadata modifier values per type (maxlength, precision, scale, etc)
- long maxLength = 0;
- byte precision = 0;
- byte scale = 0;
- switch (colDbType)
- {
- case SqlDbType.BigInt:
- case SqlDbType.Bit:
- case SqlDbType.DateTime:
- case SqlDbType.Float:
- case SqlDbType.Image:
- case SqlDbType.Int:
- case SqlDbType.Money:
- case SqlDbType.NText:
- case SqlDbType.Real:
- case SqlDbType.UniqueIdentifier:
- case SqlDbType.SmallDateTime:
- case SqlDbType.SmallInt:
- case SqlDbType.SmallMoney:
- case SqlDbType.Text:
- case SqlDbType.Timestamp:
- case SqlDbType.TinyInt:
- case SqlDbType.Variant:
- case SqlDbType.Xml:
- case SqlDbType.Date:
- // These types require no metadata modifies
- break;
- case SqlDbType.Binary:
- case SqlDbType.VarBinary:
- // These types need a binary max length
- temp = schemaRow[SchemaTableColumn.ColumnSize];
- if (DBNull.Value == temp)
- {
- // source isn't specifying a size, so assume the worst
- if (SqlDbType.Binary == colDbType)
- {
- maxLength = SmiMetaData.MaxBinaryLength;
- }
- else
- {
- maxLength = SmiMetaData.UnlimitedMaxLengthIndicator;
- }
- }
- else
- {
- // We (should) have a valid maxlength, so use it.
- maxLength = Convert.ToInt64(temp, null);
-
- // Max length must be 0 to MaxBinaryLength or it can be UnlimitedMAX if type is varbinary
- // If it's greater than MaxBinaryLength, just promote it to UnlimitedMAX, if possible
- if (maxLength > SmiMetaData.MaxBinaryLength)
- {
- maxLength = SmiMetaData.UnlimitedMaxLengthIndicator;
- }
-
- if ((maxLength < 0 &&
- (maxLength != SmiMetaData.UnlimitedMaxLengthIndicator ||
- SqlDbType.Binary == colDbType)))
- {
- throw SQL.InvalidColumnMaxLength(colName, maxLength);
- }
- }
- break;
- case SqlDbType.Char:
- case SqlDbType.VarChar:
- // These types need an ANSI max length
- temp = schemaRow[SchemaTableColumn.ColumnSize];
- if (DBNull.Value == temp)
- {
- // source isn't specifying a size, so assume the worst
- if (SqlDbType.Char == colDbType)
- {
- maxLength = SmiMetaData.MaxANSICharacters;
- }
- else
- {
- maxLength = SmiMetaData.UnlimitedMaxLengthIndicator;
- }
- }
- else
- {
- // We (should) have a valid maxlength, so use it.
- maxLength = Convert.ToInt64(temp, null);
-
- // Max length must be 0 to MaxANSICharacters or it can be UnlimitedMAX if type is varbinary
- // If it's greater than MaxANSICharacters, just promote it to UnlimitedMAX, if possible
- if (maxLength > SmiMetaData.MaxANSICharacters)
- {
- maxLength = SmiMetaData.UnlimitedMaxLengthIndicator;
- }
-
- if ((maxLength < 0 &&
- (maxLength != SmiMetaData.UnlimitedMaxLengthIndicator ||
- SqlDbType.Char == colDbType)))
- {
- throw SQL.InvalidColumnMaxLength(colName, maxLength);
- }
- }
- break;
- case SqlDbType.NChar:
- case SqlDbType.NVarChar:
- // These types need a unicode max length
- temp = schemaRow[SchemaTableColumn.ColumnSize];
- if (DBNull.Value == temp)
- {
- // source isn't specifying a size, so assume the worst
- if (SqlDbType.NChar == colDbType)
- {
- maxLength = SmiMetaData.MaxUnicodeCharacters;
- }
- else
- {
- maxLength = SmiMetaData.UnlimitedMaxLengthIndicator;
- }
- }
- else
- {
- // We (should) have a valid maxlength, so use it.
- maxLength = Convert.ToInt64(temp, null);
-
- // Max length must be 0 to MaxUnicodeCharacters or it can be UnlimitedMAX if type is varbinary
- // If it's greater than MaxUnicodeCharacters, just promote it to UnlimitedMAX, if possible
- if (maxLength > SmiMetaData.MaxUnicodeCharacters)
- {
- maxLength = SmiMetaData.UnlimitedMaxLengthIndicator;
- }
-
- if ((maxLength < 0 &&
- (maxLength != SmiMetaData.UnlimitedMaxLengthIndicator ||
- SqlDbType.NChar == colDbType)))
- {
- throw SQL.InvalidColumnMaxLength(colName, maxLength);
- }
- }
- break;
- case SqlDbType.Decimal:
- // Decimal requires precision and scale
- temp = schemaRow[SchemaTableColumn.NumericPrecision];
- if (DBNull.Value == temp)
- {
- precision = SmiMetaData.DefaultDecimal.Precision;
- }
- else
- {
- precision = Convert.ToByte(temp, null);
- }
-
- temp = schemaRow[SchemaTableColumn.NumericScale];
- if (DBNull.Value == temp)
- {
- scale = SmiMetaData.DefaultDecimal.Scale;
- }
- else
- {
- scale = Convert.ToByte(temp, null);
- }
-
- if (precision < SmiMetaData.MinPrecision ||
- precision > SqlDecimal.MaxPrecision ||
- scale < SmiMetaData.MinScale ||
- scale > SqlDecimal.MaxScale ||
- scale > precision)
- {
- throw SQL.InvalidColumnPrecScale();
- }
- break;
- case SqlDbType.Time:
- case SqlDbType.DateTime2:
- case SqlDbType.DateTimeOffset:
- // requires scale
- temp = schemaRow[SchemaTableColumn.NumericScale];
- if (DBNull.Value == temp)
- {
- scale = SmiMetaData.DefaultTime.Scale;
- }
- else
- {
- scale = Convert.ToByte(temp, null);
- }
-
- if (scale > SmiMetaData.MaxTimeScale)
- {
- throw SQL.InvalidColumnPrecScale();
- }
- else if (scale < 0)
- {
- scale = SmiMetaData.DefaultTime.Scale;
- }
- break;
- case SqlDbType.Udt:
- case SqlDbType.Structured:
- default:
- // These types are not supported from SchemaTable
- throw SQL.UnsupportedColumnTypeForSqlProvider(colName, colType.ToString());
- }
-
- return new SmiExtendedMetaData(
- colDbType,
- maxLength,
- precision,
- scale,
- System.Globalization.CultureInfo.CurrentCulture.LCID,
- SmiMetaData.GetDefaultForType(colDbType).CompareOptions,
- null, // no support for UDTs from SchemaTable
- false, // no support for multi-valued columns in a TVP yet
- null, // no support for structured columns yet
- null, // no support for structured columns yet
- colName,
- null,
- null,
- null);
- }
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/MetadataUtilsSmi.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/MetadataUtilsSmi.cs
similarity index 93%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/MetadataUtilsSmi.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/MetadataUtilsSmi.cs
index 85abc33550..590429222a 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/MetadataUtilsSmi.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/MetadataUtilsSmi.cs
@@ -13,21 +13,24 @@
namespace Microsoft.Data.SqlClient.Server
{
- // Utilities for manipulating smi-related metadata.
- //
- // Since this class is built on top of SMI, SMI should not have a dependency on this class
- //
- // These are all based off of knowing the clr type of the value
- // as an ExtendedClrTypeCode enum for rapid access.
+ ///
+ /// Utilities for manipulating smi-related metadata.
+ /// Since this class is built on top of SMI, SMI should not have a dependency on this class
+ /// These are all based off of knowing the clr type of the value
+ /// as an ExtendedClrTypeCode enum for rapid access.
+ ///
internal class MetaDataUtilsSmi
{
internal const SqlDbType InvalidSqlDbType = (SqlDbType)(-1);
internal const long InvalidMaxLength = -2;
- // Standard type inference map to get SqlDbType when all you know is the value's type (typecode)
- // This map's index is off by one (add one to typecode locate correct entry) in order
- // to support ExtendedSqlDbType.Invalid
- // This array is meant to be accessed from InferSqlDbTypeFromTypeCode.
+
+ ///
+ /// Standard type inference map to get SqlDbType when all you know is the value's type (typecode)
+ /// This map's index is off by one (add one to typecode locate correct entry) in order
+ /// to support ExtendedSqlDbType.Invalid
+ /// This array is meant to be accessed from InferSqlDbTypeFromTypeCode.
+ ///
private static readonly SqlDbType[] s_extendedTypeCodeToSqlDbTypeMap = {
InvalidSqlDbType, // Invalid extended type code
SqlDbType.Bit, // System.Boolean
@@ -74,8 +77,11 @@ internal class MetaDataUtilsSmi
SqlDbType.DateTimeOffset, // System.DateTimeOffset
};
- // Dictionary to map from clr type object to ExtendedClrTypeCodeMap enum.
- // This dictionary should only be accessed from DetermineExtendedTypeCode and class ctor for setup.
+
+ ///
+ /// Dictionary to map from clr type object to ExtendedClrTypeCodeMap enum.
+ /// This dictionary should only be accessed from DetermineExtendedTypeCode and class ctor for setup.
+ ///
private static readonly Dictionary s_typeToExtendedTypeCodeMap = CreateTypeToExtendedTypeCodeMap();
private static Dictionary CreateTypeToExtendedTypeCodeMap()
@@ -130,12 +136,9 @@ private static Dictionary CreateTypeToExtendedTypeCod
return dictionary;
}
- internal static bool IsCharOrXmlType(SqlDbType type)
- {
- return IsUnicodeType(type) ||
+ internal static bool IsCharOrXmlType(SqlDbType type) => IsUnicodeType(type) ||
IsAnsiType(type) ||
type == SqlDbType.Xml;
- }
internal static bool IsUnicodeType(SqlDbType type)
{
@@ -144,29 +147,21 @@ internal static bool IsUnicodeType(SqlDbType type)
type == SqlDbType.NText;
}
- internal static bool IsAnsiType(SqlDbType type)
- {
- return type == SqlDbType.Char ||
+ internal static bool IsAnsiType(SqlDbType type) => type == SqlDbType.Char ||
type == SqlDbType.VarChar ||
type == SqlDbType.Text;
- }
- internal static bool IsBinaryType(SqlDbType type)
- {
- return type == SqlDbType.Binary ||
+ internal static bool IsBinaryType(SqlDbType type) => type == SqlDbType.Binary ||
type == SqlDbType.VarBinary ||
type == SqlDbType.Image;
- }
// Does this type use PLP format values?
- internal static bool IsPlpFormat(SmiMetaData metaData)
- {
- return metaData.MaxLength == SmiMetaData.UnlimitedMaxLengthIndicator ||
+ internal static bool IsPlpFormat(SmiMetaData metaData) =>
+ metaData.MaxLength == SmiMetaData.UnlimitedMaxLengthIndicator ||
metaData.SqlDbType == SqlDbType.Image ||
metaData.SqlDbType == SqlDbType.NText ||
metaData.SqlDbType == SqlDbType.Text ||
metaData.SqlDbType == SqlDbType.Udt;
- }
// If we know we're only going to use this object to assign to a specific SqlDbType back end object,
// we can save some processing time by only checking for the few valid types that can be assigned to the dbType.
@@ -183,7 +178,11 @@ internal static ExtendedClrTypeCode DetermineExtendedTypeCodeForUseWithSqlDbType
SqlDbType dbType,
bool isMultiValued,
object value,
- Type udtType)
+ Type udtType
+#if NETFRAMEWORK
+ ,ulong smiVersion
+#endif
+ )
{
ExtendedClrTypeCode extendedCode = ExtendedClrTypeCode.Invalid;
@@ -246,6 +245,13 @@ internal static ExtendedClrTypeCode DetermineExtendedTypeCodeForUseWithSqlDbType
break;
case SqlDbType.Date:
case SqlDbType.DateTime2:
+#if NETFRAMEWORK
+ if (smiVersion >= SmiContextFactory.Sql2008Version)
+ {
+ goto case SqlDbType.DateTime;
+ }
+ break;
+#endif
case SqlDbType.DateTime:
case SqlDbType.SmallDateTime:
if (value.GetType() == typeof(DateTime))
@@ -325,11 +331,19 @@ internal static ExtendedClrTypeCode DetermineExtendedTypeCodeForUseWithSqlDbType
}
break;
case SqlDbType.Time:
- if (value.GetType() == typeof(TimeSpan))
+ if (value.GetType() == typeof(TimeSpan)
+#if NETFRAMEWORK
+ && smiVersion >= SmiContextFactory.Sql2008Version
+#endif
+ )
extendedCode = ExtendedClrTypeCode.TimeSpan;
break;
case SqlDbType.DateTimeOffset:
- if (value.GetType() == typeof(DateTimeOffset))
+ if (value.GetType() == typeof(DateTimeOffset)
+#if NETFRAMEWORK
+ && smiVersion >= SmiContextFactory.Sql2008Version
+#endif
+ )
extendedCode = ExtendedClrTypeCode.DateTimeOffset;
break;
case SqlDbType.Xml:
@@ -424,35 +438,11 @@ internal static SqlDbType InferSqlDbTypeFromType_2008(Type type)
return returnType;
}
- internal static SqlMetaData SmiExtendedMetaDataToSqlMetaData(SmiExtendedMetaData source)
- {
- if (SqlDbType.Xml == source.SqlDbType)
- {
- return new SqlMetaData(source.Name,
- source.SqlDbType,
- source.MaxLength,
- source.Precision,
- source.Scale,
- source.LocaleId,
- source.CompareOptions,
- source.TypeSpecificNamePart1,
- source.TypeSpecificNamePart2,
- source.TypeSpecificNamePart3,
- true,
- source.Type);
- }
-
- return new SqlMetaData(source.Name,
- source.SqlDbType,
- source.MaxLength,
- source.Precision,
- source.Scale,
- source.LocaleId,
- source.CompareOptions,
- null);
- }
-
- // Convert SqlMetaData instance to an SmiExtendedMetaData instance.
+ ///
+ /// Convert SqlMetaData instance to an SmiExtendedMetaData instance.
+ ///
+ ///
+ ///
internal static SmiExtendedMetaData SqlMetaDataToSmiExtendedMetaData(SqlMetaData source)
{
// now map everything across to the extended metadata object
@@ -510,7 +500,11 @@ internal static SmiExtendedMetaData SqlMetaDataToSmiExtendedMetaData(SqlMetaData
source.Scale,
source.LocaleId,
source.CompareOptions,
+#if NETFRAMEWORK
+ source.Type,
+#else
null,
+#endif
source.Name,
typeSpecificNamePart1,
typeSpecificNamePart2,
@@ -526,6 +520,7 @@ internal static bool IsCompatible(SmiMetaData firstMd, SqlMetaData secondMd)
firstMd.Scale == secondMd.Scale &&
firstMd.CompareOptions == secondMd.CompareOptions &&
firstMd.LocaleId == secondMd.LocaleId &&
+ firstMd.Type == secondMd.Type &&
firstMd.SqlDbType != SqlDbType.Structured && // SqlMetaData doesn't support Structured types
!firstMd.IsMultiValued; // SqlMetaData doesn't have a "multivalued" option
}
@@ -645,7 +640,11 @@ internal static SmiExtendedMetaData SmiMetaDataFromDataColumn(DataColumn column,
scale,
columnLocale.LCID,
SmiMetaData.DefaultNVarChar.CompareOptions,
+#if NETFRAMEWORK
+ column.DataType,
+#else
null,
+#endif
false, // no support for multi-valued columns in a TVP yet
null, // no support for structured columns yet
null, // no support for structured columns yet
@@ -959,5 +958,27 @@ internal static SmiExtendedMetaData SmiMetaDataFromSchemaTableRow(DataRow schema
null,
null);
}
+
+#if NETFRAMEWORK
+
+ static internal bool IsValidForSmiVersion(SmiExtendedMetaData md, ulong smiVersion)
+ {
+ if (SmiContextFactory.LatestVersion == smiVersion)
+ {
+ return true;
+ }
+ else
+ {
+ // 2005 doesn't support Structured nor the new time types
+ Debug.Assert(SmiContextFactory.Sql2005Version == smiVersion, "Other versions should have been eliminated during link stage");
+ return md.SqlDbType != SqlDbType.Structured &&
+ md.SqlDbType != SqlDbType.Date &&
+ md.SqlDbType != SqlDbType.DateTime2 &&
+ md.SqlDbType != SqlDbType.DateTimeOffset &&
+ md.SqlDbType != SqlDbType.Time;
+ }
+ }
+
+#endif
}
}