Skip to content

Commit 23733c0

Browse files
authored
Merge pull request #26 from cipherstash/feat/update-json-payload-query-support
Update json payload query support
2 parents b89c198 + b76f6ef commit 23733c0

File tree

6 files changed

+161
-67
lines changed

6 files changed

+161
-67
lines changed

languages/go/goeql/goeql.go

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type EncryptedColumn struct {
2929
P string `json:"p"`
3030
I TableColumn `json:"i"`
3131
V int `json:"v"`
32+
Q string `json:"q"`
3233
}
3334

3435
// EncryptedText is a string value to be encrypted
@@ -149,9 +150,29 @@ func (eb *EncryptedBool) Deserialize(data []byte) (EncryptedBool, error) {
149150
return false, fmt.Errorf("invalid format: missing 'p' field")
150151
}
151152

152-
// SerializeQuery produces a jsonb payload used by EQL query functions to perform search operations like equality checks, range queries, and unique constraints.
153-
func SerializeQuery(value any, table string, column string) ([]byte, error) {
154-
query, err := ToEncryptedColumn(value, table, column)
153+
// MatchQuery serializes a plaintext value used in a match query
154+
func MatchQuery(value any, table string, column string) ([]byte, error) {
155+
return serializeQuery(value, table, column, "match")
156+
}
157+
158+
// OreQuery serializes a plaintext value used in an ore query
159+
func OreQuery(value any, table string, column string) ([]byte, error) {
160+
return serializeQuery(value, table, column, "ore")
161+
}
162+
163+
// UniqueQuery serializes a plaintext value used in a unique query
164+
func UniqueQuery(value any, table string, column string) ([]byte, error) {
165+
return serializeQuery(value, table, column, "unique")
166+
}
167+
168+
// JsonbQuery serializes a plaintext value used in a jsonb query
169+
func JsonbQuery(value any, table string, column string) ([]byte, error) {
170+
return serializeQuery(value, table, column, "ste_vec")
171+
}
172+
173+
// serializeQuery produces a jsonb payload used by EQL query functions to perform search operations like equality checks, range queries, and unique constraints.
174+
func serializeQuery(value any, table string, column string, queryType string) ([]byte, error) {
175+
query, err := ToEncryptedColumn(value, table, column, queryType)
155176
if err != nil {
156177
return nil, fmt.Errorf("error converting to EncryptedColumn: %v", err)
157178
}
@@ -165,14 +186,15 @@ func SerializeQuery(value any, table string, column string) ([]byte, error) {
165186
}
166187

167188
// ToEncryptedColumn converts a plaintext value to a string, and returns the EncryptedColumn struct for inserting into a database.
168-
func ToEncryptedColumn(value any, table string, column string) (EncryptedColumn, error) {
189+
func ToEncryptedColumn(value any, table string, column string, queryType ...string) (EncryptedColumn, error) {
169190
str, err := convertToString(value)
170191
if err != nil {
171192
return EncryptedColumn{}, fmt.Errorf("error: %v", err)
172193
}
173-
174194
data := EncryptedColumn{K: "pt", P: str, I: TableColumn{T: table, C: column}, V: 1}
175-
195+
if queryType != nil {
196+
data.Q = queryType[0]
197+
}
176198
return data, nil
177199
}
178200

languages/go/goeql/goeql_test.go

Lines changed: 95 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -210,34 +210,105 @@ func TestEncryptedBool_Deserialize(t *testing.T) {
210210
}
211211
}
212212

213-
// Test SerializeQuery Function
214-
func TestSerializeQuery(t *testing.T) {
215-
tests := []struct {
216-
value interface{}
217-
table string
218-
column string
219-
expectedP string
220-
}{
221-
{value: "test_string", table: "table1", column: "column1", expectedP: "test_string"},
222-
{value: 123, table: "table2", column: "column2", expectedP: "123"},
223-
{value: true, table: "table3", column: "column3", expectedP: "true"},
224-
{value: map[string]interface{}{"key": "value"}, table: "table4", column: "column4", expectedP: `{"key":"value"}`},
213+
func TestMatchQuerySerialization(t *testing.T) {
214+
value := "test_string"
215+
table := "table1"
216+
column := "column1"
217+
expectedP := "test_string"
218+
expectedQ := "match"
219+
220+
serializedData, err := MatchQuery(value, table, column)
221+
if err != nil {
222+
t.Fatalf("SerializeQuery returned error: %v", err)
225223
}
226224

227-
for _, tt := range tests {
228-
serializedData, err := SerializeQuery(tt.value, tt.table, tt.column)
229-
if err != nil {
230-
t.Fatalf("SerializeQuery returned error: %v", err)
231-
}
225+
var ec EncryptedColumn
226+
if err := json.Unmarshal(serializedData, &ec); err != nil {
227+
t.Fatalf("Error unmarshaling serialized data: %v", err)
228+
}
232229

233-
var ec EncryptedColumn
234-
if err := json.Unmarshal(serializedData, &ec); err != nil {
235-
t.Fatalf("Error unmarshaling serialized data: %v", err)
236-
}
230+
if ec.P != expectedP {
231+
t.Errorf("Expected P to be '%s', got '%s'", expectedP, ec.P)
232+
}
237233

238-
if ec.P != tt.expectedP {
239-
t.Errorf("Expected P to be '%s', got '%s'", tt.expectedP, ec.P)
240-
}
234+
if ec.Q != expectedQ {
235+
t.Errorf("Expected Q to be '%s', got '%s'", expectedQ, ec.Q)
236+
}
237+
}
238+
func TestOreQuerySerialization(t *testing.T) {
239+
value := 123
240+
table := "table1"
241+
column := "column1"
242+
expectedP := "123"
243+
expectedQ := "ore"
244+
245+
serializedData, err := OreQuery(value, table, column)
246+
if err != nil {
247+
t.Fatalf("SerializeQuery returned error: %v", err)
248+
}
249+
250+
var ec EncryptedColumn
251+
if err := json.Unmarshal(serializedData, &ec); err != nil {
252+
t.Fatalf("Error unmarshaling serialized data: %v", err)
253+
}
254+
255+
if ec.P != expectedP {
256+
t.Errorf("Expected P to be '%s', got '%s'", expectedP, ec.P)
257+
}
258+
259+
if ec.Q != expectedQ {
260+
t.Errorf("Expected Q to be '%s', got '%s'", expectedQ, ec.Q)
261+
}
262+
}
263+
264+
func TestUniqueQuerySerialization(t *testing.T) {
265+
value := true
266+
table := "table1"
267+
column := "column1"
268+
expectedP := "true"
269+
expectedQ := "unique"
270+
271+
serializedData, err := UniqueQuery(value, table, column)
272+
if err != nil {
273+
t.Fatalf("SerializeQuery returned error: %v", err)
274+
}
275+
276+
var ec EncryptedColumn
277+
if err := json.Unmarshal(serializedData, &ec); err != nil {
278+
t.Fatalf("Error unmarshaling serialized data: %v", err)
279+
}
280+
281+
if ec.P != expectedP {
282+
t.Errorf("Expected P to be '%s', got '%s'", expectedP, ec.P)
283+
}
284+
285+
if ec.Q != expectedQ {
286+
t.Errorf("Expected Q to be '%s', got '%s'", expectedQ, ec.Q)
287+
}
288+
}
289+
290+
func TestJsonbQuerySerialization(t *testing.T) {
291+
value := map[string]interface{}{"key": "value"}
292+
table := "table1"
293+
column := "column1"
294+
expectedP := `{"key":"value"}`
295+
expectedQ := "ste_vec"
296+
297+
serializedData, err := JsonbQuery(value, table, column)
298+
if err != nil {
299+
t.Fatalf("SerializeQuery returned error: %v", err)
300+
}
301+
302+
var ec EncryptedColumn
303+
if err := json.Unmarshal(serializedData, &ec); err != nil {
304+
t.Fatalf("Error unmarshaling serialized data: %v", err)
305+
}
306+
307+
if ec.P != expectedP {
308+
t.Errorf("Expected P to be '%s', got '%s'", expectedP, ec.P)
309+
}
310+
if ec.Q != expectedQ {
311+
t.Errorf("Expected Q to be '%s', got '%s'", expectedQ, ec.Q)
241312
}
242313
}
243314

languages/go/xorm/e2e_test.go

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ func TestWhereQueryOnUnencryptedColumn(t *testing.T) {
5151
t.Fatalf("Could not insert new example: %v", err)
5252
}
5353

54-
var example Example
54+
var returnedExample Example
5555
text := "sydney"
5656

57-
has, err := engine.Where("non_encrypted_field = ?", text).Get(&example)
57+
has, err := engine.Where("non_encrypted_field = ?", text).Get(&returnedExample)
5858
if err != nil {
5959
t.Fatalf("Could not retrieve example: %v", err)
6060
}
@@ -63,10 +63,10 @@ func TestWhereQueryOnUnencryptedColumn(t *testing.T) {
6363
t.Errorf("Expected has to equal true, got: %v", has)
6464
}
6565

66-
assert.Equal(t, newExample.NonEncryptedField, example.NonEncryptedField, "NonEncryptedField does not match")
67-
assert.Equal(t, newExample.EncryptedIntField, example.EncryptedIntField, "EncryptedIntField does not match")
68-
assert.Equal(t, newExample.EncryptedTextField, example.EncryptedTextField, "EncryptedTextField does not match")
69-
assert.Equal(t, newExample.EncryptedJsonbField, example.EncryptedJsonbField, "EncryptedJsonbField does not match")
66+
assert.Equal(t, newExample.NonEncryptedField, returnedExample.NonEncryptedField, "NonEncryptedField does not match")
67+
assert.Equal(t, newExample.EncryptedIntField, returnedExample.EncryptedIntField, "EncryptedIntField does not match")
68+
assert.Equal(t, newExample.EncryptedTextField, returnedExample.EncryptedTextField, "EncryptedTextField does not match")
69+
assert.Equal(t, newExample.EncryptedJsonbField, returnedExample.EncryptedJsonbField, "EncryptedJsonbField does not match")
7070
}
7171

7272
func TestMatchQueryLongString(t *testing.T) {
@@ -82,6 +82,12 @@ func TestMatchQueryLongString(t *testing.T) {
8282
}
8383

8484
examples := []Example{
85+
{
86+
NonEncryptedField: "brisbane",
87+
EncryptedIntField: 23,
88+
EncryptedTextField: "another string that shouldn't be returned",
89+
EncryptedJsonbField: jsonData,
90+
},
8591
{
8692
NonEncryptedField: "sydney",
8793
EncryptedIntField: 23,
@@ -102,9 +108,9 @@ func TestMatchQueryLongString(t *testing.T) {
102108
t.Errorf("Error inserting examples: %v", err)
103109
}
104110

105-
assert.Equal(t, int64(2), inserted, "Expected to insert 2 rows")
111+
assert.Equal(t, int64(3), inserted, "Expected to insert 2 rows")
106112

107-
query, err := goeql.SerializeQuery("this", "examples", "encrypted_text_field")
113+
query, err := goeql.MatchQuery("this", "examples", "encrypted_text_field")
108114
if err != nil {
109115
log.Fatalf("Error marshaling encrypted_text_field query: %v", err)
110116
}
@@ -119,7 +125,7 @@ func TestMatchQueryLongString(t *testing.T) {
119125
t.Errorf("Expected has to equal true, got: %v", has)
120126
}
121127

122-
assert.Equal(t, returnedExample.EncryptedTextField, EncryptedTextField("this is a long string"), "EncryptedTextField should match")
128+
assert.Equal(t, EncryptedTextField("this is a long string"), returnedExample.EncryptedTextField, "EncryptedTextField should match")
123129
}
124130

125131
func TestMatchQueryEmail(t *testing.T) {
@@ -157,7 +163,7 @@ func TestMatchQueryEmail(t *testing.T) {
157163

158164
assert.Equal(t, int64(2), inserted, "Expected to insert 2 rows")
159165

160-
query, err := goeql.SerializeQuery("test", "examples", "encrypted_text_field")
166+
query, err := goeql.MatchQuery("test", "examples", "encrypted_text_field")
161167
if err != nil {
162168
log.Fatalf("Error marshaling encrypted_text_field query: %v", err)
163169
}
@@ -172,7 +178,7 @@ func TestMatchQueryEmail(t *testing.T) {
172178
t.Errorf("Expected has to equal true, got: %v", has)
173179
}
174180

175-
assert.Equal(t, returnedExample.EncryptedTextField, EncryptedTextField("testemail@test.com"), "EncryptedTextField should match")
181+
assert.Equal(t, EncryptedTextField("testemail@test.com"), returnedExample.EncryptedTextField, "EncryptedTextField should match")
176182
}
177183

178184
func TestJsonbQuerySimple(t *testing.T) {
@@ -218,7 +224,7 @@ func TestJsonbQuerySimple(t *testing.T) {
218224
},
219225
}
220226

221-
query, errTwo := goeql.SerializeQuery(jsonbQuery, "examples", "encrypted_jsonb_field")
227+
query, errTwo := goeql.JsonbQuery(jsonbQuery, "examples", "encrypted_jsonb_field")
222228
if errTwo != nil {
223229
log.Fatalf("Error marshaling encrypted_jsonb_field: %v", errTwo)
224230
}
@@ -233,7 +239,7 @@ func TestJsonbQuerySimple(t *testing.T) {
233239
t.Errorf("Expected has to equal true, got: %v", has)
234240
}
235241

236-
assert.Equal(t, returnedExample.EncryptedJsonbField, EncryptedJsonbField(expectedJson), "EncryptedJsonb field should match")
242+
assert.Equal(t, EncryptedJsonbField(expectedJson), returnedExample.EncryptedJsonbField, "EncryptedJsonb field should match")
237243
}
238244

239245
func TestJsonbQueryNested(t *testing.T) {
@@ -284,7 +290,7 @@ func TestJsonbQueryNested(t *testing.T) {
284290
},
285291
}
286292

287-
query, errTwo := goeql.SerializeQuery(jsonbQuery, "examples", "encrypted_jsonb_field")
293+
query, errTwo := goeql.JsonbQuery(jsonbQuery, "examples", "encrypted_jsonb_field")
288294
if errTwo != nil {
289295
log.Fatalf("Error marshaling encrypted_jsonb_field: %v", errTwo)
290296
}
@@ -299,7 +305,7 @@ func TestJsonbQueryNested(t *testing.T) {
299305
t.Errorf("Expected has to equal true, got: %v", has)
300306
}
301307

302-
assert.Equal(t, returnedExample.EncryptedJsonbField, EncryptedJsonbField(expectedJson), "EncryptedJsonb field should match")
308+
assert.Equal(t, EncryptedJsonbField(expectedJson), returnedExample.EncryptedJsonbField, "EncryptedJsonb field should match")
303309
}
304310

305311
func TestOreStringRangeQuery(t *testing.T) {
@@ -331,7 +337,7 @@ func TestOreStringRangeQuery(t *testing.T) {
331337
assert.Equal(t, int64(2), inserted, "Expected to insert 2 rows")
332338

333339
// Query
334-
query, errQuery := goeql.SerializeQuery("tree", "examples", "encrypted_text_field")
340+
query, errQuery := goeql.OreQuery("tree", "examples", "encrypted_text_field")
335341
if errQuery != nil {
336342
log.Fatalf("err: %v", errQuery)
337343
}
@@ -346,7 +352,7 @@ func TestOreStringRangeQuery(t *testing.T) {
346352
t.Errorf("Expected has to equal true, got: %v", has)
347353
}
348354

349-
assert.Equal(t, returnedExample.EncryptedTextField, expected, "EncryptedText field should match")
355+
assert.Equal(t, expected, returnedExample.EncryptedTextField, "EncryptedText field should match")
350356
}
351357

352358
func TestOreIntRangeQuery(t *testing.T) {
@@ -378,7 +384,7 @@ func TestOreIntRangeQuery(t *testing.T) {
378384
assert.Equal(t, int64(2), inserted, "Expected to insert 2 rows")
379385

380386
// Query
381-
query, errQuery := goeql.SerializeQuery(32, "examples", "encrypted_int_field")
387+
query, errQuery := goeql.OreQuery(32, "examples", "encrypted_int_field")
382388
if errQuery != nil {
383389
log.Fatalf("err: %v", errQuery)
384390
}
@@ -393,7 +399,7 @@ func TestOreIntRangeQuery(t *testing.T) {
393399
t.Errorf("Expected has to equal true, got: %v", has)
394400
}
395401

396-
assert.Equal(t, returnedExample.EncryptedIntField, expected, "EncryptedInt field should match")
402+
assert.Equal(t, expected, returnedExample.EncryptedIntField, "EncryptedInt field should match")
397403
}
398404

399405
func TestOreBoolRangeQuery(t *testing.T) {
@@ -434,7 +440,7 @@ func TestOreBoolRangeQuery(t *testing.T) {
434440
assert.Equal(t, int64(3), inserted, "Expected to insert 3 rows")
435441

436442
// Query
437-
query, errQuery := goeql.SerializeQuery(false, "examples", "encrypted_bool_field")
443+
query, errQuery := goeql.OreQuery(false, "examples", "encrypted_bool_field")
438444
if errQuery != nil {
439445
log.Fatalf("err: %v", errQuery)
440446
}
@@ -449,7 +455,7 @@ func TestOreBoolRangeQuery(t *testing.T) {
449455
t.Errorf("Expected has to equal true, got: %v", has)
450456
}
451457

452-
assert.Equal(t, returnedExample.EncryptedBoolField, expected, "EncryptedBool field should match")
458+
assert.Equal(t, expected, returnedExample.EncryptedBoolField, "EncryptedBool field should match")
453459
}
454460

455461
func TestUniqueStringQuery(t *testing.T) {
@@ -490,7 +496,7 @@ func TestUniqueStringQuery(t *testing.T) {
490496
assert.Equal(t, int64(3), inserted, "Expected to insert 3 rows")
491497

492498
// Query
493-
query, errQuery := goeql.SerializeQuery("testing two", "examples", "encrypted_text_field")
499+
query, errQuery := goeql.UniqueQuery("testing two", "examples", "encrypted_text_field")
494500
if errQuery != nil {
495501
log.Fatalf("err: %v", errQuery)
496502
}
@@ -505,5 +511,5 @@ func TestUniqueStringQuery(t *testing.T) {
505511
t.Errorf("Expected has to equal true, got: %v", has)
506512
}
507513

508-
assert.Equal(t, returnedExample.EncryptedTextField, expected, "EncryptedText field should match")
514+
assert.Equal(t, expected, returnedExample.EncryptedTextField, "EncryptedText field should match")
509515
}

0 commit comments

Comments
 (0)