22
22
import com .google .cloud .Date ;
23
23
import com .google .cloud .Timestamp ;
24
24
import com .google .cloud .spanner .Dialect ;
25
+ import com .google .cloud .spanner .Interval ;
25
26
import com .google .cloud .spanner .MockSpannerServiceImpl .StatementResult ;
26
27
import com .google .cloud .spanner .ResultSet ;
27
28
import com .google .cloud .spanner .SingerProto .Genre ;
35
36
import com .google .spanner .v1 .Type ;
36
37
import com .google .spanner .v1 .TypeCode ;
37
38
import java .math .BigDecimal ;
39
+ import java .math .BigInteger ;
38
40
import java .nio .charset .StandardCharsets ;
39
41
import java .util .Arrays ;
40
42
import java .util .Base64 ;
@@ -78,6 +80,7 @@ public static Object[] data() {
78
80
public static final Date DATE_VALUE = Date .fromYearMonthDay (2024 , 3 , 2 );
79
81
public static final Timestamp TIMESTAMP_VALUE =
80
82
Timestamp .parseTimestamp ("2024-03-02T07:07:00.20982735Z" );
83
+ public static final Interval INTERVAL_VALUE = Interval .parseFromString ("P2Y4M3DT10H1M7.3S" );
81
84
82
85
public static final List <Boolean > BOOL_ARRAY_VALUE = Arrays .asList (true , null , false );
83
86
public static final List <Long > INT64_ARRAY_VALUE =
@@ -131,6 +134,13 @@ public static Object[] data() {
131
134
Timestamp .parseTimestamp ("2024-03-03T07:07:00Z" ),
132
135
Timestamp .MIN_VALUE ,
133
136
Timestamp .MAX_VALUE );
137
+ public static final List <Interval > INTERVAL_ARRAY_VALUE =
138
+ Arrays .asList (
139
+ INTERVAL_VALUE ,
140
+ null ,
141
+ Interval .fromMonthsDaysNanos (9 , 39 , BigInteger .TEN ),
142
+ Interval .fromMonthsDaysNanos (-120000 , -3660000 , new BigInteger ("-316224000000000000000" )),
143
+ Interval .fromMonthsDaysNanos (120000 , 3660000 , new BigInteger ("316224000000000000000" )));
134
144
135
145
@ Before
136
146
public void setupDialect () {
@@ -158,14 +168,15 @@ private void setupAllTypesResultSet(Dialect dialect) {
158
168
// COL8: BYTES
159
169
// COL9: DATE
160
170
// COL10: TIMESTAMP
161
- // COL11: PG_OID (added only for POSTGRESQL dialect)
162
- // COL12-21: ARRAY<..> for the types above.
171
+ // COL11: INTERVAL
172
+ // COL12: PG_OID (added only for POSTGRESQL dialect)
173
+ // COL13-22: ARRAY<..> for the types above.
163
174
// Only for GoogleSQL:
164
- // COL22 : PROTO
165
- // COL23 : ENUM
166
- // COL24 : ARRAY<PROTO>
167
- // COL25 : ARRAY<ENUM>
168
- // COL26 : ARRAY<PG_OID> (added only for POSTGRESQL dialect)
175
+ // COL23 : PROTO
176
+ // COL24 : ENUM
177
+ // COL25 : ARRAY<PROTO>
178
+ // COL26 : ARRAY<ENUM>
179
+ // COL27 : ARRAY<PG_OID> (added only for POSTGRESQL dialect)
169
180
ListValue .Builder row1Builder =
170
181
ListValue .newBuilder ()
171
182
.addValues (Value .newBuilder ().setBoolValue (BOOL_VALUE ))
@@ -183,7 +194,8 @@ private void setupAllTypesResultSet(Dialect dialect) {
183
194
.addValues (
184
195
Value .newBuilder ().setStringValue (Base64 .getEncoder ().encodeToString (BYTES_VALUE )))
185
196
.addValues (Value .newBuilder ().setStringValue (DATE_VALUE .toString ()))
186
- .addValues (Value .newBuilder ().setStringValue (TIMESTAMP_VALUE .toString ()));
197
+ .addValues (Value .newBuilder ().setStringValue (TIMESTAMP_VALUE .toString ()))
198
+ .addValues (Value .newBuilder ().setStringValue (INTERVAL_VALUE .toString ()));
187
199
if (dialect == Dialect .POSTGRESQL ) {
188
200
row1Builder .addValues (
189
201
Value .newBuilder ().setStringValue (String .valueOf (PG_OID_VALUE )).build ());
@@ -372,6 +384,23 @@ private void setupAllTypesResultSet(Dialect dialect) {
372
384
.setStringValue (timestamp .toString ())
373
385
.build ())
374
386
.collect (Collectors .toList ()))
387
+ .build ()))
388
+ .addValues (
389
+ Value .newBuilder ()
390
+ .setListValue (
391
+ ListValue .newBuilder ()
392
+ .addAllValues (
393
+ INTERVAL_ARRAY_VALUE .stream ()
394
+ .map (
395
+ interval ->
396
+ interval == null
397
+ ? Value .newBuilder ()
398
+ .setNullValue (NullValue .NULL_VALUE )
399
+ .build ()
400
+ : Value .newBuilder ()
401
+ .setStringValue (interval .toISO8601 ())
402
+ .build ())
403
+ .collect (Collectors .toList ()))
375
404
.build ()));
376
405
377
406
if (dialect == Dialect .GOOGLE_STANDARD_SQL ) {
@@ -509,7 +538,9 @@ public static Statement createInsertStatement(Dialect dialect) {
509
538
.bind ("p" + ++param )
510
539
.to (DATE_VALUE )
511
540
.bind ("p" + ++param )
512
- .to (TIMESTAMP_VALUE );
541
+ .to (TIMESTAMP_VALUE )
542
+ .bind ("p" + ++param )
543
+ .to (INTERVAL_VALUE );
513
544
if (dialect == Dialect .POSTGRESQL ) {
514
545
builder .bind ("p" + ++param ).to (PG_OID_VALUE );
515
546
}
@@ -539,7 +570,9 @@ public static Statement createInsertStatement(Dialect dialect) {
539
570
.bind ("p" + ++param )
540
571
.toDateArray (DATE_ARRAY_VALUE )
541
572
.bind ("p" + ++param )
542
- .toTimestampArray (TIMESTAMP_ARRAY_VALUE );
573
+ .toTimestampArray (TIMESTAMP_ARRAY_VALUE )
574
+ .bind ("p" + ++param )
575
+ .toIntervalArray (INTERVAL_ARRAY_VALUE );
543
576
if (dialect == Dialect .POSTGRESQL ) {
544
577
builder .bind ("p" + ++param ).toInt64Array (PG_OID_ARRAY_VALUE );
545
578
}
@@ -574,6 +607,7 @@ public void testSelectAllTypes() {
574
607
assertArrayEquals (BYTES_VALUE , resultSet .getBytes (++col ).toByteArray ());
575
608
assertEquals (DATE_VALUE , resultSet .getDate (++col ));
576
609
assertEquals (TIMESTAMP_VALUE , resultSet .getTimestamp (++col ));
610
+ assertEquals (INTERVAL_VALUE , resultSet .getInterval (++col ));
577
611
if (dialect == Dialect .POSTGRESQL ) {
578
612
assertEquals (PG_OID_VALUE , resultSet .getLong (++col ));
579
613
}
@@ -596,6 +630,7 @@ public void testSelectAllTypes() {
596
630
assertEquals (BYTES_ARRAY_VALUE , resultSet .getBytesList (++col ));
597
631
assertEquals (DATE_ARRAY_VALUE , resultSet .getDateList (++col ));
598
632
assertEquals (TIMESTAMP_ARRAY_VALUE , resultSet .getTimestampList (++col ));
633
+ assertEquals (INTERVAL_ARRAY_VALUE , resultSet .getIntervalList (++col ));
599
634
if (dialect == Dialect .POSTGRESQL ) {
600
635
assertEquals (PG_OID_ARRAY_VALUE , resultSet .getLongList (++col ));
601
636
}
@@ -613,8 +648,8 @@ public void testInsertAllTypes() {
613
648
ExecuteSqlRequest request = mockSpanner .getRequestsOfType (ExecuteSqlRequest .class ).get (0 );
614
649
Map <String , Type > paramTypes = request .getParamTypesMap ();
615
650
Map <String , Value > params = request .getParams ().getFieldsMap ();
616
- assertEquals (dialect == Dialect .POSTGRESQL ? 22 : 20 , paramTypes .size ());
617
- assertEquals (dialect == Dialect .POSTGRESQL ? 22 : 20 , params .size ());
651
+ assertEquals (dialect == Dialect .POSTGRESQL ? 24 : 22 , paramTypes .size ());
652
+ assertEquals (dialect == Dialect .POSTGRESQL ? 24 : 22 , params .size ());
618
653
619
654
// Verify param types.
620
655
ImmutableList <TypeCode > expectedTypes ;
@@ -631,6 +666,7 @@ public void testInsertAllTypes() {
631
666
TypeCode .BYTES ,
632
667
TypeCode .DATE ,
633
668
TypeCode .TIMESTAMP ,
669
+ TypeCode .INTERVAL ,
634
670
TypeCode .INT64 );
635
671
} else {
636
672
expectedTypes =
@@ -644,7 +680,8 @@ public void testInsertAllTypes() {
644
680
TypeCode .JSON ,
645
681
TypeCode .BYTES ,
646
682
TypeCode .DATE ,
647
- TypeCode .TIMESTAMP );
683
+ TypeCode .TIMESTAMP ,
684
+ TypeCode .INTERVAL );
648
685
}
649
686
for (int col = 0 ; col < expectedTypes .size (); col ++) {
650
687
assertEquals (expectedTypes .get (col ), paramTypes .get ("p" + (col + 1 )).getCode ());
@@ -671,6 +708,7 @@ public void testInsertAllTypes() {
671
708
params .get ("p" + ++col ).getStringValue ());
672
709
assertEquals (DATE_VALUE .toString (), params .get ("p" + ++col ).getStringValue ());
673
710
assertEquals (TIMESTAMP_VALUE .toString (), params .get ("p" + ++col ).getStringValue ());
711
+ assertEquals (INTERVAL_VALUE .toString (), params .get ("p" + ++col ).getStringValue ());
674
712
if (dialect == Dialect .POSTGRESQL ) {
675
713
assertEquals (String .valueOf (PG_OID_VALUE ), params .get ("p" + ++col ).getStringValue ());
676
714
}
@@ -739,6 +777,15 @@ public void testInsertAllTypes() {
739
777
? null
740
778
: Timestamp .parseTimestamp (value .getStringValue ()))
741
779
.collect (Collectors .toList ()));
780
+ assertEquals (
781
+ INTERVAL_ARRAY_VALUE ,
782
+ params .get ("p" + ++col ).getListValue ().getValuesList ().stream ()
783
+ .map (
784
+ value ->
785
+ value .hasNullValue ()
786
+ ? null
787
+ : Interval .parseFromString (value .getStringValue ()))
788
+ .collect (Collectors .toList ()));
742
789
if (dialect == Dialect .POSTGRESQL ) {
743
790
assertEquals (
744
791
PG_OID_ARRAY_VALUE ,
0 commit comments