Skip to content

Commit 24a3d7f

Browse files
authored
Merge pull request #59 from cipherstash/CIP-864/validate-q-values
Raise exceptions if index fields are missing
2 parents 705ecc6 + 13bf286 commit 24a3d7f

File tree

2 files changed

+164
-73
lines changed

2 files changed

+164
-73
lines changed

sql/010-core.sql

Lines changed: 85 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -159,125 +159,145 @@ ALTER DOMAIN cs_encrypted_v1
159159
);
160160

161161

162-
DROP FUNCTION IF EXISTS cs_ciphertext_v1_v0_0(col jsonb);
162+
DROP FUNCTION IF EXISTS cs_ciphertext_v1_v0_0(val jsonb);
163163

164-
CREATE FUNCTION cs_ciphertext_v1_v0_0(col jsonb)
165-
RETURNS text
166-
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
167-
BEGIN ATOMIC
168-
RETURN col->>'c';
169-
END;
164+
CREATE FUNCTION cs_ciphertext_v1_v0_0(val jsonb)
165+
RETURNS text
166+
IMMUTABLE STRICT PARALLEL SAFE
167+
AS $$
168+
BEGIN
169+
IF val ? 'c' THEN
170+
RETURN val->>'c';
171+
END IF;
172+
RAISE 'Expected a ciphertext (c) value in json: %', val;
173+
END;
174+
$$ LANGUAGE plpgsql;
170175

171176

172-
DROP FUNCTION IF EXISTS cs_ciphertext_v1_v0(col jsonb);
177+
DROP FUNCTION IF EXISTS cs_ciphertext_v1_v0(val jsonb);
173178

174-
CREATE FUNCTION cs_ciphertext_v1_v0(col jsonb)
179+
CREATE FUNCTION cs_ciphertext_v1_v0(val jsonb)
175180
RETURNS text
176181
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
177182
BEGIN ATOMIC
178-
RETURN cs_ciphertext_v1_v0_0(col);
183+
RETURN cs_ciphertext_v1_v0_0(val);
179184
END;
180185

181186

182-
DROP FUNCTION IF EXISTS cs_ciphertext_v1(col jsonb);
187+
DROP FUNCTION IF EXISTS cs_ciphertext_v1(val jsonb);
183188

184-
CREATE FUNCTION cs_ciphertext_v1(col jsonb)
189+
CREATE FUNCTION cs_ciphertext_v1(val jsonb)
185190
RETURNS text
186191
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
187192
BEGIN ATOMIC
188-
RETURN cs_ciphertext_v1_v0_0(col);
193+
RETURN cs_ciphertext_v1_v0_0(val);
189194
END;
190195

191196

192197
-- extracts match index from an emcrypted column
193-
DROP FUNCTION IF EXISTS cs_match_v1_v0_0(col jsonb);
198+
DROP FUNCTION IF EXISTS cs_match_v1_v0_0(val jsonb);
194199

195-
CREATE FUNCTION cs_match_v1_v0_0(col jsonb)
200+
CREATE FUNCTION cs_match_v1_v0_0(val jsonb)
196201
RETURNS cs_match_index_v1
197-
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
198-
BEGIN ATOMIC
199-
SELECT ARRAY(SELECT jsonb_array_elements(col->'m'))::cs_match_index_v1;
200-
END;
202+
IMMUTABLE STRICT PARALLEL SAFE
203+
AS $$
204+
BEGIN
205+
IF val ? 'm' THEN
206+
RETURN ARRAY(SELECT jsonb_array_elements(val->'m'))::cs_match_index_v1;
207+
END IF;
208+
RAISE 'Expected a match index (m) value in json: %', val;
209+
END;
210+
$$ LANGUAGE plpgsql;
201211

202212

203-
DROP FUNCTION IF EXISTS cs_match_v1_v0(col jsonb);
213+
DROP FUNCTION IF EXISTS cs_match_v1_v0(val jsonb);
204214

205-
CREATE FUNCTION cs_match_v1_v0(col jsonb)
215+
CREATE FUNCTION cs_match_v1_v0(val jsonb)
206216
RETURNS cs_match_index_v1
207217
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
208218
BEGIN ATOMIC
209-
RETURN cs_match_v1_v0_0(col);
219+
RETURN cs_match_v1_v0_0(val);
210220
END;
211221

212222

213-
DROP FUNCTION IF EXISTS cs_match_v1(col jsonb);
223+
DROP FUNCTION IF EXISTS cs_match_v1(val jsonb);
214224

215-
CREATE FUNCTION cs_match_v1(col jsonb)
225+
CREATE FUNCTION cs_match_v1(val jsonb)
216226
RETURNS cs_match_index_v1
217227
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
218228
BEGIN ATOMIC
219-
RETURN cs_match_v1_v0_0(col);
229+
RETURN cs_match_v1_v0_0(val);
220230
END;
221231

222232

223233
-- extracts unique index from an encrypted column
224-
DROP FUNCTION IF EXISTS cs_unique_v1_v0_0(col jsonb);
234+
DROP FUNCTION IF EXISTS cs_unique_v1_v0_0(val jsonb);
225235

226-
CREATE FUNCTION cs_unique_v1_v0_0(col jsonb)
236+
CREATE FUNCTION cs_unique_v1_v0_0(val jsonb)
227237
RETURNS cs_unique_index_v1
228-
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
229-
BEGIN ATOMIC
230-
RETURN col->>'u';
231-
END;
238+
IMMUTABLE STRICT PARALLEL SAFE
239+
AS $$
240+
BEGIN
241+
IF val ? 'u' THEN
242+
RETURN val->>'u';
243+
END IF;
244+
RAISE 'Expected a unique index (u) value in json: %', val;
245+
END;
246+
$$ LANGUAGE plpgsql;
232247

233248

234-
DROP FUNCTION IF EXISTS cs_unique_v1_v0(col jsonb);
249+
DROP FUNCTION IF EXISTS cs_unique_v1_v0(val jsonb);
235250

236-
CREATE FUNCTION cs_unique_v1_v0(col jsonb)
251+
CREATE FUNCTION cs_unique_v1_v0(val jsonb)
237252
RETURNS cs_unique_index_v1
238253
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
239254
BEGIN ATOMIC
240-
RETURN cs_unique_v1_v0_0(col);
255+
RETURN cs_unique_v1_v0_0(val);
241256
END;
242257

243258

244-
DROP FUNCTION IF EXISTS cs_unique_v1(col jsonb);
259+
DROP FUNCTION IF EXISTS cs_unique_v1(val jsonb);
245260

246-
CREATE FUNCTION cs_unique_v1(col jsonb)
261+
CREATE FUNCTION cs_unique_v1(val jsonb)
247262
RETURNS cs_unique_index_v1
248263
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
249264
BEGIN ATOMIC
250-
RETURN cs_unique_v1_v0_0(col);
265+
RETURN cs_unique_v1_v0_0(val);
251266
END;
252267

253268
-- extracts json ste_vec index from an encrypted column
254-
DROP FUNCTION IF EXISTS cs_ste_vec_v1_v0_0(col jsonb);
269+
DROP FUNCTION IF EXISTS cs_ste_vec_v1_v0_0(val jsonb);
255270

256-
CREATE FUNCTION cs_ste_vec_v1_v0_0(col jsonb)
271+
CREATE FUNCTION cs_ste_vec_v1_v0_0(val jsonb)
257272
RETURNS cs_ste_vec_index_v1
258-
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
259-
BEGIN ATOMIC
260-
SELECT (col->'sv')::cs_ste_vec_index_v1;
261-
END;
273+
IMMUTABLE STRICT PARALLEL SAFE
274+
AS $$
275+
BEGIN
276+
IF val ? 'sv' THEN
277+
RETURN (val->'sv')::cs_ste_vec_index_v1;
278+
END IF;
279+
RAISE 'Expected a structured vector index (sv) value in json: %', val;
280+
END;
281+
$$ LANGUAGE plpgsql;
262282

263283

264-
DROP FUNCTION IF EXISTS cs_ste_vec_v1_v0(col jsonb);
284+
DROP FUNCTION IF EXISTS cs_ste_vec_v1_v0(val jsonb);
265285

266-
CREATE FUNCTION cs_ste_vec_v1_v0(col jsonb)
286+
CREATE FUNCTION cs_ste_vec_v1_v0(val jsonb)
267287
RETURNS cs_ste_vec_index_v1
268288
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
269289
BEGIN ATOMIC
270-
RETURN cs_ste_vec_v1_v0_0(col);
290+
RETURN cs_ste_vec_v1_v0_0(val);
271291
END;
272292

273293

274-
DROP FUNCTION IF EXISTS cs_ste_vec_v1(col jsonb);
294+
DROP FUNCTION IF EXISTS cs_ste_vec_v1(val jsonb);
275295

276-
CREATE FUNCTION cs_ste_vec_v1(col jsonb)
296+
CREATE FUNCTION cs_ste_vec_v1(val jsonb)
277297
RETURNS cs_ste_vec_index_v1
278298
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
279299
BEGIN ATOMIC
280-
RETURN cs_ste_vec_v1_v0_0(col);
300+
RETURN cs_ste_vec_v1_v0_0(val);
281301
END;
282302

283303

@@ -303,39 +323,31 @@ DROP FUNCTION IF EXISTS cs_ore_64_8_v1_v0_0(val jsonb);
303323

304324
CREATE FUNCTION cs_ore_64_8_v1_v0_0(val jsonb)
305325
RETURNS ore_64_8_v1
306-
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
307-
BEGIN ATOMIC
308-
SELECT (val->>'o')::ore_64_8_v1;
309-
END;
326+
IMMUTABLE STRICT PARALLEL SAFE
327+
AS $$
328+
BEGIN
329+
IF val ? 'o' THEN
330+
RETURN (val->>'o')::ore_64_8_v1;
331+
END IF;
332+
RAISE 'Expected an ore index (o) value in json: %', val;
333+
END;
334+
$$ LANGUAGE plpgsql;
335+
310336

311-
DROP FUNCTION IF EXISTS cs_ore_64_8_v1_v0(col jsonb);
337+
DROP FUNCTION IF EXISTS cs_ore_64_8_v1_v0(val jsonb);
312338

313-
CREATE FUNCTION cs_ore_64_8_v1_v0(col jsonb)
339+
CREATE FUNCTION cs_ore_64_8_v1_v0(val jsonb)
314340
RETURNS ore_64_8_v1
315341
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
316342
BEGIN ATOMIC
317-
RETURN cs_ore_64_8_v1_v0_0(col);
343+
RETURN cs_ore_64_8_v1_v0_0(val);
318344
END;
319345

320-
DROP FUNCTION IF EXISTS cs_ore_64_8_v1(col jsonb);
346+
DROP FUNCTION IF EXISTS cs_ore_64_8_v1(val jsonb);
321347

322-
CREATE FUNCTION cs_ore_64_8_v1(col jsonb)
348+
CREATE FUNCTION cs_ore_64_8_v1(val jsonb)
323349
RETURNS ore_64_8_v1
324350
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
325351
BEGIN ATOMIC
326-
RETURN cs_ore_64_8_v1_v0_0(col);
352+
RETURN cs_ore_64_8_v1_v0_0(val);
327353
END;
328-
329-
DROP FUNCTION IF EXISTS _cs_first_grouped_value(jsonb, jsonb);
330-
331-
CREATE FUNCTION _cs_first_grouped_value(jsonb, jsonb)
332-
RETURNS jsonb AS $$
333-
SELECT COALESCE($1, $2);
334-
$$ LANGUAGE sql IMMUTABLE;
335-
336-
DROP AGGREGATE IF EXISTS cs_grouped_value_v1(jsonb);
337-
338-
CREATE AGGREGATE cs_grouped_value_v1(jsonb) (
339-
SFUNC = _cs_first_grouped_value,
340-
STYPE = jsonb
341-
);

tests/core-functions.sql

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
\set ON_ERROR_STOP on
2+
3+
4+
DO $$
5+
BEGIN
6+
ASSERT (SELECT EXISTS (SELECT cs_unique_v1('{"u": "u"}'::jsonb)));
7+
ASSERT (SELECT EXISTS (SELECT cs_match_v1('{"m": []}'::jsonb)));
8+
ASSERT (SELECT EXISTS (SELECT cs_ste_vec_v1('{"sv": [[]]}'::jsonb)));
9+
ASSERT (SELECT EXISTS (SELECT cs_ore_64_8_v1('{"o": "()"}'::jsonb)));
10+
11+
END;
12+
$$ LANGUAGE plpgsql;
13+
14+
DO $$
15+
BEGIN
16+
-- sanity check
17+
PERFORM cs_ore_64_8_v1('{"o": "()"}'::jsonb);
18+
19+
BEGIN
20+
PERFORM cs_ore_64_8_v1('{}'::jsonb);
21+
RAISE NOTICE 'Missing index. Function call should have failed.';
22+
ASSERT false;
23+
EXCEPTION
24+
WHEN OTHERS THEN
25+
ASSERT true;
26+
END;
27+
END;
28+
$$ LANGUAGE plpgsql;
29+
30+
DO $$
31+
BEGIN
32+
-- sanity check
33+
PERFORM cs_ste_vec_v1('{"sv": [[]]}'::jsonb);
34+
35+
BEGIN
36+
PERFORM cs_ste_vec_v1('{}'::jsonb);
37+
RAISE NOTICE 'Missing index. Function call should have failed.';
38+
ASSERT false;
39+
EXCEPTION
40+
WHEN OTHERS THEN
41+
ASSERT true;
42+
END;
43+
END;
44+
$$ LANGUAGE plpgsql;
45+
46+
47+
DO $$
48+
BEGIN
49+
-- sanity check
50+
PERFORM cs_unique_v1('{"u": "u"}'::jsonb);
51+
52+
BEGIN
53+
PERFORM cs_unique_v1_v0('{}'::jsonb);
54+
RAISE NOTICE 'Missing index. Function call should have failed.';
55+
ASSERT false;
56+
EXCEPTION
57+
WHEN OTHERS THEN
58+
ASSERT true;
59+
END;
60+
END;
61+
$$ LANGUAGE plpgsql;
62+
63+
64+
DO $$
65+
BEGIN
66+
-- sanity check
67+
PERFORM cs_match_v1('{"m": []}'::jsonb);
68+
69+
BEGIN
70+
PERFORM cs_match_v1('{}'::jsonb);
71+
RAISE NOTICE 'Missing index. Function call should have failed.';
72+
ASSERT false;
73+
EXCEPTION
74+
WHEN OTHERS THEN
75+
ASSERT true;
76+
END;
77+
END;
78+
$$ LANGUAGE plpgsql;
79+

0 commit comments

Comments
 (0)