diff --git a/diagrams/overview-insert.drawio.svg b/diagrams/overview-insert.drawio.svg
deleted file mode 100644
index cef7acf..0000000
--- a/diagrams/overview-insert.drawio.svg
+++ /dev/null
@@ -1,457 +0,0 @@
-
\ No newline at end of file
diff --git a/diagrams/overview-select.drawio.svg b/diagrams/overview-select.drawio.svg
deleted file mode 100644
index 1effb5a..0000000
--- a/diagrams/overview-select.drawio.svg
+++ /dev/null
@@ -1,552 +0,0 @@
-
diff --git a/src/blake3/functions.sql b/src/blake3/functions.sql
new file mode 100644
index 0000000..3682c84
--- /dev/null
+++ b/src/blake3/functions.sql
@@ -0,0 +1,38 @@
+-- REQUIRE: src/schema.sql
+
+-- extracts ste_vec index from a jsonb value
+-- DROP FUNCTION IF EXISTS eql_v1.blake3(val jsonb);
+
+-- extracts blake3 index from a jsonb value
+-- DROP FUNCTION IF EXISTS eql_v1.blake3(val jsonb);
+
+CREATE FUNCTION eql_v1.blake3(val jsonb)
+ RETURNS eql_v1.blake3
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+
+ IF NOT (val ? 'b') NULL THEN
+ RAISE 'Expected a blake3 index (b) value in json: %', val;
+ END IF;
+
+ IF val->>'b' IS NULL THEN
+ RETURN NULL;
+ END IF;
+
+ RETURN val->>'b';
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- extracts blake3 index from an eql_v1_encrypted value
+-- DROP FUNCTION IF EXISTS eql_v1.blake3(val eql_v1_encrypted);
+
+CREATE FUNCTION eql_v1.blake3(val eql_v1_encrypted)
+ RETURNS eql_v1.blake3
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN (SELECT eql_v1.blake3(val.data));
+ END;
+$$ LANGUAGE plpgsql;
diff --git a/src/blake3/types.sql b/src/blake3/types.sql
new file mode 100644
index 0000000..ab6f965
--- /dev/null
+++ b/src/blake3/types.sql
@@ -0,0 +1,4 @@
+-- REQUIRE: src/schema.sql
+
+-- DROP DOMAIN IF EXISTS eql_v1.blake3;
+CREATE DOMAIN eql_v1.blake3 AS text;
diff --git a/src/common.sql b/src/common.sql
index ff587e0..3e4ed9e 100644
--- a/src/common.sql
+++ b/src/common.sql
@@ -2,11 +2,65 @@
-- REQUIRE: src/schema.sql
+-- Constant time comparison of 2 bytea values
+
+
+
+
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.bytea_eq(a bytea, b bytea);
+
+CREATE FUNCTION eql_v1.bytea_eq(a bytea, b bytea) RETURNS boolean AS $$
+DECLARE
+ result boolean;
+ differing bytea;
+BEGIN
+
+ -- Check if the bytea values are the same length
+ IF LENGTH(a) != LENGTH(b) THEN
+ RETURN false;
+ END IF;
+
+ -- Compare each byte in the bytea values
+ result := true;
+ FOR i IN 1..LENGTH(a) LOOP
+ IF SUBSTRING(a FROM i FOR 1) != SUBSTRING(b FROM i FOR 1) THEN
+ result := result AND false;
+ END IF;
+ END LOOP;
+
+ RETURN result;
+END;
+$$ LANGUAGE plpgsql;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_array_to_bytea_array(val jsonb);
+
+-- Casts a jsonb array of hex-encoded strings to an array of bytea.
+CREATE FUNCTION eql_v1.jsonb_array_to_bytea_array(val jsonb)
+RETURNS bytea[] AS $$
+DECLARE
+ terms_arr bytea[];
+BEGIN
+ IF jsonb_typeof(val) = 'null' THEN
+ RETURN NULL;
+ END IF;
+
+ SELECT array_agg(decode(value::text, 'hex')::bytea)
+ INTO terms_arr
+ FROM jsonb_array_elements_text(val) AS value;
+
+ RETURN terms_arr;
+END;
+$$ LANGUAGE plpgsql;
+
+
--
-- Convenience function to log a message
--
-DROP FUNCTION IF EXISTS eql_v1.log(text);
+-- DROP FUNCTION IF EXISTS eql_v1.log(text);
CREATE FUNCTION eql_v1.log(s text)
RETURNS void
AS $$
@@ -19,7 +73,7 @@ $$ LANGUAGE plpgsql;
--
-- Convenience function to describe a test
--
-DROP FUNCTION IF EXISTS eql_v1.log(text, text);
+-- DROP FUNCTION IF EXISTS eql_v1.log(text, text);
CREATE FUNCTION eql_v1.log(ctx text, s text)
RETURNS void
AS $$
diff --git a/src/config/config_test.sql b/src/config/config_test.sql
index 500e9ca..227e9c9 100644
--- a/src/config/config_test.sql
+++ b/src/config/config_test.sql
@@ -4,7 +4,7 @@
--
-- Helper function for assertions
--
-DROP FUNCTION IF EXISTS _index_exists(text, text, text, text);
+-- DROP FUNCTION IF EXISTS _index_exists(text, text, text, text);
CREATE FUNCTION _index_exists(table_name text, column_name text, index_name text, state text DEFAULT 'pending')
RETURNS boolean
LANGUAGE sql STRICT PARALLEL SAFE
diff --git a/src/config/constraints.sql b/src/config/constraints.sql
index a5ad001..b69349a 100644
--- a/src/config/constraints.sql
+++ b/src/config/constraints.sql
@@ -5,7 +5,7 @@
--
-- Used by the eql_v1.config_check_indexes as part of the configuration_data_v1 constraint
--
-DROP FUNCTION IF EXISTS eql_v1.config_get_indexes(jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.config_get_indexes(jsonb);
CREATE FUNCTION eql_v1.config_get_indexes(val jsonb)
RETURNS SETOF text
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
@@ -18,7 +18,7 @@ END;
--
-- Used by the cs_configuration_data_v1_check constraint
--
-DROP FUNCTION IF EXISTS eql_v1.config_check_indexes(jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.config_check_indexes(jsonb);
CREATE FUNCTION eql_v1.config_check_indexes(val jsonb)
RETURNS BOOLEAN
IMMUTABLE STRICT PARALLEL SAFE
@@ -36,7 +36,7 @@ AS $$
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.config_check_cast(jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.config_check_cast(jsonb);
CREATE FUNCTION eql_v1.config_check_cast(val jsonb)
RETURNS BOOLEAN
@@ -52,7 +52,7 @@ $$ LANGUAGE plpgsql;
--
-- Should include a tables field
-- Tables should not be empty
-DROP FUNCTION IF EXISTS eql_v1.config_check_tables(jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.config_check_tables(jsonb);
CREATE FUNCTION eql_v1.config_check_tables(val jsonb)
RETURNS boolean
AS $$
@@ -65,7 +65,7 @@ AS $$
$$ LANGUAGE plpgsql;
-- Should include a version field
-DROP FUNCTION IF EXISTS eql_v1.config_check_version(jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.config_check_version(jsonb);
CREATE FUNCTION eql_v1.config_check_version(val jsonb)
RETURNS boolean
AS $$
diff --git a/src/config/functions.sql b/src/config/functions.sql
index ec948e6..100d00a 100644
--- a/src/config/functions.sql
+++ b/src/config/functions.sql
@@ -4,7 +4,7 @@
--
--
-DROP FUNCTION IF EXISTS eql_v1.config_default(config jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.config_default(config jsonb);
CREATE FUNCTION eql_v1.config_default(config jsonb)
RETURNS jsonb
@@ -19,7 +19,7 @@ AS $$
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.config_add_table(table_name text, config jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.config_add_table(table_name text, config jsonb);
CREATE FUNCTION eql_v1.config_add_table(table_name text, config jsonb)
RETURNS jsonb
@@ -37,7 +37,7 @@ $$ LANGUAGE plpgsql;
-- Add the column if it doesn't exist
-DROP FUNCTION IF EXISTS eql_v1.config_add_column(table_name text, column_name text, config jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.config_add_column(table_name text, column_name text, config jsonb);
CREATE FUNCTION eql_v1.config_add_column(table_name text, column_name text, config jsonb)
RETURNS jsonb
@@ -56,7 +56,7 @@ $$ LANGUAGE plpgsql;
-- Set the cast
-DROP FUNCTION IF EXISTS eql_v1.config_add_cast(table_name text, column_name text, cast_as text, config jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.config_add_cast(table_name text, column_name text, cast_as text, config jsonb);
CREATE FUNCTION eql_v1.config_add_cast(table_name text, column_name text, cast_as text, config jsonb)
RETURNS jsonb
@@ -70,7 +70,7 @@ $$ LANGUAGE plpgsql;
-- Add the column if it doesn't exist
-DROP FUNCTION IF EXISTS eql_v1.config_add_index(table_name text, column_name text, index_name text, opts jsonb, config jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.config_add_index(table_name text, column_name text, index_name text, opts jsonb, config jsonb);
CREATE FUNCTION eql_v1.config_add_index(table_name text, column_name text, index_name text, opts jsonb, config jsonb)
RETURNS jsonb
@@ -86,7 +86,7 @@ $$ LANGUAGE plpgsql;
--
-- Default options for match index
--
-DROP FUNCTION IF EXISTS eql_v1.config_match_default();
+-- DROP FUNCTION IF EXISTS eql_v1.config_match_default();
CREATE FUNCTION eql_v1.config_match_default()
RETURNS jsonb
@@ -103,7 +103,7 @@ END;
--
-- Adds an index term to the configuration
--
-DROP FUNCTION IF EXISTS eql_v1.add_index(table_name text, column_name text, index_name text, cast_as text, opts jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.add_index(table_name text, column_name text, index_name text, cast_as text, opts jsonb);
CREATE FUNCTION eql_v1.add_index(table_name text, column_name text, index_name text, cast_as text DEFAULT 'text', opts jsonb DEFAULT '{}')
RETURNS jsonb
@@ -155,7 +155,7 @@ AS $$
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.remove_index(table_name text, column_name text, index_name text);
+-- DROP FUNCTION IF EXISTS eql_v1.remove_index(table_name text, column_name text, index_name text);
CREATE FUNCTION eql_v1.remove_index(table_name text, column_name text, index_name text)
RETURNS jsonb
@@ -216,7 +216,7 @@ AS $$
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.modify_index(table_name text, column_name text, index_name text, cast_as text, opts jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.modify_index(table_name text, column_name text, index_name text, cast_as text, opts jsonb);
CREATE FUNCTION eql_v1.modify_index(table_name text, column_name text, index_name text, cast_as text DEFAULT 'text', opts jsonb DEFAULT '{}')
RETURNS jsonb
@@ -240,7 +240,7 @@ $$ LANGUAGE plpgsql;
--
-- Raises an exception if the configuration is already `encrypting` or if there is no `pending` configuration to encrypt.
--
-DROP FUNCTION IF EXISTS eql_v1.encrypt();
+-- DROP FUNCTION IF EXISTS eql_v1.encrypt();
CREATE FUNCTION eql_v1.encrypt(force boolean DEFAULT false)
RETURNS boolean
@@ -267,7 +267,7 @@ AS $$
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.activate();
+-- DROP FUNCTION IF EXISTS eql_v1.activate();
CREATE FUNCTION eql_v1.activate()
RETURNS boolean
@@ -285,7 +285,7 @@ AS $$
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.discard();
+-- DROP FUNCTION IF EXISTS eql_v1.discard();
CREATE FUNCTION eql_v1.discard()
RETURNS boolean
@@ -301,7 +301,7 @@ AS $$
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.add_column(table_name text, column_name text, cast_as text);
+-- DROP FUNCTION IF EXISTS eql_v1.add_column(table_name text, column_name text, cast_as text);
CREATE FUNCTION eql_v1.add_column(table_name text, column_name text, cast_as text DEFAULT 'text')
RETURNS jsonb
@@ -340,7 +340,7 @@ AS $$
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.remove_column(table_name text, column_name text);
+-- DROP FUNCTION IF EXISTS eql_v1.remove_column(table_name text, column_name text);
CREATE FUNCTION eql_v1.remove_column(table_name text, column_name text)
RETURNS jsonb
@@ -396,7 +396,7 @@ AS $$
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.reload_config();
+-- DROP FUNCTION IF EXISTS eql_v1.reload_config();
CREATE FUNCTION eql_v1.reload_config()
RETURNS void
@@ -405,7 +405,7 @@ BEGIN ATOMIC
RETURN NULL;
END;
-DROP FUNCTION IF EXISTS eql_v1.config();
+-- DROP FUNCTION IF EXISTS eql_v1.config();
-- A convenience function to return the configuration in a tabular format, allowing for easier filtering, and querying.
-- Query using `SELECT * FROM cs_config();`
diff --git a/src/config/tables.sql b/src/config/tables.sql
index 43fd3c9..c22e800 100644
--- a/src/config/tables.sql
+++ b/src/config/tables.sql
@@ -2,7 +2,7 @@
--
--
--- CREATE the cs_configuration_v1 TABLE
+-- CREATE the eql_v1_configuration TABLE
--
CREATE TABLE IF NOT EXISTS public.eql_v1_configuration
(
diff --git a/src/encrypted/aggregates.sql b/src/encrypted/aggregates.sql
index 9e2dff1..78a2c20 100644
--- a/src/encrypted/aggregates.sql
+++ b/src/encrypted/aggregates.sql
@@ -3,8 +3,8 @@
-- REQUIRE: src/ore/functions.sql
-- Aggregate functions for ORE
-DROP AGGREGATE IF EXISTS eql_v1.min(eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1.min(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP AGGREGATE IF EXISTS eql_v1.min(eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.min(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.min(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS eql_v1_encrypted
@@ -27,8 +27,8 @@ CREATE AGGREGATE eql_v1.min(eql_v1_encrypted)
stype = eql_v1_encrypted
);
-DROP AGGREGATE IF EXISTS eql_v1.max(eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1.max(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP AGGREGATE IF EXISTS eql_v1.max(eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.max(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.max(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS eql_v1_encrypted
diff --git a/src/encrypted/aggregates_test.sql b/src/encrypted/aggregates_test.sql
index 4872ca8..285d2fa 100644
--- a/src/encrypted/aggregates_test.sql
+++ b/src/encrypted/aggregates_test.sql
@@ -1,7 +1,7 @@
\set ON_ERROR_STOP on
-- create table
-DROP TABLE IF EXISTS agg_test;
+-- DROP TABLE IF EXISTS agg_test;
CREATE TABLE agg_test
(
plain_int integer,
diff --git a/src/encrypted/casts.sql b/src/encrypted/casts.sql
index 0c63c5b..2b6470b 100644
--- a/src/encrypted/casts.sql
+++ b/src/encrypted/casts.sql
@@ -5,7 +5,7 @@
--
-- Convert jsonb to eql_v1.encrypted
--
-DROP FUNCTION IF EXISTS eql_v1.to_encrypted(data jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.to_encrypted(data jsonb);
CREATE FUNCTION eql_v1.to_encrypted(data jsonb)
RETURNS public.eql_v1_encrypted AS $$
@@ -17,7 +17,7 @@ $$ LANGUAGE plpgsql;
--
-- Cast jsonb to eql_v1.encrypted
--
-DROP CAST IF EXISTS (jsonb AS public.eql_v1_encrypted);
+-- DROP CAST IF EXISTS (jsonb AS public.eql_v1_encrypted);
CREATE CAST (jsonb AS public.eql_v1_encrypted)
WITH FUNCTION eql_v1.to_encrypted(jsonb) AS IMPLICIT;
@@ -26,7 +26,7 @@ CREATE CAST (jsonb AS public.eql_v1_encrypted)
--
-- Convert text to eql_v1.encrypted
--
-DROP FUNCTION IF EXISTS eql_v1.to_encrypted(data text);
+-- DROP FUNCTION IF EXISTS eql_v1.to_encrypted(data text);
CREATE FUNCTION eql_v1.to_encrypted(data text)
RETURNS public.eql_v1_encrypted AS $$
@@ -38,7 +38,7 @@ $$ LANGUAGE plpgsql;
--
-- Cast text to eql_v1.encrypted
--
-DROP CAST IF EXISTS (text AS public.eql_v1_encrypted);
+-- DROP CAST IF EXISTS (text AS public.eql_v1_encrypted);
CREATE CAST (text AS public.eql_v1_encrypted)
WITH FUNCTION eql_v1.to_encrypted(text) AS IMPLICIT;
@@ -48,7 +48,7 @@ CREATE CAST (text AS public.eql_v1_encrypted)
--
-- Convert eql_v1.encrypted to jsonb
--
-DROP FUNCTION IF EXISTS eql_v1.to_jsonb(e public.eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.to_jsonb(e public.eql_v1_encrypted);
CREATE FUNCTION eql_v1.to_jsonb(e public.eql_v1_encrypted)
RETURNS jsonb AS $$
@@ -60,7 +60,7 @@ $$ LANGUAGE plpgsql;
--
-- Cast eql_v1.encrypted to jsonb
--
-DROP CAST IF EXISTS (public.eql_v1_encrypted AS jsonb);
+-- DROP CAST IF EXISTS (public.eql_v1_encrypted AS jsonb);
CREATE CAST (public.eql_v1_encrypted AS jsonb)
WITH FUNCTION eql_v1.to_jsonb(public.eql_v1_encrypted) AS ASSIGNMENT;
diff --git a/src/encrypted/constraints.sql b/src/encrypted/constraints.sql
index 9103212..3296b25 100644
--- a/src/encrypted/constraints.sql
+++ b/src/encrypted/constraints.sql
@@ -76,7 +76,7 @@
-- $$ LANGUAGE plpgsql;
-- Should include an ident field
-DROP FUNCTION IF EXISTS eql_v1._encrypted_check_i(jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1._encrypted_check_i(jsonb);
CREATE FUNCTION eql_v1._encrypted_check_i(val jsonb)
RETURNS boolean
AS $$
@@ -106,7 +106,7 @@ $$ LANGUAGE plpgsql;
-- $$ LANGUAGE plpgsql;
-- Ident field should include table and column
-DROP FUNCTION IF EXISTS eql_v1._encrypted_check_i_ct(jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1._encrypted_check_i_ct(jsonb);
CREATE FUNCTION eql_v1._encrypted_check_i_ct(val jsonb)
RETURNS boolean
AS $$
@@ -132,7 +132,7 @@ $$ LANGUAGE plpgsql;
-- $$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.check_encrypted(val jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.check_encrypted(val jsonb);
CREATE FUNCTION eql_v1.check_encrypted(val jsonb)
RETURNS BOOLEAN
diff --git a/src/encrypted/functions.sql b/src/encrypted/functions.sql
index fb09bf4..f200943 100644
--- a/src/encrypted/functions.sql
+++ b/src/encrypted/functions.sql
@@ -4,7 +4,7 @@
-- REQUIRE: src/unique/types.sql
-DROP FUNCTION IF EXISTS eql_v1.ciphertext(val jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.ciphertext(val jsonb);
CREATE FUNCTION eql_v1.ciphertext(val jsonb)
RETURNS text
@@ -19,26 +19,26 @@ AS $$
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.to_jsonb(val eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.ciphertext(val eql_v1_encrypted);
-CREATE FUNCTION eql_v1.to_jsonb(val eql_v1_encrypted)
- RETURNS jsonb
+CREATE FUNCTION eql_v1.ciphertext(val eql_v1_encrypted)
+ RETURNS text
IMMUTABLE STRICT PARALLEL SAFE
AS $$
BEGIN
- RETURN val.data;
+ RETURN eql_v1.ciphertext(val.data);
END;
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1._first_grouped_value(jsonb, jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1._first_grouped_value(jsonb, jsonb);
CREATE FUNCTION eql_v1._first_grouped_value(jsonb, jsonb)
RETURNS jsonb AS $$
SELECT COALESCE($1, $2);
$$ LANGUAGE sql IMMUTABLE;
-DROP AGGREGATE IF EXISTS eql_v1.cs_grouped_value(jsonb);
+-- DROP AGGREGATE IF EXISTS eql_v1.cs_grouped_value(jsonb);
CREATE AGGREGATE eql_v1.cs_grouped_value(jsonb) (
SFUNC = eql_v1._first_grouped_value,
diff --git a/src/encryptindex/functions.sql b/src/encryptindex/functions.sql
index 448f102..4aafd53 100644
--- a/src/encryptindex/functions.sql
+++ b/src/encryptindex/functions.sql
@@ -1,7 +1,7 @@
-- Return the diff of two configurations
-- Returns the set of keys in a that have different values to b
-- The json comparison is on object values held by the key
-DROP FUNCTION IF EXISTS eql_v1.diff_config(a JSONB, b JSONB);
+-- DROP FUNCTION IF EXISTS eql_v1.diff_config(a JSONB, b JSONB);
CREATE FUNCTION eql_v1.diff_config(a JSONB, b JSONB)
RETURNS TABLE(table_name TEXT, column_name TEXT)
@@ -34,7 +34,7 @@ $$ LANGUAGE plpgsql;
-- Returns the set of columns with pending configuration changes
-- Compares the columns in pending configuration that do not match the active config
-DROP FUNCTION IF EXISTS eql_v1.select_pending_columns();
+-- DROP FUNCTION IF EXISTS eql_v1.select_pending_columns();
CREATE FUNCTION eql_v1.select_pending_columns()
RETURNS TABLE(table_name TEXT, column_name TEXT)
@@ -72,7 +72,7 @@ $$ LANGUAGE plpgsql;
-- On initial encryption from plaintext the target column will be `{column_name}_encrypted `
-- OR NULL if the column does not exist
--
-DROP FUNCTION IF EXISTS eql_v1.select_target_columns();
+-- DROP FUNCTION IF EXISTS eql_v1.select_target_columns();
CREATE FUNCTION eql_v1.select_target_columns()
RETURNS TABLE(table_name TEXT, column_name TEXT, target_column TEXT)
@@ -93,7 +93,7 @@ $$ LANGUAGE sql;
--
-- Returns true if all pending columns have a target (encrypted) column
-DROP FUNCTION IF EXISTS eql_v1.ready_for_encryption();
+-- DROP FUNCTION IF EXISTS eql_v1.ready_for_encryption();
CREATE FUNCTION eql_v1.ready_for_encryption()
RETURNS BOOLEAN
@@ -113,7 +113,7 @@ $$ LANGUAGE sql;
-- Executes the ALTER TABLE statement
-- `ALTER TABLE {target_table} ADD COLUMN {column_name}_encrypted eql_v1_encrypted;`
--
-DROP FUNCTION IF EXISTS eql_v1.create_encrypted_columns();
+-- DROP FUNCTION IF EXISTS eql_v1.create_encrypted_columns();
CREATE FUNCTION eql_v1.create_encrypted_columns()
RETURNS TABLE(table_name TEXT, column_name TEXT)
@@ -138,7 +138,7 @@ $$ LANGUAGE plpgsql;
-- `ALTER TABLE {target_table} RENAME COLUMN {column_name} TO {column_name}_plaintext;
-- `ALTER TABLE {target_table} RENAME COLUMN {column_name}_encrypted TO {column_name};`
--
-DROP FUNCTION IF EXISTS eql_v1.rename_encrypted_columns();
+-- DROP FUNCTION IF EXISTS eql_v1.rename_encrypted_columns();
CREATE FUNCTION eql_v1.rename_encrypted_columns()
RETURNS TABLE(table_name TEXT, column_name TEXT, target_column TEXT)
@@ -155,7 +155,7 @@ AS $$
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.count_encrypted_with_active_config(table_name TEXT, column_name TEXT);
+-- DROP FUNCTION IF EXISTS eql_v1.count_encrypted_with_active_config(table_name TEXT, column_name TEXT);
CREATE FUNCTION eql_v1.count_encrypted_with_active_config(table_name TEXT, column_name TEXT)
RETURNS BIGINT
diff --git a/src/encryptindex/functions_test.sql b/src/encryptindex/functions_test.sql
index 5e89d19..9dd7cc7 100644
--- a/src/encryptindex/functions_test.sql
+++ b/src/encryptindex/functions_test.sql
@@ -8,7 +8,7 @@
TRUNCATE TABLE eql_v1_configuration;
-- Create a table with a plaintext column
-DROP TABLE IF EXISTS users;
+-- DROP TABLE IF EXISTS users;
CREATE TABLE users
(
id bigint GENERATED ALWAYS AS IDENTITY,
@@ -63,7 +63,7 @@ $$ LANGUAGE plpgsql;
TRUNCATE TABLE eql_v1_configuration;
-- Create a table with multiple plaintext columns
-DROP TABLE IF EXISTS users;
+-- DROP TABLE IF EXISTS users;
CREATE TABLE users
(
id bigint GENERATED ALWAYS AS IDENTITY,
@@ -119,7 +119,7 @@ $$ LANGUAGE plpgsql;
-- The schema should be validated first.
-- Users table does not exist, so should fail.
-- -----------------------------------------------
-DROP TABLE IF EXISTS users;
+-- DROP TABLE IF EXISTS users;
TRUNCATE TABLE eql_v1_configuration;
@@ -148,7 +148,7 @@ $$ LANGUAGE plpgsql;
--
-- Schema validation is skipped
-- -----------------------------------------------
-DROP TABLE IF EXISTS users;
+-- DROP TABLE IF EXISTS users;
TRUNCATE TABLE eql_v1_configuration;
DO $$
@@ -194,7 +194,7 @@ INSERT INTO eql_v1_configuration (state, data) VALUES (
);
-- Create a table with plaintext and encrypted columns
-DROP TABLE IF EXISTS users;
+-- DROP TABLE IF EXISTS users;
CREATE TABLE users
(
id bigint GENERATED ALWAYS AS IDENTITY,
@@ -244,7 +244,7 @@ INSERT INTO eql_v1_configuration (state, data) VALUES (
);
-- Create a table with plaintext and jsonb column
-DROP TABLE IF EXISTS users;
+-- DROP TABLE IF EXISTS users;
CREATE TABLE users
(
id bigint GENERATED ALWAYS AS IDENTITY,
@@ -295,7 +295,7 @@ INSERT INTO eql_v1_configuration (state, data) VALUES (
-- Create a table with multiple plaintext columns
-DROP TABLE IF EXISTS users;
+-- DROP TABLE IF EXISTS users;
CREATE TABLE users
(
id bigint GENERATED ALWAYS AS IDENTITY,
diff --git a/src/jsonb/functions.sql b/src/jsonb/functions.sql
new file mode 100644
index 0000000..ade1b35
--- /dev/null
+++ b/src/jsonb/functions.sql
@@ -0,0 +1,291 @@
+-- REQUIRE: src/schema.sql
+-- REQUIRE: src/encrypted/types.sql
+
+-- The jsonpath operators @? and @@ suppress the following errors:
+-- missing object field or array element,
+-- unexpected JSON item type,
+-- datetime and numeric errors.
+-- The jsonpath-related functions described below can also be told to suppress these types of errors.
+-- This behavior might be helpful when searching JSON document collections of varying structure.
+
+
+
+--
+--
+-- Returns the stevec encrypted element matching the selector
+--
+-- If the selector is not found, the function returns NULL
+-- If the selector is found, the function returns the matching element
+--
+-- Array elements use the same selector
+-- Multiple matching elements are wrapped into an eql_v1_encrypted with an array flag
+--
+--
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_path_query(val jsonb, selector text);
+
+CREATE FUNCTION eql_v1.jsonb_path_query(val jsonb, selector text)
+ RETURNS SETOF eql_v1_encrypted
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ DECLARE
+ sv eql_v1_encrypted[];
+ found jsonb[];
+ e jsonb;
+ ary boolean;
+ BEGIN
+
+ IF val IS NULL THEN
+ RETURN NEXT NULL;
+ END IF;
+
+ sv := eql_v1.ste_vec(val);
+
+ FOR idx IN 1..array_length(sv, 1) LOOP
+ e := sv[idx];
+
+ IF eql_v1.selector(e) = selector THEN
+ found := array_append(found, e);
+ IF eql_v1.is_ste_vec_array(e) THEN
+ ary := true;
+ END IF;
+
+ END IF;
+ END LOOP;
+
+ IF found IS NOT NULL THEN
+
+ IF ary THEN
+
+ -- Wrapp found array elements as eql_v1_encrypted
+ RETURN NEXT jsonb_build_object(
+ 'sv', found,
+ 'a', 1
+ )::eql_v1_encrypted;
+
+ ELSE
+ RETURN NEXT found[1]::eql_v1_encrypted;
+ END IF;
+
+ END IF;
+
+ RETURN;
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_path_query(val eql_v1_encrypted, selector text);
+
+CREATE FUNCTION eql_v1.jsonb_path_query(val eql_v1_encrypted, selector text)
+ RETURNS SETOF eql_v1_encrypted
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN QUERY
+ SELECT * FROM eql_v1.jsonb_path_query(val.data, selector);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_path_exists(val jsonb, selector text);
+
+CREATE FUNCTION eql_v1.jsonb_path_exists(val jsonb, selector text)
+ RETURNS boolean
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN EXISTS (
+ SELECT eql_v1.jsonb_path_query(val, selector)
+ );
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_path_exists(val eql_v1_encrypted, selector text);
+
+CREATE FUNCTION eql_v1.jsonb_path_exists(val eql_v1_encrypted, selector text)
+ RETURNS boolean
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN EXISTS (
+ SELECT eql_v1.jsonb_path_query(val, selector)
+ );
+ END;
+$$ LANGUAGE plpgsql;
+
+
+--
+--
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_path_query_first(val jsonb, selector text);
+
+CREATE FUNCTION eql_v1.jsonb_path_query_first(val jsonb, selector text)
+ RETURNS eql_v1_encrypted
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN (
+ SELECT (
+ SELECT e
+ FROM eql_v1.jsonb_path_query(val.data, selector) AS e
+ LIMIT 1
+ )
+ );
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_path_query_first(val eql_v1_encrypted, selector text);
+
+CREATE FUNCTION eql_v1.jsonb_path_query_first(val eql_v1_encrypted, selector text)
+ RETURNS eql_v1_encrypted
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN (
+ SELECT e
+ FROM eql_v1.jsonb_path_query(val.data, selector) as e
+ LIMIT 1
+ );
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+--
+
+
+-- =====================================================================
+--
+-- Returns the length of an encrypted jsonb array
+---
+-- An encrypted is a jsonb array if it contains an "a" field/attribute with a truthy value
+--
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_array_length(val jsonb);
+
+CREATE FUNCTION eql_v1.jsonb_array_length(val jsonb)
+ RETURNS integer
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ DECLARE
+ sv eql_v1_encrypted[];
+ found eql_v1_encrypted[];
+ BEGIN
+
+ IF val IS NULL THEN
+ RETURN NULL;
+ END IF;
+
+ IF eql_v1.is_ste_vec_array(val) THEN
+ sv := eql_v1.ste_vec(val);
+ RETURN array_length(sv, 1);
+ END IF;
+
+ RAISE 'cannot get array length of a non-array';
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_array_length(val eql_v1_encrypted);
+
+CREATE FUNCTION eql_v1.jsonb_array_length(val eql_v1_encrypted)
+ RETURNS integer
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN (
+ SELECT eql_v1.jsonb_array_length(val.data)
+ );
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+
+-- =====================================================================
+--
+-- Returns the length of an encrypted jsonb array
+---
+-- An encrypted is a jsonb array if it contains an "a" field/attribute with a truthy value
+--
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_array_elements(val jsonb);
+
+CREATE FUNCTION eql_v1.jsonb_array_elements(val jsonb)
+ RETURNS SETOF eql_v1_encrypted
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ DECLARE
+ sv eql_v1_encrypted[];
+ found eql_v1_encrypted[];
+ BEGIN
+
+ IF NOT eql_v1.is_ste_vec_array(val) THEN
+ RAISE 'cannot extract elements from non-array';
+ END IF;
+
+ sv := eql_v1.ste_vec(val);
+
+ FOR idx IN 1..array_length(sv, 1) LOOP
+ RETURN NEXT sv[idx];
+ END LOOP;
+
+ RETURN;
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_array_elements(val eql_v1_encrypted);
+
+CREATE FUNCTION eql_v1.jsonb_array_elements(val eql_v1_encrypted)
+ RETURNS SETOF eql_v1_encrypted
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN QUERY
+ SELECT * FROM eql_v1.jsonb_array_elements(val.data);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- =====================================================================
+--
+-- Returns the length of an encrypted jsonb array
+---
+-- An encrypted is a jsonb array if it contains an "a" field/attribute with a truthy value
+--
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_array_elements_text(val jsonb);
+
+CREATE FUNCTION eql_v1.jsonb_array_elements_text(val jsonb)
+ RETURNS SETOF text
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ DECLARE
+ sv eql_v1_encrypted[];
+ found eql_v1_encrypted[];
+ BEGIN
+ IF NOT eql_v1.is_ste_vec_array(val) THEN
+ RAISE 'cannot extract elements from non-array';
+ END IF;
+
+ sv := eql_v1.ste_vec(val);
+
+ FOR idx IN 1..array_length(sv, 1) LOOP
+ RETURN NEXT eql_v1.ciphertext(sv[idx]);
+ END LOOP;
+
+ RETURN;
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_array_elements_text(val eql_v1_encrypted);
+
+CREATE FUNCTION eql_v1.jsonb_array_elements_text(val eql_v1_encrypted)
+ RETURNS SETOF text
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN QUERY
+ SELECT * FROM eql_v1.jsonb_array_elements_text(val.data);
+ END;
+$$ LANGUAGE plpgsql;
diff --git a/src/jsonb/functions_test.sql b/src/jsonb/functions_test.sql
new file mode 100644
index 0000000..ca99302
--- /dev/null
+++ b/src/jsonb/functions_test.sql
@@ -0,0 +1,333 @@
+\set ON_ERROR_STOP on
+
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+
+-- DROP TABLE IF EXISTS unencrypted;
+-- CREATE TABLE unencrypted
+-- (
+-- id bigint GENERATED ALWAYS AS IDENTITY,
+-- u jsonb,
+-- PRIMARY KEY(id)
+-- );
+-- INSERT INTO unencrypted (u)
+-- VALUES
+-- ('{"a": [1, 2, 3] }'),
+-- ('{"a": [1, 2, 3, 4] }'),
+-- ('{"a": [1, 2, 3, 4, 5] }');
+
+-- SELECT *
+-- FROM unencrypted
+-- WHERE EXISTS (
+-- SELECT 1
+-- FROM jsonb_array_elements(u->'a') AS elem
+-- WHERE elem::int < 2
+-- );
+
+-- SELECT seed_encrypted(get_array_ste_vec()::eql_v1_encrypted);
+-- SELECT *
+-- FROM encrypted
+-- WHERE EXISTS (
+-- SELECT 1
+-- FROM eql_v1.jsonb_array_elements(e->'f510853730e1c3dbd31b86963f029dd5') AS elem
+-- WHERE elem > '{"ocf": "b0c0a7385cb2f7dfe32a2649a9d8294794b8fc05585a240c1315f1e45ee7d9012616db3f01b43fa94351618670a29c24fc75df1392d52764c757b34495888b1c"}'::jsonb
+-- );
+
+-- SELECT eql_v1.jsonb_path_query_first(e, '33743aed3ae636f6bf05cff11ac4b519') as e
+-- FROM encrypted
+-- WHERE eql_v1.jsonb_path_query(e, '33743aed3ae636f6bf05cff11ac4b519') IS NOT NULL;
+
+
+
+-- "ocf": "b0c0a7385cb2f7dfe32a2649a9d8294794b8fc05585a240c1315f1e45ee7d9012616db3f01b43fa94351618670a29c24fc75df1392d52764c757b34495888b1c",
+
+-- SELECT eql_v1.jsonb_array_elements(eql_v1.jsonb_path_query(e, 'f510853730e1c3dbd31b86963f029dd5')) as e FROM encrypted ;
+
+
+
+
+-- -- SELECT eql_v1.jsonb_path_exists(e, ''f510853730e1c3dbd31b86963f029dd5'') FROM encrypted;
+-- -- SELECT eql_v1.jsonb_path_query(e, 'f510853730e1c3dbd31b86963f029dd5') FROM encrypted;
+
+-- -- SELECT eql_v1.jsonb_path_query(e, 'f510853730e1c3dbd31b86963f029dd5') as e FROM encrypted;
+-- -- SELECT eql_v1.jsonb_array_length(eql_v1.jsonb_path_query(e, 'f510853730e1c3dbd31b86963f029dd5')) as e FROM encrypted LIMIT 1;
+-- -- SELECT eql_v1.jsonb_array_elements(eql_v1.jsonb_path_query(e, 'f510853730e1c3dbd31b86963f029dd5')) as e FROM encrypted ;
+-- -- SELECT eql_v1.jsonb_array_elements_text(eql_v1.jsonb_path_query(e, 'f510853730e1c3dbd31b86963f029dd5')) as e FROM encrypted ;
+-- -- SELECT eql_v1.jsonb_array_length(eql_v1.jsonb_path_query(e, 'f510853730e1c3dbd31b86963f029dd5')) as e FROM encrypted LIMIT 1;
+-- -- SELECT eql_v1.jsonb_path_query(e, 'f510853730e1c3dbd31b86963f029dd5') as e FROM encrypted;
+
+
+
+
+-- ========================================================================
+--
+-- Selector &.a[*]
+-- -> 33743aed3ae636f6bf05cff11ac4b519
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ results eql_v1_encrypted[];
+ BEGIN
+
+ PERFORM seed_encrypted_json();
+ PERFORM seed_encrypted(get_array_ste_vec()::eql_v1_encrypted);
+
+ PERFORM assert_result(
+ 'jsonb_array_elements returns array elements from jsonb_path_query result',
+ 'SELECT eql_v1.jsonb_array_elements(eql_v1.jsonb_path_query(e, ''f510853730e1c3dbd31b86963f029dd5'')) as e FROM encrypted;');
+
+ PERFORM assert_count(
+ 'jsonb_array_elements returns the correct number of array elements from jsonb_path_query result',
+ 'SELECT eql_v1.jsonb_array_elements(eql_v1.jsonb_path_query(e, ''f510853730e1c3dbd31b86963f029dd5'')) as e FROM encrypted;',
+ 5);
+
+ PERFORM assert_exception(
+ 'jsonb_array_elements exception if input is not an array',
+ 'SELECT eql_v1.jsonb_array_elements(eql_v1.jsonb_path_query(e, ''33743aed3ae636f6bf05cff11ac4b519'')) as e FROM encrypted LIMIT 1;');
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- -- ========================================================================
+-- --
+-- -- Selector &.a[*]
+-- -- -> 33743aed3ae636f6bf05cff11ac4b519
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ results eql_v1_encrypted[];
+ BEGIN
+
+ PERFORM seed_encrypted_json();
+ PERFORM seed_encrypted(get_array_ste_vec()::eql_v1_encrypted);
+
+ PERFORM assert_result(
+ 'jsonb_array_elements_text returns array elements from jsonb_path_query result',
+ 'SELECT eql_v1.jsonb_array_elements_text(eql_v1.jsonb_path_query(e, ''f510853730e1c3dbd31b86963f029dd5'')) as e FROM encrypted;');
+
+ PERFORM assert_count(
+ 'jsonb_array_elements_text returns the correct number of array elements from jsonb_path_query result',
+ 'SELECT eql_v1.jsonb_array_elements_text(eql_v1.jsonb_path_query(e, ''f510853730e1c3dbd31b86963f029dd5'')) as e FROM encrypted;',
+ 5);
+
+ PERFORM assert_exception(
+ 'jsonb_array_elements_text exception if input is not an array',
+ 'SELECT eql_v1.jsonb_array_elements_text(eql_v1.jsonb_path_query(e, ''33743aed3ae636f6bf05cff11ac4b519'')) as e FROM encrypted LIMIT 1;');
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- ========================================================================
+--
+-- Selector &.a[*]
+-- -> 33743aed3ae636f6bf05cff11ac4b519
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ results eql_v1_encrypted[];
+ BEGIN
+
+ PERFORM seed_encrypted_json();
+ PERFORM seed_encrypted(get_array_ste_vec()::eql_v1_encrypted);
+
+ PERFORM assert_result(
+ 'jsonb_array_length returns array length of jsonb_path_query result',
+ 'SELECT eql_v1.jsonb_array_length(eql_v1.jsonb_path_query(e, ''f510853730e1c3dbd31b86963f029dd5'')) as e FROM encrypted LIMIT 1;',
+ '5');
+
+ PERFORM assert_exception(
+ 'jsonb_array_length exception if input is not an array',
+ 'SELECT eql_v1.jsonb_array_length(eql_v1.jsonb_path_query(e, ''33743aed3ae636f6bf05cff11ac4b519'')) as e FROM encrypted LIMIT 1;');
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- -- ========================================================================
+--
+-- -- "{\"hello\": \"four\", \"n\": 20, \"a\": [1, 2, 3, 4, 5] }",
+--
+-- Selector &.a[*]
+-- -> 33743aed3ae636f6bf05cff11ac4b519
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ results eql_v1_encrypted[];
+ BEGIN
+
+ PERFORM seed_encrypted_json();
+
+ -- Insert a row with array selector
+ sv := get_array_ste_vec()::eql_v1_encrypted;
+ PERFORM seed_encrypted(sv);
+
+ PERFORM assert_count(
+ 'jsonb_path_query with array selector returns count',
+ 'SELECT eql_v1.jsonb_path_query_first(e, ''33743aed3ae636f6bf05cff11ac4b519'') as e FROM encrypted;',
+ 4
+ );
+
+ PERFORM assert_count(
+ 'jsonb_path_query with array selector returns count',
+ 'SELECT eql_v1.jsonb_path_query_first(e, ''33743aed3ae636f6bf05cff11ac4b519'') as e FROM encrypted WHERE eql_v1.jsonb_path_query_first(e, ''33743aed3ae636f6bf05cff11ac4b519'') IS NOT NULL;',
+ 1
+ );
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- ------------------------------------------------------------------------
+
+
+
+-- ------------------------------------------------------------------------
+--
+-- jsonb_path_query
+--
+
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+--
+DO $$
+ BEGIN
+ PERFORM seed_encrypted_json();
+
+ PERFORM assert_result(
+ 'jsonb_path_query',
+ 'SELECT eql_v1.jsonb_path_query(e, ''2517068c0d1f9d4d41d2c666211f785e'') FROM encrypted LIMIT 1;');
+
+ PERFORM assert_count(
+ 'jsonb_path_query returns count',
+ 'SELECT eql_v1.jsonb_path_query(e, ''2517068c0d1f9d4d41d2c666211f785e'') FROM encrypted;',
+ 3);
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+DO $$
+ BEGIN
+
+ PERFORM seed_encrypted_json();
+
+ PERFORM assert_result(
+ 'jsonb_path_exists returns true',
+ 'SELECT eql_v1.jsonb_path_exists(e, ''2517068c0d1f9d4d41d2c666211f785e'') FROM encrypted LIMIT 1;',
+ 'true');
+
+ PERFORM assert_result(
+ 'jsonb_path_exists returns false',
+ 'SELECT eql_v1.jsonb_path_exists(e, ''blahvtha'') FROM encrypted LIMIT 1;',
+ 'false');
+
+ PERFORM assert_count(
+ 'jsonb_path_exists returns count',
+ 'SELECT eql_v1.jsonb_path_exists(e, ''2517068c0d1f9d4d41d2c666211f785e'') FROM encrypted;',
+ 3);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- --
+-- -- Selector &.a[*]
+-- -- -> 33743aed3ae636f6bf05cff11ac4b519
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ results eql_v1_encrypted[];
+ BEGIN
+
+ -- Insert a row with array selector
+ sv := get_array_ste_vec()::eql_v1_encrypted;
+ PERFORM seed_encrypted(sv);
+
+ PERFORM assert_result(
+ 'jsonb_path_query with array selector',
+ 'SELECT eql_v1.jsonb_path_query(e, ''f510853730e1c3dbd31b86963f029dd5'') FROM encrypted;');
+
+ -- An array should be wrapped and returned as a single element
+ PERFORM assert_count(
+ 'jsonb_path_query with array selector returns one result',
+ 'SELECT eql_v1.jsonb_path_query(e, ''f510853730e1c3dbd31b86963f029dd5'') FROM encrypted;',
+ 1);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- --
+-- -- Selector &.a[*]
+-- -- -> 33743aed3ae636f6bf05cff11ac4b519
+-- --
+DO $$
+ DECLARE
+ sv eql_v1_encrypted;
+ results eql_v1_encrypted[];
+ BEGIN
+
+ PERFORM seed_encrypted_json();
+
+ -- Insert a row with array selector
+ sv := get_array_ste_vec()::eql_v1_encrypted;
+ PERFORM seed_encrypted(sv);
+
+ PERFORM assert_result(
+ 'jsonb_path_exists with array selector',
+ 'SELECT eql_v1.jsonb_path_exists(e, ''f510853730e1c3dbd31b86963f029dd5'') FROM encrypted;');
+
+ PERFORM assert_count(
+ 'jsonb_path_exists with array selector returns correct number of records',
+ 'SELECT eql_v1.jsonb_path_exists(e, ''f510853730e1c3dbd31b86963f029dd5'') FROM encrypted;',
+ 4);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- --
+-- -- Selector &.a[*]
+-- -- -> 33743aed3ae636f6bf05cff11ac4b519
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ results eql_v1_encrypted[];
+ BEGIN
+
+ PERFORM seed_encrypted_json();
+
+ -- Insert a row with array selector
+ sv := get_array_ste_vec()::eql_v1_encrypted;
+ PERFORM seed_encrypted(sv);
+
+ PERFORM assert_count(
+ 'jsonb_path_query with array selector returns count',
+ 'SELECT eql_v1.jsonb_path_query_first(e, ''33743aed3ae636f6bf05cff11ac4b519'') as e FROM encrypted;',
+ 4
+ );
+
+ PERFORM assert_count(
+ 'jsonb_path_query with array selector returns count',
+ 'SELECT eql_v1.jsonb_path_query_first(e, ''33743aed3ae636f6bf05cff11ac4b519'') as e FROM encrypted WHERE eql_v1.jsonb_path_query_first(e, ''33743aed3ae636f6bf05cff11ac4b519'') IS NOT NULL;',
+ 1
+ );
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
diff --git a/src/match/functions.sql b/src/match/functions.sql
index 0febe46..0df79c0 100644
--- a/src/match/functions.sql
+++ b/src/match/functions.sql
@@ -2,7 +2,7 @@
-- extracts match index from an emcrypted column
-DROP FUNCTION IF EXISTS eql_v1.match(val jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.match(val jsonb);
CREATE FUNCTION eql_v1.match(val jsonb)
RETURNS eql_v1.match_index
@@ -18,7 +18,7 @@ $$ LANGUAGE plpgsql;
-- extracts unique index from an encrypted column
-DROP FUNCTION IF EXISTS eql_v1.match(val eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.match(val eql_v1_encrypted);
CREATE FUNCTION eql_v1.match(val eql_v1_encrypted)
RETURNS eql_v1.match_index
@@ -28,5 +28,3 @@ AS $$
RETURN (SELECT eql_v1.match(val.data));
END;
$$ LANGUAGE plpgsql;
-
-
diff --git a/src/match/types.sql b/src/match/types.sql
index c89e406..0b72631 100644
--- a/src/match/types.sql
+++ b/src/match/types.sql
@@ -1,5 +1,5 @@
-- REQUIRE: src/schema.sql
-DROP DOMAIN IF EXISTS eql_v1.match_index;
+-- DROP DOMAIN IF EXISTS eql_v1.match_index;
CREATE DOMAIN eql_v1.match_index AS smallint[];
diff --git a/src/operators/->.sql b/src/operators/->.sql
index 904373d..8c997e6 100644
--- a/src/operators/->.sql
+++ b/src/operators/->.sql
@@ -1,51 +1,81 @@
+-- REQUIRE: src/schema.sql
-- REQUIRE: src/encrypted/types.sql
-- REQUIRE: src/encrypted/functions.sql
-
-DROP OPERATOR IF EXISTS -> (eql_v1_encrypted, text);
-DROP FUNCTION IF EXISTS eql_v1."->"(e eql_v1_encrypted, selector text);
-
--
--- Returns
+-- The -> operator returns an encrypted matching the selector
+-- Encyprted JSON is represented as an array of `eql_v1_encrypted`.
+-- Each `eql_v1_encrypted` value has a selector, ciphertext, and an index term of
+-- - blake3
+-- - ore_cllw_u64_8
+-- - ore_cllw_var_8
--
+-- {
+-- "sv": [ {"c": "", "s": "", "b": "" } ]
+-- }
+--
+-- DROP OPERATOR IF EXISTS -> (eql_v1_encrypted, text);
+
+-- DROP FUNCTION IF EXISTS eql_v1."->"(e eql_v1_encrypted, selector text);
+
CREATE FUNCTION eql_v1."->"(e eql_v1_encrypted, selector text)
RETURNS eql_v1_encrypted
IMMUTABLE STRICT PARALLEL SAFE
AS $$
- -- DECLARE
- -- j jsonb;
- -- found: text;
- -- ignored: text;
+ DECLARE
+ sv eql_v1_encrypted[];
+ found eql_v1_encrypted;
+ BEGIN
+
+ IF e IS NULL THEN
+ RETURN NULL;
+ END IF;
+
+ sv := eql_v1.ste_vec(e);
+
+ FOR idx IN 1..array_length(sv, 1) LOOP
+ if eql_v1.selector(sv[idx]) = selector THEN
+ found := sv[idx];
+ END IF;
+ END LOOP;
+
+ RETURN found;
+ END;
+$$ LANGUAGE plpgsql;
+
+
+--
+
+
+-- DROP OPERATOR IF EXISTS -> (eql_v1_encrypted, integer);
+
+-- DROP FUNCTION IF EXISTS eql_v1."->"(e eql_v1_encrypted, selector integer);
+
+CREATE FUNCTION eql_v1."->"(e eql_v1_encrypted, selector integer)
+ RETURNS eql_v1_encrypted
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ DECLARE
+ sv eql_v1_encrypted[];
+ found eql_v1_encrypted;
BEGIN
+ IF NOT eql_v1.is_ste_vec_array(e) THEN
+ RETURN NULL;
+ END IF;
+
+ sv := eql_v1.ste_vec(e);
- -- j := e->'j';
- -- PERFORM eql_v1.log(j);
-
- -- FOR i IN 1..jsonb_array_length(j, 1) LOOP
- -- -- -- The ELSE part is to help ensure constant time operation.
- -- -- -- The result is thrown away.
- -- IF j[i]->'s' = selector THEN
- -- found := j[i]->'c';
- -- ELSE
- -- ignored := j[i]->'c';
- -- END IF;
- -- END LOOP;
-
- -- IF found IS NOT NULL THEN
- -- RETURN found;
- -- ELSE
- -- RETURN NULL;
- -- END IF;
-
- RETURN (
- SELECT elem::eql_v1_encrypted
- FROM jsonb_array_elements(e.data->'j') AS elem
- WHERE elem->>'s' = selector
- LIMIT 1
- );
+ -- PostgreSQL arrays are 1-based
+ -- JSONB arrays are 0-based and so the selector is 0-based
+ FOR idx IN 1..array_length(sv, 1) LOOP
+ if (idx-1) = selector THEN
+ found := sv[idx];
+ END IF;
+ END LOOP;
+ RETURN found;
END;
$$ LANGUAGE plpgsql;
@@ -57,34 +87,9 @@ CREATE OPERATOR ->(
);
--- ste_vec_index := eql_v1.ste_vec(col);
-
--- IF ste_vec_index IS NULL THEN
--- RETURN NULL;
--- END IF;
-
--- target_selector := selector->>'svs';
-
--- FOR i IN 1..array_length(ste_vec_index.entries, 1) LOOP
--- -- The ELSE part is to help ensure constant time operation.
--- -- The result is thrown away.
--- IF ste_vec_index.entries[i].tokenized_selector = target_selector THEN
--- found := ste_vec_index.entries[i].ciphertext;
--- ELSE
--- ignored := ste_vec_index.entries[i].ciphertext;
--- END IF;
--- END LOOP;
-
--- IF found IS NOT NULL THEN
--- RETURN jsonb_build_object(
--- 'k', 'ct',
--- 'c', found,
--- 'o', NULL,
--- 'm', NULL,
--- 'u', NULL,
--- 'i', col->'i',
--- 'v', 1
--- );
--- ELSE
--- RETURN NULL;
--- END IF;
+CREATE OPERATOR ->(
+ FUNCTION=eql_v1."->",
+ LEFTARG=eql_v1_encrypted,
+ RIGHTARG=integer
+);
+
diff --git a/src/operators/->>.sql b/src/operators/->>.sql
index 2e7ed8e..7a49b7a 100644
--- a/src/operators/->>.sql
+++ b/src/operators/->>.sql
@@ -1,46 +1,22 @@
+-- REQUIRE: src/schema.sql
-- REQUIRE: src/encrypted/types.sql
-- REQUIRE: src/encrypted/functions.sql
-
-DROP OPERATOR IF EXISTS ->> (eql_v1_encrypted, text);
-DROP FUNCTION IF EXISTS eql_v1."->>"(e eql_v1_encrypted, selector text);
+-- DROP OPERATOR IF EXISTS ->> (eql_v1_encrypted, text);
+-- DROP FUNCTION IF EXISTS eql_v1."->>"(e eql_v1_encrypted, selector text);
CREATE FUNCTION eql_v1."->>"(e eql_v1_encrypted, selector text)
RETURNS text
- IMMUTABLE STRICT PARALLEL SAFE
+IMMUTABLE STRICT PARALLEL SAFE
AS $$
DECLARE
- j jsonb;
- found text;
- ignored text;
+ found eql_v1_encrypted;
BEGIN
- -- j := e.data->'j';
- -- -- PERFORM eql_v1.log(j::text);
- -- PERFORM eql_v1.log('jsonb_array_length(j)');
- -- PERFORM eql_v1.log(jsonb_array_length(j)::text);
-
- -- FOR i IN 0..jsonb_array_length(j) LOOP
- -- -- The ELSE part is to help ensure constant time operation.
- -- -- The result is thrown away.
- -- IF j[i]->>'s' = selector THEN
- -- found := eql_v1.ciphertext(j->i);
- -- ELSE
- -- ignored := eql_v1.ciphertext(j->i);
- -- END IF;
- -- END LOOP;
-
- -- IF found IS NOT NULL THEN
- -- RETURN found;
- -- ELSE
- -- RETURN NULL;
- -- END IF;
- RETURN (
- SELECT eql_v1.ciphertext(elem)
- FROM jsonb_array_elements(e.data->'j') AS elem
- WHERE elem->>'s' = selector
- LIMIT 1
- );
+
+ found = eql_v1."->"(e, selector);
+
+ RETURN eql_v1.ciphertext(found);
END;
$$ LANGUAGE plpgsql;
diff --git a/src/operators/->>_test.sql b/src/operators/->>_test.sql
new file mode 100644
index 0000000..afae58d
--- /dev/null
+++ b/src/operators/->>_test.sql
@@ -0,0 +1,45 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+--
+-- The ->> operator returns ciphertext matching the selector
+DO $$
+ BEGIN
+ PERFORM assert_result(
+ 'Selector ->> returns at least one eql_v1_encrypted',
+ 'SELECT e->>''bca213de9ccce676fa849ff9c4807963'' FROM encrypted;');
+
+ PERFORM assert_count(
+ 'Selector ->> returns all eql_v1_encrypted',
+ 'SELECT e->>''bca213de9ccce676fa849ff9c4807963'' FROM encrypted;',
+ 3);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+--
+-- The ->> operator returns NULL if no matching selector
+DO $$
+ BEGIN
+ PERFORM assert_no_result(
+ 'Unknown selector -> returns null',
+ 'SELECT e->>''blahvtha'' FROM encrypted;');
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+--
+-- The ->> operator returns ciphertext matching the selector
+DO $$
+ BEGIN
+
+ PERFORM assert_result(
+ 'Selector ->> returns all eql_v1_encrypted',
+ 'SELECT e->>''bca213de9ccce676fa849ff9c4807963'' FROM encrypted LIMIT 1;',
+ 'mBbLGB9xHAGzLvUj-`@Wmf=IhD87n7r3ir3n!Sk6AKir_YawR=0c>pk(OydB;ntIEXK~c>V&4>)rNkf_test.sql b/src/operators/->_test.sql
new file mode 100644
index 0000000..34983f5
--- /dev/null
+++ b/src/operators/->_test.sql
@@ -0,0 +1,79 @@
+\set ON_ERROR_STOP on
+
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+
+--
+-- The -> operator returns an encrypted matching the selector
+DO $$
+ BEGIN
+ PERFORM assert_result(
+ 'Selector -> returns at least one eql_v1_encrypted',
+ 'SELECT e->''bca213de9ccce676fa849ff9c4807963'' FROM encrypted;');
+
+ PERFORM assert_count(
+ 'Selector -> returns all eql_v1_encrypted',
+ 'SELECT e->''bca213de9ccce676fa849ff9c4807963'' FROM encrypted;',
+ 3);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+--
+-- The -> operator returns NULL if no matching selector
+DO $$
+ BEGIN
+ PERFORM assert_no_result(
+ 'Unknown selector -> returns null',
+ 'SELECT e->''blahvtha'' FROM encrypted;');
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+--
+-- encrypted returned from -> operator expression called via eql_v1.ciphertext
+--
+DO $$
+ DECLARE
+ result eql_v1_encrypted;
+ BEGIN
+ PERFORM assert_result(
+ 'Fetch ciphertext via selector',
+ 'SELECT eql_v1.ciphertext(e->''2517068c0d1f9d4d41d2c666211f785e'') FROM encrypted;');
+
+ PERFORM assert_count(
+ 'Fetch ciphertext via selector returns all eql_v1_encrypted',
+ 'SELECT eql_v1.ciphertext(e->''2517068c0d1f9d4d41d2c666211f785e'') FROM encrypted;',
+ 3);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+--
+-- encrypted returned from -> operator expression called via eql_v1.ciphertext
+--
+DO $$
+ DECLARE
+ result eql_v1_encrypted;
+ BEGIN
+
+ PERFORM truncate_table_with_encrypted();
+ PERFORM seed_encrypted(get_array_ste_vec()::eql_v1_encrypted);
+
+ PERFORM assert_result(
+ '-> operator with integer returns array',
+ 'SELECT eql_v1.jsonb_path_query_first(e, ''f510853730e1c3dbd31b86963f029dd5'')->0 as e FROM encrypted');
+
+ PERFORM assert_count(
+ '-> operator with integer returns array',
+ 'SELECT eql_v1.jsonb_path_query_first(e, ''f510853730e1c3dbd31b86963f029dd5'')->0 as e FROM encrypted',
+ 1);
+
+ END;
+$$ LANGUAGE plpgsql;
+
diff --git a/src/operators/<.sql b/src/operators/<.sql
index 89a1835..9421c22 100644
--- a/src/operators/<.sql
+++ b/src/operators/<.sql
@@ -20,22 +20,39 @@
--
--
-DROP OPERATOR CLASS IF EXISTS eql_v1.encrypted_operator USING btree;
-DROP OPERATOR FAMILY IF EXISTS eql_v1.encrypted_operator USING btree;
-
-DROP FUNCTION IF EXISTS eql_v1.lt(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.lt(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.lt(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
AS $$
BEGIN
- RETURN eql_v1.ore_64_8_v1(a) < eql_v1.ore_64_8_v1(b);
+
+ BEGIN
+ RETURN eql_v1.ore_cllw_u64_8(a) < eql_v1.ore_cllw_u64_8(b);
+ -- RETURN (eql_v1.unique(a) = eql_v1.unique(b));
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('eql_v1.lt no ore_cllw_u64_8 index');
+ END;
+
+ BEGIN
+ RETURN eql_v1.ore_cllw_var_8(a) < eql_v1.ore_cllw_var_8(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('eql_v1.lt no ore_cllw_var_8 index');
+ END;
+
+ BEGIN
+ RETURN eql_v1.ore_64_8_v1(a) < eql_v1.ore_64_8_v1(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('eql_v1.lt no ore_64_8_v1 index');
+ END;
+
+ RETURN false;
END;
$$ LANGUAGE plpgsql;
-DROP OPERATOR IF EXISTS < (eql_v1_encrypted, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1."<"(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS < (eql_v1_encrypted, eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1."<"(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1."<"(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
@@ -56,8 +73,8 @@ CREATE OPERATOR <(
);
-DROP OPERATOR IF EXISTS < (eql_v1_encrypted, jsonb);
-DROP FUNCTION IF EXISTS eql_v1."<"(a eql_v1_encrypted, b jsonb);
+-- DROP OPERATOR IF EXISTS < (eql_v1_encrypted, jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1."<"(a eql_v1_encrypted, b jsonb);
CREATE FUNCTION eql_v1."<"(a eql_v1_encrypted, b jsonb)
RETURNS boolean
@@ -78,8 +95,8 @@ CREATE OPERATOR <(
);
-DROP OPERATOR IF EXISTS < (jsonb, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1."<"(a jsonb, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS < (jsonb, eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1."<"(a jsonb, b eql_v1_encrypted);
CREATE FUNCTION eql_v1."<"(a jsonb, b eql_v1_encrypted)
RETURNS boolean
diff --git a/src/operators/<=.sql b/src/operators/<=.sql
index af6a280..75e4cad 100644
--- a/src/operators/<=.sql
+++ b/src/operators/<=.sql
@@ -20,19 +20,38 @@
--
--
-DROP FUNCTION IF EXISTS eql_v1.lte(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.lte(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.lte(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
AS $$
BEGIN
- RETURN eql_v1.ore_64_8_v1(a) >= eql_v1.ore_64_8_v1(b);
+
+ BEGIN
+ RETURN eql_v1.ore_cllw_u64_8(a) <= eql_v1.ore_cllw_u64_8(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('eql_v1.lte no ore_cllw_u64_8 index');
+ END;
+
+ BEGIN
+ RETURN eql_v1.ore_cllw_var_8(a) <= eql_v1.ore_cllw_var_8(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('eql_v1.lte no ore_cllw_var_8 index');
+ END;
+
+ BEGIN
+ RETURN eql_v1.ore_64_8_v1(a) <= eql_v1.ore_64_8_v1(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('eql_v1.lte no ore_64_8_v1 index');
+ END;
+
+ RETURN false;
END;
$$ LANGUAGE plpgsql;
-DROP OPERATOR IF EXISTS <= (eql_v1_encrypted, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1."<="(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS <= (eql_v1_encrypted, eql_v1_encrypted) CASCADE;
+-- DROP FUNCTION IF EXISTS eql_v1."<="(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1."<="(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
@@ -53,8 +72,8 @@ CREATE OPERATOR <=(
);
-DROP OPERATOR IF EXISTS <= (eql_v1_encrypted, jsonb);
-DROP FUNCTION IF EXISTS eql_v1."<="(a eql_v1_encrypted, b jsonb);
+-- DROP OPERATOR IF EXISTS <= (eql_v1_encrypted, jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1."<="(a eql_v1_encrypted, b jsonb);
CREATE FUNCTION eql_v1."<="(a eql_v1_encrypted, b jsonb)
RETURNS boolean
@@ -75,8 +94,8 @@ CREATE OPERATOR <=(
);
-DROP OPERATOR IF EXISTS <= (jsonb, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1."<="(a jsonb, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS <= (jsonb, eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1."<="(a jsonb, b eql_v1_encrypted);
CREATE FUNCTION eql_v1."<="(a jsonb, b eql_v1_encrypted)
RETURNS boolean
diff --git a/src/operators/<=_test.sql b/src/operators/<=_test.sql
index e091a6b..dd7b136 100644
--- a/src/operators/<=_test.sql
+++ b/src/operators/<=_test.sql
@@ -3,6 +3,99 @@
SELECT create_table_with_encrypted();
SELECT seed_encrypted_json();
+SELECT e FROM encrypted WHERE e->'a7cea93975ed8c01f861ccb6bd082784' <= '("{""c"": ""mBbM0#UZON2jQ3@LiWcvns2Yf6y3L;hykEh`}*fX#aF;n*=>+*o5Uarod39C7TF-SiCD-NgkG)l%Vw=l!tX>H*P bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ -- json n: 30
+ sv := get_numeric_ste_vec_30()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'2517068c0d1f9d4d41d2c666211f785e';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted <= eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' <= %L::eql_v1_encrypted', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted <= eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' <= %L::eql_v1_encrypted', term),
+ 3);
+
+ -- -- Check the $.hello path
+ -- -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_no_result(
+ format('eql_v1_encrypted <= eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' <= %L::eql_v1_encrypted', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- eql_v1_encrypted < eql_v1_encrypted with ore_cllw_var_8 index
+--
+-- Test data is in form '{"hello": "{one | two | three}", "n": {10 | 20 | 30} }'
+--
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ -- json n: 30
+ sv := get_numeric_ste_vec_30()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted <= eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' <= %L::eql_v1_encrypted', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted <= eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' <= %L::eql_v1_encrypted', term),
+ 2);
+
+ -- -- Check the $.n path
+ -- -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_no_result(
+ format('eql_v1_encrypted <= eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' <= %L::eql_v1_encrypted', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
--
-- ORE - eql_v1_encrypted <= eql_v1_encrypted
--
@@ -12,32 +105,29 @@ DECLARE
ore_term jsonb;
BEGIN
- -- Create a record with HIGH ore
- e := create_encrypted_json()::jsonb || get_high_ore();
+ -- Record with a Numeric ORE term of 42
+ e := create_encrypted_ore_json(42);
PERFORM seed_encrypted(e);
- -- Default has LOW ore
- e := create_encrypted_json();
-
PERFORM assert_result(
- 'eql_v1_encrypted >= eql_v1_encrypted',
+ 'eql_v1_encrypted <= eql_v1_encrypted',
format('SELECT e FROM encrypted WHERE e <= %L::eql_v1_encrypted', e));
-
- for i in 1..3 loop
- e := create_encrypted_json(i);
-
- PERFORM assert_result(
- format('eql_v1_encrypted >= eql_v1_encrypted %s of 3', i),
- format('SELECT e FROM encrypted WHERE e <= %L;', e));
-
- PERFORM assert_count(
- format('eql_v1_encrypted >= eql_v1_encrypted %s of 3', i),
+ PERFORM assert_count(
+ format('eql_v1_encrypted <= eql_v1_encrypted'),
format('SELECT e FROM encrypted WHERE e <= %L;', e),
4);
- end loop;
+ e := create_encrypted_ore_json(20);
+
+ PERFORM assert_result(
+ 'eql_v1_encrypted <= eql_v1_encrypted',
+ format('SELECT e FROM encrypted WHERE e <= %L::eql_v1_encrypted', e));
+ PERFORM assert_count(
+ format('eql_v1_encrypted <= eql_v1_encrypted'),
+ format('SELECT e FROM encrypted WHERE e <= %L;', e),
+ 2);
END;
$$ LANGUAGE plpgsql;
@@ -50,13 +140,25 @@ DECLARE
e eql_v1_encrypted;
ore_term jsonb;
BEGIN
+ -- Reset data
+ PERFORM seed_encrypted_json();
- -- Create a record with HIGH ore
- e := create_encrypted_json()::jsonb || get_high_ore();
+ -- Record with a Numeric ORE term of 42
+ e := create_encrypted_ore_json(42);
PERFORM seed_encrypted(e);
- -- Default has LOW ore
- e := create_encrypted_json();
+ PERFORM assert_result(
+ 'eql_v1.lte(a eql_v1_encrypted, b eql_v1_encrypted)',
+ format('SELECT e FROM encrypted WHERE eql_v1.lte(e, %L)', e));
+
+ -- include
+ PERFORM assert_count(
+ 'eql_v1.lte(a eql_v1_encrypted, b eql_v1_encrypted)',
+ format('SELECT e FROM encrypted WHERE eql_v1.lte(e, %L)', e),
+ 4);
+
+ -- Record with a Numeric ORE term of 30
+ e := create_encrypted_ore_json(30);
PERFORM assert_result(
'eql_v1.get(a eql_v1_encrypted, b eql_v1_encrypted)',
@@ -65,7 +167,7 @@ DECLARE
PERFORM assert_count(
'eql_v1.get(a eql_v1_encrypted, b eql_v1_encrypted)',
format('SELECT e FROM encrypted WHERE eql_v1.lte(e, %L)', e),
- 5);
+ 3);
END;
$$ LANGUAGE plpgsql;
diff --git a/src/operators/<>.sql b/src/operators/<>.sql
index 57cbfdd..de55a65 100644
--- a/src/operators/<>.sql
+++ b/src/operators/<>.sql
@@ -21,7 +21,7 @@
-- We check these index terms in this order and use the first one that exists for both parameters
--
--
-DROP FUNCTION IF EXISTS eql_v1.neq(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.neq(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.neq(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
@@ -33,8 +33,8 @@ AS $$
$$ LANGUAGE plpgsql;
-DROP OPERATOR IF EXISTS <> (eql_v1_encrypted, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1."<>"(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS <> (eql_v1_encrypted, eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1."<>"(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1."<>"(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
@@ -57,8 +57,8 @@ CREATE OPERATOR <> (
MERGES
);
-DROP OPERATOR IF EXISTS <> (eql_v1_encrypted, jsonb);
-DROP FUNCTION IF EXISTS eql_v1."<>"(a eql_v1_encrypted, b jsonb);
+-- DROP OPERATOR IF EXISTS <> (eql_v1_encrypted, jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1."<>"(a eql_v1_encrypted, b jsonb);
CREATE FUNCTION eql_v1."<>"(a eql_v1_encrypted, b jsonb)
RETURNS boolean
@@ -81,8 +81,8 @@ CREATE OPERATOR <> (
);
-DROP OPERATOR IF EXISTS <> (jsonb, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1."<>"(a jsonb, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS <> (jsonb, eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1."<>"(a jsonb, b eql_v1_encrypted);
CREATE FUNCTION eql_v1."<>"(a jsonb, b eql_v1_encrypted)
RETURNS boolean
diff --git a/src/operators/<>_ore_cllw_u64_8_test.sql b/src/operators/<>_ore_cllw_u64_8_test.sql
new file mode 100644
index 0000000..1a950a2
--- /dev/null
+++ b/src/operators/<>_ore_cllw_u64_8_test.sql
@@ -0,0 +1,57 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+
+-- ========================================================================
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- ore_cllw_u64_8 equality
+--
+-- Test data is '{"hello": "world", "n": 42}'
+
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+--
+
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ -- json n: 10
+ sv := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'2517068c0d1f9d4d41d2c666211f785e';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted <> eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE (e->''2517068c0d1f9d4d41d2c666211f785e'') <> %L::eql_v1_encrypted', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted <> eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' <> %L::eql_v1_encrypted', term),
+ 2);
+
+ -- -- Check the $.hello path
+ -- -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_result(
+ format('eql_v1_encrypted <> eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' <> %L::eql_v1_encrypted', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+SELECT drop_table_with_encrypted();
\ No newline at end of file
diff --git a/src/operators/<>_ore_cllw_var_8_test.sql b/src/operators/<>_ore_cllw_var_8_test.sql
new file mode 100644
index 0000000..6cc0438
--- /dev/null
+++ b/src/operators/<>_ore_cllw_var_8_test.sql
@@ -0,0 +1,56 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+
+-- ========================================================================
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- ore_cllw_u64_8 equality
+--
+-- Test data is '{"hello": "world", "n": 42}'
+
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ -- json n: 10
+ sv := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted <> eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE (e->''a7cea93975ed8c01f861ccb6bd082784'') <> %L::eql_v1_encrypted', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted <> eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' <> %L::eql_v1_encrypted', term),
+ 2);
+
+ -- -- Check the $.n path
+ -- -- Returned encrypted does not have ore_cllw_var_8
+ PERFORM assert_result(
+ format('eql_v1_encrypted <> eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' <> %L::eql_v1_encrypted', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+SELECT drop_table_with_encrypted();
\ No newline at end of file
diff --git a/src/operators/<>_ore_test.sql b/src/operators/<>_ore_test.sql
new file mode 100644
index 0000000..eaddf83
--- /dev/null
+++ b/src/operators/<>_ore_test.sql
@@ -0,0 +1,87 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+
+--
+-- ORE - eql_v1_encrypted <> eql_v1_encrypted
+--
+DO $$
+DECLARE
+ e eql_v1_encrypted;
+ ore_term jsonb;
+ BEGIN
+
+ -- Record with a Numeric ORE term of 42
+ e := create_encrypted_ore_json(42);
+ PERFORM seed_encrypted(e);
+
+ PERFORM assert_result(
+ 'eql_v1_encrypted <> eql_v1_encrypted',
+ format('SELECT e FROM encrypted WHERE e <> %L::eql_v1_encrypted', e));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted <> eql_v1_encrypted'),
+ format('SELECT e FROM encrypted WHERE e <> %L;', e),
+ 3);
+
+ e := create_encrypted_ore_json(20);
+
+ PERFORM assert_result(
+ 'eql_v1_encrypted <> eql_v1_encrypted',
+ format('SELECT e FROM encrypted WHERE e <> %L::eql_v1_encrypted', e));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted <> eql_v1_encrypted'),
+ format('SELECT e FROM encrypted WHERE e <> %L;', e),
+ 3);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+--
+-- ORE - eql_v1.gte(a eql_v1_encrypted, b eql_v1_encrypted)
+--
+DO $$
+DECLARE
+ e eql_v1_encrypted;
+ ore_term jsonb;
+ BEGIN
+ -- Reset data
+ PERFORM seed_encrypted_json();
+
+ -- Record with a Numeric ORE term of 20
+ e := create_encrypted_ore_json(20);
+ PERFORM seed_encrypted(e);
+
+ PERFORM assert_result(
+ 'eql_v1.neq(a eql_v1_encrypted, b eql_v1_encrypted)',
+ format('SELECT e FROM encrypted WHERE eql_v1.neq(e, %L)', e));
+
+ -- include
+ PERFORM assert_count(
+ 'eql_v1.neq(a eql_v1_encrypted, b eql_v1_encrypted)',
+ format('SELECT e FROM encrypted WHERE eql_v1.neq(e, %L)', e),
+ 2);
+
+ -- Record with a Numeric ORE term of 30
+ e := create_encrypted_ore_json(30);
+
+ PERFORM assert_result(
+ 'eql_v1.get(a eql_v1_encrypted, b eql_v1_encrypted)',
+ format('SELECT e FROM encrypted WHERE eql_v1.neq(e, %L)', e));
+
+ PERFORM assert_count(
+ 'eql_v1.get(a eql_v1_encrypted, b eql_v1_encrypted)',
+ format('SELECT e FROM encrypted WHERE eql_v1.neq(e, %L)', e),
+ 3);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- ========================================================================
+
+
+SELECT drop_table_with_encrypted();
\ No newline at end of file
diff --git a/src/operators/<>_test.sql b/src/operators/<>_test.sql
index e4fa58d..844650f 100644
--- a/src/operators/<>_test.sql
+++ b/src/operators/<>_test.sql
@@ -3,8 +3,9 @@
SELECT create_table_with_encrypted();
SELECT seed_encrypted_json();
+
--
--- Unique inequality - eql_v1_encrypted <> eql_v1_encrypted
+-- Unique equality - eql_v1_encrypted <> eql_v1_encrypted
--
DO $$
DECLARE
@@ -12,36 +13,30 @@ DECLARE
BEGIN
for i in 1..3 loop
- e := create_encrypted_json(i)::jsonb-'o';
-
- PERFORM assert_result(
- format('eql_v1_encrypted <> eql_v1_encrypted with unique index term %s of 3', i),
- format('SELECT e FROM encrypted WHERE e <> %L;', e));
+ e := create_encrypted_json(i, 'u');
PERFORM assert_count(
- format('eql_v1_encrypted <> eql_v1_encrypted with ore index term'),
- format('SELECT e FROM encrypted WHERE e <> %L', e),
+ format('eql_v1_encrypted <> eql_v1_encrypted with unique index term %s of 3', i),
+ format('SELECT e FROM encrypted WHERE e <> %L;', e),
2);
+
end loop;
- -- remove the ore index term
- e := create_encrypted_json(91347)::jsonb-'o';
+ -- record not in database
+ e := create_encrypted_json(91347, 'u');
- PERFORM assert_result(
+ PERFORM assert_no_result(
'eql_v1_encrypted <> eql_v1_encrypted with no matching record',
format('SELECT e FROM encrypted WHERE e <> %L;', e));
- PERFORM assert_count(
- 'eql_v1_encrypted <> eql_v1_encrypted with no matching record',
- format('SELECT e FROM encrypted WHERE e <> %L;', e),
- 3);
-
END;
$$ LANGUAGE plpgsql;
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
--
--- Unique inequality - eql_v1.neq(eql_v1_encrypted, eql_v1_encrypted)
+-- Unique equality - eql_v1.neq(eql_v1_encrypted, eql_v1_encrypted)
--
DO $$
DECLARE
@@ -49,204 +44,122 @@ DECLARE
BEGIN
for i in 1..3 loop
- e := create_encrypted_json(i)::jsonb-'o';
-
- PERFORM assert_result(
- format('eql_v1.neq(eql_v1_encrypted, eql_v1_encrypted) with unique index term %s of 3', i),
- format('SELECT e FROM encrypted WHERE eql_v1.neq(e, %L);', e));
-
+ e := create_encrypted_json(i, 'u');
PERFORM assert_count(
- format('eql_v1_encrypted <> eql_v1_encrypted with ore index term %s of 3', i),
+ format('eql_v1.neq(eql_v1_encrypted, eql_v1_encrypted) with unique index term %s of 3', i),
format('SELECT e FROM encrypted WHERE eql_v1.neq(e, %L);', e),
2);
end loop;
- -- remove the ore index term
- e := create_encrypted_json(91347)::jsonb-'o';
-
- PERFORM assert_result(
- 'eql_v1.eq(eql_v1_encrypted, eql_v1_encrypted) with no matching record',
- format('SELECT e FROM encrypted WHERE eql_v1.neq(e, %L);', e));
+ -- record not in database
+ e := create_encrypted_json(91347, 'u');
- PERFORM assert_count(
- 'eql_v1_encrypted <> eql_v1_encrypted with ore index term',
- format('SELECT e FROM encrypted WHERE eql_v1.neq(e, %L);', e),
- 3);
+ PERFORM assert_no_result(
+ 'eql_v1_encrypted <> eql_v1_encrypted with no matching record',
+ format('SELECT e FROM encrypted WHERE e <> %L;', e));
END;
$$ LANGUAGE plpgsql;
+-- ========================================================================
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
--
--- Unique equality - eql_v1_encrypted <> jsonb
+-- Blake equality - eql_v1_encrypted <> eql_v1_encrypted
--
DO $$
DECLARE
- e jsonb;
+ e eql_v1_encrypted;
BEGIN
+
for i in 1..3 loop
- e := create_encrypted_json(i)::jsonb-'o';
+ e := create_encrypted_json(i, 'b');
PERFORM assert_result(
- format('eql_v1_encrypted <> eql_v1_encrypted with unique index term %s of 3', i),
- format('SELECT e FROM encrypted WHERE e <> %L::jsonb;', e));
+ format('eql_v1_encrypted <> eql_v1_encrypted with blake3 index term %s of 3', i),
+ format('SELECT e FROM encrypted WHERE e <> %L;', e));
- PERFORM assert_count(
- format('eql_v1_encrypted <> eql_v1_encrypted with ore index term %s of 3', i),
- format('SELECT e FROM encrypted WHERE e <> %L::jsonb', e),
- 2);
end loop;
-- remove the ore index term
- e := create_encrypted_json(91347)::jsonb-'o';
-
- PERFORM assert_result(
- 'eql_v1_encrypted <> eql_v1_encrypted with no matching record',
- format('SELECT e FROM encrypted WHERE e <> %L::jsonb;', e));
+ e := create_encrypted_json(91347, 'b');
- PERFORM assert_count(
+ PERFORM assert_no_result(
'eql_v1_encrypted <> eql_v1_encrypted with no matching record',
- format('SELECT e FROM encrypted WHERE e <> %L::jsonb;', e),
- 3);
+ format('SELECT e FROM encrypted WHERE e <> %L;', e));
END;
$$ LANGUAGE plpgsql;
-
---
--- ORE inequality eql_v1_encrypted <> eql_v1_encrypted
---
---
--- Example ORE values are generated from an array in the form `vec![0, 1, 2, 3, 4, 5]`;
---
--- JSON values are JSON escaped on top of a PostgreSQL escaped Record
---
--- PostgreSQL value is ("{""(\\""\\\\\\\\x000102030405\\"")""}")
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
--
+-- Blake3 equality - eql_v1.neq(eql_v1_encrypted, eql_v1_encrypted)
--
DO $$
DECLARE
e eql_v1_encrypted;
- ore_term jsonb;
BEGIN
- -- remove the unique index term
- e := create_encrypted_json()::jsonb-'u';
-
- -- Same ORE value for all items so no results
- PERFORM assert_no_result(
- 'eql_v1_encrypted <> eql_v1_encrypted with ore index term',
- format('SELECT e FROM encrypted WHERE e <> %L', e));
-
-
- -- -- not the same ore term
- ore_term := '{"o": ["1212121212125932e28282d03415e7714fccd69eb7eb476c70743e485e20331f59cbc1c848dcdeda716f351eb20588c406a7df5fb8917ebf816739aa1414ac3b8498e493bf0badea5c9fdb3cc34da8b152b995957591880c523beb1d3f12487c38d18f62dd26209a727674e5a5fe3a3e3037860839afd8011f94b49eaa5fa5a60e1e2adccde4185a7d6c7f83088500b677f897d4ffc276016d614708488f407c01bd3ccf2be653269062cb97f8945a621d049277d19b1c248611f25d047038928d2efeb4323c402af4c19288c7b36911dc06639af5bb34367519b66c1f525bbd3828c12067c9c579aeeb4fb3ae0918125dc1dad5fd518019a5ae67894ce1a7f7bed1a591ba8edda2fdf4cd403761fd981fb1ea5eb0bf806f919350ee60cac16d0a39a491a4d79301781f95ea3870aea82e9946053537360b2fb415b18b61aed0af81d461ad6b923f10c0df79daddc4e279ff543a282bb3a37f9fa03238348b3dac51a453b04bced1f5bd318ddd829bdfe5f37abdbeda730e21441b818302f3c5c2c4d5657accfca4c53d7a80eb3db43946d38965be5f796b"]}'::jsonb;
-
- -- remove the unique index term and add the ore term
- e := create_encrypted_json()::jsonb-'u' || ore_term;
+ for i in 1..3 loop
+ e := create_encrypted_json(i, 'b');
PERFORM assert_result(
- 'eql_v1_encrypted <> eql_v1_encrypted with ore index term',
- format('SELECT e FROM encrypted WHERE e <> %L', e));
-
- PERFORM assert_count(
- 'eql_v1_encrypted <> eql_v1_encrypted with no matching record',
- format('SELECT e FROM encrypted WHERE e <> %L;', e),
- 3);
-
- END;
-$$ LANGUAGE plpgsql;
-
-
-
--- --
--- -- ORE equality using the `eql_v1.ore_64_8_v1(eql_v1_encrypted)` function calls
--- --
--- -- Example ORE values are generated from an array in the form `vec![0, 1, 2, 3, 4, 5]`;
--- --
--- -- JSON values are JSON escaped on top of a PostgreSQL escaped Record
--- --
--- -- PostgreSQL value is ("{""(\\""\\\\\\\\x000102030405\\"")""}")
--- --
--- --
-DO $$
-DECLARE
- e eql_v1_encrypted;
- ore_term jsonb;
- BEGIN
-
- -- remove the unique index term
- e := create_encrypted_json()::jsonb-'u';
-
- PERFORM assert_no_result(
- 'eql_v1.ore_64_8_v1(eql_v1_encrypted) <> eql_v1.ore_64_8_v1(eql_v1_encrypted)',
- format('SELECT e FROM encrypted WHERE eql_v1.ore_64_8_v1(e) <> eql_v1.ore_64_8_v1(%L::eql_v1_encrypted)', e));
-
- -- new ore term
- ore_term := '{"o": ["1212121212125932e28282d03415e7714fccd69eb7eb476c70743e485e20331f59cbc1c848dcdeda716f351eb20588c406a7df5fb8917ebf816739aa1414ac3b8498e493bf0badea5c9fdb3cc34da8b152b995957591880c523beb1d3f12487c38d18f62dd26209a727674e5a5fe3a3e3037860839afd8011f94b49eaa5fa5a60e1e2adccde4185a7d6c7f83088500b677f897d4ffc276016d614708488f407c01bd3ccf2be653269062cb97f8945a621d049277d19b1c248611f25d047038928d2efeb4323c402af4c19288c7b36911dc06639af5bb34367519b66c1f525bbd3828c12067c9c579aeeb4fb3ae0918125dc1dad5fd518019a5ae67894ce1a7f7bed1a591ba8edda2fdf4cd403761fd981fb1ea5eb0bf806f919350ee60cac16d0a39a491a4d79301781f95ea3870aea82e9946053537360b2fb415b18b61aed0af81d461ad6b923f10c0df79daddc4e279ff543a282bb3a37f9fa03238348b3dac51a453b04bced1f5bd318ddd829bdfe5f37abdbeda730e21441b818302f3c5c2c4d5657accfca4c53d7a80eb3db43946d38965be5f796b"]}'::jsonb;
-
- -- remove the unique index term and add the ore term
- e := create_encrypted_json()::jsonb-'u' || ore_term;
- -- -- PERFORM eql_v1.log('e', e::text);
+ format('eql_v1.neq(eql_v1_encrypted, eql_v1_encrypted) with unique index term %s of 3', i),
+ format('SELECT e FROM encrypted WHERE eql_v1.neq(e, %L);', e));
+ end loop;
- PERFORM assert_result(
- 'eql_v1.ore_64_8_v1(eql_v1_encrypted) <> eql_v1.ore_64_8_v1(eql_v1_encrypted)',
- format('SELECT e FROM encrypted WHERE eql_v1.ore_64_8_v1(e) <> eql_v1.ore_64_8_v1(%L::eql_v1_encrypted)', e));
+ -- remove the ore index term
+ e := create_encrypted_json(91347, 'b');
- PERFORM assert_count(
- 'eql_v1.ore_64_8_v1(eql_v1_encrypted) <> eql_v1.ore_64_8_v1(eql_v1_encrypted)',
- format('SELECT e FROM encrypted WHERE eql_v1.ore_64_8_v1(e) <> eql_v1.ore_64_8_v1(%L::eql_v1_encrypted)', e),
- 3);
+ PERFORM assert_no_result(
+ 'eql_v1.neq(eql_v1_encrypted, eql_v1_encrypted) with no matching record',
+ format('SELECT e FROM encrypted WHERE eql_v1.neq(e, %L);', e));
END;
$$ LANGUAGE plpgsql;
-
---
--- ORE equality using the `eql_v1.neq(eql_v1_encrypted, eql_v1_encrypted)` function calls
---
--- Example ORE values are generated from an array in the form `vec![0, 1, 2, 3, 4, 5]`;
---
--- JSON values are JSON escaped on top of a PostgreSQL escaped Record
---
--- PostgreSQL value is ("{""(\\""\\\\\\\\x000102030405\\"")""}")
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
--
+-- Blake3 equality - eql_v1_encrypted = jsonb
--
DO $$
DECLARE
- e eql_v1_encrypted;
- ore_term jsonb;
+ e jsonb;
BEGIN
+ for i in 1..3 loop
- -- remove the unique index term
- e := create_encrypted_json()::jsonb-'u';
+ -- remove the default
+ e := create_encrypted_json(i, 'b');
- PERFORM assert_no_result(
- 'eql_v1.neq(eql_v1_encrypted, eql_v1_encrypted)',
- format('SELECT e FROM encrypted WHERE eql_v1.neq(e, %L);', e));
+ PERFORM assert_result(
+ format('eql_v1_encrypted = jsonb with unique index term %s of 3', i),
+ format('SELECT e FROM encrypted WHERE e <> %L::jsonb;', e));
- -- new ore term
- ore_term := '{"o": ["1212121212125932e28282d03415e7714fccd69eb7eb476c70743e485e20331f59cbc1c848dcdeda716f351eb20588c406a7df5fb8917ebf816739aa1414ac3b8498e493bf0badea5c9fdb3cc34da8b152b995957591880c523beb1d3f12487c38d18f62dd26209a727674e5a5fe3a3e3037860839afd8011f94b49eaa5fa5a60e1e2adccde4185a7d6c7f83088500b677f897d4ffc276016d614708488f407c01bd3ccf2be653269062cb97f8945a621d049277d19b1c248611f25d047038928d2efeb4323c402af4c19288c7b36911dc06639af5bb34367519b66c1f525bbd3828c12067c9c579aeeb4fb3ae0918125dc1dad5fd518019a5ae67894ce1a7f7bed1a591ba8edda2fdf4cd403761fd981fb1ea5eb0bf806f919350ee60cac16d0a39a491a4d79301781f95ea3870aea82e9946053537360b2fb415b18b61aed0af81d461ad6b923f10c0df79daddc4e279ff543a282bb3a37f9fa03238348b3dac51a453b04bced1f5bd318ddd829bdfe5f37abdbeda730e21441b818302f3c5c2c4d5657accfca4c53d7a80eb3db43946d38965be5f796b"]}'::jsonb;
+ PERFORM assert_result(
+ format('jsonb = eql_v1_encrypted with unique index term %s of 3', i),
+ format('SELECT e FROM encrypted WHERE %L::jsonb = e', e));
+ end loop;
- -- remove the unique index term and add the ore term
- e := create_encrypted_json()::jsonb-'u' || ore_term;
+ e := create_encrypted_json(91347, 'b');
+ PERFORM assert_no_result(
+ 'eql_v1_encrypted = jsonb with no matching record',
+ format('SELECT e FROM encrypted WHERE e <> %L::jsonb', e));
- PERFORM assert_result(
- 'eql_v1.neq(eql_v1_encrypted, eql_v1_encrypted)',
- format('SELECT e FROM encrypted WHERE eql_v1.neq(e, %L);', e));
-
+ PERFORM assert_no_result(
+ 'jsonb = eql_v1_encrypted with no matching record',
+ format('SELECT e FROM encrypted WHERE %L::jsonb = e', e));
END;
$$ LANGUAGE plpgsql;
-
-
-
-
SELECT drop_table_with_encrypted();
\ No newline at end of file
diff --git a/src/operators/<@.sql b/src/operators/<@.sql
index e69de29..cbe76bf 100644
--- a/src/operators/<@.sql
+++ b/src/operators/<@.sql
@@ -0,0 +1,19 @@
+-- REQUIRE: src/schema.sql
+-- REQUIRE: src/encrypted/types.sql
+-- REQUIRE: src/ste_vec/functions.sql
+
+
+-- DROP OPERATOR IF EXISTS <@ (eql_v1_encrypted, eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1."<@"(e eql_v1_encrypted, b eql_v1_encrypted);
+
+CREATE FUNCTION eql_v1."<@"(a eql_v1_encrypted, b eql_v1_encrypted)
+RETURNS boolean AS $$
+ -- Contains with reversed arguments
+ SELECT eql_v1.ste_vec_contains(b, a)
+$$ LANGUAGE SQL;
+
+CREATE OPERATOR <@(
+ FUNCTION=eql_v1."<@",
+ LEFTARG=eql_v1_encrypted,
+ RIGHTARG=eql_v1_encrypted
+);
diff --git a/src/operators/<@_test.sql b/src/operators/<@_test.sql
new file mode 100644
index 0000000..8012576
--- /dev/null
+++ b/src/operators/<@_test.sql
@@ -0,0 +1,44 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- ore_cllw_u64_8 equality
+--
+-- Test data is in form '{"hello": "{one | two | three}", "n": {10 | 20 | 30} }'
+--
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ sv := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE %L::eql_v1_encrypted <@ e', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE %L::eql_v1_encrypted <@ e', term),
+ 1);
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+SELECT drop_table_with_encrypted();
\ No newline at end of file
diff --git a/src/operators/<_test.sql b/src/operators/<_test.sql
index 1d51f6a..6da744c 100644
--- a/src/operators/<_test.sql
+++ b/src/operators/<_test.sql
@@ -3,6 +3,97 @@
SELECT create_table_with_encrypted();
SELECT seed_encrypted_json();
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- eql_v1_encrypted < eql_v1_encrypted with ore_cllw_u64_8 index
+--
+-- Test data is in form '{"hello": "{one | two | three}", "n": {10 | 20 | 30} }'
+--
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ -- json n: 30
+ sv := get_numeric_ste_vec_30()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'2517068c0d1f9d4d41d2c666211f785e';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted < eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' < %L::eql_v1_encrypted', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted < eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' < %L::eql_v1_encrypted', term),
+ 2);
+
+ -- -- Check the $.hello path
+ -- -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_no_result(
+ format('eql_v1_encrypted < eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' < %L::eql_v1_encrypted', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- eql_v1_encrypted < eql_v1_encrypted with ore_cllw_var_8 index
+--
+-- Test data is in form '{"hello": "{one | two | three}", "n": {10 | 20 | 30} }'
+--
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ sv := get_numeric_ste_vec_30()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted < eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' < %L::eql_v1_encrypted', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted < eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' < %L::eql_v1_encrypted', term),
+ 1);
+
+ -- -- Check the $.n path
+ -- -- Returned encrypted does not have ore_cllw_var_8
+ PERFORM assert_no_result(
+ format('eql_v1_encrypted < eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' < %L::eql_v1_encrypted', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
--
-- ORE - eql_v1_encrypted < eql_v1_encrypted
--
@@ -11,7 +102,6 @@ DECLARE
e eql_v1_encrypted;
ore_term eql_v1_encrypted;
BEGIN
-
SELECT ore.e FROM ore WHERE id = 42 INTO ore_term;
PERFORM assert_count(
@@ -19,19 +109,15 @@ DECLARE
format('SELECT id FROM ore WHERE e < %L ORDER BY e DESC', ore_term),
41);
- for i in 1..3 loop
- e := create_encrypted_json(i);
+ -- Record with a Numeric ORE term of 1
+ e := create_encrypted_ore_json(1);
- PERFORM assert_no_result(
- format('eql_v1_encrypted < eql_v1_encrypted %s of 3', i),
- format('SELECT e FROM encrypted WHERE e < %L;', e));
- end loop;
+ PERFORM assert_no_result(
+ format('eql_v1_encrypted < eql_v1_encrypted'),
+ format('SELECT e FROM encrypted WHERE e < %L;', e));
- -- "HIGH" ORE
- ore_term := '{"o": ["1212121212125932e28282d03415e7714fccd69eb7eb476c70743e485e20331f59cbc1c848dcdeda716f351eb20588c406a7df5fb8917ebf816739aa1414ac3b8498e493bf0badea5c9fdb3cc34da8b152b995957591880c523beb1d3f12487c38d18f62dd26209a727674e5a5fe3a3e3037860839afd8011f94b49eaa5fa5a60e1e2adccde4185a7d6c7f83088500b677f897d4ffc276016d614708488f407c01bd3ccf2be653269062cb97f8945a621d049277d19b1c248611f25d047038928d2efeb4323c402af4c19288c7b36911dc06639af5bb34367519b66c1f525bbd3828c12067c9c579aeeb4fb3ae0918125dc1dad5fd518019a5ae67894ce1a7f7bed1a591ba8edda2fdf4cd403761fd981fb1ea5eb0bf806f919350ee60cac16d0a39a491a4d79301781f95ea3870aea82e9946053537360b2fb415b18b61aed0af81d461ad6b923f10c0df79daddc4e279ff543a282bb3a37f9fa03238348b3dac51a453b04bced1f5bd318ddd829bdfe5f37abdbeda730e21441b818302f3c5c2c4d5657accfca4c53d7a80eb3db43946d38965be5f796b"]}'::jsonb;
-
- -- add the ore term
- e := (create_encrypted_json()::jsonb || ore_term::jsonb)::eql_v1_encrypted;
+ -- Record with a Numeric ORE term of 42
+ e := create_encrypted_ore_json(42);
PERFORM assert_result(
'eql_v1_encrypted < eql_v1_encrypted',
@@ -53,11 +139,8 @@ DECLARE
e eql_v1_encrypted;
ore_term jsonb;
BEGIN
- -- "HIGH" ORE
- ore_term := '{"o": ["1212121212125932e28282d03415e7714fccd69eb7eb476c70743e485e20331f59cbc1c848dcdeda716f351eb20588c406a7df5fb8917ebf816739aa1414ac3b8498e493bf0badea5c9fdb3cc34da8b152b995957591880c523beb1d3f12487c38d18f62dd26209a727674e5a5fe3a3e3037860839afd8011f94b49eaa5fa5a60e1e2adccde4185a7d6c7f83088500b677f897d4ffc276016d614708488f407c01bd3ccf2be653269062cb97f8945a621d049277d19b1c248611f25d047038928d2efeb4323c402af4c19288c7b36911dc06639af5bb34367519b66c1f525bbd3828c12067c9c579aeeb4fb3ae0918125dc1dad5fd518019a5ae67894ce1a7f7bed1a591ba8edda2fdf4cd403761fd981fb1ea5eb0bf806f919350ee60cac16d0a39a491a4d79301781f95ea3870aea82e9946053537360b2fb415b18b61aed0af81d461ad6b923f10c0df79daddc4e279ff543a282bb3a37f9fa03238348b3dac51a453b04bced1f5bd318ddd829bdfe5f37abdbeda730e21441b818302f3c5c2c4d5657accfca4c53d7a80eb3db43946d38965be5f796b"]}'::jsonb;
-
- -- add the ore term
- e := (create_encrypted_json()::jsonb || ore_term)::eql_v1_encrypted;
+ -- Record with a Numeric ORE term of 42
+ e := create_encrypted_ore_json(42);
PERFORM assert_result(
'eql_v1.lt(a eql_v1_encrypted, b eql_v1_encrypted)',
diff --git a/src/operators/=.sql b/src/operators/=.sql
index 5337275..8ef9f27 100644
--- a/src/operators/=.sql
+++ b/src/operators/=.sql
@@ -3,7 +3,12 @@
-- REQUIRE: src/unique/functions.sql
-- REQUIRE: src/ore/types.sql
-- REQUIRE: src/ore/functions.sql
-
+-- REQUIRE: src/ore/operators.sql
+-- REQUIRE: src/blake3/types.sql
+-- REQUIRE: src/blake3/functions.sql
+-- REQUIRE: src/ore_cllw_u64_8/types.sql
+-- REQUIRE: src/ore_cllw_u64_8/functions.sql
+-- REQUIRE: src/ore_cllw_u64_8/operators.sql
-- Operators for equality comparisons of eql_v1_encrypted types
--
@@ -16,43 +21,57 @@
-- There are multiple index terms that provide equality comparisons
-- - unique
-- - ore_64_8_v1
--- - ore_cllw_8_v1
+--
--
-- We check these index terms in this order and use the first one that exists for both parameters
--
--
-DROP FUNCTION IF EXISTS eql_v1.eq(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.eq(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.eq(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
IMMUTABLE STRICT PARALLEL SAFE
AS $$
- DECLARE
- u boolean;
- o boolean;
BEGIN
+
BEGIN
- u := (SELECT eql_v1.unique(a) = eql_v1.unique(b));
+ RETURN eql_v1.unique(a) = eql_v1.unique(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('No unique index');
+ END;
+ BEGIN
+ RETURN eql_v1.blake3(a) = eql_v1.blake3(b);
EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('No blake3 index');
+ END;
- u := false;
+ BEGIN
+ RETURN eql_v1.ore_cllw_u64_8(a) = eql_v1.ore_cllw_u64_8(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('No ore_cllw_u64_8 index');
+ END;
+
+ BEGIN
+ RETURN eql_v1.ore_cllw_var_8(a) = eql_v1.ore_cllw_var_8(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('No ore_cllw_u64_8 index');
END;
BEGIN
- o := (SELECT eql_v1.ore_64_8_v1(a) = eql_v1.ore_64_8_v1(b));
+ RETURN eql_v1.ore_64_8_v1(a) = eql_v1.ore_64_8_v1(b);
EXCEPTION WHEN OTHERS THEN
- o := false;
+ -- PERFORM eql_v1.log('No ore_64_8_v1 index');
END;
- RETURN u OR o;
+ RETURN false;
END;
$$ LANGUAGE plpgsql;
-DROP OPERATOR IF EXISTS = (eql_v1_encrypted, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1."="(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS = (eql_v1_encrypted, eql_v1_encrypted) CASCADE;
+-- DROP FUNCTION IF EXISTS eql_v1."="(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1."="(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
@@ -74,8 +93,8 @@ CREATE OPERATOR = (
MERGES
);
-DROP OPERATOR IF EXISTS = (eql_v1_encrypted, jsonb);
-DROP FUNCTION IF EXISTS eql_v1."="(a eql_v1_encrypted, b jsonb);
+-- DROP OPERATOR IF EXISTS = (eql_v1_encrypted, jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1."="(a eql_v1_encrypted, b jsonb);
CREATE FUNCTION eql_v1."="(a eql_v1_encrypted, b jsonb)
RETURNS boolean
@@ -97,8 +116,8 @@ CREATE OPERATOR = (
MERGES
);
-DROP OPERATOR IF EXISTS = (jsonb, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1."="(a jsonb, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS = (jsonb, eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1."="(a jsonb, b eql_v1_encrypted);
CREATE FUNCTION eql_v1."="(a jsonb, b eql_v1_encrypted)
RETURNS boolean
diff --git a/src/operators/=_ore_cllw_u64_8_test.sql b/src/operators/=_ore_cllw_u64_8_test.sql
new file mode 100644
index 0000000..7f52203
--- /dev/null
+++ b/src/operators/=_ore_cllw_u64_8_test.sql
@@ -0,0 +1,56 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+
+-- ========================================================================
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- ore_cllw_u64_8 equality
+--
+-- Test data is in form '{"hello": "{one | two | three}", "n": {10 | 20 | 30} }'
+--
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ -- json n: 10
+ sv := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'2517068c0d1f9d4d41d2c666211f785e';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE (e->''2517068c0d1f9d4d41d2c666211f785e'') = %L::eql_v1_encrypted', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' = %L::eql_v1_encrypted', term),
+ 1);
+
+ -- -- Check the $.hello path
+ -- -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_no_result(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' = %L::eql_v1_encrypted', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+SELECT drop_table_with_encrypted();
\ No newline at end of file
diff --git a/src/operators/=_ore_cllw_var_8_test.sql b/src/operators/=_ore_cllw_var_8_test.sql
new file mode 100644
index 0000000..8ef38ab
--- /dev/null
+++ b/src/operators/=_ore_cllw_var_8_test.sql
@@ -0,0 +1,53 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- ore_cllw_u64_8 equality
+--
+-- Test data is in form '{"hello": "{one | two | three}", "n": {10 | 20 | 30} }'
+--
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ -- json n: 10
+ sv := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE (e->''a7cea93975ed8c01f861ccb6bd082784'') = %L::eql_v1_encrypted', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' = %L::eql_v1_encrypted', term),
+ 1);
+
+ -- -- Check the $.n path
+ -- -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_no_result(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' = %L::eql_v1_encrypted', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+SELECT drop_table_with_encrypted();
\ No newline at end of file
diff --git a/src/operators/=_ore_test.sql b/src/operators/=_ore_test.sql
new file mode 100644
index 0000000..1b06c6b
--- /dev/null
+++ b/src/operators/=_ore_test.sql
@@ -0,0 +1,87 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+
+--
+-- ORE - eql_v1_encrypted = eql_v1_encrypted
+--
+DO $$
+DECLARE
+ e eql_v1_encrypted;
+ ore_term jsonb;
+ BEGIN
+
+ -- Record with a Numeric ORE term of 42
+ e := create_encrypted_ore_json(42);
+ PERFORM seed_encrypted(e);
+
+ PERFORM assert_result(
+ 'eql_v1_encrypted = eql_v1_encrypted',
+ format('SELECT e FROM encrypted WHERE e = %L::eql_v1_encrypted', e));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted = eql_v1_encrypted'),
+ format('SELECT e FROM encrypted WHERE e = %L;', e),
+ 1);
+
+ e := create_encrypted_ore_json(20);
+
+ PERFORM assert_result(
+ 'eql_v1_encrypted = eql_v1_encrypted',
+ format('SELECT e FROM encrypted WHERE e = %L::eql_v1_encrypted', e));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted = eql_v1_encrypted'),
+ format('SELECT e FROM encrypted WHERE e = %L;', e),
+ 1);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+--
+-- ORE - eql_v1.gte(a eql_v1_encrypted, b eql_v1_encrypted)
+--
+DO $$
+DECLARE
+ e eql_v1_encrypted;
+ ore_term jsonb;
+ BEGIN
+ -- Reset data
+ PERFORM seed_encrypted_json();
+
+ -- Record with a Numeric ORE term of 20
+ e := create_encrypted_ore_json(20);
+ PERFORM seed_encrypted(e);
+
+ PERFORM assert_result(
+ 'eql_v1.eq(a eql_v1_encrypted, b eql_v1_encrypted)',
+ format('SELECT e FROM encrypted WHERE eql_v1.eq(e, %L)', e));
+
+ -- include
+ PERFORM assert_count(
+ 'eql_v1.eq(a eql_v1_encrypted, b eql_v1_encrypted)',
+ format('SELECT e FROM encrypted WHERE eql_v1.eq(e, %L)', e),
+ 2);
+
+ -- Record with a Numeric ORE term of 30
+ e := create_encrypted_ore_json(30);
+
+ PERFORM assert_result(
+ 'eql_v1.get(a eql_v1_encrypted, b eql_v1_encrypted)',
+ format('SELECT e FROM encrypted WHERE eql_v1.eq(e, %L)', e));
+
+ PERFORM assert_count(
+ 'eql_v1.get(a eql_v1_encrypted, b eql_v1_encrypted)',
+ format('SELECT e FROM encrypted WHERE eql_v1.eq(e, %L)', e),
+ 1);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- ========================================================================
+
+
+SELECT drop_table_with_encrypted();
\ No newline at end of file
diff --git a/src/operators/=_test.sql b/src/operators/=_test.sql
index 7251253..d50267c 100644
--- a/src/operators/=_test.sql
+++ b/src/operators/=_test.sql
@@ -3,7 +3,6 @@
SELECT create_table_with_encrypted();
SELECT seed_encrypted_json();
-SELECT e FROM encrypted WHERE e = '("{""c"": ""ciphertext"", ""i"": {""c"": ""e"", ""t"": ""encrypted""}, ""j"": [{""c"": ""ciphertext.1"", ""s"": ""selector.1"", ""t"": ""term.1""}], ""m"": [10, 11, 12, 13, 14, 15], ""u"": ""unique.1"", ""75d1219a941e4853572b60f51"": ""902cd835193393f41315d2e00""}")';
--
-- Unique equality - eql_v1_encrypted = eql_v1_encrypted
@@ -14,7 +13,7 @@ DECLARE
BEGIN
for i in 1..3 loop
- e := create_encrypted_json(i)::jsonb-'o';
+ e := create_encrypted_json(i, 'u');
PERFORM assert_result(
format('eql_v1_encrypted = eql_v1_encrypted with unique index term %s of 3', i),
@@ -23,7 +22,7 @@ DECLARE
end loop;
-- remove the ore index term
- e := create_encrypted_json(91347)::jsonb-'o';
+ e := create_encrypted_json(91347, 'u');
PERFORM assert_no_result(
'eql_v1_encrypted = eql_v1_encrypted with no matching record',
@@ -95,136 +94,103 @@ DECLARE
$$ LANGUAGE plpgsql;
+
+-- ========================================================================
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
--
--- Example ORE values are generated from an array in the form `vec![0, 1, 2, 3, 4, 5]`;
---
--- JSON values are JSON escaped on top of a PostgreSQL escaped Record
---
--- PostgreSQL value is ("{""(\\""\\\\\\\\x000102030405\\"")""}")
---
+-- Blake equality - eql_v1_encrypted = eql_v1_encrypted
--
DO $$
DECLARE
e eql_v1_encrypted;
- ore_term jsonb;
BEGIN
- -- remove the unique index term
- e := create_encrypted_json()::jsonb-'u';
+ for i in 1..3 loop
+ e := create_encrypted_json(i, 'b');
PERFORM assert_result(
- format('eql_v1_encrypted = eql_v1_encrypted with ore index term'),
- format('SELECT e FROM encrypted WHERE e = %L', e));
-
- PERFORM assert_count(
- format('eql_v1_encrypted = eql_v1_encrypted with ore index term'),
- format('SELECT e FROM encrypted WHERE e = %L', e),
- 3);
-
+ format('eql_v1_encrypted = eql_v1_encrypted with unique index term %s of 3', i),
+ format('SELECT e FROM encrypted WHERE e = %L;', e));
- -- -- not the same ore term
- ore_term := '{"o": ["1212121212125932e28282d03415e7714fccd69eb7eb476c70743e485e20331f59cbc1c848dcdeda716f351eb20588c406a7df5fb8917ebf816739aa1414ac3b8498e493bf0badea5c9fdb3cc34da8b152b995957591880c523beb1d3f12487c38d18f62dd26209a727674e5a5fe3a3e3037860839afd8011f94b49eaa5fa5a60e1e2adccde4185a7d6c7f83088500b677f897d4ffc276016d614708488f407c01bd3ccf2be653269062cb97f8945a621d049277d19b1c248611f25d047038928d2efeb4323c402af4c19288c7b36911dc06639af5bb34367519b66c1f525bbd3828c12067c9c579aeeb4fb3ae0918125dc1dad5fd518019a5ae67894ce1a7f7bed1a591ba8edda2fdf4cd403761fd981fb1ea5eb0bf806f919350ee60cac16d0a39a491a4d79301781f95ea3870aea82e9946053537360b2fb415b18b61aed0af81d461ad6b923f10c0df79daddc4e279ff543a282bb3a37f9fa03238348b3dac51a453b04bced1f5bd318ddd829bdfe5f37abdbeda730e21441b818302f3c5c2c4d5657accfca4c53d7a80eb3db43946d38965be5f796b"]}'::jsonb;
+ end loop;
- -- remove the unique index term and add the ore term
- e := create_encrypted_json()::jsonb-'u' || ore_term;
+ -- remove the ore index term
+ e := create_encrypted_json(91347, 'b');
- PERFORM assert_no_result(
- format('eql_v1_encrypted = eql_v1_encrypted with ore index term'),
- format('SELECT e FROM encrypted WHERE e = %L', e));
+ PERFORM assert_no_result(
+ 'eql_v1_encrypted = eql_v1_encrypted with no matching record',
+ format('SELECT e FROM encrypted WHERE e = %L;', e));
END;
$$ LANGUAGE plpgsql;
-
---
--- ORE equality using the `eql_v1.ore_64_8_v1(eql_v1_encrypted)` function calls
---
--- Example ORE values are generated from an array in the form `vec![0, 1, 2, 3, 4, 5]`;
---
--- JSON values are JSON escaped on top of a PostgreSQL escaped Record
---
--- PostgreSQL value is ("{""(\\""\\\\\\\\x000102030405\\"")""}")
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
--
+-- Blake3 equality - eql_v1.eq(eql_v1_encrypted, eql_v1_encrypted)
--
DO $$
DECLARE
e eql_v1_encrypted;
- ore_term jsonb;
BEGIN
- -- remove the unique index term
- e := create_encrypted_json()::jsonb-'u';
+ for i in 1..3 loop
+ e := create_encrypted_json(i, 'b');
PERFORM assert_result(
- format('eql_v1.ore_64_8_v1(eql_v1_encrypted) = eql_v1.ore_64_8_v1(eql_v1_encrypted)'),
- format('SELECT e FROM encrypted WHERE eql_v1.ore_64_8_v1(e) = eql_v1.ore_64_8_v1(%L::eql_v1_encrypted)', e));
-
- -- all seed values have the same ore term
- PERFORM assert_count(
- format('eql_v1.ore_64_8_v1(eql_v1_encrypted) = eql_v1.ore_64_8_v1(eql_v1_encrypted)'),
- format('SELECT e FROM encrypted WHERE eql_v1.ore_64_8_v1(e) = eql_v1.ore_64_8_v1(%L::eql_v1_encrypted)', e),
- 3);
-
-
- -- new ore term
- ore_term := '{"o": ["1212121212125932e28282d03415e7714fccd69eb7eb476c70743e485e20331f59cbc1c848dcdeda716f351eb20588c406a7df5fb8917ebf816739aa1414ac3b8498e493bf0badea5c9fdb3cc34da8b152b995957591880c523beb1d3f12487c38d18f62dd26209a727674e5a5fe3a3e3037860839afd8011f94b49eaa5fa5a60e1e2adccde4185a7d6c7f83088500b677f897d4ffc276016d614708488f407c01bd3ccf2be653269062cb97f8945a621d049277d19b1c248611f25d047038928d2efeb4323c402af4c19288c7b36911dc06639af5bb34367519b66c1f525bbd3828c12067c9c579aeeb4fb3ae0918125dc1dad5fd518019a5ae67894ce1a7f7bed1a591ba8edda2fdf4cd403761fd981fb1ea5eb0bf806f919350ee60cac16d0a39a491a4d79301781f95ea3870aea82e9946053537360b2fb415b18b61aed0af81d461ad6b923f10c0df79daddc4e279ff543a282bb3a37f9fa03238348b3dac51a453b04bced1f5bd318ddd829bdfe5f37abdbeda730e21441b818302f3c5c2c4d5657accfca4c53d7a80eb3db43946d38965be5f796b"]}'::jsonb;
+ format('eql_v1.eq(eql_v1_encrypted, eql_v1_encrypted) with unique index term %s of 3', i),
+ format('SELECT e FROM encrypted WHERE eql_v1.eq(e, %L);', e));
+ end loop;
- -- remove the unique index term and add the ore term
- e := create_encrypted_json()::jsonb-'u' || ore_term;
- -- -- PERFORM eql_v1.log('e', e::text);
+ -- remove the ore index term
+ e := create_encrypted_json(91347, 'b');
- PERFORM assert_no_result(
- format('eql_v1.ore_64_8_v1(eql_v1_encrypted) = eql_v1.ore_64_8_v1(eql_v1_encrypted)'),
- format('SELECT e FROM encrypted WHERE eql_v1.ore_64_8_v1(e) = eql_v1.ore_64_8_v1(%L::eql_v1_encrypted)', e));
+ PERFORM assert_no_result(
+ 'eql_v1.eq(eql_v1_encrypted, eql_v1_encrypted) with no matching record',
+ format('SELECT e FROM encrypted WHERE eql_v1.eq(e, %L);', e));
END;
$$ LANGUAGE plpgsql;
-
---
--- ORE equality using the `eql_v1.eq(eql_v1_encrypted, eql_v1_encrypted)'
---
--- Example ORE values are generated from an array in the form `vec![0, 1, 2, 3, 4, 5]`;
---
--- JSON values are JSON escaped on top of a PostgreSQL escaped Record
---
--- PostgreSQL value is ("{""(\\""\\\\\\\\x000102030405\\"")""}")
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
--
+-- Blake3 equality - eql_v1_encrypted = jsonb
--
DO $$
DECLARE
- e eql_v1_encrypted;
- ore_term jsonb;
+ e jsonb;
BEGIN
+ for i in 1..3 loop
- -- remove the unique index term
- e := create_encrypted_json()::jsonb-'u';
+ -- remove the default
+ e := create_encrypted_json(i, 'b');
PERFORM assert_result(
- 'eql_v1.eq(eql_v1_encrypted, eql_v1_encrypted)',
- format('SELECT e FROM encrypted WHERE eql_v1.eq(e, %L);', e));
+ format('eql_v1_encrypted = jsonb with unique index term %s of 3', i),
+ format('SELECT e FROM encrypted WHERE e = %L::jsonb;', e));
- -- all seed values have the same ore term
- PERFORM assert_count(
- 'eql_v1.eq(eql_v1_encrypted, eql_v1_encrypted)',
- format('SELECT e FROM encrypted WHERE eql_v1.eq(e, %L);', e),
- 3);
+ PERFORM assert_result(
+ format('jsonb = eql_v1_encrypted with unique index term %s of 3', i),
+ format('SELECT e FROM encrypted WHERE %L::jsonb = e', e));
+ end loop;
+ e := create_encrypted_json(91347, 'b');
- -- new ore term
- ore_term := '{"o": ["1212121212125932e28282d03415e7714fccd69eb7eb476c70743e485e20331f59cbc1c848dcdeda716f351eb20588c406a7df5fb8917ebf816739aa1414ac3b8498e493bf0badea5c9fdb3cc34da8b152b995957591880c523beb1d3f12487c38d18f62dd26209a727674e5a5fe3a3e3037860839afd8011f94b49eaa5fa5a60e1e2adccde4185a7d6c7f83088500b677f897d4ffc276016d614708488f407c01bd3ccf2be653269062cb97f8945a621d049277d19b1c248611f25d047038928d2efeb4323c402af4c19288c7b36911dc06639af5bb34367519b66c1f525bbd3828c12067c9c579aeeb4fb3ae0918125dc1dad5fd518019a5ae67894ce1a7f7bed1a591ba8edda2fdf4cd403761fd981fb1ea5eb0bf806f919350ee60cac16d0a39a491a4d79301781f95ea3870aea82e9946053537360b2fb415b18b61aed0af81d461ad6b923f10c0df79daddc4e279ff543a282bb3a37f9fa03238348b3dac51a453b04bced1f5bd318ddd829bdfe5f37abdbeda730e21441b818302f3c5c2c4d5657accfca4c53d7a80eb3db43946d38965be5f796b"]}'::jsonb;
+ PERFORM assert_no_result(
+ 'eql_v1_encrypted = jsonb with no matching record',
+ format('SELECT e FROM encrypted WHERE e = %L::jsonb', e));
- -- remove the unique index term and add the ore term
- e := create_encrypted_json()::jsonb-'u' || ore_term;
+ PERFORM assert_no_result(
+ 'jsonb = eql_v1_encrypted with no matching record',
+ format('SELECT e FROM encrypted WHERE %L::jsonb = e', e));
- PERFORM assert_no_result(
- 'eql_v1.eq(eql_v1_encrypted, eql_v1_encrypted)',
- format('SELECT e FROM encrypted WHERE eql_v1.eq(e, %L);', e));
END;
$$ LANGUAGE plpgsql;
-
SELECT drop_table_with_encrypted();
\ No newline at end of file
diff --git a/src/operators/>.sql b/src/operators/>.sql
index 86d4600..279e3ec 100644
--- a/src/operators/>.sql
+++ b/src/operators/>.sql
@@ -20,19 +20,43 @@
--
--
-DROP FUNCTION IF EXISTS eql_v1.gt(a eql_v1_encrypted, b eql_v1_encrypted);
+-- WHERE a > b
+-- WHERE eql_v1.gt(a, b)
+--
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.gt(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.gt(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
AS $$
BEGIN
- RETURN eql_v1.ore_64_8_v1(a) > eql_v1.ore_64_8_v1(b);
+
+ BEGIN
+ RETURN eql_v1.ore_cllw_u64_8(a) > eql_v1.ore_cllw_u64_8(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('eql_v1.gt no ore_cllw_u64_8 index');
+ END;
+
+ BEGIN
+ RETURN eql_v1.ore_cllw_var_8(a) > eql_v1.ore_cllw_var_8(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('eql_v1.gt no ore_cllw_var_8 index');
+ END;
+
+ BEGIN
+ RETURN eql_v1.ore_64_8_v1(a) > eql_v1.ore_64_8_v1(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('eql_v1.gt no ore_64_8_v1 index');
+ END;
+
+ RETURN false;
END;
$$ LANGUAGE plpgsql;
-DROP OPERATOR IF EXISTS > (eql_v1_encrypted, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1.">"(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS > (eql_v1_encrypted, eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.">"(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.">"(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
@@ -53,8 +77,8 @@ CREATE OPERATOR >(
);
-DROP OPERATOR IF EXISTS > (eql_v1_encrypted, jsonb);
-DROP FUNCTION IF EXISTS eql_v1.">"(a eql_v1_encrypted, b jsonb);
+-- DROP OPERATOR IF EXISTS > (eql_v1_encrypted, jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.">"(a eql_v1_encrypted, b jsonb);
CREATE FUNCTION eql_v1.">"(a eql_v1_encrypted, b jsonb)
RETURNS boolean
@@ -75,8 +99,8 @@ CREATE OPERATOR >(
);
-DROP OPERATOR IF EXISTS > (jsonb, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1.">"(a jsonb, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS > (jsonb, eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.">"(a jsonb, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.">"(a jsonb, b eql_v1_encrypted)
RETURNS boolean
diff --git a/src/operators/>=.sql b/src/operators/>=.sql
index 20e6d89..100d969 100644
--- a/src/operators/>=.sql
+++ b/src/operators/>=.sql
@@ -20,19 +20,38 @@
--
--
-DROP FUNCTION IF EXISTS eql_v1.gte(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.gte(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.gte(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
AS $$
BEGIN
- RETURN eql_v1.ore_64_8_v1(a) >= eql_v1.ore_64_8_v1(b);
+
+ BEGIN
+ RETURN eql_v1.ore_cllw_u64_8(a) >= eql_v1.ore_cllw_u64_8(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('eql_v1.gte no ore_cllw_u64_8 index');
+ END;
+
+ BEGIN
+ RETURN eql_v1.ore_cllw_var_8(a) >= eql_v1.ore_cllw_var_8(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('eql_v1.gte no ore_cllw_var_8 index');
+ END;
+
+ BEGIN
+ RETURN eql_v1.ore_64_8_v1(a) >= eql_v1.ore_64_8_v1(b);
+ EXCEPTION WHEN OTHERS THEN
+ -- PERFORM eql_v1.log('eql_v1.gte no ore_64_8_v1 index');
+ END;
+
+ RETURN false;
END;
$$ LANGUAGE plpgsql;
-DROP OPERATOR IF EXISTS >= (eql_v1_encrypted, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1.">="(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS >= (eql_v1_encrypted, eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.">="(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.">="(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
@@ -54,8 +73,8 @@ CREATE OPERATOR >=(
);
-DROP OPERATOR IF EXISTS >= (eql_v1_encrypted, jsonb);
-DROP FUNCTION IF EXISTS eql_v1.">="(a eql_v1_encrypted, b jsonb);
+-- DROP OPERATOR IF EXISTS >= (eql_v1_encrypted, jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.">="(a eql_v1_encrypted, b jsonb);
CREATE FUNCTION eql_v1.">="(a eql_v1_encrypted, b jsonb)
RETURNS boolean
@@ -76,8 +95,8 @@ CREATE OPERATOR >=(
);
-DROP OPERATOR IF EXISTS >= (jsonb, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1.">="(a jsonb, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS >= (jsonb, eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.">="(a jsonb, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.">="(a jsonb, b eql_v1_encrypted)
RETURNS boolean
diff --git a/src/operators/>=_test.sql b/src/operators/>=_test.sql
index 01c060b..8e7635a 100644
--- a/src/operators/>=_test.sql
+++ b/src/operators/>=_test.sql
@@ -3,6 +3,97 @@
SELECT create_table_with_encrypted();
SELECT seed_encrypted_json();
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- eql_v1_encrypted < eql_v1_encrypted with ore_cllw_var_8 index
+--
+-- Test data is in form '{"hello": "{one | two | three}", "n": {10 | 20 | 30} }'
+--
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ -- json n: 30
+ sv := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'2517068c0d1f9d4d41d2c666211f785e';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted >= eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' >= %L::eql_v1_encrypted', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted >= eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' >= %L::eql_v1_encrypted', term),
+ 3);
+
+ -- -- Check the $.hello path
+ -- -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_no_result(
+ format('eql_v1_encrypted >= eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' >= %L::eql_v1_encrypted', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- eql_v1_encrypted < eql_v1_encrypted with ore_cllw_var_8 index
+--
+-- Test data is in form '{"hello": "{one | two | three}", "n": {10 | 20 | 30} }'
+--
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ -- json n: 30
+ sv := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted >= eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' >= %L::eql_v1_encrypted', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted >= eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' >= %L::eql_v1_encrypted', term),
+ 3);
+
+ -- -- Check the $.hello path
+ -- -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_no_result(
+ format('eql_v1_encrypted >= eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' >= %L::eql_v1_encrypted', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
--
-- ORE - eql_v1_encrypted >= eql_v1_encrypted
--
@@ -12,32 +103,29 @@ DECLARE
ore_term jsonb;
BEGIN
- -- Create a record with HIGH ore
- e := create_encrypted_json()::jsonb || get_high_ore();
+ -- Record with a Numeric ORE term of 12
+ e := create_encrypted_ore_json(12);
PERFORM seed_encrypted(e);
- -- Default has LOW ore
- e := create_encrypted_json();
-
PERFORM assert_result(
'eql_v1_encrypted >= eql_v1_encrypted',
- format('SELECT e FROM encrypted WHERE e >= %L::eql_v1_encrypted', e));
+ format('SELECT e FROM encrypted WHERE e >= %L', e));
-
- for i in 1..3 loop
- e := create_encrypted_json(i);
-
- PERFORM assert_result(
- format('eql_v1_encrypted >= eql_v1_encrypted %s of 3', i),
- format('SELECT e FROM encrypted WHERE e >= %L;', e));
-
- PERFORM assert_count(
- format('eql_v1_encrypted >= eql_v1_encrypted %s of 3', i),
+ PERFORM assert_count(
+ format('eql_v1_encrypted >= eql_v1_encrypted'),
format('SELECT e FROM encrypted WHERE e >= %L;', e),
- 4);
- end loop;
+ 3);
+ e := create_encrypted_ore_json(20);
+
+ PERFORM assert_result(
+ 'eql_v1_encrypted >= eql_v1_encrypted',
+ format('SELECT e FROM encrypted WHERE e >= %L::eql_v1_encrypted', e));
+ PERFORM assert_count(
+ format('eql_v1_encrypted >= eql_v1_encrypted'),
+ format('SELECT e FROM encrypted WHERE e >= %L;', e),
+ 2);
END;
$$ LANGUAGE plpgsql;
@@ -50,13 +138,25 @@ DECLARE
e eql_v1_encrypted;
ore_term jsonb;
BEGIN
+ -- Reset data
+ PERFORM seed_encrypted_json();
- -- Create a record with HIGH ore
- e := create_encrypted_json()::jsonb || get_high_ore();
+ -- Record with a Numeric ORE term of 42
+ e := create_encrypted_ore_json(42);
PERFORM seed_encrypted(e);
- -- Default has LOW ore
- e := create_encrypted_json();
+ PERFORM assert_result(
+ 'eql_v1.gte(a eql_v1_encrypted, b eql_v1_encrypted)',
+ format('SELECT e FROM encrypted WHERE eql_v1.gte(e, %L)', e));
+
+ -- include
+ PERFORM assert_count(
+ 'eql_v1.gte(a eql_v1_encrypted, b eql_v1_encrypted)',
+ format('SELECT e FROM encrypted WHERE eql_v1.gte(e, %L)', e),
+ 1);
+
+ -- Record with a Numeric ORE term of 30
+ e := create_encrypted_ore_json(30);
PERFORM assert_result(
'eql_v1.get(a eql_v1_encrypted, b eql_v1_encrypted)',
@@ -65,7 +165,7 @@ DECLARE
PERFORM assert_count(
'eql_v1.get(a eql_v1_encrypted, b eql_v1_encrypted)',
format('SELECT e FROM encrypted WHERE eql_v1.gte(e, %L)', e),
- 5);
+ 2);
END;
$$ LANGUAGE plpgsql;
diff --git a/src/operators/>_test.sql b/src/operators/>_test.sql
index 89b6766..55f73f5 100644
--- a/src/operators/>_test.sql
+++ b/src/operators/>_test.sql
@@ -3,62 +3,153 @@
SELECT create_table_with_encrypted();
SELECT seed_encrypted_json();
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
--
--- ORE - eql_v1_encrypted > eql_v1_encrypted
+-- eql_v1_encrypted < eql_v1_encrypted with ore_cllw_u64_8 index
+--
+-- Test data is in form '{"hello": "{one | two | three}", "n": {10 | 20 | 30} }'
--
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+-- --
DO $$
DECLARE
- e eql_v1_encrypted;
- ore_term jsonb;
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
BEGIN
- -- Create a record with HIGH ore
- e := create_encrypted_json()::jsonb || get_high_ore();
- PERFORM seed_encrypted(e);
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ -- json n: 30
+ sv := get_numeric_ste_vec_20()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'2517068c0d1f9d4d41d2c666211f785e';
- -- Default has LOW ore
- e := create_encrypted_json();
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted > eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' > %L::eql_v1_encrypted', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted > eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' > %L::eql_v1_encrypted', term),
+ 1);
+
+ -- -- Check the $.hello path
+ -- -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_no_result(
+ format('eql_v1_encrypted > eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' > %L::eql_v1_encrypted', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- eql_v1_encrypted < eql_v1_encrypted with ore_cllw_var_8 index
+--
+-- Test data is in form '{"hello": "{one | two | three}", "n": {10 | 20 | 30} }'
+--
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ -- json n: 30
+ sv := get_numeric_ste_vec_30()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ -- -- -- -- $.n
PERFORM assert_result(
- 'eql_v1_encrypted > eql_v1_encrypted',
- format('SELECT e FROM encrypted WHERE e > %L::eql_v1_encrypted', e));
+ format('eql_v1_encrypted > eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' > %L::eql_v1_encrypted', term));
- for i in 1..3 loop
- e := create_encrypted_json(i);
+ PERFORM assert_count(
+ format('eql_v1_encrypted > eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''a7cea93975ed8c01f861ccb6bd082784'' > %L::eql_v1_encrypted', term),
+ 1);
- PERFORM assert_result(
- format('eql_v1_encrypted > eql_v1_encrypted %s of 3', i),
- format('SELECT e FROM encrypted WHERE e > %L;', e));
- end loop;
+ -- -- Check the $.hello path
+ -- -- Returned encrypted does not have ore_cllw_var_8
+ PERFORM assert_no_result(
+ format('eql_v1_encrypted > eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e->''2517068c0d1f9d4d41d2c666211f785e'' > %L::eql_v1_encrypted', term));
END;
$$ LANGUAGE plpgsql;
--
--- ORE - eql_v1.gt(a eql_v1_encrypted, b eql_v1_encrypted)
+-- ORE - eql_v1_encrypted > eql_v1_encrypted
--
DO $$
DECLARE
e eql_v1_encrypted;
- ore_term jsonb;
+ ore_term eql_v1_encrypted;
BEGIN
+ SELECT ore.e FROM ore WHERE id = 42 INTO ore_term;
+
+ PERFORM assert_count(
+ 'eql_v1_encrypted > eql_v1_encrypted',
+ format('SELECT id FROM ore WHERE e > %L ORDER BY e DESC', ore_term),
+ 57);
+
+ -- Record with a Numeric ORE term of 1
+ e := create_encrypted_ore_json(99);
+
+ PERFORM assert_no_result(
+ format('eql_v1_encrypted > eql_v1_encrypted'),
+ format('SELECT e FROM encrypted WHERE e > %L;', e));
+
+ -- Record with a Numeric ORE term of 42
+ e := create_encrypted_ore_json(17);
+
+ PERFORM assert_result(
+ 'eql_v1_encrypted > eql_v1_encrypted',
+ format('SELECT e FROM encrypted WHERE e > %L', e));
+
+ PERFORM assert_count(
+ 'eql_v1_encrypted > eql_v1_encrypted',
+ format('SELECT e FROM encrypted WHERE e > %L', e),
+ 2);
+ END;
+$$ LANGUAGE plpgsql;
- -- Create a record with HIGH ore
- e := create_encrypted_json()::jsonb || get_high_ore();
- PERFORM seed_encrypted(e);
- -- Default has LOW ore
- e := create_encrypted_json();
+-- --
+-- -- ORE - eql_v1.lt(a eql_v1_encrypted, b eql_v1_encrypted)
+-- --
+DO $$
+DECLARE
+ e eql_v1_encrypted;
+ ore_term jsonb;
+ BEGIN
+ -- Record with a Numeric ORE term of 42
+ e := create_encrypted_ore_json(21);
PERFORM assert_result(
- 'eql_v1.get(a eql_v1_encrypted, b eql_v1_encrypted)',
+ 'eql_v1.lt(a eql_v1_encrypted, b eql_v1_encrypted)',
format('SELECT e FROM encrypted WHERE eql_v1.gt(e, %L)', e));
PERFORM assert_count(
- 'eql_v1.get(a eql_v1_encrypted, b eql_v1_encrypted)',
+ 'eql_v1.lt(a eql_v1_encrypted, b eql_v1_encrypted)',
format('SELECT e FROM encrypted WHERE eql_v1.gt(e, %L)', e),
- 2);
+ 1);
END;
$$ LANGUAGE plpgsql;
diff --git a/src/operators/@>.sql b/src/operators/@>.sql
index 32932a5..daf540d 100644
--- a/src/operators/@>.sql
+++ b/src/operators/@>.sql
@@ -1,94 +1,18 @@
+-- REQUIRE: src/schema.sql
-- REQUIRE: src/encrypted/types.sql
--- REQUIRE: src/encrypted/functions.sql
+-- REQUIRE: src/ste_vec/functions.sql
-DROP OPERATOR IF EXISTS @> (eql_v1_encrypted, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1."@>"(e eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS @> (eql_v1_encrypted, eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1."@>"(e eql_v1_encrypted, b eql_v1_encrypted);
---
--- Returns the element that
---
CREATE FUNCTION eql_v1."@>"(a eql_v1_encrypted, b eql_v1_encrypted)
- RETURNS boolean
- IMMUTABLE STRICT PARALLEL SAFE
-AS $$
- DECLARE
- selector text;
- term text;
- BEGIN
- selector := b.data->>'s';
- term := b.data->>'t';
-
- IF selector IS NULL THEN
- RETURN false;
- END IF;
-
- IF term IS NULL THEN
- RETURN false;
- END IF;
-
- RETURN (
- SELECT exists (
- SELECT elem::eql_v1_encrypted
- FROM jsonb_array_elements(a.data->'j') AS elem
- WHERE elem->>'s' = selector AND
- elem->>'t' = term
- LIMIT 1
- )
- );
-
- END;
-$$ LANGUAGE plpgsql;
-
+RETURNS boolean AS $$
+ SELECT eql_v1.ste_vec_contains(a, b)
+$$ LANGUAGE SQL;
CREATE OPERATOR @>(
FUNCTION=eql_v1."@>",
LEFTARG=eql_v1_encrypted,
RIGHTARG=eql_v1_encrypted
);
-
-
-
-
--- -- Determine if a contains b (ignoring ciphertext values)
--- DROP FUNCTION IF EXISTS eql_v1.ste_vec_logical_contains(a eql_v1.ste_vec_index, b eql_v1.ste_vec_index);
-
--- CREATE FUNCTION eql_v1.ste_vec_logical_contains(a eql_v1.ste_vec_index, b eql_v1.ste_vec_index)
--- RETURNS boolean AS $$
--- DECLARE
--- result boolean;
--- intermediate_result boolean;
--- BEGIN
--- result := true;
--- IF array_length(b.entries, 1) IS NULL THEN
--- RETURN result;
--- END IF;
--- FOR i IN 1..array_length(b.entries, 1) LOOP
--- intermediate_result := eql_v1.ste_vec_entry_array_contains_entry(a.entries, b.entries[i]);
--- result := result AND intermediate_result;
--- END LOOP;
--- RETURN result;
--- END;
--- $$ LANGUAGE plpgsql;
-
--- -- Determine if a contains b (ignoring ciphertext values)
--- DROP FUNCTION IF EXISTS eql_v1.ste_vec_entry_array_contains_entry(a eql_v1.ste_vec_entry[], b eql_v1.ste_vec_entry);
-
--- CREATE FUNCTION eql_v1.ste_vec_entry_array_contains_entry(a eql_v1.ste_vec_entry[], b eql_v1.ste_vec_entry)
--- RETURNS boolean AS $$
--- DECLARE
--- result boolean;
--- intermediate_result boolean;
--- BEGIN
--- IF array_length(a, 1) IS NULL THEN
--- RETURN false;
--- END IF;
-
--- result := false;
--- FOR i IN 1..array_length(a, 1) LOOP
--- intermediate_result := a[i].tokenized_selector = b.tokenized_selector AND a[i].term = b.term;
--- result := result OR intermediate_result;
--- END LOOP;
--- RETURN result;
--- END;
--- $$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/src/operators/@>_test.sql b/src/operators/@>_test.sql
new file mode 100644
index 0000000..c3d6405
--- /dev/null
+++ b/src/operators/@>_test.sql
@@ -0,0 +1,94 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- eql_v1_encrypted contains itself
+--
+--
+DO $$
+ DECLARE
+ a eql_v1_encrypted;
+ b eql_v1_encrypted;
+ BEGIN
+
+ a := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ b := get_numeric_ste_vec_10()::eql_v1_encrypted;
+
+ ASSERT a @> b;
+ ASSERT b @> a;
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- eql_v1_encrypted contains a term
+--
+--
+DO $$
+ DECLARE
+ a eql_v1_encrypted;
+ b eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ a := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ b := get_numeric_ste_vec_10()::eql_v1_encrypted;
+
+ -- $.n
+ term := b->'2517068c0d1f9d4d41d2c666211f785e';
+
+ ASSERT a @> term;
+
+ ASSERT NOT term @> a;
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- ore_cllw_u64_8 equality
+--
+-- Test data is in form '{"hello": "{one | two | three}", "n": {10 | 20 | 30} }'
+--
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- This extracts the data associated with the field from the test eql_v1_encrypted
+ sv := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ -- extract the term at $.n returned as eql_v1_encrypted
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE e @> %L::eql_v1_encrypted', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE e @> %L::eql_v1_encrypted', term),
+ 1);
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+SELECT drop_table_with_encrypted();
\ No newline at end of file
diff --git a/src/operators/class.sql b/src/operators/class.sql
index 17a15e5..652bc57 100644
--- a/src/operators/class.sql
+++ b/src/operators/class.sql
@@ -11,10 +11,10 @@
-- DROP ORERATOR CLASS & FAMILY BEFORE FUNCTION
-DROP OPERATOR CLASS IF EXISTS eql_v1.encrypted_operator USING btree;
-DROP OPERATOR FAMILY IF EXISTS eql_v1.encrypted_operator USING btree;
+-- DROP OPERATOR CLASS IF EXISTS eql_v1.encrypted_operator USING btree;
+-- DROP OPERATOR FAMILY IF EXISTS eql_v1.encrypted_operator USING btree;
-DROP FUNCTION IF EXISTS eql_v1.compare(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.compare(a eql_v1_encrypted, b eql_v1_encrypted);
--
-- Comparison function for eql_v1_encrypted
diff --git a/src/operators/~~.sql b/src/operators/~~.sql
index 4e48406..59b4e20 100644
--- a/src/operators/~~.sql
+++ b/src/operators/~~.sql
@@ -1,3 +1,4 @@
+-- REQUIRE: src/schema.sql
-- REQUIRE: src/encrypted/types.sql
-- REQUIRE: src/match/types.sql
-- REQUIRE: src/match/functions.sql
@@ -12,7 +13,7 @@
--
-DROP FUNCTION IF EXISTS eql_v1.match(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.match(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1.match(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean AS $$
@@ -21,10 +22,10 @@ $$ LANGUAGE SQL;
-- DROP OPERATOR BEFORE FUNCTION
-DROP OPERATOR IF EXISTS ~~ (eql_v1_encrypted, eql_v1_encrypted);
-DROP OPERATOR IF EXISTS ~~* (eql_v1_encrypted, eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS ~~ (eql_v1_encrypted, eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS ~~* (eql_v1_encrypted, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1."~~"(a eql_v1_encrypted, b eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1."~~"(a eql_v1_encrypted, b eql_v1_encrypted);
CREATE FUNCTION eql_v1."~~"(a eql_v1_encrypted, b eql_v1_encrypted)
RETURNS boolean
@@ -55,10 +56,10 @@ CREATE OPERATOR ~~*(
MERGES
);
-DROP OPERATOR IF EXISTS ~~ (eql_v1_encrypted, jsonb);
-DROP OPERATOR IF EXISTS ~~* (eql_v1_encrypted, jsonb);
+-- DROP OPERATOR IF EXISTS ~~ (eql_v1_encrypted, jsonb);
+-- DROP OPERATOR IF EXISTS ~~* (eql_v1_encrypted, jsonb);
-DROP FUNCTION IF EXISTS eql_v1."~~"(a eql_v1_encrypted, b jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1."~~"(a eql_v1_encrypted, b jsonb);
CREATE FUNCTION eql_v1."~~"(a eql_v1_encrypted, b jsonb)
RETURNS boolean
@@ -90,10 +91,10 @@ CREATE OPERATOR ~~*(
);
-DROP OPERATOR IF EXISTS ~~ (jsonb, eql_v1_encrypted);
-DROP OPERATOR IF EXISTS ~~* (jsonb, eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS ~~ (jsonb, eql_v1_encrypted);
+-- DROP OPERATOR IF EXISTS ~~* (jsonb, eql_v1_encrypted);
-DROP FUNCTION IF EXISTS eql_v1."~~"(a jsonb, b eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1."~~"(a jsonb, b eql_v1_encrypted);
CREATE FUNCTION eql_v1."~~"(a jsonb, b eql_v1_encrypted)
RETURNS boolean
@@ -126,34 +127,3 @@ CREATE OPERATOR ~~*(
-- -----------------------------------------------------------------------------
-
-
-
-
--- DROP OPERATOR IF EXISTS ~~ (eql_v1.match_index, eql_v1.match_index);
--- DROP FUNCTION IF EXISTS eql_v1.encrypted_match(a eql_v1.match_index, b eql_v1.match_index);
-
--- CREATE FUNCTION eql_v1.encrypted_match(a eql_v1.match_index, b eql_v1.match_index)
--- RETURNS boolean AS $$
--- SELECT a @> b;
--- $$ LANGUAGE SQL;
-
--- CREATE OPERATOR ~~(
--- FUNCTION=eql_v1.encrypted_match,
--- LEFTARG=eql_v1.match_index,
--- RIGHTARG=eql_v1.match_index,
--- RESTRICT = eqsel,
--- JOIN = eqjoinsel,
--- HASHES,
--- MERGES
--- );
-
--- CREATE OPERATOR ~~*(
--- FUNCTION=eql_v1.encrypted_match,
--- LEFTARG=eql_v1.match_index,
--- RIGHTARG=eql_v1.match_index,
--- RESTRICT = eqsel,
--- JOIN = eqjoinsel,
--- HASHES,
--- MERGES
--- );
diff --git a/src/operators/~~_test.sql b/src/operators/~~_test.sql
index efc2d5a..48f1a35 100644
--- a/src/operators/~~_test.sql
+++ b/src/operators/~~_test.sql
@@ -25,7 +25,7 @@ DECLARE
end loop;
-- Partial match
- e := create_encrypted_json()::jsonb || '{"m": [10, 11]}';
+ e := create_encrypted_json('m')::jsonb || '{"m": [10, 11]}';
PERFORM assert_result(
'eql_v1_encrypted ~~ eql_v1_encrypted with partial match',
@@ -48,7 +48,7 @@ DECLARE
BEGIN
for i in 1..3 loop
- e := create_encrypted_json(i);
+ e := create_encrypted_json(i, 'm');
PERFORM assert_result(
format('eql_v1_encrypted ~~* eql_v1_encrypted %s of 3', i),
@@ -61,7 +61,7 @@ DECLARE
end loop;
-- Partial match
- e := create_encrypted_json()::jsonb || '{"m": [10, 11]}';
+ e := create_encrypted_json('m')::jsonb || '{"m": [10, 11]}';
PERFORM assert_result(
'eql_v1_encrypted ~~* eql_v1_encrypted with partial match',
@@ -84,7 +84,7 @@ DECLARE
BEGIN
for i in 1..3 loop
- e := create_encrypted_json(i);
+ e := create_encrypted_json(i, 'm');
PERFORM assert_result(
format('eql_v1.match(eql_v1_encrypted, eql_v1_encrypted)', i),
@@ -93,7 +93,7 @@ DECLARE
end loop;
-- Partial match
- e := create_encrypted_json()::jsonb || '{"m": [10, 11]}';
+ e := create_encrypted_json('m')::jsonb || '{"m": [10, 11]}';
PERFORM assert_result(
'eql_v1.match(eql_v1_encrypted, eql_v1_encrypted)',
diff --git a/src/ore-cllw/operators.sql b/src/ore-cllw/operators.sql
deleted file mode 100644
index e69de29..0000000
diff --git a/src/ore-cllw/types.sql b/src/ore-cllw/types.sql
deleted file mode 100644
index d8e449c..0000000
--- a/src/ore-cllw/types.sql
+++ /dev/null
@@ -1 +0,0 @@
--- REQUIRE: src/schema.sql
diff --git a/src/ore/casts.sql b/src/ore/casts.sql
index 1c80dc5..82465cc 100644
--- a/src/ore/casts.sql
+++ b/src/ore/casts.sql
@@ -2,7 +2,7 @@
-- REQUIRE: src/ore/types.sql
-- casts text to ore_64_8_v1_term (bytea)
-DROP FUNCTION IF EXISTS eql_v1.text_to_ore_64_8_v1_term(t text);
+-- DROP FUNCTION IF EXISTS eql_v1.text_to_ore_64_8_v1_term(t text);
CREATE FUNCTION eql_v1.text_to_ore_64_8_v1_term(t text)
RETURNS eql_v1.ore_64_8_v1_term
@@ -12,7 +12,7 @@ BEGIN ATOMIC
END;
-- cast to cleanup ore_64_8_v1 extraction
-DROP CAST IF EXISTS (text AS eql_v1.ore_64_8_v1_term);
+-- DROP CAST IF EXISTS (text AS eql_v1.ore_64_8_v1_term);
CREATE CAST (text AS eql_v1.ore_64_8_v1_term)
WITH FUNCTION eql_v1.text_to_ore_64_8_v1_term(text) AS IMPLICIT;
diff --git a/src/ore/functions.sql b/src/ore/functions.sql
index 899a6e1..79afb91 100644
--- a/src/ore/functions.sql
+++ b/src/ore/functions.sql
@@ -4,32 +4,52 @@
-- REQUIRE: src/ore/types.sql
-DROP FUNCTION IF EXISTS eql_v1.jsonb_array_to_ore_64_8_v1(val jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.jsonb_array_to_ore_64_8_v1(val jsonb);
-- Casts a jsonb array of hex-encoded strings to the `ore_64_8_v1` composite type.
-- In other words, this function takes the ORE index format sent through in the
-- EQL payload from Proxy and decodes it as the composite type that we use for
-- ORE operations on the Postgres side.
+-- CREATE FUNCTION eql_v1.jsonb_array_to_ore_64_8_v1(val jsonb)
+-- RETURNS eql_v1.ore_64_8_v1 AS $$
+-- DECLARE
+-- terms_arr eql_v1.ore_64_8_v1_term[];
+-- BEGIN
+-- IF jsonb_typeof(val) = 'null' THEN
+-- RETURN NULL;
+-- END IF;
+
+-- SELECT array_agg(ROW(decode(value::text, 'hex'))::eql_v1.ore_64_8_v1_term)
+-- INTO terms_arr
+-- FROM jsonb_array_elements_text(val) AS value;
+
+-- PERFORM eql_v1.log('terms', terms_arr::text);
+
+-- RETURN ROW(terms_arr)::eql_v1.ore_64_8_v1;
+-- END;
+-- $$ LANGUAGE plpgsql;
+
+
CREATE FUNCTION eql_v1.jsonb_array_to_ore_64_8_v1(val jsonb)
RETURNS eql_v1.ore_64_8_v1 AS $$
DECLARE
- terms_arr eql_v1.ore_64_8_v1_term[];
+ terms eql_v1.ore_64_8_v1_term[];
BEGIN
IF jsonb_typeof(val) = 'null' THEN
RETURN NULL;
END IF;
- SELECT array_agg(ROW(decode(value::text, 'hex'))::eql_v1.ore_64_8_v1_term)
- INTO terms_arr
- FROM jsonb_array_elements_text(val) AS value;
+ SELECT array_agg(ROW(b)::eql_v1.ore_64_8_v1_term)
+ INTO terms
+ FROM unnest(eql_v1.jsonb_array_to_bytea_array(val)) AS b;
- RETURN ROW(terms_arr)::eql_v1.ore_64_8_v1;
+ RETURN ROW(terms)::eql_v1.ore_64_8_v1;
END;
$$ LANGUAGE plpgsql;
-- extracts ore index from jsonb
-DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1(val jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1(val jsonb);
CREATE FUNCTION eql_v1.ore_64_8_v1(val jsonb)
RETURNS eql_v1.ore_64_8_v1
@@ -45,7 +65,7 @@ $$ LANGUAGE plpgsql;
-- extracts ore index from an encrypted column
-DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1(val eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1(val eql_v1_encrypted);
CREATE FUNCTION eql_v1.ore_64_8_v1(val eql_v1_encrypted)
RETURNS eql_v1.ore_64_8_v1
@@ -58,7 +78,7 @@ $$ LANGUAGE plpgsql;
-- This function uses lexicographic comparison
-DROP FUNCTION IF EXISTS eql_v1.compare_ore_64_8_v1(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
+-- DROP FUNCTION IF EXISTS eql_v1.compare_ore_64_8_v1(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
CREATE FUNCTION eql_v1.compare_ore_64_8_v1(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1)
RETURNS integer AS $$
@@ -69,7 +89,7 @@ RETURNS integer AS $$
$$ LANGUAGE plpgsql;
-DROP FUNCTION IF EXISTS eql_v1.compare_ore_64_8_v1_term(a eql_v1.ore_64_8_v1_term, b eql_v1.ore_64_8_v1_term);
+-- DROP FUNCTION IF EXISTS eql_v1.compare_ore_64_8_v1_term(a eql_v1.ore_64_8_v1_term, b eql_v1.ore_64_8_v1_term);
CREATE FUNCTION eql_v1.compare_ore_64_8_v1_term(a eql_v1.ore_64_8_v1_term, b eql_v1.ore_64_8_v1_term)
RETURNS integer
@@ -157,7 +177,7 @@ $$ LANGUAGE plpgsql;
-- doesn't always make sense but it's here for completeness.
-- If both are non-empty, we compare the first element. If they are equal
-- we need to consider the next block so we recurse, otherwise we return the comparison result.
-DROP FUNCTION IF EXISTS eql_v1.compare_ore_array(a eql_v1.ore_64_8_v1_term[], b eql_v1.ore_64_8_v1_term[]);
+-- DROP FUNCTION IF EXISTS eql_v1.compare_ore_array(a eql_v1.ore_64_8_v1_term[], b eql_v1.ore_64_8_v1_term[]);
CREATE FUNCTION eql_v1.compare_ore_array(a eql_v1.ore_64_8_v1_term[], b eql_v1.ore_64_8_v1_term[])
RETURNS integer AS $$
diff --git a/src/ore/operators.sql b/src/ore/operators.sql
index 99772e1..7c249a3 100644
--- a/src/ore/operators.sql
+++ b/src/ore/operators.sql
@@ -4,7 +4,7 @@
-- REQUIRE: src/ore/functions.sql
-DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1_eq(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
+-- DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1_eq(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
CREATE FUNCTION eql_v1.ore_64_8_v1_eq(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1)
RETURNS boolean AS $$
@@ -12,7 +12,7 @@ RETURNS boolean AS $$
$$ LANGUAGE SQL;
-DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1_neq(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
+-- DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1_neq(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
CREATE FUNCTION eql_v1.ore_64_8_v1_neq(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1)
RETURNS boolean AS $$
@@ -20,7 +20,7 @@ RETURNS boolean AS $$
$$ LANGUAGE SQL;
-DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1_lt(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
+-- DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1_lt(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
CREATE FUNCTION eql_v1.ore_64_8_v1_lt(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1)
RETURNS boolean AS $$
@@ -28,7 +28,7 @@ RETURNS boolean AS $$
$$ LANGUAGE SQL;
-DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1_lte(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
+-- DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1_lte(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
CREATE FUNCTION eql_v1.ore_64_8_v1_lte(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1)
RETURNS boolean AS $$
@@ -36,7 +36,7 @@ RETURNS boolean AS $$
$$ LANGUAGE SQL;
-DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1_gt(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
+-- DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1_gt(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
CREATE FUNCTION eql_v1.ore_64_8_v1_gt(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1)
RETURNS boolean AS $$
@@ -44,7 +44,7 @@ RETURNS boolean AS $$
$$ LANGUAGE SQL;
-DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1_gte(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
+-- DROP FUNCTION IF EXISTS eql_v1.ore_64_8_v1_gte(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1);
CREATE FUNCTION eql_v1.ore_64_8_v1_gte(a eql_v1.ore_64_8_v1, b eql_v1.ore_64_8_v1)
RETURNS boolean AS $$
@@ -52,7 +52,7 @@ RETURNS boolean AS $$
$$ LANGUAGE SQL;
-DROP OPERATOR IF EXISTS = (eql_v1.ore_64_8_v1, eql_v1.ore_64_8_v1);
+-- DROP OPERATOR IF EXISTS = (eql_v1.ore_64_8_v1, eql_v1.ore_64_8_v1);
CREATE OPERATOR = (
FUNCTION=eql_v1.ore_64_8_v1_eq,
@@ -66,7 +66,7 @@ CREATE OPERATOR = (
);
-DROP OPERATOR IF EXISTS <> (eql_v1.ore_64_8_v1, eql_v1.ore_64_8_v1);
+-- DROP OPERATOR IF EXISTS <> (eql_v1.ore_64_8_v1, eql_v1.ore_64_8_v1);
CREATE OPERATOR <> (
FUNCTION=eql_v1.ore_64_8_v1_neq,
@@ -79,7 +79,7 @@ CREATE OPERATOR <> (
MERGES
);
-DROP OPERATOR IF EXISTS > (eql_v1.ore_64_8_v1, eql_v1.ore_64_8_v1);
+-- DROP OPERATOR IF EXISTS > (eql_v1.ore_64_8_v1, eql_v1.ore_64_8_v1);
CREATE OPERATOR > (
FUNCTION=eql_v1.ore_64_8_v1_gt,
@@ -92,7 +92,7 @@ CREATE OPERATOR > (
);
-DROP OPERATOR IF EXISTS < (eql_v1.ore_64_8_v1, eql_v1.ore_64_8_v1);
+-- DROP OPERATOR IF EXISTS < (eql_v1.ore_64_8_v1, eql_v1.ore_64_8_v1);
CREATE OPERATOR < (
FUNCTION=eql_v1.ore_64_8_v1_lt,
@@ -105,7 +105,7 @@ CREATE OPERATOR < (
);
-DROP OPERATOR IF EXISTS <= (eql_v1.ore_64_8_v1, eql_v1.ore_64_8_v1);
+-- DROP OPERATOR IF EXISTS <= (eql_v1.ore_64_8_v1, eql_v1.ore_64_8_v1);
CREATE OPERATOR <= (
FUNCTION=eql_v1.ore_64_8_v1_lte,
@@ -118,7 +118,7 @@ CREATE OPERATOR <= (
);
-DROP OPERATOR IF EXISTS >= (eql_v1.ore_64_8_v1, eql_v1.ore_64_8_v1);
+-- DROP OPERATOR IF EXISTS >= (eql_v1.ore_64_8_v1, eql_v1.ore_64_8_v1);
CREATE OPERATOR >= (
FUNCTION=eql_v1.ore_64_8_v1_gte,
@@ -131,12 +131,12 @@ CREATE OPERATOR >= (
);
-DROP OPERATOR FAMILY IF EXISTS eql_v1.ore_64_8_v1_btree_ops USING btree;
+-- DROP OPERATOR FAMILY IF EXISTS eql_v1.ore_64_8_v1_btree_ops USING btree;
CREATE OPERATOR FAMILY eql_v1.ore_64_8_v1_btree_ops USING btree;
-DROP OPERATOR CLASS IF EXISTS eql_v1.ore_64_8_v1_btree_ops USING btree;
+-- DROP OPERATOR CLASS IF EXISTS eql_v1.ore_64_8_v1_btree_ops USING btree;
CREATE OPERATOR CLASS eql_v1.ore_64_8_v1_btree_ops DEFAULT FOR TYPE eql_v1.ore_64_8_v1 USING btree FAMILY eql_v1.ore_64_8_v1_btree_ops AS
OPERATOR 1 <,
diff --git a/src/ore/types.sql b/src/ore/types.sql
index cb86d09..eba6ea9 100644
--- a/src/ore/types.sql
+++ b/src/ore/types.sql
@@ -1,12 +1,12 @@
-- REQUIRE: src/schema.sql
-DROP TYPE IF EXISTS eql_v1.ore_64_8_v1_term;
+-- DROP TYPE IF EXISTS eql_v1.ore_64_8_v1_term;
CREATE TYPE eql_v1.ore_64_8_v1_term AS (
bytes bytea
);
-DROP TYPE IF EXISTS eql_v1.ore_64_8_v1;
+-- DROP TYPE IF EXISTS eql_v1.ore_64_8_v1;
CREATE TYPE eql_v1.ore_64_8_v1 AS (
terms eql_v1.ore_64_8_v1_term[]
diff --git a/src/ore_cllw_u64_8/class.sql b/src/ore_cllw_u64_8/class.sql
new file mode 100644
index 0000000..f1f8b39
--- /dev/null
+++ b/src/ore_cllw_u64_8/class.sql
@@ -0,0 +1,19 @@
+-- REQUIRE: src/schema.sql
+-- REQUIRE: src/ore_cllw_u64_8/types.sql
+-- REQUIRE: src/ore_cllw_u64_8/functions.sql
+-- REQUIRE: src/ore_cllw_u64_8/operators.sql
+
+
+-- DROP OPERATOR FAMILY IF EXISTS eql_v1.ore_cllw_u64_8_btree_ops USING btree;
+
+CREATE OPERATOR FAMILY eql_v1.ore_cllw_u64_8_btree_ops USING btree;
+
+-- DROP OPERATOR CLASS IF EXISTS eql_v1.ore_cllw_u64_8_btree_ops USING btree;
+
+CREATE OPERATOR CLASS eql_v1.ore_cllw_u64_8_btree_ops DEFAULT FOR TYPE eql_v1.ore_cllw_u64_8 USING btree FAMILY eql_v1.ore_cllw_u64_8_btree_ops AS
+ OPERATOR 1 <,
+ OPERATOR 2 <=,
+ OPERATOR 3 =,
+ OPERATOR 4 >=,
+ OPERATOR 5 >,
+ FUNCTION 1 eql_v1.compare_ore_cllw_u64_8(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8);
diff --git a/src/ore_cllw_u64_8/functions.sql b/src/ore_cllw_u64_8/functions.sql
new file mode 100644
index 0000000..706c754
--- /dev/null
+++ b/src/ore_cllw_u64_8/functions.sql
@@ -0,0 +1,114 @@
+-- REQUIRE: src/schema.sql
+-- REQUIRE: src/common.sql
+-- REQUIRE: src/ore_cllw_u64_8/types.sql
+
+
+
+-- extracts ste_vec index from a jsonb value
+-- DROP FUNCTION IF EXISTS eql_v1.ste_vec(val jsonb);
+
+-- extracts ore_cllw_u64_8 index from a jsonb value
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_u64_8(val jsonb);
+
+CREATE FUNCTION eql_v1.ore_cllw_u64_8(val jsonb)
+ RETURNS eql_v1.ore_cllw_u64_8
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+
+ IF NOT (val ? 'ocf') THEN
+ RAISE 'Expected a ore_cllw_u64_8 index (ocf) value in json: %', val;
+ END IF;
+
+ IF val->>'ocf' IS NULL THEN
+ RETURN NULL;
+ END IF;
+
+ RETURN ROW(decode(val->>'ocf', 'hex'));
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- extracts ore_cllw_u64_8 index from an eql_v1_encrypted value
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_u64_8(val eql_v1_encrypted);
+
+CREATE FUNCTION eql_v1.ore_cllw_u64_8(val eql_v1_encrypted)
+ RETURNS eql_v1.ore_cllw_u64_8
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN (SELECT eql_v1.ore_cllw_u64_8(val.data));
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+--
+-- Compare ore cllw bytes
+-- Used by both fixed and variable ore cllw variants
+--
+
+-- DROP FUNCTION IF EXISTS eql_v1.__compare_inner_ore_cllw_u64_8(a bytea, b bytea);
+-- DROP FUNCTION IF EXISTS eql_v1.compare_ore_cllw(a bytea, b bytea);
+CREATE FUNCTION eql_v1.compare_ore_cllw(a bytea, b bytea)
+RETURNS int AS $$
+DECLARE
+ len_a INT;
+ x BYTEA;
+ y BYTEA;
+ i INT;
+ differing RECORD;
+BEGIN
+ len_a := LENGTH(a);
+
+ -- Iterate over each byte and compare them
+ FOR i IN 1..len_a LOOP
+ x := SUBSTRING(a FROM i FOR 1);
+ y := SUBSTRING(b FROM i FOR 1);
+
+ -- Check if there's a difference
+ IF x != y THEN
+ differing := (x, y);
+ EXIT;
+ END IF;
+ END LOOP;
+
+ -- If a difference is found, compare the bytes as in Rust logic
+ IF differing IS NOT NULL THEN
+ IF (get_byte(y, 0) + 1) % 256 = get_byte(x, 0) THEN
+ RETURN 1;
+ ELSE
+ RETURN -1;
+ END IF;
+ ELSE
+ RETURN 0;
+ END IF;
+END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.compare_ore_cllw_u64_8(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8);
+
+CREATE FUNCTION eql_v1.compare_ore_cllw_u64_8(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8)
+RETURNS int AS $$
+DECLARE
+ len_a INT;
+ len_b INT;
+BEGIN
+ IF a IS NULL OR b IS NULL THEN
+ RETURN NULL;
+ END IF;
+
+ -- Check if the lengths of the two bytea arguments are the same
+ len_a := LENGTH(a.bytes);
+ len_b := LENGTH(b.bytes);
+
+ IF len_a != len_b THEN
+ RAISE EXCEPTION 'ore_cllw_u64_8 index terms are not the same length';
+ END IF;
+
+ RETURN eql_v1.compare_ore_cllw(a.bytes, b.bytes);
+END;
+$$ LANGUAGE plpgsql;
+
diff --git a/src/ore_cllw_u64_8/operators.sql b/src/ore_cllw_u64_8/operators.sql
new file mode 100644
index 0000000..e4c6cce
--- /dev/null
+++ b/src/ore_cllw_u64_8/operators.sql
@@ -0,0 +1,141 @@
+-- REQUIRE: src/schema.sql
+-- REQUIRE: src/common.sql
+-- REQUIRE: src/ore_cllw_u64_8/types.sql
+-- REQUIRE: src/ore_cllw_u64_8/functions.sql
+
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_u64_8_eq(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8);
+
+CREATE FUNCTION eql_v1.ore_cllw_u64_8_eq(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8)
+RETURNS boolean AS $$
+ SELECT eql_v1.bytea_eq(a.bytes, b.bytes)
+$$ LANGUAGE SQL;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_u64_8_neq(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8);
+
+CREATE FUNCTION eql_v1.ore_cllw_u64_8_neq(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8)
+RETURNS boolean AS $$
+ SELECT NOT eql_v1.bytea_eq(a.bytes, b.bytes)
+$$ LANGUAGE SQL;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_u64_8_lt(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8);
+
+CREATE FUNCTION eql_v1.ore_cllw_u64_8_lt(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8)
+RETURNS boolean
+AS $$
+ BEGIN
+ RETURN eql_v1.compare_ore_cllw_u64_8(a, b) = -1;
+ END
+$$ LANGUAGE plpgsql;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_u64_8_lte(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8);
+
+CREATE FUNCTION eql_v1.ore_cllw_u64_8_lte(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8)
+RETURNS boolean AS $$
+ SELECT eql_v1.compare_ore_cllw_u64_8(a, b) != 1
+$$ LANGUAGE SQL;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_u64_8_gt(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8);
+
+CREATE FUNCTION eql_v1.ore_cllw_u64_8_gt(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8)
+RETURNS boolean AS $$
+ SELECT eql_v1.compare_ore_cllw_u64_8(a, b) = 1
+$$ LANGUAGE SQL;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_u64_8_gte(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8);
+
+CREATE FUNCTION eql_v1.ore_cllw_u64_8_gte(a eql_v1.ore_cllw_u64_8, b eql_v1.ore_cllw_u64_8)
+RETURNS boolean AS $$
+ SELECT eql_v1.compare_ore_cllw_u64_8(a, b) != -1
+$$ LANGUAGE SQL;
+
+
+-- DROP OPERATOR IF EXISTS = (eql_v1.ore_cllw_u64_8, eql_v1.ore_cllw_u64_8);
+
+CREATE OPERATOR = (
+ FUNCTION=eql_v1.ore_cllw_u64_8_eq,
+ LEFTARG=eql_v1.ore_cllw_u64_8,
+ RIGHTARG=eql_v1.ore_cllw_u64_8,
+ NEGATOR = <>,
+ RESTRICT = eqsel,
+ JOIN = eqjoinsel,
+ HASHES,
+ MERGES
+);
+
+
+-- DROP OPERATOR IF EXISTS <> (eql_v1.ore_cllw_u64_8, eql_v1.ore_cllw_u64_8);
+
+CREATE OPERATOR <> (
+ FUNCTION=eql_v1.ore_cllw_u64_8_neq,
+ LEFTARG=eql_v1.ore_cllw_u64_8,
+ RIGHTARG=eql_v1.ore_cllw_u64_8,
+ NEGATOR = =,
+ RESTRICT = eqsel,
+ JOIN = eqjoinsel,
+ HASHES,
+ MERGES
+);
+
+
+-- DROP OPERATOR IF EXISTS > (eql_v1.ore_cllw_u64_8, eql_v1.ore_cllw_u64_8);
+
+CREATE OPERATOR > (
+ FUNCTION=eql_v1.ore_cllw_u64_8_gt,
+ LEFTARG=eql_v1.ore_cllw_u64_8,
+ RIGHTARG=eql_v1.ore_cllw_u64_8,
+ NEGATOR = <=,
+ RESTRICT = scalarltsel,
+ JOIN = scalarltjoinsel,
+ HASHES,
+ MERGES
+);
+
+
+-- DROP OPERATOR IF EXISTS < (eql_v1.ore_cllw_u64_8, eql_v1.ore_cllw_u64_8);
+
+CREATE OPERATOR < (
+ FUNCTION=eql_v1.ore_cllw_u64_8_lt,
+ LEFTARG=eql_v1.ore_cllw_u64_8,
+ RIGHTARG=eql_v1.ore_cllw_u64_8,
+ NEGATOR = >=,
+ RESTRICT = scalargtsel,
+ JOIN = scalargtjoinsel,
+ HASHES,
+ MERGES
+);
+
+
+-- DROP OPERATOR IF EXISTS >= (eql_v1.ore_cllw_u64_8, eql_v1.ore_cllw_u64_8);
+
+CREATE OPERATOR >= (
+ FUNCTION=eql_v1.ore_cllw_u64_8_gte,
+ LEFTARG=eql_v1.ore_cllw_u64_8,
+ RIGHTARG=eql_v1.ore_cllw_u64_8,
+ NEGATOR = <,
+ RESTRICT = scalarltsel,
+ JOIN = scalarltjoinsel,
+ HASHES,
+ MERGES
+);
+
+
+-- DROP OPERATOR IF EXISTS <= (eql_v1.ore_cllw_u64_8, eql_v1.ore_cllw_u64_8);
+
+CREATE OPERATOR <= (
+ FUNCTION=eql_v1.ore_cllw_u64_8_lte,
+ LEFTARG=eql_v1.ore_cllw_u64_8,
+ RIGHTARG=eql_v1.ore_cllw_u64_8,
+ NEGATOR = >,
+ RESTRICT = scalargtsel,
+ JOIN = scalargtjoinsel,
+ HASHES,
+ MERGES
+);
+
+
+
diff --git a/src/ore_cllw_u64_8/operators_test.sql b/src/ore_cllw_u64_8/operators_test.sql
new file mode 100644
index 0000000..9bc130e
--- /dev/null
+++ b/src/ore_cllw_u64_8/operators_test.sql
@@ -0,0 +1,234 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- ore_cllw_u64_8 < ore_cllw_u64_8
+--
+-- Test data is '{"hello": "world", "n": 42}'
+
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- json n: 20
+ sv := get_numeric_ste_vec_20()::eql_v1_encrypted;
+ -- extract the term at $.n
+ term := sv->'2517068c0d1f9d4d41d2c666211f785e';
+
+ PERFORM eql_v1.log('term', term::text);
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted < eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''2517068c0d1f9d4d41d2c666211f785e'') < eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted < eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''2517068c0d1f9d4d41d2c666211f785e'') < eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term),
+ 1);
+
+ -- Check the $.hello path
+ -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_exception(
+ format('eql_v1_encrypted < eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''a7cea93975ed8c01f861ccb6bd082784'') < eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- ore_cllw_u64_8 <= ore_cllw_u64_8
+--
+-- Test data is '{"hello": "world", "n": 42}'
+
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- json n: 20
+ sv := get_numeric_ste_vec_20()::eql_v1_encrypted;
+
+ -- extract the term at $.n
+ term := sv->'2517068c0d1f9d4d41d2c666211f785e';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted <= eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''2517068c0d1f9d4d41d2c666211f785e'') <= eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted <= eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''2517068c0d1f9d4d41d2c666211f785e'') <= eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term),
+ 2);
+
+ -- Check the $.hello path
+ -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_exception(
+ format('eql_v1_encrypted <= eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''a7cea93975ed8c01f861ccb6bd082784'') <= eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- ore_cllw_u64_8 >= ore_cllw_u64_8
+--
+-- Test data is '{"hello": "world", "n": 42}'
+
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- json n: 30
+ sv := get_numeric_ste_vec_30()::eql_v1_encrypted;
+
+ -- extract the term at $.n
+ term := sv->'2517068c0d1f9d4d41d2c666211f785e';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted >= eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''2517068c0d1f9d4d41d2c666211f785e'') >= eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted >= eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''2517068c0d1f9d4d41d2c666211f785e'') >= eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term),
+ 1);
+
+ -- Check the $ path
+ -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_exception(
+ format('eql_v1_encrypted >= eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''bca213de9ccce676fa849ff9c4807963'') >= eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- ore_cllw_u64_8 > ore_cllw_u64_8
+--
+-- Test data is '{"hello": "world", "n": 42}'
+
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- json n: 20
+ sv := get_numeric_ste_vec_20()::eql_v1_encrypted;
+
+ -- extract the term at $.n
+ term := sv->'2517068c0d1f9d4d41d2c666211f785e';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted > eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''2517068c0d1f9d4d41d2c666211f785e'') > eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted > eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''2517068c0d1f9d4d41d2c666211f785e'') > eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term),
+ 1);
+
+ -- Check the $ path
+ -- Returned encrypted does not have ore_cllw_u64_8
+ PERFORM assert_exception(
+ format('eql_v1_encrypted > eql_v1_encrypted with ore index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''bca213de9ccce676fa849ff9c4807963'') > eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+
+-- -- ------------------------------------------------------------------------
+-- -- ------------------------------------------------------------------------
+-- --
+-- -- ore_cllw_u64_8 = ore_cllw_u64_8
+-- --
+-- -- Test data is '{"hello": "world", "n": 42}'
+
+-- -- Paths
+-- -- $ -> bca213de9ccce676fa849ff9c4807963
+-- -- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- -- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+-- --
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- json n: 20
+ sv := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ -- extract the term at $.n
+ term := sv->'2517068c0d1f9d4d41d2c666211f785e';
+
+ PERFORM assert_result(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''2517068c0d1f9d4d41d2c666211f785e'') = eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''2517068c0d1f9d4d41d2c666211f785e'') = eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term),
+ 1);
+
+ -- Check the $.n path
+ -- Returned encrypted does not have ore_cllw_u64_8 and raises exception
+ PERFORM assert_exception(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore_cllw_u64_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_u64_8(e->''a7cea93975ed8c01f861ccb6bd082784'') = eql_v1.ore_cllw_u64_8(%L::eql_v1_encrypted)', term));
+
+ END;
+$$ LANGUAGE plpgsql;
diff --git a/src/ore_cllw_u64_8/types.sql b/src/ore_cllw_u64_8/types.sql
new file mode 100644
index 0000000..01f600c
--- /dev/null
+++ b/src/ore_cllw_u64_8/types.sql
@@ -0,0 +1,7 @@
+-- REQUIRE: src/schema.sql
+
+-- Represents a ciphertext encrypted with the CLLW ORE scheme for a fixed output size
+-- Each output block is 8-bits
+CREATE TYPE eql_v1.ore_cllw_u64_8 AS (
+ bytes bytea
+);
diff --git a/src/ore_cllw_var_8/class.sql b/src/ore_cllw_var_8/class.sql
new file mode 100644
index 0000000..3f9965a
--- /dev/null
+++ b/src/ore_cllw_var_8/class.sql
@@ -0,0 +1,19 @@
+-- REQUIRE: src/schema.sql
+-- REQUIRE: src/ore_cllw_var_8/types.sql
+-- REQUIRE: src/ore_cllw_var_8/functions.sql
+-- REQUIRE: src/ore_cllw_var_8/operators.sql
+
+
+-- DROP OPERATOR FAMILY IF EXISTS eql_v1.ore_cllw_var_8_variable_btree_ops USING btree;
+
+CREATE OPERATOR FAMILY eql_v1.ore_cllw_var_8_variable_btree_ops USING btree;
+
+-- DROP OPERATOR CLASS IF EXISTS eql_v1.ore_cllw_var_8_variable_btree_ops USING btree;
+
+CREATE OPERATOR CLASS eql_v1.ore_cllw_var_8_variable_btree_ops DEFAULT FOR TYPE eql_v1.ore_cllw_var_8 USING btree FAMILY eql_v1.ore_cllw_var_8_variable_btree_ops AS
+ OPERATOR 1 <,
+ OPERATOR 2 <=,
+ OPERATOR 3 =,
+ OPERATOR 4 >=,
+ OPERATOR 5 >,
+ FUNCTION 1 eql_v1.compare_ore_cllw_var_8(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8);
diff --git a/src/ore_cllw_var_8/functions.sql b/src/ore_cllw_var_8/functions.sql
new file mode 100644
index 0000000..8cf61de
--- /dev/null
+++ b/src/ore_cllw_var_8/functions.sql
@@ -0,0 +1,100 @@
+-- REQUIRE: src/schema.sql
+-- REQUIRE: src/common.sql
+-- REQUIRE: src/ore_cllw_var_8/types.sql
+-- REQUIRE: src/ore_cllw_u64_8/functions.sql
+
+
+
+-- extracts ore_cllw_var_8 index from a jsonb value
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_var_8(val jsonb);
+
+CREATE FUNCTION eql_v1.ore_cllw_var_8(val jsonb)
+ RETURNS eql_v1.ore_cllw_var_8
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+
+ IF NOT (val ? 'ocv') THEN
+ RAISE 'Expected a ore_cllw_var_8 index (ocv) value in json: %', val;
+ END IF;
+
+ IF val->>'ocv' IS NULL THEN
+ RETURN NULL;
+ END IF;
+
+ RETURN ROW(decode(val->>'ocv', 'hex'));
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- extracts ore_cllw_var_8 index from an eql_v1_encrypted value
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_var_8(val eql_v1_encrypted);
+
+CREATE FUNCTION eql_v1.ore_cllw_var_8(val eql_v1_encrypted)
+ RETURNS eql_v1.ore_cllw_var_8
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN (SELECT eql_v1.ore_cllw_var_8(val.data));
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.compare_ore_cllw_var_8(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8);
+
+CREATE FUNCTION eql_v1.compare_ore_cllw_var_8(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8)
+RETURNS int AS $$
+DECLARE
+ len_a INT;
+ len_b INT;
+ -- length of the common part of the two bytea values
+ common_len INT;
+ cmp_result INT;
+BEGIN
+ IF a IS NULL OR b IS NULL THEN
+ RETURN NULL;
+ END IF;
+
+ -- Get the lengths of both bytea inputs
+ len_a := LENGTH(a.bytes);
+ len_b := LENGTH(b.bytes);
+
+ -- Handle empty cases
+ IF len_a = 0 AND len_b = 0 THEN
+ RETURN 0;
+ ELSIF len_a = 0 THEN
+ RETURN -1;
+ ELSIF len_b = 0 THEN
+ RETURN 1;
+ END IF;
+
+ -- Find the length of the shorter bytea
+ IF len_a < len_b THEN
+ common_len := len_a;
+ ELSE
+ common_len := len_b;
+ END IF;
+
+ -- Use the compare_bytea function to compare byte by byte
+ cmp_result := eql_v1.compare_ore_cllw(
+ SUBSTRING(a.bytes FROM 1 FOR common_len),
+ SUBSTRING(b.bytes FROM 1 FOR common_len)
+ );
+
+ -- If the comparison returns 'less' or 'greater', return that result
+ IF cmp_result = -1 THEN
+ RETURN -1;
+ ELSIF cmp_result = 1 THEN
+ RETURN 1;
+ END IF;
+
+ -- If the bytea comparison is 'equal', compare lengths
+ IF len_a < len_b THEN
+ RETURN -1;
+ ELSIF len_a > len_b THEN
+ RETURN 1;
+ ELSE
+ RETURN 0;
+ END IF;
+END;
+$$ LANGUAGE plpgsql;
diff --git a/src/ore-cllw/functions.sql b/src/ore_cllw_var_8/functions_test.sql
similarity index 100%
rename from src/ore-cllw/functions.sql
rename to src/ore_cllw_var_8/functions_test.sql
diff --git a/src/ore_cllw_var_8/operators.sql b/src/ore_cllw_var_8/operators.sql
new file mode 100644
index 0000000..584a76d
--- /dev/null
+++ b/src/ore_cllw_var_8/operators.sql
@@ -0,0 +1,127 @@
+-- REQUIRE: src/ore_cllw_var_8/types.sql
+-- REQUIRE: src/ore_cllw_var_8/functions.sql
+
+
+
+-- Lexical comparison operators
+
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_var_8_eq(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8);
+
+CREATE OR REPLACE FUNCTION eql_v1.ore_cllw_var_8_eq(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8) RETURNS boolean AS $$
+ SELECT eql_v1.bytea_eq(a.bytes, b.bytes)
+$$ LANGUAGE SQL;
+
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_var_8_neq(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8);
+
+CREATE OR REPLACE FUNCTION eql_v1.ore_cllw_var_8_neq(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8) RETURNS boolean AS $$
+ SELECT NOT eql_v1.bytea_eq(a.bytes, b.bytes)
+$$ LANGUAGE SQL;
+
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_var_8_lt(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8);
+
+CREATE OR REPLACE FUNCTION eql_v1.ore_cllw_var_8_lt(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8)
+RETURNS boolean
+-- AS $$
+-- SELECT eql_v1.compare_ore_cllw_var_8(a, b) = -1
+-- $$ LANGUAGE SQL;
+AS $$
+ BEGIN
+ RETURN eql_v1.compare_ore_cllw_var_8(a, b) = -1;
+ END;
+$$ LANGUAGE plpgsql;
+
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_var_8_lte(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8);
+
+CREATE OR REPLACE FUNCTION eql_v1.ore_cllw_var_8_lte(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8) RETURNS boolean AS $$
+ SELECT eql_v1.compare_ore_cllw_var_8(a, b) != 1
+$$ LANGUAGE SQL;
+
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_var_8_gt(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8);
+
+CREATE OR REPLACE FUNCTION eql_v1.ore_cllw_var_8_gt(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8) RETURNS boolean AS $$
+ SELECT eql_v1.compare_ore_cllw_var_8(a, b) = 1
+$$ LANGUAGE SQL;
+
+-- DROP FUNCTION IF EXISTS eql_v1.ore_cllw_var_8_gte(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8);
+
+CREATE OR REPLACE FUNCTION eql_v1.ore_cllw_var_8_gte(a eql_v1.ore_cllw_var_8, b eql_v1.ore_cllw_var_8) RETURNS boolean AS $$
+ SELECT eql_v1.compare_ore_cllw_var_8(a, b) != -1
+$$ LANGUAGE SQL;
+
+-- DROP OPERATOR IF EXISTS = (eql_v1.ore_cllw_var_8, eql_v1.ore_cllw_var_8);
+
+CREATE OPERATOR = (
+ FUNCTION=eql_v1.ore_cllw_var_8_eq,
+ LEFTARG=eql_v1.ore_cllw_var_8,
+ RIGHTARG=eql_v1.ore_cllw_var_8,
+ NEGATOR = <>,
+ RESTRICT = eqsel,
+ JOIN = eqjoinsel,
+ HASHES,
+ MERGES
+);
+
+-- DROP OPERATOR IF EXISTS <> (eql_v1.ore_cllw_var_8, eql_v1.ore_cllw_var_8);
+
+CREATE OPERATOR <> (
+ FUNCTION=eql_v1.ore_cllw_var_8_neq,
+ LEFTARG=eql_v1.ore_cllw_var_8,
+ RIGHTARG=eql_v1.ore_cllw_var_8,
+ NEGATOR = =,
+ RESTRICT = eqsel,
+ JOIN = eqjoinsel,
+ HASHES,
+ MERGES
+);
+
+-- DROP OPERATOR IF EXISTS > (eql_v1.ore_cllw_var_8, eql_v1.ore_cllw_var_8);
+
+CREATE OPERATOR > (
+ FUNCTION=eql_v1.ore_cllw_var_8_gt,
+ LEFTARG=eql_v1.ore_cllw_var_8,
+ RIGHTARG=eql_v1.ore_cllw_var_8,
+ NEGATOR = <=,
+ RESTRICT = scalarltsel,
+ JOIN = scalarltjoinsel,
+ HASHES,
+ MERGES
+);
+
+-- DROP OPERATOR IF EXISTS < (eql_v1.ore_cllw_var_8, eql_v1.ore_cllw_var_8);
+
+CREATE OPERATOR < (
+ FUNCTION=eql_v1.ore_cllw_var_8_lt,
+ LEFTARG=eql_v1.ore_cllw_var_8,
+ RIGHTARG=eql_v1.ore_cllw_var_8,
+ NEGATOR = >=,
+ RESTRICT = scalargtsel,
+ JOIN = scalargtjoinsel,
+ HASHES,
+ MERGES
+);
+
+-- DROP OPERATOR IF EXISTS >= (eql_v1.ore_cllw_var_8, eql_v1.ore_cllw_var_8);
+
+CREATE OPERATOR >= (
+ FUNCTION=eql_v1.ore_cllw_var_8_gte,
+ LEFTARG=eql_v1.ore_cllw_var_8,
+ RIGHTARG=eql_v1.ore_cllw_var_8,
+ NEGATOR = <,
+ RESTRICT = scalarltsel,
+ JOIN = scalarltjoinsel,
+ HASHES,
+ MERGES
+);
+
+-- DROP OPERATOR IF EXISTS <= (eql_v1.ore_cllw_var_8, eql_v1.ore_cllw_var_8);
+
+CREATE OPERATOR <= (
+ FUNCTION=eql_v1.ore_cllw_var_8_lte,
+ LEFTARG=eql_v1.ore_cllw_var_8,
+ RIGHTARG=eql_v1.ore_cllw_var_8,
+ NEGATOR = >,
+ RESTRICT = scalargtsel,
+ JOIN = scalargtjoinsel,
+ HASHES,
+ MERGES
+);
diff --git a/src/ore_cllw_var_8/operators_test.sql b/src/ore_cllw_var_8/operators_test.sql
new file mode 100644
index 0000000..5b89813
--- /dev/null
+++ b/src/ore_cllw_var_8/operators_test.sql
@@ -0,0 +1,234 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- ore_cllw_var_8 < ore_cllw_var_8
+--
+-- Test data is '{"hello": "world", "n": 42}'
+
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
+--
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- json n: 20
+ sv := get_numeric_ste_vec_20()::eql_v1_encrypted;
+
+ -- extract the term at $.n
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted < eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''a7cea93975ed8c01f861ccb6bd082784'') < eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term));
+
+ -- other values are "one" and "three"
+ PERFORM assert_count(
+ format('eql_v1_encrypted < eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''a7cea93975ed8c01f861ccb6bd082784'') < eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term),
+ 2);
+
+ -- Check the $.n path
+ -- Returned encrypted does not have ore_cllw_var_8 and raises an exception
+ PERFORM assert_exception(
+ format('eql_v1_encrypted < eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''2517068c0d1f9d4d41d2c666211f785e'') < eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+
+-- -- ------------------------------------------------------------------------
+-- -- ------------------------------------------------------------------------
+-- --
+-- -- ore_cllw_var_8 <= ore_cllw_var_8
+-- --
+-- -- Test data is '{"hello": "world", "n": 42}'
+
+-- -- Paths
+-- -- $ -> bca213de9ccce676fa849ff9c4807963
+-- -- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- -- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+-- --
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- json n: 20
+ sv := get_numeric_ste_vec_20()::eql_v1_encrypted;
+
+ -- extract the term at $.n
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted <= eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''a7cea93975ed8c01f861ccb6bd082784'') <= eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted <= eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''a7cea93975ed8c01f861ccb6bd082784'') <= eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term),
+ 3);
+
+ -- Check the $.hello path
+ -- Returned encrypted does not have ore_cllw_var_8
+ PERFORM assert_exception(
+ format('eql_v1_encrypted <= eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''2517068c0d1f9d4d41d2c666211f785e'') <= eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- -- ------------------------------------------------------------------------
+-- -- ------------------------------------------------------------------------
+-- --
+-- -- ore_cllw_var_8 >= ore_cllw_var_8
+-- --
+-- -- Test data is '{"hello": "world", "n": 42}'
+
+-- -- Paths
+-- -- $ -> bca213de9ccce676fa849ff9c4807963
+-- -- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- -- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+-- --
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- json n: 30
+ sv := get_numeric_ste_vec_30()::eql_v1_encrypted;
+
+ -- extract the term at $.n
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted >= eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''a7cea93975ed8c01f861ccb6bd082784'') >= eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted >= eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''a7cea93975ed8c01f861ccb6bd082784'') >= eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term),
+ 2);
+
+ -- Check the $ path
+ -- Returned encrypted does not have ore_cllw_var_8
+ PERFORM assert_exception(
+ format('eql_v1_encrypted >= eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''bca213de9ccce676fa849ff9c4807963'') >= eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- -- ------------------------------------------------------------------------
+-- -- ------------------------------------------------------------------------
+-- --
+-- -- ore_cllw_var_8 > ore_cllw_var_8
+-- --
+-- -- Test data is '{"hello": "world", "n": 42}'
+
+-- -- Paths
+-- -- $ -> bca213de9ccce676fa849ff9c4807963
+-- -- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- -- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+-- --
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- json hello: one
+ sv := get_numeric_ste_vec_10()::eql_v1_encrypted;
+
+ -- extract the term at $.n
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ -- -- -- -- $.n
+ PERFORM assert_result(
+ format('eql_v1_encrypted > eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''a7cea93975ed8c01f861ccb6bd082784'') > eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted > eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''a7cea93975ed8c01f861ccb6bd082784'') > eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term),
+ 2);
+
+ -- Check the $ path
+ -- Returned encrypted does not have ore_cllw_var_8
+ PERFORM assert_exception(
+ format('eql_v1_encrypted > eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''bca213de9ccce676fa849ff9c4807963'') > eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+
+-- -- ------------------------------------------------------------------------
+-- -- ------------------------------------------------------------------------
+-- --
+-- -- ore_cllw_var_8 = ore_cllw_var_8
+-- --
+-- -- Test data is '{"hello": "world", "n": 42}'
+
+-- -- Paths
+-- -- $ -> bca213de9ccce676fa849ff9c4807963
+-- -- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- -- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+-- --
+-- --
+DO $$
+DECLARE
+ sv eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ -- json n: 20
+ sv := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ -- extract the term at $.n
+ term := sv->'a7cea93975ed8c01f861ccb6bd082784';
+
+ PERFORM assert_result(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''a7cea93975ed8c01f861ccb6bd082784'') = eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term));
+
+ PERFORM assert_count(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''a7cea93975ed8c01f861ccb6bd082784'') = eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term),
+ 1);
+
+ -- Check the $.n path
+ -- Returned encrypted does not have ore_cllw_var_8 and raises exception
+ PERFORM assert_exception(
+ format('eql_v1_encrypted = eql_v1_encrypted with ore_cllw_var_8 index term'),
+ format('SELECT e FROM encrypted WHERE eql_v1.ore_cllw_var_8(e->''2517068c0d1f9d4d41d2c666211f785e'') = eql_v1.ore_cllw_var_8(%L::eql_v1_encrypted)', term));
+
+ END;
+$$ LANGUAGE plpgsql;
diff --git a/src/ore_cllw_var_8/types.sql b/src/ore_cllw_var_8/types.sql
new file mode 100644
index 0000000..145432a
--- /dev/null
+++ b/src/ore_cllw_var_8/types.sql
@@ -0,0 +1,7 @@
+-- REQUIRE: src/schema.sql
+
+-- Represents a ciphertext encrypted with the CLLW ORE scheme for a variable output size
+-- Each output block is 8-bits
+CREATE TYPE eql_v1.ore_cllw_var_8 AS (
+ bytes bytea
+);
diff --git a/src/ste_vec/functions.sql b/src/ste_vec/functions.sql
new file mode 100644
index 0000000..f3ecd01
--- /dev/null
+++ b/src/ste_vec/functions.sql
@@ -0,0 +1,162 @@
+-- REQUIRE: src/schema.sql
+-- REQUIRE: src/encrypted/types.sql
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.ste_vec(val jsonb);
+--
+CREATE FUNCTION eql_v1.ste_vec(val jsonb)
+ RETURNS eql_v1_encrypted[]
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ DECLARE
+ sv jsonb;
+ ary eql_v1_encrypted[];
+ BEGIN
+
+ IF val ? 'sv' THEN
+ sv := val->'sv';
+ ELSE
+ sv := jsonb_build_array(val);
+ END IF;
+
+ SELECT array_agg(elem::eql_v1_encrypted)
+ INTO ary
+ FROM jsonb_array_elements(sv) AS elem;
+
+ RETURN ary;
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- extracts ste_vec index from an eql_v1_encrypted value
+-- DROP FUNCTION IF EXISTS eql_v1.ste_vec(val eql_v1_encrypted);
+
+CREATE FUNCTION eql_v1.ste_vec(val eql_v1_encrypted)
+ RETURNS eql_v1_encrypted[]
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN (SELECT eql_v1.ste_vec(val.data));
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.selector(val jsonb);
+
+CREATE FUNCTION eql_v1.selector(val jsonb)
+ RETURNS text
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ IF val ? 's' THEN
+ RETURN val->>'s';
+ END IF;
+ RAISE 'Expected a selector index (s) value in json: %', val;
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- extracts ste_vec index from an eql_v1_encrypted value
+-- DROP FUNCTION IF EXISTS eql_v1.selector(val eql_v1_encrypted);
+
+CREATE FUNCTION eql_v1.selector(val eql_v1_encrypted)
+ RETURNS text
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN (SELECT eql_v1.selector(val.data));
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- DROP FUNCTION IF EXISTS eql_v1.is_ste_vec_array(val jsonb);
+
+CREATE FUNCTION eql_v1.is_ste_vec_array(val jsonb)
+ RETURNS boolean
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ IF val ? 'a' THEN
+ RETURN (val->>'a')::boolean;
+ END IF;
+
+ RETURN false;
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- extracts ste_vec index from an eql_v1_encrypted value
+-- DROP FUNCTION IF EXISTS eql_v1.is_ste_vec_array(val eql_v1_encrypted);
+
+CREATE FUNCTION eql_v1.is_ste_vec_array(val eql_v1_encrypted)
+ RETURNS boolean
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ BEGIN
+ RETURN (SELECT eql_v1.is_ste_vec_array(val.data));
+ END;
+$$ LANGUAGE plpgsql;
+
+
+
+-- Returns true if b is contained in any element of a
+-- DROP FUNCTION IF EXISTS eql_v1.ste_vec_contains(a eql_v1_encrypted[], b eql_v1_encrypted);
+CREATE FUNCTION eql_v1.ste_vec_contains(a eql_v1_encrypted[], b eql_v1_encrypted)
+ RETURNS boolean
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ DECLARE
+ result boolean;
+ _a eql_v1_encrypted;
+ BEGIN
+
+ result := false;
+
+ FOR idx IN 1..array_length(a, 1) LOOP
+ _a := a[idx];
+ result := result OR (eql_v1.selector(_a) = eql_v1.selector(b) AND _a = b);
+ END LOOP;
+
+ RETURN result;
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- Returns truy if a contains b
+-- All values of b must be in a
+-- DROP FUNCTION IF EXISTS eql_v1.ste_vec_contains(a eql_v1_encrypted, b eql_v1_encrypted);
+CREATE FUNCTION eql_v1.ste_vec_contains(a eql_v1_encrypted, b eql_v1_encrypted)
+ RETURNS boolean
+ IMMUTABLE STRICT PARALLEL SAFE
+AS $$
+ DECLARE
+ result boolean;
+ sv_a eql_v1_encrypted[];
+ sv_b eql_v1_encrypted[];
+ _b eql_v1_encrypted;
+ BEGIN
+
+ -- jsonb arrays of ste_vec encrypted values
+ sv_a := eql_v1.ste_vec(a);
+ sv_b := eql_v1.ste_vec(b);
+
+ -- an empty b is always contained in a
+ IF array_length(sv_b, 1) IS NULL THEN
+ RETURN true;
+ END IF;
+
+ IF array_length(sv_a, 1) IS NULL THEN
+ RETURN false;
+ END IF;
+
+ result := true;
+
+ -- for each element of b check if it is in a
+ FOR idx IN 1..array_length(sv_b, 1) LOOP
+ _b := sv_b[idx];
+ result := result AND eql_v1.ste_vec_contains(sv_a, _b);
+ END LOOP;
+
+ RETURN result;
+ END;
+$$ LANGUAGE plpgsql;
diff --git a/src/ste_vec/functions_test.sql b/src/ste_vec/functions_test.sql
new file mode 100644
index 0000000..2b40318
--- /dev/null
+++ b/src/ste_vec/functions_test.sql
@@ -0,0 +1,92 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+
+DO $$
+ DECLARE
+ e eql_v1_encrypted;
+ sv eql_v1_encrypted[];
+ BEGIN
+
+ SELECT encrypted.e FROM encrypted LIMIT 1 INTO e;
+
+ sv := eql_v1.ste_vec(e);
+ ASSERT array_length(sv, 1) = 3;
+
+ -- eql_v1_encrypted that IS a ste_vec element
+ e := get_numeric_ste_vec_10()::eql_v1_encrypted;
+
+ sv := eql_v1.ste_vec(e);
+ ASSERT array_length(sv, 1) = 3;
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+DO $$
+ DECLARE
+ e eql_v1_encrypted;
+ sv eql_v1_encrypted[];
+ BEGIN
+ e := '{ "a": 1 }'::jsonb::eql_v1_encrypted;
+ ASSERT eql_v1.is_ste_vec_array(e);
+
+
+ e := '{ "a": 0 }'::jsonb::eql_v1_encrypted;
+ ASSERT NOT eql_v1.is_ste_vec_array(e);
+
+ e := '{ }'::jsonb::eql_v1_encrypted;
+ ASSERT NOT eql_v1.is_ste_vec_array(e);
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- eql_v1_encrypted contains itself
+--
+--
+DO $$
+ DECLARE
+ a eql_v1_encrypted;
+ b eql_v1_encrypted;
+ BEGIN
+
+ a := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ b := get_numeric_ste_vec_10()::eql_v1_encrypted;
+
+ ASSERT eql_v1.ste_vec_contains(a, b);
+ ASSERT eql_v1.ste_vec_contains(b, a);
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- ------------------------------------------------------------------------
+-- ------------------------------------------------------------------------
+--
+-- eql_v1_encrypted contains a term
+--
+--
+DO $$
+ DECLARE
+ a eql_v1_encrypted;
+ b eql_v1_encrypted;
+ term eql_v1_encrypted;
+ BEGIN
+
+ a := get_numeric_ste_vec_10()::eql_v1_encrypted;
+ b := get_numeric_ste_vec_10()::eql_v1_encrypted;
+
+ -- $.n
+ term := b->'2517068c0d1f9d4d41d2c666211f785e';
+
+ ASSERT eql_v1.ste_vec_contains(a, term);
+
+ ASSERT NOT eql_v1.ste_vec_contains(term, a);
+ END;
+$$ LANGUAGE plpgsql;
+
diff --git a/src/unique/functions.sql b/src/unique/functions.sql
index 301dbb7..4d18f67 100644
--- a/src/unique/functions.sql
+++ b/src/unique/functions.sql
@@ -1,7 +1,8 @@
+-- REQUIRE: src/schema.sql
-- REQUIRE: src/unique/types.sql
-- extracts unique index from an encrypted column
-DROP FUNCTION IF EXISTS eql_v1.unique(val jsonb);
+-- DROP FUNCTION IF EXISTS eql_v1.unique(val jsonb);
CREATE FUNCTION eql_v1.unique(val jsonb)
RETURNS eql_v1.unique_index
@@ -17,7 +18,7 @@ $$ LANGUAGE plpgsql;
-- extracts unique index from an encrypted column
-DROP FUNCTION IF EXISTS eql_v1.unique(val eql_v1_encrypted);
+-- DROP FUNCTION IF EXISTS eql_v1.unique(val eql_v1_encrypted);
CREATE FUNCTION eql_v1.unique(val eql_v1_encrypted)
RETURNS eql_v1.unique_index
diff --git a/src/unique/types.sql b/src/unique/types.sql
index aa3890a..df496c6 100644
--- a/src/unique/types.sql
+++ b/src/unique/types.sql
@@ -1,4 +1,4 @@
-- REQUIRE: src/schema.sql
-DROP DOMAIN IF EXISTS eql_v1.unique_index;
+-- DROP DOMAIN IF EXISTS eql_v1.unique_index;
CREATE DOMAIN eql_v1.unique_index AS text;
diff --git a/tasks/build.sh b/tasks/build.sh
index b861898..7293615 100755
--- a/tasks/build.sh
+++ b/tasks/build.sh
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
#MISE description="Build SQL into single release file"
#MISE alias="b"
-#MISE sources=["sql/*.sql"]
+#MISE sources=["src/**/*.sql"]
#MISE outputs=["release/cipherstash-encrypt.sql","release/cipherstash-encrypt-uninstall.sql"]
#USAGE flag "--version " help="Specify release version of EQL" default="DEV"
diff --git a/tasks/test.sh b/tasks/test.sh
index 4a45e47..c86909c 100755
--- a/tasks/test.sh
+++ b/tasks/test.sh
@@ -30,11 +30,7 @@ run_test () {
echo '###############################################'
echo
-
-
cat $1 | docker exec -i ${container_name} psql --variable ON_ERROR_STOP=1 $connection_url -f-
-
-
}
# setup
@@ -42,7 +38,10 @@ fail_if_postgres_not_running
mise run build --force
mise run reset --force --postgres ${POSTGRES_VERSION}
+echo '/////////////////////////////////////////////////////////'
cat release/cipherstash-encrypt.sql
+echo '/////////////////////////////////////////////////////////'
+
# Install
# cat release/cipherstash-encrypt.sql | docker exec -i ${container_name} psql ${connection_url} -f-
diff --git a/tasks/uninstall.sql b/tasks/uninstall.sql
index d79c4d6..0f35210 100644
--- a/tasks/uninstall.sql
+++ b/tasks/uninstall.sql
@@ -5,4 +5,6 @@ BEGIN
END
$$;
-DROP SCHEMA IF EXISTS eql_v1 CASCADE;
\ No newline at end of file
+ALTER TABLE public.eql_v1_configuration DROP CONSTRAINT IF EXISTS eql_v1_configuration_data_check;
+
+DROP SCHEMA IF EXISTS eql_v1 CASCADE;
diff --git a/tests/old/@>_test.sql b/tests/old/@>_test.sql
new file mode 100644
index 0000000..1147314
--- /dev/null
+++ b/tests/old/@>_test.sql
@@ -0,0 +1,98 @@
+\set ON_ERROR_STOP on
+
+SELECT create_table_with_encrypted();
+SELECT seed_encrypted_json();
+
+SELECT * FROM encrypted;
+
+SELECT e @> '{
+ "c": "ciphertext",
+ "i": {
+ "t": "encrypted",
+ "c": "e"
+ },
+ "s": "selector.1",
+ "t": "term.1"
+ }'::jsonb::eql_v1_encrypted FROM encrypted;
+
+
+\set ON_ERROR_STOP on
+
+
+SELECT create_table_with_encrypted();
+
+
+DO $$
+ BEGIN
+ PERFORM assert_result(
+ 'Fetch ciphertext from encrypted column',
+ 'SELECT e->>''selector.1'' FROM encrypted;');
+ END;
+$$ LANGUAGE plpgsql;
+
+
+DO $$
+ BEGIN
+ PERFORM assert_result(
+ 'Fetch ciphertext from encrypted column',
+ 'SELECT e->>''selector.1'' FROM encrypted;');
+ END;
+$$ LANGUAGE plpgsql;
+
+
+DO $$
+ BEGIN
+ PERFORM assert_result(
+ 'Fetch encrypted using selected',
+ 'SELECT e->''selector.1'' FROM encrypted;');
+
+
+ PERFORM assert_no_result(
+ '-> operator only works on top level of encrypted column',
+ 'SELECT e->''selector.1''->''blah'' FROM encrypted;');
+ END;
+$$ LANGUAGE plpgsql;
+
+
+SELECT drop_table_with_encrypted();
+
+-- DO $$
+-- DECLARE
+-- e eql_v1_encrypted;
+-- BEGIN
+-- e := '{
+-- "c": "ciphertext",
+-- "i": {
+-- "t": "encrypted",
+-- "c": "e"
+-- },
+-- "s": "selector.1",
+-- "t": "term.1"
+-- }'::jsonb::eql_v1_encrypted;
+
+-- PERFORM eql_v1.log('Encrypted', e::text);
+
+
+-- PERFORM assert_result(
+-- 'Fetch ciphertext from encrypted column',
+-- format('SELECT e @> %s FROM encrypted;', e));
+
+-- END;
+-- $$ LANGUAGE plpgsql;
+
+
+-- -- DO $$
+-- -- BEGIN
+-- -- PERFORM assert_result(
+-- -- 'Fetch encrypted using selected',
+-- -- 'SELECT e->''selector.1'' FROM encrypted;');
+
+
+-- -- PERFORM assert_no_result(
+-- -- '-> operator only works on top level of encrypted column',
+-- -- 'SELECT e->''selector.1''->''blah'' FROM encrypted;');
+-- -- END;
+-- -- $$ LANGUAGE plpgsql;
+
+
+SELECT drop_table_with_encrypted();
\ No newline at end of file
diff --git a/tests/old/core.sql b/tests/old/core.sql
new file mode 100644
index 0000000..04a5e2c
--- /dev/null
+++ b/tests/old/core.sql
@@ -0,0 +1,219 @@
+\set ON_ERROR_STOP on
+
+-- Create a table with a plaintext column
+DROP TABLE IF EXISTS users;
+CREATE TABLE users
+(
+ id bigint GENERATED ALWAYS AS IDENTITY,
+ name_encrypted eql_v1_encrypted,
+ PRIMARY KEY(id)
+);
+
+
+TRUNCATE TABLE users;
+
+
+INSERT INTO users (name_encrypted) VALUES (
+ '{
+ "v": 1,
+ "k": "ct",
+ "c": "ciphertext",
+ "i": {
+ "t": "users",
+ "c": "name"
+ },
+ "m": [1, 1],
+ "u": "text",
+ "o": ["a"]
+ }'::jsonb
+);
+
+DO $$
+ BEGIN
+
+ ASSERT (SELECT EXISTS (SELECT id FROM users WHERE eql_v1.ciphertext(name_encrypted) = 'ciphertext'));
+
+ ASSERT (SELECT EXISTS (SELECT id FROM users WHERE eql_v1.match(name_encrypted) = '{1,1}'));
+
+ ASSERT (SELECT EXISTS (SELECT id FROM users WHERE eql_v1.unique(name_encrypted) = 'text'));
+
+ -- ORE PAYLOAD ABOUT TO CHANGE
+ -- ASSERT (SELECT EXISTS (SELECT id FROM users WHERE eql_v1.ore_64_8_v1(name_encrypted) = '{a}'));
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+TRUNCATE TABLE users;
+
+INSERT INTO users DEFAULT VALUES;
+
+SELECT id FROM users;
+
+DO $$
+ BEGIN
+ ASSERT (SELECT EXISTS (SELECT id FROM users));
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- -----------------------------------------------
+---
+-- eql_v1_encrypted type
+-- Validate configuration schema
+-- Try and insert many invalid configurations
+-- None should exist
+--
+-- -----------------------------------------------
+TRUNCATE TABLE users;
+
+\set ON_ERROR_STOP off
+\set ON_ERROR_ROLLBACK on
+
+DO $$
+ BEGIN
+ RAISE NOTICE 'eql_v1_encrypted constraint tests: 10 errors expected here';
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- no version
+INSERT INTO users (name_encrypted) VALUES (
+ '{
+ "v": 1,
+ "k": "ct",
+ "c": "ciphertext",
+ "i": {
+ "t": "users",
+ "c": "name"
+ }
+ }'::jsonb
+);
+
+-- no ident details
+INSERT INTO users (name_encrypted) VALUES (
+ '{
+ "v": 1,
+ "k": "ct",
+ "c": "ciphertext"
+ }'::jsonb
+);
+
+-- no kind
+INSERT INTO users (name_encrypted) VALUES (
+ '{
+ "v": 1,
+ "c": "ciphertext",
+ "i": {
+ "t": "users",
+ "c": "name"
+ }
+ }'::jsonb
+);
+
+
+
+-- bad kind
+INSERT INTO users (name_encrypted) VALUES (
+ '{
+ "v": 1,
+ "k": "vtha",
+ "c": "ciphertext",
+ "i": {
+ "t": "users",
+ "c": "name"
+ }
+ }'::jsonb
+);
+
+-- pt
+INSERT INTO users (name_encrypted) VALUES (
+ '{
+ "v": 1,
+ "k": "pt",
+ "i": {
+ "t": "users",
+ "c": "name"
+ }
+ }'::jsonb
+);
+
+--pt with ciphertext
+INSERT INTO users (name_encrypted) VALUES (
+ '{
+ "v": 1,
+ "k": "pt",
+ "c": "ciphertext",
+ "i": {
+ "t": "users",
+ "c": "name"
+ }
+ }'::jsonb
+);
+
+-- ct without ciphertext
+INSERT INTO users (name_encrypted) VALUES (
+ '{
+ "v": 1,
+ "k": "ct",
+ "i": {
+ "t": "users",
+ "c": "name"
+ }
+ }'::jsonb
+);
+
+
+-- ct with plaintext
+INSERT INTO users (name_encrypted) VALUES (
+ '{
+ "v": 1,
+ "k": "ct",
+ "p": "plaintext",
+ "i": {
+ "t": "users",
+ "c": "name"
+ }
+ }'::jsonb
+);
+
+
+-- ciphertext without ct
+INSERT INTO users (name_encrypted) VALUES (
+ '{
+ "v": 1,
+ "c": "ciphertext",
+ "i": {
+ "t": "users",
+ "c": "name"
+ }
+ }'::jsonb
+);
+
+-- ciphertext with invalid q
+INSERT INTO users (name_encrypted) VALUES (
+ '{
+ "v": 1,
+ "c": "ciphertext",
+ "i": {
+ "t": "users",
+ "c": "name"
+ },
+ "q": "invalid"
+ }'::jsonb
+);
+
+-- Nothing should be in the DB
+DO $$
+ BEGIN
+ ASSERT (SELECT NOT EXISTS (SELECT * FROM users c));
+ END;
+$$ LANGUAGE plpgsql;
+
+
+\set ON_ERROR_STOP on
+\set ON_ERROR_ROLLBACK off
+
+
+
+
diff --git a/tests/test_helpers.sql b/tests/test_helpers.sql
index 5707348..eb806c0 100644
--- a/tests/test_helpers.sql
+++ b/tests/test_helpers.sql
@@ -25,25 +25,249 @@ AS $$
END;
$$ LANGUAGE plpgsql;
+--
+-- Creates a table with an encrypted column for testing
+--
+DROP FUNCTION IF EXISTS truncate_table_with_encrypted();
+CREATE FUNCTION truncate_table_with_encrypted()
+ RETURNS void
+AS $$
+ BEGIN
+ TRUNCATE encrypted;
+ END;
+$$ LANGUAGE plpgsql;
+
+
-DROP FUNCTION IF EXISTS get_high_ore();
-CREATE FUNCTION get_high_ore()
+DROP FUNCTION IF EXISTS get_numeric_ste_vec_10();
+CREATE FUNCTION get_numeric_ste_vec_10()
RETURNS jsonb
AS $$
BEGIN
- RETURN '{"o": ["1212121212125932e28282d03415e7714fccd69eb7eb476c70743e485e20331f59cbc1c848dcdeda716f351eb20588c406a7df5fb8917ebf816739aa1414ac3b8498e493bf0badea5c9fdb3cc34da8b152b995957591880c523beb1d3f12487c38d18f62dd26209a727674e5a5fe3a3e3037860839afd8011f94b49eaa5fa5a60e1e2adccde4185a7d6c7f83088500b677f897d4ffc276016d614708488f407c01bd3ccf2be653269062cb97f8945a621d049277d19b1c248611f25d047038928d2efeb4323c402af4c19288c7b36911dc06639af5bb34367519b66c1f525bbd3828c12067c9c579aeeb4fb3ae0918125dc1dad5fd518019a5ae67894ce1a7f7bed1a591ba8edda2fdf4cd403761fd981fb1ea5eb0bf806f919350ee60cac16d0a39a491a4d79301781f95ea3870aea82e9946053537360b2fb415b18b61aed0af81d461ad6b923f10c0df79daddc4e279ff543a282bb3a37f9fa03238348b3dac51a453b04bced1f5bd318ddd829bdfe5f37abdbeda730e21441b818302f3c5c2c4d5657accfca4c53d7a80eb3db43946d38965be5f796b"]}'::jsonb;
-END;
+ RETURN '{
+ "sv": [
+ {
+ "b": "7b4ffe5d60e4e4300dc3e28d9c300c87",
+ "c": "mBbLGB9xHAGzLvUj-`@Wmf=IhD87n7r3ir3n!Sk6AKir_YawR=0c>pk(OydB;ntIEXK~c>V&4>)rNkfF eql_v1_encrypted[]
+-- a [
+-- 1
+-- ]
+--
+
+-- ORIGINAL $.a encoding
+-- {
+-- "b": "8258356162d2415d55244abf49e40da3",
+-- "c": "mBbL9j9(QoRD)R+z?=Fvn#=FR9iI)K4Nzk-ea`~#Lx@wBSDPSmkp-h+tNEHoo@T@#vwh?Ejvk%78G}b+je+xufQA5mSwHSid)iEOkg@>mpuh",
+-- "s": "f510853730e1c3dbd31b86963f029dd5"
+-- },
+
+DROP FUNCTION IF EXISTS get_array_ste_vec();
+CREATE FUNCTION get_array_ste_vec()
+ RETURNS jsonb
+AS $$
+ BEGIN
+ RETURN '{
+ "sv": [
+ {
+ "b": "7b4ffe5d60e4e4300dc3e28d9c300c87",
+ "c": "mBbL9j9(QoRD)R+z?=Fvn#=FRIg79JJM`MCq+nE0*U^ca-cViL884d-TInfY&E9HW@X>!U&lkYne2!EecKG8xwLYb0X#y7|05rrPvwh?Ejvk%78G}b+je+xufQA5mSwHSid)iEOkg@>mpuh",
+ "s": "bca213de9ccce676fa849ff9c4807963"
+ },
+
+
+
+ {
+
+ "c": "mBbL9j9(QoRD)R+z?=Fvn#=FR6Z{(4c^$CD^7q>z{xl^%5S4=m#2~YMW7y15TC<^_oBO-6ni$TotY#2~YMz{xl^%5S4=m#2~YMW7y15TC<^_oBO-6ni$TotY#2~YMoG#B*Y-IedG9!9-X`ygGXYGf%A%hh5&w9KkiR^+DvtjvHG(8jjwtt=6Wr{!%WJ?vt(v&0~?edG9!9-X`ygGXYGf%A%hh5&w9KkiR^+DvtjvHH*Pjq@SFR7iRajU#?{(K%x=#2^Zs|F~fm*&w!wSjZQIUaj-XX01=c??f8cq8*Vf?zEu5",
+ "ocv": "af96e1dabbec581f36d71e3a48ffb427f54832851b4fefa6989887ccaf7e038f66f8cb40e6959458",
+ "s": "a7cea93975ed8c01f861ccb6bd082784"
+ },
+ {
+ "c": "mBbM0#UZON2jQ3@LiWcvns2Yf6y3L;hykEh`}*fX#aF;n*=>+*o5Uarod39C7TF-SiCD-NgkG)l%Vw=l!tX>H*PkiFH&De7C+d}sDugsc?JuI*>$AsG83nsXvrND0-(S",
+ "b": "7b4ffe5d60e4e4300dc3e28d9c300c87",
+ "s": "bca213de9ccce676fa849ff9c4807963"
+ },
+ {
+ "c": "mBbK0Cob5dQ5Jki69vRd75f9k8Rn)lVSgZ9Q3jQYu)}sv8};==6AExb8MwqC=TCnxQeQ_FKiJQxgbDw71`CJTb)@Vv6Q`bN$sH2{puh",
+ "ocv": "af96e1dabbec5913707844664eb160923982fdec75bda4bcd063e26b4254a9f334ce7ebc2612713c",
+ "s": "a7cea93975ed8c01f861ccb6bd082784"
+ },
+ {
+ "c": "mBbK0Cob5dQ5Jki69vRd75f9k6yc;BV`COqamPOX6P`g5TMr)AeZ(N=Pk%%2`Uq=={*w3hh3IBNp3y0Ztr0g;ir=DoZ9TNhezy",
+ "ocf": "b0c13d4a4a9ffcb2ef8629d60d5e32db453fad8792b2450d02f37ec5fe207b42da30093fd14c4975c9b192ecbf939b2d5a56a7ae2db1254e6532aa7569971462",
+ "s": "2517068c0d1f9d4d41d2c666211f785e"
+ }
+ ]
+ }'::jsonb;
+ END;
+$$ LANGUAGE plpgsql;
-- --
@@ -51,6 +275,13 @@ $$ LANGUAGE plpgsql;
--
-- Creates a table with an encrypted column for testing
--
+-- JSON -- '{"hello": "world", "n": 42}'
+--
+-- Paths
+-- $ -> bca213de9ccce676fa849ff9c4807963
+-- $.hello -> a7cea93975ed8c01f861ccb6bd082784
+-- $.n -> 2517068c0d1f9d4d41d2c666211f785e
+--
-- --
-- --
DROP FUNCTION IF EXISTS create_encrypted_json(integer);
@@ -64,6 +295,8 @@ AS $$
stop integer;
random_key text;
random_val text;
+ sv jsonb;
+ ore_term jsonb;
BEGIN
start := (10 * id);
@@ -73,6 +306,22 @@ AS $$
select substr(md5(random()::text), 1, 25) INTO random_key;
select substr(md5(random()::text), 1, 25) INTO random_val;
+ CASE id
+ WHEN 1 THEN
+ sv := get_numeric_ste_vec_10();
+ WHEN 2 THEN
+ sv := get_numeric_ste_vec_20();
+ WHEN 3 THEN
+ sv := get_numeric_ste_vec_30();
+ ELSE
+ sv := get_numeric_ste_vec_42();
+ END CASE;
+
+
+ SELECT ore.e FROM ore WHERE ore.id = start INTO ore_term;
+
+ -- PERFORM eql_v1.log('ore_term: ', ore_term::text);
+
s := format(
'{
"%s": "%s",
@@ -82,23 +331,80 @@ AS $$
"c": "e"
},
"u": "unique.%s",
- "m": %s,
- "o": ["12121212121259bfe28282d03415e7714fccd69eb7eb476c70743e485e20331f59cbc1c848dcdeda716f351eb20588c406a7df5fb8917ebf816739aa1414ac3b8498e493bf0badea5c9fdb3cc34da8b152b995957591880c523beb1d3f12487c38d18f62dd26209a727674e5a5fe3a3e3037860839afd801ff4a28b714e4cde8df10625dce72602fdbdcc53d515857f1119f5912804ce09c6cf6c2d37393a27a465134523b512664582f834e15003b7216cb668480bc3e7d1c069f2572ece7c848b9eb9a28b4e62bfc2b97c93e61b2054154e621c5bbb7bed37de3d7c343bd3dbcf7b4af20128c961351bf55910a855f08a8587c2059a5f05ca8d7a082e695b3dd4ff3ce86694d4fe98972220eea1ab90f5de493ef3a502b74a569f103ee2897ebc9ae9b16a17e7be67415ee830519beb3058ffc1c1eb0e574d66c8b365919f27eb00aa7bce475d7bdaad4ed800f8fc3d626e0eb842e312b0cc22a1ccf89847ebb2cd0a6e18aec21bd2deeec1c47301fc687f7f764bb882b50f553c246a6da5816b78b3530119ea68b08a8403a90e063e58502670563bd4d"],
- "j": [
- {
- "c": "ciphertext.%s",
- "s": "selector.%s",
- "t": "term.%s"
- }
- ]
+ "b": "blake3.%s",
+ "m": %s
}',
random_key,
random_val,
- id, m, id, id, id);
+ id, id, m);
+
+ s := s::jsonb || sv || ore_term;
+
+ -- PERFORM eql_v1.log('json: %', s);
RETURN s::eql_v1_encrypted;
+ END;
+$$ LANGUAGE plpgsql;
+
+
+DROP FUNCTION IF EXISTS create_encrypted_json(integer, VARIADIC indexes text[]);
+CREATE FUNCTION create_encrypted_json(id integer, VARIADIC indexes text[])
+ RETURNS eql_v1_encrypted
+AS $$
+ DECLARE
+ j jsonb;
+ BEGIN
+ j := create_encrypted_json(id);
+
+ j := (
+ SELECT jsonb_object_agg(key, value)
+ FROM jsonb_each(j)
+ WHERE key = ANY(indexes)
+ );
+
+ RETURN j::eql_v1_encrypted;
+
+ END;
+$$ LANGUAGE plpgsql;
+
+
+DROP FUNCTION IF EXISTS create_encrypted_json(VARIADIC indexes text[]);
+CREATE FUNCTION create_encrypted_json(VARIADIC indexes text[])
+ RETURNS eql_v1_encrypted
+AS $$
+ DECLARE
+ default_indexes text[];
+ j jsonb;
+ BEGIN
+
+ default_indexes := ARRAY['c', 'i', 'v'];
+
+ j := create_encrypted_json(1);
+
+ j := (
+ SELECT jsonb_object_agg(key, value)
+ FROM jsonb_each(j)
+ WHERE key = ANY(indexes || default_indexes)
+ );
+
+ RETURN j::eql_v1_encrypted;
+
+ END;
+$$ LANGUAGE plpgsql;
+
+DROP FUNCTION IF EXISTS create_encrypted_ore_json(val integer);
+CREATE FUNCTION create_encrypted_ore_json(val integer)
+ RETURNS eql_v1_encrypted
+AS $$
+ DECLARE
+ e eql_v1_encrypted;
+ ore_term jsonb;
+ BEGIN
+ EXECUTE format('SELECT ore.e FROM ore WHERE id = %s', val) INTO ore_term;
+ e := create_encrypted_json('o')::jsonb || ore_term;
+ RETURN e::eql_v1_encrypted;
END;
$$ LANGUAGE plpgsql;
@@ -107,8 +413,13 @@ DROP FUNCTION IF EXISTS create_encrypted_json();
CREATE FUNCTION create_encrypted_json()
RETURNS eql_v1_encrypted
AS $$
+ DECLARE
+ id integer;
+ j jsonb;
BEGIN
- RETURN (create_encrypted_json(1));
+ id := trunc(random() * 1000 + 1);
+ j := create_encrypted_json(id);
+ RETURN j::eql_v1_encrypted;
END;
$$ LANGUAGE plpgsql;
@@ -124,13 +435,14 @@ $$ LANGUAGE plpgsql;
--
--- Creates a table with an encrypted column for testing
+-- Truncates and creates base test data
--
DROP FUNCTION IF EXISTS seed_encrypted_json();
CREATE FUNCTION seed_encrypted_json()
RETURNS void
AS $$
BEGIN
+ PERFORM truncate_table_with_encrypted();
PERFORM seed_encrypted(create_encrypted_json(1));
PERFORM seed_encrypted(create_encrypted_json(2));
PERFORM seed_encrypted(create_encrypted_json(3));
@@ -179,7 +491,7 @@ AS $$
EXECUTE sql into result;
if result IS NULL THEN
- RAISE NOTICE 'ASSERTION FAILED';
+ RAISE NOTICE 'ASSERT RESULT FAILED';
RAISE NOTICE '%', regexp_replace(sql, '^\s+|\s*$', '', 'g');
ASSERT false;
END IF;
@@ -188,6 +500,31 @@ AS $$
$$ LANGUAGE plpgsql;
+--
+-- Assert the the provided SQL statement returns a non-null result
+--
+DROP FUNCTION IF EXISTS assert_result(describe text, sql text, result text);
+
+CREATE FUNCTION assert_result(describe text, sql text, expected text)
+ RETURNS void
+AS $$
+ DECLARE
+ result text;
+ BEGIN
+ RAISE NOTICE '%', describe;
+ EXECUTE sql into result;
+
+ if result <> expected THEN
+ RAISE NOTICE 'ASSERT EXPECTED RESULT FAILED';
+ RAISE NOTICE 'Expected: %', expected;
+ RAISE NOTICE 'Result: %', result;
+ RAISE NOTICE '%', regexp_replace(sql, '^\s+|\s*$', '', 'g');
+ ASSERT false;
+ END IF;
+
+ END;
+$$ LANGUAGE plpgsql;
+
--
-- Assert the the provided SQL statement returns a non-null result
--
@@ -203,7 +540,7 @@ AS $$
EXECUTE sql into result_id;
IF result_id <> id THEN
- RAISE NOTICE 'ASSERTION FAILED';
+ RAISE NOTICE 'ASSERT ID FAILED';
RAISE NOTICE 'Expected row with id % but returned %', id, result_id;
RAISE NOTICE '%', regexp_replace(sql, '^\s+|\s*$', '', 'g');
ASSERT false;
@@ -228,7 +565,7 @@ AS $$
EXECUTE sql into result;
IF result IS NOT NULL THEN
- RAISE NOTICE 'ASSERTION FAILED';
+ RAISE NOTICE 'ASSERT NO RESULT FAILED';
RAISE NOTICE '%', regexp_replace(sql, '^\s+|\s*$', '', 'g');
ASSERT false;
END IF;
@@ -257,7 +594,7 @@ AS $$
EXECUTE format('SELECT COUNT(*) FROM (%s) as q', sql) INTO result;
if result <> expected THEN
- RAISE NOTICE 'ASSERTION FAILED';
+ RAISE NOTICE 'ASSERT COUNT FAILED';
RAISE NOTICE 'Expected % rows and returned %', expected, result;
RAISE NOTICE '%', regexp_replace(sql, '^\s+|\s*$', '', 'g');
ASSERT false;
@@ -281,7 +618,7 @@ AS $$
BEGIN
EXECUTE sql;
- RAISE NOTICE 'ASSERTION FAILED';
+ RAISE NOTICE 'ASSERT EXCEPTION FAILED';
RAISE NOTICE 'EXPECTED STATEMENT TO RAISE EXCEPTION';
RAISE NOTICE '%', regexp_replace(sql, '^\s+|\s*$', '', 'g');
ASSERT false;