This document provides a comprehensive reference for all EQL (Encrypt Query Language) functions available for querying encrypted data in PostgreSQL.
- Configuration Functions
- Query Functions
- Index Term Extraction Functions
- JSONB Path Functions
- Array Functions
- Helper Functions
- Aggregate Functions
- Utility Functions
These functions manage encrypted column configurations. See Configuration Tutorial for detailed usage.
Initialize a column for encryption/decryption.
eql_v2.add_column(
table_name text,
column_name text,
cast_as text DEFAULT 'text',
migrating boolean DEFAULT false
) RETURNS jsonbExample:
SELECT eql_v2.add_column('users', 'encrypted_email', 'text');Add a searchable index to an encrypted column.
eql_v2.add_search_config(
table_name text,
column_name text,
index_name text, -- 'unique', 'match', 'ore', 'ste_vec'
cast_as text DEFAULT 'text',
opts jsonb DEFAULT '{}',
migrating boolean DEFAULT false
) RETURNS jsonbSupported index types:
unique- Exact equality (uses hmac_256 or blake3)match- Full-text search (uses bloom_filter)ore- Range queries and ordering (uses ore_block_u64_8_256)ste_vec- JSONB containment queries (uses structured encryption)
Example:
SELECT eql_v2.add_search_config('users', 'encrypted_email', 'unique', 'text');
SELECT eql_v2.add_search_config('docs', 'encrypted_content', 'match', 'text');
SELECT eql_v2.add_search_config('events', 'encrypted_data', 'ste_vec', 'jsonb', '{"prefix": "events/encrypted_data"}');Remove column configuration completely.
eql_v2.remove_column(
table_name text,
column_name text,
migrating boolean DEFAULT false
) RETURNS jsonbRemove a specific search index (preserves column configuration).
eql_v2.remove_search_config(
table_name text,
column_name text,
index_name text,
migrating boolean DEFAULT false
) RETURNS jsonbModify an existing search index configuration.
eql_v2.modify_search_config(
table_name text,
column_name text,
index_name text,
cast_as text DEFAULT 'text',
opts jsonb DEFAULT '{}',
migrating boolean DEFAULT false
) RETURNS jsonbView current configuration in tabular format.
eql_v2.config() RETURNS TABLE (
state eql_v2_configuration_state,
relation text,
col_name text,
decrypts_as text,
indexes jsonb
)Example:
SELECT * FROM eql_v2.config();Transition pending configuration to encrypting state.
eql_v2.migrate_config() RETURNS booleanDescription:
- Validates that all configured columns exist with
eql_v2_encryptedtype - Marks the pending configuration as 'encrypting'
- Required before activating a new configuration
Raises exception if:
- An encryption is already in progress
- No pending configuration exists
- Some pending columns don't have encrypted targets
Example:
-- Add configuration changes
SELECT eql_v2.add_search_config('users', 'email', 'unique', 'text', migrating => true);
-- Validate and migrate
SELECT eql_v2.migrate_config();
-- After re-encrypting data, activate
SELECT eql_v2.activate_config();Activate an encrypting configuration.
eql_v2.activate_config() RETURNS booleanDescription:
- Moves 'encrypting' configuration to 'active' state
- Marks previous 'active' configuration as 'inactive'
- Should be called after data has been re-encrypted with new index terms
Raises exception if:
- No encrypting configuration exists
Example:
SELECT eql_v2.activate_config();Discard pending configuration without activating.
eql_v2.discard() RETURNS booleanDescription:
- Deletes the pending configuration
- Use when you want to abandon configuration changes
Raises exception if:
- No pending configuration exists
Example:
SELECT eql_v2.discard();Reload active configuration (no-op for compatibility).
eql_v2.reload_config() RETURNS voidDescription:
- Placeholder function for configuration reload
- Currently has no effect (configuration is loaded automatically)
EQL overloads standard PostgreSQL operators to work directly on eql_v2_encrypted columns. Use these whenever possible.
-- Exact match (uses 'unique' index: hmac_256 or blake3)
SELECT * FROM users WHERE encrypted_email = $1::eql_v2_encrypted;
SELECT * FROM users WHERE encrypted_email = $1::jsonb;
-- Not equal
SELECT * FROM users WHERE encrypted_email <> $1::eql_v2_encrypted;-- Case-sensitive LIKE (uses 'match' index: bloom_filter)
SELECT * FROM docs WHERE encrypted_content ~~ $1::eql_v2_encrypted;
SELECT * FROM docs WHERE encrypted_content LIKE $1::eql_v2_encrypted;
-- Case-insensitive ILIKE
SELECT * FROM docs WHERE encrypted_content ~~* $1::eql_v2_encrypted;
SELECT * FROM docs WHERE encrypted_content ILIKE $1::eql_v2_encrypted;-- Uses 'ore' index: ore_block_u64_8_256
SELECT * FROM events WHERE encrypted_date < $1::eql_v2_encrypted;
SELECT * FROM events WHERE encrypted_date <= $1::eql_v2_encrypted;
SELECT * FROM events WHERE encrypted_date > $1::eql_v2_encrypted;
SELECT * FROM events WHERE encrypted_date >= $1::eql_v2_encrypted;
-- Ordering
SELECT * FROM events ORDER BY encrypted_date DESC;
SELECT * FROM events ORDER BY encrypted_date ASC;-- Uses 'ste_vec' index
SELECT * FROM users WHERE encrypted_data @> $1::eql_v2_encrypted;
SELECT * FROM users WHERE encrypted_data <@ $1::eql_v2_encrypted;-- Extract field by selector hash (returns eql_v2_encrypted)
SELECT encrypted_json->'abc123...' FROM users;
SELECT encrypted_json->encrypted_selector FROM users;
-- Extract field by array index (returns eql_v2_encrypted)
SELECT encrypted_json->0 FROM users;
-- Extract field as ciphertext (returns text)
SELECT encrypted_json->>'abc123...' FROM users;
SELECT encrypted_json->>encrypted_selector FROM users;For environments that don't support custom operators (like Supabase), use these function versions:
Equality comparison.
eql_v2.eq(a eql_v2_encrypted, b eql_v2_encrypted) RETURNS booleanExample:
SELECT * FROM users WHERE eql_v2.eq(encrypted_email, $1::eql_v2_encrypted);Not-equal comparison.
eql_v2.neq(a eql_v2_encrypted, b eql_v2_encrypted) RETURNS booleanPattern matching (case-sensitive).
eql_v2.like(a eql_v2_encrypted, b eql_v2_encrypted) RETURNS booleanExample:
SELECT * FROM docs WHERE eql_v2.like(encrypted_content, $1::eql_v2_encrypted);Pattern matching (case-insensitive).
eql_v2.ilike(a eql_v2_encrypted, b eql_v2_encrypted) RETURNS booleanExample:
SELECT * FROM docs WHERE eql_v2.ilike(encrypted_content, $1::eql_v2_encrypted);Less than comparison.
eql_v2.lt(a eql_v2_encrypted, b eql_v2_encrypted) RETURNS booleanExample:
SELECT * FROM events WHERE eql_v2.lt(encrypted_date, $1::eql_v2_encrypted);Less than or equal comparison.
eql_v2.lte(a eql_v2_encrypted, b eql_v2_encrypted) RETURNS booleanExample:
SELECT * FROM events WHERE eql_v2.lte(encrypted_date, $1::eql_v2_encrypted);Greater than comparison.
eql_v2.gt(a eql_v2_encrypted, b eql_v2_encrypted) RETURNS booleanExample:
SELECT * FROM events WHERE eql_v2.gt(encrypted_date, $1::eql_v2_encrypted);Greater than or equal comparison.
eql_v2.gte(a eql_v2_encrypted, b eql_v2_encrypted) RETURNS booleanExample:
SELECT * FROM events WHERE eql_v2.gte(encrypted_date, $1::eql_v2_encrypted);These functions extract specific index terms from encrypted values. Typically used internally by operators, but available for advanced use cases.
Extract HMAC-256 unique index term.
eql_v2.hmac_256(val eql_v2_encrypted) RETURNS eql_v2.hmac_256
eql_v2.hmac_256(val jsonb) RETURNS eql_v2.hmac_256Extract Blake3 unique index term.
eql_v2.blake3(val eql_v2_encrypted) RETURNS eql_v2.blake3
eql_v2.blake3(val jsonb) RETURNS eql_v2.blake3Extract bloom filter match index term.
eql_v2.bloom_filter(val eql_v2_encrypted) RETURNS eql_v2.bloom_filter
eql_v2.bloom_filter(val jsonb) RETURNS eql_v2.bloom_filterExtract ORE (Order-Revealing Encryption) index term.
eql_v2.ore_block_u64_8_256(val eql_v2_encrypted) RETURNS eql_v2.ore_block_u64_8_256
eql_v2.ore_block_u64_8_256(val jsonb) RETURNS eql_v2.ore_block_u64_8_256Extract structured encryption vector array.
eql_v2.ste_vec(val eql_v2_encrypted) RETURNS eql_v2_encrypted[]
eql_v2.ste_vec(val jsonb) RETURNS eql_v2_encrypted[]Functions for querying encrypted JSONB data using selector hashes.
Returns all encrypted elements matching a selector.
eql_v2.jsonb_path_query(val eql_v2_encrypted, selector text) RETURNS SETOF eql_v2_encrypted
eql_v2.jsonb_path_query(val eql_v2_encrypted, selector eql_v2_encrypted) RETURNS SETOF eql_v2_encrypted
eql_v2.jsonb_path_query(val jsonb, selector text) RETURNS SETOF eql_v2_encryptedExample:
SELECT eql_v2.jsonb_path_query(encrypted_json, 'abc123...') FROM users;Returns the first encrypted element matching a selector.
eql_v2.jsonb_path_query_first(val eql_v2_encrypted, selector text) RETURNS eql_v2_encrypted
eql_v2.jsonb_path_query_first(val eql_v2_encrypted, selector eql_v2_encrypted) RETURNS eql_v2_encrypted
eql_v2.jsonb_path_query_first(val jsonb, selector text) RETURNS eql_v2_encryptedChecks if any element matches a selector.
eql_v2.jsonb_path_exists(val eql_v2_encrypted, selector text) RETURNS boolean
eql_v2.jsonb_path_exists(val eql_v2_encrypted, selector eql_v2_encrypted) RETURNS boolean
eql_v2.jsonb_path_exists(val jsonb, selector text) RETURNS booleanExample:
SELECT * FROM users
WHERE eql_v2.jsonb_path_exists(encrypted_json, 'email_selector');Functions for working with encrypted arrays.
Returns the length of an encrypted array.
eql_v2.jsonb_array_length(val eql_v2_encrypted) RETURNS integer
eql_v2.jsonb_array_length(val jsonb) RETURNS integerExample:
SELECT eql_v2.jsonb_array_length(encrypted_array) FROM users;Returns each array element as an encrypted value.
eql_v2.jsonb_array_elements(val eql_v2_encrypted) RETURNS SETOF eql_v2_encrypted
eql_v2.jsonb_array_elements(val jsonb) RETURNS SETOF eql_v2_encryptedExample:
SELECT eql_v2.jsonb_array_elements(
eql_v2.jsonb_path_query(encrypted_json, 'array_selector')
) FROM users;Returns each array element's ciphertext as text.
eql_v2.jsonb_array_elements_text(val eql_v2_encrypted) RETURNS SETOF text
eql_v2.jsonb_array_elements_text(val jsonb) RETURNS SETOF textUtility functions for working with encrypted data.
Extract ciphertext from encrypted value.
eql_v2.ciphertext(val eql_v2_encrypted) RETURNS text
eql_v2.ciphertext(val jsonb) RETURNS textExtract metadata (table/column identifiers and version).
eql_v2.meta_data(val eql_v2_encrypted) RETURNS jsonb
eql_v2.meta_data(val jsonb) RETURNS jsonbExtract selector hash from encrypted value.
eql_v2.selector(val eql_v2_encrypted) RETURNS textCheck if value represents an encrypted array.
eql_v2.is_ste_vec_array(val eql_v2_encrypted) RETURNS booleanCheck if value is a single ste_vec element.
eql_v2.is_ste_vec_value(val eql_v2_encrypted) RETURNS booleanConvert ste_vec array with single element to regular encrypted value.
eql_v2.to_ste_vec_value(val eql_v2_encrypted) RETURNS eql_v2_encryptedCheck if all ste_vec terms in b exist in a (backs the @> operator).
eql_v2.ste_vec_contains(a eql_v2_encrypted, b eql_v2_encrypted) RETURNS booleanCheck if value contains hmac_256 index term.
eql_v2.has_hmac_256(val eql_v2_encrypted) RETURNS booleanCheck if value contains blake3 index term.
eql_v2.has_blake3(val eql_v2_encrypted) RETURNS booleanCheck if value contains bloom_filter index term.
eql_v2.has_bloom_filter(val eql_v2_encrypted) RETURNS booleanCheck if value contains ore index term.
eql_v2.has_ore_block_u64_8_256(val eql_v2_encrypted) RETURNS booleanAggregate function for grouping encrypted values (returns first non-null value in group).
eql_v2.grouped_value(jsonb) RETURNS jsonbExample:
SELECT eql_v2.grouped_value(
eql_v2.jsonb_path_query_first(encrypted_json, 'color_selector')::jsonb
) AS color,
COUNT(*)
FROM products
GROUP BY eql_v2.jsonb_path_query_first(encrypted_json, 'color_selector');Returns the minimum encrypted value in a set (requires ore index for ordering).
eql_v2.min(eql_v2_encrypted) RETURNS eql_v2_encryptedExample:
SELECT eql_v2.min(encrypted_date) FROM events;
SELECT eql_v2.min(encrypted_price) FROM products WHERE category = 'electronics';Returns the maximum encrypted value in a set (requires ore index for ordering).
eql_v2.max(eql_v2_encrypted) RETURNS eql_v2_encryptedExample:
SELECT eql_v2.max(encrypted_date) FROM events;
SELECT eql_v2.max(encrypted_price) FROM products WHERE category = 'electronics';Get the installed EQL version.
eql_v2.version() RETURNS textExample:
SELECT eql_v2.version();
-- Returns version string (e.g., '2.1.8')Convert jsonb or text to eql_v2_encrypted type.
eql_v2.to_encrypted(data jsonb) RETURNS eql_v2_encrypted
eql_v2.to_encrypted(data text) RETURNS eql_v2_encryptedExample:
-- Convert jsonb payload to encrypted type
SELECT eql_v2.to_encrypted('{"v":2,"k":"pt","p":"plaintext"}'::jsonb);
-- Convert text payload to encrypted type
SELECT eql_v2.to_encrypted('{"v":2,"k":"pt","p":"plaintext"}');Convert eql_v2_encrypted to jsonb.
eql_v2.to_jsonb(e eql_v2_encrypted) RETURNS jsonbExample:
SELECT eql_v2.to_jsonb(encrypted_column) FROM users;Validate encrypted payload structure (used in constraints).
eql_v2.check_encrypted(val jsonb) RETURNS boolean
eql_v2.check_encrypted(val eql_v2_encrypted) RETURNS booleanDescription:
- Validates that encrypted value has required fields (
v,c,i) - Checks that version is
2and identifier contains table (t) and column (c) fields - Returns true if valid, raises exception if invalid
- Automatically added as constraint when using
eql_v2.add_column()
Example:
SELECT eql_v2.check_encrypted('{"v":2,"c":"ciphertext","i":{"t":"users","c":"email"}}'::jsonb);
-- Returns: true
SELECT eql_v2.check_encrypted('{"invalid":"structure"}'::jsonb);
-- Raises exception: 'Encrypted column missing version (v) field'- EQL Configuration Guide - How to set up encrypted columns
- Database Indexes - PostgreSQL B-tree index creation and usage
- JSON/JSONB Support - Working with encrypted JSON data
- Index Configuration - Index types and configuration options
- Payload Format - EQL data format specification