Skip to content

Commit 8564572

Browse files
authored
Merge pull request #86 from cipherstash/operator-please
ORE Operators and Sorting
2 parents 01dcc24 + eea9365 commit 8564572

10 files changed

+435
-1033
lines changed

sql/000-ore.sql

Lines changed: 41 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
CREATE EXTENSION IF NOT EXISTS pgcrypto;
22

3-
CREATE TYPE ore_64_8_v1_term AS (
4-
bytes bytea
5-
);
6-
7-
CREATE TYPE ore_64_8_v1 AS (
8-
terms ore_64_8_v1_term[]
9-
);
3+
CREATE DOMAIN ore_64_8_index_v1 AS bytea[];
104

11-
DROP FUNCTION IF EXISTS compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term);
5+
DROP FUNCTION IF EXISTS compare_ore_64_8_v1_term(a bytea, b bytea);
126

13-
CREATE FUNCTION compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term) returns integer AS $$
7+
CREATE FUNCTION compare_ore_64_8_v1_term(a bytea, b bytea) returns integer AS $$
148
DECLARE
159
eq boolean := true;
1610
unequal_block smallint := 0;
@@ -35,7 +29,7 @@ CREATE FUNCTION compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term)
3529
RETURN 1;
3630
END IF;
3731

38-
IF bit_length(a.bytes) != bit_length(b.bytes) THEN
32+
IF bit_length(a) != bit_length(b) THEN
3933
RAISE EXCEPTION 'Ciphertexts are different lengths';
4034
END IF;
4135

@@ -47,8 +41,8 @@ CREATE FUNCTION compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term)
4741
-- * We are not worrying about timing attacks here; don't fret about
4842
-- the OR or !=.
4943
IF
50-
substr(a.bytes, 1 + block, 1) != substr(b.bytes, 1 + block, 1)
51-
OR substr(a.bytes, 9 + left_block_size * block, left_block_size) != substr(b.bytes, 9 + left_block_size * BLOCK, left_block_size)
44+
substr(a, 1 + block, 1) != substr(b, 1 + block, 1)
45+
OR substr(a, 9 + left_block_size * block, left_block_size) != substr(b, 9 + left_block_size * BLOCK, left_block_size)
5246
THEN
5347
-- set the first unequal block we find
5448
IF eq THEN
@@ -63,20 +57,20 @@ CREATE FUNCTION compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term)
6357
END IF;
6458

6559
-- Hash key is the IV from the right CT of b
66-
hash_key := substr(b.bytes, right_offset + 1, 16);
60+
hash_key := substr(b, right_offset + 1, 16);
6761

6862
-- first right block is at right offset + nonce_size (ordinally indexed)
69-
target_block := substr(b.bytes, right_offset + 17 + (unequal_block * right_block_size), right_block_size);
63+
target_block := substr(b, right_offset + 17 + (unequal_block * right_block_size), right_block_size);
7064

7165
indicator := (
7266
get_bit(
7367
encrypt(
74-
substr(a.bytes, 9 + (left_block_size * unequal_block), left_block_size),
68+
substr(a, 9 + (left_block_size * unequal_block), left_block_size),
7569
hash_key,
7670
'aes-ecb'
7771
),
7872
0
79-
) + get_bit(target_block, get_byte(a.bytes, unequal_block))) % 2;
73+
) + get_bit(target_block, get_byte(a, unequal_block))) % 2;
8074

8175
IF indicator = 1 THEN
8276
RETURN 1::integer;
@@ -87,169 +81,34 @@ CREATE FUNCTION compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term)
8781
$$ LANGUAGE plpgsql;
8882

8983

90-
DROP FUNCTION IF EXISTS ore_64_8_v1_term_eq(a ore_64_8_v1_term, b ore_64_8_v1_term);
91-
92-
CREATE FUNCTION ore_64_8_v1_term_eq(a ore_64_8_v1_term, b ore_64_8_v1_term)
93-
RETURNS boolean AS $$
94-
SELECT compare_ore_64_8_v1_term(a, b) = 0
95-
$$ LANGUAGE SQL;
96-
97-
98-
DROP FUNCTION IF EXISTS ore_64_8_v1_term_neq(a ore_64_8_v1_term, b ore_64_8_v1_term);
99-
100-
CREATE FUNCTION ore_64_8_v1_term_neq(a ore_64_8_v1_term, b ore_64_8_v1_term)
101-
RETURNS boolean AS $$
102-
SELECT compare_ore_64_8_v1_term(a, b) <> 0
103-
$$ LANGUAGE SQL;
104-
105-
106-
DROP FUNCTION IF EXISTS ore_64_8_v1_term_lt(a ore_64_8_v1_term, b ore_64_8_v1_term);
107-
108-
CREATE FUNCTION ore_64_8_v1_term_lt(a ore_64_8_v1_term, b ore_64_8_v1_term)
109-
RETURNS boolean AS $$
110-
SELECT compare_ore_64_8_v1_term(a, b) = -1
111-
$$ LANGUAGE SQL;
112-
113-
114-
DROP FUNCTION IF EXISTS ore_64_8_v1_term_lte(a ore_64_8_v1_term, b ore_64_8_v1_term);
115-
116-
CREATE FUNCTION ore_64_8_v1_term_lte(a ore_64_8_v1_term, b ore_64_8_v1_term)
117-
RETURNS boolean AS $$
118-
SELECT compare_ore_64_8_v1_term(a, b) != 1
119-
$$ LANGUAGE SQL;
120-
121-
122-
DROP FUNCTION IF EXISTS ore_64_8_v1_term_gt(a ore_64_8_v1_term, b ore_64_8_v1_term);
123-
124-
CREATE FUNCTION ore_64_8_v1_term_gt(a ore_64_8_v1_term, b ore_64_8_v1_term)
125-
RETURNS boolean AS $$
126-
SELECT compare_ore_64_8_v1_term(a, b) = 1
127-
$$ LANGUAGE SQL;
128-
129-
130-
DROP FUNCTION IF EXISTS ore_64_8_v1_term_gte(a ore_64_8_v1_term, b ore_64_8_v1_term);
131-
132-
CREATE FUNCTION ore_64_8_v1_term_gte(a ore_64_8_v1_term, b ore_64_8_v1_term)
133-
RETURNS boolean AS $$
134-
SELECT compare_ore_64_8_v1_term(a, b) != -1
135-
$$ LANGUAGE SQL;
136-
137-
138-
DROP OPERATOR IF EXISTS = (ore_64_8_v1_term, ore_64_8_v1_term);
139-
140-
CREATE OPERATOR = (
141-
PROCEDURE="ore_64_8_v1_term_eq",
142-
LEFTARG=ore_64_8_v1_term,
143-
RIGHTARG=ore_64_8_v1_term,
144-
NEGATOR = <>,
145-
RESTRICT = eqsel,
146-
JOIN = eqjoinsel,
147-
HASHES,
148-
MERGES
149-
);
150-
151-
152-
DROP OPERATOR IF EXISTS <> (ore_64_8_v1_term, ore_64_8_v1_term);
153-
154-
CREATE OPERATOR <> (
155-
PROCEDURE="ore_64_8_v1_term_neq",
156-
LEFTARG=ore_64_8_v1_term,
157-
RIGHTARG=ore_64_8_v1_term,
158-
NEGATOR = =,
159-
RESTRICT = eqsel,
160-
JOIN = eqjoinsel,
161-
HASHES,
162-
MERGES
163-
);
164-
165-
DROP OPERATOR IF EXISTS > (ore_64_8_v1_term, ore_64_8_v1_term);
166-
167-
CREATE OPERATOR > (
168-
PROCEDURE="ore_64_8_v1_term_gt",
169-
LEFTARG=ore_64_8_v1_term,
170-
RIGHTARG=ore_64_8_v1_term,
171-
COMMUTATOR = <,
172-
NEGATOR = <=,
173-
RESTRICT = scalargtsel,
174-
JOIN = scalargtjoinsel
175-
);
176-
177-
DROP OPERATOR IF EXISTS < (ore_64_8_v1_term, ore_64_8_v1_term);
178-
179-
CREATE OPERATOR < (
180-
PROCEDURE="ore_64_8_v1_term_lt",
181-
LEFTARG=ore_64_8_v1_term,
182-
RIGHTARG=ore_64_8_v1_term,
183-
COMMUTATOR = >,
184-
NEGATOR = >=,
185-
RESTRICT = scalarltsel,
186-
JOIN = scalarltjoinsel
187-
);
188-
189-
DROP OPERATOR IF EXISTS <= (ore_64_8_v1_term, ore_64_8_v1_term);
190-
191-
CREATE OPERATOR <= (
192-
PROCEDURE="ore_64_8_v1_term_lte",
193-
LEFTARG=ore_64_8_v1_term,
194-
RIGHTARG=ore_64_8_v1_term,
195-
COMMUTATOR = >=,
196-
NEGATOR = >,
197-
RESTRICT = scalarlesel,
198-
JOIN = scalarlejoinsel
199-
);
200-
201-
DROP OPERATOR IF EXISTS >= (ore_64_8_v1_term, ore_64_8_v1_term);
202-
203-
CREATE OPERATOR >= (
204-
PROCEDURE="ore_64_8_v1_term_gte",
205-
LEFTARG=ore_64_8_v1_term,
206-
RIGHTARG=ore_64_8_v1_term,
207-
COMMUTATOR = <=,
208-
NEGATOR = <,
209-
RESTRICT = scalarlesel,
210-
JOIN = scalarlejoinsel
211-
);
212-
213-
DROP OPERATOR FAMILY IF EXISTS ore_64_8_v1_term_btree_ops USING btree;
214-
215-
CREATE OPERATOR FAMILY ore_64_8_v1_term_btree_ops USING btree;
216-
217-
218-
DROP OPERATOR CLASS IF EXISTS ore_64_8_v1_term_btree_ops USING btree;
219-
220-
CREATE OPERATOR CLASS ore_64_8_v1_term_btree_ops DEFAULT FOR TYPE ore_64_8_v1_term USING btree FAMILY ore_64_8_v1_term_btree_ops AS
221-
OPERATOR 1 <,
222-
OPERATOR 2 <=,
223-
OPERATOR 3 =,
224-
OPERATOR 4 >=,
225-
OPERATOR 5 >,
226-
FUNCTION 1 compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term);
227-
22884
-- Compare the "head" of each array and recurse if necessary
22985
-- This function assumes an empty string is "less than" everything else
23086
-- so if a is empty we return -1, if be is empty and a isn't, we return 1.
23187
-- If both are empty we return 0. This cases probably isn't necessary as equality
23288
-- doesn't always make sense but it's here for completeness.
23389
-- If both are non-empty, we compare the first element. If they are equal
23490
-- we need to consider the next block so we recurse, otherwise we return the comparison result.
235-
DROP FUNCTION IF EXISTS compare_ore_array(a ore_64_8_v1_term[], b ore_64_8_v1_term[]);
23691

237-
CREATE FUNCTION compare_ore_array(a ore_64_8_v1_term[], b ore_64_8_v1_term[])
92+
93+
CREATE FUNCTION compare_ore_array(a ore_64_8_index_v1, b ore_64_8_index_v1)
23894
RETURNS integer AS $$
23995
DECLARE
24096
cmp_result integer;
24197
BEGIN
24298
IF (array_length(a, 1) = 0 OR a IS NULL) AND (array_length(b, 1) = 0 OR b IS NULL) THEN
24399
RETURN 0;
244100
END IF;
101+
245102
IF array_length(a, 1) = 0 OR a IS NULL THEN
246103
RETURN -1;
247104
END IF;
105+
248106
IF array_length(b, 1) = 0 OR a IS NULL THEN
249107
RETURN 1;
250108
END IF;
251109

252110
cmp_result := compare_ore_64_8_v1_term(a[1], b[1]);
111+
253112
IF cmp_result = 0 THEN
254113
-- Removes the first element in the array, and calls this fn again to compare the next element/s in the array.
255114
RETURN compare_ore_array(a[2:array_length(a,1)], b[2:array_length(b,1)]);
@@ -260,68 +119,68 @@ RETURNS integer AS $$
260119
$$ LANGUAGE plpgsql;
261120

262121
-- This function uses lexicographic comparison
263-
DROP FUNCTION IF EXISTS compare_ore_64_8_v1(a ore_64_8_v1, b ore_64_8_v1);
122+
DROP FUNCTION IF EXISTS compare_ore_64_8_v1(a ore_64_8_index_v1, b ore_64_8_index_v1);
264123

265-
CREATE FUNCTION compare_ore_64_8_v1(a ore_64_8_v1, b ore_64_8_v1)
124+
CREATE FUNCTION compare_ore_64_8_v1(a ore_64_8_index_v1, b ore_64_8_index_v1)
266125
RETURNS integer AS $$
267-
DECLARE
268-
cmp_result integer;
269126
BEGIN
270127
-- Recursively compare blocks bailing as soon as we can make a decision
271-
RETURN compare_ore_array(a.terms, b.terms);
128+
RETURN compare_ore_array(a, b);
272129
END
273130
$$ LANGUAGE plpgsql;
274131

275132

276-
DROP FUNCTION IF EXISTS ore_64_8_v1_eq(a ore_64_8_v1, b ore_64_8_v1);
133+
DROP FUNCTION IF EXISTS ore_64_8_v1_eq(a ore_64_8_index_v1, b ore_64_8_index_v1);
277134

278-
CREATE FUNCTION ore_64_8_v1_eq(a ore_64_8_v1, b ore_64_8_v1)
135+
CREATE FUNCTION ore_64_8_v1_eq(a ore_64_8_index_v1, b ore_64_8_index_v1)
279136
RETURNS boolean AS $$
280137
SELECT compare_ore_64_8_v1(a, b) = 0
281138
$$ LANGUAGE SQL;
282139

283140

284-
DROP FUNCTION IF EXISTS ore_64_8_v1_neq(a ore_64_8_v1, b ore_64_8_v1);
141+
DROP FUNCTION IF EXISTS ore_64_8_v1_neq(a ore_64_8_index_v1, b ore_64_8_index_v1);
285142

286-
CREATE FUNCTION ore_64_8_v1_neq(a ore_64_8_v1, b ore_64_8_v1)
143+
CREATE FUNCTION ore_64_8_v1_neq(a ore_64_8_index_v1, b ore_64_8_index_v1)
287144
RETURNS boolean AS $$
288145
SELECT compare_ore_64_8_v1(a, b) <> 0
289146
$$ LANGUAGE SQL;
290147

291148

292-
DROP FUNCTION IF EXISTS ore_64_8_v1_lt(a ore_64_8_v1, b ore_64_8_v1);
149+
DROP FUNCTION IF EXISTS ore_64_8_v1_lt(a ore_64_8_index_v1, b ore_64_8_index_v1);
293150

294-
CREATE FUNCTION ore_64_8_v1_lt(a ore_64_8_v1, b ore_64_8_v1)
151+
CREATE FUNCTION ore_64_8_v1_lt(a ore_64_8_index_v1, b ore_64_8_index_v1)
295152
RETURNS boolean AS $$
296153
SELECT compare_ore_64_8_v1(a, b) = -1
297154
$$ LANGUAGE SQL;
298155

299156

300-
DROP FUNCTION IF EXISTS ore_64_8_v1_lte(a ore_64_8_v1, b ore_64_8_v1);
157+
DROP FUNCTION IF EXISTS ore_64_8_v1_lte(a ore_64_8_index_v1, b ore_64_8_index_v1);
301158

302-
CREATE FUNCTION ore_64_8_v1_lte(a ore_64_8_v1, b ore_64_8_v1)
159+
CREATE FUNCTION ore_64_8_v1_lte(a ore_64_8_index_v1, b ore_64_8_index_v1)
303160
RETURNS boolean AS $$
304161
SELECT compare_ore_64_8_v1(a, b) != 1
305162
$$ LANGUAGE SQL;
306163

307164

308-
DROP FUNCTION IF EXISTS ore_64_8_v1_gt(a ore_64_8_v1, b ore_64_8_v1);
165+
DROP FUNCTION IF EXISTS ore_64_8_v1_gt(a ore_64_8_index_v1, b ore_64_8_index_v1);
309166

310-
CREATE FUNCTION ore_64_8_v1_gt(a ore_64_8_v1, b ore_64_8_v1)
167+
CREATE FUNCTION ore_64_8_v1_gt(a ore_64_8_index_v1, b ore_64_8_index_v1)
311168
RETURNS boolean AS $$
312-
SELECT compare_ore_64_8_v1(a, b) = 1
313-
$$ LANGUAGE SQL;
169+
BEGIN
170+
SELECT compare_ore_64_8_v1(a, b) = 1;
171+
END;
172+
$$ LANGUAGE plpgsql;
314173

315174

316-
DROP FUNCTION IF EXISTS ore_64_8_v1_gte(a ore_64_8_v1, b ore_64_8_v1);
175+
DROP FUNCTION IF EXISTS ore_64_8_v1_gte(a ore_64_8_index_v1, b ore_64_8_index_v1);
317176

318-
CREATE FUNCTION ore_64_8_v1_gte(a ore_64_8_v1, b ore_64_8_v1)
177+
CREATE FUNCTION ore_64_8_v1_gte(a ore_64_8_index_v1, b ore_64_8_index_v1)
319178
RETURNS boolean AS $$
320179
SELECT compare_ore_64_8_v1(a, b) != -1
321180
$$ LANGUAGE SQL;
322181

323182

324-
DROP OPERATOR IF EXISTS = (ore_64_8_v1, ore_64_8_v1);
183+
DROP OPERATOR IF EXISTS = (ore_64_8_index_v1, ore_64_8_index_v1);
325184

326185
CREATE OPERATOR = (
327186
PROCEDURE="ore_64_8_v1_eq",
@@ -335,7 +194,7 @@ CREATE OPERATOR = (
335194
);
336195

337196

338-
DROP OPERATOR IF EXISTS <> (ore_64_8_v1, ore_64_8_v1);
197+
DROP OPERATOR IF EXISTS <> (ore_64_8_index_v1, ore_64_8_index_v1);
339198

340199
CREATE OPERATOR <> (
341200
PROCEDURE="ore_64_8_v1_neq",
@@ -348,7 +207,7 @@ CREATE OPERATOR <> (
348207
MERGES
349208
);
350209

351-
DROP OPERATOR IF EXISTS > (ore_64_8_v1, ore_64_8_v1);
210+
DROP OPERATOR IF EXISTS > (ore_64_8_index_v1, ore_64_8_index_v1);
352211

353212
CREATE OPERATOR > (
354213
PROCEDURE="ore_64_8_v1_gt",
@@ -361,7 +220,7 @@ CREATE OPERATOR > (
361220
);
362221

363222

364-
DROP OPERATOR IF EXISTS < (ore_64_8_v1, ore_64_8_v1);
223+
DROP OPERATOR IF EXISTS < (ore_64_8_index_v1, ore_64_8_index_v1);
365224

366225
CREATE OPERATOR < (
367226
PROCEDURE="ore_64_8_v1_lt",
@@ -374,7 +233,7 @@ CREATE OPERATOR < (
374233
);
375234

376235

377-
DROP OPERATOR IF EXISTS <= (ore_64_8_v1, ore_64_8_v1);
236+
DROP OPERATOR IF EXISTS <= (ore_64_8_index_v1, ore_64_8_index_v1);
378237

379238
CREATE OPERATOR <= (
380239
PROCEDURE="ore_64_8_v1_lte",
@@ -387,7 +246,7 @@ CREATE OPERATOR <= (
387246
);
388247

389248

390-
DROP OPERATOR IF EXISTS >= (ore_64_8_v1, ore_64_8_v1);
249+
DROP OPERATOR IF EXISTS >= (ore_64_8_index_v1, ore_64_8_index_v1);
391250

392251
CREATE OPERATOR >= (
393252
PROCEDURE="ore_64_8_v1_gte",
@@ -413,4 +272,4 @@ CREATE OPERATOR CLASS ore_64_8_v1_btree_ops DEFAULT FOR TYPE ore_64_8_v1 USING b
413272
OPERATOR 3 =,
414273
OPERATOR 4 >=,
415274
OPERATOR 5 >,
416-
FUNCTION 1 compare_ore_64_8_v1(a ore_64_8_v1, b ore_64_8_v1);
275+
FUNCTION 1 compare_ore_64_8_v1(a ore_64_8_index_v1, b ore_64_8_index_v1);

0 commit comments

Comments
 (0)