39
39
import com .google .cloud .spanner .testing .EmulatorSpannerHelper ;
40
40
import com .google .cloud .spanner .testing .RemoteSpannerHelper ;
41
41
import com .google .common .collect .ImmutableList ;
42
+ import com .google .protobuf .ListValue ;
42
43
import com .google .protobuf .NullValue ;
43
44
import java .util .ArrayList ;
45
+ import java .util .Arrays ;
44
46
import java .util .Collections ;
45
47
import java .util .List ;
46
48
import java .util .concurrent .ExecutionException ;
47
49
import java .util .concurrent .TimeUnit ;
50
+ import java .util .stream .Collectors ;
48
51
import org .junit .AfterClass ;
49
52
import org .junit .Before ;
50
53
import org .junit .BeforeClass ;
56
59
import org .junit .runners .JUnit4 ;
57
60
import org .threeten .bp .Duration ;
58
61
59
- // TODO: Re-enable when jsonb is GA.
60
- @ Ignore ("Feature is not yet generally available" )
61
62
@ Category (ParallelIntegrationTest .class )
62
63
@ RunWith (JUnit4 .class )
63
64
public class ITPgJsonbTest {
@@ -118,7 +119,9 @@ public void setUp() throws Exception {
118
119
instanceId ,
119
120
databaseId ,
120
121
Collections .singletonList (
121
- "CREATE TABLE \" " + tableName + "\" (id BIGINT PRIMARY KEY, col1 JSONB)" ),
122
+ "CREATE TABLE \" "
123
+ + tableName
124
+ + "\" (id BIGINT PRIMARY KEY, col1 JSONB, colarray JSONB[])" ),
122
125
null )
123
126
.get (OPERATION_TIMEOUT .toMillis (), TimeUnit .MILLISECONDS );
124
127
}
@@ -181,6 +184,8 @@ public void testPgJsonbInSecondaryIndex() {
181
184
+ " {\" color\" :\" green\" ,\" value\" :\" #0f0\" },"
182
185
+ " {\" color\" :\" blue\" ,\" value\" :\" #00f\" }"
183
186
+ "]" ;
187
+ private static final List <String > JSON_ARRAY1 = Arrays .asList (JSON_VALUE_1 , JSON_VALUE_2 );
188
+ private static final List <String > JSON_ARRAY2 = Arrays .asList ("[]" , "{}" );
184
189
185
190
@ Test
186
191
public void testLiteralPgJsonb () {
@@ -192,18 +197,24 @@ public void testLiteralPgJsonb() {
192
197
transaction -> {
193
198
transaction .executeUpdate (
194
199
Statement .of (
195
- "INSERT INTO "
196
- + tableName
197
- + " (id, col1) VALUES"
198
- + " (1, '"
199
- + JSON_VALUE_1
200
- + "')"
201
- + ", (2, '"
202
- + JSON_VALUE_2
203
- + "')"
204
- + ", (3, '{}')"
205
- + ", (4, '[]')"
206
- + ", (5, null)" ));
200
+ String .format (
201
+ "INSERT INTO %s (id, col1, colarray) VALUES "
202
+ + "(1, '%s', array[%s]::jsonb[]), "
203
+ + "(2, '%s', array[%s]::jsonb[]), "
204
+ + "(3, '{}', array['{}']::jsonb[]), "
205
+ + "(4, '[]', array['[]']::jsonb[]), "
206
+ + "(5, null, null)" ,
207
+ tableName ,
208
+ JSON_VALUE_1 ,
209
+ // Convert array into string with literals separated by comma
210
+ // [a, b, c, null] -> 'a','b','c',null
211
+ JSON_ARRAY1 .stream ()
212
+ .map (item -> (item == null ? null : "'" + item + "'" ))
213
+ .collect (Collectors .joining ("," )),
214
+ JSON_VALUE_2 ,
215
+ JSON_ARRAY2 .stream ()
216
+ .map (item -> (item == null ? null : "'" + item + "'" ))
217
+ .collect (Collectors .joining ("," )))));
207
218
return null ;
208
219
});
209
220
@@ -222,29 +233,48 @@ public void testPgJsonbParameter() {
222
233
Statement .newBuilder (
223
234
"INSERT INTO "
224
235
+ tableName
225
- + " (id, col1) VALUES"
226
- + " (1, $1)"
227
- + ", (2, $2 )"
228
- + ", (3, $3 )"
229
- + ", (4, $4 )"
230
- + ", (5, $5 )" )
236
+ + " (id, col1, colarray ) VALUES"
237
+ + " (1, $1, $2 )"
238
+ + ", (2, $3, $4 )"
239
+ + ", (3, $5, $6 )"
240
+ + ", (4, $7, $8 )"
241
+ + ", (5, $9, $10 )" )
231
242
.bind ("p1" )
232
243
.to (Value .pgJsonb (JSON_VALUE_1 ))
233
244
.bind ("p2" )
234
- .to (Value .pgJsonb ( JSON_VALUE_2 ))
245
+ .to (Value .pgJsonbArray ( JSON_ARRAY1 ))
235
246
.bind ("p3" )
236
- .to (Value .pgJsonb ("{}" ))
247
+ .to (Value .pgJsonb (JSON_VALUE_2 ))
237
248
.bind ("p4" )
238
- .to (Value .pgJsonb ( "[]" ))
249
+ .to (Value .pgJsonbArray ( JSON_ARRAY2 ))
239
250
.bind ("p5" )
251
+ .to (Value .pgJsonb ("{}" ))
252
+ .bind ("p6" )
253
+ .to (Value .pgJsonbArray (Collections .singletonList ("{}" )))
254
+ .bind ("p7" )
255
+ .to (Value .pgJsonb ("[]" ))
256
+ .bind ("p8" )
257
+ .to (Value .pgJsonbArray (Collections .singletonList ("[]" )))
258
+ .bind ("p9" )
240
259
.to (Value .pgJsonb (null ))
260
+ .bind ("p10" )
261
+ .to (Value .pgJsonbArray (null ))
241
262
.build ());
242
263
return null ;
243
264
});
244
265
245
266
verifyContents ();
246
267
}
247
268
269
+ private ListValue getJsonListValue (List <String > jsonList ) {
270
+ return ListValue .newBuilder ()
271
+ .addAllValues (
272
+ jsonList .stream ()
273
+ .map (json -> com .google .protobuf .Value .newBuilder ().setStringValue (json ).build ())
274
+ .collect (Collectors .toList ()))
275
+ .build ();
276
+ }
277
+
248
278
@ Ignore ("Untyped jsonb parameters are not yet supported" )
249
279
@ Test
250
280
public void testPgJsonbUntypedParameter () {
@@ -261,12 +291,12 @@ public void testPgJsonbUntypedParameter() {
261
291
Statement .newBuilder (
262
292
"INSERT INTO "
263
293
+ tableName
264
- + " (id, col1) VALUES"
265
- + " (1, $1)"
266
- + ", (2, $2 )"
267
- + ", (3, $3 )"
268
- + ", (4, $4 )"
269
- + ", (5, $5 )" )
294
+ + " (id, col1, colarray ) VALUES"
295
+ + " (1, $1, $2 )"
296
+ + ", (2, $3, $4 )"
297
+ + ", (3, $5, $6 )"
298
+ + ", (4, $7, $8 )"
299
+ + ", (5, $9, $10 )" )
270
300
.bind ("p1" )
271
301
.to (
272
302
Value .untyped (
@@ -277,17 +307,47 @@ public void testPgJsonbUntypedParameter() {
277
307
.to (
278
308
Value .untyped (
279
309
com .google .protobuf .Value .newBuilder ()
280
- .setStringValue ( JSON_VALUE_2 )
310
+ .setListValue ( getJsonListValue ( JSON_ARRAY1 ) )
281
311
.build ()))
282
312
.bind ("p3" )
283
313
.to (
284
314
Value .untyped (
285
- com .google .protobuf .Value .newBuilder ().setStringValue ("{}" ).build ()))
315
+ com .google .protobuf .Value .newBuilder ()
316
+ .setStringValue (JSON_VALUE_2 )
317
+ .build ()))
286
318
.bind ("p4" )
287
319
.to (
288
320
Value .untyped (
289
- com .google .protobuf .Value .newBuilder ().setStringValue ("[]" ).build ()))
321
+ com .google .protobuf .Value .newBuilder ()
322
+ .setListValue (getJsonListValue (JSON_ARRAY2 ))
323
+ .build ()))
290
324
.bind ("p5" )
325
+ .to (
326
+ Value .untyped (
327
+ com .google .protobuf .Value .newBuilder ().setStringValue ("{}" ).build ()))
328
+ .bind ("p6" )
329
+ .to (
330
+ Value .untyped (
331
+ com .google .protobuf .Value .newBuilder ()
332
+ .setListValue (getJsonListValue (Collections .singletonList ("{}" )))
333
+ .build ()))
334
+ .bind ("p7" )
335
+ .to (
336
+ Value .untyped (
337
+ com .google .protobuf .Value .newBuilder ().setStringValue ("[]" ).build ()))
338
+ .bind ("p8" )
339
+ .to (
340
+ Value .untyped (
341
+ com .google .protobuf .Value .newBuilder ()
342
+ .setListValue (getJsonListValue (Collections .singletonList ("[]" )))
343
+ .build ()))
344
+ .bind ("p9" )
345
+ .to (
346
+ Value .untyped (
347
+ com .google .protobuf .Value .newBuilder ()
348
+ .setNullValue (NullValue .NULL_VALUE )
349
+ .build ()))
350
+ .bind ("p10" )
291
351
.to (
292
352
Value .untyped (
293
353
com .google .protobuf .Value .newBuilder ()
@@ -315,30 +375,40 @@ public void testMutationsWithPgJsonbAsString() {
315
375
.to (1 )
316
376
.set ("col1" )
317
377
.to (JSON_VALUE_1 )
378
+ .set ("colarray" )
379
+ .to (Value .pgJsonbArray (JSON_ARRAY1 ))
318
380
.build (),
319
381
Mutation .newInsertBuilder (tableName )
320
382
.set ("id" )
321
383
.to (2 )
322
384
.set ("col1" )
323
385
.to (JSON_VALUE_2 )
386
+ .set ("colarray" )
387
+ .to (Value .pgJsonbArray (JSON_ARRAY2 ))
324
388
.build (),
325
389
Mutation .newInsertBuilder (tableName )
326
390
.set ("id" )
327
391
.to (3 )
328
392
.set ("col1" )
329
393
.to ("{}" )
394
+ .set ("colarray" )
395
+ .to (Value .pgJsonbArray (Collections .singletonList ("{}" )))
330
396
.build (),
331
397
Mutation .newInsertBuilder (tableName )
332
398
.set ("id" )
333
399
.to (4 )
334
400
.set ("col1" )
335
401
.to ("[]" )
402
+ .set ("colarray" )
403
+ .to (Value .pgJsonbArray (Collections .singletonList ("[]" )))
336
404
.build (),
337
405
Mutation .newInsertBuilder (tableName )
338
406
.set ("id" )
339
407
.to (5 )
340
408
.set ("col1" )
341
409
.to ((String ) null )
410
+ .set ("colarray" )
411
+ .to (Value .pgJsonbArray (null ))
342
412
.build ()));
343
413
return null ;
344
414
});
@@ -361,30 +431,40 @@ public void testMutationsWithPgJsonbAsValue() {
361
431
.to (1 )
362
432
.set ("col1" )
363
433
.to (Value .pgJsonb (JSON_VALUE_1 ))
434
+ .set ("colarray" )
435
+ .to (Value .pgJsonbArray (JSON_ARRAY1 ))
364
436
.build (),
365
437
Mutation .newInsertBuilder (tableName )
366
438
.set ("id" )
367
439
.to (2 )
368
440
.set ("col1" )
369
441
.to (Value .pgJsonb (JSON_VALUE_2 ))
442
+ .set ("colarray" )
443
+ .to (Value .pgJsonbArray (JSON_ARRAY2 ))
370
444
.build (),
371
445
Mutation .newInsertBuilder (tableName )
372
446
.set ("id" )
373
447
.to (3 )
374
448
.set ("col1" )
375
449
.to (Value .pgJsonb ("{}" ))
450
+ .set ("colarray" )
451
+ .to (Value .pgJsonbArray (Collections .singletonList ("{}" )))
376
452
.build (),
377
453
Mutation .newInsertBuilder (tableName )
378
454
.set ("id" )
379
455
.to (4 )
380
456
.set ("col1" )
381
457
.to (Value .pgJsonb ("[]" ))
458
+ .set ("colarray" )
459
+ .to (Value .pgJsonbArray (Collections .singletonList ("[]" )))
382
460
.build (),
383
461
Mutation .newInsertBuilder (tableName )
384
462
.set ("id" )
385
463
.to (5 )
386
464
.set ("col1" )
387
465
.to (Value .pgJsonb (null ))
466
+ .set ("colarray" )
467
+ .to (Value .pgJsonbArray (null ))
388
468
.build ()));
389
469
return null ;
390
470
});
@@ -405,6 +485,21 @@ private void verifyContents() {
405
485
assertEquals ("{\" color\" : \" red\" , \" value\" : \" #f00\" }" , resultSet .getPgJsonb ("col1" ));
406
486
assertEquals (
407
487
Value .pgJsonb ("{\" color\" : \" red\" , \" value\" : \" #f00\" }" ), resultSet .getValue ("col1" ));
488
+ assertEquals (
489
+ Arrays .asList (
490
+ "{\" color\" : \" red\" , \" value\" : \" #f00\" }" ,
491
+ "[{\" color\" : \" red\" , \" value\" : \" #f00\" }, "
492
+ + "{\" color\" : \" green\" , \" value\" : \" #0f0\" }, "
493
+ + "{\" color\" : \" blue\" , \" value\" : \" #00f\" }]" ),
494
+ resultSet .getPgJsonbList ("colarray" ));
495
+ assertEquals (
496
+ Value .pgJsonbArray (
497
+ Arrays .asList (
498
+ "{\" color\" : \" red\" , \" value\" : \" #f00\" }" ,
499
+ "[{\" color\" : \" red\" , \" value\" : \" #f00\" }, "
500
+ + "{\" color\" : \" green\" , \" value\" : \" #0f0\" }, "
501
+ + "{\" color\" : \" blue\" , \" value\" : \" #00f\" }]" )),
502
+ resultSet .getValue ("colarray" ));
408
503
409
504
assertTrue (resultSet .next ());
410
505
assertEquals (
@@ -422,17 +517,26 @@ private void verifyContents() {
422
517
+ "{\" color\" : \" blue\" , \" value\" : \" #00f\" }"
423
518
+ "]" ),
424
519
resultSet .getValue ("col1" ));
520
+ assertEquals (JSON_ARRAY2 , resultSet .getPgJsonbList ("colarray" ));
521
+ assertEquals (Value .pgJsonbArray (JSON_ARRAY2 ), resultSet .getValue ("colarray" ));
425
522
426
523
assertTrue (resultSet .next ());
427
524
assertEquals ("{}" , resultSet .getPgJsonb ("col1" ));
428
525
assertEquals (Value .pgJsonb ("{}" ), resultSet .getValue ("col1" ));
526
+ assertEquals (Collections .singletonList ("{}" ), resultSet .getPgJsonbList ("colarray" ));
527
+ assertEquals (
528
+ Value .pgJsonbArray (Collections .singletonList ("{}" )), resultSet .getValue ("colarray" ));
429
529
430
530
assertTrue (resultSet .next ());
431
531
assertEquals ("[]" , resultSet .getPgJsonb ("col1" ));
432
532
assertEquals (Value .pgJsonb ("[]" ), resultSet .getValue ("col1" ));
533
+ assertEquals (Collections .singletonList ("[]" ), resultSet .getPgJsonbList ("colarray" ));
534
+ assertEquals (
535
+ Value .pgJsonbArray (Collections .singletonList ("[]" )), resultSet .getValue ("colarray" ));
433
536
434
537
assertTrue (resultSet .next ());
435
538
assertTrue (resultSet .isNull ("col1" ));
539
+ assertTrue (resultSet .isNull ("colarray" ));
436
540
437
541
assertFalse (resultSet .next ());
438
542
}
0 commit comments