internal static bool IsGetterAccessValid(SmiMetaData metaData, SmiXetterTypeCode xetterType)
        {
            // Make sure no-one adds a new xetter type without updating this file!
            Debug.Assert(SmiXetterTypeCode.XetBoolean <= xetterType && SmiXetterTypeCode.XetDateTimeOffset >= xetterType);

            return(__isGetterAccessValid[(int)metaData.SqlDbType, (int)xetterType]);
        }
Exemple #2
0
        // valid for DateTimeOffset
        internal void SetDateTimeOffset(DateTimeOffset value)
        {
            Debug.Assert(
                SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetDateTimeOffset));
            byte scale;
            byte length;

            if (SqlDbType.Variant == _metaData.SqlDbType)
            {
                // VSTFDevDiv #885208 - DateTimeOffset throws ArgumentException for when passing DateTimeOffset value to a sql_variant TVP
                //                      using a SqlDataRecord or SqlDataReader
                MSS.SmiMetaData dateTimeOffsetMetaData = MSS.SmiMetaData.DefaultDateTimeOffset;
                scale  = MetaType.MetaDateTimeOffset.Scale;
                length = (byte)dateTimeOffsetMetaData.MaxLength;
                _stateObj.Parser.WriteSqlVariantHeader(13, TdsEnums.SQLDATETIMEOFFSET, 1, _stateObj);
                _stateObj.WriteByte(scale); //propbytes: scale
            }
            else
            {
                scale  = _metaData.Scale;
                length = (byte)_metaData.MaxLength;
                _stateObj.WriteByte(length);
            }
            DateTime utcDateTime = value.UtcDateTime;
            long     time        = utcDateTime.TimeOfDay.Ticks / TdsEnums.TICKS_FROM_SCALE[scale];
            int      days        = utcDateTime.Subtract(DateTime.MinValue).Days;
            short    offset      = (short)value.Offset.TotalMinutes;

            _stateObj.WriteByteArray(BitConverter.GetBytes(time), length - 5, 0); // time
            _stateObj.WriteByteArray(BitConverter.GetBytes(days), 3, 0);          // date
            _stateObj.WriteByte((byte)(offset & 0xff));                           // offset byte 1
            _stateObj.WriteByte((byte)((offset >> 8) & 0xff));                    // offset byte 2
        }
Exemple #3
0
        public virtual object GetSqlValue(int ordinal)
        {
            EnsureSubclassOverride();
            SmiMetaData metaData = GetSmiMetaData(ordinal);

            return(ValueUtilsSmi.GetSqlValue200(_eventSink, _recordBuffer, ordinal, metaData));
        }
        public virtual Object GetValue(int ordinal)
        {
            EnsureSubclassOverride();
            SmiMetaData metaData = GetSmiMetaData(ordinal);

            if (SmiVersion >= SmiContextFactory.KatmaiVersion)
            {
                return(ValueUtilsSmi.GetValue200(
                           _eventSink,
                           _recordBuffer,
                           ordinal,
                           metaData,
                           _recordContext
                           ));
            }
            else
            {
                return(ValueUtilsSmi.GetValue(
                           _eventSink,
                           (ITypedGettersV3)_recordBuffer,
                           ordinal,
                           metaData,
                           _recordContext
                           ));
            }
        }
Exemple #5
0
        private static long GetBytesConversion(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull) {
            object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
            if (null == obj) {
                throw ADP.InvalidCast();
            }
            SqlBinary value = (SqlBinary) obj;

            if (value.IsNull) {
                if (throwOnNull) {
                    throw SQL.SqlNullValue();
                }
                else {
                    // return zero length in any case
                    return 0;
                }
            }

            if ( null == buffer ) {
                return value.Length;
            }

            length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength * sizeof(char), value.Length, 
                        fieldOffset, buffer.Length, bufferOffset, length );
            Array.Copy( value.Value, checked((int)fieldOffset), buffer, bufferOffset, length );
            return length;
        }
 internal SmiSettersStream(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData)
 {
     this._sink          = sink;
     this._setters       = setters;
     this._ordinal       = ordinal;
     this._lengthWritten = 0L;
     this._metaData      = metaData;
 }
 internal SmiGettersStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
 {
     this._sink         = sink;
     this._getters      = getters;
     this._ordinal      = ordinal;
     this._readPosition = 0L;
     this._metaData     = metaData;
 }
 internal TdsValueSetter(TdsParserStateObject stateObj, SmiMetaData md)
 {
     this._stateObj = stateObj;
     this._metaData = md;
     this._isPlp = MetaDataUtilsSmi.IsPlpFormat(md);
     this._plpUnknownSent = false;
     this._encoder = null;
 }
Exemple #9
0
 // 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);
 }
 internal static bool IsPlpFormat(SmiMetaData metaData)
 {
     if (((metaData.MaxLength != -1L) && (metaData.SqlDbType != SqlDbType.Image)) && ((metaData.SqlDbType != SqlDbType.NText) && (metaData.SqlDbType != SqlDbType.Text)))
     {
         return(metaData.SqlDbType == SqlDbType.Udt);
     }
     return(true);
 }
 internal SmiSettersStream(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData)
 {
     this._sink = sink;
     this._setters = setters;
     this._ordinal = ordinal;
     this._lengthWritten = 0L;
     this._metaData = metaData;
 }
 internal SmiGettersStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
 {
     this._sink = sink;
     this._getters = getters;
     this._ordinal = ordinal;
     this._readPosition = 0L;
     this._metaData = metaData;
 }
        internal MemoryRecordBuffer(SmiMetaData[] metaData) {
            Debug.Assert(null != metaData, "invalid attempt to instantiate MemoryRecordBuffer with null SmiMetaData[]");

            _buffer = new SqlRecordBuffer[metaData.Length];

            for (int i = 0; i < _buffer.Length; ++i) {
                _buffer[i] = new SqlRecordBuffer(metaData[i]);
            }
        }
 internal TdsRecordBufferSetter(TdsParserStateObject stateObj, SmiMetaData md)
 {
     this._fieldSetters = new TdsValueSetter[md.FieldMetaData.Count];
     for (int i = 0; i < md.FieldMetaData.Count; i++)
     {
         this._fieldSetters[i] = new TdsValueSetter(stateObj, md.FieldMetaData[i]);
     }
     this._stateObj = stateObj;
     this._metaData = md;
 }
        public virtual void SetVariantMetaData(SmiEventSink sink, int ordinal, SmiMetaData metaData)
        {
            // ******** OBSOLETING from SMI -- this should have been removed from ITypedSettersV3
            //  Intended to be removed prior to RTM.  Sub-classes need not implement

            // Implement body with throw because there are only a couple of ways to get to this code:
            //  1) Client is calling this method even though the server negotiated for V3+ and dropped support for V2-.
            //  2) Server didn't implement V2- on some interface and negotiated V2-.
            throw System.Data.Common.ADP.InternalError(System.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod);
        }
Exemple #16
0
        private int                     _currentOffset; // for chunking, verify that caller is using correct offsets
#endif

        #endregion

        #region Exposed Construct/factory methods

        internal TdsValueSetter(TdsParserStateObject stateObj, SmiMetaData md) {
            _stateObj = stateObj;
            _metaData = md;
            _isPlp = MetaDataUtilsSmi.IsPlpFormat(md);
            _plpUnknownSent = false;
            _encoder = null;
#if DEBUG
            _currentOffset = 0;
#endif
        }
Exemple #17
0
 // compare SmiMetaData to SqlMetaData and determine if they are compatible.
 internal static 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.SqlDbType != SqlDbType.Structured && // SqlMetaData doesn't support Structured types
            !firstMd.IsMultiValued);                     // SqlMetaData doesn't have a "multivalued" option
 }
Exemple #18
0
 internal static byte GetByte( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
     ThrowIfITypedGettersIsNull( sink, getters, ordinal );
     if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.Byte ) ) {
         return GetByte_Unchecked( sink, getters, ordinal );
     }
     object result = GetValue( sink, getters, ordinal, metaData, null );
     if (null == result) {
         throw ADP.InvalidCast();
     }
     return (Byte)result;
 }
Exemple #19
0
        public virtual string GetString(int ordinal)
        {
            this.EnsureSubclassOverride();
            SmiMetaData smiMetaData = this.GetSmiMetaData(ordinal);

            if (this._usesStringStorageForXml && (SqlDbType.Xml == smiMetaData.SqlDbType))
            {
                return(ValueUtilsSmi.GetString(this._eventSink, this._recordBuffer, ordinal, __maxNVarCharForXml));
            }
            return(ValueUtilsSmi.GetString(this._eventSink, this._recordBuffer, ordinal, this.GetSmiMetaData(ordinal)));
        }
Exemple #20
0
        public virtual object GetValue(int ordinal)
        {
            this.EnsureSubclassOverride();
            SmiMetaData smiMetaData = this.GetSmiMetaData(ordinal);

            if (this.SmiVersion >= 210L)
            {
                return(ValueUtilsSmi.GetValue200(this._eventSink, this._recordBuffer, ordinal, smiMetaData, this._recordContext));
            }
            return(ValueUtilsSmi.GetValue(this._eventSink, this._recordBuffer, ordinal, smiMetaData, this._recordContext));
        }
        private int                     _currentField;      // validate that caller sets columns in correct order.
#endif

        #endregion
        
        #region Exposed Construct and control methods/properties

        internal TdsRecordBufferSetter(TdsParserStateObject stateObj, SmiMetaData md) {
            Debug.Assert(SqlDbType.Structured == md.SqlDbType, "Unsupported SqlDbType: " + md.SqlDbType);
            _fieldSetters = new TdsValueSetter[md.FieldMetaData.Count];
            for(int i=0; i<md.FieldMetaData.Count; i++) {
                _fieldSetters[i] = new TdsValueSetter(stateObj, md.FieldMetaData[i]);
            }
            _stateObj = stateObj;
            _metaData = md;
#if DEBUG
            _currentField = ReadyForToken;
#endif
        }
        internal SmiGettersStream( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
            Debug.Assert( null != sink );
            Debug.Assert( null != getters );
            Debug.Assert( 0 <= ordinal );
            Debug.Assert( null != metaData );

            _sink = sink;
            _getters = getters;
            _ordinal = ordinal;
            _readPosition = 0;
            _metaData = metaData;
        }
        internal SmiSettersStream( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData ) {
            Debug.Assert( null != sink );
            Debug.Assert( null != setters );
            Debug.Assert( 0 <= ordinal );
            Debug.Assert( null != metaData );

            _sink = sink;
            _setters = setters;
            _ordinal = ordinal;
            _lengthWritten = 0;
            _metaData = metaData;
        }
Exemple #24
0
        internal SmiGettersStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData)
        {
            Debug.Assert(null != sink);
            Debug.Assert(null != getters);
            Debug.Assert(0 <= ordinal);
            Debug.Assert(null != metaData);

            _sink         = sink;
            _getters      = getters;
            _ordinal      = ordinal;
            _readPosition = 0;
            _metaData     = metaData;
        }
Exemple #25
0
        internal SmiSettersStream(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData)
        {
            Debug.Assert(null != sink);
            Debug.Assert(null != setters);
            Debug.Assert(0 <= ordinal);
            Debug.Assert(null != metaData);

            _sink          = sink;
            _setters       = setters;
            _ordinal       = ordinal;
            _lengthWritten = 0;
            _metaData      = metaData;
        }
Exemple #26
0
        public virtual string GetString(int ordinal)
        {
            EnsureSubclassOverride();
            SmiMetaData colMeta = GetSmiMetaData(ordinal);

            if (_usesStringStorageForXml && SqlDbType.Xml == colMeta.SqlDbType)
            {
                return(ValueUtilsSmi.GetString(_eventSink, _recordBuffer, ordinal, s_maxNVarCharForXml));
            }
            else
            {
                return(ValueUtilsSmi.GetString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)));
            }
        }
Exemple #27
0
        // Internal setter to be used by constructors only!  Modifies state!
        private void SetDefaultsForType(SqlDbType dbType)
        {
            SmiMetaData smdDflt = GetDefaultForType(dbType);

            _databaseType       = dbType;
            _maxLength          = smdDflt.MaxLength;
            _precision          = smdDflt.Precision;
            _scale              = smdDflt.Scale;
            _localeId           = smdDflt.LocaleId;
            _compareOptions     = smdDflt.CompareOptions;
            _isMultiValued      = smdDflt._isMultiValued;
            _fieldMetaData      = smdDflt._fieldMetaData;       // This is ok due to immutability
            _extendedProperties = smdDflt._extendedProperties;  // This is ok due to immutability
        }
        private void SetDefaultsForType(System.Data.SqlDbType dbType)
        {
            SmiMetaData defaultForType = GetDefaultForType(dbType);

            this._databaseType       = dbType;
            this._maxLength          = defaultForType.MaxLength;
            this._precision          = defaultForType.Precision;
            this._scale              = defaultForType.Scale;
            this._localeId           = defaultForType.LocaleId;
            this._compareOptions     = defaultForType.CompareOptions;
            this._clrType            = null;
            this._isMultiValued      = defaultForType._isMultiValued;
            this._fieldMetaData      = defaultForType._fieldMetaData;
            this._extendedProperties = defaultForType._extendedProperties;
        }
        private bool         _isMetaSet; // flag to indicate whether we have set the variant metadata

        internal SqlRecordBuffer(SmiMetaData metaData) {
            _isNull = true;
        }
Exemple #30
0
        //  implements SqlClient 1.1-compatible GetSqlValue() semantics for everything except output parameters
        internal static object GetSqlValue(
            SmiEventSink_Default    sink,
            ITypedGettersV3         getters,
            int                     ordinal,
            SmiMetaData             metaData,
            SmiContext              context
            ) {
            object result = null;
            if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
                if (SqlDbType.Udt == metaData.SqlDbType) {
                    result = NullUdtInstance(metaData);
                }
                else {
                    result = __typeSpecificNullForSqlValue[(int)metaData.SqlDbType];
                }
            }
            else {
                switch( metaData.SqlDbType ) {
                    case SqlDbType.BigInt:
                        result = new SqlInt64( GetInt64_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.Binary:
                        result = GetSqlBinary_Unchecked( sink, getters, ordinal );
                        break;
                    case SqlDbType.Bit:
                        result = new SqlBoolean( GetBoolean_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.Char:
                        result = new SqlString( GetString_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.DateTime:
                        result = new SqlDateTime( GetDateTime_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.Decimal:
                        result = GetSqlDecimal_Unchecked( sink, getters, ordinal );
                        break;
                    case SqlDbType.Float:
                        result = new SqlDouble( GetDouble_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.Image:
                        result = GetSqlBinary_Unchecked( sink, getters, ordinal );
                        break;
                    case SqlDbType.Int:
                        result = new SqlInt32( GetInt32_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.Money:
                        result = GetSqlMoney_Unchecked( sink, getters, ordinal );
                        break;
                    case SqlDbType.NChar: 
                        result = new SqlString( GetString_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.NText: 
                        result = new SqlString( GetString_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.NVarChar: 
                        result = new SqlString( GetString_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.Real:
                        result = new SqlSingle( GetSingle_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.UniqueIdentifier:
                        result = new SqlGuid( GetGuid_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.SmallDateTime:
                        result = new SqlDateTime( GetDateTime_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.SmallInt:
                        result = new SqlInt16( GetInt16_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.SmallMoney:
                        result = GetSqlMoney_Unchecked( sink, getters, ordinal );
                        break;
                    case SqlDbType.Text:
                        result = new SqlString( GetString_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.Timestamp:
                        result = GetSqlBinary_Unchecked( sink, getters, ordinal );
                        break;
                    case SqlDbType.TinyInt:
                        result = new SqlByte( GetByte_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.VarBinary:
                        result = GetSqlBinary_Unchecked( sink, getters, ordinal );
                        break;
                    case SqlDbType.VarChar:
                        result = new SqlString( GetString_Unchecked( sink, getters, ordinal ) );
                        break;
                    case SqlDbType.Variant:
                        metaData = getters.GetVariantType( sink, ordinal );
                        sink.ProcessMessagesAndThrow();
                        Debug.Assert( SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!" );
                        result = GetSqlValue( sink, getters, ordinal, metaData, context );
                        break;
                    case SqlDbType.Xml: 
                        result = GetSqlXml_Unchecked( sink, getters, ordinal, context );
                        break;
                    case SqlDbType.Udt:
                        result = GetUdt_LengthChecked( sink, getters, ordinal, metaData );
                        break;
                }
            }

            return result;
        }
        internal static SmiExtendedMetaData SmiMetaDataFromSchemaTableRow(DataRow schemaRow)
        {
            string columnName = "";
            object obj2       = schemaRow[SchemaTableColumn.ColumnName];

            if (DBNull.Value != obj2)
            {
                columnName = (string)obj2;
            }
            obj2 = schemaRow[SchemaTableColumn.DataType];
            if (DBNull.Value == obj2)
            {
                throw SQL.NullSchemaTableDataTypeNotSupported(columnName);
            }
            Type      type2  = (Type)obj2;
            SqlDbType dbType = InferSqlDbTypeFromType_Katmai(type2);

            if (~SqlDbType.BigInt == dbType)
            {
                if (typeof(object) != type2)
                {
                    throw SQL.UnsupportedColumnTypeForSqlProvider(columnName, type2.ToString());
                }
                dbType = SqlDbType.VarBinary;
            }
            long maxLength = 0L;
            byte precision = 0;
            byte scale     = 0;

            switch (dbType)
            {
            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:
                goto Label_0302;

            case SqlDbType.Binary:
            case SqlDbType.VarBinary:
                obj2 = schemaRow[SchemaTableColumn.ColumnSize];
                if (DBNull.Value != obj2)
                {
                    maxLength = Convert.ToInt64(obj2, null);
                    if (maxLength > 0x1f40L)
                    {
                        maxLength = -1L;
                    }
                    if ((maxLength < 0L) && ((maxLength != -1L) || (SqlDbType.Binary == dbType)))
                    {
                        throw SQL.InvalidColumnMaxLength(columnName, maxLength);
                    }
                }
                else if (SqlDbType.Binary != dbType)
                {
                    maxLength = -1L;
                }
                else
                {
                    maxLength = 0x1f40L;
                }
                goto Label_0302;

            case SqlDbType.Char:
            case SqlDbType.VarChar:
                obj2 = schemaRow[SchemaTableColumn.ColumnSize];
                if (DBNull.Value != obj2)
                {
                    maxLength = Convert.ToInt64(obj2, null);
                    if (maxLength > 0x1f40L)
                    {
                        maxLength = -1L;
                    }
                    if ((maxLength < 0L) && ((maxLength != -1L) || (SqlDbType.Char == dbType)))
                    {
                        throw SQL.InvalidColumnMaxLength(columnName, maxLength);
                    }
                }
                else if (SqlDbType.Char != dbType)
                {
                    maxLength = -1L;
                }
                else
                {
                    maxLength = 0x1f40L;
                }
                goto Label_0302;

            case SqlDbType.Decimal:
                obj2 = schemaRow[SchemaTableColumn.NumericPrecision];
                if (DBNull.Value != obj2)
                {
                    precision = Convert.ToByte(obj2, null);
                    break;
                }
                precision = SmiMetaData.DefaultDecimal.Precision;
                break;

            case SqlDbType.NChar:
            case SqlDbType.NVarChar:
                obj2 = schemaRow[SchemaTableColumn.ColumnSize];
                if (DBNull.Value != obj2)
                {
                    maxLength = Convert.ToInt64(obj2, null);
                    if (maxLength > 0xfa0L)
                    {
                        maxLength = -1L;
                    }
                    if ((maxLength < 0L) && ((maxLength != -1L) || (SqlDbType.NChar == dbType)))
                    {
                        throw SQL.InvalidColumnMaxLength(columnName, maxLength);
                    }
                }
                else if (SqlDbType.NChar != dbType)
                {
                    maxLength = -1L;
                }
                else
                {
                    maxLength = 0xfa0L;
                }
                goto Label_0302;

            case SqlDbType.Time:
            case SqlDbType.DateTime2:
            case SqlDbType.DateTimeOffset:
                obj2 = schemaRow[SchemaTableColumn.NumericScale];
                if (DBNull.Value != obj2)
                {
                    scale = Convert.ToByte(obj2, null);
                }
                else
                {
                    scale = SmiMetaData.DefaultTime.Scale;
                }
                if (scale > 7)
                {
                    throw SQL.InvalidColumnPrecScale();
                }
                if (scale < 0)
                {
                    scale = SmiMetaData.DefaultTime.Scale;
                }
                goto Label_0302;

            default:
                throw SQL.UnsupportedColumnTypeForSqlProvider(columnName, type2.ToString());
            }
            obj2 = schemaRow[SchemaTableColumn.NumericScale];
            if (DBNull.Value == obj2)
            {
                scale = SmiMetaData.DefaultDecimal.Scale;
            }
            else
            {
                scale = Convert.ToByte(obj2, null);
            }
            if (((precision < 1) || (precision > SqlDecimal.MaxPrecision)) || (((scale < 0) || (scale > SqlDecimal.MaxScale)) || (scale > precision)))
            {
                throw SQL.InvalidColumnPrecScale();
            }
Label_0302:
            return(new SmiExtendedMetaData(dbType, maxLength, precision, scale, (long)CultureInfo.CurrentCulture.LCID, SmiMetaData.GetDefaultForType(dbType).CompareOptions, null, false, null, null, columnName, null, null, null));
        }
Exemple #32
0
 // calling GetTimeSpan on possibly v100 SMI
 internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool gettersSupportKatmaiDateTime) {
     if (gettersSupportKatmaiDateTime) {
         return GetTimeSpan(sink, (SmiTypedGetterSetter)getters, ordinal, metaData);
     }
     ThrowIfITypedGettersIsNull(sink, getters, ordinal);
     object obj = GetValue(sink, getters, ordinal, metaData, null);
     if (null == obj) {
         throw ADP.InvalidCast();
     }
     return (TimeSpan) obj;
 }
Exemple #33
0
        internal static Stream GetStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool bypassTypeCheck = false) {
            bool isDbNull = ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal);

            // If a sql_variant, get the internal type
            if ( !bypassTypeCheck ) {
                if ((!isDbNull) && (metaData.SqlDbType == SqlDbType.Variant)) {
                    metaData = getters.GetVariantType(sink, ordinal);
                }
                // If the SqlDbType is still variant, then it must contain null, so don't throw InvalidCast
                if ((metaData.SqlDbType != SqlDbType.Variant) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Stream))) {
                    throw ADP.InvalidCast();
                }
            }

            byte[] data;
            if (isDbNull) {
                // "null" stream
                data = new byte[0];
            }
            else {
                // Read all data
                data = GetByteArray_Unchecked(sink, getters, ordinal);
            }

            // Wrap data in pre-built object
            return new MemoryStream(data, writable: false);
        }
Exemple #34
0
        internal static SqlSequentialTextReaderSmi GetSequentialTextReader( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
            Debug.Assert(!ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal), "Should not try to get a SqlSequentialTextReaderSmi on a null column");
            ThrowIfITypedGettersIsNull( sink, getters, ordinal );
            if ( !CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.TextReader ) ) {
                throw ADP.InvalidCast();
            }

            // This will advance the column to ordinal
            long length = GetCharsLength_Unchecked(sink, getters, ordinal);
            return new SqlSequentialTextReaderSmi(sink, getters, ordinal, length);
        }
Exemple #35
0
        internal static SqlXml GetSqlXml( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, SmiContext context ) {
            SqlXml result;
            if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlXml ) ) {
                if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
                    result = SqlXml.Null;
                }
                else {
                    result = GetSqlXml_Unchecked( sink, getters, ordinal, context );
                }
            }
            else {
                object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
                if (null == obj) {
                    throw ADP.InvalidCast();
                }
                result = (SqlXml) obj;
            }

            return result;
        }
Exemple #36
0
        private bool _isMetaSet;       // flag to indicate whether we have set the variant metadata

        internal SqlRecordBuffer(SmiMetaData metaData)
        {
            _isNull = true;
        }
 internal static 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)))) && !firstMd.IsMultiValued);
 }
Exemple #38
0
        // This is a modified version of SmiMetaDataFromSchemaTableRow above
        // Since CoreCLR doesn't have GetSchema, we need to infer the MetaData from the CLR Type alone
        internal static SmiExtendedMetaData SmiMetaDataFromType(string colName, Type colType)
        {
            // Determine correct SqlDbType.
            SqlDbType colDbType = InferSqlDbTypeFromType_Katmai(colType);

            if (InvalidSqlDbType == colDbType)
            {
                // Unknown through standard mapping, use VarBinary for columns that are Object typed, otherwise we error out.
                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 modifiers
                break;

            case SqlDbType.Binary:
            case SqlDbType.VarBinary:
                // source isn't specifying a size, so assume the Maximum
                if (SqlDbType.Binary == colDbType)
                {
                    maxLength = SmiMetaData.MaxBinaryLength;
                }
                else
                {
                    maxLength = SmiMetaData.UnlimitedMaxLengthIndicator;
                }
                break;

            case SqlDbType.Char:
            case SqlDbType.VarChar:
                // source isn't specifying a size, so assume the Maximum
                if (SqlDbType.Char == colDbType)
                {
                    maxLength = SmiMetaData.MaxANSICharacters;
                }
                else
                {
                    maxLength = SmiMetaData.UnlimitedMaxLengthIndicator;
                }
                break;

            case SqlDbType.NChar:
            case SqlDbType.NVarChar:
                // source isn't specifying a size, so assume the Maximum
                if (SqlDbType.NChar == colDbType)
                {
                    maxLength = SmiMetaData.MaxUnicodeCharacters;
                }
                else
                {
                    maxLength = SmiMetaData.UnlimitedMaxLengthIndicator;
                }
                break;

            case SqlDbType.Decimal:
                // Decimal requires precision and scale
                precision = SmiMetaData.DefaultDecimal.Precision;
                scale     = SmiMetaData.DefaultDecimal.Scale;
                break;

            case SqlDbType.Time:
            case SqlDbType.DateTime2:
            case SqlDbType.DateTimeOffset:
                // requires scale
                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,
                       CultureInfo.CurrentCulture.LCID,
                       SmiMetaData.GetDefaultForType(colDbType).CompareOptions,
                       false,                   // no support for multi-valued columns in a TVP yet
                       null,                    // no support for structured columns yet
                       null,
                       colName,
                       null,
                       null,
                       null));
        }
Exemple #39
0
 // valid for SqlDbType.Variant
 public override void SetVariantMetaData(SmiEventSink sink, int ordinal, SmiMetaData metaData)
 {
     _buffer[ordinal].VariantType = metaData;
 }
Exemple #40
0
 internal static bool IsSetterAccessValid(SmiMetaData metaData, SmiXetterTypeCode xetterType)
 {
     return(__isSetterAccessValid[(int)metaData.SqlDbType, (int)xetterType]);
 }
Exemple #41
0
        internal static SqlString GetSqlString( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
            SqlString result;
            if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlString ) ) {
                if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
                    result = SqlString.Null;
                }
                else {
                    String temp = GetString_Unchecked( sink, getters, ordinal );
                    result = new SqlString( temp );
                }
            }
            else if (SqlDbType.Xml == metaData.SqlDbType) {
                SqlXml xmlValue = GetSqlXml_Unchecked( sink, getters, ordinal, null );
                
                if (xmlValue.IsNull) {
                    result = SqlString.Null;
                }
                else {
                    result = new SqlString( xmlValue.Value );
                }
            }
            else {
                object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
                if (null == obj) {
                    throw ADP.InvalidCast();
                }
                result = (SqlString) obj;
            }

            return result;
        }
Exemple #42
0
        private static void SetSqlMoney_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlMoney value ) {
            if ( value.IsNull ) {
                setters.SetDBNull( sink, ordinal );
            }
            else {
                if ( SqlDbType.Variant == metaData.SqlDbType ) {
                    setters.SetVariantMetaData( sink, ordinal, SmiMetaData.DefaultMoney );
                    sink.ProcessMessagesAndThrow();
                }

                setters.SetInt64( sink, ordinal, value.ToSqlInternalRepresentation() );
             }
            sink.ProcessMessagesAndThrow();
        }
Exemple #43
0
 internal static String GetString( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
     ThrowIfITypedGettersIsNull( sink, getters, ordinal );
     if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.String ) ) {
         return GetString_Unchecked( sink, getters, ordinal );
     }
     object obj = GetValue( sink, getters, ordinal, metaData, null  );
     if (null == obj) {
         throw ADP.InvalidCast();
     }
     return (String) obj;
 }
Exemple #44
0
 private static void SetSqlString_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlString value, int offset, int length ) {
     if ( value.IsNull ) {
         setters.SetDBNull( sink, ordinal );
         sink.ProcessMessagesAndThrow();
     }
     else {
         if (SqlDbType.Variant == metaData.SqlDbType) {
             // Set up a NVarChar metadata with correct LCID/Collation
             metaData = new SmiMetaData(
                     SqlDbType.NVarChar, 
                     SmiMetaData.MaxUnicodeCharacters,
                     0, 
                     0, 
                     value.LCID,
                     value.SqlCompareOptions,
                     null);
             setters.SetVariantMetaData( sink, ordinal, metaData );
             sink.ProcessMessagesAndThrow();
         }
         SetString_Unchecked( sink, setters, ordinal, value.Value, offset, length );
     }
 }
Exemple #45
0
 public virtual void SetVariantMetaData(SmiEventSink sink, int ordinal, SmiMetaData metaData)
 {
     throw ADP.InternalError(ADP.InternalErrorCode.UnimplementedSMIMethod);
 }
Exemple #46
0
        private static void SetDataTable_Unchecked(
                SmiEventSink_Default    sink,
                SmiTypedGetterSetter    setters,
                int                     ordinal,
                SmiMetaData             metaData,
                DataTable               value
            ) {
            // Get the target gettersetter
            setters = setters.GetTypedGetterSetter(sink, ordinal);
            sink.ProcessMessagesAndThrow();

            // iterate over all records
            //  if first record was obtained earlier, use it prior to pulling more
            ExtendedClrTypeCode[] cellTypes = new ExtendedClrTypeCode[metaData.FieldMetaData.Count];
            for(int i=0; i<metaData.FieldMetaData.Count; i++) {
                cellTypes[i] = ExtendedClrTypeCode.Invalid;
            }
            foreach(DataRow row in value.Rows) {
                setters.NewElement(sink);
                sink.ProcessMessagesAndThrow();

                // Set all columns in the record
                for(int i=0; i<metaData.FieldMetaData.Count; i++) {
                    SmiMetaData fieldMetaData = metaData.FieldMetaData[i];
                    if (row.IsNull(i)) {
                        SetDBNull_Unchecked(sink, setters, i);
                    }
                    else {
                        object cellValue = row[i];

                        // Only determine cell types for first row, to save expensive 
                        if (ExtendedClrTypeCode.Invalid == cellTypes[i]) {
                            cellTypes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(
                                    fieldMetaData.SqlDbType, fieldMetaData.IsMultiValued, cellValue, fieldMetaData.Type, 
                                    // 

                                    SmiContextFactory.KatmaiVersion 
                                    );
                        }
                        SetCompatibleValueV200(sink, setters, i, fieldMetaData, cellValue, cellTypes[i], 0, NoLengthLimit, null);
                    }
                }
            }

            setters.EndElements(sink);
            sink.ProcessMessagesAndThrow();
        }
Exemple #47
0
        internal static TextReader GetTextReader( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
            bool isDbNull = ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal);

            // If a sql_variant, get the internal type
            if ((!isDbNull) && (metaData.SqlDbType == SqlDbType.Variant)) {
                metaData = getters.GetVariantType(sink, ordinal);
            }
            // If the SqlDbType is still variant, then it must contain null, so don't throw InvalidCast
            if ((metaData.SqlDbType != SqlDbType.Variant) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TextReader))) {
                throw ADP.InvalidCast();
            }

            string data;
            if (isDbNull) {
                // "null" textreader
                data = string.Empty;
            }
            else {
                // Read all data
                data = GetString_Unchecked(sink, getters, ordinal);
            }

            // Wrap in pre-built object
            return new StringReader(data);
        }
Exemple #48
0
        // Set a DbDataReader to a Structured+MultiValued setter (table type)
        //  Assumes metaData correctly describes the reader's shape, and consumes only the current resultset
        private static void SetDbDataReader_Unchecked(
            SmiEventSink_Default    sink,
            SmiTypedGetterSetter    setters,
            int                     ordinal,
            SmiMetaData             metaData,
            DbDataReader            value
            ) {
            // Get the target gettersetter
            setters = setters.GetTypedGetterSetter(sink, ordinal);
            sink.ProcessMessagesAndThrow();

            // Iterate over all rows in the current set of results
            while (value.Read()) {
                setters.NewElement(sink);
                sink.ProcessMessagesAndThrow();

                FillCompatibleSettersFromReader(sink, setters, metaData.FieldMetaData, value);
            }

            setters.EndElements(sink);
            sink.ProcessMessagesAndThrow();
        }
Exemple #49
0
 // dealing with v200 SMI
 internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData) {
     ThrowIfITypedGettersIsNull(sink, getters, ordinal);
     if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TimeSpan)) {
         return GetTimeSpan_Unchecked(sink, getters, ordinal);
     }
     return (TimeSpan)GetValue200(sink, getters, ordinal, metaData, null);
 }
Exemple #50
0
        private static void SetIEnumerableOfSqlDataRecord_Unchecked(
            SmiEventSink_Default        sink,
            SmiTypedGetterSetter        setters,
            int                         ordinal,
            SmiMetaData                 metaData,
            IEnumerable<SqlDataRecord>  value,
            ParameterPeekAheadValue     peekAhead
            ) {
            // Get target gettersetter
            setters = setters.GetTypedGetterSetter(sink, ordinal);
            sink.ProcessMessagesAndThrow();

            IEnumerator<SqlDataRecord> enumerator = null;
            try {
                // Need to copy field metadata to an array to call FillCompatibleITypeSettersFromRecord
                SmiExtendedMetaData[] mdFields = new SmiExtendedMetaData[metaData.FieldMetaData.Count];
                metaData.FieldMetaData.CopyTo(mdFields, 0);

                SmiDefaultFieldsProperty defaults = (SmiDefaultFieldsProperty) metaData.ExtendedProperties[SmiPropertySelector.DefaultFields];

                int recordNumber = 1;   // used only for reporting position when there are errors.

                // obtain enumerator and handle any peekahead values
                if (null != peekAhead && null != peekAhead.FirstRecord) {
                    // hook up to enumerator
                    enumerator = peekAhead.Enumerator;

                    // send the first record that was obtained earlier
                    setters.NewElement(sink);
                    sink.ProcessMessagesAndThrow();
                    FillCompatibleSettersFromRecord(sink, setters, mdFields, peekAhead.FirstRecord, defaults);
                    recordNumber++;
                }
                else {
                    enumerator = value.GetEnumerator();
                }

                using (enumerator) {
                    while(enumerator.MoveNext()) {
                        setters.NewElement(sink);
                        sink.ProcessMessagesAndThrow();

                        SqlDataRecord record = enumerator.Current;

                        if (record.FieldCount != mdFields.Length) {
                            throw SQL.EnumeratedRecordFieldCountChanged(recordNumber);
                        }

                        for(int i=0; i<record.FieldCount; i++) {
                            if (!MetaDataUtilsSmi.IsCompatible(metaData.FieldMetaData[i], record.GetSqlMetaData(i))) {
                                throw SQL.EnumeratedRecordMetaDataChanged(record.GetName(i), recordNumber);
                            }
                        }

                        FillCompatibleSettersFromRecord(sink, setters, mdFields, record, defaults);
                        recordNumber++;
                    }

                    setters.EndElements(sink);
                    sink.ProcessMessagesAndThrow();
                }
            }
            finally {
                // Clean up!
                IDisposable disposable = enumerator as IDisposable;
                if (null != disposable) {
                    disposable.Dispose();
                }
            }
        }
Exemple #51
0
        // dealing with v200 SMI
        internal static object GetSqlValue200(
            SmiEventSink_Default sink,
            SmiTypedGetterSetter getters,
            int ordinal,
            SmiMetaData metaData,
            SmiContext context
            ) {
            object result = null;
            if (IsDBNull_Unchecked(sink, getters, ordinal)) {
                if (SqlDbType.Udt == metaData.SqlDbType) {
                    result = NullUdtInstance(metaData);
                } else {
                    result = __typeSpecificNullForSqlValue[(int)metaData.SqlDbType];
                }
            } else {
                switch (metaData.SqlDbType) {
                    case SqlDbType.Variant: // Handle variants specifically for v200, since they could contain v200 types
                        metaData = getters.GetVariantType(sink, ordinal);
                        sink.ProcessMessagesAndThrow();
                        Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!");
                        result = GetSqlValue200(sink, getters, ordinal, metaData, context);
                        break;
                    case SqlDbType.Date:
                    case SqlDbType.DateTime2:
                        result = GetDateTime_Unchecked(sink, getters, ordinal);
                        break;
                    case SqlDbType.Time:
                        result = GetTimeSpan_Unchecked(sink, getters, ordinal);
                        break;
                    case SqlDbType.DateTimeOffset:
                        result = GetDateTimeOffset_Unchecked(sink, getters, ordinal);
                        break;
                    default:
                        result = GetSqlValue(sink, getters, ordinal, metaData, context);
                        break;
                }
            }

            return result;
        }
Exemple #52
0
        internal static SqlChars GetSqlChars( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, SmiContext context ) {
            SqlChars result;
            if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlChars ) ) {
                if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
                    result = SqlChars.Null;
                }
                else {
                    long length = GetCharsLength_Unchecked( sink, getters, ordinal );
                    if ( length < __maxCharChunkSize || !InOutOfProcHelper.InProc) {
                        char[] charBuffer = GetCharArray_Unchecked( sink, getters, ordinal );
                        result = new SqlChars( charBuffer );
                    }
                    else {    // InProc only
                        Stream s = new SmiGettersStream( sink, getters, ordinal, metaData );
                        SqlStreamChars sc = CopyIntoNewSmiScratchStreamChars( s, sink, context );
                        result = new SqlChars( sc );
                    }
                }
            }
            else {
                SqlString stringValue;
                if (SqlDbType.Xml == metaData.SqlDbType) {
                    SqlXml xmlValue = GetSqlXml_Unchecked( sink, getters, ordinal, null );

                    if (xmlValue.IsNull) {
                        result = SqlChars.Null;
                    }
                    else {
                        result = new SqlChars( xmlValue.Value.ToCharArray() );
                    }
                }
                else {
                    object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
                    if (null == obj) {
                        throw ADP.InvalidCast();
                    }
                    stringValue = (SqlString) obj;

                    if ( stringValue.IsNull ) {
                        result = SqlChars.Null;
                    }
                    else {
                        result = new SqlChars( stringValue.Value.ToCharArray() );
                    }
                }
            }

            return result;
        }
        public virtual void SetVariantMetaData( SmiEventSink sink, int ordinal, SmiMetaData metaData ) {
            // ******** OBSOLETING from SMI -- this should have been removed from ITypedSettersV3
            //  Intended to be removed prior to RTM.  Sub-classes need not implement

            // Implement body with throw because there are only a couple of ways to get to this code:
            //  1) Client is calling this method even though the server negotiated for V3+ and dropped support for V2-.
            //  2) Server didn't implement V2- on some interface and negotiated V2-.
            throw System.Data.Common.ADP.InternalError( System.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod );
        }
Exemple #54
0
        internal static SqlSingle GetSqlSingle( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
            SqlSingle result;
            if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlSingle ) ) {
                if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
                    result = SqlSingle.Null;
                }
                else {
                    Single temp = GetSingle_Unchecked( sink, getters, ordinal );
                    result = new SqlSingle( temp );
                }
            }
            else {
                object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
                if (null == obj) {
                    throw ADP.InvalidCast();
                }
                result = (SqlSingle) obj;
            }

            return result;
        }
 internal SqlRecordBuffer(SmiMetaData metaData)
 {
 }
Exemple #56
0
        // 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.
        internal static SmiExtendedMetaData SmiMetaDataFromSchemaTableRow(DataRow schemaRow)
        {
            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_Katmai(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));
        }