private Object readSqlVariant()

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;
    }