// UDTs and null variants come back via return value, all else is via targetBuffer. // implements SqlClient 2.0-compatible output parameter semantics internal static object GetOutputParameterV3Smi( SmiEventSink_Default sink, // event sink for errors ITypedGettersV3 getters, // getters interface to grab value from int ordinal, // parameter within getters SmiMetaData metaData, // Getter's type for this ordinal SmiContext context, // used to obtain scratch streams SqlBuffer targetBuffer // destination ) { object result = null; // Workaround for UDT hack in non-Smi code paths. if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) { GetNullOutputParameterSmi(metaData, targetBuffer, ref result); } else { switch( metaData.SqlDbType ) { case SqlDbType.BigInt: targetBuffer.Int64 = GetInt64_Unchecked( sink, getters, ordinal ); break; case SqlDbType.Binary: case SqlDbType.Image: case SqlDbType.Timestamp: case SqlDbType.VarBinary: targetBuffer.SqlBinary = GetSqlBinary_Unchecked( sink, getters, ordinal ); break; case SqlDbType.Bit: targetBuffer.Boolean = GetBoolean_Unchecked( sink, getters, ordinal ); break; case SqlDbType.NChar: case SqlDbType.NText: case SqlDbType.NVarChar: case SqlDbType.Char: case SqlDbType.VarChar: case SqlDbType.Text: targetBuffer.SetToString( GetString_Unchecked( sink, getters, ordinal ) ); break; case SqlDbType.DateTime: case SqlDbType.SmallDateTime: { SqlDateTime dt = new SqlDateTime( GetDateTime_Unchecked( sink, getters, ordinal ) ); targetBuffer.SetToDateTime( dt.DayTicks, dt.TimeTicks ); break; } case SqlDbType.Decimal: { SqlDecimal dec = GetSqlDecimal_Unchecked( sink, getters, ordinal ); targetBuffer.SetToDecimal( dec.Precision, dec.Scale, dec.IsPositive, dec.Data ); break; } case SqlDbType.Float: targetBuffer.Double = GetDouble_Unchecked( sink, getters, ordinal ); break; case SqlDbType.Int: targetBuffer.Int32 = GetInt32_Unchecked( sink, getters, ordinal ); break; case SqlDbType.Money: case SqlDbType.SmallMoney: targetBuffer.SetToMoney( GetInt64_Unchecked( sink, getters, ordinal) ); break; case SqlDbType.Real: targetBuffer.Single = GetSingle_Unchecked( sink, getters, ordinal ); break; case SqlDbType.UniqueIdentifier: targetBuffer.SqlGuid = new SqlGuid( GetGuid_Unchecked( sink, getters, ordinal ) ); break; case SqlDbType.SmallInt: targetBuffer.Int16 = GetInt16_Unchecked( sink, getters, ordinal ); break; case SqlDbType.TinyInt: targetBuffer.Byte = GetByte_Unchecked( sink, getters, ordinal ); break; case SqlDbType.Variant: // For variants, recur using the current value's sqldbtype metaData = getters.GetVariantType( sink, ordinal ); sink.ProcessMessagesAndThrow(); Debug.Assert( SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant not supposed to be possible!" ); GetOutputParameterV3Smi( sink, getters, ordinal, metaData, context, targetBuffer ); break; case SqlDbType.Udt: result = GetUdt_LengthChecked( sink, getters, ordinal, metaData ); break; case SqlDbType.Xml: targetBuffer.SqlXml = GetSqlXml_Unchecked( sink, getters, ordinal, null ); break; default: Debug.Assert( false, "Unexpected SqlDbType" ); break; } } return result; }
internal bool TryReadSqlValueInternal(SqlBuffer value, byte tdsType, int length, TdsParserStateObject stateObj) { switch (tdsType) { case TdsEnums.SQLBIT: case TdsEnums.SQLBITN: Debug.Assert(length == 1, "invalid length for SqlBoolean type!"); byte byteValue; if (!stateObj.TryReadByte(out byteValue)) { return false; } value.Boolean = (byteValue != 0); break; case TdsEnums.SQLINTN: if (length == 1) { goto case TdsEnums.SQLINT1; } else if (length == 2) { goto case TdsEnums.SQLINT2; } else if (length == 4) { goto case TdsEnums.SQLINT4; } else { goto case TdsEnums.SQLINT8; } case TdsEnums.SQLINT1: Debug.Assert(length == 1, "invalid length for SqlByte type!"); if (!stateObj.TryReadByte(out byteValue)) { return false; } value.Byte = byteValue; break; case TdsEnums.SQLINT2: Debug.Assert(length == 2, "invalid length for SqlInt16 type!"); short shortValue; if (!stateObj.TryReadInt16(out shortValue)) { return false; } value.Int16 = shortValue; break; case TdsEnums.SQLINT4: Debug.Assert(length == 4, "invalid length for SqlInt32 type!"); int intValue; if (!stateObj.TryReadInt32(out intValue)) { return false; } value.Int32 = intValue; break; case TdsEnums.SQLINT8: Debug.Assert(length == 8, "invalid length for SqlInt64 type!"); long longValue; if (!stateObj.TryReadInt64(out longValue)) { return false; } value.Int64 = longValue; break; case TdsEnums.SQLFLTN: if (length == 4) { goto case TdsEnums.SQLFLT4; } else { goto case TdsEnums.SQLFLT8; } case TdsEnums.SQLFLT4: Debug.Assert(length == 4, "invalid length for SqlSingle type!"); float singleValue; if (!stateObj.TryReadSingle(out singleValue)) { return false; } value.Single = singleValue; break; case TdsEnums.SQLFLT8: Debug.Assert(length == 8, "invalid length for SqlDouble type!"); double doubleValue; if (!stateObj.TryReadDouble(out doubleValue)) { return false; } value.Double = doubleValue; break; case TdsEnums.SQLMONEYN: if (length == 4) { goto case TdsEnums.SQLMONEY4; } else { goto case TdsEnums.SQLMONEY; } case TdsEnums.SQLMONEY: { int mid; uint lo; if (!stateObj.TryReadInt32(out mid)) { return false; } if (!stateObj.TryReadUInt32(out lo)) { return false; } long l = (((long)mid) << 0x20) + ((long)lo); value.SetToMoney(l); break; } case TdsEnums.SQLMONEY4: if (!stateObj.TryReadInt32(out intValue)) { return false; } value.SetToMoney(intValue); break; case TdsEnums.SQLDATETIMN: if (length == 4) { goto case TdsEnums.SQLDATETIM4; } else { goto case TdsEnums.SQLDATETIME; } case TdsEnums.SQLDATETIM4: ushort daypartShort, timepartShort; if (!stateObj.TryReadUInt16(out daypartShort)) { return false; } if (!stateObj.TryReadUInt16(out timepartShort)) { return false; } value.SetToDateTime(daypartShort, timepartShort * SqlDateTime.SQLTicksPerMinute); break; case TdsEnums.SQLDATETIME: int daypart; uint timepart; if (!stateObj.TryReadInt32(out daypart)) { return false; } if (!stateObj.TryReadUInt32(out timepart)) { return false; } value.SetToDateTime(daypart, (int)timepart); break; case TdsEnums.SQLUNIQUEID: { Debug.Assert(length == 16, "invalid length for SqlGuid type!"); byte[] b = new byte[length]; if (!stateObj.TryReadByteArray(b, 0, length)) { return false; } value.SqlGuid = new SqlGuid(b, true); // doesn't copy the byte array break; } case TdsEnums.SQLBINARY: case TdsEnums.SQLBIGBINARY: case TdsEnums.SQLBIGVARBINARY: case TdsEnums.SQLVARBINARY: case TdsEnums.SQLIMAGE: { // Note: Better not come here with plp data!! Debug.Assert(length <= TdsEnums.MAXSIZE); byte[] b = new byte[length]; if (!stateObj.TryReadByteArray(b, 0, length)) { return false; } value.SqlBinary = new SqlBinary(b, true); // doesn't copy the byte array break; } case TdsEnums.SQLVARIANT: if (!TryReadSqlVariant(value, length, stateObj)) { return false; } break; default: Debug.Assert(false, "Unknown SqlType!" + tdsType.ToString(CultureInfo.InvariantCulture)); break; } // switch return true; }
/// <summary> /// Deserializes the unencrypted bytes into a value based on the target type info. /// </summary> internal bool DeserializeUnencryptedValue (SqlBuffer value, byte[] unencryptedBytes, SqlMetaDataPriv md, TdsParserStateObject stateObj, byte normalizationVersion) { if (normalizationVersion != 0x01) { throw SQL.UnsupportedNormalizationVersion(normalizationVersion); } byte tdsType = md.baseTI.tdsType; int length = unencryptedBytes.Length; // For normalized types, the length and scale of the actual type might be different than the value's. int denormalizedLength = md.baseTI.length; byte denormalizedScale = md.baseTI.scale; Debug.Assert (false == md.baseTI.isEncrypted, "Double encryption detected"); switch (tdsType) { // We normalize to allow conversion across data types. All data types below are serialized into a BIGINT. case TdsEnums.SQLBIT: case TdsEnums.SQLBITN: case TdsEnums.SQLINTN: case TdsEnums.SQLINT1: case TdsEnums.SQLINT2: case TdsEnums.SQLINT4: case TdsEnums.SQLINT8: Debug.Assert(length == 8, "invalid length for SqlInt64 type!"); byte byteValue; long longValue; if (unencryptedBytes.Length != 8) { return false; } longValue = BitConverter.ToInt64(unencryptedBytes, 0); if (tdsType == TdsEnums.SQLBIT || tdsType == TdsEnums.SQLBITN) { value.Boolean = (longValue != 0); break; } if (tdsType == TdsEnums.SQLINT1 || denormalizedLength == 1) value.Byte = (byte)longValue; else if (tdsType == TdsEnums.SQLINT2 || denormalizedLength == 2) value.Int16 = (Int16)longValue; else if (tdsType == TdsEnums.SQLINT4 || denormalizedLength == 4) value.Int32 = (Int32)longValue; else value.Int64 = longValue; break; case TdsEnums.SQLFLTN: if (length == 4) { goto case TdsEnums.SQLFLT4; } else { goto case TdsEnums.SQLFLT8; } case TdsEnums.SQLFLT4: Debug.Assert(length == 4, "invalid length for SqlSingle type!"); float singleValue; if (unencryptedBytes.Length != 4) { return false; } singleValue = BitConverter.ToSingle(unencryptedBytes, 0); value.Single = singleValue; break; case TdsEnums.SQLFLT8: double doubleValue; if (unencryptedBytes.Length != 8) { return false; } doubleValue = BitConverter.ToDouble(unencryptedBytes, 0); value.Double = doubleValue; break; // We normalize to allow conversion across data types. SMALLMONEY is serialized into a MONEY. case TdsEnums.SQLMONEYN: case TdsEnums.SQLMONEY4: case TdsEnums.SQLMONEY: { int mid; uint lo; if (unencryptedBytes.Length != 8) { return false; } mid = BitConverter.ToInt32(unencryptedBytes, 0); lo = BitConverter.ToUInt32(unencryptedBytes, 4); long l = (((long)mid) << 0x20) + ((long)lo); value.SetToMoney(l); break; } case TdsEnums.SQLDATETIMN: if (length == 4) { goto case TdsEnums.SQLDATETIM4; } else { goto case TdsEnums.SQLDATETIME; } case TdsEnums.SQLDATETIM4: ushort daypartShort, timepartShort; if (unencryptedBytes.Length != 4) { return false; } daypartShort = (UInt16)((unencryptedBytes[1] << 8) + unencryptedBytes[0]); timepartShort = (UInt16)((unencryptedBytes[3] << 8) + unencryptedBytes[2]); value.SetToDateTime(daypartShort, timepartShort * SqlDateTime.SQLTicksPerMinute); break; case TdsEnums.SQLDATETIME: int daypart; uint timepart; if (unencryptedBytes.Length != 8) { return false; } daypart = BitConverter.ToInt32(unencryptedBytes, 0); timepart = BitConverter.ToUInt32(unencryptedBytes, 4); value.SetToDateTime(daypart, (int)timepart); break; case TdsEnums.SQLUNIQUEID: { Debug.Assert(length == 16, "invalid length for SqlGuid type!"); value.SqlGuid = new SqlGuid(unencryptedBytes, true); // doesn't copy the byte array break; } case TdsEnums.SQLBINARY: case TdsEnums.SQLBIGBINARY: case TdsEnums.SQLBIGVARBINARY: case TdsEnums.SQLVARBINARY: case TdsEnums.SQLIMAGE: { // Note: Better not come here with plp data!! Debug.Assert(length <= TdsEnums.MAXSIZE, "Plp data decryption attempted"); // If this is a fixed length type, pad with zeros to get to the fixed length size. if (tdsType == TdsEnums.SQLBINARY || tdsType == TdsEnums.SQLBIGBINARY) { byte[] bytes = new byte[md.baseTI.length]; Buffer.BlockCopy(unencryptedBytes, 0, bytes, 0, unencryptedBytes.Length); unencryptedBytes = bytes; } value.SqlBinary = new SqlBinary(unencryptedBytes, true); // doesn't copy the byte array break; } case TdsEnums.SQLDECIMALN: case TdsEnums.SQLNUMERICN: // Check the sign from the first byte. int index = 0; byteValue = unencryptedBytes[index++]; bool fPositive = (1 == byteValue); // Now read the 4 next integers which contain the actual value. length = checked((int)length-1); int[] bits = new int[4]; int decLength = length>>2; for (int i = 0; i < decLength; i++) { // up to 16 bytes of data following the sign byte bits[i] = BitConverter.ToInt32(unencryptedBytes, index); index += 4; } value.SetToDecimal (md.baseTI.precision, md.baseTI.scale, fPositive, bits); break; case TdsEnums.SQLCHAR: case TdsEnums.SQLBIGCHAR: case TdsEnums.SQLVARCHAR: case TdsEnums.SQLBIGVARCHAR: case TdsEnums.SQLTEXT: { System.Text.Encoding encoding = md.baseTI.encoding; if (null == encoding) { encoding = _defaultEncoding; } if (null == encoding) { ThrowUnsupportedCollationEncountered(stateObj); } string strValue = encoding.GetString(unencryptedBytes, 0, length); // If this is a fixed length type, pad with spaces to get to the fixed length size. if (tdsType == TdsEnums.SQLCHAR || tdsType == TdsEnums.SQLBIGCHAR) { strValue = strValue.PadRight(md.baseTI.length); } value.SetToString(strValue); break; } case TdsEnums.SQLNCHAR: case TdsEnums.SQLNVARCHAR: case TdsEnums.SQLNTEXT: { string strValue = System.Text.Encoding.Unicode.GetString(unencryptedBytes, 0, length); // If this is a fixed length type, pad with spaces to get to the fixed length size. if (tdsType == TdsEnums.SQLNCHAR) { strValue = strValue.PadRight(md.baseTI.length / ADP.CharSize); } value.SetToString(strValue); break; } case TdsEnums.SQLDATE: Debug.Assert(length == 3, "invalid length for date type!"); value.SetToDate(unencryptedBytes); break; case TdsEnums.SQLTIME: // We normalize to maximum precision to allow conversion across different precisions. Debug.Assert(length == 5, "invalid length for time type!"); value.SetToTime(unencryptedBytes, length, TdsEnums.MAX_TIME_SCALE, denormalizedScale); break; case TdsEnums.SQLDATETIME2: // We normalize to maximum precision to allow conversion across different precisions. Debug.Assert(length == 8, "invalid length for datetime2 type!"); value.SetToDateTime2(unencryptedBytes, length, TdsEnums.MAX_TIME_SCALE, denormalizedScale); break; case TdsEnums.SQLDATETIMEOFFSET: // We normalize to maximum precision to allow conversion across different precisions. Debug.Assert(length == 10, "invalid length for datetimeoffset type!"); value.SetToDateTimeOffset(unencryptedBytes, length, TdsEnums.MAX_TIME_SCALE, denormalizedScale); break; default: MetaType metaType = md.baseTI.metaType; // If we don't have a metatype already, construct one to get the proper type name. if (metaType == null) { metaType = MetaType.GetSqlDataType(tdsType, userType:0, length:length); } throw SQL.UnsupportedDatatypeEncryption(metaType.TypeName); } return true; }
internal static object GetOutputParameterV3Smi(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, SmiContext context, SqlBuffer targetBuffer) { object result = null; if (IsDBNull_Unchecked(sink, getters, ordinal)) { GetNullOutputParameterSmi(metaData, targetBuffer, ref result); return result; } switch (metaData.SqlDbType) { case SqlDbType.BigInt: targetBuffer.Int64 = GetInt64_Unchecked(sink, getters, ordinal); return result; case SqlDbType.Binary: case SqlDbType.Image: case SqlDbType.Timestamp: case SqlDbType.VarBinary: targetBuffer.SqlBinary = GetSqlBinary_Unchecked(sink, getters, ordinal); return result; case SqlDbType.Bit: targetBuffer.Boolean = GetBoolean_Unchecked(sink, getters, ordinal); return result; case SqlDbType.Char: case SqlDbType.NChar: case SqlDbType.NText: case SqlDbType.NVarChar: case SqlDbType.Text: case SqlDbType.VarChar: targetBuffer.SetToString(GetString_Unchecked(sink, getters, ordinal)); return result; case SqlDbType.DateTime: case SqlDbType.SmallDateTime: { SqlDateTime time = new SqlDateTime(GetDateTime_Unchecked(sink, getters, ordinal)); targetBuffer.SetToDateTime(time.DayTicks, time.TimeTicks); return result; } case SqlDbType.Decimal: { SqlDecimal num = GetSqlDecimal_Unchecked(sink, getters, ordinal); targetBuffer.SetToDecimal(num.Precision, num.Scale, num.IsPositive, num.Data); return result; } case SqlDbType.Float: targetBuffer.Double = GetDouble_Unchecked(sink, getters, ordinal); return result; case SqlDbType.Int: targetBuffer.Int32 = GetInt32_Unchecked(sink, getters, ordinal); return result; case SqlDbType.Money: case SqlDbType.SmallMoney: targetBuffer.SetToMoney(GetInt64_Unchecked(sink, getters, ordinal)); return result; case SqlDbType.Real: targetBuffer.Single = GetSingle_Unchecked(sink, getters, ordinal); return result; case SqlDbType.UniqueIdentifier: targetBuffer.SqlGuid = new SqlGuid(GetGuid_Unchecked(sink, getters, ordinal)); return result; case SqlDbType.SmallInt: targetBuffer.Int16 = GetInt16_Unchecked(sink, getters, ordinal); return result; case SqlDbType.TinyInt: targetBuffer.Byte = GetByte_Unchecked(sink, getters, ordinal); return result; case SqlDbType.Variant: metaData = getters.GetVariantType(sink, ordinal); sink.ProcessMessagesAndThrow(); GetOutputParameterV3Smi(sink, getters, ordinal, metaData, context, targetBuffer); return result; case (SqlDbType.SmallInt | SqlDbType.Int): case (SqlDbType.Text | SqlDbType.Int): case (SqlDbType.Xml | SqlDbType.Bit): case (SqlDbType.TinyInt | SqlDbType.Int): return result; case SqlDbType.Xml: targetBuffer.SqlXml = GetSqlXml_Unchecked(sink, getters, ordinal, null); return result; case SqlDbType.Udt: return GetUdt_LengthChecked(sink, getters, ordinal, metaData); } return result; }
internal void ReadSqlValueInternal(SqlBuffer value, byte tdsType, int typeId, int length, TdsParserStateObject stateObj) { int num4; switch (tdsType) { case 0x7f: goto Label_011A; case 0xa5: case 0xad: case 0x22: case 0x25: case 0x2d: { byte[] buff = new byte[length]; stateObj.ReadByteArray(buff, 0, length); value.SqlBinary = new SqlBinary(buff, true); return; } case 0x6d: if (length != 4) { goto Label_013B; } goto Label_012D; case 110: if (length == 4) { goto Label_0173; } goto Label_014E; case 0x6f: if (length != 4) { goto Label_01A2; } goto Label_0187; case 0x7a: goto Label_0173; case 0x62: this.ReadSqlVariant(value, length, stateObj); return; case 0x68: case 50: value.Boolean = stateObj.ReadByte() != 0; return; case 0x23: case 0x2e: case 0x2f: case 0x31: case 0x33: case 0x35: case 0x36: case 0x37: case 0x39: return; case 0x24: { byte[] buffer2 = new byte[length]; stateObj.ReadByteArray(buffer2, 0, length); value.SqlGuid = new SqlGuid(buffer2, true); return; } case 0x26: if (length == 1) { break; } if (length == 2) { goto Label_00FE; } if (length != 4) { goto Label_011A; } goto Label_010C; case 0x30: break; case 0x34: goto Label_00FE; case 0x38: goto Label_010C; case 0x3a: goto Label_0187; case 0x3b: goto Label_012D; case 60: goto Label_014E; case 0x3d: goto Label_01A2; case 0x3e: goto Label_013B; default: return; } value.Byte = stateObj.ReadByte(); return; Label_00FE: value.Int16 = stateObj.ReadInt16(); return; Label_010C: value.Int32 = stateObj.ReadInt32(); return; Label_011A: value.Int64 = stateObj.ReadInt64(); return; Label_012D: value.Single = stateObj.ReadSingle(); return; Label_013B: value.Double = stateObj.ReadDouble(); return; Label_014E: num4 = stateObj.ReadInt32(); uint num3 = stateObj.ReadUInt32(); long num2 = (num4 << 0x20) + num3; value.SetToMoney(num2); return; Label_0173: value.SetToMoney((long) stateObj.ReadInt32()); return; Label_0187: value.SetToDateTime(stateObj.ReadUInt16(), stateObj.ReadUInt16() * SqlDateTime.SQLTicksPerMinute); return; Label_01A2: value.SetToDateTime(stateObj.ReadInt32(), (int) stateObj.ReadUInt32()); }