diff --git a/sql/010-core.sql b/sql/010-core.sql index b85a9eb..9b48c85 100644 --- a/sql/010-core.sql +++ b/sql/010-core.sql @@ -159,125 +159,145 @@ 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(col jsonb) - RETURNS text - LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -BEGIN ATOMIC - RETURN col->>'c'; -END; +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; -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 +323,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); +DROP FUNCTION IF EXISTS cs_ore_64_8_v1_v0(val jsonb); -CREATE FUNCTION cs_ore_64_8_v1_v0(col 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 0000000..792a7e3 --- /dev/null +++ b/tests/core-functions.sql @@ -0,0 +1,79 @@ +\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))); + 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 + 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; +