@@ -3,6 +3,7 @@ package main
3
3
import (
4
4
"fmt"
5
5
"log"
6
+ "reflect"
6
7
"testing"
7
8
8
9
"github.com/cipherstash/goeql"
@@ -181,7 +182,7 @@ func TestMatchQueryEmail(t *testing.T) {
181
182
assert .Equal (t , EncryptedTextField ("testemail@test.com" ), returnedExample .EncryptedTextField , "EncryptedTextField should match" )
182
183
}
183
184
184
- func TestJsonbQuerySimple (t * testing.T ) {
185
+ func TestJsonbQueryContainment (t * testing.T ) {
185
186
engine := proxyEngine ()
186
187
truncateDb (engine )
187
188
@@ -242,7 +243,7 @@ func TestJsonbQuerySimple(t *testing.T) {
242
243
assert .Equal (t , EncryptedJsonbField (expectedJson ), returnedExample .EncryptedJsonbField , "EncryptedJsonb field should match" )
243
244
}
244
245
245
- func TestJsonbQueryNested (t * testing.T ) {
246
+ func TestJsonbQueryNestedContainment (t * testing.T ) {
246
247
engine := proxyEngine ()
247
248
truncateDb (engine )
248
249
@@ -308,6 +309,242 @@ func TestJsonbQueryNested(t *testing.T) {
308
309
assert .Equal (t , EncryptedJsonbField (expectedJson ), returnedExample .EncryptedJsonbField , "EncryptedJsonb field should match" )
309
310
}
310
311
312
+ func TestJsonbExtractionOp (t * testing.T ) {
313
+ engine := proxyEngine ()
314
+ truncateDb (engine )
315
+
316
+ expected_one := map [string ]interface {}{
317
+ "nested_two" : "hello world" ,
318
+ }
319
+ jsonOne := map [string ]interface {}{
320
+ "top" : map [string ]interface {}{
321
+ "integer" : float64 (101 ),
322
+ "float" : 1.234 ,
323
+ "string" : "some string" ,
324
+ "nested" : expected_one ,
325
+ },
326
+ "bottom" : "value_three" ,
327
+ }
328
+ expected_two := map [string ]interface {}{
329
+ "nested_two" : "foo bar" ,
330
+ }
331
+ jsonTwo := map [string ]interface {}{
332
+ "top" : map [string ]interface {}{
333
+ "integer" : float64 (101 ),
334
+ "float" : 1.234 ,
335
+ "string" : "some string" ,
336
+ "nested" : expected_two ,
337
+ },
338
+ "bottom" : "value_three" ,
339
+ }
340
+
341
+ examples := []Example {
342
+ {
343
+ NonEncryptedField : "sydney" ,
344
+ EncryptedTextField : "testing" ,
345
+ EncryptedIntField : 42 ,
346
+ EncryptedJsonbField : jsonOne ,
347
+ },
348
+ {
349
+ NonEncryptedField : "melbourne" ,
350
+ EncryptedIntField : 42 ,
351
+ EncryptedTextField : "someone@gmail.com" ,
352
+ EncryptedJsonbField : jsonTwo ,
353
+ },
354
+ }
355
+
356
+ inserted , err := engine .Insert (& examples )
357
+
358
+ if err != nil {
359
+ t .Errorf ("Error inserting examples: %v" , err )
360
+ }
361
+
362
+ assert .Equal (t , int64 (2 ), inserted , "Expected to insert 2 rows" )
363
+
364
+ sql := `SELECT cs_ste_vec_value_v1(encrypted_jsonb_field, ?) AS val FROM examples`
365
+ ejson_path , err := goeql .EJsonPathQuery ("$.top.nested" , "examples" , "encrypted_jsonb_field" )
366
+
367
+ if err != nil {
368
+ log .Fatalf ("Error serializing fields_encrypted query: %v" , err )
369
+ }
370
+ results , err := engine .Query (sql , ejson_path )
371
+ if err != nil {
372
+ t .Fatalf ("Could not retrieve example using extraction: %v" , err )
373
+ }
374
+
375
+ assert .Equal (t , 2 , len (results ))
376
+
377
+ for i := range results {
378
+
379
+ var encryptedJson goeql.EncryptedJsonb
380
+
381
+ deserializedValue , err := encryptedJson .Deserialize (results [i ]["val" ])
382
+ if err != nil {
383
+ log .Fatal ("Deserialization error:" , err )
384
+ }
385
+ jsonb_expected_one := goeql .EncryptedJsonb (expected_one )
386
+ jsonb_expected_two := goeql .EncryptedJsonb (expected_two )
387
+
388
+ if ! reflect .DeepEqual (deserializedValue , jsonb_expected_one ) && ! reflect .DeepEqual (deserializedValue , jsonb_expected_two ) {
389
+ t .Errorf ("Expected value to be either %v or %v, but got %v" , jsonb_expected_one , jsonb_expected_two , deserializedValue )
390
+ }
391
+
392
+ }
393
+ }
394
+
395
+ func TestJsonbComparisonOp (t * testing.T ) {
396
+ engine := proxyEngine ()
397
+ truncateDb (engine )
398
+
399
+ jsonOne := map [string ]interface {}{
400
+ "top" : map [string ]interface {}{
401
+ "integer" : 3 ,
402
+ "float" : 1.234 ,
403
+ "string" : "some string" ,
404
+ },
405
+ "bottom" : "value_three" ,
406
+ }
407
+ jsonTwo := map [string ]interface {}{
408
+ "top" : map [string ]interface {}{
409
+ "integer" : 50 ,
410
+ "float" : 1.234 ,
411
+ "string" : "some string" ,
412
+ },
413
+ "bottom" : "value_three" ,
414
+ }
415
+ expected_id := int64 (2 )
416
+ example_one := Example {
417
+ Id : int64 (1 ),
418
+ NonEncryptedField : "sydney" ,
419
+ EncryptedTextField : "testing" ,
420
+ EncryptedIntField : 42 ,
421
+ EncryptedJsonbField : jsonOne ,
422
+ }
423
+ example_two := Example {
424
+ Id : expected_id ,
425
+ NonEncryptedField : "melbourne" ,
426
+ EncryptedIntField : 42 ,
427
+ EncryptedTextField : "someone@gmail.com" ,
428
+ EncryptedJsonbField : jsonTwo ,
429
+ }
430
+
431
+ examples := []Example {
432
+ example_one ,
433
+ example_two ,
434
+ }
435
+
436
+ inserted , err := engine .Insert (& examples )
437
+
438
+ if err != nil {
439
+ t .Errorf ("Error inserting examples: %v" , err )
440
+ }
441
+
442
+ assert .Equal (t , int64 (2 ), inserted , "Expected to insert 2 rows" )
443
+
444
+ t .Skip ("TODO: Fix failing test due to issue with cllw ore" )
445
+ path := "$.top.integer"
446
+ ejson_path , err := goeql .EJsonPathQuery (path , "examples" , "encrypted_jsonb_field" )
447
+
448
+ if err != nil {
449
+ log .Fatalf ("Error serializing fields_encrypted query: %v" , err )
450
+ }
451
+ value := 10
452
+ comparison_value , err := goeql .JsonbQuery (value , "examples" , "encrypted_jsonb_field" )
453
+
454
+ if err != nil {
455
+ log .Fatalf ("Error marshaling comparison value: %v" , err )
456
+ }
457
+ var results []Example
458
+ err = engine .Where ("cs_ste_vec_term_v1(examples.encrypted_jsonb_field, ?) > cs_ste_vec_term_v1(?)" , ejson_path , comparison_value ).Find (& results )
459
+
460
+ if err != nil {
461
+ t .Fatalf ("Could not retrieve example using comparison op: %v" , err )
462
+ }
463
+
464
+ assert .Equal (t , 1 , len (results ))
465
+ assert .Equal (t , expected_id , results [0 ].Id )
466
+ }
467
+
468
+ func TestJsonbTermsOp (t * testing.T ) {
469
+ engine := proxyEngine ()
470
+ truncateDb (engine )
471
+
472
+ jsonOne := map [string ]interface {}{
473
+ "top" : map [string ]interface {}{
474
+ "integer" : 3 ,
475
+ "float" : 1.234 ,
476
+ "string" : "some string" ,
477
+ "nums" : []int64 {1 , 2 , 3 },
478
+ },
479
+ "bottom" : "value_three" ,
480
+ }
481
+ jsonTwo := map [string ]interface {}{
482
+ "top" : map [string ]interface {}{
483
+ "integer" : 50 ,
484
+ "float" : 1.234 ,
485
+ "string" : "some string" ,
486
+ "nums" : []int64 {4 , 5 , 6 },
487
+ },
488
+ "bottom" : "value_three" ,
489
+ }
490
+ expected_id := int64 (2 )
491
+ example_one := Example {
492
+ Id : int64 (1 ),
493
+ NonEncryptedField : "sydney" ,
494
+ EncryptedTextField : "testing" ,
495
+ EncryptedIntField : 42 ,
496
+ EncryptedJsonbField : jsonOne ,
497
+ }
498
+ example_two := Example {
499
+ Id : expected_id ,
500
+ NonEncryptedField : "melbourne" ,
501
+ EncryptedIntField : 42 ,
502
+ EncryptedTextField : "someone@gmail.com" ,
503
+ EncryptedJsonbField : jsonTwo ,
504
+ }
505
+
506
+ examples := []Example {
507
+ example_one ,
508
+ example_two ,
509
+ }
510
+
511
+ inserted , err := engine .Insert (& examples )
512
+
513
+ if err != nil {
514
+ t .Errorf ("Error inserting examples: %v" , err )
515
+ }
516
+
517
+ assert .Equal (t , int64 (2 ), inserted , "Expected to insert 2 rows" )
518
+
519
+ // Serialize value as jsonb
520
+ value := 5
521
+ comparison_value , err := goeql .JsonbQuery (value , "examples" , "encrypted_jsonb_field" )
522
+ if err != nil {
523
+ log .Fatalf ("Error marshaling comparison value: %v" , err )
524
+ }
525
+ // Serialize path
526
+ path := "$.top.nums[*]"
527
+ ejson_path , err := goeql .EJsonPathQuery (path , "examples" , "encrypted_jsonb_field" )
528
+
529
+ sql := `SELECT * from examples e
530
+ WHERE EXISTS (
531
+ SELECT 1
532
+ FROM unnest(cs_ste_vec_terms_v1(e.encrypted_jsonb_field, ?)) AS term
533
+ WHERE term > cs_ste_vec_term_v1(?)
534
+ )`
535
+
536
+ if err != nil {
537
+ log .Fatalf ("Error serializing encrypted_jsonb_field query: %v" , err )
538
+ }
539
+ t .Skip ("TODO: Fix failing test due to issue with cllw ore" )
540
+ results , err := engine .Query (sql , ejson_path , comparison_value )
541
+ if err != nil {
542
+ t .Fatalf ("Could not retrieve example using terms: %v" , err )
543
+ }
544
+
545
+ assert .Equal (t , 1 , len (results ))
546
+ }
547
+
311
548
func TestOreStringRangeQuery (t * testing.T ) {
312
549
engine := proxyEngine ()
313
550
truncateDb (engine )
@@ -513,3 +750,14 @@ func TestUniqueStringQuery(t *testing.T) {
513
750
514
751
assert .Equal (t , expected , returnedExample .EncryptedTextField , "EncryptedText field should match" )
515
752
}
753
+
754
+ func generateJsonbData (value_one string , value_two string , value_three string ) map [string ]any {
755
+ data := map [string ]any {
756
+ "top" : map [string ]any {
757
+ "nested" : []any {value_one , value_two },
758
+ },
759
+ "bottom" : value_three ,
760
+ }
761
+
762
+ return data
763
+ }
0 commit comments