private Task WriteUnterminatedValue(object value, MetaType type, byte scale, int actualLength, int encodingByteSize, int offset, TdsParserStateObject stateObj, int paramSize, bool isDataFeed)
{
Debug.Assert((null != value) && (DBNull.Value != value), "unexpected missing or empty object");
// parameters are always sent over as BIG or N types
switch (type.NullableType)
{
case TdsEnums.SQLFLTN:
if (type.FixedLength == 4)
WriteFloat((Single)value, stateObj);
else
{
Debug.Assert(type.FixedLength == 8, "Invalid length for SqlDouble type!");
WriteDouble((Double)value, stateObj);
}
break;
case TdsEnums.SQLBIGBINARY:
case TdsEnums.SQLBIGVARBINARY:
case TdsEnums.SQLIMAGE:
case TdsEnums.SQLUDT:
{
// An array should be in the object
Debug.Assert(isDataFeed || value is byte[], "Value should be an array of bytes");
Debug.Assert(!isDataFeed || value is StreamDataFeed, "Value should be a stream");
if (isDataFeed)
{
Debug.Assert(type.IsPlp, "Stream assigned to non-PLP was not converted!");
return NullIfCompletedWriteTask(WriteStreamFeed((StreamDataFeed)value, stateObj, paramSize));
}
else
{
if (type.IsPlp)
{
WriteInt(actualLength, stateObj); // chunk length
}
return stateObj.WriteByteArray((byte[])value, actualLength, offset, canAccumulate: false);
}
}
case TdsEnums.SQLUNIQUEID:
{
System.Guid guid = (System.Guid)value;
byte[] b = guid.ToByteArray();
Debug.Assert((actualLength == b.Length) && (actualLength == 16), "Invalid length for guid type in com+ object");
stateObj.WriteByteArray(b, actualLength, 0);
break;
}
case TdsEnums.SQLBITN:
{
Debug.Assert(type.FixedLength == 1, "Invalid length for SqlBoolean type");
if ((bool)value == true)
stateObj.WriteByte(1);
else
stateObj.WriteByte(0);
break;
}
case TdsEnums.SQLINTN:
if (type.FixedLength == 1)
stateObj.WriteByte((byte)value);
else if (type.FixedLength == 2)
WriteShort((short)value, stateObj);
else if (type.FixedLength == 4)
WriteInt((int)value, stateObj);
else
{
Debug.Assert(type.FixedLength == 8, "invalid length for SqlIntN type: " + type.FixedLength.ToString(CultureInfo.InvariantCulture));
WriteLong((long)value, stateObj);
}
break;
case TdsEnums.SQLBIGCHAR:
case TdsEnums.SQLBIGVARCHAR:
case TdsEnums.SQLTEXT:
{
Debug.Assert(!isDataFeed || (value is TextDataFeed || value is XmlDataFeed), "Value must be a TextReader or XmlReader");
Debug.Assert(isDataFeed || (value is string || value is byte[]), "Value is a byte array or string");
if (isDataFeed)
{
Debug.Assert(type.IsPlp, "Stream assigned to non-PLP was not converted!");
TextDataFeed tdf = value as TextDataFeed;
if (tdf == null)
{
return NullIfCompletedWriteTask(WriteXmlFeed((XmlDataFeed)value, stateObj, needBom: true, encoding: _defaultEncoding, size: paramSize));
}
else
{
return NullIfCompletedWriteTask(WriteTextFeed(tdf, _defaultEncoding, false, stateObj, paramSize));
}
}
else
{
if (type.IsPlp)
{
WriteInt(encodingByteSize, stateObj); // chunk length
}
if (value is byte[])
{ // If LazyMat non-filled blob, send cookie rather than value
return stateObj.WriteByteArray((byte[])value, actualLength, 0, canAccumulate: false);
}
else
{
return WriteEncodingChar((string)value, actualLength, offset, _defaultEncoding, stateObj, canAccumulate: false);
}
}
}
case TdsEnums.SQLNCHAR:
case TdsEnums.SQLNVARCHAR:
case TdsEnums.SQLNTEXT:
case TdsEnums.SQLXMLTYPE:
{
Debug.Assert(!isDataFeed || (value is TextDataFeed || value is XmlDataFeed), "Value must be a TextReader or XmlReader");
Debug.Assert(isDataFeed || (value is string || value is byte[]), "Value is a byte array or string");
if (isDataFeed)
{
Debug.Assert(type.IsPlp, "Stream assigned to non-PLP was not converted!");
TextDataFeed tdf = value as TextDataFeed;
if (tdf == null)
{
return NullIfCompletedWriteTask(WriteXmlFeed((XmlDataFeed)value, stateObj, IsBOMNeeded(type, value), Encoding.Unicode, paramSize));
}
else
{
return NullIfCompletedWriteTask(WriteTextFeed(tdf, null, IsBOMNeeded(type, value), stateObj, paramSize));
}
}
else
{
if (type.IsPlp)
{
if (IsBOMNeeded(type, value))
{
WriteInt(actualLength + 2, stateObj); // chunk length
WriteShort(TdsEnums.XMLUNICODEBOM, stateObj);
}
else
{
WriteInt(actualLength, stateObj); // chunk length
}
}
if (value is byte[])
{ // If LazyMat non-filled blob, send cookie rather than value
return stateObj.WriteByteArray((byte[])value, actualLength, 0, canAccumulate: false);
}
else
{
// convert to cchars instead of cbytes
actualLength >>= 1;
return WriteString((string)value, actualLength, offset, stateObj, canAccumulate: false);
}
}
}
case TdsEnums.SQLNUMERICN:
Debug.Assert(type.FixedLength <= 17, "Decimal length cannot be greater than 17 bytes");
WriteDecimal((Decimal)value, stateObj);
break;
case TdsEnums.SQLDATETIMN:
Debug.Assert(type.FixedLength <= 0xff, "Invalid Fixed Length");
TdsDateTime dt = MetaType.FromDateTime((DateTime)value, (byte)type.FixedLength);
if (type.FixedLength == 4)
{
if (0 > dt.days || dt.days > ushort.MaxValue)
throw SQL.SmallDateTimeOverflow(MetaType.ToDateTime(dt.days, dt.time, 4).ToString(CultureInfo.InvariantCulture));
WriteShort(dt.days, stateObj);
WriteShort(dt.time, stateObj);
}
else
{
WriteInt(dt.days, stateObj);
WriteInt(dt.time, stateObj);
}
break;
case TdsEnums.SQLMONEYN:
{
WriteCurrency((Decimal)value, type.FixedLength, stateObj);
break;
}
case TdsEnums.SQLDATE:
{
WriteDate((DateTime)value, stateObj);
break;
}
case TdsEnums.SQLTIME:
if (scale > TdsEnums.DEFAULT_VARTIME_SCALE)
{
throw SQL.TimeScaleValueOutOfRange(scale);
}
WriteTime((TimeSpan)value, scale, actualLength, stateObj);
break;
case TdsEnums.SQLDATETIME2:
if (scale > TdsEnums.DEFAULT_VARTIME_SCALE)
{
throw SQL.TimeScaleValueOutOfRange(scale);
}
WriteDateTime2((DateTime)value, scale, actualLength, stateObj);
break;
case TdsEnums.SQLDATETIMEOFFSET:
WriteDateTimeOffset((DateTimeOffset)value, scale, actualLength, stateObj);
break;
default:
Debug.Assert(false, "Unknown TdsType!" + type.NullableType.ToString("x2", (IFormatProvider)null));
break;
} // switch
// return point for accumulated writes, note: non-accumulated writes returned from their case statements
return null;
// Debug.WriteLine("value: " + value.ToString(CultureInfo.InvariantCulture));
}