// Semantics for SetChars are to modify existing value, not overwrite // Use in combination with SetLength to ensure overwriting when necessary // valid for character types: Char, VarChar, Text, NChar, NVarChar, NText // (NVarChar and global clr collation assumed for variants) internal int SetChars(long fieldOffset, char[] buffer, int bufferOffset, int length) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetChars)); // ANSI types must convert to byte[] because that's the tool we have. if (MetaDataUtilsSmi.IsAnsiType(_metaData.SqlDbType)) { if (null == _encoder) { _encoder = _stateObj.Parser._defaultEncoding.GetEncoder(); } byte[] bytes = new byte[_encoder.GetByteCount(buffer, bufferOffset, length, false)]; _encoder.GetBytes(buffer, bufferOffset, length, bytes, 0, false); SetBytesNoOffsetHandling(fieldOffset, bytes, 0, bytes.Length); } else { CheckSettingOffset(fieldOffset); // Send via PLP format if we can. if (_isPlp) { // Handle initial PLP markers if (!_plpUnknownSent) { _stateObj.Parser.WriteUnsignedLong(TdsEnums.SQL_PLP_UNKNOWNLEN, _stateObj); _plpUnknownSent = true; } // Write chunk length _stateObj.Parser.WriteInt(length * ADP.CharSize, _stateObj); _stateObj.Parser.WriteCharArray(buffer, length, bufferOffset, _stateObj); } else { // Non-plp data must be sent in one chunk for now. #if DEBUG Debug.Assert(0 == _currentOffset, "SetChars doesn't yet support chunking for non-plp data: " + _currentOffset); #endif if (SqlDbType.Variant == _metaData.SqlDbType) { _stateObj.Parser.WriteSqlVariantValue(new string(buffer, bufferOffset, length), length, 0, _stateObj); } else { Debug.Assert(!MetaType.GetMetaTypeFromSqlDbType(_metaData.SqlDbType, _metaData.IsMultiValued).IsLong, "We're assuming long length types are sent as PLP. SqlDbType = " + _metaData.SqlDbType); _stateObj.Parser.WriteShort(length * ADP.CharSize, _stateObj); _stateObj.Parser.WriteCharArray(buffer, length, bufferOffset, _stateObj); } } } #if DEBUG _currentOffset += length; #endif return(length); }
internal int SetChars(long fieldOffset, char[] buffer, int bufferOffset, int length) { if (MetaDataUtilsSmi.IsAnsiType(this._metaData.SqlDbType)) { if (this._encoder == null) { this._encoder = this._stateObj.Parser._defaultEncoding.GetEncoder(); } byte[] bytes = new byte[this._encoder.GetByteCount(buffer, bufferOffset, length, false)]; this._encoder.GetBytes(buffer, bufferOffset, length, bytes, 0, false); this.SetBytesNoOffsetHandling(fieldOffset, bytes, 0, bytes.Length); return(length); } if (this._isPlp) { if (!this._plpUnknownSent) { this._stateObj.Parser.WriteUnsignedLong(18446744073709551614L, this._stateObj); this._plpUnknownSent = true; } this._stateObj.Parser.WriteInt(length * ADP.CharSize, this._stateObj); this._stateObj.Parser.WriteCharArray(buffer, length, bufferOffset, this._stateObj); return(length); } if (SqlDbType.Variant == this._metaData.SqlDbType) { this._stateObj.Parser.WriteSqlVariantValue(new string(buffer, bufferOffset, length), length, 0, this._stateObj); return(length); } this._stateObj.Parser.WriteShort(length * ADP.CharSize, this._stateObj); this._stateObj.Parser.WriteCharArray(buffer, length, bufferOffset, this._stateObj); return(length); }
internal TdsValueSetter(TdsParserStateObject stateObj, SmiMetaData md) { this._stateObj = stateObj; this._metaData = md; this._isPlp = MetaDataUtilsSmi.IsPlpFormat(md); this._plpUnknownSent = false; this._encoder = null; }
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 }
// valid for character types: Char, VarChar, Text, NChar, NVarChar, NText internal void SetString(string value, int offset, int length) { Debug.Assert( SmiXetterAccessMap.IsSetterAccessValid(_metaData, SmiXetterTypeCode.XetString)); // ANSI types must convert to byte[] because that's the tool we have. if (MetaDataUtilsSmi.IsAnsiType(_metaData.SqlDbType)) { byte[] bytes; // Optimize for common case of writing entire string if (offset == 0 && value.Length <= length) { bytes = _stateObj.Parser._defaultEncoding.GetBytes(value); } else { char[] chars = value.ToCharArray(offset, length); bytes = _stateObj.Parser._defaultEncoding.GetBytes(chars); } SetBytes(0, bytes, 0, bytes.Length); SetBytesLength(bytes.Length); } else if (SqlDbType.Variant == _metaData.SqlDbType) { Debug.Assert(null != _variantType && SqlDbType.NVarChar == _variantType.SqlDbType, "Invalid variant type"); SqlCollation collation = new SqlCollation(); collation.LCID = checked ((int)_variantType.LocaleId); collation.SqlCompareOptions = _variantType.CompareOptions; if (length * ADP.CharSize > TdsEnums.TYPE_SIZE_LIMIT) { // send as varchar for length greater than 4000 byte[] bytes; // Optimize for common case of writing entire string if (offset == 0 && value.Length <= length) { bytes = _stateObj.Parser._defaultEncoding.GetBytes(value); } else { bytes = _stateObj.Parser._defaultEncoding.GetBytes(value.ToCharArray(offset, length)); } _stateObj.Parser.WriteSqlVariantHeader(9 + bytes.Length, TdsEnums.SQLBIGVARCHAR, 7, _stateObj); _stateObj.Parser.WriteUnsignedInt(collation.info, _stateObj); // propbytes: collation.Info _stateObj.WriteByte(collation.sortId); // propbytes: collation.SortId _stateObj.Parser.WriteShort(bytes.Length, _stateObj); // propbyte: varlen _stateObj.WriteByteArray(bytes, bytes.Length, 0); } else { _stateObj.Parser.WriteSqlVariantHeader(9 + length * ADP.CharSize, TdsEnums.SQLNVARCHAR, 7, _stateObj); _stateObj.Parser.WriteUnsignedInt(collation.info, _stateObj); // propbytes: collation.Info _stateObj.WriteByte(collation.sortId); // propbytes: collation.SortId _stateObj.Parser.WriteShort(length * ADP.CharSize, _stateObj); // propbyte: varlen _stateObj.Parser.WriteString(value, length, offset, _stateObj); } _variantType = null; } else if (_isPlp) { // Send the string as a complete PLP chunk. _stateObj.Parser.WriteLong(length * ADP.CharSize, _stateObj); // PLP total length _stateObj.Parser.WriteInt(length * ADP.CharSize, _stateObj); // Chunk length _stateObj.Parser.WriteString(value, length, offset, _stateObj); // Data if (length != 0) { _stateObj.Parser.WriteInt(TdsEnums.SQL_PLP_CHUNK_TERMINATOR, _stateObj); // Terminator } } else { _stateObj.Parser.WriteShort(length * ADP.CharSize, _stateObj); _stateObj.Parser.WriteString(value, length, offset, _stateObj); } }
internal void SetString(string value, int offset, int length) { if (MetaDataUtilsSmi.IsAnsiType(this._metaData.SqlDbType)) { byte[] bytes; if ((offset == 0) && (value.Length <= length)) { bytes = this._stateObj.Parser._defaultEncoding.GetBytes(value); } else { char[] chars = value.ToCharArray(offset, length); bytes = this._stateObj.Parser._defaultEncoding.GetBytes(chars); } this.SetBytes(0L, bytes, 0, bytes.Length); this.SetBytesLength((long)bytes.Length); } else if (SqlDbType.Variant == this._metaData.SqlDbType) { SqlCollation collation = new SqlCollation { LCID = (int)this._variantType.LocaleId, SqlCompareOptions = this._variantType.CompareOptions }; if ((length * ADP.CharSize) > 0x1f40) { byte[] buffer; if ((offset == 0) && (value.Length <= length)) { buffer = this._stateObj.Parser._defaultEncoding.GetBytes(value); } else { buffer = this._stateObj.Parser._defaultEncoding.GetBytes(value.ToCharArray(offset, length)); } this._stateObj.Parser.WriteSqlVariantHeader(9 + buffer.Length, 0xa7, 7, this._stateObj); this._stateObj.Parser.WriteUnsignedInt(collation.info, this._stateObj); this._stateObj.Parser.WriteByte(collation.sortId, this._stateObj); this._stateObj.Parser.WriteShort(buffer.Length, this._stateObj); this._stateObj.Parser.WriteByteArray(buffer, buffer.Length, 0, this._stateObj); } else { this._stateObj.Parser.WriteSqlVariantHeader(9 + (length * ADP.CharSize), 0xe7, 7, this._stateObj); this._stateObj.Parser.WriteUnsignedInt(collation.info, this._stateObj); this._stateObj.Parser.WriteByte(collation.sortId, this._stateObj); this._stateObj.Parser.WriteShort(length * ADP.CharSize, this._stateObj); this._stateObj.Parser.WriteString(value, length, offset, this._stateObj); } this._variantType = null; } else if (this._isPlp) { this._stateObj.Parser.WriteLong((long)(length * ADP.CharSize), this._stateObj); this._stateObj.Parser.WriteInt(length * ADP.CharSize, this._stateObj); this._stateObj.Parser.WriteString(value, length, offset, this._stateObj); if (length != 0) { this._stateObj.Parser.WriteInt(0, this._stateObj); } } else { this._stateObj.Parser.WriteShort(length * ADP.CharSize, this._stateObj); this._stateObj.Parser.WriteString(value, length, offset, this._stateObj); } }