Skip to content

Commit cfa5162

Browse files
committed
copy over custom types
1 parent 38c3cec commit cfa5162

File tree

2 files changed

+337
-0
lines changed

2 files changed

+337
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
CREATE EXTENSION IF NOT EXISTS pgcrypto;
2+
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+
);
10+
11+
CREATE OR REPLACE FUNCTION compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term) returns integer AS $$
12+
DECLARE
13+
eq boolean := true;
14+
unequal_block smallint := 0;
15+
hash_key bytea;
16+
target_block bytea;
17+
18+
left_block_size CONSTANT smallint := 16;
19+
right_block_size CONSTANT smallint := 32;
20+
right_offset CONSTANT smallint := 136; -- 8 * 17
21+
22+
indicator smallint := 0;
23+
BEGIN
24+
IF a IS NULL AND b IS NULL THEN
25+
RETURN 0;
26+
END IF;
27+
28+
IF a IS NULL THEN
29+
RETURN -1;
30+
END IF;
31+
32+
IF b IS NULL THEN
33+
RETURN 1;
34+
END IF;
35+
36+
IF bit_length(a.bytes) != bit_length(b.bytes) THEN
37+
RAISE EXCEPTION 'Ciphertexts are different lengths';
38+
END IF;
39+
40+
FOR block IN 0..7 LOOP
41+
-- Compare each PRP (byte from the first 8 bytes) and PRF block (8 byte
42+
-- chunks of the rest of the value).
43+
-- NOTE:
44+
-- * Substr is ordinally indexed (hence 1 and not 0, and 9 and not 8).
45+
-- * We are not worrying about timing attacks here; don't fret about
46+
-- the OR or !=.
47+
IF
48+
substr(a.bytes, 1 + block, 1) != substr(b.bytes, 1 + block, 1)
49+
OR substr(a.bytes, 9 + left_block_size * block, left_block_size) != substr(b.bytes, 9 + left_block_size * BLOCK, left_block_size)
50+
THEN
51+
-- set the first unequal block we find
52+
IF eq THEN
53+
unequal_block := block;
54+
END IF;
55+
eq = false;
56+
END IF;
57+
END LOOP;
58+
59+
IF eq THEN
60+
RETURN 0::integer;
61+
END IF;
62+
63+
-- Hash key is the IV from the right CT of b
64+
hash_key := substr(b.bytes, right_offset + 1, 16);
65+
66+
-- first right block is at right offset + nonce_size (ordinally indexed)
67+
target_block := substr(b.bytes, right_offset + 17 + (unequal_block * right_block_size), right_block_size);
68+
69+
indicator := (
70+
get_bit(
71+
encrypt(
72+
substr(a.bytes, 9 + (left_block_size * unequal_block), left_block_size),
73+
hash_key,
74+
'aes-ecb'
75+
),
76+
0
77+
) + get_bit(target_block, get_byte(a.bytes, unequal_block))) % 2;
78+
79+
IF indicator = 1 THEN
80+
RETURN 1::integer;
81+
ELSE
82+
RETURN -1::integer;
83+
END IF;
84+
END;
85+
$$ LANGUAGE plpgsql;
86+
87+
88+
CREATE OR REPLACE FUNCTION ore_64_8_v1_term_eq(a ore_64_8_v1_term, b ore_64_8_v1_term) RETURNS boolean AS $$
89+
SELECT compare_ore_64_8_v1_term(a, b) = 0
90+
$$ LANGUAGE SQL;
91+
92+
CREATE OR REPLACE FUNCTION ore_64_8_v1_term_neq(a ore_64_8_v1_term, b ore_64_8_v1_term) RETURNS boolean AS $$
93+
SELECT compare_ore_64_8_v1_term(a, b) <> 0
94+
$$ LANGUAGE SQL;
95+
96+
CREATE OR REPLACE FUNCTION ore_64_8_v1_term_lt(a ore_64_8_v1_term, b ore_64_8_v1_term) RETURNS boolean AS $$
97+
SELECT compare_ore_64_8_v1_term(a, b) = -1
98+
$$ LANGUAGE SQL;
99+
100+
CREATE OR REPLACE FUNCTION ore_64_8_v1_term_lte(a ore_64_8_v1_term, b ore_64_8_v1_term) RETURNS boolean AS $$
101+
SELECT compare_ore_64_8_v1_term(a, b) != 1
102+
$$ LANGUAGE SQL;
103+
104+
CREATE OR REPLACE FUNCTION ore_64_8_v1_term_gt(a ore_64_8_v1_term, b ore_64_8_v1_term) RETURNS boolean AS $$
105+
SELECT compare_ore_64_8_v1_term(a, b) = 1
106+
$$ LANGUAGE SQL;
107+
108+
CREATE OR REPLACE FUNCTION ore_64_8_v1_term_gte(a ore_64_8_v1_term, b ore_64_8_v1_term) RETURNS boolean AS $$
109+
SELECT compare_ore_64_8_v1_term(a, b) != -1
110+
$$ LANGUAGE SQL;
111+
112+
CREATE OPERATOR = (
113+
PROCEDURE="ore_64_8_v1_term_eq",
114+
LEFTARG=ore_64_8_v1_term,
115+
RIGHTARG=ore_64_8_v1_term,
116+
NEGATOR = <>,
117+
RESTRICT = eqsel,
118+
JOIN = eqjoinsel,
119+
HASHES,
120+
MERGES
121+
);
122+
123+
CREATE OPERATOR <> (
124+
PROCEDURE="ore_64_8_v1_term_neq",
125+
LEFTARG=ore_64_8_v1_term,
126+
RIGHTARG=ore_64_8_v1_term,
127+
NEGATOR = =,
128+
RESTRICT = eqsel,
129+
JOIN = eqjoinsel,
130+
HASHES,
131+
MERGES
132+
);
133+
134+
CREATE OPERATOR > (
135+
PROCEDURE="ore_64_8_v1_term_gt",
136+
LEFTARG=ore_64_8_v1_term,
137+
RIGHTARG=ore_64_8_v1_term,
138+
COMMUTATOR = <,
139+
NEGATOR = <=,
140+
RESTRICT = scalargtsel,
141+
JOIN = scalargtjoinsel
142+
);
143+
144+
CREATE OPERATOR < (
145+
PROCEDURE="ore_64_8_v1_term_lt",
146+
LEFTARG=ore_64_8_v1_term,
147+
RIGHTARG=ore_64_8_v1_term,
148+
COMMUTATOR = >,
149+
NEGATOR = >=,
150+
RESTRICT = scalarltsel,
151+
JOIN = scalarltjoinsel
152+
);
153+
154+
CREATE OPERATOR <= (
155+
PROCEDURE="ore_64_8_v1_term_lte",
156+
LEFTARG=ore_64_8_v1_term,
157+
RIGHTARG=ore_64_8_v1_term,
158+
COMMUTATOR = >=,
159+
NEGATOR = >,
160+
RESTRICT = scalarlesel,
161+
JOIN = scalarlejoinsel
162+
);
163+
164+
CREATE OPERATOR >= (
165+
PROCEDURE="ore_64_8_v1_term_gte",
166+
LEFTARG=ore_64_8_v1_term,
167+
RIGHTARG=ore_64_8_v1_term,
168+
COMMUTATOR = <=,
169+
NEGATOR = <,
170+
RESTRICT = scalarlesel,
171+
JOIN = scalarlejoinsel
172+
);
173+
174+
CREATE OPERATOR FAMILY ore_64_8_v1_term_btree_ops USING btree;
175+
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
176+
OPERATOR 1 <,
177+
OPERATOR 2 <=,
178+
OPERATOR 3 =,
179+
OPERATOR 4 >=,
180+
OPERATOR 5 >,
181+
FUNCTION 1 compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term);
182+
183+
-- Compare the "head" of each array and recurse if necessary
184+
-- This function assumes an empty string is "less than" everything else
185+
-- so if a is empty we return -1, if be is empty and a isn't, we return 1.
186+
-- If both are empty we return 0. This cases probably isn't necessary as equality
187+
-- doesn't always make sense but it's here for completeness.
188+
-- If both are non-empty, we compare the first element. If they are equal
189+
-- we need to consider the next block so we recurse, otherwise we return the comparison result.
190+
CREATE OR REPLACE FUNCTION compare_ore_array(a ore_64_8_v1_term[], b ore_64_8_v1_term[]) returns integer AS $$
191+
DECLARE
192+
cmp_result integer;
193+
BEGIN
194+
IF (array_length(a, 1) = 0 OR a IS NULL) AND (array_length(b, 1) = 0 OR b IS NULL) THEN
195+
RETURN 0;
196+
END IF;
197+
IF array_length(a, 1) = 0 OR a IS NULL THEN
198+
RETURN -1;
199+
END IF;
200+
IF array_length(b, 1) = 0 OR a IS NULL THEN
201+
RETURN 1;
202+
END IF;
203+
204+
cmp_result := compare_ore_64_8_v1_term(a[1], b[1]);
205+
IF cmp_result = 0 THEN
206+
-- Removes the first element in the array, and calls this fn again to compare the next element/s in the array.
207+
RETURN compare_ore_array(a[2:array_length(a,1)], b[2:array_length(b,1)]);
208+
END IF;
209+
210+
RETURN cmp_result;
211+
END
212+
$$ LANGUAGE plpgsql;
213+
214+
-- This function uses lexicographic comparison
215+
CREATE OR REPLACE FUNCTION compare_ore_64_8_v1(a ore_64_8_v1, b ore_64_8_v1) returns integer AS $$
216+
DECLARE
217+
cmp_result integer;
218+
BEGIN
219+
-- Recursively compare blocks bailing as soon as we can make a decision
220+
RETURN compare_ore_array(a.terms, b.terms);
221+
END
222+
$$ LANGUAGE plpgsql;
223+
224+
CREATE OR REPLACE FUNCTION ore_64_8_v1_eq(a ore_64_8_v1, b ore_64_8_v1) RETURNS boolean AS $$
225+
SELECT compare_ore_64_8_v1(a, b) = 0
226+
$$ LANGUAGE SQL;
227+
228+
CREATE OR REPLACE FUNCTION ore_64_8_v1_neq(a ore_64_8_v1, b ore_64_8_v1) RETURNS boolean AS $$
229+
SELECT compare_ore_64_8_v1(a, b) <> 0
230+
$$ LANGUAGE SQL;
231+
232+
CREATE OR REPLACE FUNCTION ore_64_8_v1_lt(a ore_64_8_v1, b ore_64_8_v1) RETURNS boolean AS $$
233+
SELECT compare_ore_64_8_v1(a, b) = -1
234+
$$ LANGUAGE SQL;
235+
236+
CREATE OR REPLACE FUNCTION ore_64_8_v1_lte(a ore_64_8_v1, b ore_64_8_v1) RETURNS boolean AS $$
237+
SELECT compare_ore_64_8_v1(a, b) != 1
238+
$$ LANGUAGE SQL;
239+
240+
CREATE OR REPLACE FUNCTION ore_64_8_v1_gt(a ore_64_8_v1, b ore_64_8_v1) RETURNS boolean AS $$
241+
SELECT compare_ore_64_8_v1(a, b) = 1
242+
$$ LANGUAGE SQL;
243+
244+
CREATE OR REPLACE FUNCTION ore_64_8_v1_gte(a ore_64_8_v1, b ore_64_8_v1) RETURNS boolean AS $$
245+
SELECT compare_ore_64_8_v1(a, b) != -1
246+
$$ LANGUAGE SQL;
247+
248+
CREATE OPERATOR = (
249+
PROCEDURE="ore_64_8_v1_eq",
250+
LEFTARG=ore_64_8_v1,
251+
RIGHTARG=ore_64_8_v1,
252+
NEGATOR = <>,
253+
RESTRICT = eqsel,
254+
JOIN = eqjoinsel,
255+
HASHES,
256+
MERGES
257+
);
258+
259+
CREATE OPERATOR <> (
260+
PROCEDURE="ore_64_8_v1_neq",
261+
LEFTARG=ore_64_8_v1,
262+
RIGHTARG=ore_64_8_v1,
263+
NEGATOR = =,
264+
RESTRICT = eqsel,
265+
JOIN = eqjoinsel,
266+
HASHES,
267+
MERGES
268+
);
269+
270+
CREATE OPERATOR > (
271+
PROCEDURE="ore_64_8_v1_gt",
272+
LEFTARG=ore_64_8_v1,
273+
RIGHTARG=ore_64_8_v1,
274+
COMMUTATOR = <,
275+
NEGATOR = <=,
276+
RESTRICT = scalargtsel,
277+
JOIN = scalargtjoinsel
278+
);
279+
280+
CREATE OPERATOR < (
281+
PROCEDURE="ore_64_8_v1_lt",
282+
LEFTARG=ore_64_8_v1,
283+
RIGHTARG=ore_64_8_v1,
284+
COMMUTATOR = >,
285+
NEGATOR = >=,
286+
RESTRICT = scalarltsel,
287+
JOIN = scalarltjoinsel
288+
);
289+
290+
CREATE OPERATOR <= (
291+
PROCEDURE="ore_64_8_v1_lte",
292+
LEFTARG=ore_64_8_v1,
293+
RIGHTARG=ore_64_8_v1,
294+
COMMUTATOR = >=,
295+
NEGATOR = >,
296+
RESTRICT = scalarlesel,
297+
JOIN = scalarlejoinsel
298+
);
299+
300+
CREATE OPERATOR >= (
301+
PROCEDURE="ore_64_8_v1_gte",
302+
LEFTARG=ore_64_8_v1,
303+
RIGHTARG=ore_64_8_v1,
304+
COMMUTATOR = <=,
305+
NEGATOR = <,
306+
RESTRICT = scalarlesel,
307+
JOIN = scalarlejoinsel
308+
);
309+
310+
CREATE OPERATOR FAMILY ore_64_8_v1_btree_ops USING btree;
311+
CREATE OPERATOR CLASS ore_64_8_v1_btree_ops DEFAULT FOR TYPE ore_64_8_v1 USING btree FAMILY ore_64_8_v1_btree_ops AS
312+
OPERATOR 1 <,
313+
OPERATOR 2 <=,
314+
OPERATOR 3 =,
315+
OPERATOR 4 >=,
316+
OPERATOR 5 >,
317+
FUNCTION 1 compare_ore_64_8_v1(a ore_64_8_v1, b ore_64_8_v1);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-- TODO: what happens if we try to uninstall a type which is in use?
2+
DROP OPERATOR IF EXISTS = (ore_64_8_v1_term, ore_64_8_v1_term) CASCADE;
3+
DROP OPERATOR IF EXISTS <> (ore_64_8_v1_term, ore_64_8_v1_term) CASCADE;
4+
DROP OPERATOR IF EXISTS > (ore_64_8_v1_term, ore_64_8_v1_term) CASCADE;
5+
DROP OPERATOR IF EXISTS < (ore_64_8_v1_term, ore_64_8_v1_term) CASCADE;
6+
DROP OPERATOR IF EXISTS <= (ore_64_8_v1_term, ore_64_8_v1_term) CASCADE;
7+
DROP OPERATOR IF EXISTS >= (ore_64_8_v1_term, ore_64_8_v1_term) CASCADE;
8+
DROP OPERATOR CLASS IF EXISTS ore_64_8_v1_term_btree_ops USING btree CASCADE;
9+
DROP OPERATOR FAMILY IF EXISTS ore_64_8_v1_term_btree_ops USING btree CASCADE;
10+
DROP TYPE IF EXISTS ore_64_8_v1_term CASCADE;
11+
12+
DROP OPERATOR IF EXISTS = (ore_64_8_v1, ore_64_8_v1) CASCADE;
13+
DROP OPERATOR IF EXISTS <> (ore_64_8_v1, ore_64_8_v1) CASCADE;
14+
DROP OPERATOR IF EXISTS > (ore_64_8_v1, ore_64_8_v1) CASCADE;
15+
DROP OPERATOR IF EXISTS < (ore_64_8_v1, ore_64_8_v1) CASCADE;
16+
DROP OPERATOR IF EXISTS <= (ore_64_8_v1, ore_64_8_v1) CASCADE;
17+
DROP OPERATOR IF EXISTS >= (ore_64_8_v1, ore_64_8_v1) CASCADE;
18+
DROP OPERATOR CLASS IF EXISTS ore_64_8_v1_btree_ops USING btree CASCADE;
19+
DROP OPERATOR FAMILY IF EXISTS ore_64_8_v1_btree_ops USING btree CASCADE;
20+
DROP TYPE IF EXISTS ore_64_8_v1 CASCADE;

0 commit comments

Comments
 (0)