26
26
import com .apple .foundationdb .relational .api .RelationalStruct ;
27
27
import com .apple .foundationdb .relational .api .RelationalStructBuilder ;
28
28
import com .apple .foundationdb .relational .api .exceptions .ErrorCode ;
29
+ import com .apple .foundationdb .relational .api .exceptions .RelationalException ;
29
30
import com .apple .foundationdb .relational .api .metadata .DataType ;
30
31
import com .apple .foundationdb .relational .jdbc .grpc .v1 .column .Column ;
31
32
import com .apple .foundationdb .relational .jdbc .grpc .v1 .column .ColumnMetadata ;
32
33
import com .apple .foundationdb .relational .jdbc .grpc .v1 .column .ListColumn ;
33
34
import com .apple .foundationdb .relational .jdbc .grpc .v1 .column .ListColumnMetadata ;
34
35
import com .apple .foundationdb .relational .jdbc .grpc .v1 .column .Struct ;
36
+ import com .apple .foundationdb .relational .jdbc .grpc .v1 .column .Type ;
35
37
import com .apple .foundationdb .relational .util .PositionalIndex ;
36
38
37
39
import com .apple .foundationdb .relational .util .SpotBugsSuppressWarnings ;
38
40
import com .google .common .annotations .VisibleForTesting ;
41
+ import com .google .common .base .Suppliers ;
39
42
import com .google .protobuf .ByteString ;
40
43
41
44
import javax .annotation .Nonnull ;
42
45
import javax .annotation .Nullable ;
46
+ import java .sql .DatabaseMetaData ;
43
47
import java .sql .SQLException ;
44
48
import java .sql .Types ;
45
49
import java .util .ArrayList ;
46
50
import java .util .HashMap ;
47
51
import java .util .List ;
48
52
import java .util .Map ;
49
53
import java .util .UUID ;
54
+ import java .util .function .Supplier ;
50
55
51
56
/**
52
57
* Facade over grpc protobuf objects that offers a {@link RelationalStruct} view.
@@ -415,7 +420,7 @@ int getZeroBasedOffsetOrThrow(String fieldName) throws SQLException {
415
420
public RelationalStructBuilder addBoolean (String fieldName , boolean b ) throws SQLException {
416
421
// Add the metadata and get offset at where to insert data.
417
422
int offset = addMetadata (ColumnMetadata .newBuilder ()
418
- .setName (fieldName ).setJavaSqlTypesCode (Types .BOOLEAN ).build ());
423
+ .setName (fieldName ).setJavaSqlTypesCode (Types .BOOLEAN ).setType ( Type . BOOLEAN ). build ());
419
424
// Add field data.
420
425
this .listColumnBuilder .addColumn (offset , Column .newBuilder ().setBoolean (b ).build ());
421
426
return this ;
@@ -424,7 +429,7 @@ public RelationalStructBuilder addBoolean(String fieldName, boolean b) throws SQ
424
429
@ Override
425
430
public RelationalStructBuilder addLong (String fieldName , long l ) throws SQLException {
426
431
int offset = addMetadata (ColumnMetadata .newBuilder ()
427
- .setName (fieldName ).setJavaSqlTypesCode (Types .BIGINT ).build ());
432
+ .setName (fieldName ).setJavaSqlTypesCode (Types .BIGINT ).setType ( Type . LONG ). build ());
428
433
this .listColumnBuilder .addColumn (offset , Column .newBuilder ().setLong (l ).build ());
429
434
return this ;
430
435
}
@@ -437,15 +442,15 @@ public RelationalStructBuilder addFloat(String fieldName, float f) throws SQLExc
437
442
@ Override
438
443
public RelationalStructBuilder addDouble (String fieldName , double d ) throws SQLException {
439
444
int offset = addMetadata (ColumnMetadata .newBuilder ()
440
- .setName (fieldName ).setJavaSqlTypesCode (Types .DOUBLE ).build ());
445
+ .setName (fieldName ).setJavaSqlTypesCode (Types .DOUBLE ).setType ( Type . DOUBLE ). build ());
441
446
this .listColumnBuilder .addColumn (offset , Column .newBuilder ().setDouble (d ).build ());
442
447
return this ;
443
448
}
444
449
445
450
@ Override
446
451
public RelationalStructBuilder addBytes (String fieldName , byte [] bytes ) throws SQLException {
447
452
int offset = addMetadata (ColumnMetadata .newBuilder ()
448
- .setName (fieldName ).setJavaSqlTypesCode (Types .BINARY ).build ());
453
+ .setName (fieldName ).setJavaSqlTypesCode (Types .BINARY ).setType ( Type . BYTES ). build ());
449
454
this .listColumnBuilder .addColumn (offset , Column .newBuilder ().setBinary (ByteString .copyFrom (bytes )).build ());
450
455
return this ;
451
456
}
@@ -454,7 +459,7 @@ public RelationalStructBuilder addBytes(String fieldName, byte[] bytes) throws S
454
459
@ SpotBugsSuppressWarnings ("NP" )
455
460
public RelationalStructBuilder addString (String fieldName , @ Nullable String s ) throws SQLException {
456
461
int offset = addMetadata (ColumnMetadata .newBuilder ()
457
- .setName (fieldName ).setJavaSqlTypesCode (Types .VARCHAR ).build ());
462
+ .setName (fieldName ).setJavaSqlTypesCode (Types .VARCHAR ).setType ( Type . STRING ). build ());
458
463
// TODO: setString requires a non-null string, but this method takes a nullable string
459
464
this .listColumnBuilder .addColumn (offset , Column .newBuilder ().setString (s ).build ());
460
465
return this ;
@@ -477,7 +482,7 @@ public RelationalStructBuilder addStruct(String fieldName, @Nonnull RelationalSt
477
482
// Insert the data portion of RelationalStruct here.
478
483
RelationalStructFacade relationalStructFacade = struct .unwrap (RelationalStructFacade .class );
479
484
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 ());
481
486
this .listColumnBuilder
482
487
.addColumn (offset , Column .newBuilder ().setStruct (relationalStructFacade .delegate ).build ());
483
488
return this ;
@@ -490,7 +495,7 @@ public RelationalStructBuilder addArray(String fieldName, @Nonnull RelationalArr
490
495
// Insert the data portion of RelationalStruct here.
491
496
RelationalArrayFacade relationalArrayFacade = array .unwrap (RelationalArrayFacade .class );
492
497
int offset = addMetadata (ColumnMetadata .newBuilder ()
493
- .setName (fieldName ).setJavaSqlTypesCode (Types .ARRAY )
498
+ .setName (fieldName ).setJavaSqlTypesCode (Types .ARRAY ). setType ( Type . ARRAY )
494
499
.setArrayMetadata (relationalArrayFacade .getDelegateMetadata ())
495
500
.build ());
496
501
this .listColumnBuilder .addColumn (offset ,
@@ -520,9 +525,52 @@ public RelationalStruct build() {
520
525
*/
521
526
static final class RelationalStructFacadeMetaData implements StructMetaData {
522
527
private final ListColumnMetadata metadata ;
528
+ private final Supplier <DataType .StructType > type ;
523
529
524
530
RelationalStructFacadeMetaData (ListColumnMetadata metadata ) {
525
531
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
+ }
526
574
}
527
575
528
576
@ Override
@@ -592,7 +640,7 @@ public int getLeadingPhantomColumnCount() {
592
640
593
641
@ Override
594
642
public DataType .StructType getRelationalDataType () throws SQLException {
595
- throw new SQLException ( "Not implemented" , ErrorCode . UNSUPPORTED_OPERATION . getErrorCode () );
643
+ return type . get ( );
596
644
}
597
645
598
646
@ Override
0 commit comments