diff --git a/sql/016-operators-match.sql b/sql/016-operators-match.sql index e3e9e7e..4c3b8b5 100644 --- a/sql/016-operators-match.sql +++ b/sql/016-operators-match.sql @@ -2,21 +2,21 @@ -- -- Support for the following comparisons: -- --- cs_encrypted_v1 @> cs_encrypted_v1 --- cs_encrypted_v1 @> jsonb --- cs_encrypted_v1 @> cs_match_index_v1 +-- cs_encrypted_v1 ~~ cs_encrypted_v1 +-- cs_encrypted_v1 ~~ jsonb +-- cs_encrypted_v1 ~~ cs_match_index_v1 -- -DROP OPERATOR IF EXISTS @> (cs_encrypted_v1, cs_encrypted_v1); -DROP FUNCTION IF EXISTS cs_encrypted_contains_v1(a cs_encrypted_v1, b cs_encrypted_v1); +DROP OPERATOR IF EXISTS ~~ (cs_encrypted_v1, cs_encrypted_v1); +DROP FUNCTION IF EXISTS cs_encrypted_match_v1(a cs_encrypted_v1, b cs_encrypted_v1); -CREATE FUNCTION cs_encrypted_contains_v1(a cs_encrypted_v1, b cs_encrypted_v1) +CREATE FUNCTION cs_encrypted_match_v1(a cs_encrypted_v1, b cs_encrypted_v1) RETURNS boolean AS $$ SELECT cs_match_v1(a) @> cs_match_v1(b); $$ LANGUAGE SQL; -CREATE OPERATOR @>( - PROCEDURE="cs_encrypted_contains_v1", +CREATE OPERATOR ~~( + PROCEDURE="cs_encrypted_match_v1", LEFTARG=cs_encrypted_v1, RIGHTARG=cs_encrypted_v1, RESTRICT = eqsel, @@ -25,17 +25,37 @@ CREATE OPERATOR @>( MERGES ); +CREATE OPERATOR ~~*( + PROCEDURE="cs_encrypted_match_v1", + LEFTARG=cs_encrypted_v1, + RIGHTARG=cs_encrypted_v1, + RESTRICT = eqsel, + JOIN = eqjoinsel, + HASHES, + MERGES +); -DROP OPERATOR IF EXISTS @> (cs_encrypted_v1, cs_match_index_v1); -DROP FUNCTION IF EXISTS cs_encrypted_contains_v1(a cs_encrypted_v1, b cs_match_index_v1); -CREATE FUNCTION cs_encrypted_contains_v1(a cs_encrypted_v1, b cs_match_index_v1) +DROP OPERATOR IF EXISTS ~~ (cs_encrypted_v1, cs_match_index_v1); +DROP FUNCTION IF EXISTS cs_encrypted_match_v1(a cs_encrypted_v1, b cs_match_index_v1); + +CREATE FUNCTION cs_encrypted_match_v1(a cs_encrypted_v1, b cs_match_index_v1) RETURNS boolean AS $$ SELECT cs_match_v1(a) @> b; $$ LANGUAGE SQL; -CREATE OPERATOR @>( - PROCEDURE="cs_encrypted_contains_v1", +CREATE OPERATOR ~~( + PROCEDURE="cs_encrypted_match_v1", + LEFTARG=cs_encrypted_v1, + RIGHTARG=cs_match_index_v1, + RESTRICT = eqsel, + JOIN = eqjoinsel, + HASHES, + MERGES +); + +CREATE OPERATOR ~~*( + PROCEDURE="cs_encrypted_match_v1", LEFTARG=cs_encrypted_v1, RIGHTARG=cs_match_index_v1, RESTRICT = eqsel, @@ -46,16 +66,16 @@ CREATE OPERATOR @>( -DROP OPERATOR IF EXISTS @> (cs_match_index_v1, cs_encrypted_v1); -DROP FUNCTION IF EXISTS cs_encrypted_contains_v1(a cs_match_index_v1, b cs_encrypted_v1); +DROP OPERATOR IF EXISTS ~~ (cs_match_index_v1, cs_encrypted_v1); +DROP FUNCTION IF EXISTS cs_encrypted_match_v1(a cs_match_index_v1, b cs_encrypted_v1); -CREATE FUNCTION cs_encrypted_contains_v1(a cs_match_index_v1, b cs_encrypted_v1) +CREATE FUNCTION cs_encrypted_match_v1(a cs_match_index_v1, b cs_encrypted_v1) RETURNS boolean AS $$ SELECT a @> cs_match_v1(b); $$ LANGUAGE SQL; -CREATE OPERATOR @>( - PROCEDURE="cs_encrypted_contains_v1", +CREATE OPERATOR ~~( + PROCEDURE="cs_encrypted_match_v1", LEFTARG=cs_match_index_v1, RIGHTARG=cs_encrypted_v1, RESTRICT = eqsel, @@ -64,22 +84,39 @@ CREATE OPERATOR @>( MERGES ); - ------------------------------------------------------------------------------ +CREATE OPERATOR ~~*( + PROCEDURE="cs_encrypted_match_v1", + LEFTARG=cs_match_index_v1, + RIGHTARG=cs_encrypted_v1, + RESTRICT = eqsel, + JOIN = eqjoinsel, + HASHES, + MERGES +); -DROP OPERATOR IF EXISTS <@ (cs_encrypted_v1, cs_encrypted_v1); -DROP FUNCTION IF EXISTS cs_encrypted_contained_v1(a cs_encrypted_v1, b cs_encrypted_v1); +DROP OPERATOR IF EXISTS ~~ (cs_match_index_v1, cs_match_index_v1); +DROP FUNCTION IF EXISTS cs_encrypted_match_v1(a cs_match_index_v1, b cs_match_index_v1); -CREATE FUNCTION cs_encrypted_contained_v1(a cs_encrypted_v1, b cs_encrypted_v1) +CREATE FUNCTION cs_encrypted_match_v1(a cs_match_index_v1, b cs_match_index_v1) RETURNS boolean AS $$ - SELECT cs_match_v1(a) <@ cs_match_v1(b); + SELECT a @> b; $$ LANGUAGE SQL; -CREATE OPERATOR <@( - PROCEDURE="cs_encrypted_contained_v1", - LEFTARG=cs_encrypted_v1, - RIGHTARG=cs_encrypted_v1, +CREATE OPERATOR ~~( + PROCEDURE="cs_encrypted_match_v1", + LEFTARG=cs_match_index_v1, + RIGHTARG=cs_match_index_v1, + RESTRICT = eqsel, + JOIN = eqjoinsel, + HASHES, + MERGES +); + +CREATE OPERATOR ~~*( + PROCEDURE="cs_encrypted_match_v1", + LEFTARG=cs_match_index_v1, + RIGHTARG=cs_match_index_v1, RESTRICT = eqsel, JOIN = eqjoinsel, HASHES, @@ -87,18 +124,28 @@ CREATE OPERATOR <@( ); -DROP OPERATOR IF EXISTS <@ (cs_encrypted_v1, cs_match_index_v1); -DROP FUNCTION IF EXISTS cs_encrypted_contained_v1(a cs_encrypted_v1, b cs_match_index_v1); +DROP OPERATOR IF EXISTS ~~ (cs_encrypted_v1, jsonb); +DROP FUNCTION IF EXISTS cs_encrypted_match_v1(a cs_encrypted_v1, b jsonb); -CREATE FUNCTION cs_encrypted_contained_v1(a cs_encrypted_v1, b cs_match_index_v1) +CREATE FUNCTION cs_encrypted_match_v1(a cs_encrypted_v1, b jsonb) RETURNS boolean AS $$ - SELECT cs_match_v1(a) <@ b; + SELECT cs_match_v1(a) @> cs_match_v1(b); $$ LANGUAGE SQL; -CREATE OPERATOR <@ ( - PROCEDURE="cs_encrypted_contained_v1", +CREATE OPERATOR ~~( + PROCEDURE="cs_encrypted_match_v1", LEFTARG=cs_encrypted_v1, - RIGHTARG=cs_match_index_v1, + RIGHTARG=jsonb, + RESTRICT = eqsel, + JOIN = eqjoinsel, + HASHES, + MERGES +); + +CREATE OPERATOR ~~*( + PROCEDURE="cs_encrypted_match_v1", + LEFTARG=cs_encrypted_v1, + RIGHTARG=jsonb, RESTRICT = eqsel, JOIN = eqjoinsel, HASHES, @@ -106,17 +153,18 @@ CREATE OPERATOR <@ ( ); -DROP OPERATOR IF EXISTS <@ (cs_match_index_v1, cs_encrypted_v1); -DROP FUNCTION IF EXISTS cs_encrypted_contained_v1(a cs_match_index_v1, b cs_encrypted_v1); -CREATE FUNCTION cs_encrypted_contained_v1(a cs_match_index_v1, b cs_encrypted_v1) +DROP OPERATOR IF EXISTS ~~ (jsonb, cs_encrypted_v1); +DROP FUNCTION IF EXISTS cs_encrypted_match_v1(a jsonb, b cs_encrypted_v1); + +CREATE FUNCTION cs_encrypted_match_v1(a jsonb, b cs_encrypted_v1) RETURNS boolean AS $$ - SELECT a <@ cs_match_v1(b); + SELECT cs_match_v1(a) @> cs_match_v1(b); $$ LANGUAGE SQL; -CREATE OPERATOR <@ ( - PROCEDURE="cs_encrypted_contained_v1", - LEFTARG=cs_match_index_v1, +CREATE OPERATOR ~~( + PROCEDURE="cs_encrypted_match_v1", + LEFTARG=jsonb, RIGHTARG=cs_encrypted_v1, RESTRICT = eqsel, JOIN = eqjoinsel, @@ -124,7 +172,16 @@ CREATE OPERATOR <@ ( MERGES ); +CREATE OPERATOR ~~*( + PROCEDURE="cs_encrypted_match_v1", + LEFTARG=jsonb, + RIGHTARG=cs_encrypted_v1, + RESTRICT = eqsel, + JOIN = eqjoinsel, + HASHES, + MERGES +); ------------------------------------------------------------------------------------------ +-- ----------------------------------------------------------------------------- diff --git a/sql/017-operators-ore.sql b/sql/017-operators-ore.sql index 400a683..15f306a 100644 --- a/sql/017-operators-ore.sql +++ b/sql/017-operators-ore.sql @@ -411,16 +411,23 @@ CREATE FUNCTION cs_encrypted_ore_64_8_compare(a cs_encrypted_v1, b cs_encrypted_ END; $$ LANGUAGE plpgsql; -DROP FUNCTION IF EXISTS cs_encrypted_ore_64_8_compare(a cs_encrypted_v1, b cs_encrypted_v1); +DROP FUNCTION IF EXISTS cs_encrypted_ore_64_8_compare(a cs_encrypted_v1, b jsonb); CREATE FUNCTION cs_encrypted_ore_64_8_compare(a cs_encrypted_v1, b jsonb) RETURNS integer AS $$ BEGIN - RETURN compare_ore_64_8_v1(cs_ore_64_8_v1(a), cs_ore_64_8_v1(jsonb)); + RETURN compare_ore_64_8_v1(cs_ore_64_8_v1(a), cs_ore_64_8_v1(b)); END; $$ LANGUAGE plpgsql; +CREATE FUNCTION cs_encrypted_ore_64_8_compare(a cs_encrypted_v1, b jsonb) + RETURNS integer AS $$ + BEGIN + RETURN compare_ore_64_8_v1(cs_ore_64_8_v1(a), cs_ore_64_8_v1(b)); + END; +$$ LANGUAGE plpgsql; + ----------------------------------------------------------------------------------------- diff --git a/tests/operators-match.sql b/tests/operators-match.sql index b7ddf33..58743d4 100644 --- a/tests/operators-match.sql +++ b/tests/operators-match.sql @@ -29,21 +29,40 @@ INSERT INTO users (name_encrypted) VALUES ( --- MATCH @> OPERATORS +-- MATCH ~~ OPERATORS DO $$ BEGIN -- SANITY CHECK - ASSERT (SELECT EXISTS (SELECT id FROM users WHERE cs_match_v1(name_encrypted) @> cs_match_v1('{"m":[1,2]}'))); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE cs_match_v1(name_encrypted) ~~ cs_match_v1('{"m":[1,2]}'))); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE cs_match_v1(name_encrypted) ~~* cs_match_v1('{"m":[1,2]}'))); -- cs_encrypted_v1 = jsonb - ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted @> '{"m":[1,2]}'::jsonb)); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted ~~ '{"m":[1,2]}'::jsonb)); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted ~~* '{"m":[1,2]}'::jsonb)); + + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE '{"m":[1,2,3,6,7,8,9]}'::jsonb ~~ name_encrypted)); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE '{"m":[1,2,3,6,7,8,9]}'::jsonb ~~* name_encrypted)); -- cs_encrypted_v1 = text - ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted @> ARRAY[1,2]::smallint[])); - ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted @> ARRAY[1,2]::cs_match_index_v1)); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted ~~ ARRAY[1,2]::smallint[])); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted ~~* ARRAY[1,2]::smallint[])); + + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted ~~ ARRAY[1,2]::cs_match_index_v1)); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted ~~* ARRAY[1,2]::cs_match_index_v1)); -- cs_encrypted_v1 = cs_encrypted_v1 - ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted @> '{ + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted ~~ '{ + "v": 1, + "k": "ct", + "c": "ciphertext", + "i": { + "t": "users", + "c": "name" + }, + "m": [1, 2] + }'::cs_encrypted_v1)); + + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted ~~* '{ "v": 1, "k": "ct", "c": "ciphertext", @@ -54,26 +73,58 @@ DO $$ "m": [1, 2] }'::cs_encrypted_v1)); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE '{ + "v": 1, + "k": "ct", + "c": "ciphertext", + "i": { + "t": "users", + "c": "name" + }, + "m": [1, 2, 3, 4, 5] + }'::cs_encrypted_v1 ~~ name_encrypted)); + + + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE '{ + "v": 1, + "k": "ct", + "c": "ciphertext", + "i": { + "t": "users", + "c": "name" + }, + "m": [1, 2, 3, 4, 5] + }'::cs_encrypted_v1 ~~* name_encrypted)); + END; $$ LANGUAGE plpgsql; --- MATCH <@ OPERATORS + +-- MATCH ~~ OPERATORS DO $$ BEGIN -- SANITY CHECK - ASSERT (SELECT EXISTS (SELECT id FROM users WHERE cs_match_v1('{"m":[1,2]}') <@ cs_match_v1(name_encrypted))); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE cs_match_v1(name_encrypted) LIKE cs_match_v1('{"m":[1,2]}'))); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE cs_match_v1(name_encrypted) ILIKE cs_match_v1('{"m":[1,2]}'))); -- cs_encrypted_v1 = jsonb - ASSERT (SELECT EXISTS (SELECT id FROM users WHERE '{"m":[1,2]}'::jsonb <@ name_encrypted)); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted LIKE '{"m":[1,2]}'::jsonb)); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted ILIKE '{"m":[1,2]}'::jsonb)); + + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE '{"m":[1,2,3,6,7,8,9]}'::jsonb LIKE name_encrypted)); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE '{"m":[1,2,3,6,7,8,9]}'::jsonb ILIKE name_encrypted)); -- cs_encrypted_v1 = text - ASSERT (SELECT EXISTS (SELECT id FROM users WHERE ARRAY[1,2]::smallint[] <@ name_encrypted)); - ASSERT (SELECT EXISTS (SELECT id FROM users WHERE ARRAY[1,2]::cs_match_index_v1 <@ name_encrypted)); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted LIKE ARRAY[1,2]::smallint[])); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted ILIKE ARRAY[1,2]::smallint[])); + + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted LIKE ARRAY[1,2]::cs_match_index_v1)); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted ILIKE ARRAY[1,2]::cs_match_index_v1)); -- cs_encrypted_v1 = cs_encrypted_v1 - ASSERT (SELECT EXISTS (SELECT id FROM users WHERE '{ + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted LIKE '{ "v": 1, "k": "ct", "c": "ciphertext", @@ -82,9 +133,41 @@ DO $$ "c": "name" }, "m": [1, 2] - }'::cs_encrypted_v1 <@ name_encrypted)); + }'::cs_encrypted_v1)); - END; -$$ LANGUAGE plpgsql; + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE name_encrypted ILIKE '{ + "v": 1, + "k": "ct", + "c": "ciphertext", + "i": { + "t": "users", + "c": "name" + }, + "m": [1, 2] + }'::cs_encrypted_v1)); + + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE '{ + "v": 1, + "k": "ct", + "c": "ciphertext", + "i": { + "t": "users", + "c": "name" + }, + "m": [1, 2, 3, 4, 5] + }'::cs_encrypted_v1 LIKE name_encrypted)); + ASSERT (SELECT EXISTS (SELECT id FROM users WHERE '{ + "v": 1, + "k": "ct", + "c": "ciphertext", + "i": { + "t": "users", + "c": "name" + }, + "m": [1, 2, 3, 4, 5] + }'::cs_encrypted_v1 ILIKE name_encrypted)); + + END; +$$ LANGUAGE plpgsql; \ No newline at end of file