builder.setType(protoRep);
valueBuilder.setType(Common.Rep.STRING).setStringValue((String) obj); break; case GET_DEFAULT_TRANSACTION_ISOLATION: valueBuilder.setType(Common.Rep.INTEGER).setNumberValue(((Integer) obj).longValue()); break; default: if (obj instanceof Integer) { valueBuilder.setType(Common.Rep.INTEGER).setNumberValue((Integer) obj); } else { String value; value = obj.toString(); valueBuilder.setType(Common.Rep.STRING).setStringValue(value);
private static void writeToProtoWithType(Common.TypedValue.Builder builder, Object o, Common.Rep type) { builder.setType(type);
valueBuilder.setType(Common.Rep.STRING).setStringValue((String) obj); break; case GET_DEFAULT_TRANSACTION_ISOLATION: valueBuilder.setType(Common.Rep.INTEGER).setNumberValue(((Integer) obj).longValue()); break; default: if (obj instanceof Integer) { valueBuilder.setType(Common.Rep.INTEGER).setNumberValue((Integer) obj); } else { String value; value = obj.toString(); valueBuilder.setType(Common.Rep.STRING).setStringValue(value);
valueBuilder.setType(Common.Rep.BYTE).setNumberValue(((Byte) element).longValue()); } else if (element instanceof Short) { valueBuilder.setType(Common.Rep.SHORT).setNumberValue(((Short) element).longValue()); } else if (element instanceof Integer) { valueBuilder.setType(Common.Rep.INTEGER) .setNumberValue(((Integer) element).longValue()); } else if (element instanceof Long) { valueBuilder.setType(Common.Rep.LONG).setNumberValue((Long) element); } else if (element instanceof Double) { valueBuilder.setType(Common.Rep.DOUBLE).setDoubleValue((Double) element); } else if (element instanceof Float) { valueBuilder.setType(Common.Rep.FLOAT).setNumberValue(((Float) element).longValue()); } else if (element instanceof BigDecimal) { valueBuilder.setType(Common.Rep.NUMBER) .setDoubleValue(((BigDecimal) element).doubleValue()); valueBuilder.setType(Common.Rep.STRING) .setStringValue((String) element); } else if (element instanceof Character) { valueBuilder.setType(Common.Rep.CHARACTER) .setStringValue(((Character) element).toString()); valueBuilder.setType(Common.Rep.BYTE_STRING) .setBytesValues(ByteString.copyFrom((byte[]) element)); valueBuilder.setType(Common.Rep.BOOLEAN).setBoolValue((boolean) element); } else if (null == element) { valueBuilder.setType(Common.Rep.NULL);
/** * Creates a protocol buffer equivalent object for <code>this</code>. * @return A protobuf TypedValue equivalent for <code>this</code> */ public Common.TypedValue toProto() { final Common.TypedValue.Builder builder = Common.TypedValue.newBuilder(); // This isn't a static method, therefore we have a non-null TypedValue. Thus, this message // cannot be implicitly null builder.setImplicitlyNull(false); Common.Rep protoRep = type.toProto(); // Protobuf has an explicit BIG_DECIMAL representation enum value. if (Common.Rep.NUMBER == protoRep && value instanceof BigDecimal) { protoRep = Common.Rep.BIG_DECIMAL; } else if (Common.Rep.ARRAY == protoRep) { // This column value is an Array (many TypedValue's) builder.setType(Common.Rep.ARRAY); // Get the array component's type Common.Rep protoComponentRep = componentType.toProto(); // Set the array's component on the message builder.setComponentType(protoComponentRep); // Serialize that array into the builder @SuppressWarnings("unchecked") List<Object> list = (List<Object>) value; return serializeArray(list, builder, protoComponentRep); } // Serialize the type into the protobuf writeToProtoWithType(builder, value, protoRep); return builder.build(); }
Common.TypedValue serializeArray(List<Object> list, Common.TypedValue.Builder builder, Common.Rep protoArrayComponentRep) { for (Object element : list) { if (element instanceof List) { // We have a list of lists: recursively build up the protobuf @SuppressWarnings("unchecked") List<Object> subList = (List<Object>) element; Common.TypedValue.Builder subListBuilder = Common.TypedValue.newBuilder(); // This is "technically" an array, but we just persist the underlying component type subListBuilder.setType(protoArrayComponentRep); Common.TypedValue protoSubList = serializeArray(subList, subListBuilder, protoArrayComponentRep); builder.addArrayValue(protoSubList); } else { // We have a list of "scalars", just serialize the value Common.TypedValue.Builder elementBuilder = Common.TypedValue.newBuilder(); if (null == element) { writeToProtoWithType(elementBuilder, null, Common.Rep.NULL); } else { writeToProtoWithType(elementBuilder, element, protoArrayComponentRep); } builder.addArrayValue(elementBuilder.build()); } } return builder.build(); }
Common.TypedValue serializeArray(List<Object> list, Common.TypedValue.Builder builder, Common.Rep protoArrayComponentRep) { for (Object element : list) { if (element instanceof List) { // We have a list of lists: recursively build up the protobuf @SuppressWarnings("unchecked") List<Object> subList = (List<Object>) element; Common.TypedValue.Builder subListBuilder = Common.TypedValue.newBuilder(); // This is "technically" an array, but we just persist the underlying component type subListBuilder.setType(protoArrayComponentRep); Common.TypedValue protoSubList = serializeArray(subList, subListBuilder, protoArrayComponentRep); builder.addArrayValue(protoSubList); } else { // We have a list of "scalars", just serialize the value Common.TypedValue.Builder elementBuilder = Common.TypedValue.newBuilder(); if (null == element) { writeToProtoWithType(elementBuilder, null, Common.Rep.NULL); } else { writeToProtoWithType(elementBuilder, element, protoArrayComponentRep); } builder.addArrayValue(elementBuilder.build()); } } return builder.build(); }
/** * Creates a protocol buffer equivalent object for <code>this</code>. * @return A protobuf TypedValue equivalent for <code>this</code> */ public Common.TypedValue toProto() { final Common.TypedValue.Builder builder = Common.TypedValue.newBuilder(); // This isn't a static method, therefore we have a non-null TypedValue. Thus, this message // cannot be implicitly null builder.setImplicitlyNull(false); Common.Rep protoRep = type.toProto(); // Protobuf has an explicit BIG_DECIMAL representation enum value. if (Common.Rep.NUMBER == protoRep && value instanceof BigDecimal) { protoRep = Common.Rep.BIG_DECIMAL; } else if (Common.Rep.ARRAY == protoRep) { // This column value is an Array (many TypedValue's) builder.setType(Common.Rep.ARRAY); // Get the array component's type Common.Rep protoComponentRep = componentType.toProto(); // Set the array's component on the message builder.setComponentType(protoComponentRep); // Serialize that array into the builder @SuppressWarnings("unchecked") List<Object> list = (List<Object>) value; return serializeArray(list, builder, protoComponentRep); } // Serialize the type into the protobuf writeToProtoWithType(builder, value, protoRep); return builder.build(); }
@Test public void testLegacyBase64StringEncodingForBytes() { // CALCITE-1103 CALCITE-1209 We observed that binary data was being // serialized as base-64 encoded strings instead of the native binary // data type in protobufs. We need to still handle older clients sending // data in this form. final byte[] bytes = "asdf".getBytes(UTF_8); final String base64Str = Base64.encodeBytes(bytes); Common.TypedValue.Builder builder = Common.TypedValue.newBuilder(); builder.setStringValue(base64Str); builder.setType(Common.Rep.BYTE_STRING); Common.TypedValue protoTv = builder.build(); TypedValue tv = TypedValue.fromProto(protoTv); assertEquals(Rep.BYTE_STRING, tv.type); assertEquals(base64Str, tv.value); }
@Test public void testBase64() { byte[] bytes = "qwertyasdf".getBytes(UTF_8); // Plain bytes get put into protobuf for simplicitly Common.TypedValue proto = Common.TypedValue.newBuilder().setBytesValue( com.google.protobuf.ByteString.copyFrom(bytes)) .setType(Common.Rep.BYTE_STRING).build(); // But we should get back a b64-string to make sure TypedValue doesn't get confused. Object deserializedObj = TypedValue.getSerialFromProto(proto); assertThat(deserializedObj, is(instanceOf(String.class))); assertEquals(new ByteString(bytes).toBase64String(), (String) deserializedObj); // But we should get a non-b64 byte array as the JDBC representation deserializedObj = TypedValue.protoToJdbc(proto, DateTimeUtils.calendar()); assertThat(deserializedObj, is(instanceOf(byte[].class))); assertArrayEquals(bytes, (byte[]) deserializedObj); }
@Test public void testLegacyBase64StringEncodingForBytes() { // CALCITE-1103 CALCITE-1209 We observed that binary data was being // serialized as base-64 encoded strings instead of the native binary // data type in protobufs. We need to still handle older clients sending // data in this form. final byte[] bytes = "asdf".getBytes(UTF_8); final String base64Str = Base64.encodeBytes(bytes); Common.TypedValue.Builder builder = Common.TypedValue.newBuilder(); builder.setStringValue(base64Str); builder.setType(Common.Rep.BYTE_STRING); Common.TypedValue protoTv = builder.build(); TypedValue tv = TypedValue.fromProto(protoTv); assertEquals(Rep.BYTE_STRING, tv.type); assertEquals(base64Str, tv.value); }
@Test public void testBase64() { byte[] bytes = "qwertyasdf".getBytes(UTF_8); // Plain bytes get put into protobuf for simplicitly Common.TypedValue proto = Common.TypedValue.newBuilder().setBytesValue( com.google.protobuf.ByteString.copyFrom(bytes)) .setType(Common.Rep.BYTE_STRING).build(); // But we should get back a b64-string to make sure TypedValue doesn't get confused. Object deserializedObj = TypedValue.getSerialFromProto(proto); assertThat(deserializedObj, is(instanceOf(String.class))); assertEquals(new ByteString(bytes).toBase64String(), (String) deserializedObj); // But we should get a non-b64 byte array as the JDBC representation deserializedObj = TypedValue.protoToJdbc(proto, DateTimeUtils.calendar()); assertThat(deserializedObj, is(instanceOf(byte[].class))); assertArrayEquals(bytes, (byte[]) deserializedObj); }
@Test public void testLegacyDecimalParsing() { final BigDecimal decimal = new BigDecimal("123451234512345"); final Calendar calendar = DateTimeUtils.calendar(); // CALCITE-1103 Decimals were (incorrectly) getting serialized as normal "numbers" which // caused them to use the numberValue field. TypedValue should still be able to handle // values like this (but large values will be truncated and return bad values). Common.TypedValue oldProtoStyle = Common.TypedValue.newBuilder().setType(Common.Rep.NUMBER) .setNumberValue(decimal.longValue()).build(); TypedValue fromProtoTv = TypedValue.fromProto(oldProtoStyle); Object o = fromProtoTv.toJdbc(calendar); assertEquals(decimal, o); }
@Test public void testLegacyDecimalParsing() { final BigDecimal decimal = new BigDecimal("123451234512345"); final Calendar calendar = DateTimeUtils.calendar(); // CALCITE-1103 Decimals were (incorrectly) getting serialized as normal "numbers" which // caused them to use the numberValue field. TypedValue should still be able to handle // values like this (but large values will be truncated and return bad values). Common.TypedValue oldProtoStyle = Common.TypedValue.newBuilder().setType(Common.Rep.NUMBER) .setNumberValue(decimal.longValue()).build(); TypedValue fromProtoTv = TypedValue.fromProto(oldProtoStyle); Object o = fromProtoTv.toJdbc(calendar); assertEquals(decimal, o); }