Skip to content

Commit bdc3827

Browse files
committed
new type enum for JDBC
1 parent cf55c5d commit bdc3827

File tree

8 files changed

+178
-52
lines changed

8 files changed

+178
-52
lines changed

fdb-relational-grpc/src/main/java/com/apple/foundationdb/relational/jdbc/RelationalArrayFacade.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@
2121
package com.apple.foundationdb.relational.jdbc;
2222

2323
import com.apple.foundationdb.relational.api.ArrayMetaData;
24+
import com.apple.foundationdb.relational.api.RelationalArrayMetaData;
2425
import com.apple.foundationdb.relational.api.SqlTypeNamesSupport;
2526
import com.apple.foundationdb.relational.api.RelationalArray;
2627
import com.apple.foundationdb.relational.api.RelationalArrayBuilder;
2728
import com.apple.foundationdb.relational.api.RelationalResultSet;
2829
import com.apple.foundationdb.relational.api.RelationalStruct;
2930
import com.apple.foundationdb.relational.api.exceptions.ErrorCode;
31+
import com.apple.foundationdb.relational.api.metadata.DataType;
3032
import com.apple.foundationdb.relational.jdbc.grpc.v1.ResultSet;
3133
import com.apple.foundationdb.relational.jdbc.grpc.v1.ResultSetMetadata;
3234
import com.apple.foundationdb.relational.jdbc.grpc.v1.column.Array;
@@ -35,14 +37,18 @@
3537
import com.apple.foundationdb.relational.jdbc.grpc.v1.column.ListColumn;
3638
import com.apple.foundationdb.relational.jdbc.grpc.v1.column.ListColumnMetadata;
3739
import com.apple.foundationdb.relational.jdbc.grpc.v1.column.Struct;
40+
import com.apple.foundationdb.relational.jdbc.grpc.v1.column.Type;
3841
import com.apple.foundationdb.relational.util.Assert;
3942
import com.apple.foundationdb.relational.util.PositionalIndex;
43+
import com.google.common.base.Suppliers;
4044

4145
import javax.annotation.Nonnull;
46+
import java.sql.DatabaseMetaData;
4247
import java.sql.SQLException;
4348
import java.sql.SQLFeatureNotSupportedException;
4449
import java.sql.Types;
4550
import java.util.UUID;
51+
import java.util.function.Supplier;
4652

4753
/**
4854
* Facade over grpc protobuf objects that offers a {@link RelationalArray} view.
@@ -57,6 +63,7 @@ class RelationalArrayFacade implements RelationalArray {
5763
* Package-private so protobuf is available to serializer (in same package).
5864
*/
5965
private final ColumnMetadata delegateMetadata;
66+
private final Supplier<DataType.ArrayType> type;
6067

6168
/**
6269
* Array data as protobuf.
@@ -67,9 +74,14 @@ class RelationalArrayFacade implements RelationalArray {
6774

6875
RelationalArrayFacade(@Nonnull ColumnMetadata delegateMetadata, Array array) {
6976
this.delegateMetadata = delegateMetadata;
77+
this.type = Suppliers.memoize(this::computeType);
7078
this.delegate = array;
7179
}
7280

81+
private DataType.ArrayType computeType() {
82+
return DataType.ArrayType.from(RelationalStructFacade.RelationalStructFacadeMetaData.getDataType(delegateMetadata.getType(), delegateMetadata, delegateMetadata.getNullable() == DatabaseMetaData.columnNullable));
83+
}
84+
7385
/**
7486
* Package-private so protobuf is available to serializer (in same package).
7587
* @return The backing protobuf used to keep Array data.
@@ -88,7 +100,7 @@ ColumnMetadata getDelegateMetadata() {
88100

89101
@Override
90102
public ArrayMetaData getMetaData() throws SQLException {
91-
throw new SQLFeatureNotSupportedException("get Metadata not supported in JDBC Relational Arrays");
103+
return RelationalArrayMetaData.of(type.get());
92104
}
93105

94106
@Override
@@ -254,7 +266,7 @@ public RelationalArrayBuilder addStruct(RelationalStruct struct) throws SQLExcep
254266

255267
private void initOrCheckMetadata(ListColumnMetadata innerMetadata) {
256268
if (metadata == null) {
257-
final var builder = ColumnMetadata.newBuilder().setName("ARRAY").setJavaSqlTypesCode(Types.STRUCT);
269+
final var builder = ColumnMetadata.newBuilder().setName("ARRAY").setJavaSqlTypesCode(Types.STRUCT).setType(Type.STRUCT);
258270
builder.setStructMetadata(innerMetadata);
259271
metadata = builder.build();
260272
} else {

fdb-relational-grpc/src/main/java/com/apple/foundationdb/relational/jdbc/RelationalStructFacade.java

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,32 @@
2626
import com.apple.foundationdb.relational.api.RelationalStruct;
2727
import com.apple.foundationdb.relational.api.RelationalStructBuilder;
2828
import com.apple.foundationdb.relational.api.exceptions.ErrorCode;
29+
import com.apple.foundationdb.relational.api.exceptions.RelationalException;
2930
import com.apple.foundationdb.relational.api.metadata.DataType;
3031
import com.apple.foundationdb.relational.jdbc.grpc.v1.column.Column;
3132
import com.apple.foundationdb.relational.jdbc.grpc.v1.column.ColumnMetadata;
3233
import com.apple.foundationdb.relational.jdbc.grpc.v1.column.ListColumn;
3334
import com.apple.foundationdb.relational.jdbc.grpc.v1.column.ListColumnMetadata;
3435
import com.apple.foundationdb.relational.jdbc.grpc.v1.column.Struct;
36+
import com.apple.foundationdb.relational.jdbc.grpc.v1.column.Type;
3537
import com.apple.foundationdb.relational.util.PositionalIndex;
3638

3739
import com.apple.foundationdb.relational.util.SpotBugsSuppressWarnings;
3840
import com.google.common.annotations.VisibleForTesting;
41+
import com.google.common.base.Suppliers;
3942
import com.google.protobuf.ByteString;
4043

4144
import javax.annotation.Nonnull;
4245
import javax.annotation.Nullable;
46+
import java.sql.DatabaseMetaData;
4347
import java.sql.SQLException;
4448
import java.sql.Types;
4549
import java.util.ArrayList;
4650
import java.util.HashMap;
4751
import java.util.List;
4852
import java.util.Map;
4953
import java.util.UUID;
54+
import java.util.function.Supplier;
5055

5156
/**
5257
* Facade over grpc protobuf objects that offers a {@link RelationalStruct} view.
@@ -415,7 +420,7 @@ int getZeroBasedOffsetOrThrow(String fieldName) throws SQLException {
415420
public RelationalStructBuilder addBoolean(String fieldName, boolean b) throws SQLException {
416421
// Add the metadata and get offset at where to insert data.
417422
int offset = addMetadata(ColumnMetadata.newBuilder()
418-
.setName(fieldName).setJavaSqlTypesCode(Types.BOOLEAN).build());
423+
.setName(fieldName).setJavaSqlTypesCode(Types.BOOLEAN).setType(Type.BOOLEAN).build());
419424
// Add field data.
420425
this.listColumnBuilder.addColumn(offset, Column.newBuilder().setBoolean(b).build());
421426
return this;
@@ -424,7 +429,7 @@ public RelationalStructBuilder addBoolean(String fieldName, boolean b) throws SQ
424429
@Override
425430
public RelationalStructBuilder addLong(String fieldName, long l) throws SQLException {
426431
int offset = addMetadata(ColumnMetadata.newBuilder()
427-
.setName(fieldName).setJavaSqlTypesCode(Types.BIGINT).build());
432+
.setName(fieldName).setJavaSqlTypesCode(Types.BIGINT).setType(Type.LONG).build());
428433
this.listColumnBuilder.addColumn(offset, Column.newBuilder().setLong(l).build());
429434
return this;
430435
}
@@ -437,15 +442,15 @@ public RelationalStructBuilder addFloat(String fieldName, float f) throws SQLExc
437442
@Override
438443
public RelationalStructBuilder addDouble(String fieldName, double d) throws SQLException {
439444
int offset = addMetadata(ColumnMetadata.newBuilder()
440-
.setName(fieldName).setJavaSqlTypesCode(Types.DOUBLE).build());
445+
.setName(fieldName).setJavaSqlTypesCode(Types.DOUBLE).setType(Type.DOUBLE).build());
441446
this.listColumnBuilder.addColumn(offset, Column.newBuilder().setDouble(d).build());
442447
return this;
443448
}
444449

445450
@Override
446451
public RelationalStructBuilder addBytes(String fieldName, byte[] bytes) throws SQLException {
447452
int offset = addMetadata(ColumnMetadata.newBuilder()
448-
.setName(fieldName).setJavaSqlTypesCode(Types.BINARY).build());
453+
.setName(fieldName).setJavaSqlTypesCode(Types.BINARY).setType(Type.BYTES).build());
449454
this.listColumnBuilder.addColumn(offset, Column.newBuilder().setBinary(ByteString.copyFrom(bytes)).build());
450455
return this;
451456
}
@@ -454,7 +459,7 @@ public RelationalStructBuilder addBytes(String fieldName, byte[] bytes) throws S
454459
@SpotBugsSuppressWarnings("NP")
455460
public RelationalStructBuilder addString(String fieldName, @Nullable String s) throws SQLException {
456461
int offset = addMetadata(ColumnMetadata.newBuilder()
457-
.setName(fieldName).setJavaSqlTypesCode(Types.VARCHAR).build());
462+
.setName(fieldName).setJavaSqlTypesCode(Types.VARCHAR).setType(Type.STRING).build());
458463
// TODO: setString requires a non-null string, but this method takes a nullable string
459464
this.listColumnBuilder.addColumn(offset, Column.newBuilder().setString(s).build());
460465
return this;
@@ -477,7 +482,7 @@ public RelationalStructBuilder addStruct(String fieldName, @Nonnull RelationalSt
477482
// Insert the data portion of RelationalStruct here.
478483
RelationalStructFacade relationalStructFacade = struct.unwrap(RelationalStructFacade.class);
479484
int offset = addMetadata(ColumnMetadata.newBuilder().setName(fieldName)
480-
.setJavaSqlTypesCode(Types.STRUCT).setStructMetadata(relationalStructFacade.delegateMetadata).build());
485+
.setJavaSqlTypesCode(Types.STRUCT).setType(Type.STRUCT).setStructMetadata(relationalStructFacade.delegateMetadata).build());
481486
this.listColumnBuilder
482487
.addColumn(offset, Column.newBuilder().setStruct(relationalStructFacade.delegate).build());
483488
return this;
@@ -490,7 +495,7 @@ public RelationalStructBuilder addArray(String fieldName, @Nonnull RelationalArr
490495
// Insert the data portion of RelationalStruct here.
491496
RelationalArrayFacade relationalArrayFacade = array.unwrap(RelationalArrayFacade.class);
492497
int offset = addMetadata(ColumnMetadata.newBuilder()
493-
.setName(fieldName).setJavaSqlTypesCode(Types.ARRAY)
498+
.setName(fieldName).setJavaSqlTypesCode(Types.ARRAY).setType(Type.ARRAY)
494499
.setArrayMetadata(relationalArrayFacade.getDelegateMetadata())
495500
.build());
496501
this.listColumnBuilder.addColumn(offset,
@@ -520,9 +525,52 @@ public RelationalStruct build() {
520525
*/
521526
static final class RelationalStructFacadeMetaData implements StructMetaData {
522527
private final ListColumnMetadata metadata;
528+
private final Supplier<DataType.StructType> type;
523529

524530
RelationalStructFacadeMetaData(ListColumnMetadata metadata) {
525531
this.metadata = metadata;
532+
this.type = Suppliers.memoize(this::computeType);
533+
}
534+
535+
private DataType.StructType computeType() {
536+
return getStructDataType(metadata.getColumnMetadataList(), false);
537+
}
538+
539+
private static DataType.StructType getStructDataType(@Nonnull List<ColumnMetadata> columnMetadataList, boolean nullable) {
540+
final var fields = new ArrayList<DataType.StructType.Field>();
541+
for (int i = 0; i < columnMetadataList.size(); i++) {
542+
final var columnMetadata = columnMetadataList.get(i);
543+
fields.add(DataType.StructType.Field.from(columnMetadata.getName(), getDataType(columnMetadata.getType(), columnMetadata, DatabaseMetaData.columnNullable == columnMetadata.getNullable()), i));
544+
}
545+
return DataType.StructType.from("ANONYMOUS_STRUCT", fields, nullable);
546+
}
547+
548+
static DataType getDataType(@Nonnull Type type, @Nonnull ColumnMetadata columnMetadata, boolean nullable) {
549+
switch (type) {
550+
case LONG:
551+
return nullable ? DataType.Primitives.NULLABLE_LONG.type() : DataType.Primitives.LONG.type();
552+
case INTEGER:
553+
return nullable ? DataType.Primitives.NULLABLE_INTEGER.type() : DataType.Primitives.INTEGER.type();
554+
case DOUBLE:
555+
return nullable ? DataType.Primitives.NULLABLE_DOUBLE.type() : DataType.Primitives.DOUBLE.type();
556+
case FLOAT:
557+
return nullable ? DataType.Primitives.NULLABLE_FLOAT.type() : DataType.Primitives.FLOAT.type();
558+
case BOOLEAN:
559+
return nullable ? DataType.Primitives.NULLABLE_BOOLEAN.type() : DataType.Primitives.BOOLEAN.type();
560+
case BYTES:
561+
return nullable ? DataType.Primitives.NULLABLE_BYTES.type() : DataType.Primitives.BYTES.type();
562+
case UUID:
563+
return nullable ? DataType.Primitives.NULLABLE_UUID.type() : DataType.Primitives.UUID.type();
564+
case STRING:
565+
return nullable ? DataType.Primitives.NULLABLE_STRING.type() : DataType.Primitives.STRING.type();
566+
case STRUCT:
567+
return getStructDataType(columnMetadata.getStructMetadata().getColumnMetadataList(), nullable);
568+
case ARRAY:
569+
final var arrayMetadata = columnMetadata.getArrayMetadata();
570+
return DataType.ArrayType.from(getDataType(arrayMetadata.getType(), arrayMetadata, arrayMetadata.getNullable() == DatabaseMetaData.columnNullable), nullable);
571+
default:
572+
throw new RelationalException("Not implemeneted: " + type.name(), ErrorCode.INTERNAL_ERROR).toUncheckedWrappedException();
573+
}
526574
}
527575

528576
@Override
@@ -592,7 +640,7 @@ public int getLeadingPhantomColumnCount() {
592640

593641
@Override
594642
public DataType.StructType getRelationalDataType() throws SQLException {
595-
throw new SQLException("Not implemented", ErrorCode.UNSUPPORTED_OPERATION.getErrorCode());
643+
return type.get();
596644
}
597645

598646
@Override

0 commit comments

Comments
 (0)