Skip to content

Commit 3e96b26

Browse files
committed
docs(sql): document encrypted functions and comparison operators (Phase 2 checkpoint 2)
Add Doxygen documentation for encrypted column operations and operators: Encrypted functions: - ciphertext: Extract ciphertext from encrypted values (2 overloads) - meta_data: Extract index terms/metadata (2 overloads) - grouped_value: Aggregate for first non-null value in groups - _first_grouped_value: Internal state function for aggregate - add_encrypted_constraint: Add validation constraints - remove_encrypted_constraint: Remove validation constraints Comparison operators: - lt: Less-than helper (internal) - < operator: Three overloads for ORE-based comparisons Pattern matching operators: - like: LIKE helper using bloom filters (internal) - ilike: Case-insensitive LIKE helper (internal) - ~~ operator: Three overloads for pattern matching (LIKE) - ~~* operator: Case-insensitive pattern matching (ILIKE) Coverage: 16 functions/operators documented across 3 files All include @brief, @param, @return tags Customer-facing functions include @example tags Internal functions marked with @internal Part of: add-doxygen-sql-comments plan Phase: 2 (Core modules - checkpoint 2/7)
1 parent ad579b1 commit 3e96b26

File tree

3 files changed

+280
-60
lines changed

3 files changed

+280
-60
lines changed

src/encrypted/functions.sql

Lines changed: 131 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,21 @@
33
-- REQUIRE: src/ore_block_u64_8_256/types.sql
44
-- REQUIRE: src/hmac_256/types.sql
55

6-
7-
6+
--! @brief Extract ciphertext from encrypted JSONB value
7+
--!
8+
--! Extracts the ciphertext (c field) from a raw JSONB encrypted value.
9+
--! The ciphertext is the base64-encoded encrypted data.
10+
--!
11+
--! @param val JSONB Raw encrypted value containing 'c' field
12+
--! @return Text Base64-encoded ciphertext string
13+
--! @throws Exception if 'c' field is not present in JSONB
14+
--!
15+
--! @example
16+
--! -- Extract ciphertext from JSONB literal
17+
--! SELECT eql_v2.ciphertext('{"c":"AQIDBA==","i":{"unique":"..."}}'::jsonb);
18+
--!
19+
--! @see eql_v2.ciphertext(eql_v2_encrypted)
20+
--! @see eql_v2.meta_data
821
CREATE FUNCTION eql_v2.ciphertext(val jsonb)
922
RETURNS text
1023
IMMUTABLE STRICT PARALLEL SAFE
@@ -17,7 +30,21 @@ AS $$
1730
END;
1831
$$ LANGUAGE plpgsql;
1932

20-
33+
--! @brief Extract ciphertext from encrypted column value
34+
--!
35+
--! Extracts the ciphertext from an encrypted column value. Convenience
36+
--! overload that unwraps eql_v2_encrypted type and delegates to JSONB version.
37+
--!
38+
--! @param val eql_v2_encrypted Encrypted column value
39+
--! @return Text Base64-encoded ciphertext string
40+
--! @throws Exception if encrypted value is malformed
41+
--!
42+
--! @example
43+
--! -- Extract ciphertext from encrypted column
44+
--! SELECT eql_v2.ciphertext(encrypted_email) FROM users;
45+
--!
46+
--! @see eql_v2.ciphertext(jsonb)
47+
--! @see eql_v2.meta_data
2148
CREATE FUNCTION eql_v2.ciphertext(val eql_v2_encrypted)
2249
RETURNS text
2350
IMMUTABLE STRICT PARALLEL SAFE
@@ -27,26 +54,70 @@ AS $$
2754
END;
2855
$$ LANGUAGE plpgsql;
2956

30-
57+
--! @brief State transition function for grouped_value aggregate
58+
--! @internal
59+
--!
60+
--! Returns the first non-null value encountered. Used as state function
61+
--! for the grouped_value aggregate to select first value in each group.
62+
--!
63+
--! @param $1 JSONB Accumulated state (first non-null value found)
64+
--! @param $2 JSONB New value from current row
65+
--! @return JSONB First non-null value (state or new value)
66+
--!
67+
--! @see eql_v2.grouped_value
3168
CREATE FUNCTION eql_v2._first_grouped_value(jsonb, jsonb)
3269
RETURNS jsonb AS $$
3370
SELECT COALESCE($1, $2);
3471
$$ LANGUAGE sql IMMUTABLE;
3572

36-
73+
--! @brief Return first non-null encrypted value in a group
74+
--!
75+
--! Aggregate function that returns the first non-null encrypted value
76+
--! encountered within a GROUP BY clause. Useful for deduplication or
77+
--! selecting representative values from grouped encrypted data.
78+
--!
79+
--! @param input JSONB Encrypted values to aggregate
80+
--! @return JSONB First non-null encrypted value in group
81+
--!
82+
--! @example
83+
--! -- Get first email per user group
84+
--! SELECT user_id, eql_v2.grouped_value(encrypted_email)
85+
--! FROM user_emails
86+
--! GROUP BY user_id;
87+
--!
88+
--! -- Deduplicate encrypted values
89+
--! SELECT DISTINCT ON (user_id)
90+
--! user_id,
91+
--! eql_v2.grouped_value(encrypted_ssn) as primary_ssn
92+
--! FROM user_records
93+
--! GROUP BY user_id;
94+
--!
95+
--! @see eql_v2._first_grouped_value
3796
CREATE AGGREGATE eql_v2.grouped_value(jsonb) (
3897
SFUNC = eql_v2._first_grouped_value,
3998
STYPE = jsonb
4099
);
41100

42-
43-
--
44-
-- Adds eql_v2.check_encrypted constraint to the column_name in table_name
45-
--
46-
-- Executes the ALTER TABLE statement
47-
-- `ALTER TABLE {table_name} ADD CONSTRAINT eql_v2_encrypted_check_{column_name} CHECK (eql_v2.check_encrypted({column_name}))`
48-
--
49-
--
101+
--! @brief Add validation constraint to encrypted column
102+
--!
103+
--! Adds a CHECK constraint to ensure column values conform to encrypted data
104+
--! structure. Constraint uses eql_v2.check_encrypted to validate format.
105+
--! Called automatically by eql_v2.add_column.
106+
--!
107+
--! @param table_name TEXT Name of table containing the column
108+
--! @param column_name TEXT Name of column to constrain
109+
--! @return Void
110+
--!
111+
--! @example
112+
--! -- Manually add constraint (normally done by add_column)
113+
--! SELECT eql_v2.add_encrypted_constraint('users', 'encrypted_email');
114+
--!
115+
--! -- Resulting constraint:
116+
--! -- ALTER TABLE users ADD CONSTRAINT eql_v2_encrypted_check_encrypted_email
117+
--! -- CHECK (eql_v2.check_encrypted(encrypted_email));
118+
--!
119+
--! @see eql_v2.add_column
120+
--! @see eql_v2.remove_encrypted_constraint
50121
CREATE FUNCTION eql_v2.add_encrypted_constraint(table_name TEXT, column_name TEXT)
51122
RETURNS void
52123
AS $$
@@ -55,13 +126,22 @@ AS $$
55126
END;
56127
$$ LANGUAGE plpgsql;
57128

58-
59-
--
60-
-- Removes the eql_v2.check_encrypted constraint from the column_name in table_name
61-
--
62-
-- Executes the ALTER TABLE statement
63-
-- `ALTER TABLE {table_name} DROP CONSTRAINT eql_v2_encrypted_check_{column_name}`
64-
--
129+
--! @brief Remove validation constraint from encrypted column
130+
--!
131+
--! Removes the CHECK constraint that validates encrypted data structure.
132+
--! Called automatically by eql_v2.remove_column. Uses IF EXISTS to avoid
133+
--! errors if constraint doesn't exist.
134+
--!
135+
--! @param table_name TEXT Name of table containing the column
136+
--! @param column_name TEXT Name of column to unconstrain
137+
--! @return Void
138+
--!
139+
--! @example
140+
--! -- Manually remove constraint (normally done by remove_column)
141+
--! SELECT eql_v2.remove_encrypted_constraint('users', 'encrypted_email');
142+
--!
143+
--! @see eql_v2.remove_column
144+
--! @see eql_v2.add_encrypted_constraint
65145
CREATE FUNCTION eql_v2.remove_encrypted_constraint(table_name TEXT, column_name TEXT)
66146
RETURNS void
67147
AS $$
@@ -70,7 +150,21 @@ AS $$
70150
END;
71151
$$ LANGUAGE plpgsql;
72152

73-
153+
--! @brief Extract metadata from encrypted JSONB value
154+
--!
155+
--! Extracts index terms (i) and version (v) from a raw JSONB encrypted value.
156+
--! Returns metadata object containing searchable index terms without ciphertext.
157+
--!
158+
--! @param val JSONB Raw encrypted value
159+
--! @return JSONB Metadata object with 'i' (index terms) and 'v' (version) fields
160+
--!
161+
--! @example
162+
--! -- Extract metadata to inspect index terms
163+
--! SELECT eql_v2.meta_data('{"c":"...","i":{"unique":"abc123"},"v":1}'::jsonb);
164+
--! -- Returns: {"i":{"unique":"abc123"},"v":1}
165+
--!
166+
--! @see eql_v2.meta_data(eql_v2_encrypted)
167+
--! @see eql_v2.ciphertext
74168
CREATE FUNCTION eql_v2.meta_data(val jsonb)
75169
RETURNS jsonb
76170
IMMUTABLE STRICT PARALLEL SAFE
@@ -83,7 +177,22 @@ AS $$
83177
END;
84178
$$ LANGUAGE plpgsql;
85179

86-
180+
--! @brief Extract metadata from encrypted column value
181+
--!
182+
--! Extracts index terms and version from an encrypted column value.
183+
--! Convenience overload that unwraps eql_v2_encrypted type and
184+
--! delegates to JSONB version.
185+
--!
186+
--! @param val eql_v2_encrypted Encrypted column value
187+
--! @return JSONB Metadata object with 'i' (index terms) and 'v' (version) fields
188+
--!
189+
--! @example
190+
--! -- Inspect index terms for encrypted column
191+
--! SELECT user_id, eql_v2.meta_data(encrypted_email) as email_metadata
192+
--! FROM users;
193+
--!
194+
--! @see eql_v2.meta_data(jsonb)
195+
--! @see eql_v2.ciphertext
87196
CREATE FUNCTION eql_v2.meta_data(val eql_v2_encrypted)
88197
RETURNS jsonb
89198
IMMUTABLE STRICT PARALLEL SAFE

src/operators/<.sql

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22
-- REQUIRE: src/encrypted/types.sql
33
-- REQUIRE: src/operators/compare.sql
44

5-
6-
-- Operators for < less than comparisons of eql_v2_encrypted types
7-
--
8-
-- Uses `eql_v2.compare` for the actual comparison logic.
9-
--
10-
--
5+
--! @brief Less-than comparison helper for encrypted values
6+
--! @internal
7+
--!
8+
--! Internal helper that delegates to eql_v2.compare for less-than testing.
9+
--! Returns true if first value is less than second using ORE comparison.
10+
--!
11+
--! @param a eql_v2_encrypted First encrypted value
12+
--! @param b eql_v2_encrypted Second encrypted value
13+
--! @return Boolean True if a < b (compare result = -1)
14+
--!
15+
--! @see eql_v2.compare
16+
--! @see eql_v2."<"
1117
CREATE FUNCTION eql_v2.lt(a eql_v2_encrypted, b eql_v2_encrypted)
1218
RETURNS boolean
1319
AS $$
@@ -16,8 +22,26 @@ AS $$
1622
END;
1723
$$ LANGUAGE plpgsql;
1824

19-
20-
25+
--! @brief Less-than operator for encrypted values
26+
--!
27+
--! Implements the < operator for comparing two encrypted values using Order-Revealing
28+
--! Encryption (ORE) index terms. Enables range queries and sorting without decryption.
29+
--! Requires 'ore' index configuration on the column.
30+
--!
31+
--! @param a eql_v2_encrypted Left operand
32+
--! @param b eql_v2_encrypted Right operand
33+
--! @return Boolean True if a is less than b
34+
--!
35+
--! @example
36+
--! -- Range query on encrypted timestamps
37+
--! SELECT * FROM events
38+
--! WHERE encrypted_timestamp < '2024-01-01'::timestamp::text::eql_v2_encrypted;
39+
--!
40+
--! -- Compare encrypted numeric columns
41+
--! SELECT * FROM products WHERE encrypted_price < encrypted_discount_price;
42+
--!
43+
--! @see eql_v2.compare
44+
--! @see eql_v2.add_search_config
2145
CREATE FUNCTION eql_v2."<"(a eql_v2_encrypted, b eql_v2_encrypted)
2246
RETURNS boolean
2347
AS $$
@@ -36,8 +60,19 @@ CREATE OPERATOR <(
3660
JOIN = scalarltjoinsel
3761
);
3862

39-
40-
63+
--! @brief Less-than operator for encrypted value and JSONB
64+
--!
65+
--! Overload of < operator accepting JSONB on the right side. Automatically
66+
--! casts JSONB to eql_v2_encrypted for ORE comparison.
67+
--!
68+
--! @param a eql_v2_encrypted Left operand (encrypted value)
69+
--! @param b JSONB Right operand (will be cast to eql_v2_encrypted)
70+
--! @return Boolean True if a < b
71+
--!
72+
--! @example
73+
--! SELECT * FROM events WHERE encrypted_age < '18'::int::text::jsonb;
74+
--!
75+
--! @see eql_v2."<"(eql_v2_encrypted, eql_v2_encrypted)
4176
CREATE FUNCTION eql_v2."<"(a eql_v2_encrypted, b jsonb)
4277
RETURNS boolean
4378
AS $$
@@ -56,8 +91,19 @@ CREATE OPERATOR <(
5691
JOIN = scalarltjoinsel
5792
);
5893

59-
60-
94+
--! @brief Less-than operator for JSONB and encrypted value
95+
--!
96+
--! Overload of < operator accepting JSONB on the left side. Automatically
97+
--! casts JSONB to eql_v2_encrypted for ORE comparison.
98+
--!
99+
--! @param a JSONB Left operand (will be cast to eql_v2_encrypted)
100+
--! @param b eql_v2_encrypted Right operand (encrypted value)
101+
--! @return Boolean True if a < b
102+
--!
103+
--! @example
104+
--! SELECT * FROM events WHERE '2023-01-01'::date::text::jsonb < encrypted_date;
105+
--!
106+
--! @see eql_v2."<"(eql_v2_encrypted, eql_v2_encrypted)
61107
CREATE FUNCTION eql_v2."<"(a jsonb, b eql_v2_encrypted)
62108
RETURNS boolean
63109
AS $$

0 commit comments

Comments
 (0)