From 0654418e50e29f434b9fd6dd3bf23045d896bb56 Mon Sep 17 00:00:00 2001 From: Toby Hede Date: Mon, 4 Nov 2024 16:24:11 +1100 Subject: [PATCH 1/2] Raise exceptions if index fields are missing --- sql/010-core.sql | 160 +++++++++++++++++++++------------------ tests/core-functions.sql | 43 +++++++++++ 2 files changed, 130 insertions(+), 73 deletions(-) create mode 100644 tests/core-functions.sql diff --git a/sql/010-core.sql b/sql/010-core.sql index b85a9eb4..36f14f57 100644 --- a/sql/010-core.sql +++ b/sql/010-core.sql @@ -159,125 +159,147 @@ ALTER DOMAIN cs_encrypted_v1 ); -DROP FUNCTION IF EXISTS cs_ciphertext_v1_v0_0(col jsonb); +DROP FUNCTION IF EXISTS cs_ciphertext_v1_v0_0(val jsonb); + +CREATE FUNCTION cs_ciphertext_v1_v0_0(val jsonb) + RETURNS text + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + BEGIN + IF val ? 'c' THEN + RETURN val->>'c'; + END IF; + RAISE 'Expected a ciphertext (c) value in json: %', val; + END; +$$ LANGUAGE plpgsql; -CREATE FUNCTION cs_ciphertext_v1_v0_0(col jsonb) - RETURNS text - LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -BEGIN ATOMIC - RETURN col->>'c'; -END; -DROP FUNCTION IF EXISTS cs_ciphertext_v1_v0(col jsonb); +DROP FUNCTION IF EXISTS cs_ciphertext_v1_v0(val jsonb); -CREATE FUNCTION cs_ciphertext_v1_v0(col jsonb) +CREATE FUNCTION cs_ciphertext_v1_v0(val jsonb) RETURNS text LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE BEGIN ATOMIC - RETURN cs_ciphertext_v1_v0_0(col); + RETURN cs_ciphertext_v1_v0_0(val); END; -DROP FUNCTION IF EXISTS cs_ciphertext_v1(col jsonb); +DROP FUNCTION IF EXISTS cs_ciphertext_v1(val jsonb); -CREATE FUNCTION cs_ciphertext_v1(col jsonb) +CREATE FUNCTION cs_ciphertext_v1(val jsonb) RETURNS text LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE BEGIN ATOMIC - RETURN cs_ciphertext_v1_v0_0(col); + RETURN cs_ciphertext_v1_v0_0(val); END; -- extracts match index from an emcrypted column -DROP FUNCTION IF EXISTS cs_match_v1_v0_0(col jsonb); +DROP FUNCTION IF EXISTS cs_match_v1_v0_0(val jsonb); -CREATE FUNCTION cs_match_v1_v0_0(col jsonb) +CREATE FUNCTION cs_match_v1_v0_0(val jsonb) RETURNS cs_match_index_v1 - LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -BEGIN ATOMIC - SELECT ARRAY(SELECT jsonb_array_elements(col->'m'))::cs_match_index_v1; -END; + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + BEGIN + + IF val ? 'm' THEN + RETURN ARRAY(SELECT jsonb_array_elements(val->'m'))::cs_match_index_v1; + END IF; + RAISE 'Expected a match index (m) value in json: %', val; + END; +$$ LANGUAGE plpgsql; -DROP FUNCTION IF EXISTS cs_match_v1_v0(col jsonb); +DROP FUNCTION IF EXISTS cs_match_v1_v0(val jsonb); -CREATE FUNCTION cs_match_v1_v0(col jsonb) +CREATE FUNCTION cs_match_v1_v0(val jsonb) RETURNS cs_match_index_v1 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE BEGIN ATOMIC - RETURN cs_match_v1_v0_0(col); + RETURN cs_match_v1_v0_0(val); END; -DROP FUNCTION IF EXISTS cs_match_v1(col jsonb); +DROP FUNCTION IF EXISTS cs_match_v1(val jsonb); -CREATE FUNCTION cs_match_v1(col jsonb) +CREATE FUNCTION cs_match_v1(val jsonb) RETURNS cs_match_index_v1 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE BEGIN ATOMIC - RETURN cs_match_v1_v0_0(col); + RETURN cs_match_v1_v0_0(val); END; -- extracts unique index from an encrypted column -DROP FUNCTION IF EXISTS cs_unique_v1_v0_0(col jsonb); +DROP FUNCTION IF EXISTS cs_unique_v1_v0_0(val jsonb); -CREATE FUNCTION cs_unique_v1_v0_0(col jsonb) +CREATE FUNCTION cs_unique_v1_v0_0(val jsonb) RETURNS cs_unique_index_v1 - LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -BEGIN ATOMIC - RETURN col->>'u'; -END; + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + BEGIN + IF val ? 'u' THEN + RETURN val->>'u'; + END IF; + RAISE 'Expected a unique index (u) value in json: %', val; + END; +$$ LANGUAGE plpgsql; -DROP FUNCTION IF EXISTS cs_unique_v1_v0(col jsonb); +DROP FUNCTION IF EXISTS cs_unique_v1_v0(val jsonb); -CREATE FUNCTION cs_unique_v1_v0(col jsonb) +CREATE FUNCTION cs_unique_v1_v0(val jsonb) RETURNS cs_unique_index_v1 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE BEGIN ATOMIC - RETURN cs_unique_v1_v0_0(col); + RETURN cs_unique_v1_v0_0(val); END; -DROP FUNCTION IF EXISTS cs_unique_v1(col jsonb); +DROP FUNCTION IF EXISTS cs_unique_v1(val jsonb); -CREATE FUNCTION cs_unique_v1(col jsonb) +CREATE FUNCTION cs_unique_v1(val jsonb) RETURNS cs_unique_index_v1 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE BEGIN ATOMIC - RETURN cs_unique_v1_v0_0(col); + RETURN cs_unique_v1_v0_0(val); END; -- extracts json ste_vec index from an encrypted column -DROP FUNCTION IF EXISTS cs_ste_vec_v1_v0_0(col jsonb); +DROP FUNCTION IF EXISTS cs_ste_vec_v1_v0_0(val jsonb); -CREATE FUNCTION cs_ste_vec_v1_v0_0(col jsonb) +CREATE FUNCTION cs_ste_vec_v1_v0_0(val jsonb) RETURNS cs_ste_vec_index_v1 - LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -BEGIN ATOMIC - SELECT (col->'sv')::cs_ste_vec_index_v1; -END; + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + BEGIN + IF val ? 'sv' THEN + RETURN (val->'sv')::cs_ste_vec_index_v1; + END IF; + RAISE 'Expected a structured vector index (sv) value in json: %', val; + END; +$$ LANGUAGE plpgsql; -DROP FUNCTION IF EXISTS cs_ste_vec_v1_v0(col jsonb); +DROP FUNCTION IF EXISTS cs_ste_vec_v1_v0(val jsonb); -CREATE FUNCTION cs_ste_vec_v1_v0(col jsonb) +CREATE FUNCTION cs_ste_vec_v1_v0(val jsonb) RETURNS cs_ste_vec_index_v1 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE BEGIN ATOMIC - RETURN cs_ste_vec_v1_v0_0(col); + RETURN cs_ste_vec_v1_v0_0(val); END; -DROP FUNCTION IF EXISTS cs_ste_vec_v1(col jsonb); +DROP FUNCTION IF EXISTS cs_ste_vec_v1(val jsonb); -CREATE FUNCTION cs_ste_vec_v1(col jsonb) +CREATE FUNCTION cs_ste_vec_v1(val jsonb) RETURNS cs_ste_vec_index_v1 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE BEGIN ATOMIC - RETURN cs_ste_vec_v1_v0_0(col); + RETURN cs_ste_vec_v1_v0_0(val); END; @@ -303,39 +325,31 @@ DROP FUNCTION IF EXISTS cs_ore_64_8_v1_v0_0(val jsonb); CREATE FUNCTION cs_ore_64_8_v1_v0_0(val jsonb) RETURNS ore_64_8_v1 - LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -BEGIN ATOMIC - SELECT (val->>'o')::ore_64_8_v1; -END; + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + BEGIN + IF val ? 'o' THEN + RETURN (val->>'o')::ore_64_8_v1; + END IF; + RAISE 'Expected an ore index (o) value in json: %', val; + END; +$$ LANGUAGE plpgsql; -DROP FUNCTION IF EXISTS cs_ore_64_8_v1_v0(col jsonb); -CREATE FUNCTION cs_ore_64_8_v1_v0(col jsonb) +DROP FUNCTION IF EXISTS cs_ore_64_8_v1_v0(val jsonb); + +CREATE FUNCTION cs_ore_64_8_v1_v0(val jsonb) RETURNS ore_64_8_v1 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE BEGIN ATOMIC - RETURN cs_ore_64_8_v1_v0_0(col); + RETURN cs_ore_64_8_v1_v0_0(val); END; -DROP FUNCTION IF EXISTS cs_ore_64_8_v1(col jsonb); +DROP FUNCTION IF EXISTS cs_ore_64_8_v1(val jsonb); -CREATE FUNCTION cs_ore_64_8_v1(col jsonb) +CREATE FUNCTION cs_ore_64_8_v1(val jsonb) RETURNS ore_64_8_v1 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE BEGIN ATOMIC - RETURN cs_ore_64_8_v1_v0_0(col); + RETURN cs_ore_64_8_v1_v0_0(val); END; - -DROP FUNCTION IF EXISTS _cs_first_grouped_value(jsonb, jsonb); - -CREATE FUNCTION _cs_first_grouped_value(jsonb, jsonb) -RETURNS jsonb AS $$ - SELECT COALESCE($1, $2); -$$ LANGUAGE sql IMMUTABLE; - -DROP AGGREGATE IF EXISTS cs_grouped_value_v1(jsonb); - -CREATE AGGREGATE cs_grouped_value_v1(jsonb) ( - SFUNC = _cs_first_grouped_value, - STYPE = jsonb -); diff --git a/tests/core-functions.sql b/tests/core-functions.sql new file mode 100644 index 00000000..fcb66a94 --- /dev/null +++ b/tests/core-functions.sql @@ -0,0 +1,43 @@ +\set ON_ERROR_STOP on + + +DO $$ + BEGIN + ASSERT (SELECT EXISTS (SELECT cs_unique_v1('{"u": "u"}'::jsonb))); + ASSERT (SELECT EXISTS (SELECT cs_match_v1('{"m": []}'::jsonb))); + END; +$$ LANGUAGE plpgsql; + +DO $$ + BEGIN + -- sanity check + PERFORM cs_unique_v1('{"u": "u"}'::jsonb); + + BEGIN + PERFORM cs_unique_v1_v0('{}'::jsonb); + RAISE NOTICE 'Missing index. Function call should have failed.'; + ASSERT false; + EXCEPTION + WHEN OTHERS THEN + ASSERT true; + END; + END; +$$ LANGUAGE plpgsql; + + +DO $$ + BEGIN + -- sanity check + PERFORM cs_match_v1('{"m": []}'::jsonb); + + BEGIN + PERFORM cs_match_v1('{}'::jsonb); + RAISE NOTICE 'Missing index. Function call should have failed.'; + ASSERT false; + EXCEPTION + WHEN OTHERS THEN + ASSERT true; + END; + END; +$$ LANGUAGE plpgsql; + From 13bf286bbb8ae1170efc820e4689024198458652 Mon Sep 17 00:00:00 2001 From: Toby Hede Date: Tue, 5 Nov 2024 12:52:28 +1100 Subject: [PATCH 2/2] Add ore and sv tests --- sql/010-core.sql | 4 +--- tests/core-functions.sql | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/sql/010-core.sql b/sql/010-core.sql index 36f14f57..9b48c852 100644 --- a/sql/010-core.sql +++ b/sql/010-core.sql @@ -174,7 +174,6 @@ AS $$ $$ LANGUAGE plpgsql; - DROP FUNCTION IF EXISTS cs_ciphertext_v1_v0(val jsonb); CREATE FUNCTION cs_ciphertext_v1_v0(val jsonb) @@ -203,7 +202,6 @@ CREATE FUNCTION cs_match_v1_v0_0(val jsonb) IMMUTABLE STRICT PARALLEL SAFE AS $$ BEGIN - IF val ? 'm' THEN RETURN ARRAY(SELECT jsonb_array_elements(val->'m'))::cs_match_index_v1; END IF; @@ -212,7 +210,7 @@ AS $$ $$ LANGUAGE plpgsql; -DROP FUNCTION IF EXISTS cs_match_v1_v0(val jsonb); +DROP FUNCTION IF EXISTS cs_match_v1_v0(val jsonb); CREATE FUNCTION cs_match_v1_v0(val jsonb) RETURNS cs_match_index_v1 diff --git a/tests/core-functions.sql b/tests/core-functions.sql index fcb66a94..792a7e3a 100644 --- a/tests/core-functions.sql +++ b/tests/core-functions.sql @@ -5,9 +5,45 @@ DO $$ BEGIN ASSERT (SELECT EXISTS (SELECT cs_unique_v1('{"u": "u"}'::jsonb))); ASSERT (SELECT EXISTS (SELECT cs_match_v1('{"m": []}'::jsonb))); + ASSERT (SELECT EXISTS (SELECT cs_ste_vec_v1('{"sv": [[]]}'::jsonb))); + ASSERT (SELECT EXISTS (SELECT cs_ore_64_8_v1('{"o": "()"}'::jsonb))); + + END; +$$ LANGUAGE plpgsql; + +DO $$ + BEGIN + -- sanity check + PERFORM cs_ore_64_8_v1('{"o": "()"}'::jsonb); + + BEGIN + PERFORM cs_ore_64_8_v1('{}'::jsonb); + RAISE NOTICE 'Missing index. Function call should have failed.'; + ASSERT false; + EXCEPTION + WHEN OTHERS THEN + ASSERT true; + END; END; $$ LANGUAGE plpgsql; +DO $$ + BEGIN + -- sanity check + PERFORM cs_ste_vec_v1('{"sv": [[]]}'::jsonb); + + BEGIN + PERFORM cs_ste_vec_v1('{}'::jsonb); + RAISE NOTICE 'Missing index. Function call should have failed.'; + ASSERT false; + EXCEPTION + WHEN OTHERS THEN + ASSERT true; + END; + END; +$$ LANGUAGE plpgsql; + + DO $$ BEGIN -- sanity check