in core/src/main/java/org/apache/calcite/avatica/remote/TypedValue.java [676:760]
public static Object getSerialFromProto(Common.TypedValue protoValue) {
// Deserialize the value again
switch (protoValue.getType()) {
case BOOLEAN:
case PRIMITIVE_BOOLEAN:
return protoValue.getBoolValue();
case BYTE_STRING:
if (protoValue.hasField(STRING_DESCRIPTOR) && !protoValue.hasField(BYTES_DESCRIPTOR)) {
// Prior to CALCITE-1103, clients would send b64 strings for bytes instead of using the
// native byte format. The value we need to provide as the local format for TypedValue
// is directly accessible via the Protobuf representation. Both fields are sent by the
// server to support older clients, so only parse the string value when it is alone.
return protoValue.getStringValue();
}
// TypedValue is still going to expect a b64string for BYTE_STRING even though we sent it
// across the wire natively as bytes. Return it as b64.
return (new ByteString(protoValue.getBytesValue().toByteArray())).toBase64String();
case STRING:
return protoValue.getStringValue();
case PRIMITIVE_CHAR:
case CHARACTER:
return protoValue.getStringValue().charAt(0);
case BYTE:
case PRIMITIVE_BYTE:
return Long.valueOf(protoValue.getNumberValue()).byteValue();
case DOUBLE:
case PRIMITIVE_DOUBLE:
return protoValue.getDoubleValue();
case FLOAT:
case PRIMITIVE_FLOAT:
return Float.intBitsToFloat((int) protoValue.getNumberValue());
case INTEGER:
case PRIMITIVE_INT:
return Long.valueOf(protoValue.getNumberValue()).intValue();
case PRIMITIVE_SHORT:
case SHORT:
return Long.valueOf(protoValue.getNumberValue()).shortValue();
case LONG:
case PRIMITIVE_LONG:
return Long.valueOf(protoValue.getNumberValue());
case JAVA_SQL_DATE:
case JAVA_SQL_TIME:
return Long.valueOf(protoValue.getNumberValue()).intValue();
case JAVA_SQL_TIMESTAMP:
case JAVA_UTIL_DATE:
return protoValue.getNumberValue();
case BIG_INTEGER:
return new BigInteger(protoValue.getBytesValue().toByteArray());
case BIG_DECIMAL:
// CALCITE-1103 shifts BigDecimals to be serialized as strings.
if (protoValue.hasField(NUMBER_DESCRIPTOR)) {
// This is the old (broken) style.
BigInteger bigInt = new BigInteger(protoValue.getBytesValue().toByteArray());
return new BigDecimal(bigInt, (int) protoValue.getNumberValue());
}
return new BigDecimal(protoValue.getStringValueBytes().toStringUtf8());
case NUMBER:
return Long.valueOf(protoValue.getNumberValue());
case NULL:
return null;
case ARRAY:
final List<Common.TypedValue> protoList = protoValue.getArrayValueList();
final List<Object> list = new ArrayList<>(protoList.size());
for (Common.TypedValue protoElement : protoList) {
// Deserialize the TypedValue protobuf into the JDBC type
TypedValue listElement = TypedValue.fromProto(protoElement);
// Must preserve the TypedValue so serial/jdbc/local conversion can work as expected
list.add(listElement);
}
return list;
case OBJECT:
if (protoValue.getNull()) {
return null;
}
// Intentional fall through to RTE. If we sent an object over the wire, it could only
// possibly be null (at this point). Anything else has to be an error.
// fall through
case UNRECOGNIZED:
// Fail?
throw new RuntimeException("Unhandled type: " + protoValue.getType());
default:
// Fail?
throw new RuntimeException("Unknown type: " + protoValue.getType());
}
}