in src/main/java/com/microsoft/sqlserver/jdbc/dtv.java [3914:4132]
private Object readSqlVariant(int intbaseType, int cbPropsActual, int valueLength, TDSReader tdsReader,
SSType baseSSType, TypeInfo typeInfo, JDBCType jdbcType, InputStreamGetterArgs streamGetterArgs,
Calendar cal) throws SQLServerException {
Object convertedValue = null;
int lengthConsumed = 2 + cbPropsActual; // We have already read 2bytes for baseType earlier.
int expectedValueLength = valueLength - lengthConsumed;
SQLCollation collation = null;
int precision;
int scale;
int maxLength;
TDSType baseType = TDSType.valueOf(intbaseType);
switch (baseType) {
case INT8:
convertedValue = DDC.convertLongToObject(tdsReader.readLong(), jdbcType, baseSSType,
streamGetterArgs.streamType);
break;
case INT4:
convertedValue = DDC.convertIntegerToObject(tdsReader.readInt(), valueLength, jdbcType,
streamGetterArgs.streamType);
break;
case INT2:
convertedValue = DDC.convertIntegerToObject(tdsReader.readShort(), valueLength, jdbcType,
streamGetterArgs.streamType);
break;
case INT1:
convertedValue = DDC.convertIntegerToObject(tdsReader.readUnsignedByte(), valueLength, jdbcType,
streamGetterArgs.streamType);
break;
case DECIMALN:
case NUMERICN:
if (cbPropsActual != sqlVariantProbBytes.DECIMALN.getIntValue()) { // Numeric and decimal have the same
// probbytes value
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidProbbytes"));
throw new SQLServerException(form.format(new Object[] {baseType}), null, 0, null);
}
precision = tdsReader.readUnsignedByte();
scale = tdsReader.readUnsignedByte();
typeInfo.setScale(scale); // typeInfo needs to be updated. typeInfo is usually set when reading
// columnMetaData, but for sql_variant
// type the actual columnMetaData is is set when reading the data rows.
internalVariant.setPrecision(precision);
internalVariant.setScale(scale);
convertedValue = tdsReader.readDecimal(expectedValueLength, typeInfo, jdbcType,
streamGetterArgs.streamType);
break;
case FLOAT4:
convertedValue = tdsReader.readReal(expectedValueLength, jdbcType, streamGetterArgs.streamType);
break;
case FLOAT8:
convertedValue = tdsReader.readFloat(expectedValueLength, jdbcType, streamGetterArgs.streamType);
break;
case MONEY4:
precision = Long.toString(Long.MAX_VALUE).length();
typeInfo.setPrecision(precision);
scale = 4;
typeInfo.setDisplaySize(("-" + "." + Integer.toString(Integer.MAX_VALUE)).length());
typeInfo.setScale(scale);
internalVariant.setPrecision(precision);
internalVariant.setScale(scale);
convertedValue = tdsReader.readMoney(expectedValueLength, jdbcType, streamGetterArgs.streamType);
break;
case MONEY8:
precision = Long.toString(Long.MAX_VALUE).length();
scale = 4;
typeInfo.setPrecision(precision);
typeInfo.setDisplaySize(("-" + "." + Integer.toString(Integer.MAX_VALUE)).length());
typeInfo.setScale(scale);
internalVariant.setPrecision(precision);
internalVariant.setScale(scale);
convertedValue = tdsReader.readMoney(expectedValueLength, jdbcType, streamGetterArgs.streamType);
break;
case BIT1:
case BITN:
convertedValue = DDC.convertIntegerToObject(tdsReader.readUnsignedByte(), expectedValueLength,
jdbcType, streamGetterArgs.streamType);
break;
case BIGVARCHAR:
case BIGCHAR:
if (cbPropsActual != sqlVariantProbBytes.BIGCHAR.getIntValue()) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidProbbytes"));
throw new SQLServerException(form.format(new Object[] {baseType}), null, 0, null);
}
collation = tdsReader.readCollation();
typeInfo.setSQLCollation(collation);
maxLength = tdsReader.readUnsignedShort();
if (maxLength > DataTypes.SHORT_VARTYPE_MAX_BYTES)
tdsReader.throwInvalidTDS();
typeInfo.setDisplaySize(maxLength);
typeInfo.setPrecision(maxLength);
internalVariant.setPrecision(maxLength);
internalVariant.setCollation(collation);
typeInfo.setCharset(collation.getCharset());
convertedValue = DDC.convertStreamToObject(
new SimpleInputStream(tdsReader, expectedValueLength, streamGetterArgs, this), typeInfo,
jdbcType, streamGetterArgs);
break;
case NCHAR:
case NVARCHAR:
if (cbPropsActual != sqlVariantProbBytes.NCHAR.getIntValue()) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidProbbytes"));
throw new SQLServerException(form.format(new Object[] {baseType}), null, 0, null);
}
collation = tdsReader.readCollation();
typeInfo.setSQLCollation(collation);
maxLength = tdsReader.readUnsignedShort();
if (maxLength > DataTypes.SHORT_VARTYPE_MAX_BYTES || 0 != maxLength % 2)
tdsReader.throwInvalidTDS();
typeInfo.setDisplaySize(maxLength / 2);
typeInfo.setPrecision(maxLength / 2);
internalVariant.setPrecision(maxLength / 2);
internalVariant.setCollation(collation);
typeInfo.setCharset(Encoding.UNICODE.charset());
convertedValue = DDC.convertStreamToObject(
new SimpleInputStream(tdsReader, expectedValueLength, streamGetterArgs, this), typeInfo,
jdbcType, streamGetterArgs);
break;
case DATETIME8:
jdbcType = JDBCType.DATETIME;
convertedValue = tdsReader.readDateTime(expectedValueLength, cal, jdbcType,
streamGetterArgs.streamType);
break;
case DATETIME4:
jdbcType = JDBCType.SMALLDATETIME;
convertedValue = tdsReader.readDateTime(expectedValueLength, cal, jdbcType,
streamGetterArgs.streamType);
break;
case DATEN:
jdbcType = JDBCType.DATE;
convertedValue = tdsReader.readDate(expectedValueLength, cal, jdbcType);
break;
case TIMEN:
if (cbPropsActual != sqlVariantProbBytes.TIMEN.getIntValue()) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidProbbytes"));
throw new SQLServerException(form.format(new Object[] {baseType}), null, 0, null);
}
if (internalVariant.isBaseTypeTimeValue()) {
jdbcType = JDBCType.TIMESTAMP;
}
scale = tdsReader.readUnsignedByte();
typeInfo.setScale(scale);
internalVariant.setScale(scale);
convertedValue = tdsReader.readTime(expectedValueLength, typeInfo, cal, jdbcType);
break;
case DATETIME2N:
if (cbPropsActual != sqlVariantProbBytes.DATETIME2N.getIntValue()) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidProbbytes"));
throw new SQLServerException(form.format(new Object[] {baseType}), null, 0, null);
}
jdbcType = JDBCType.TIMESTAMP;
scale = tdsReader.readUnsignedByte();
typeInfo.setScale(scale);
internalVariant.setScale(scale);
convertedValue = tdsReader.readDateTime2(expectedValueLength, typeInfo, cal, jdbcType);
break;
case DATETIMEOFFSETN:
jdbcType = JDBCType.DATETIMEOFFSET;
scale = tdsReader.readUnsignedByte();
typeInfo.setScale(scale);
internalVariant.setScale(scale);
convertedValue = tdsReader.readDateTimeOffset(expectedValueLength, typeInfo, jdbcType);
break;
case BIGBINARY: // e.g binary20, binary 512, binary 8000 -> reads as bigbinary
case BIGVARBINARY:
if (cbPropsActual != sqlVariantProbBytes.BIGBINARY.getIntValue()) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidProbbytes"));
throw new SQLServerException(form.format(new Object[] {baseType}), null, 0, null);
}
if (TDSType.BIGBINARY == baseType)
jdbcType = JDBCType.BINARY;// LONGVARCHAR;
else if (TDSType.BIGVARBINARY == baseType)
jdbcType = JDBCType.VARBINARY;
maxLength = tdsReader.readUnsignedShort();
internalVariant.setMaxLength(maxLength);
if (maxLength > DataTypes.SHORT_VARTYPE_MAX_BYTES)
tdsReader.throwInvalidTDS();
typeInfo.setDisplaySize(2 * maxLength);
typeInfo.setPrecision(maxLength);
convertedValue = DDC.convertStreamToObject(
new SimpleInputStream(tdsReader, expectedValueLength, streamGetterArgs, this), typeInfo,
jdbcType, streamGetterArgs);
break;
case GUID:
jdbcType = JDBCType.GUID;
internalVariant.setBaseType(intbaseType);
internalVariant.setBaseJDBCType(jdbcType);
typeInfo.setDisplaySize("NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN".length());
lengthConsumed = 2 + cbPropsActual;
convertedValue = tdsReader.readGUID(expectedValueLength, jdbcType, streamGetterArgs.streamType);
break;
// Unsupported TdsType should throw error message
default: {
MessageFormat form = new MessageFormat(
SQLServerException.getErrString("R_invalidDataTypeSupportForSQLVariant"));
throw new SQLServerException(form.format(new Object[] {baseType}), null, 0, null);
}
}
return convertedValue;
}