Skip to content

Commit 51ace5d

Browse files
committed
test: selects use indexes
1 parent 430675f commit 51ace5d

File tree

10 files changed

+230
-31
lines changed

10 files changed

+230
-31
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ SELECT eql_v2.add_column('users', 'encrypted_email');
103103
After modifying configurations, activate them by running:
104104

105105
```sql
106-
SELECT eql_v2.encrypt();
107-
SELECT eql_v2.activate();
106+
SELECT eql_v2.migrate_config();
107+
SELECT eql_v2.activate_config();
108108
```
109109

110110
**Important:** These functions must be run after any modifications to the configuration.
@@ -219,8 +219,8 @@ SELECT eql_v2.add_search_config(
219219
After adding an index, you have to activate the configuration:
220220

221221
```sql
222-
SELECT eql_v2.encrypt();
223-
SELECT eql_v2.activate();
222+
SELECT eql_v2.migrate_config();
223+
SELECT eql_v2.activate_config();
224224
```
225225

226226
## Searching data with EQL

src/config/functions.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ $$ LANGUAGE plpgsql;
144144
-- Raises an exception if the configuration is already `encrypting` or if there is no `pending` configuration to encrypt.
145145
--
146146

147-
CREATE FUNCTION eql_v2.encrypt()
147+
CREATE FUNCTION eql_v2.migrate_config()
148148
RETURNS boolean
149149
AS $$
150150
BEGIN
@@ -168,7 +168,7 @@ $$ LANGUAGE plpgsql;
168168

169169

170170

171-
CREATE FUNCTION eql_v2.activate()
171+
CREATE FUNCTION eql_v2.activate_config()
172172
RETURNS boolean
173173
AS $$
174174
BEGIN

src/encryptindex/functions_test.sql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ CREATE TABLE users
155155
DO $$
156156
BEGIN
157157
PERFORM eql_v2.add_search_config('users', 'name', 'match');
158-
PERFORM eql_v2.encrypt();
158+
PERFORM eql_v2.migrate_config();
159159

160160
ASSERT (SELECT EXISTS (SELECT FROM eql_v2_configuration c WHERE c.state = 'active'));
161161
ASSERT (SELECT EXISTS (SELECT FROM eql_v2_configuration c WHERE c.state = 'encrypting'));
@@ -205,7 +205,7 @@ CREATE TABLE users
205205
DO $$
206206
BEGIN
207207
PERFORM eql_v2.add_search_config('users', 'name', 'match');
208-
PERFORM eql_v2.encrypt();
208+
PERFORM eql_v2.migrate_config();
209209

210210
ASSERT (SELECT EXISTS (SELECT FROM eql_v2_configuration c WHERE c.state = 'active'));
211211
ASSERT (SELECT EXISTS (SELECT FROM eql_v2_configuration c WHERE c.state = 'encrypting'));
@@ -256,8 +256,8 @@ DO $$
256256
BEGIN
257257
PERFORM eql_v2.add_search_config('users', 'name', 'match');
258258

259-
PERFORM eql_v2.encrypt(); -- need to encrypt first
260-
PERFORM eql_v2.activate();
259+
PERFORM eql_v2.migrate_config(); -- need to encrypt first
260+
PERFORM eql_v2.activate_config();
261261

262262
ASSERT (SELECT EXISTS (SELECT FROM eql_v2_configuration c WHERE c.state = 'active'));
263263
ASSERT (SELECT EXISTS (SELECT FROM eql_v2_configuration c WHERE c.state = 'inactive'));

src/hmac_256/functions.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,27 @@ AS $$
1616
$$ LANGUAGE plpgsql;
1717

1818

19+
CREATE FUNCTION eql_v2.has_hmac_256(val jsonb)
20+
RETURNS boolean
21+
IMMUTABLE STRICT PARALLEL SAFE
22+
AS $$
23+
BEGIN
24+
RETURN val ? 'hm';
25+
END;
26+
$$ LANGUAGE plpgsql;
27+
28+
29+
CREATE FUNCTION eql_v2.has_hmac_256(val eql_v2_encrypted)
30+
RETURNS boolean
31+
IMMUTABLE STRICT PARALLEL SAFE
32+
AS $$
33+
BEGIN
34+
RETURN eql_v2.has_hmac_256(val.data);
35+
END;
36+
$$ LANGUAGE plpgsql;
37+
38+
39+
1940
-- extracts hmac_256 index from an encrypted column
2041

2142
CREATE FUNCTION eql_v2.hmac_256(val eql_v2_encrypted)

src/hmac_256/functions_test.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,15 @@ DO $$
1212

1313
END;
1414
$$ LANGUAGE plpgsql;
15+
16+
17+
DO $$
18+
DECLARE
19+
e eql_v2_encrypted;
20+
BEGIN
21+
e := create_encrypted_json(1, 'hm');
22+
23+
ASSERT eql_v2.has_hmac_256(e);
24+
END;
25+
$$ LANGUAGE plpgsql;
26+

src/operators/operator_class.sql

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,43 @@
1010
-- REQUIRE: src/operators/>.sql
1111

1212

13+
--
14+
-- Compare two eql_v2_encrypted values
15+
-- Uses `ore_block_u64_8_256` or `has_hmac_256` index terms for comparison if defined on ONE of the compared value
16+
--
17+
-- Important note: order of term operations is reversed
18+
-- In equality operations, `has_hmac_256` is preferred as it reduces to a text comparison and is more efficient
19+
-- As compare is used for ordering, `ore_block_u64_8_256` provides more complete ordering and is checked first.
20+
--
21+
--
1322
CREATE FUNCTION eql_v2.compare(a eql_v2_encrypted, b eql_v2_encrypted)
1423
RETURNS integer
1524
IMMUTABLE STRICT PARALLEL SAFE
25+
AS $$
26+
BEGIN
27+
28+
-- PERFORM eql_v2.log('eql_v2.has_hmac_256(a)', eql_v2.has_hmac_256(a)::text);
29+
-- PERFORM eql_v2.log('eql_v2.has_hmac_256(b)', eql_v2.has_hmac_256(b)::text);
30+
-- PERFORM eql_v2.log('eql_v2.has_ore_block_u64_8_256(b)', eql_v2.has_ore_block_u64_8_256(b)::text);
31+
-- PERFORM eql_v2.log('eql_v2.has_ore_block_u64_8_256(b)', eql_v2.has_ore_block_u64_8_256(b)::text);
32+
33+
IF eql_v2.has_ore_block_u64_8_256(a) OR eql_v2.has_ore_block_u64_8_256(b) THEN
34+
RETURN eql_v2.compare_ore_block_u64_8_256(a, b);
35+
END IF;
36+
37+
IF eql_v2.has_hmac_256(a) OR eql_v2.has_hmac_256(b) THEN
38+
RETURN eql_v2.compare_hmac(a, b);
39+
END IF;
40+
41+
RAISE 'Expected an hmac_256 (hm) or ore_block_u64_8_256 (ob) value in json: %', val;
42+
END;
43+
$$ LANGUAGE plpgsql;
44+
45+
--------------------
46+
47+
CREATE FUNCTION eql_v2.compare_ore_block_u64_8_256(a eql_v2_encrypted, b eql_v2_encrypted)
48+
RETURNS integer
49+
IMMUTABLE STRICT PARALLEL SAFE
1650
AS $$
1751
DECLARE
1852
a_ore eql_v2.ore_block_u64_8_256;
@@ -38,20 +72,9 @@ AS $$
3872
END;
3973
$$ LANGUAGE plpgsql;
4074

41-
CREATE OPERATOR FAMILY eql_v2.encrypted_operator USING btree;
42-
43-
CREATE OPERATOR CLASS eql_v2.encrypted_operator DEFAULT FOR TYPE eql_v2_encrypted USING btree FAMILY eql_v2.encrypted_operator AS
44-
OPERATOR 1 <,
45-
OPERATOR 2 <=,
46-
OPERATOR 3 =,
47-
OPERATOR 4 >=,
48-
OPERATOR 5 >,
49-
FUNCTION 1 eql_v2.compare(a eql_v2_encrypted, b eql_v2_encrypted);
50-
5175

5276
--------------------
5377

54-
5578
CREATE FUNCTION eql_v2.compare_hmac(a eql_v2_encrypted, b eql_v2_encrypted)
5679
RETURNS integer
5780
IMMUTABLE STRICT PARALLEL SAFE
@@ -80,13 +103,40 @@ AS $$
80103
$$ LANGUAGE plpgsql;
81104

82105

83-
CREATE OPERATOR FAMILY eql_v2.encrypted_hmac_256_operator USING btree;
106+
--------------------
84107

85-
CREATE OPERATOR CLASS eql_v2.encrypted_hmac_256_operator FOR TYPE eql_v2_encrypted USING btree FAMILY eql_v2.encrypted_hmac_256_operator AS
108+
CREATE OPERATOR FAMILY eql_v2.encrypted_operator USING btree;
109+
110+
CREATE OPERATOR CLASS eql_v2.encrypted_operator DEFAULT FOR TYPE eql_v2_encrypted USING btree FAMILY eql_v2.encrypted_operator AS
86111
OPERATOR 1 <,
87112
OPERATOR 2 <=,
88113
OPERATOR 3 =,
89114
OPERATOR 4 >=,
90115
OPERATOR 5 >,
91-
FUNCTION 1 eql_v2.compare_hmac(a eql_v2_encrypted, b eql_v2_encrypted);
116+
FUNCTION 1 eql_v2.compare(a eql_v2_encrypted, b eql_v2_encrypted);
117+
118+
119+
--------------------
120+
121+
-- CREATE OPERATOR FAMILY eql_v2.encrypted_operator_ore_block_u64_8_256 USING btree;
122+
123+
-- CREATE OPERATOR CLASS eql_v2.encrypted_operator_ore_block_u64_8_256 FOR TYPE eql_v2_encrypted USING btree FAMILY eql_v2.encrypted_operator_ore_block_u64_8_256 AS
124+
-- OPERATOR 1 <,
125+
-- OPERATOR 2 <=,
126+
-- OPERATOR 3 =,
127+
-- OPERATOR 4 >=,
128+
-- OPERATOR 5 >,
129+
-- FUNCTION 1 eql_v2.compare_ore_block_u64_8_256(a eql_v2_encrypted, b eql_v2_encrypted);
130+
131+
-- --------------------
132+
133+
-- CREATE OPERATOR FAMILY eql_v2.encrypted_hmac_256_operator USING btree;
134+
135+
-- CREATE OPERATOR CLASS eql_v2.encrypted_hmac_256_operator FOR TYPE eql_v2_encrypted USING btree FAMILY eql_v2.encrypted_hmac_256_operator AS
136+
-- OPERATOR 1 <,
137+
-- OPERATOR 2 <=,
138+
-- OPERATOR 3 =,
139+
-- OPERATOR 4 >=,
140+
-- OPERATOR 5 >,
141+
-- FUNCTION 1 eql_v2.compare_hmac(a eql_v2_encrypted, b eql_v2_encrypted);
92142

src/operators/operator_class_test.sql

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,77 @@ DO $$
5858
END;
5959
$$ LANGUAGE plpgsql;
6060

61+
SELECT * FROM encrypted;
62+
63+
--
64+
-- ORE GROUP BY
65+
--
66+
DO $$
67+
DECLARE
68+
ore_term eql_v2_encrypted;
69+
result text;
70+
BEGIN
71+
72+
PERFORM create_table_with_encrypted();
73+
74+
EXECUTE 'EXPLAIN ANALYZE SELECT e::jsonb FROM encrypted WHERE e = ''("{\"hm\": \"abc\"}")'';' into result;
75+
76+
PERFORM eql_v2.log('', result);
77+
78+
IF position('Bitmap Heap Scan on encrypted' in result) > 0 THEN
79+
RAISE EXCEPTION 'Unexpected Bitmap Heap Scan: %', result;
80+
ELSE
81+
ASSERT true;
82+
END IF;
83+
84+
EXECUTE 'EXPLAIN ANALYZE SELECT e::jsonb FROM encrypted WHERE e = ''("{\"ob\": \"abc\"}")'';' into result;
85+
86+
PERFORM eql_v2.log('', result);
87+
88+
IF position('Bitmap Heap Scan on encrypted' in result) > 0 THEN
89+
RAISE EXCEPTION 'Unexpected Bitmap Heap Scan: %', result;
90+
ELSE
91+
ASSERT true;
92+
END IF;
93+
94+
95+
-- Add index
96+
CREATE INDEX ON encrypted (e);
97+
98+
EXECUTE 'EXPLAIN ANALYZE SELECT e::jsonb FROM encrypted WHERE e = ''("{\"hm\": \"abc\"}")'';' into result;
99+
100+
PERFORM eql_v2.log(result);
101+
102+
IF position('Bitmap Heap Scan on encrypted' in result) > 0 THEN
103+
ASSERT true;
104+
ELSE
105+
RAISE EXCEPTION 'Expected Bitmap Heap Scan: %', result;
106+
END IF;
107+
108+
PERFORM seed_encrypted_json();
109+
110+
SELECT ore.e FROM ore WHERE id = 42 INTO ore_term;
111+
EXECUTE format('EXPLAIN ANALYZE SELECT e::jsonb FROM encrypted WHERE e = %L::eql_v2_encrypted;', ore_term) into result;
112+
113+
PERFORM eql_v2.log(result);
114+
115+
IF position('Bitmap Heap Scan on encrypted' in result) > 0 THEN
116+
ASSERT true;
117+
ELSE
118+
RAISE EXCEPTION 'Expected Bitmap Heap Scan: %', result;
119+
END IF;
120+
121+
122+
-- ---
123+
-- EXECUTE 'EXPLAIN ANALYZE SELECT e::jsonb FROM encrypted WHERE e = ''("{\"blah\": \"vtha\"}")'';' into result;
124+
125+
-- IF position('Bitmap Heap Scan on encrypted' in result) > 0 THEN
126+
-- ASSERT true;
127+
-- ELSE
128+
-- RAISE EXCEPTION 'Expected Bitmap Heap Scan: %', result;
129+
-- END IF;
130+
131+
END;
132+
$$ LANGUAGE plpgsql;
61133

62134
SELECT drop_table_with_encrypted();

src/ore_block_u64_8_256/functions.sql

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
-- REQUIRE: src/schema.sql
2+
-- REQUIRE: src/crypto.sql
23
-- REQUIRE: src/encrypted/types.sql
34
-- REQUIRE: src/encrypted/functions.sql
45
-- REQUIRE: src/ore_block_u64_8_256/types.sql
56

67

7-
88
-- Casts a jsonb array of hex-encoded strings to the `ore_block_u64_8_256` composite type.
99
-- In other words, this function takes the ORE index format sent through in the
1010
-- EQL payload from Proxy and decodes it as the composite type that we use for
@@ -78,6 +78,29 @@ AS $$
7878
$$ LANGUAGE plpgsql;
7979

8080

81+
--
82+
-- Checks if val contains an ore_block_u64_8_256 search term
83+
--
84+
CREATE FUNCTION eql_v2.has_ore_block_u64_8_256(val jsonb)
85+
RETURNS boolean
86+
IMMUTABLE STRICT PARALLEL SAFE
87+
AS $$
88+
BEGIN
89+
RETURN val ? 'ob';
90+
END;
91+
$$ LANGUAGE plpgsql;
92+
93+
94+
CREATE FUNCTION eql_v2.has_ore_block_u64_8_256(val eql_v2_encrypted)
95+
RETURNS boolean
96+
IMMUTABLE STRICT PARALLEL SAFE
97+
AS $$
98+
BEGIN
99+
RETURN eql_v2.has_ore_block_u64_8_256(val.data);
100+
END;
101+
$$ LANGUAGE plpgsql;
102+
103+
81104
-- This function uses lexicographic comparison
82105

83106
CREATE FUNCTION eql_v2.compare_ore_block_u64_8_256(a eql_v2.ore_block_u64_8_256, b eql_v2.ore_block_u64_8_256)
@@ -97,6 +120,8 @@ AS $$
97120
eq boolean := true;
98121
unequal_block smallint := 0;
99122
hash_key bytea;
123+
data_block bytea;
124+
encrypt_block bytea;
100125
target_block bytea;
101126

102127
left_block_size CONSTANT smallint := 16;
@@ -150,13 +175,18 @@ AS $$
150175
-- first right block is at right offset + nonce_size (ordinally indexed)
151176
target_block := substr(b.bytes, right_offset + 17 + (unequal_block * right_block_size), right_block_size);
152177

178+
data_block := substr(a.bytes, 9 + (left_block_size * unequal_block), left_block_size);
179+
180+
-- PERFORM eql_v2.log('substr', data_block::text);
181+
-- PERFORM eql_v2.log('hash_key', hash_key::text);
182+
-- PERFORM eql_v2.log('data_block', pg_typeof(data_block)::text);
183+
-- PERFORM eql_v2.log('hash_key', pg_typeof(hash_key)::text);
184+
185+
encrypt_block := public.encrypt(data_block::bytea, hash_key::bytea, 'aes-ecb');
186+
153187
indicator := (
154188
get_bit(
155-
encrypt(
156-
substr(a.bytes, 9 + (left_block_size * unequal_block), left_block_size),
157-
hash_key,
158-
'aes-ecb'
159-
),
189+
encrypt_block,
160190
0
161191
) + get_bit(target_block, get_byte(a.bytes, unequal_block))) % 2;
162192

src/ore_block_u64_8_256/functions_test.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,21 @@ DO $$
1212
END;
1313
$$ LANGUAGE plpgsql;
1414

15+
16+
17+
DO $$
18+
DECLARE
19+
ore_term eql_v2_encrypted;
20+
BEGIN
21+
SELECT ore.e FROM ore WHERE id = 42 INTO ore_term;
22+
23+
ASSERT eql_v2.has_ore_block_u64_8_256(ore_term);
24+
25+
END;
26+
$$ LANGUAGE plpgsql;
27+
28+
29+
1530
--
1631
-- ORE - ORDER BY ore_block_u64_8_256(eql_v2_encrypted)
1732
--

0 commit comments

Comments
 (0)