in src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataTable.java [157:308]
private void internalAddrow(JDBCType jdbcType, Object val, Object[] rowValues,
Map.Entry<Integer, SQLServerDataColumn> pair) throws SQLServerException {
int key = pair.getKey();
if (null != val) {
SQLServerDataColumn currentColumnMetadata = pair.getValue();
int nValueLen;
switch (jdbcType) {
case BIGINT:
rowValues[key] = (val instanceof Long) ? val : Long.parseLong(val.toString());
break;
case BIT:
if (val instanceof Boolean) {
rowValues[key] = val;
} else {
String valString = val.toString();
if ("0".equals(valString) || valString.equalsIgnoreCase(Boolean.FALSE.toString())) {
rowValues[key] = Boolean.FALSE;
} else if ("1".equals(valString) || valString.equalsIgnoreCase(Boolean.TRUE.toString())) {
rowValues[key] = Boolean.TRUE;
} else {
MessageFormat form = new MessageFormat(
SQLServerException.getErrString("R_TVPInvalidColumnValue"));
Object[] msgArgs = {jdbcType};
throw new SQLServerException(null, form.format(msgArgs), null, 0, false);
}
}
break;
case INTEGER:
rowValues[key] = (val instanceof Integer) ? val : Integer.parseInt(val.toString());
break;
case SMALLINT:
case TINYINT:
rowValues[key] = (val instanceof Short) ? val : Short.parseShort(val.toString());
break;
case DECIMAL:
case NUMERIC:
BigDecimal bd = null;
boolean isColumnMetadataUpdated = false;
bd = new BigDecimal(val.toString());
// BigDecimal#precision returns number of digits in the unscaled value.
// Say, for value 0.01, it returns 1 but the precision should be 3 for SQLServer
int precision = Util.getValueLengthBaseOnJavaType(bd, JavaType.of(bd), null, null, jdbcType);
if (bd.scale() > currentColumnMetadata.scale) {
currentColumnMetadata.scale = bd.scale();
isColumnMetadataUpdated = true;
}
if (precision > currentColumnMetadata.precision) {
currentColumnMetadata.precision = precision;
isColumnMetadataUpdated = true;
}
// precision equal: the maximum number of digits in integer part + the maximum scale
int numberOfDigitsIntegerPart = precision - bd.scale();
if (numberOfDigitsIntegerPart > currentColumnMetadata.numberOfDigitsIntegerPart) {
currentColumnMetadata.numberOfDigitsIntegerPart = numberOfDigitsIntegerPart;
isColumnMetadataUpdated = true;
}
if (isColumnMetadataUpdated) {
currentColumnMetadata.precision = currentColumnMetadata.scale
+ currentColumnMetadata.numberOfDigitsIntegerPart;
columnMetadata.put(pair.getKey(), currentColumnMetadata);
}
rowValues[key] = bd;
break;
case DOUBLE:
rowValues[key] = (val instanceof Double) ? val : Double.parseDouble(val.toString());
break;
case FLOAT:
case REAL:
rowValues[key] = (val instanceof Float) ? val : Float.parseFloat(val.toString());
break;
case TIMESTAMP_WITH_TIMEZONE:
case TIME_WITH_TIMEZONE:
case DATE:
case TIME:
case TIMESTAMP:
case DATETIMEOFFSET:
case DATETIME:
case SMALLDATETIME:
// Sending temporal types as string. Error from database is thrown if parsing fails
// no need to send precision for temporal types, string literal will never exceed
// DataTypes.SHORT_VARTYPE_MAX_BYTES
// java.sql.Date, java.sql.Time and java.sql.Timestamp are subclass of java.util.Date
if (val instanceof java.util.Date || val instanceof microsoft.sql.DateTimeOffset
|| val instanceof OffsetDateTime || val instanceof OffsetTime)
rowValues[key] = val.toString();
else
rowValues[key] = val;
break;
case BINARY:
case VARBINARY:
case LONGVARBINARY:
nValueLen = ((byte[]) val).length;
if (nValueLen > currentColumnMetadata.precision) {
currentColumnMetadata.precision = nValueLen;
columnMetadata.put(pair.getKey(), currentColumnMetadata);
}
rowValues[key] = val;
break;
case CHAR:
case VARCHAR:
case NCHAR:
case NVARCHAR:
case LONGVARCHAR:
case LONGNVARCHAR:
case SQLXML:
if (val instanceof UUID)
val = val.toString();
nValueLen = (2 * ((String) val).length());
if (nValueLen > currentColumnMetadata.precision) {
currentColumnMetadata.precision = nValueLen;
columnMetadata.put(pair.getKey(), currentColumnMetadata);
}
rowValues[key] = val;
break;
case SQL_VARIANT:
JDBCType internalJDBCType;
JavaType javaType = JavaType.of(val);
internalJDBCType = javaType.getJDBCType(SSType.UNKNOWN, jdbcType);
internalAddrow(internalJDBCType, val, rowValues, pair);
break;
default:
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_unsupportedDataTypeTVP"));
Object[] msgArgs = {jdbcType};
throw new SQLServerException(null, form.format(msgArgs), null, 0, false);
}
} else {
rowValues[key] = null;
if (jdbcType == JDBCType.SQL_VARIANT) {
throw new SQLServerException(SQLServerException.getErrString("R_invalidValueForTVPWithSQLVariant"),
null);
}
}
}