From 04b0f322e01695c24ad7ae1181e1de7cc938a48e Mon Sep 17 00:00:00 2001 From: Toby Hede Date: Mon, 1 Jun 2026 11:09:42 +1000 Subject: [PATCH 1/6] feat(encrypted-domain): move int4 domain family into a new eql_v3 schema Introduce a separate eql_v3 schema for the encrypted-domain type families and move the int4 family into it, dropping the redundant version prefix: eql_v3.int4{,_eq,_ord,_ord_ore}, with extractors/wrappers/aggregates (eql_v3.eq_term, ord_term, eq/neq/lt/lte/gt/gte, min/max) also in eql_v3. The core index-term types (eql_v2.hmac_256, eql_v2.ore_block_u64_8_256) stay in eql_v2 and are referenced cross-schema. eql_v2 is unchanged. - codegen: DOMAIN_SCHEMA/CORE_SCHEMA in templates.py; schema-qualified domain_name; schema-v3 REQUIRE edges in generate.py - new src/schema-v3.sql; blocker helper moved to eql_v3 - pin_search_path: pin loop + structural skip broadened to eql_v3 - lints: operator/blocker/domain_over_domain/domain_opclass recognisers extended to eql_v3 - splinter: scope + eql_v3 allowlist rows - SQLx harness + family/lint tests + codegen tests + reference baseline - uninstallers drop eql_v3; docs, CHANGELOG, CLAUDE.md updated Resolves the open PR #239 review thread asking to move the family to eql_v3. The generator/test-quality hardening that was previously bundled here (_sql_str, brief disambiguation, placeholder/aggregate rationale comments, assert_index_scan_uses) now lands separately on v3-domain-type-int4, since it is schema-independent and useful to every scalar type. --- CHANGELOG.md | 4 +- CLAUDE.md | 6 +- docs/reference/encrypted-domain-generator.md | 12 +- .../encrypted-domain-implementation-spec.md | 25 +- docs/reference/eql-functions.md | 40 +- docs/reference/sql-support.md | 18 +- src/encrypted_domain/functions.sql | 10 +- src/lint/lints.sql | 29 +- src/schema-v3.sql | 22 + tasks/codegen/generate.py | 7 +- tasks/codegen/templates.py | 53 ++- tasks/codegen/test_generate.py | 16 +- tasks/codegen/test_templates.py | 110 ++--- tasks/pin_search_path.sql | 17 +- tasks/test/splinter.sh | 33 +- tasks/uninstall-protect.sql | 1 + tasks/uninstall.sql | 5 + .../reference/int4/int4_eq_functions.sql | 389 +++++++++--------- .../reference/int4/int4_eq_operators.sql | 178 ++++---- .../codegen/reference/int4/int4_functions.sql | 383 ++++++++--------- .../codegen/reference/int4/int4_operators.sql | 178 ++++---- .../reference/int4/int4_ord_aggregates.sql | 54 +-- .../reference/int4/int4_ord_functions.sql | 389 +++++++++--------- .../reference/int4/int4_ord_operators.sql | 178 ++++---- .../int4/int4_ord_ore_aggregates.sql | 54 +-- .../reference/int4/int4_ord_ore_functions.sql | 389 +++++++++--------- .../reference/int4/int4_ord_ore_operators.sql | 178 ++++---- tests/codegen/reference/int4/int4_types.sql | 18 +- tests/sqlx/src/matrix.rs | 74 ++-- tests/sqlx/src/scalar_domains.rs | 13 +- .../encrypted_domain/family/inlinability.rs | 112 ++--- .../family/jsonb_operator_surface.rs | 2 +- .../encrypted_domain/family/mutations.rs | 54 +-- .../tests/encrypted_domain/family/support.rs | 76 ++-- tests/sqlx/tests/lint_tests.rs | 18 +- 35 files changed, 1621 insertions(+), 1524 deletions(-) create mode 100644 src/schema-v3.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index e3d45c0a..00215fd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,8 +22,8 @@ Each entry that ships in a published release links to the PR that introduced it. ### Added -- **`eql_v2_int4` encrypted-domain type family.** Four jsonb-backed domains for encrypted `int4` columns: `eql_v2_int4` (storage-only), `eql_v2_int4_eq` (`=` / `<>` via HMAC), and `eql_v2_int4_ord` / `eql_v2_int4_ord_ore` (also `<` `<=` `>` `>=` via ORE block terms). Supported comparisons resolve to inlinable wrappers; the native `jsonb` operator surface reachable through domain fallback is blocked (raises rather than silently mis-resolving). Each domain's `CHECK` requires the EQL envelope (`v`, `i`), the ciphertext (`c`), and the variant's index term(s), and pins the payload version (`VALUE->>'v' = '2'`, matching `eql_v2._encrypted_check_v`) — so a missing key or wrong-version payload is rejected on insert or cast rather than surfacing later at query time. Index via a functional index on the `eql_v2.eq_term` / `eql_v2.ord_term` extractors, not an operator class on the domain. Why: a type-safe, per-capability encrypted integer column instead of the untyped `eql_v2_encrypted`. This is the reference scalar implementation for the generated domain family. ([#239](https://github.com/cipherstash/encrypt-query-language/pull/239), supersedes [#225](https://github.com/cipherstash/encrypt-query-language/pull/225)) -- **Per-domain `MIN` / `MAX` aggregates for the encrypted-domain family.** `eql_v2.min(eql_v2__ord)` / `eql_v2.max(eql_v2__ord)` (and the `_ord_ore` twin) are generated for every ord-capable scalar variant, giving type-safe extrema on domain-typed columns — comparison routes through the variant's `<` / `>` operator (ORE block term, no decryption). The aggregates are declared `PARALLEL = SAFE` with a combine function (the state function itself — min/max are associative), so PostgreSQL can use partial/parallel aggregation on large `GROUP BY` workloads. Why: the new domain types previously had no equivalent of the composite-type aggregates. The existing `eql_v2.min(eql_v2_encrypted)` / `eql_v2.max(eql_v2_encrypted)` aggregates are **retained** and continue to work on `eql_v2_encrypted` columns; the per-domain aggregates are additive and coexist with them. ([#239](https://github.com/cipherstash/encrypt-query-language/pull/239)) +- **`eql_v3` encrypted-domain schema, with the `int4` family as its first member.** Encrypted-domain type families now live in a new, additional `eql_v3` schema (the existing `eql_v2` schema is unchanged — it keeps the core types/operators and stays the documented public API). Four jsonb-backed domains for encrypted `int4` columns: `eql_v3.int4` (storage-only), `eql_v3.int4_eq` (`=` / `<>` via HMAC), and `eql_v3.int4_ord` / `eql_v3.int4_ord_ore` (also `<` `<=` `>` `>=` via ORE block terms). Supported comparisons resolve to inlinable wrappers; the native `jsonb` operator surface reachable through domain fallback is blocked (raises rather than silently mis-resolving). Each domain's `CHECK` requires the EQL envelope (`v`, `i`), the ciphertext (`c`), and the variant's index term(s), and pins the payload version (`VALUE->>'v' = '2'`, matching `eql_v2._encrypted_check_v`) — so a missing key or wrong-version payload is rejected on insert or cast rather than surfacing later at query time. Index via a functional index on the `eql_v3.eq_term` / `eql_v3.ord_term` extractors, not an operator class on the domain. The extractors still return the core `eql_v2.hmac_256` / `eql_v2.ore_block_u64_8_256` index-term types, which remain in `eql_v2` and are referenced cross-schema. Why: a type-safe, per-capability encrypted integer column instead of the untyped `eql_v2_encrypted`, namespaced under its own schema. This is the reference scalar implementation for the generated domain family. ([#239](https://github.com/cipherstash/encrypt-query-language/pull/239), supersedes [#225](https://github.com/cipherstash/encrypt-query-language/pull/225)) +- **Per-domain `MIN` / `MAX` aggregates for the encrypted-domain family.** `eql_v3.min(eql_v3._ord)` / `eql_v3.max(eql_v3._ord)` (and the `_ord_ore` twin) are generated for every ord-capable scalar variant, giving type-safe extrema on domain-typed columns — comparison routes through the variant's `<` / `>` operator (ORE block term, no decryption). The aggregates are declared `PARALLEL = SAFE` with a combine function (the state function itself — min/max are associative), so PostgreSQL can use partial/parallel aggregation on large `GROUP BY` workloads. Why: the new domain types previously had no equivalent of the composite-type aggregates. The existing `eql_v2.min(eql_v2_encrypted)` / `eql_v2.max(eql_v2_encrypted)` aggregates are **retained** and continue to work on `eql_v2_encrypted` columns; the per-domain aggregates are additive and coexist with them. ([#239](https://github.com/cipherstash/encrypt-query-language/pull/239)) ## [2.3.1] — 2026-05-21 diff --git a/CLAUDE.md b/CLAUDE.md index 361fd31b..1328a8b0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -50,7 +50,7 @@ This project uses `mise` for task management. Common commands: This is the **Encrypt Query Language (EQL)** - a PostgreSQL extension for searchable encryption. Key architectural components: ### Core Structure -- **Schema**: All EQL functions/types are in `eql_v2` PostgreSQL schema +- **Schema**: Core EQL functions/types are in the `eql_v2` PostgreSQL schema. The encrypted-domain type families (`int4` and future scalar domains) live in a separate `eql_v3` schema (see below); they reuse the core `eql_v2` index-term types cross-schema. `eql_v2` is unchanged and remains the documented public API. - **Main Type**: `eql_v2_encrypted` - composite type for encrypted columns (stored as JSONB) - **Configuration**: `eql_v2_configuration` table tracks encryption configs - **Index Types**: Various encrypted index types (blake3, hmac_256, bloom_filter, ore variants) @@ -75,7 +75,7 @@ This is the **Encrypt Query Language (EQL)** - a PostgreSQL extension for search ### Encrypted-Domain Types -`src/encrypted_domain/` holds **encrypted-domain type families** — jsonb-backed PostgreSQL domains, one domain per operator/index capability (`eql_v2_` storage-only, `eql_v2__eq`, `eql_v2__ord`). `eql_v2_int4` (PR #225) is the reference scalar implementation; future scalar types such as `int8`, `bool`, `date`, `float`, `numeric`, and `timestamp` follow this materializer pattern. `jsonb` needs a separate design and is out of scope for the scalar materializer. +`src/encrypted_domain/` holds **encrypted-domain type families** — jsonb-backed PostgreSQL domains in the **`eql_v3` schema**, one domain per operator/index capability (`eql_v3.` storage-only, `eql_v3._eq`, `eql_v3._ord`). The schema qualifier replaces the old version-prefixed name, so the domains are `eql_v3.int4`, `eql_v3.int4_eq`, `eql_v3.int4_ord`, `eql_v3.int4_ord_ore` — created in `eql_v3`, not `public`. Their extractors/wrappers/aggregates (`eql_v3.eq_term`, `eql_v3.ord_term`, `eql_v3.eq`/`lt`/…, `eql_v3.min`/`max`) also live in `eql_v3`, but the index-term types they return and construct (`eql_v2.hmac_256`, `eql_v2.ore_block_u64_8_256`) stay in `eql_v2` and are referenced cross-schema. `eql_v3.int4` (PR #239, supersedes #225) is the reference scalar implementation; future scalar types such as `int8`, `bool`, `date`, `float`, `numeric`, and `timestamp` follow this materializer pattern. `jsonb` needs a separate design and is out of scope for the scalar materializer. Adding a scalar encrypted-domain type is generated from a minimal manifest at `tasks/codegen/types/.toml`: the filename supplies ``, and the `[domain]` table maps each generated domain name to the fixed index terms it carries. Example: `int4_eq = ["hm"]`, `int4_ord = ["ore"]`. Term capabilities are fixed in `tasks/codegen/terms.py`: `hm` provides equality, and `ore` provides equality plus ordering. `mise run build` regenerates the scalar SQL surface into `src/encrypted_domain//` from every manifest at the start of every build; that surface includes supported comparison wrappers plus blockers for native `jsonb` operators that would otherwise be reachable through domain fallback. Use `mise run codegen:domain ` to refresh a single type manually while iterating on its manifest, or `mise run codegen:domain:all` to regenerate every type at once (the same enumeration `mise run build` uses). The generated `*_types.sql` / `*_functions.sql` / `*_operators.sql` files are gitignored and never committed — the TOML manifest plus `tasks/codegen/terms.py` are the source of truth. Generated files carry an `AUTO-GENERATED — DO NOT EDIT` header; change the manifest or term catalog and rebuild, never hand-edit. Hand-written SQL beyond the fixed surface goes in `src/encrypted_domain//_extensions.sql` with no auto-generated header and explicit `-- REQUIRE:` edges — that file IS committed. `text` and `jsonb` are out of scope for this scalar materializer. @@ -260,7 +260,7 @@ The entry under `Changed` / `Deprecated` should cross-link to the `U-NNN`. See ` ### Versioning -The `eql_v2` PostgreSQL schema name is part of the public API and is **independent of the EQL release version**. Major-version bumps to EQL do not rename the schema. When deciding on a version bump: +The `eql_v2` PostgreSQL schema name is part of the public API and is **independent of the EQL release version**. Major-version bumps to EQL do not rename the schema. The `eql_v3` schema is **not** a rename of `eql_v2`: it is a separate, additional schema introduced to namespace the encrypted-domain type families. Both schemas coexist; `eql_v2` keeps the core types/operators and is unchanged. Adding a new schema for a new surface is additive, not a public-API break. When deciding on a version bump: - **Patch (`2.3.x`)** — bug fixes, no behaviour changes - **Minor (`2.x.0`)** — additive changes, behaviour changes that don't break the public API (signatures, schema name, payload format, operator names) diff --git a/docs/reference/encrypted-domain-generator.md b/docs/reference/encrypted-domain-generator.md index 9b502690..bb6252be 100644 --- a/docs/reference/encrypted-domain-generator.md +++ b/docs/reference/encrypted-domain-generator.md @@ -7,7 +7,7 @@ The contract those outputs must satisfy is in [`encrypted-domain-implementation-spec.md`](./encrypted-domain-implementation-spec.md); this file describes the machine that produces them. -The reference type is `eql_v2_int4` (PR #239). `text` and `jsonb` are +The reference type is `eql_v3.int4` (PR #239). `text` and `jsonb` are outside scope. ## 1. Why a generator @@ -245,7 +245,7 @@ operators are always blockers. The table above covers `_functions.sql` only. Ordered domains additionally emit `_aggregates.sql` — two state functions (`min_sfunc`, `max_sfunc`) and two `CREATE AGGREGATE` declarations -(`eql_v2.min`, `eql_v2.max`). Each aggregate declares +(`eql_v3.min`, `eql_v3.max`). Each aggregate declares `combinefunc = ` and `parallel = safe`: min/max are associative, so the state function doubles as the combine function, enabling partial and parallel aggregation on large `GROUP BY` ORE workloads with no decryption. @@ -280,13 +280,13 @@ incorrect SQL unreachable. Invariants encoded in code: (`templates.py:46`), which doubles embedded single quotes. Today's catalog strings are all quote-free so it is a no-op, but it guarantees a future quote-bearing catalog string cannot break out of its literal. -- **No domain-over-domain.** Every domain is `CREATE DOMAIN ... AS - jsonb`, never `AS ` (`templates.py:72`). PostgreSQL +- **No domain-over-domain.** Every domain is `CREATE DOMAIN eql_v3. + AS jsonb`, never `AS ` (`templates.py:72`). PostgreSQL resolves operators against the underlying base type; a derived domain would silently bypass the fixed operator surface. - **No operator class on a domain.** The generator emits operators, not operator classes. Callers index through the extractor function - (e.g. `USING btree (eql_v2.ord_term(col))`), whose return type + (e.g. `USING btree (eql_v3.ord_term(col))`), whose return type already carries a default opclass. - **Ownership boundary.** `writer.is_generated` recognises owned files by their header line and refuses to overwrite anything else @@ -323,7 +323,7 @@ output without per-type edits: - **`tasks/pin_search_path.sql:265-290`** — structural skip identifies encrypted-domain functions by language (`sql`), volatility (`IMMUTABLE`), and the presence of at least one argument typed as a - jsonb-backed `DOMAIN` in `public` named `eql_v2_*`. New scalar types + jsonb-backed `DOMAIN` in the `eql_v3` schema. New scalar types need no edit here. - **`tasks/test/splinter.sh`** — name-based allowlist. The converged wrapper names (`eq`, `neq`, `lt`, `lte`, `gt`, `gte`, `eq_term`, diff --git a/docs/reference/encrypted-domain-implementation-spec.md b/docs/reference/encrypted-domain-implementation-spec.md index 4499c20d..c6bec96a 100644 --- a/docs/reference/encrypted-domain-implementation-spec.md +++ b/docs/reference/encrypted-domain-implementation-spec.md @@ -8,8 +8,9 @@ the fixed term catalog in `tasks/codegen/terms.py`. ## 1. Model -Each generated public domain is a concrete `jsonb` domain named -`public.eql_v2_`. The manifest is intentionally small: +Each generated domain is a concrete `jsonb` domain in the `eql_v3` +schema named `eql_v3.` (dropped by `DROP SCHEMA eql_v3 CASCADE`; +survives an `eql_v2` uninstall). The manifest is intentionally small: ```toml [domain] @@ -110,10 +111,10 @@ with `v` pinned to `2`. Beyond key presence and the version value, a malformed term can still fail later inside its extractor unless a future catalog design adds stronger validation. -Every generated domain is a concrete domain over `jsonb`. Do not define -one generated domain over another generated domain; PostgreSQL resolves -operators against the underlying base type in ways that bypass the fixed -operator surface. +Every generated domain is a concrete domain over `jsonb` in the `eql_v3` +schema. Do not define one generated domain over another generated domain; +PostgreSQL resolves operators against the underlying base type in ways +that bypass the fixed operator surface. ## 4. Extractors And Wrappers @@ -179,7 +180,7 @@ minimal metadata because they should never be planner-visible supported paths. PostgreSQL's operator resolver still prefers the built-in `jsonb` operator -for untyped string literals in forms such as `payload::eql_v2_int4 ? 'c'`. +for untyped string literals in forms such as `payload::eql_v3.int4 ? 'c'`. Use typed parameters or explicit casts (`'c'::text`) to route those forms to the generated blocker. The generated surface blocks the typed native operator shapes exposed by the catalog. @@ -189,8 +190,8 @@ operator shapes exposed by the catalog. Each ordered (ord-capable) domain additionally gets a generated `_aggregates.sql` file declaring `MIN` / `MAX`: -- two state functions, `eql_v2.min_sfunc` and `eql_v2.max_sfunc`, and -- two aggregates, `eql_v2.min()` and `eql_v2.max()`. +- two state functions, `eql_v3.min_sfunc` and `eql_v3.max_sfunc`, and +- two aggregates, `eql_v3.min()` and `eql_v3.max()`. Comparison routes through the domain's `<` / `>` operator (the ORE block term — no decryption). The state functions are `LANGUAGE plpgsql @@ -224,12 +225,12 @@ generated siblings, `_extensions.sql` IS committed. ## 7. Indexing -Do not create operator classes on generated public domains. Index through +Do not create operator classes on generated domains. Index through the extractor: ```sql -CREATE INDEX ... ON table_name USING btree (eql_v2.ord_term(col)); -CREATE INDEX ... ON table_name USING hash (eql_v2.eq_term(col)); +CREATE INDEX ... ON table_name USING btree (eql_v3.ord_term(col)); +CREATE INDEX ... ON table_name USING hash (eql_v3.eq_term(col)); ``` The extractor return type must already have the needed PostgreSQL access diff --git a/docs/reference/eql-functions.md b/docs/reference/eql-functions.md index 5ee40c77..e517e63e 100644 --- a/docs/reference/eql-functions.md +++ b/docs/reference/eql-functions.md @@ -422,31 +422,33 @@ eql_v2.ste_vec(val eql_v2_encrypted) RETURNS eql_v2_encrypted[] eql_v2.ste_vec(val jsonb) RETURNS eql_v2_encrypted[] ``` -### `eql_v2.eq_term()` / `eql_v2.ord_term()` (encrypted-domain) +### `eql_v3.eq_term()` / `eql_v3.ord_term()` (encrypted-domain) Extract the equality (`hm`) or ordering (`ob`) index term from a scalar encrypted-domain value. Generated per eq/ord-capable variant of every scalar type — see [Encrypted-Domain Code Generator](./encrypted-domain-generator.md). The argument type selects the overload, and both are inlinable so a -functional index built on the extractor engages. +functional index built on the extractor engages. The extractors live in +the `eql_v3` schema; their return types remain the core `eql_v2` +index-term types. ```sql -- int4 — generated for every scalar type's eq / ord variants. -eql_v2.eq_term(a eql_v2_int4_eq) RETURNS eql_v2.hmac_256 -eql_v2.ord_term(a eql_v2_int4_ord) RETURNS eql_v2.ore_block_u64_8_256 -eql_v2.ord_term(a eql_v2_int4_ord_ore) RETURNS eql_v2.ore_block_u64_8_256 +eql_v3.eq_term(a eql_v3.int4_eq) RETURNS eql_v2.hmac_256 +eql_v3.ord_term(a eql_v3.int4_ord) RETURNS eql_v2.ore_block_u64_8_256 +eql_v3.ord_term(a eql_v3.int4_ord_ore) RETURNS eql_v2.ore_block_u64_8_256 ``` **Example:** ```sql -- Functional indexes on the extracted terms (see Database Indexes) -CREATE INDEX ON users USING hash (eql_v2.eq_term(salary_encrypted)); -CREATE INDEX ON users USING btree (eql_v2.ord_term(salary_encrypted)); +CREATE INDEX ON users USING hash (eql_v3.eq_term(salary_encrypted)); +CREATE INDEX ON users USING btree (eql_v3.ord_term(salary_encrypted)); ``` > The full per-domain operator/wrapper/blocker surface (and the -> `eql_v2_` / `_eq` / `_ord` / `_ord_ore` domain types themselves) is -> documented in [SQL support](./sql-support.md#encrypted-domain-scalar-types-eql_v2_t) +> `eql_v3.` / `_eq` / `_ord` / `_ord_ore` domain types themselves) is +> documented in [SQL support](./sql-support.md#encrypted-domain-scalar-types-eql_v3t) > and the [generator reference](./encrypted-domain-generator.md). --- @@ -669,28 +671,28 @@ SELECT eql_v2.min(encrypted_date) FROM events; SELECT eql_v2.max(encrypted_price) FROM products WHERE category = 'electronics'; ``` -### `eql_v2.min()` / `eql_v2.max()` (per-domain) +### `eql_v3.min()` / `eql_v3.max()` (per-domain) -Returns the minimum or maximum encrypted value in a set on an ordered encrypted-domain column. Defined per ord-capable variant of every scalar type (`eql_v2__ord`, `eql_v2__ord_ore`); the input type selects the aggregate via PostgreSQL's overload resolution. These are type-safe alternatives to the composite-type aggregates above and coexist with them. +Returns the minimum or maximum encrypted value in a set on an ordered encrypted-domain column. Defined per ord-capable variant of every scalar type (`eql_v3._ord`, `eql_v3._ord_ore`); the input type selects the aggregate via PostgreSQL's overload resolution. These are type-safe alternatives to the composite-type aggregates above and coexist with them. ```sql -- int4 — generated for every ordered variant of every scalar type. -eql_v2.min(eql_v2_int4_ord) RETURNS eql_v2_int4_ord -eql_v2.max(eql_v2_int4_ord) RETURNS eql_v2_int4_ord -eql_v2.min(eql_v2_int4_ord_ore) RETURNS eql_v2_int4_ord_ore -eql_v2.max(eql_v2_int4_ord_ore) RETURNS eql_v2_int4_ord_ore +eql_v3.min(eql_v3.int4_ord) RETURNS eql_v3.int4_ord +eql_v3.max(eql_v3.int4_ord) RETURNS eql_v3.int4_ord +eql_v3.min(eql_v3.int4_ord_ore) RETURNS eql_v3.int4_ord_ore +eql_v3.max(eql_v3.int4_ord_ore) RETURNS eql_v3.int4_ord_ore ``` Comparison routes through the variant's `<` / `>` operator, which uses the ORE block term — no decryption. The state function is `STRICT`, so `NULL` inputs are skipped and an all-`NULL` input set returns `NULL`. **Example:** ```sql --- ord-capable column (e.g. price_encrypted typed as eql_v2_int4_ord) -SELECT eql_v2.min(price_encrypted) FROM products; -SELECT eql_v2.max(price_encrypted) FROM products WHERE category = 'electronics'; +-- ord-capable column (e.g. price_encrypted typed as eql_v3.int4_ord) +SELECT eql_v3.min(price_encrypted) FROM products; +SELECT eql_v3.max(price_encrypted) FROM products WHERE category = 'electronics'; -- Equivalent on a generic jsonb column (cast to the right domain) -SELECT eql_v2.min(price_jsonb::eql_v2_int4_ord) FROM products; +SELECT eql_v3.min(price_jsonb::eql_v3.int4_ord) FROM products; ``` `SUM` / `AVG` and other numeric aggregates are not supported on encrypted columns — decrypt at the application boundary. `MIN` / `MAX` only require comparator-revealing terms; arithmetic aggregates would require homomorphic encryption. diff --git a/docs/reference/sql-support.md b/docs/reference/sql-support.md index ff2de727..d15be2ee 100644 --- a/docs/reference/sql-support.md +++ b/docs/reference/sql-support.md @@ -59,22 +59,22 @@ Use the equivalent [`jsonb_path_query`](#jsonb-functions-and-selectors-enabled-b --- -## Encrypted-domain scalar types (`eql_v2_`) +## Encrypted-domain scalar types (`eql_v3.`) -Scalar encrypted-domain types (e.g. `eql_v2_int4`; see the [generator reference](./encrypted-domain-generator.md)) are a different access model from the matrix above. Instead of configuring a search index on an `eql_v2_encrypted` column, you type the column as a specific domain *variant* whose operator surface is fixed at generation time. The index terms travel in the payload; there is no `add_search_config` step. +Scalar encrypted-domain types (e.g. `eql_v3.int4`; see the [generator reference](./encrypted-domain-generator.md)) are a different access model from the matrix above. Instead of configuring a search index on an `eql_v2_encrypted` column, you type the column as a specific domain *variant* whose operator surface is fixed at generation time. The index terms travel in the payload; there is no `add_search_config` step. The domains and their operator surface live in the `eql_v3` schema (dropped by `DROP SCHEMA eql_v3 CASCADE`, and they survive an `eql_v2` uninstall); their extracted index-term types remain the core `eql_v2` types. Each scalar type `` generates one storage-only variant plus eq/ord query variants: | Domain variant | Term carried | `=` `<>` | `<` `<=` `>` `>=` | `MIN` / `MAX` | `LIKE`/`ILIKE`, JSONB / ste_vec ops | | ------------------------------- | ------------------- | :------: | :---------------: | :-----------: | :---------------------------------: | -| `eql_v2_` | none (storage only) | ❌ | ❌ | ❌ | ❌ | -| `eql_v2__eq` | `hm` (hmac_256) | ✅ | ❌ | ❌ | ❌ | -| `eql_v2__ord` / `_ord_ore` | `ob` (ore_block) | ✅ | ✅ | ✅ | ❌ | +| `eql_v3.` | none (storage only) | ❌ | ❌ | ❌ | ❌ | +| `eql_v3._eq` | `hm` (hmac_256) | ✅ | ❌ | ❌ | ❌ | +| `eql_v3._ord` / `_ord_ore` | `ob` (ore_block) | ✅ | ✅ | ✅ | ❌ | -- The bare `eql_v2_` variant carries no index term and **blocks every comparison operator** — it is storage / decryption only. Type the column as `_eq` or `_ord` (or cast at the call site) when you need to query. +- The bare `eql_v3.` variant carries no index term and **blocks every comparison operator** — it is storage / decryption only. Type the column as `_eq` or `_ord` (or cast at the call site) when you need to query. - Unsupported operators are not silent no-ops: they route to blocker functions that `RAISE` an "operator not supported" exception (a `NULL` operand still raises — the blockers are deliberately not `STRICT`). - `LIKE` / `ILIKE` and the native JSONB operators (`@>`, `<@`, `->`, `->>`, `?`, `?|`, `?&`, `@?`, `@@`, `#>`, `#>>`, `-`, `#-`, `||`) are blocked on **every** scalar domain variant — they are meaningless on a scalar payload. -- `MIN` / `MAX` are exposed only on the ordered variants as `eql_v2.min(eql_v2__ord)` / `eql_v2.max(...)` — see [EQL Functions Reference](./eql-functions.md#eql_v2min--eql_v2max-per-domain). +- `MIN` / `MAX` are exposed only on the ordered variants as `eql_v3.min(eql_v3._ord)` / `eql_v3.max(...)` — see [EQL Functions Reference](./eql-functions.md#eql_v3min--eql_v3max-per-domain). --- @@ -95,7 +95,7 @@ This matrix covers higher-level SQL constructs rather than individual operators. | `GROUP BY col` | requires `unique` on the whole column; `ore` / `ope` not yet supported (see note below). Extracted JSON paths have separate caveats — see [ste_vec section](#index-terms-by-json-node-type). | ✅ | ❌ | ❌ | ❌ | ❌ | | `DISTINCT` / `DISTINCT ON (col)` | `unique`, `ore`, or `ope` | ✅ | ✅ | ✅ | ❌ | ❌ | | `HAVING` | same index requirements as the predicates used in `HAVING` (see operator matrix) | varies | varies | varies | varies | varies | -| `MIN(col)` / `MAX(col)` | `eql_v2.min(eql_v2_encrypted)` / `max` work on any `eql_v2_encrypted` column with `ore` terms. The encrypted-domain family additionally exposes type-safe `eql_v2.min(eql_v2__ord)` / `max` (and the `_ord_ore` twin); `Storage` and `Eq` variants have no comparator and do not declare these aggregates. | ❌ | ✅ | ✅ | ❌ | ❌ | +| `MIN(col)` / `MAX(col)` | `eql_v2.min(eql_v2_encrypted)` / `max` work on any `eql_v2_encrypted` column with `ore` terms. The encrypted-domain family additionally exposes type-safe `eql_v3.min(eql_v3._ord)` / `max` (and the `_ord_ore` twin); `Storage` and `Eq` variants have no comparator and do not declare these aggregates. | ❌ | ✅ | ✅ | ❌ | ❌ | | `COUNT(col)` / `COUNT(DISTINCT col)` | `ore` / `ope` or `unique` for `DISTINCT`; none for plain `COUNT(col)` | ✅ | ✅ | ✅ | ✅ | ✅ | | `JOIN … ON lhs.col = rhs.col` | same index and keyset on both sides | ✅ | ✅ | ✅ | ❌ | ❌ | | `JOIN … ON lhs.col < rhs.col` etc. | same index and keyset on both sides | ❌ | ✅ | ✅ | ❌ | ❌ | @@ -108,7 +108,7 @@ Notes: - **Cross-column / cross-table comparisons** (joins, `IN (subquery)`, `UNION` dedup, etc.) require both sides to have been encrypted with the *same* keyset and the matching search index. Encrypted values from different `ste_vec` prefixes are deliberately incomparable. - **`GROUP BY`** on encrypted columns relies on an operator class which currently only supports encrypted values with a `unique` index term. This is a surprising limitation because it would be natural to expect `ore` / `ope` index terms to also work. This limitation will be lifted in the future. See [Database Indexes](./database-indexes.md#group-by) for performance considerations. - **`ORDER BY`** without an `ore` or `ope` index will still *run* (the EQL `compare` function has a deterministic literal fallback to avoid btree errors), but the resulting order is not meaningful. Configure `ore` (or `ope`) whenever ordering matters. -- **`MIN(col)` / `MAX(col)`** is available two ways. The composite-type aggregates `eql_v2.min(eql_v2_encrypted)` / `eql_v2.max(eql_v2_encrypted)` work on any `eql_v2_encrypted` column carrying `ore` terms. The encrypted-domain family additionally exposes type-safe per-variant aggregates — see `eql_v2.min(eql_v2__ord)` / `eql_v2.max(eql_v2__ord)` (and the `_ord_ore` twin) in [EQL Functions Reference](./eql-functions.md#eql_v2min--eql_v2max-per-domain). For a domain-typed column, type it as the appropriate `_ord` variant or cast at the call site (`eql_v2.min(col::eql_v2_int4_ord)`). +- **`MIN(col)` / `MAX(col)`** is available two ways. The composite-type aggregates `eql_v2.min(eql_v2_encrypted)` / `eql_v2.max(eql_v2_encrypted)` work on any `eql_v2_encrypted` column carrying `ore` terms. The encrypted-domain family additionally exposes type-safe per-variant aggregates — see `eql_v3.min(eql_v3._ord)` / `eql_v3.max(eql_v3._ord)` (and the `_ord_ore` twin) in [EQL Functions Reference](./eql-functions.md#eql_v3min--eql_v3max-per-domain). For a domain-typed column, type it as the appropriate `_ord` variant or cast at the call site (`eql_v3.min(col::eql_v3.int4_ord)`). - **Aggregates beyond `MIN`/`MAX`** (e.g. `SUM`, `AVG`) are not supported on encrypted values — they would require homomorphic encryption. Decrypt at the application boundary and perform those aggregates client-side. - **Parameter binding**: CipherStash Proxy rewrites bound parameters in `WHERE`, `JOIN`, and `RETURNING` clauses with `::JSONB::eql_v2_encrypted` casts so that the encrypted operator and any B-tree / GIN indexes are selected. Writing those casts yourself is only required when bypassing the proxy. diff --git a/src/encrypted_domain/functions.sql b/src/encrypted_domain/functions.sql index 24b75145..71a070a1 100644 --- a/src/encrypted_domain/functions.sql +++ b/src/encrypted_domain/functions.sql @@ -1,9 +1,9 @@ --- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql --! @file encrypted_domain/functions.sql ---! @brief Shared blocker helper for the eql_v2_int4 domain family. +--! @brief Shared blocker helper for the eql_v3 encrypted-domain families. --! ---! Per-domain wrapper functions live in src/encrypted_domain/int4/. +--! Per-domain wrapper functions live in src/encrypted_domain//. --! Blockers in those files delegate to encrypted_domain_unsupported_bool --! so every domain raises a uniform domain-specific error rather than --! letting an unsupported operator fall through to native jsonb @@ -12,10 +12,10 @@ --! @brief Shared blocker helper. Raises 'operator X is not supported --! for TYPE' so unsupported domain operators surface a clear --! error rather than fall through to native jsonb behaviour. ---! @param type_name Domain type name (eql_v2_int4*) +--! @param type_name Domain type name (eql_v3.*) --! @param operator_name Operator symbol (=, <, @>, ->, etc.) --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.encrypted_domain_unsupported_bool(type_name text, operator_name text) +CREATE FUNCTION eql_v3.encrypted_domain_unsupported_bool(type_name text, operator_name text) RETURNS boolean IMMUTABLE PARALLEL SAFE SET search_path = pg_catalog, extensions, public diff --git a/src/lint/lints.sql b/src/lint/lints.sql index b378f1bb..bf38c1e6 100644 --- a/src/lint/lints.sql +++ b/src/lint/lints.sql @@ -1,4 +1,5 @@ -- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql --! @brief EQL lint: detect non-inlinable operator implementation functions --! @@ -92,7 +93,8 @@ AS $$ SELECT 1 FROM pg_type t WHERE t.oid IN (op.oprleft, op.oprright) AND (t.typname LIKE 'eql_v2%' - OR t.typnamespace = 'eql_v2'::regnamespace) + OR t.typnamespace = 'eql_v2'::regnamespace + OR t.typnamespace = 'eql_v3'::regnamespace) ) ), @@ -132,7 +134,7 @@ AS $$ FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace JOIN pg_catalog.pg_language lang_l ON lang_l.oid = p.prolang - WHERE n.nspname = 'eql_v2' + WHERE n.nspname IN ('eql_v2', 'eql_v3') AND (p.prosrc LIKE '%encrypted_domain_unsupported_bool%' OR p.prosrc LIKE '%is not supported for%') AND EXISTS ( @@ -142,9 +144,11 @@ AS $$ JOIN pg_catalog.pg_namespace dn ON dn.oid = dt.typnamespace JOIN pg_catalog.pg_type bt ON bt.oid = dt.typbasetype WHERE dt.typtype = 'd' - AND dn.nspname = 'public' - AND dt.typname LIKE 'eql_v2\_%' AND bt.typname = 'jsonb' + AND ( + dn.nspname = 'eql_v3' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) ) ) @@ -320,10 +324,15 @@ AS $$ JOIN pg_catalog.pg_type bt ON bt.oid = dt.typbasetype JOIN pg_catalog.pg_namespace bn ON bn.oid = bt.typnamespace WHERE dt.typtype = 'd' - AND dn.nspname = 'public' - AND dt.typname LIKE 'eql_v2\_%' + AND ( + dn.nspname = 'eql_v3' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) AND bt.typtype = 'd' - AND bt.typname LIKE 'eql_v2\_%' + AND ( + bn.nspname = 'eql_v3' + OR (bn.nspname = 'public' AND bt.typname LIKE 'eql_v2\_%') + ) -- ┌─────────────────────────────────────────────────────────────────┐ -- │ Domain opclass: an operator class declared FOR TYPE on an │ @@ -345,8 +354,10 @@ AS $$ JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace JOIN pg_catalog.pg_namespace cn ON cn.oid = oc.opcnamespace WHERE t.typtype = 'd' - AND tn.nspname = 'public' - AND t.typname LIKE 'eql_v2\_%' + AND ( + tn.nspname = 'eql_v3' + OR (tn.nspname = 'public' AND t.typname LIKE 'eql_v2\_%') + ) ORDER BY 1, 2, 3; $$; diff --git a/src/schema-v3.sql b/src/schema-v3.sql new file mode 100644 index 00000000..06df8d38 --- /dev/null +++ b/src/schema-v3.sql @@ -0,0 +1,22 @@ +--! @file schema-v3.sql +--! @brief EQL v3 schema creation +--! +--! Creates the eql_v3 schema, which houses the encrypted-domain type +--! families (eql_v3.int4 and future scalar domains): their domains, index-term +--! extractors, comparison wrappers, blockers, and aggregates. The core +--! index-term types these reuse (eql_v2.hmac_256, eql_v2.ore_block_u64_8_256) +--! remain in the eql_v2 schema and are referenced cross-schema. +--! +--! Drops existing schema if present to support clean reinstallation. +--! +--! @warning DROP SCHEMA CASCADE will remove all objects in the schema +--! @note eql_v3 is a new, additional schema for domain families; the eql_v2 +--! schema name is unchanged. + +--! @brief Drop existing EQL v3 schema +--! @warning CASCADE will drop all dependent objects +DROP SCHEMA IF EXISTS eql_v3 CASCADE; + +--! @brief Create EQL v3 schema +--! @note Houses the encrypted-domain type families +CREATE SCHEMA eql_v3; diff --git a/tasks/codegen/generate.py b/tasks/codegen/generate.py index cf30c598..03ac6be7 100644 --- a/tasks/codegen/generate.py +++ b/tasks/codegen/generate.py @@ -87,7 +87,7 @@ def render_types_file(spec: TypeSpec) -> str: """ blocks = [render_domain_block(domain, spec.token) for domain in spec.domains] return ( - "-- REQUIRE: src/schema.sql\n\n" + "-- REQUIRE: src/schema-v3.sql\n\n" f"--! @file encrypted_domain/{spec.token}/{spec.token}_types.sql\n" f"--! @brief Encrypted-domain type family for {spec.token}.\n\n" "DO $$\nBEGIN\n" @@ -99,6 +99,7 @@ def render_types_file(spec: TypeSpec) -> str: def _functions_requires(spec: TypeSpec, domain: DomainSpec) -> list[str]: reqs = [ "src/schema.sql", + "src/schema-v3.sql", _types_path(spec.token), "src/encrypted_domain/functions.sql", ] @@ -181,7 +182,7 @@ def render_operators_file(spec: TypeSpec, domain: DomainSpec) -> str: ) requires = ( - "-- REQUIRE: src/schema.sql\n" + "-- REQUIRE: src/schema-v3.sql\n" f"-- REQUIRE: {_types_path(spec.token)}\n" f"-- REQUIRE: src/encrypted_domain/{spec.token}/" f"{domain.name}_functions.sql\n" @@ -202,7 +203,7 @@ def render_aggregates_file(spec: TypeSpec, domain: DomainSpec) -> str | None: return None parts = [render_aggregate(domain, AGGREGATE_OPS[name]) for name in ("min", "max")] requires = ( - "-- REQUIRE: src/schema.sql\n" + "-- REQUIRE: src/schema-v3.sql\n" f"-- REQUIRE: {_types_path(spec.token)}\n" f"-- REQUIRE: src/encrypted_domain/{spec.token}/" f"{domain.name}_functions.sql\n" diff --git a/tasks/codegen/templates.py b/tasks/codegen/templates.py index 60833495..0c446fec 100644 --- a/tasks/codegen/templates.py +++ b/tasks/codegen/templates.py @@ -49,7 +49,8 @@ def _sql_str(s: str) -> str: Use this at every `'{...}'` interpolation boundary in the render_* helpers — payload keys, operator symbols, domain names rendered into - RAISE messages, etc. + RAISE messages, etc. NOT for schema-qualified identifiers like + ``eql_v3.foo``: those are emitted unquoted and must not be doubled. Today every catalog string (term keys, operator symbols) is quote-free, so this is a no-op on real input and output stays byte-identical. It @@ -58,6 +59,16 @@ def _sql_str(s: str) -> str: return s.replace("'", "''") +# Schema housing the encrypted-domain families: the domains themselves plus +# their index-term extractors, comparison wrappers, blockers, and aggregates. +# New in v3 and distinct from the core eql_v2 schema, which still owns the +# shared index-term types the extractors return and construct +# (eql_v2.hmac_256, eql_v2.ore_block_u64_8_256). +DOMAIN_SCHEMA = "eql_v3" +# Schema owning the core index-term types/constructors the extractors reuse. +CORE_SCHEMA = "eql_v2" + + def render_fixture_values_rs(spec: TypeSpec) -> str: """Body for tests/sqlx/src/fixtures/_values.rs. @@ -170,8 +181,8 @@ def brief_role_clause(domain: DomainSpec, token: str) -> str: def domain_name(domain: str) -> str: - """The public SQL domain type name.""" - return f"eql_v2_{domain}" + """The schema-qualified SQL domain type name, e.g. ``eql_v3.int4_eq``.""" + return f"{DOMAIN_SCHEMA}.{domain}" def _arg_label(dom: str, arg_type: str) -> str: @@ -203,10 +214,10 @@ def render_domain_block(domain: DomainSpec, token: str) -> str: f" --! @brief {phrase} encrypted {token} domain.{clause}\n" f" IF NOT EXISTS (\n" f" SELECT 1 FROM pg_type\n" - f" WHERE typname = '{_sql_str(dom)}' " - f"AND typnamespace = 'public'::regnamespace\n" + f" WHERE typname = '{_sql_str(domain.name)}' " + f"AND typnamespace = '{DOMAIN_SCHEMA}'::regnamespace\n" f" ) THEN\n" - f" CREATE DOMAIN public.{dom} AS jsonb\n" + f" CREATE DOMAIN {dom} AS jsonb\n" f" CHECK (\n" f" jsonb_typeof(VALUE) = 'object'\n" f" AND {checks}\n" @@ -224,18 +235,18 @@ def render_extractor(domain: DomainSpec, term: Term) -> str: f"--! @return {term.returns}\n" ) return doxy + ( - f"CREATE FUNCTION eql_v2.{term.extractor}(a {dom})\n" + f"CREATE FUNCTION {DOMAIN_SCHEMA}.{term.extractor}(a {dom})\n" f"RETURNS {term.returns}\n" f"LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE\n" - f"AS $$ SELECT eql_v2.{term.ctor}(a::jsonb) $$;\n" + f"AS $$ SELECT {CORE_SCHEMA}.{term.ctor}(a::jsonb) $$;\n" ) def _extract_arg(arg_type: str, extractor: str, domain: str, arg: str) -> str: """The extractor-call SQL for one operand, casting jsonb to the domain first.""" if arg_type == "jsonb": - return f"eql_v2.{extractor}({arg}::{domain})" - return f"eql_v2.{extractor}({arg})" + return f"{DOMAIN_SCHEMA}.{extractor}({arg}::{domain})" + return f"{DOMAIN_SCHEMA}.{extractor}({arg})" def render_wrapper( @@ -254,7 +265,7 @@ def render_wrapper( f"--! @return boolean\n" ) return doxy + ( - f"CREATE FUNCTION eql_v2.{backing}(a {arg_a}, b {arg_b})\n" + f"CREATE FUNCTION {DOMAIN_SCHEMA}.{backing}(a {arg_a}, b {arg_b})\n" f"RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE\n" f"AS $$ SELECT {call_a} {op} {call_b} $$;\n" ) @@ -276,9 +287,9 @@ def render_blocker_bool( f"--! @return boolean (never returns; always raises)\n" ) return doxy + ( - f"CREATE FUNCTION eql_v2.{backing}(a {arg_a}, b {arg_b})\n" + f"CREATE FUNCTION {DOMAIN_SCHEMA}.{backing}(a {arg_a}, b {arg_b})\n" f"RETURNS boolean IMMUTABLE PARALLEL SAFE\n" - f"AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool(" + f"AS $$ BEGIN RETURN {DOMAIN_SCHEMA}.encrypted_domain_unsupported_bool(" f"'{_sql_str(dom)}', '{_sql_str(op)}'); END; $$\n" f"LANGUAGE plpgsql;\n" ) @@ -301,7 +312,7 @@ def render_blocker_path( f"--! @return {returns} (never returns; always raises)\n" ) return doxy + ( - f"CREATE FUNCTION eql_v2.{backing}(a {arg_a}, selector {arg_b})\n" + f"CREATE FUNCTION {DOMAIN_SCHEMA}.{backing}(a {arg_a}, selector {arg_b})\n" f"RETURNS {returns} IMMUTABLE PARALLEL SAFE\n" f"AS $$ BEGIN RAISE EXCEPTION " f"'operator % is not supported for %', '{_sql_str(op)}', " @@ -328,7 +339,7 @@ def render_blocker_native( ) if returns == "boolean": body = ( - "BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool(" + f"BEGIN RETURN {DOMAIN_SCHEMA}.encrypted_domain_unsupported_bool(" f"'{_sql_str(dom)}', '{_sql_str(op)}'); END;" ) else: @@ -338,7 +349,7 @@ def render_blocker_native( f"'{_sql_str(dom)}'; END;" ) return doxy + ( - f"CREATE FUNCTION eql_v2.{backing}(a {arg_a}, b {arg_b})\n" + f"CREATE FUNCTION {DOMAIN_SCHEMA}.{backing}(a {arg_a}, b {arg_b})\n" f"RETURNS {returns} IMMUTABLE PARALLEL SAFE\n" f"AS $$ {body} $$\n" f"LANGUAGE plpgsql;\n" @@ -407,7 +418,7 @@ def render_aggregate(domain: DomainSpec, op: AggregateOp) -> str: "-- also work, but the procedural form mirrors the blocker convention.)\n" ) sfunc = sfunc_rationale + ( - f"CREATE FUNCTION eql_v2.{op.sfunc_name}(state {dom}, value {dom})\n" + f"CREATE FUNCTION {DOMAIN_SCHEMA}.{op.sfunc_name}(state {dom}, value {dom})\n" f"RETURNS {dom}\n" f"LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE\n" f"SET search_path = pg_catalog, extensions, public\n" @@ -442,10 +453,10 @@ def render_aggregate(domain: DomainSpec, op: AggregateOp) -> str: "-- combinefunc = sfunc: min/max are associative, so merging two partial\n" "-- extrema is the same comparison. PARALLEL SAFE enables partial and\n" "-- parallel aggregation on large GROUP BY workloads, with no decryption.\n" - f"CREATE AGGREGATE eql_v2.{op.name}({dom}) (\n" - f" sfunc = eql_v2.{op.sfunc_name},\n" + f"CREATE AGGREGATE {DOMAIN_SCHEMA}.{op.name}({dom}) (\n" + f" sfunc = {DOMAIN_SCHEMA}.{op.sfunc_name},\n" f" stype = {dom},\n" - f" combinefunc = eql_v2.{op.sfunc_name},\n" + f" combinefunc = {DOMAIN_SCHEMA}.{op.sfunc_name},\n" f" parallel = safe\n" f");\n" ) @@ -470,7 +481,7 @@ def render_operator( ) lines += [ f"CREATE OPERATOR {op} (", - f" FUNCTION = eql_v2.{backing},", + f" FUNCTION = {DOMAIN_SCHEMA}.{backing},", f" LEFTARG = {leftarg}, RIGHTARG = {rightarg}", ] if supported and meta.kind == "symmetric": diff --git a/tasks/codegen/test_generate.py b/tasks/codegen/test_generate.py index e92e2f2f..db93b989 100644 --- a/tasks/codegen/test_generate.py +++ b/tasks/codegen/test_generate.py @@ -54,10 +54,10 @@ def load(tmp_path): def test_types_file_has_all_four_domains(tmp_path): spec = load(tmp_path) sql = render_types_file(spec) - assert "-- REQUIRE: src/schema.sql" in sql - for dom in ("eql_v2_int4", "eql_v2_int4_eq", - "eql_v2_int4_ord", "eql_v2_int4_ord_ore"): - assert f"CREATE DOMAIN public.{dom} AS jsonb" in sql + assert "-- REQUIRE: src/schema-v3.sql" in sql + for dom in ("int4", "int4_eq", + "int4_ord", "int4_ord_ore"): + assert f"CREATE DOMAIN eql_v3.{dom} AS jsonb" in sql def test_storage_functions_file_is_all_blockers(tmp_path): @@ -75,7 +75,7 @@ def test_eq_functions_file_counts_and_extractor(tmp_path): eq = next(d for d in spec.domains if d.name == "int4_eq") sql = render_functions_file(spec, eq) assert sql.count("CREATE FUNCTION") == 45 - assert "CREATE FUNCTION eql_v2.eq_term(a eql_v2_int4_eq)" in sql + assert "CREATE FUNCTION eql_v3.eq_term(a eql_v3.int4_eq)" in sql assert "RETURNS eql_v2.hmac_256" in sql # 1 extractor + 6 wrappers (=, <> across 3 arg-shapes) inlined as SQL; # 38 blockers across the remaining native jsonb surface as plpgsql. @@ -89,7 +89,7 @@ def test_ore_functions_file_counts_and_extractor(tmp_path): ordered = next(d for d in spec.domains if d.name == "int4_ord") sql = render_functions_file(spec, ordered) assert sql.count("CREATE FUNCTION") == 45 - assert "CREATE FUNCTION eql_v2.ord_term(a eql_v2_int4_ord)" in sql + assert "CREATE FUNCTION eql_v3.ord_term(a eql_v3.int4_ord)" in sql assert "RETURNS eql_v2.ore_block_u64_8_256" in sql # 1 extractor + 18 wrappers (=, <>, <, <=, >, >= across 3 shapes); # 26 blockers across containment/path/native-jsonb fallback ops. @@ -343,8 +343,8 @@ def test_render_aggregates_file_carries_both_min_and_max(tmp_path): assert sql is not None assert sql.count("CREATE FUNCTION") == 2 assert sql.count("CREATE AGGREGATE") == 2 - assert "eql_v2.min_sfunc" in sql - assert "eql_v2.max_sfunc" in sql + assert "eql_v3.min_sfunc" in sql + assert "eql_v3.max_sfunc" in sql # REQUIRE edges: types + functions + operators must all be declared. assert "-- REQUIRE: src/encrypted_domain/int4/int4_ord_operators.sql" in sql assert "-- REQUIRE: src/encrypted_domain/int4/int4_ord_functions.sql" in sql diff --git a/tasks/codegen/test_templates.py b/tasks/codegen/test_templates.py index ba1e3b7d..7f30e4cb 100644 --- a/tasks/codegen/test_templates.py +++ b/tasks/codegen/test_templates.py @@ -72,7 +72,7 @@ def test_render_fixture_values_rs_preserves_manifest_order(): def test_domain_block_storage_uses_fixed_envelope_only(): domain = DomainSpec(name="int4", terms=[]) sql = render_domain_block(domain, "int4") - assert "CREATE DOMAIN public.eql_v2_int4 AS jsonb" in sql + assert "CREATE DOMAIN eql_v3.int4 AS jsonb" in sql assert "VALUE ? 'v'" in sql assert "VALUE ? 'i'" in sql assert "VALUE ? 'c'" in sql @@ -83,7 +83,7 @@ def test_domain_block_storage_uses_fixed_envelope_only(): def test_domain_block_uses_catalog_json_keys(): domain = DomainSpec(name="int4_ord", terms=["ore"]) sql = render_domain_block(domain, "int4") - assert "CREATE DOMAIN public.eql_v2_int4_ord AS jsonb" in sql + assert "CREATE DOMAIN eql_v3.int4_ord AS jsonb" in sql assert "VALUE ? 'ob'" in sql assert "VALUE ? 'ore'" not in sql @@ -109,7 +109,7 @@ def test_domain_block_check_pins_envelope_version(): def test_extractor_is_catalog_derived_and_inlinable(): domain = DomainSpec(name="int4_eq", terms=["hm"]) sql = render_extractor(domain, TERM_CATALOG["hm"]) - assert "CREATE FUNCTION eql_v2.eq_term(a eql_v2_int4_eq)" in sql + assert "CREATE FUNCTION eql_v3.eq_term(a eql_v3.int4_eq)" in sql assert "RETURNS eql_v2.hmac_256" in sql assert "LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE" in sql assert "SELECT eql_v2.hmac_256(a::jsonb)" in sql @@ -121,12 +121,12 @@ def test_wrapper_uses_term_extractor_for_supported_operator(): sql = render_wrapper( domain, op="<", - arg_a="eql_v2_int4_ord", + arg_a="eql_v3.int4_ord", arg_b="jsonb", extractor="ord_term", ) - assert "CREATE FUNCTION eql_v2.lt(a eql_v2_int4_ord, b jsonb)" in sql - assert "SELECT eql_v2.ord_term(a) < eql_v2.ord_term(b::eql_v2_int4_ord)" in sql + assert "CREATE FUNCTION eql_v3.lt(a eql_v3.int4_ord, b jsonb)" in sql + assert "SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.int4_ord)" in sql def test_wrapper_is_inlinable_sql(): @@ -135,8 +135,8 @@ def test_wrapper_is_inlinable_sql(): sql = render_wrapper( domain, op="=", - arg_a="eql_v2_int4_eq", - arg_b="eql_v2_int4_eq", + arg_a="eql_v3.int4_eq", + arg_b="eql_v3.int4_eq", extractor="eq_term", ) assert "LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE" in sql @@ -161,10 +161,10 @@ def test_blocker_bool_is_not_strict(): attribute line so any future refactor that re-adds STRICT fails loudly.""" domain = DomainSpec(name="int4", terms=[]) sql = render_blocker_bool( - domain, op="<", arg_a="eql_v2_int4", arg_b="eql_v2_int4", + domain, op="<", arg_a="eql_v3.int4", arg_b="eql_v3.int4", ) - assert "CREATE FUNCTION eql_v2.lt(a eql_v2_int4, b eql_v2_int4)" in sql - assert "encrypted_domain_unsupported_bool('eql_v2_int4', '<')" in sql + assert "CREATE FUNCTION eql_v3.lt(a eql_v3.int4, b eql_v3.int4)" in sql + assert "encrypted_domain_unsupported_bool('eql_v3.int4', '<')" in sql assert "RETURNS boolean IMMUTABLE PARALLEL SAFE\n" in sql assert "LANGUAGE plpgsql" in sql assert "STRICT" not in sql @@ -174,9 +174,9 @@ def test_blocker_path_is_not_strict(): """Mirror of test_blocker_bool_is_not_strict for path blockers.""" domain = DomainSpec(name="int4", terms=[]) sql = render_blocker_path( - domain, op="->", arg_a="eql_v2_int4", arg_b="text", + domain, op="->", arg_a="eql_v3.int4", arg_b="text", ) - assert "RETURNS eql_v2_int4 IMMUTABLE PARALLEL SAFE\n" in sql + assert "RETURNS eql_v3.int4 IMMUTABLE PARALLEL SAFE\n" in sql assert "LANGUAGE plpgsql" in sql assert "STRICT" not in sql @@ -184,12 +184,12 @@ def test_blocker_path_is_not_strict(): def test_blocker_path_returns_domain_or_text(): domain = DomainSpec(name="int4", terms=[]) arrow = render_blocker_path( - domain, op="->", arg_a="eql_v2_int4", arg_b="text", + domain, op="->", arg_a="eql_v3.int4", arg_b="text", ) - assert 'CREATE FUNCTION eql_v2."->"(a eql_v2_int4, selector text)' in arrow - assert "RETURNS eql_v2_int4" in arrow + assert 'CREATE FUNCTION eql_v3."->"(a eql_v3.int4, selector text)' in arrow + assert "RETURNS eql_v3.int4" in arrow arrow2 = render_blocker_path( - domain, op="->>", arg_a="eql_v2_int4", arg_b="text", + domain, op="->>", arg_a="eql_v3.int4", arg_b="text", ) assert "RETURNS text" in arrow2 @@ -199,19 +199,19 @@ def test_blocker_path_for_jsonb_left_arg_returns_domain(): return type for `->` (only `->>` returns text).""" domain = DomainSpec(name="int4", terms=[]) sql = render_blocker_path( - domain, op="->", arg_a="jsonb", arg_b="eql_v2_int4", + domain, op="->", arg_a="jsonb", arg_b="eql_v3.int4", ) - assert 'CREATE FUNCTION eql_v2."->"(a jsonb, selector eql_v2_int4)' in sql - assert "RETURNS eql_v2_int4" in sql + assert 'CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int4)' in sql + assert "RETURNS eql_v3.int4" in sql def test_blocker_native_bool_uses_helper_and_is_not_strict(): domain = DomainSpec(name="int4", terms=[]) sql = render_blocker_native( - domain, op="?", arg_a="eql_v2_int4", arg_b="text", returns="boolean", + domain, op="?", arg_a="eql_v3.int4", arg_b="text", returns="boolean", ) - assert 'CREATE FUNCTION eql_v2."?"(a eql_v2_int4, b text)' in sql - assert "encrypted_domain_unsupported_bool('eql_v2_int4', '?')" in sql + assert 'CREATE FUNCTION eql_v3."?"(a eql_v3.int4, b text)' in sql + assert "encrypted_domain_unsupported_bool('eql_v3.int4', '?')" in sql assert "RETURNS boolean IMMUTABLE PARALLEL SAFE\n" in sql assert "LANGUAGE plpgsql" in sql assert "STRICT" not in sql @@ -220,11 +220,11 @@ def test_blocker_native_bool_uses_helper_and_is_not_strict(): def test_blocker_native_jsonb_result_raises_and_is_not_strict(): domain = DomainSpec(name="int4", terms=[]) sql = render_blocker_native( - domain, op="#>", arg_a="eql_v2_int4", arg_b="text[]", returns="jsonb", + domain, op="#>", arg_a="eql_v3.int4", arg_b="text[]", returns="jsonb", ) - assert 'CREATE FUNCTION eql_v2."#>"(a eql_v2_int4, b text[])' in sql + assert 'CREATE FUNCTION eql_v3."#>"(a eql_v3.int4, b text[])' in sql assert "RETURNS jsonb IMMUTABLE PARALLEL SAFE\n" in sql - assert "RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v2_int4'" in sql + assert "RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int4'" in sql assert "LANGUAGE plpgsql" in sql assert "STRICT" not in sql @@ -232,9 +232,9 @@ def test_blocker_native_jsonb_result_raises_and_is_not_strict(): def test_blocker_native_text_result_raises_and_is_not_strict(): domain = DomainSpec(name="int4", terms=[]) sql = render_blocker_native( - domain, op="#>>", arg_a="eql_v2_int4", arg_b="text[]", returns="text", + domain, op="#>>", arg_a="eql_v3.int4", arg_b="text[]", returns="text", ) - assert 'CREATE FUNCTION eql_v2."#>>"(a eql_v2_int4, b text[])' in sql + assert 'CREATE FUNCTION eql_v3."#>>"(a eql_v3.int4, b text[])' in sql assert "RETURNS text IMMUTABLE PARALLEL SAFE\n" in sql assert "LANGUAGE plpgsql" in sql assert "STRICT" not in sql @@ -243,21 +243,21 @@ def test_blocker_native_text_result_raises_and_is_not_strict(): def test_blocker_native_concat_cross_shape(): domain = DomainSpec(name="int4", terms=[]) sql = render_blocker_native( - domain, op="||", arg_a="jsonb", arg_b="eql_v2_int4", returns="jsonb", + domain, op="||", arg_a="jsonb", arg_b="eql_v3.int4", returns="jsonb", ) - assert 'CREATE FUNCTION eql_v2."||"(a jsonb, b eql_v2_int4)' in sql + assert 'CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int4)' in sql assert "RETURNS jsonb" in sql def test_operator_symmetric_metadata(): sql = render_operator( op="=", backing="eq", - leftarg="eql_v2_int4_eq", rightarg="eql_v2_int4_eq", + leftarg="eql_v3.int4_eq", rightarg="eql_v3.int4_eq", supported=True, ) assert "CREATE OPERATOR = (" in sql - assert "FUNCTION = eql_v2.eq" in sql - assert "LEFTARG = eql_v2_int4_eq, RIGHTARG = eql_v2_int4_eq" in sql + assert "FUNCTION = eql_v3.eq" in sql + assert "LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq" in sql assert "NEGATOR = <>" in sql assert "RESTRICT = eqsel" in sql @@ -267,12 +267,12 @@ def test_render_operator_unsupported_emits_only_function_and_args(): (those would lie about selectivity for a function that always raises).""" sql = render_operator( op="=", backing="eq", - leftarg="eql_v2_int4", rightarg="eql_v2_int4", + leftarg="eql_v3.int4", rightarg="eql_v3.int4", supported=False, ) assert "CREATE OPERATOR = (" in sql - assert "FUNCTION = eql_v2.eq" in sql - assert "LEFTARG = eql_v2_int4, RIGHTARG = eql_v2_int4" in sql + assert "FUNCTION = eql_v3.eq" in sql + assert "LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4" in sql assert "NEGATOR" not in sql assert "RESTRICT" not in sql assert "JOIN" not in sql @@ -283,23 +283,23 @@ def test_render_aggregate_min_int4_ord_emits_state_function_and_aggregate(): """Pin the rendered shape for the canonical (int4_ord, min) case.""" domain = DomainSpec(name="int4_ord", terms=["ore"]) sql = render_aggregate(domain, AGGREGATE_OPS["min"]) - assert "CREATE FUNCTION eql_v2.min_sfunc(state eql_v2_int4_ord, value eql_v2_int4_ord)" in sql - assert "RETURNS eql_v2_int4_ord" in sql + assert "CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.int4_ord, value eql_v3.int4_ord)" in sql + assert "RETURNS eql_v3.int4_ord" in sql assert "LANGUAGE plpgsql IMMUTABLE STRICT" in sql assert "SET search_path = pg_catalog, extensions, public" in sql assert "IF value < state THEN" in sql - assert "CREATE AGGREGATE eql_v2.min(eql_v2_int4_ord) (" in sql - assert "sfunc = eql_v2.min_sfunc" in sql - assert "stype = eql_v2_int4_ord" in sql + assert "CREATE AGGREGATE eql_v3.min(eql_v3.int4_ord) (" in sql + assert "sfunc = eql_v3.min_sfunc" in sql + assert "stype = eql_v3.int4_ord" in sql def test_render_aggregate_max_uses_greater_than_comparator(): """Symmetric pin: max uses `>` not `<`.""" domain = DomainSpec(name="int4_ord_ore", terms=["ore"]) sql = render_aggregate(domain, AGGREGATE_OPS["max"]) - assert "CREATE FUNCTION eql_v2.max_sfunc(state eql_v2_int4_ord_ore, value eql_v2_int4_ord_ore)" in sql + assert "CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.int4_ord_ore, value eql_v3.int4_ord_ore)" in sql assert "IF value > state THEN" in sql - assert "CREATE AGGREGATE eql_v2.max(eql_v2_int4_ord_ore) (" in sql + assert "CREATE AGGREGATE eql_v3.max(eql_v3.int4_ord_ore) (" in sql def test_render_aggregate_state_function_is_not_inlinable(): @@ -326,11 +326,11 @@ def test_render_operator_for_containment_omits_commutator(): must still omit those clauses.""" sql = render_operator( op="@>", backing="contains", - leftarg="eql_v2_int4_ord", rightarg="eql_v2_int4_ord", + leftarg="eql_v3.int4_ord", rightarg="eql_v3.int4_ord", supported=True, ) assert "CREATE OPERATOR @> (" in sql - assert "FUNCTION = eql_v2.contains" in sql + assert "FUNCTION = eql_v3.contains" in sql assert "COMMUTATOR" not in sql assert "NEGATOR" not in sql assert "RESTRICT" not in sql @@ -347,7 +347,7 @@ def test_render_operator_unsupported_emits_placeholder_comment(): domain.""" sql = render_operator( op="<", backing="lt", - leftarg="eql_v2_int4_eq", rightarg="eql_v2_int4_eq", + leftarg="eql_v3.int4_eq", rightarg="eql_v3.int4_eq", supported=False, ) assert sql.startswith("-- Placeholder:") @@ -361,7 +361,7 @@ def test_render_operator_supported_has_no_placeholder_comment(): """Supported operators route to real wrappers — no placeholder comment.""" sql = render_operator( op="=", backing="eq", - leftarg="eql_v2_int4_eq", rightarg="eql_v2_int4_eq", + leftarg="eql_v3.int4_eq", rightarg="eql_v3.int4_eq", supported=True, ) assert "Placeholder" not in sql @@ -380,7 +380,7 @@ def test_render_aggregate_state_function_emits_plpgsql_rationale_comment(): assert "not index" in sql # The rationale precedes the state-function definition. assert sql.index("-- LANGUAGE plpgsql, not sql:") < sql.index( - "CREATE FUNCTION eql_v2.min_sfunc" + "CREATE FUNCTION eql_v3.min_sfunc" ) @@ -396,8 +396,8 @@ def test_render_aggregate_enables_parallel_and_combinefunc(): assert "LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE" in sql # ...and the aggregate must declare the combinefunc + parallel safety # inside the CREATE AGGREGATE option list (not merely in prose). - aggregate_body = sql[sql.index(f"CREATE AGGREGATE eql_v2.{op_name}"):] - assert f"combinefunc = eql_v2.{sfunc}" in aggregate_body + aggregate_body = sql[sql.index(f"CREATE AGGREGATE eql_v3.{op_name}"):] + assert f"combinefunc = eql_v3.{sfunc}" in aggregate_body assert "parallel = safe" in aggregate_body # The stale "intentionally disabled" omission note must be gone. assert "intentionally disabled" not in sql @@ -479,13 +479,13 @@ def test_blocker_escapes_quote_bearing_domain_in_rendered_sql(): string literals.)""" domain = DomainSpec(name="o'dom", terms=[]) sql = render_blocker_bool( - domain, op="<", arg_a="eql_v2_o'dom", arg_b="eql_v2_o'dom", + domain, op="<", arg_a="eql_v3.o'dom", arg_b="eql_v3.o'dom", ) # The dom flows into encrypted_domain_unsupported_bool('', '') # as a single-quoted literal — the quote must be doubled. - assert "encrypted_domain_unsupported_bool('eql_v2_o''dom', '<')" in sql + assert "encrypted_domain_unsupported_bool('eql_v3.o''dom', '<')" in sql # The raw, unescaped single-quoted form must not appear. - assert "'eql_v2_o'dom'" not in sql + assert "'eql_v3.o'dom'" not in sql def test_domain_block_escapes_quote_bearing_key_in_check(): @@ -495,5 +495,5 @@ def test_domain_block_escapes_quote_bearing_key_in_check(): # literal escaping in the IF NOT EXISTS guard. quoted = DomainSpec(name="we'ird", terms=[]) sql = render_domain_block(quoted, "int4") - assert "typname = 'eql_v2_we''ird'" in sql - assert "typname = 'eql_v2_we'ird'" not in sql + assert "typname = 'we''ird'" in sql + assert "typname = 'we'ird'" not in sql diff --git a/tasks/pin_search_path.sql b/tasks/pin_search_path.sql index 168a9478..774be740 100644 --- a/tasks/pin_search_path.sql +++ b/tasks/pin_search_path.sql @@ -250,7 +250,7 @@ BEGIN SELECT p.oid FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace - WHERE n.nspname = 'eql_v2' + WHERE n.nspname IN ('eql_v2', 'eql_v3') -- Only normal functions ('f') and window functions ('w') accept -- ALTER FUNCTION ... SET. Aggregates ('a') would be rejected by -- ALTER ROUTINE/FUNCTION, and procedures ('p') would need ALTER @@ -266,13 +266,16 @@ BEGIN -- A new encrypted-domain type needs NO edit here: its inline-critical -- extractors and comparison wrappers are recognised by the identity -- predicate — LANGUAGE sql, IMMUTABLE, and taking at least one argument - -- typed as a jsonb-backed DOMAIN in `public` named `eql_v2_*`. The + -- typed as a jsonb-backed DOMAIN of the encrypted-domain families. The + -- families live in the `eql_v3` schema (e.g. `eql_v3.int4_eq`); the + -- legacy `public.eql_v2_*` form is kept for any pre-v3 domain. The -- predicate is proconfig-independent: the outer loop has already -- excluded any function with a pinned `search_path`, so the only -- functions reaching here are unpinned. This catches no core function: -- `eql_v2_encrypted` is a composite type (not a domain), `ste_vec_entry` - -- is a domain in `eql_v2` (not `public`), and `hmac_256` is a domain - -- over `text` (not `jsonb`). + -- is a domain in `eql_v2` (not `eql_v3`/`public`), and `hmac_256` is a + -- domain over `text` (not `jsonb`). The eql_v3 blockers are plpgsql, so + -- the LANGUAGE-sql guard leaves them to be pinned as intended. AND NOT ( p.prolang = (SELECT l.oid FROM pg_catalog.pg_language l WHERE l.lanname = 'sql') @@ -283,9 +286,11 @@ BEGIN JOIN pg_catalog.pg_type dt ON dt.oid = arg.typ JOIN pg_catalog.pg_namespace dn ON dn.oid = dt.typnamespace WHERE dt.typtype = 'd' - AND dn.nspname = 'public' - AND dt.typname LIKE 'eql_v2\_%' AND dt.typbasetype = jsonb_oid + AND ( + dn.nspname = 'eql_v3' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) ) ) -- Encrypted-domain family — comment-marker fallback. Covers a diff --git a/tasks/test/splinter.sh b/tasks/test/splinter.sh index 6c203233..a01de51a 100755 --- a/tasks/test/splinter.sh +++ b/tasks/test/splinter.sh @@ -10,7 +10,7 @@ set -euo pipefail # Scope: only findings in EQL-owned schemas are gated. -EQL_OWNED_SCHEMAS="('eql_v2')" +EQL_OWNED_SCHEMAS="('eql_v2', 'eql_v3')" # Pinned to splinter main as of 2026-04-27. Bump intentionally. SPLINTER_SHA="55db5b1f28e58d816f7d9136eed87eabcd95868d" @@ -84,12 +84,12 @@ function_search_path_mutable eql_v2 jsonb_contained_by function GIN-inlining: sa function_search_path_mutable eql_v2 ore_cllw function Consolidated ORE-CLLW extractor (U-006): inlinable SQL so the planner can fold `eql_v2.ore_cllw(col -> 'sel')` calls into the calling query. SET search_path would silently undo the inlining and prevent functional-index match through the extractor form. Two overloads: (jsonb), (eql_v2.ste_vec_entry). function_search_path_mutable eql_v2 has_ore_cllw function Consolidated ORE-CLLW presence check (U-006): inlinable SQL counterpart to `eql_v2.ore_cllw`. Same rationale as `ore_cllw` — must stay unpinned to inline into the calling query. Two overloads: (jsonb), (eql_v2.ste_vec_entry). function_search_path_mutable eql_v2 selector function STE-vec entry selector extractor (#219): typed (eql_v2.ste_vec_entry) overload, inlinable so the planner can fold `eql_v2.selector(col -> 'sel')` into the calling query. -function_search_path_mutable eql_v2 eq function Equality backing function for `eql_v2.ste_vec_entry × eql_v2.ste_vec_entry` (#219). Inlines to `hmac_256(a) = hmac_256(b)`; the `=` operator must reach the functional hash index on `eql_v2.hmac_256(col -> 'sel')` for bare-form field equality to engage Index Scan. Splinter matches by name only, so this row also covers the converged eql_v2.eq wrappers on eql_v2_int4_eq / _ord / _ord_ore (PR #225). -function_search_path_mutable eql_v2 neq function Inequality backing function for `eql_v2.ste_vec_entry`. Same rationale as `eq`. Also covers the converged eql_v2.neq wrappers on eql_v2_int4_eq / _ord / _ord_ore (PR #225). -function_search_path_mutable eql_v2 lt function Less-than backing function for `eql_v2.ste_vec_entry`. Inlines to `ore_cllw(a) < ore_cllw(b)`; must reach the functional btree opclass on `eql_v2.ore_cllw` for ordered field queries to engage Index Scan. Splinter matches by name only, so this row also covers the converged eql_v2.lt wrappers on eql_v2_int4_ord / _ord_ore (PR #225). -function_search_path_mutable eql_v2 lte function Less-than-or-equal backing function for `eql_v2.ste_vec_entry`. Same rationale as `lt`. Also covers the converged eql_v2.lte wrappers on eql_v2_int4_ord / _ord_ore (PR #225). -function_search_path_mutable eql_v2 gt function Greater-than backing function for `eql_v2.ste_vec_entry`. Same rationale as `lt`. Also covers the converged eql_v2.gt wrappers on eql_v2_int4_ord / _ord_ore (PR #225). -function_search_path_mutable eql_v2 gte function Greater-than-or-equal backing function for `eql_v2.ste_vec_entry`. Same rationale as `lt`. Also covers the converged eql_v2.gte wrappers on eql_v2_int4_ord / _ord_ore (PR #225). +function_search_path_mutable eql_v2 eq function Equality backing function for `eql_v2.ste_vec_entry × eql_v2.ste_vec_entry` (#219). Inlines to `hmac_256(a) = hmac_256(b)`; the `=` operator must reach the functional hash index on `eql_v2.hmac_256(col -> 'sel')` for bare-form field equality to engage Index Scan. (The converged int4 wrappers moved to the eql_v3 schema — see the eql_v3 rows below.) +function_search_path_mutable eql_v2 neq function Inequality backing function for `eql_v2.ste_vec_entry`. Same rationale as `eq`. +function_search_path_mutable eql_v2 lt function Less-than backing function for `eql_v2.ste_vec_entry`. Inlines to `ore_cllw(a) < ore_cllw(b)`; must reach the functional btree opclass on `eql_v2.ore_cllw` for ordered field queries to engage Index Scan. +function_search_path_mutable eql_v2 lte function Less-than-or-equal backing function for `eql_v2.ste_vec_entry`. Same rationale as `lt`. +function_search_path_mutable eql_v2 gt function Greater-than backing function for `eql_v2.ste_vec_entry`. Same rationale as `lt`. +function_search_path_mutable eql_v2 gte function Greater-than-or-equal backing function for `eql_v2.ste_vec_entry`. Same rationale as `lt`. function_search_path_mutable eql_v2 ore_cllw_eq function Inner comparator for the `eql_v2.ore_cllw` type's `=` operator (#221). The outer same-type operators back the btree opclass on `eql_v2.ore_cllw`; the planner only carries the inlined form through to functional-index match if this inner function is also inlinable (no SET, IMMUTABLE). Mirrors ore_block_u64_8_256_eq. function_search_path_mutable eql_v2 ore_cllw_neq function Inner comparator for the `eql_v2.ore_cllw` type's `<>` operator (#221). Same rationale as `ore_cllw_eq`. function_search_path_mutable eql_v2 ore_cllw_lt function Inner comparator for the `eql_v2.ore_cllw` type's `<` operator (#221). Same rationale as `ore_cllw_eq`. @@ -97,11 +97,26 @@ function_search_path_mutable eql_v2 ore_cllw_lte function Inner comparator for t function_search_path_mutable eql_v2 ore_cllw_gt function Inner comparator for the `eql_v2.ore_cllw` type's `>` operator (#221). Same rationale as `ore_cllw_eq`. function_search_path_mutable eql_v2 ore_cllw_gte function Inner comparator for the `eql_v2.ore_cllw` type's `>=` operator (#221). Same rationale as `ore_cllw_eq`. function_search_path_mutable eql_v2 -> function Typed sv-element selector lookup (U-007): inlinable SQL so the planner can fold `col -> ''` into the calling query, preserving functional-index match for the chained recipes `WHERE col -> 'sel' = $1::ste_vec_entry` (via eq_term) and `ORDER BY eql_v2.ore_cllw(col -> 'sel')`. Three overloads: (enc, text), (enc, enc), (enc, int). -function_search_path_mutable eql_v2 eq_term function XOR-aware equality term extractor on a ste_vec entry (U-007): coalesces hm and oc as bytea. Must inline so `eql_v2.eq_term(col -> 'sel')` folds into the calling query and matches a functional hash index built on the same expression — same precedent as ore_cllw / hmac_256 extractors on ste_vec_entry. Also covers the eql_v2_int4_eq eq_term overload (PR #225). +function_search_path_mutable eql_v2 eq_term function XOR-aware equality term extractor on a ste_vec entry (U-007): coalesces hm and oc as bytea. Must inline so `eql_v2.eq_term(col -> 'sel')` folds into the calling query and matches a functional hash index built on the same expression — same precedent as ore_cllw / hmac_256 extractors on ste_vec_entry. (The eql_v3.int4_eq eq_term extractor is a separate overload in the eql_v3 schema — see the eql_v3 rows below.) function_search_path_mutable eql_v2 min function Aggregate (splinter labels these type=function): ALTER AGGREGATE has no SET configuration_parameter syntax, and ALTER ROUTINE/FUNCTION reject aggregates. The aggregate's SFUNC has a pinned search_path. function_search_path_mutable eql_v2 max function Aggregate: same as min. function_search_path_mutable eql_v2 grouped_value function Aggregate: same as min. -function_search_path_mutable eql_v2 ord_term function eql_v2_int4 ordered-variant index extractor: returns eql_v2.ore_block_u64_8_256 (carrying main DEFAULT btree opclass). Used inside the inlinable comparison wrappers and as the functional-index expression USING btree (eql_v2.ord_term(col)); must inline. SET search_path would disable SQL function inlining (see PostgreSQL inline_function). Covers both ord_term overloads (eql_v2_int4_ord_ore, eql_v2_int4_ord). +# Encrypted-domain families live in the eql_v3 schema (the int4 family and +# future scalar domains). Their inlinable extractors and comparison wrappers +# must stay unpinned for functional-index matching, exactly as the eql_v2 +# encrypted-type operators above; splinter matches by (schema, name, type), so +# they need their own rows. The plpgsql blockers are pinned by +# tasks/pin_search_path.sql and do not surface here. +function_search_path_mutable eql_v3 eq_term function HMAC equality term extractor for the eql_v3 *_eq domains: returns eql_v2.hmac_256. Must inline so `eql_v3.eq_term(col)` folds into the calling query and matches the functional hash/btree index built on the same expression. SET search_path would disable SQL function inlining (see PostgreSQL inline_function). +function_search_path_mutable eql_v3 ord_term function ORE-block order term extractor for the eql_v3 ordered domains: returns eql_v2.ore_block_u64_8_256 (carrying the main DEFAULT btree opclass). Used inside the inlinable comparison wrappers and as the functional-index expression USING btree (eql_v3.ord_term(col)); must inline. Covers both ord_term overloads (eql_v3.int4_ord, eql_v3.int4_ord_ore). +function_search_path_mutable eql_v3 eq function Equality comparison wrapper on the eql_v3 domains. Inlines to `eq_term(a) = eq_term(b)`; must reach the functional index on eql_v3.eq_term(col) for bare-form equality to engage Index Scan. Covers the converged eq wrappers on the eql_v3 int4 variants. +function_search_path_mutable eql_v3 neq function Inequality comparison wrapper on the eql_v3 domains. Same rationale as eql_v3.eq. +function_search_path_mutable eql_v3 lt function Less-than comparison wrapper on the eql_v3 ordered domains. Inlines to `ord_term(a) < ord_term(b)`; must reach the functional btree index on eql_v3.ord_term(col) for range queries to engage Index Scan. +function_search_path_mutable eql_v3 lte function Less-than-or-equal comparison wrapper on the eql_v3 ordered domains. Same rationale as eql_v3.lt. +function_search_path_mutable eql_v3 gt function Greater-than comparison wrapper on the eql_v3 ordered domains. Same rationale as eql_v3.lt. +function_search_path_mutable eql_v3 gte function Greater-than-or-equal comparison wrapper on the eql_v3 ordered domains. Same rationale as eql_v3.lt. +function_search_path_mutable eql_v3 min function Per-domain MIN aggregate on the eql_v3 ordered domains (splinter labels aggregates type=function): ALTER AGGREGATE has no SET configuration_parameter syntax, and ALTER ROUTINE/FUNCTION reject aggregates. The aggregate's SFUNC carries a pinned search_path. +function_search_path_mutable eql_v3 max function Per-domain MAX aggregate on the eql_v3 ordered domains. Same as eql_v3.min. ALLOW # Wrap splinter (a single bare SELECT expression) into a subquery we can diff --git a/tasks/uninstall-protect.sql b/tasks/uninstall-protect.sql index 83fddc7d..eb48602e 100644 --- a/tasks/uninstall-protect.sql +++ b/tasks/uninstall-protect.sql @@ -1 +1,2 @@ DROP SCHEMA IF EXISTS eql_v2 CASCADE; +DROP SCHEMA IF EXISTS eql_v3 CASCADE; diff --git a/tasks/uninstall.sql b/tasks/uninstall.sql index d7777870..e087e2a8 100644 --- a/tasks/uninstall.sql +++ b/tasks/uninstall.sql @@ -10,3 +10,8 @@ END $$; DROP SCHEMA IF EXISTS eql_v2 CASCADE; + +-- Encrypted-domain families (eql_v3.int4 and future scalar domains) live in +-- their own schema; drop it too. CASCADE removes the domains and any columns +-- typed with them. +DROP SCHEMA IF EXISTS eql_v3 CASCADE; diff --git a/tests/codegen/reference/int4/int4_eq_functions.sql b/tests/codegen/reference/int4/int4_eq_functions.sql index f1fe0d70..14344ba2 100644 --- a/tests/codegen/reference/int4/int4_eq_functions.sql +++ b/tests/codegen/reference/int4/int4_eq_functions.sql @@ -1,5 +1,6 @@ -- REFERENCE: hand-written parity baseline for tasks/codegen/ — see ../README.md -- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql -- REQUIRE: src/encrypted_domain/int4/int4_types.sql -- REQUIRE: src/encrypted_domain/functions.sql -- REQUIRE: src/hmac_256/functions.sql @@ -7,400 +8,400 @@ --! @file encrypted_domain/int4/int4_eq_functions.sql --! @brief Equality-only domain of the int4 encrypted-domain family — comparison/path functions. ---! @brief Index extractor for the eql_v2_int4_eq variant. ---! @param a eql_v2_int4_eq +--! @brief Index extractor for the eql_v3.int4_eq variant. +--! @param a eql_v3.int4_eq --! @return eql_v2.hmac_256 -CREATE FUNCTION eql_v2.eq_term(a eql_v2_int4_eq) +CREATE FUNCTION eql_v3.eq_term(a eql_v3.int4_eq) RETURNS eql_v2.hmac_256 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS $$ SELECT eql_v2.hmac_256(a::jsonb) $$; ---! @brief Equality wrapper for eql_v2_int4_eq. ---! @param a eql_v2_int4_eq ---! @param b eql_v2_int4_eq +--! @brief Equality wrapper for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq --! @return boolean -CREATE FUNCTION eql_v2.eq(a eql_v2_int4_eq, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.eq(a eql_v3.int4_eq, b eql_v3.int4_eq) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.eq_term(a) = eql_v2.eq_term(b) $$; +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; ---! @brief Equality wrapper for eql_v2_int4_eq (domain, jsonb). ---! @param a eql_v2_int4_eq +--! @brief Equality wrapper for eql_v3.int4_eq (domain, jsonb). +--! @param a eql_v3.int4_eq --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.eq(a eql_v2_int4_eq, b jsonb) +CREATE FUNCTION eql_v3.eq(a eql_v3.int4_eq, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.eq_term(a) = eql_v2.eq_term(b::eql_v2_int4_eq) $$; +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.int4_eq) $$; ---! @brief Equality wrapper for eql_v2_int4_eq (jsonb, domain). +--! @brief Equality wrapper for eql_v3.int4_eq (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_eq +--! @param b eql_v3.int4_eq --! @return boolean -CREATE FUNCTION eql_v2.eq(a jsonb, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.int4_eq) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.eq_term(a::eql_v2_int4_eq) = eql_v2.eq_term(b) $$; +AS $$ SELECT eql_v3.eq_term(a::eql_v3.int4_eq) = eql_v3.eq_term(b) $$; ---! @brief Inequality wrapper for eql_v2_int4_eq. ---! @param a eql_v2_int4_eq ---! @param b eql_v2_int4_eq +--! @brief Inequality wrapper for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq --! @return boolean -CREATE FUNCTION eql_v2.neq(a eql_v2_int4_eq, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.neq(a eql_v3.int4_eq, b eql_v3.int4_eq) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.eq_term(a) <> eql_v2.eq_term(b) $$; +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; ---! @brief Inequality wrapper for eql_v2_int4_eq (domain, jsonb). ---! @param a eql_v2_int4_eq +--! @brief Inequality wrapper for eql_v3.int4_eq (domain, jsonb). +--! @param a eql_v3.int4_eq --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.neq(a eql_v2_int4_eq, b jsonb) +CREATE FUNCTION eql_v3.neq(a eql_v3.int4_eq, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.eq_term(a) <> eql_v2.eq_term(b::eql_v2_int4_eq) $$; +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.int4_eq) $$; ---! @brief Inequality wrapper for eql_v2_int4_eq (jsonb, domain). +--! @brief Inequality wrapper for eql_v3.int4_eq (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_eq +--! @param b eql_v3.int4_eq --! @return boolean -CREATE FUNCTION eql_v2.neq(a jsonb, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.int4_eq) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.eq_term(a::eql_v2_int4_eq) <> eql_v2.eq_term(b) $$; +AS $$ SELECT eql_v3.eq_term(a::eql_v3.int4_eq) <> eql_v3.eq_term(b) $$; ---! @brief Blocker for < on eql_v2_int4_eq. ---! @param a eql_v2_int4_eq ---! @param b eql_v2_int4_eq +--! @brief Blocker for < on eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.lt(a eql_v2_int4_eq, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.lt(a eql_v3.int4_eq, b eql_v3.int4_eq) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '<'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '<'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for < on eql_v2_int4_eq (domain, jsonb). ---! @param a eql_v2_int4_eq +--! @brief Blocker for < on eql_v3.int4_eq (domain, jsonb). +--! @param a eql_v3.int4_eq --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.lt(a eql_v2_int4_eq, b jsonb) +CREATE FUNCTION eql_v3.lt(a eql_v3.int4_eq, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '<'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '<'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for < on eql_v2_int4_eq (jsonb, domain). +--! @brief Blocker for < on eql_v3.int4_eq (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_eq +--! @param b eql_v3.int4_eq --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.lt(a jsonb, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.int4_eq) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '<'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '<'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <= on eql_v2_int4_eq. ---! @param a eql_v2_int4_eq ---! @param b eql_v2_int4_eq +--! @brief Blocker for <= on eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.lte(a eql_v2_int4_eq, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.lte(a eql_v3.int4_eq, b eql_v3.int4_eq) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '<='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '<='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <= on eql_v2_int4_eq (domain, jsonb). ---! @param a eql_v2_int4_eq +--! @brief Blocker for <= on eql_v3.int4_eq (domain, jsonb). +--! @param a eql_v3.int4_eq --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.lte(a eql_v2_int4_eq, b jsonb) +CREATE FUNCTION eql_v3.lte(a eql_v3.int4_eq, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '<='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '<='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <= on eql_v2_int4_eq (jsonb, domain). +--! @brief Blocker for <= on eql_v3.int4_eq (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_eq +--! @param b eql_v3.int4_eq --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.lte(a jsonb, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.int4_eq) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '<='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '<='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for > on eql_v2_int4_eq. ---! @param a eql_v2_int4_eq ---! @param b eql_v2_int4_eq +--! @brief Blocker for > on eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.gt(a eql_v2_int4_eq, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.gt(a eql_v3.int4_eq, b eql_v3.int4_eq) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for > on eql_v2_int4_eq (domain, jsonb). ---! @param a eql_v2_int4_eq +--! @brief Blocker for > on eql_v3.int4_eq (domain, jsonb). +--! @param a eql_v3.int4_eq --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.gt(a eql_v2_int4_eq, b jsonb) +CREATE FUNCTION eql_v3.gt(a eql_v3.int4_eq, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for > on eql_v2_int4_eq (jsonb, domain). +--! @brief Blocker for > on eql_v3.int4_eq (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_eq +--! @param b eql_v3.int4_eq --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.gt(a jsonb, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.int4_eq) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for >= on eql_v2_int4_eq. ---! @param a eql_v2_int4_eq ---! @param b eql_v2_int4_eq +--! @brief Blocker for >= on eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.gte(a eql_v2_int4_eq, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.gte(a eql_v3.int4_eq, b eql_v3.int4_eq) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '>='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '>='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for >= on eql_v2_int4_eq (domain, jsonb). ---! @param a eql_v2_int4_eq +--! @brief Blocker for >= on eql_v3.int4_eq (domain, jsonb). +--! @param a eql_v3.int4_eq --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.gte(a eql_v2_int4_eq, b jsonb) +CREATE FUNCTION eql_v3.gte(a eql_v3.int4_eq, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '>='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '>='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for >= on eql_v2_int4_eq (jsonb, domain). +--! @brief Blocker for >= on eql_v3.int4_eq (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_eq +--! @param b eql_v3.int4_eq --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.gte(a jsonb, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.int4_eq) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '>='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '>='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @> on eql_v2_int4_eq. ---! @param a eql_v2_int4_eq ---! @param b eql_v2_int4_eq +--! @brief Blocker for @> on eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contains(a eql_v2_int4_eq, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.contains(a eql_v3.int4_eq, b eql_v3.int4_eq) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '@>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '@>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @> on eql_v2_int4_eq (domain, jsonb). ---! @param a eql_v2_int4_eq +--! @brief Blocker for @> on eql_v3.int4_eq (domain, jsonb). +--! @param a eql_v3.int4_eq --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contains(a eql_v2_int4_eq, b jsonb) +CREATE FUNCTION eql_v3.contains(a eql_v3.int4_eq, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '@>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '@>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @> on eql_v2_int4_eq (jsonb, domain). +--! @brief Blocker for @> on eql_v3.int4_eq (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_eq +--! @param b eql_v3.int4_eq --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contains(a jsonb, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.int4_eq) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '@>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '@>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <@ on eql_v2_int4_eq. ---! @param a eql_v2_int4_eq ---! @param b eql_v2_int4_eq +--! @brief Blocker for <@ on eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contained_by(a eql_v2_int4_eq, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4_eq, b eql_v3.int4_eq) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '<@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '<@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <@ on eql_v2_int4_eq (domain, jsonb). ---! @param a eql_v2_int4_eq +--! @brief Blocker for <@ on eql_v3.int4_eq (domain, jsonb). +--! @param a eql_v3.int4_eq --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contained_by(a eql_v2_int4_eq, b jsonb) +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4_eq, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '<@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '<@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <@ on eql_v2_int4_eq (jsonb, domain). +--! @brief Blocker for <@ on eql_v3.int4_eq (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_eq +--! @param b eql_v3.int4_eq --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contained_by(a jsonb, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.int4_eq) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '<@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '<@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for -> on eql_v2_int4_eq (domain, text). ---! @param a eql_v2_int4_eq +--! @brief Blocker for -> on eql_v3.int4_eq (domain, text). +--! @param a eql_v3.int4_eq --! @param selector text ---! @return eql_v2_int4_eq (never returns; always raises) -CREATE FUNCTION eql_v2."->"(a eql_v2_int4_eq, selector text) -RETURNS eql_v2_int4_eq IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v2_int4_eq'; END; $$ +--! @return eql_v3.int4_eq (never returns; always raises) +CREATE FUNCTION eql_v3."->"(a eql_v3.int4_eq, selector text) +RETURNS eql_v3.int4_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for -> on eql_v2_int4_eq (domain, integer). ---! @param a eql_v2_int4_eq +--! @brief Blocker for -> on eql_v3.int4_eq (domain, integer). +--! @param a eql_v3.int4_eq --! @param selector integer ---! @return eql_v2_int4_eq (never returns; always raises) -CREATE FUNCTION eql_v2."->"(a eql_v2_int4_eq, selector integer) -RETURNS eql_v2_int4_eq IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v2_int4_eq'; END; $$ +--! @return eql_v3.int4_eq (never returns; always raises) +CREATE FUNCTION eql_v3."->"(a eql_v3.int4_eq, selector integer) +RETURNS eql_v3.int4_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for -> on eql_v2_int4_eq (jsonb, domain). +--! @brief Blocker for -> on eql_v3.int4_eq (jsonb, domain). --! @param a jsonb ---! @param selector eql_v2_int4_eq ---! @return eql_v2_int4_eq (never returns; always raises) -CREATE FUNCTION eql_v2."->"(a jsonb, selector eql_v2_int4_eq) -RETURNS eql_v2_int4_eq IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v2_int4_eq'; END; $$ +--! @param selector eql_v3.int4_eq +--! @return eql_v3.int4_eq (never returns; always raises) +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int4_eq) +RETURNS eql_v3.int4_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ->> on eql_v2_int4_eq (domain, text). ---! @param a eql_v2_int4_eq +--! @brief Blocker for ->> on eql_v3.int4_eq (domain, text). +--! @param a eql_v3.int4_eq --! @param selector text --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."->>"(a eql_v2_int4_eq, selector text) +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4_eq, selector text) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v2_int4_eq'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ->> on eql_v2_int4_eq (domain, integer). ---! @param a eql_v2_int4_eq +--! @brief Blocker for ->> on eql_v3.int4_eq (domain, integer). +--! @param a eql_v3.int4_eq --! @param selector integer --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."->>"(a eql_v2_int4_eq, selector integer) +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4_eq, selector integer) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v2_int4_eq'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ->> on eql_v2_int4_eq (jsonb, domain). +--! @brief Blocker for ->> on eql_v3.int4_eq (jsonb, domain). --! @param a jsonb ---! @param selector eql_v2_int4_eq +--! @param selector eql_v3.int4_eq --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."->>"(a jsonb, selector eql_v2_int4_eq) +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.int4_eq) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v2_int4_eq'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ? on eql_v2_int4_eq (domain, text). ---! @param a eql_v2_int4_eq +--! @brief Blocker for ? on eql_v3.int4_eq (domain, text). +--! @param a eql_v3.int4_eq --! @param b text --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."?"(a eql_v2_int4_eq, b text) +CREATE FUNCTION eql_v3."?"(a eql_v3.int4_eq, b text) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '?'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '?'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ?| on eql_v2_int4_eq (domain, text[]). ---! @param a eql_v2_int4_eq +--! @brief Blocker for ?| on eql_v3.int4_eq (domain, text[]). +--! @param a eql_v3.int4_eq --! @param b text[] --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."?|"(a eql_v2_int4_eq, b text[]) +CREATE FUNCTION eql_v3."?|"(a eql_v3.int4_eq, b text[]) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '?|'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '?|'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ?& on eql_v2_int4_eq (domain, text[]). ---! @param a eql_v2_int4_eq +--! @brief Blocker for ?& on eql_v3.int4_eq (domain, text[]). +--! @param a eql_v3.int4_eq --! @param b text[] --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."?&"(a eql_v2_int4_eq, b text[]) +CREATE FUNCTION eql_v3."?&"(a eql_v3.int4_eq, b text[]) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '?&'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '?&'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @? on eql_v2_int4_eq (domain, jsonpath). ---! @param a eql_v2_int4_eq +--! @brief Blocker for @? on eql_v3.int4_eq (domain, jsonpath). +--! @param a eql_v3.int4_eq --! @param b jsonpath --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."@?"(a eql_v2_int4_eq, b jsonpath) +CREATE FUNCTION eql_v3."@?"(a eql_v3.int4_eq, b jsonpath) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '@?'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '@?'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @@ on eql_v2_int4_eq (domain, jsonpath). ---! @param a eql_v2_int4_eq +--! @brief Blocker for @@ on eql_v3.int4_eq (domain, jsonpath). +--! @param a eql_v3.int4_eq --! @param b jsonpath --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."@@"(a eql_v2_int4_eq, b jsonpath) +CREATE FUNCTION eql_v3."@@"(a eql_v3.int4_eq, b jsonpath) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_eq', '@@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_eq', '@@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for #> on eql_v2_int4_eq (domain, text[]). ---! @param a eql_v2_int4_eq +--! @brief Blocker for #> on eql_v3.int4_eq (domain, text[]). +--! @param a eql_v3.int4_eq --! @param b text[] --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."#>"(a eql_v2_int4_eq, b text[]) +CREATE FUNCTION eql_v3."#>"(a eql_v3.int4_eq, b text[]) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v2_int4_eq'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for #>> on eql_v2_int4_eq (domain, text[]). ---! @param a eql_v2_int4_eq +--! @brief Blocker for #>> on eql_v3.int4_eq (domain, text[]). +--! @param a eql_v3.int4_eq --! @param b text[] --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."#>>"(a eql_v2_int4_eq, b text[]) +CREATE FUNCTION eql_v3."#>>"(a eql_v3.int4_eq, b text[]) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v2_int4_eq'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for - on eql_v2_int4_eq (domain, text). ---! @param a eql_v2_int4_eq +--! @brief Blocker for - on eql_v3.int4_eq (domain, text). +--! @param a eql_v3.int4_eq --! @param b text --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."-"(a eql_v2_int4_eq, b text) +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_eq, b text) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v2_int4_eq'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for - on eql_v2_int4_eq (domain, integer). ---! @param a eql_v2_int4_eq +--! @brief Blocker for - on eql_v3.int4_eq (domain, integer). +--! @param a eql_v3.int4_eq --! @param b integer --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."-"(a eql_v2_int4_eq, b integer) +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_eq, b integer) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v2_int4_eq'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for - on eql_v2_int4_eq (domain, text[]). ---! @param a eql_v2_int4_eq +--! @brief Blocker for - on eql_v3.int4_eq (domain, text[]). +--! @param a eql_v3.int4_eq --! @param b text[] --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."-"(a eql_v2_int4_eq, b text[]) +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_eq, b text[]) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v2_int4_eq'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for #- on eql_v2_int4_eq (domain, text[]). ---! @param a eql_v2_int4_eq +--! @brief Blocker for #- on eql_v3.int4_eq (domain, text[]). +--! @param a eql_v3.int4_eq --! @param b text[] --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."#-"(a eql_v2_int4_eq, b text[]) +CREATE FUNCTION eql_v3."#-"(a eql_v3.int4_eq, b text[]) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v2_int4_eq'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for || on eql_v2_int4_eq. ---! @param a eql_v2_int4_eq ---! @param b eql_v2_int4_eq +--! @brief Blocker for || on eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."||"(a eql_v2_int4_eq, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3."||"(a eql_v3.int4_eq, b eql_v3.int4_eq) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v2_int4_eq'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for || on eql_v2_int4_eq (domain, jsonb). ---! @param a eql_v2_int4_eq +--! @brief Blocker for || on eql_v3.int4_eq (domain, jsonb). +--! @param a eql_v3.int4_eq --! @param b jsonb --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."||"(a eql_v2_int4_eq, b jsonb) +CREATE FUNCTION eql_v3."||"(a eql_v3.int4_eq, b jsonb) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v2_int4_eq'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for || on eql_v2_int4_eq (jsonb, domain). +--! @brief Blocker for || on eql_v3.int4_eq (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_eq +--! @param b eql_v3.int4_eq --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."||"(a jsonb, b eql_v2_int4_eq) +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int4_eq) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v2_int4_eq'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_eq'; END; $$ LANGUAGE plpgsql; diff --git a/tests/codegen/reference/int4/int4_eq_operators.sql b/tests/codegen/reference/int4/int4_eq_operators.sql index 85d8353c..a39951f6 100644 --- a/tests/codegen/reference/int4/int4_eq_operators.sql +++ b/tests/codegen/reference/int4/int4_eq_operators.sql @@ -1,5 +1,5 @@ -- REFERENCE: hand-written parity baseline for tasks/codegen/ — see ../README.md --- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql -- REQUIRE: src/encrypted_domain/int4/int4_types.sql -- REQUIRE: src/encrypted_domain/int4/int4_eq_functions.sql @@ -7,265 +7,265 @@ --! @brief Equality-only domain of the int4 encrypted-domain family — operator declarations. CREATE OPERATOR = ( - FUNCTION = eql_v2.eq, - LEFTARG = eql_v2_int4_eq, RIGHTARG = eql_v2_int4_eq, + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq, COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel ); CREATE OPERATOR = ( - FUNCTION = eql_v2.eq, - LEFTARG = eql_v2_int4_eq, RIGHTARG = jsonb, + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb, COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel ); CREATE OPERATOR = ( - FUNCTION = eql_v2.eq, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_eq, + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq, COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel ); CREATE OPERATOR <> ( - FUNCTION = eql_v2.neq, - LEFTARG = eql_v2_int4_eq, RIGHTARG = eql_v2_int4_eq, + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq, COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel ); CREATE OPERATOR <> ( - FUNCTION = eql_v2.neq, - LEFTARG = eql_v2_int4_eq, RIGHTARG = jsonb, + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb, COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel ); CREATE OPERATOR <> ( - FUNCTION = eql_v2.neq, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_eq, + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq, COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel ); -- Placeholder: this domain's term set does not support <; the backing function always raises. CREATE OPERATOR < ( - FUNCTION = eql_v2.lt, - LEFTARG = eql_v2_int4_eq, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support <; the backing function always raises. CREATE OPERATOR < ( - FUNCTION = eql_v2.lt, - LEFTARG = eql_v2_int4_eq, RIGHTARG = jsonb + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support <; the backing function always raises. CREATE OPERATOR < ( - FUNCTION = eql_v2.lt, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support <=; the backing function always raises. CREATE OPERATOR <= ( - FUNCTION = eql_v2.lte, - LEFTARG = eql_v2_int4_eq, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support <=; the backing function always raises. CREATE OPERATOR <= ( - FUNCTION = eql_v2.lte, - LEFTARG = eql_v2_int4_eq, RIGHTARG = jsonb + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support <=; the backing function always raises. CREATE OPERATOR <= ( - FUNCTION = eql_v2.lte, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support >; the backing function always raises. CREATE OPERATOR > ( - FUNCTION = eql_v2.gt, - LEFTARG = eql_v2_int4_eq, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support >; the backing function always raises. CREATE OPERATOR > ( - FUNCTION = eql_v2.gt, - LEFTARG = eql_v2_int4_eq, RIGHTARG = jsonb + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support >; the backing function always raises. CREATE OPERATOR > ( - FUNCTION = eql_v2.gt, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support >=; the backing function always raises. CREATE OPERATOR >= ( - FUNCTION = eql_v2.gte, - LEFTARG = eql_v2_int4_eq, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support >=; the backing function always raises. CREATE OPERATOR >= ( - FUNCTION = eql_v2.gte, - LEFTARG = eql_v2_int4_eq, RIGHTARG = jsonb + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support >=; the backing function always raises. CREATE OPERATOR >= ( - FUNCTION = eql_v2.gte, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support @>; the backing function always raises. CREATE OPERATOR @> ( - FUNCTION = eql_v2.contains, - LEFTARG = eql_v2_int4_eq, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support @>; the backing function always raises. CREATE OPERATOR @> ( - FUNCTION = eql_v2.contains, - LEFTARG = eql_v2_int4_eq, RIGHTARG = jsonb + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support @>; the backing function always raises. CREATE OPERATOR @> ( - FUNCTION = eql_v2.contains, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support <@; the backing function always raises. CREATE OPERATOR <@ ( - FUNCTION = eql_v2.contained_by, - LEFTARG = eql_v2_int4_eq, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support <@; the backing function always raises. CREATE OPERATOR <@ ( - FUNCTION = eql_v2.contained_by, - LEFTARG = eql_v2_int4_eq, RIGHTARG = jsonb + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support <@; the backing function always raises. CREATE OPERATOR <@ ( - FUNCTION = eql_v2.contained_by, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support ->; the backing function always raises. CREATE OPERATOR -> ( - FUNCTION = eql_v2."->", - LEFTARG = eql_v2_int4_eq, RIGHTARG = text + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text ); -- Placeholder: this domain's term set does not support ->; the backing function always raises. CREATE OPERATOR -> ( - FUNCTION = eql_v2."->", - LEFTARG = eql_v2_int4_eq, RIGHTARG = integer + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4_eq, RIGHTARG = integer ); -- Placeholder: this domain's term set does not support ->; the backing function always raises. CREATE OPERATOR -> ( - FUNCTION = eql_v2."->", - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support ->>; the backing function always raises. CREATE OPERATOR ->> ( - FUNCTION = eql_v2."->>", - LEFTARG = eql_v2_int4_eq, RIGHTARG = text + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text ); -- Placeholder: this domain's term set does not support ->>; the backing function always raises. CREATE OPERATOR ->> ( - FUNCTION = eql_v2."->>", - LEFTARG = eql_v2_int4_eq, RIGHTARG = integer + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4_eq, RIGHTARG = integer ); -- Placeholder: this domain's term set does not support ->>; the backing function always raises. CREATE OPERATOR ->> ( - FUNCTION = eql_v2."->>", - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support ?; the backing function always raises. CREATE OPERATOR ? ( - FUNCTION = eql_v2."?", - LEFTARG = eql_v2_int4_eq, RIGHTARG = text + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text ); -- Placeholder: this domain's term set does not support ?|; the backing function always raises. CREATE OPERATOR ?| ( - FUNCTION = eql_v2."?|", - LEFTARG = eql_v2_int4_eq, RIGHTARG = text[] + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support ?&; the backing function always raises. CREATE OPERATOR ?& ( - FUNCTION = eql_v2."?&", - LEFTARG = eql_v2_int4_eq, RIGHTARG = text[] + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support @?; the backing function always raises. CREATE OPERATOR @? ( - FUNCTION = eql_v2."@?", - LEFTARG = eql_v2_int4_eq, RIGHTARG = jsonpath + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonpath ); -- Placeholder: this domain's term set does not support @@; the backing function always raises. CREATE OPERATOR @@ ( - FUNCTION = eql_v2."@@", - LEFTARG = eql_v2_int4_eq, RIGHTARG = jsonpath + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonpath ); -- Placeholder: this domain's term set does not support #>; the backing function always raises. CREATE OPERATOR #> ( - FUNCTION = eql_v2."#>", - LEFTARG = eql_v2_int4_eq, RIGHTARG = text[] + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support #>>; the backing function always raises. CREATE OPERATOR #>> ( - FUNCTION = eql_v2."#>>", - LEFTARG = eql_v2_int4_eq, RIGHTARG = text[] + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support -; the backing function always raises. CREATE OPERATOR - ( - FUNCTION = eql_v2."-", - LEFTARG = eql_v2_int4_eq, RIGHTARG = text + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text ); -- Placeholder: this domain's term set does not support -; the backing function always raises. CREATE OPERATOR - ( - FUNCTION = eql_v2."-", - LEFTARG = eql_v2_int4_eq, RIGHTARG = integer + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_eq, RIGHTARG = integer ); -- Placeholder: this domain's term set does not support -; the backing function always raises. CREATE OPERATOR - ( - FUNCTION = eql_v2."-", - LEFTARG = eql_v2_int4_eq, RIGHTARG = text[] + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support #-; the backing function always raises. CREATE OPERATOR #- ( - FUNCTION = eql_v2."#-", - LEFTARG = eql_v2_int4_eq, RIGHTARG = text[] + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support ||; the backing function always raises. CREATE OPERATOR || ( - FUNCTION = eql_v2."||", - LEFTARG = eql_v2_int4_eq, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq ); -- Placeholder: this domain's term set does not support ||; the backing function always raises. CREATE OPERATOR || ( - FUNCTION = eql_v2."||", - LEFTARG = eql_v2_int4_eq, RIGHTARG = jsonb + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support ||; the backing function always raises. CREATE OPERATOR || ( - FUNCTION = eql_v2."||", - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_eq + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq ); diff --git a/tests/codegen/reference/int4/int4_functions.sql b/tests/codegen/reference/int4/int4_functions.sql index 27936e1d..a60bc7b1 100644 --- a/tests/codegen/reference/int4/int4_functions.sql +++ b/tests/codegen/reference/int4/int4_functions.sql @@ -1,403 +1,404 @@ -- REFERENCE: hand-written parity baseline for tasks/codegen/ — see ../README.md -- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql -- REQUIRE: src/encrypted_domain/int4/int4_types.sql -- REQUIRE: src/encrypted_domain/functions.sql --! @file encrypted_domain/int4/int4_functions.sql --! @brief Storage-only domain of the int4 encrypted-domain family — comparison/path functions. ---! @brief Blocker for = on eql_v2_int4. ---! @param a eql_v2_int4 ---! @param b eql_v2_int4 +--! @brief Blocker for = on eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.eq(a eql_v2_int4, b eql_v2_int4) +CREATE FUNCTION eql_v3.eq(a eql_v3.int4, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for = on eql_v2_int4 (domain, jsonb). ---! @param a eql_v2_int4 +--! @brief Blocker for = on eql_v3.int4 (domain, jsonb). +--! @param a eql_v3.int4 --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.eq(a eql_v2_int4, b jsonb) +CREATE FUNCTION eql_v3.eq(a eql_v3.int4, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for = on eql_v2_int4 (jsonb, domain). +--! @brief Blocker for = on eql_v3.int4 (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.eq(a jsonb, b eql_v2_int4) +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <> on eql_v2_int4. ---! @param a eql_v2_int4 ---! @param b eql_v2_int4 +--! @brief Blocker for <> on eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.neq(a eql_v2_int4, b eql_v2_int4) +CREATE FUNCTION eql_v3.neq(a eql_v3.int4, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '<>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <> on eql_v2_int4 (domain, jsonb). ---! @param a eql_v2_int4 +--! @brief Blocker for <> on eql_v3.int4 (domain, jsonb). +--! @param a eql_v3.int4 --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.neq(a eql_v2_int4, b jsonb) +CREATE FUNCTION eql_v3.neq(a eql_v3.int4, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '<>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <> on eql_v2_int4 (jsonb, domain). +--! @brief Blocker for <> on eql_v3.int4 (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.neq(a jsonb, b eql_v2_int4) +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '<>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for < on eql_v2_int4. ---! @param a eql_v2_int4 ---! @param b eql_v2_int4 +--! @brief Blocker for < on eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.lt(a eql_v2_int4, b eql_v2_int4) +CREATE FUNCTION eql_v3.lt(a eql_v3.int4, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '<'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for < on eql_v2_int4 (domain, jsonb). ---! @param a eql_v2_int4 +--! @brief Blocker for < on eql_v3.int4 (domain, jsonb). +--! @param a eql_v3.int4 --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.lt(a eql_v2_int4, b jsonb) +CREATE FUNCTION eql_v3.lt(a eql_v3.int4, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '<'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for < on eql_v2_int4 (jsonb, domain). +--! @brief Blocker for < on eql_v3.int4 (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.lt(a jsonb, b eql_v2_int4) +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '<'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <= on eql_v2_int4. ---! @param a eql_v2_int4 ---! @param b eql_v2_int4 +--! @brief Blocker for <= on eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.lte(a eql_v2_int4, b eql_v2_int4) +CREATE FUNCTION eql_v3.lte(a eql_v3.int4, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '<='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <= on eql_v2_int4 (domain, jsonb). ---! @param a eql_v2_int4 +--! @brief Blocker for <= on eql_v3.int4 (domain, jsonb). +--! @param a eql_v3.int4 --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.lte(a eql_v2_int4, b jsonb) +CREATE FUNCTION eql_v3.lte(a eql_v3.int4, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '<='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <= on eql_v2_int4 (jsonb, domain). +--! @brief Blocker for <= on eql_v3.int4 (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.lte(a jsonb, b eql_v2_int4) +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '<='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for > on eql_v2_int4. ---! @param a eql_v2_int4 ---! @param b eql_v2_int4 +--! @brief Blocker for > on eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.gt(a eql_v2_int4, b eql_v2_int4) +CREATE FUNCTION eql_v3.gt(a eql_v3.int4, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for > on eql_v2_int4 (domain, jsonb). ---! @param a eql_v2_int4 +--! @brief Blocker for > on eql_v3.int4 (domain, jsonb). +--! @param a eql_v3.int4 --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.gt(a eql_v2_int4, b jsonb) +CREATE FUNCTION eql_v3.gt(a eql_v3.int4, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for > on eql_v2_int4 (jsonb, domain). +--! @brief Blocker for > on eql_v3.int4 (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.gt(a jsonb, b eql_v2_int4) +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for >= on eql_v2_int4. ---! @param a eql_v2_int4 ---! @param b eql_v2_int4 +--! @brief Blocker for >= on eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.gte(a eql_v2_int4, b eql_v2_int4) +CREATE FUNCTION eql_v3.gte(a eql_v3.int4, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '>='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '>='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for >= on eql_v2_int4 (domain, jsonb). ---! @param a eql_v2_int4 +--! @brief Blocker for >= on eql_v3.int4 (domain, jsonb). +--! @param a eql_v3.int4 --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.gte(a eql_v2_int4, b jsonb) +CREATE FUNCTION eql_v3.gte(a eql_v3.int4, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '>='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '>='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for >= on eql_v2_int4 (jsonb, domain). +--! @brief Blocker for >= on eql_v3.int4 (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.gte(a jsonb, b eql_v2_int4) +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '>='); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '>='); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @> on eql_v2_int4. ---! @param a eql_v2_int4 ---! @param b eql_v2_int4 +--! @brief Blocker for @> on eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contains(a eql_v2_int4, b eql_v2_int4) +CREATE FUNCTION eql_v3.contains(a eql_v3.int4, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '@>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '@>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @> on eql_v2_int4 (domain, jsonb). ---! @param a eql_v2_int4 +--! @brief Blocker for @> on eql_v3.int4 (domain, jsonb). +--! @param a eql_v3.int4 --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contains(a eql_v2_int4, b jsonb) +CREATE FUNCTION eql_v3.contains(a eql_v3.int4, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '@>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '@>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @> on eql_v2_int4 (jsonb, domain). +--! @brief Blocker for @> on eql_v3.int4 (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contains(a jsonb, b eql_v2_int4) +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '@>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '@>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <@ on eql_v2_int4. ---! @param a eql_v2_int4 ---! @param b eql_v2_int4 +--! @brief Blocker for <@ on eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contained_by(a eql_v2_int4, b eql_v2_int4) +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '<@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <@ on eql_v2_int4 (domain, jsonb). ---! @param a eql_v2_int4 +--! @brief Blocker for <@ on eql_v3.int4 (domain, jsonb). +--! @param a eql_v3.int4 --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contained_by(a eql_v2_int4, b jsonb) +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '<@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <@ on eql_v2_int4 (jsonb, domain). +--! @brief Blocker for <@ on eql_v3.int4 (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4 +--! @param b eql_v3.int4 --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contained_by(a jsonb, b eql_v2_int4) +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.int4) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '<@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for -> on eql_v2_int4 (domain, text). ---! @param a eql_v2_int4 +--! @brief Blocker for -> on eql_v3.int4 (domain, text). +--! @param a eql_v3.int4 --! @param selector text ---! @return eql_v2_int4 (never returns; always raises) -CREATE FUNCTION eql_v2."->"(a eql_v2_int4, selector text) -RETURNS eql_v2_int4 IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v2_int4'; END; $$ +--! @return eql_v3.int4 (never returns; always raises) +CREATE FUNCTION eql_v3."->"(a eql_v3.int4, selector text) +RETURNS eql_v3.int4 IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for -> on eql_v2_int4 (domain, integer). ---! @param a eql_v2_int4 +--! @brief Blocker for -> on eql_v3.int4 (domain, integer). +--! @param a eql_v3.int4 --! @param selector integer ---! @return eql_v2_int4 (never returns; always raises) -CREATE FUNCTION eql_v2."->"(a eql_v2_int4, selector integer) -RETURNS eql_v2_int4 IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v2_int4'; END; $$ +--! @return eql_v3.int4 (never returns; always raises) +CREATE FUNCTION eql_v3."->"(a eql_v3.int4, selector integer) +RETURNS eql_v3.int4 IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for -> on eql_v2_int4 (jsonb, domain). +--! @brief Blocker for -> on eql_v3.int4 (jsonb, domain). --! @param a jsonb ---! @param selector eql_v2_int4 ---! @return eql_v2_int4 (never returns; always raises) -CREATE FUNCTION eql_v2."->"(a jsonb, selector eql_v2_int4) -RETURNS eql_v2_int4 IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v2_int4'; END; $$ +--! @param selector eql_v3.int4 +--! @return eql_v3.int4 (never returns; always raises) +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int4) +RETURNS eql_v3.int4 IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ->> on eql_v2_int4 (domain, text). ---! @param a eql_v2_int4 +--! @brief Blocker for ->> on eql_v3.int4 (domain, text). +--! @param a eql_v3.int4 --! @param selector text --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."->>"(a eql_v2_int4, selector text) +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4, selector text) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v2_int4'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ->> on eql_v2_int4 (domain, integer). ---! @param a eql_v2_int4 +--! @brief Blocker for ->> on eql_v3.int4 (domain, integer). +--! @param a eql_v3.int4 --! @param selector integer --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."->>"(a eql_v2_int4, selector integer) +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4, selector integer) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v2_int4'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ->> on eql_v2_int4 (jsonb, domain). +--! @brief Blocker for ->> on eql_v3.int4 (jsonb, domain). --! @param a jsonb ---! @param selector eql_v2_int4 +--! @param selector eql_v3.int4 --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."->>"(a jsonb, selector eql_v2_int4) +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.int4) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v2_int4'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ? on eql_v2_int4 (domain, text). ---! @param a eql_v2_int4 +--! @brief Blocker for ? on eql_v3.int4 (domain, text). +--! @param a eql_v3.int4 --! @param b text --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."?"(a eql_v2_int4, b text) +CREATE FUNCTION eql_v3."?"(a eql_v3.int4, b text) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '?'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '?'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ?| on eql_v2_int4 (domain, text[]). ---! @param a eql_v2_int4 +--! @brief Blocker for ?| on eql_v3.int4 (domain, text[]). +--! @param a eql_v3.int4 --! @param b text[] --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."?|"(a eql_v2_int4, b text[]) +CREATE FUNCTION eql_v3."?|"(a eql_v3.int4, b text[]) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '?|'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '?|'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ?& on eql_v2_int4 (domain, text[]). ---! @param a eql_v2_int4 +--! @brief Blocker for ?& on eql_v3.int4 (domain, text[]). +--! @param a eql_v3.int4 --! @param b text[] --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."?&"(a eql_v2_int4, b text[]) +CREATE FUNCTION eql_v3."?&"(a eql_v3.int4, b text[]) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '?&'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '?&'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @? on eql_v2_int4 (domain, jsonpath). ---! @param a eql_v2_int4 +--! @brief Blocker for @? on eql_v3.int4 (domain, jsonpath). +--! @param a eql_v3.int4 --! @param b jsonpath --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."@?"(a eql_v2_int4, b jsonpath) +CREATE FUNCTION eql_v3."@?"(a eql_v3.int4, b jsonpath) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '@?'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '@?'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @@ on eql_v2_int4 (domain, jsonpath). ---! @param a eql_v2_int4 +--! @brief Blocker for @@ on eql_v3.int4 (domain, jsonpath). +--! @param a eql_v3.int4 --! @param b jsonpath --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."@@"(a eql_v2_int4, b jsonpath) +CREATE FUNCTION eql_v3."@@"(a eql_v3.int4, b jsonpath) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '@@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '@@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for #> on eql_v2_int4 (domain, text[]). ---! @param a eql_v2_int4 +--! @brief Blocker for #> on eql_v3.int4 (domain, text[]). +--! @param a eql_v3.int4 --! @param b text[] --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."#>"(a eql_v2_int4, b text[]) +CREATE FUNCTION eql_v3."#>"(a eql_v3.int4, b text[]) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v2_int4'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for #>> on eql_v2_int4 (domain, text[]). ---! @param a eql_v2_int4 +--! @brief Blocker for #>> on eql_v3.int4 (domain, text[]). +--! @param a eql_v3.int4 --! @param b text[] --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."#>>"(a eql_v2_int4, b text[]) +CREATE FUNCTION eql_v3."#>>"(a eql_v3.int4, b text[]) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v2_int4'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for - on eql_v2_int4 (domain, text). ---! @param a eql_v2_int4 +--! @brief Blocker for - on eql_v3.int4 (domain, text). +--! @param a eql_v3.int4 --! @param b text --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."-"(a eql_v2_int4, b text) +CREATE FUNCTION eql_v3."-"(a eql_v3.int4, b text) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v2_int4'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for - on eql_v2_int4 (domain, integer). ---! @param a eql_v2_int4 +--! @brief Blocker for - on eql_v3.int4 (domain, integer). +--! @param a eql_v3.int4 --! @param b integer --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."-"(a eql_v2_int4, b integer) +CREATE FUNCTION eql_v3."-"(a eql_v3.int4, b integer) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v2_int4'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for - on eql_v2_int4 (domain, text[]). ---! @param a eql_v2_int4 +--! @brief Blocker for - on eql_v3.int4 (domain, text[]). +--! @param a eql_v3.int4 --! @param b text[] --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."-"(a eql_v2_int4, b text[]) +CREATE FUNCTION eql_v3."-"(a eql_v3.int4, b text[]) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v2_int4'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for #- on eql_v2_int4 (domain, text[]). ---! @param a eql_v2_int4 +--! @brief Blocker for #- on eql_v3.int4 (domain, text[]). +--! @param a eql_v3.int4 --! @param b text[] --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."#-"(a eql_v2_int4, b text[]) +CREATE FUNCTION eql_v3."#-"(a eql_v3.int4, b text[]) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v2_int4'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for || on eql_v2_int4. ---! @param a eql_v2_int4 ---! @param b eql_v2_int4 +--! @brief Blocker for || on eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."||"(a eql_v2_int4, b eql_v2_int4) +CREATE FUNCTION eql_v3."||"(a eql_v3.int4, b eql_v3.int4) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v2_int4'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for || on eql_v2_int4 (domain, jsonb). ---! @param a eql_v2_int4 +--! @brief Blocker for || on eql_v3.int4 (domain, jsonb). +--! @param a eql_v3.int4 --! @param b jsonb --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."||"(a eql_v2_int4, b jsonb) +CREATE FUNCTION eql_v3."||"(a eql_v3.int4, b jsonb) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v2_int4'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for || on eql_v2_int4 (jsonb, domain). +--! @brief Blocker for || on eql_v3.int4 (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4 +--! @param b eql_v3.int4 --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."||"(a jsonb, b eql_v2_int4) +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int4) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v2_int4'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4'; END; $$ LANGUAGE plpgsql; diff --git a/tests/codegen/reference/int4/int4_operators.sql b/tests/codegen/reference/int4/int4_operators.sql index fc3dd7cf..24ff1607 100644 --- a/tests/codegen/reference/int4/int4_operators.sql +++ b/tests/codegen/reference/int4/int4_operators.sql @@ -1,5 +1,5 @@ -- REFERENCE: hand-written parity baseline for tasks/codegen/ — see ../README.md --- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql -- REQUIRE: src/encrypted_domain/int4/int4_types.sql -- REQUIRE: src/encrypted_domain/int4/int4_functions.sql @@ -8,264 +8,264 @@ -- Placeholder: this domain's term set does not support =; the backing function always raises. CREATE OPERATOR = ( - FUNCTION = eql_v2.eq, - LEFTARG = eql_v2_int4, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support =; the backing function always raises. CREATE OPERATOR = ( - FUNCTION = eql_v2.eq, - LEFTARG = eql_v2_int4, RIGHTARG = jsonb + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support =; the backing function always raises. CREATE OPERATOR = ( - FUNCTION = eql_v2.eq, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support <>; the backing function always raises. CREATE OPERATOR <> ( - FUNCTION = eql_v2.neq, - LEFTARG = eql_v2_int4, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support <>; the backing function always raises. CREATE OPERATOR <> ( - FUNCTION = eql_v2.neq, - LEFTARG = eql_v2_int4, RIGHTARG = jsonb + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support <>; the backing function always raises. CREATE OPERATOR <> ( - FUNCTION = eql_v2.neq, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support <; the backing function always raises. CREATE OPERATOR < ( - FUNCTION = eql_v2.lt, - LEFTARG = eql_v2_int4, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support <; the backing function always raises. CREATE OPERATOR < ( - FUNCTION = eql_v2.lt, - LEFTARG = eql_v2_int4, RIGHTARG = jsonb + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support <; the backing function always raises. CREATE OPERATOR < ( - FUNCTION = eql_v2.lt, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support <=; the backing function always raises. CREATE OPERATOR <= ( - FUNCTION = eql_v2.lte, - LEFTARG = eql_v2_int4, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support <=; the backing function always raises. CREATE OPERATOR <= ( - FUNCTION = eql_v2.lte, - LEFTARG = eql_v2_int4, RIGHTARG = jsonb + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support <=; the backing function always raises. CREATE OPERATOR <= ( - FUNCTION = eql_v2.lte, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support >; the backing function always raises. CREATE OPERATOR > ( - FUNCTION = eql_v2.gt, - LEFTARG = eql_v2_int4, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support >; the backing function always raises. CREATE OPERATOR > ( - FUNCTION = eql_v2.gt, - LEFTARG = eql_v2_int4, RIGHTARG = jsonb + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support >; the backing function always raises. CREATE OPERATOR > ( - FUNCTION = eql_v2.gt, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support >=; the backing function always raises. CREATE OPERATOR >= ( - FUNCTION = eql_v2.gte, - LEFTARG = eql_v2_int4, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support >=; the backing function always raises. CREATE OPERATOR >= ( - FUNCTION = eql_v2.gte, - LEFTARG = eql_v2_int4, RIGHTARG = jsonb + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support >=; the backing function always raises. CREATE OPERATOR >= ( - FUNCTION = eql_v2.gte, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support @>; the backing function always raises. CREATE OPERATOR @> ( - FUNCTION = eql_v2.contains, - LEFTARG = eql_v2_int4, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support @>; the backing function always raises. CREATE OPERATOR @> ( - FUNCTION = eql_v2.contains, - LEFTARG = eql_v2_int4, RIGHTARG = jsonb + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support @>; the backing function always raises. CREATE OPERATOR @> ( - FUNCTION = eql_v2.contains, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support <@; the backing function always raises. CREATE OPERATOR <@ ( - FUNCTION = eql_v2.contained_by, - LEFTARG = eql_v2_int4, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support <@; the backing function always raises. CREATE OPERATOR <@ ( - FUNCTION = eql_v2.contained_by, - LEFTARG = eql_v2_int4, RIGHTARG = jsonb + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support <@; the backing function always raises. CREATE OPERATOR <@ ( - FUNCTION = eql_v2.contained_by, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support ->; the backing function always raises. CREATE OPERATOR -> ( - FUNCTION = eql_v2."->", - LEFTARG = eql_v2_int4, RIGHTARG = text + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4, RIGHTARG = text ); -- Placeholder: this domain's term set does not support ->; the backing function always raises. CREATE OPERATOR -> ( - FUNCTION = eql_v2."->", - LEFTARG = eql_v2_int4, RIGHTARG = integer + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4, RIGHTARG = integer ); -- Placeholder: this domain's term set does not support ->; the backing function always raises. CREATE OPERATOR -> ( - FUNCTION = eql_v2."->", - LEFTARG = jsonb, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support ->>; the backing function always raises. CREATE OPERATOR ->> ( - FUNCTION = eql_v2."->>", - LEFTARG = eql_v2_int4, RIGHTARG = text + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4, RIGHTARG = text ); -- Placeholder: this domain's term set does not support ->>; the backing function always raises. CREATE OPERATOR ->> ( - FUNCTION = eql_v2."->>", - LEFTARG = eql_v2_int4, RIGHTARG = integer + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4, RIGHTARG = integer ); -- Placeholder: this domain's term set does not support ->>; the backing function always raises. CREATE OPERATOR ->> ( - FUNCTION = eql_v2."->>", - LEFTARG = jsonb, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support ?; the backing function always raises. CREATE OPERATOR ? ( - FUNCTION = eql_v2."?", - LEFTARG = eql_v2_int4, RIGHTARG = text + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.int4, RIGHTARG = text ); -- Placeholder: this domain's term set does not support ?|; the backing function always raises. CREATE OPERATOR ?| ( - FUNCTION = eql_v2."?|", - LEFTARG = eql_v2_int4, RIGHTARG = text[] + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.int4, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support ?&; the backing function always raises. CREATE OPERATOR ?& ( - FUNCTION = eql_v2."?&", - LEFTARG = eql_v2_int4, RIGHTARG = text[] + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.int4, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support @?; the backing function always raises. CREATE OPERATOR @? ( - FUNCTION = eql_v2."@?", - LEFTARG = eql_v2_int4, RIGHTARG = jsonpath + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.int4, RIGHTARG = jsonpath ); -- Placeholder: this domain's term set does not support @@; the backing function always raises. CREATE OPERATOR @@ ( - FUNCTION = eql_v2."@@", - LEFTARG = eql_v2_int4, RIGHTARG = jsonpath + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.int4, RIGHTARG = jsonpath ); -- Placeholder: this domain's term set does not support #>; the backing function always raises. CREATE OPERATOR #> ( - FUNCTION = eql_v2."#>", - LEFTARG = eql_v2_int4, RIGHTARG = text[] + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.int4, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support #>>; the backing function always raises. CREATE OPERATOR #>> ( - FUNCTION = eql_v2."#>>", - LEFTARG = eql_v2_int4, RIGHTARG = text[] + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.int4, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support -; the backing function always raises. CREATE OPERATOR - ( - FUNCTION = eql_v2."-", - LEFTARG = eql_v2_int4, RIGHTARG = text + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4, RIGHTARG = text ); -- Placeholder: this domain's term set does not support -; the backing function always raises. CREATE OPERATOR - ( - FUNCTION = eql_v2."-", - LEFTARG = eql_v2_int4, RIGHTARG = integer + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4, RIGHTARG = integer ); -- Placeholder: this domain's term set does not support -; the backing function always raises. CREATE OPERATOR - ( - FUNCTION = eql_v2."-", - LEFTARG = eql_v2_int4, RIGHTARG = text[] + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support #-; the backing function always raises. CREATE OPERATOR #- ( - FUNCTION = eql_v2."#-", - LEFTARG = eql_v2_int4, RIGHTARG = text[] + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.int4, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support ||; the backing function always raises. CREATE OPERATOR || ( - FUNCTION = eql_v2."||", - LEFTARG = eql_v2_int4, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 ); -- Placeholder: this domain's term set does not support ||; the backing function always raises. CREATE OPERATOR || ( - FUNCTION = eql_v2."||", - LEFTARG = eql_v2_int4, RIGHTARG = jsonb + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support ||; the backing function always raises. CREATE OPERATOR || ( - FUNCTION = eql_v2."||", - LEFTARG = jsonb, RIGHTARG = eql_v2_int4 + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 ); diff --git a/tests/codegen/reference/int4/int4_ord_aggregates.sql b/tests/codegen/reference/int4/int4_ord_aggregates.sql index 52a64ec1..12f5efcc 100644 --- a/tests/codegen/reference/int4/int4_ord_aggregates.sql +++ b/tests/codegen/reference/int4/int4_ord_aggregates.sql @@ -1,5 +1,5 @@ -- REFERENCE: hand-written parity baseline for tasks/codegen/ — see ../README.md --- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql -- REQUIRE: src/encrypted_domain/int4/int4_types.sql -- REQUIRE: src/encrypted_domain/int4/int4_ord_functions.sql -- REQUIRE: src/encrypted_domain/int4/int4_ord_operators.sql @@ -7,18 +7,18 @@ --! @file encrypted_domain/int4/int4_ord_aggregates.sql --! @brief Ordered domain of the int4 encrypted-domain family — MIN/MAX aggregates. ---! @brief State function for min aggregate on eql_v2_int4_ord. +--! @brief State function for min aggregate on eql_v3.int4_ord. --! @internal --! ---! @param state eql_v2_int4_ord running extremum ---! @param value eql_v2_int4_ord next non-NULL value ---! @return eql_v2_int4_ord the minimum of state and value +--! @param state eql_v3.int4_ord running extremum +--! @param value eql_v3.int4_ord next non-NULL value +--! @return eql_v3.int4_ord the minimum of state and value -- LANGUAGE plpgsql, not sql: aggregate state functions are not index -- expressions, so opacity to the planner is fine, and a multi-statement -- BEGIN/IF/END body is the natural shape. (A LANGUAGE sql CASE would -- also work, but the procedural form mirrors the blocker convention.) -CREATE FUNCTION eql_v2.min_sfunc(state eql_v2_int4_ord, value eql_v2_int4_ord) -RETURNS eql_v2_int4_ord +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.int4_ord, value eql_v3.int4_ord) +RETURNS eql_v3.int4_ord LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE SET search_path = pg_catalog, extensions, public AS $$ @@ -30,34 +30,34 @@ BEGIN END; $$; ---! @brief Find the minimum encrypted value in a group of eql_v2_int4_ord values. +--! @brief Find the minimum encrypted value in a group of eql_v3.int4_ord values. --! --! Comparison routes through the domain's `<` operator, which uses the ORE block term — no decryption. --! ---! @param input eql_v2_int4_ord encrypted values to aggregate ---! @return eql_v2_int4_ord minimum of the group, or NULL if all inputs are NULL +--! @param input eql_v3.int4_ord encrypted values to aggregate +--! @return eql_v3.int4_ord minimum of the group, or NULL if all inputs are NULL -- combinefunc = sfunc: min/max are associative, so merging two partial -- extrema is the same comparison. PARALLEL SAFE enables partial and -- parallel aggregation on large GROUP BY workloads, with no decryption. -CREATE AGGREGATE eql_v2.min(eql_v2_int4_ord) ( - sfunc = eql_v2.min_sfunc, - stype = eql_v2_int4_ord, - combinefunc = eql_v2.min_sfunc, +CREATE AGGREGATE eql_v3.min(eql_v3.int4_ord) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.int4_ord, + combinefunc = eql_v3.min_sfunc, parallel = safe ); ---! @brief State function for max aggregate on eql_v2_int4_ord. +--! @brief State function for max aggregate on eql_v3.int4_ord. --! @internal --! ---! @param state eql_v2_int4_ord running extremum ---! @param value eql_v2_int4_ord next non-NULL value ---! @return eql_v2_int4_ord the maximum of state and value +--! @param state eql_v3.int4_ord running extremum +--! @param value eql_v3.int4_ord next non-NULL value +--! @return eql_v3.int4_ord the maximum of state and value -- LANGUAGE plpgsql, not sql: aggregate state functions are not index -- expressions, so opacity to the planner is fine, and a multi-statement -- BEGIN/IF/END body is the natural shape. (A LANGUAGE sql CASE would -- also work, but the procedural form mirrors the blocker convention.) -CREATE FUNCTION eql_v2.max_sfunc(state eql_v2_int4_ord, value eql_v2_int4_ord) -RETURNS eql_v2_int4_ord +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.int4_ord, value eql_v3.int4_ord) +RETURNS eql_v3.int4_ord LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE SET search_path = pg_catalog, extensions, public AS $$ @@ -69,18 +69,18 @@ BEGIN END; $$; ---! @brief Find the maximum encrypted value in a group of eql_v2_int4_ord values. +--! @brief Find the maximum encrypted value in a group of eql_v3.int4_ord values. --! --! Comparison routes through the domain's `>` operator, which uses the ORE block term — no decryption. --! ---! @param input eql_v2_int4_ord encrypted values to aggregate ---! @return eql_v2_int4_ord maximum of the group, or NULL if all inputs are NULL +--! @param input eql_v3.int4_ord encrypted values to aggregate +--! @return eql_v3.int4_ord maximum of the group, or NULL if all inputs are NULL -- combinefunc = sfunc: min/max are associative, so merging two partial -- extrema is the same comparison. PARALLEL SAFE enables partial and -- parallel aggregation on large GROUP BY workloads, with no decryption. -CREATE AGGREGATE eql_v2.max(eql_v2_int4_ord) ( - sfunc = eql_v2.max_sfunc, - stype = eql_v2_int4_ord, - combinefunc = eql_v2.max_sfunc, +CREATE AGGREGATE eql_v3.max(eql_v3.int4_ord) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.int4_ord, + combinefunc = eql_v3.max_sfunc, parallel = safe ); diff --git a/tests/codegen/reference/int4/int4_ord_functions.sql b/tests/codegen/reference/int4/int4_ord_functions.sql index 9d3ba2a2..a49bb1e9 100644 --- a/tests/codegen/reference/int4/int4_ord_functions.sql +++ b/tests/codegen/reference/int4/int4_ord_functions.sql @@ -1,5 +1,6 @@ -- REFERENCE: hand-written parity baseline for tasks/codegen/ — see ../README.md -- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql -- REQUIRE: src/encrypted_domain/int4/int4_types.sql -- REQUIRE: src/encrypted_domain/functions.sql -- REQUIRE: src/ore_block_u64_8_256/functions.sql @@ -8,388 +9,388 @@ --! @file encrypted_domain/int4/int4_ord_functions.sql --! @brief Ordered domain of the int4 encrypted-domain family — comparison/path functions. ---! @brief Index extractor for the eql_v2_int4_ord variant. ---! @param a eql_v2_int4_ord +--! @brief Index extractor for the eql_v3.int4_ord variant. +--! @param a eql_v3.int4_ord --! @return eql_v2.ore_block_u64_8_256 -CREATE FUNCTION eql_v2.ord_term(a eql_v2_int4_ord) +CREATE FUNCTION eql_v3.ord_term(a eql_v3.int4_ord) RETURNS eql_v2.ore_block_u64_8_256 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS $$ SELECT eql_v2.ore_block_u64_8_256(a::jsonb) $$; ---! @brief Equality wrapper for eql_v2_int4_ord. ---! @param a eql_v2_int4_ord ---! @param b eql_v2_int4_ord +--! @brief Equality wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord --! @return boolean -CREATE FUNCTION eql_v2.eq(a eql_v2_int4_ord, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.eq(a eql_v3.int4_ord, b eql_v3.int4_ord) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) = eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; ---! @brief Equality wrapper for eql_v2_int4_ord (domain, jsonb). ---! @param a eql_v2_int4_ord +--! @brief Equality wrapper for eql_v3.int4_ord (domain, jsonb). +--! @param a eql_v3.int4_ord --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.eq(a eql_v2_int4_ord, b jsonb) +CREATE FUNCTION eql_v3.eq(a eql_v3.int4_ord, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) = eql_v2.ord_term(b::eql_v2_int4_ord) $$; +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.int4_ord) $$; ---! @brief Equality wrapper for eql_v2_int4_ord (jsonb, domain). +--! @brief Equality wrapper for eql_v3.int4_ord (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord +--! @param b eql_v3.int4_ord --! @return boolean -CREATE FUNCTION eql_v2.eq(a jsonb, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.int4_ord) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a::eql_v2_int4_ord) = eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord) = eql_v3.ord_term(b) $$; ---! @brief Inequality wrapper for eql_v2_int4_ord. ---! @param a eql_v2_int4_ord ---! @param b eql_v2_int4_ord +--! @brief Inequality wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord --! @return boolean -CREATE FUNCTION eql_v2.neq(a eql_v2_int4_ord, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.neq(a eql_v3.int4_ord, b eql_v3.int4_ord) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) <> eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; ---! @brief Inequality wrapper for eql_v2_int4_ord (domain, jsonb). ---! @param a eql_v2_int4_ord +--! @brief Inequality wrapper for eql_v3.int4_ord (domain, jsonb). +--! @param a eql_v3.int4_ord --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.neq(a eql_v2_int4_ord, b jsonb) +CREATE FUNCTION eql_v3.neq(a eql_v3.int4_ord, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) <> eql_v2.ord_term(b::eql_v2_int4_ord) $$; +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.int4_ord) $$; ---! @brief Inequality wrapper for eql_v2_int4_ord (jsonb, domain). +--! @brief Inequality wrapper for eql_v3.int4_ord (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord +--! @param b eql_v3.int4_ord --! @return boolean -CREATE FUNCTION eql_v2.neq(a jsonb, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.int4_ord) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a::eql_v2_int4_ord) <> eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord) <> eql_v3.ord_term(b) $$; ---! @brief Less-than wrapper for eql_v2_int4_ord. ---! @param a eql_v2_int4_ord ---! @param b eql_v2_int4_ord +--! @brief Less-than wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord --! @return boolean -CREATE FUNCTION eql_v2.lt(a eql_v2_int4_ord, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.lt(a eql_v3.int4_ord, b eql_v3.int4_ord) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) < eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; ---! @brief Less-than wrapper for eql_v2_int4_ord (domain, jsonb). ---! @param a eql_v2_int4_ord +--! @brief Less-than wrapper for eql_v3.int4_ord (domain, jsonb). +--! @param a eql_v3.int4_ord --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.lt(a eql_v2_int4_ord, b jsonb) +CREATE FUNCTION eql_v3.lt(a eql_v3.int4_ord, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) < eql_v2.ord_term(b::eql_v2_int4_ord) $$; +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.int4_ord) $$; ---! @brief Less-than wrapper for eql_v2_int4_ord (jsonb, domain). +--! @brief Less-than wrapper for eql_v3.int4_ord (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord +--! @param b eql_v3.int4_ord --! @return boolean -CREATE FUNCTION eql_v2.lt(a jsonb, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.int4_ord) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a::eql_v2_int4_ord) < eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord) < eql_v3.ord_term(b) $$; ---! @brief Less-than-or-equal wrapper for eql_v2_int4_ord. ---! @param a eql_v2_int4_ord ---! @param b eql_v2_int4_ord +--! @brief Less-than-or-equal wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord --! @return boolean -CREATE FUNCTION eql_v2.lte(a eql_v2_int4_ord, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.lte(a eql_v3.int4_ord, b eql_v3.int4_ord) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) <= eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; ---! @brief Less-than-or-equal wrapper for eql_v2_int4_ord (domain, jsonb). ---! @param a eql_v2_int4_ord +--! @brief Less-than-or-equal wrapper for eql_v3.int4_ord (domain, jsonb). +--! @param a eql_v3.int4_ord --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.lte(a eql_v2_int4_ord, b jsonb) +CREATE FUNCTION eql_v3.lte(a eql_v3.int4_ord, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) <= eql_v2.ord_term(b::eql_v2_int4_ord) $$; +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.int4_ord) $$; ---! @brief Less-than-or-equal wrapper for eql_v2_int4_ord (jsonb, domain). +--! @brief Less-than-or-equal wrapper for eql_v3.int4_ord (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord +--! @param b eql_v3.int4_ord --! @return boolean -CREATE FUNCTION eql_v2.lte(a jsonb, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.int4_ord) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a::eql_v2_int4_ord) <= eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord) <= eql_v3.ord_term(b) $$; ---! @brief Greater-than wrapper for eql_v2_int4_ord. ---! @param a eql_v2_int4_ord ---! @param b eql_v2_int4_ord +--! @brief Greater-than wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord --! @return boolean -CREATE FUNCTION eql_v2.gt(a eql_v2_int4_ord, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.gt(a eql_v3.int4_ord, b eql_v3.int4_ord) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) > eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; ---! @brief Greater-than wrapper for eql_v2_int4_ord (domain, jsonb). ---! @param a eql_v2_int4_ord +--! @brief Greater-than wrapper for eql_v3.int4_ord (domain, jsonb). +--! @param a eql_v3.int4_ord --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.gt(a eql_v2_int4_ord, b jsonb) +CREATE FUNCTION eql_v3.gt(a eql_v3.int4_ord, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) > eql_v2.ord_term(b::eql_v2_int4_ord) $$; +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.int4_ord) $$; ---! @brief Greater-than wrapper for eql_v2_int4_ord (jsonb, domain). +--! @brief Greater-than wrapper for eql_v3.int4_ord (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord +--! @param b eql_v3.int4_ord --! @return boolean -CREATE FUNCTION eql_v2.gt(a jsonb, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.int4_ord) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a::eql_v2_int4_ord) > eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord) > eql_v3.ord_term(b) $$; ---! @brief Greater-than-or-equal wrapper for eql_v2_int4_ord. ---! @param a eql_v2_int4_ord ---! @param b eql_v2_int4_ord +--! @brief Greater-than-or-equal wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord --! @return boolean -CREATE FUNCTION eql_v2.gte(a eql_v2_int4_ord, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.gte(a eql_v3.int4_ord, b eql_v3.int4_ord) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) >= eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; ---! @brief Greater-than-or-equal wrapper for eql_v2_int4_ord (domain, jsonb). ---! @param a eql_v2_int4_ord +--! @brief Greater-than-or-equal wrapper for eql_v3.int4_ord (domain, jsonb). +--! @param a eql_v3.int4_ord --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.gte(a eql_v2_int4_ord, b jsonb) +CREATE FUNCTION eql_v3.gte(a eql_v3.int4_ord, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) >= eql_v2.ord_term(b::eql_v2_int4_ord) $$; +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.int4_ord) $$; ---! @brief Greater-than-or-equal wrapper for eql_v2_int4_ord (jsonb, domain). +--! @brief Greater-than-or-equal wrapper for eql_v3.int4_ord (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord +--! @param b eql_v3.int4_ord --! @return boolean -CREATE FUNCTION eql_v2.gte(a jsonb, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.int4_ord) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a::eql_v2_int4_ord) >= eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord) >= eql_v3.ord_term(b) $$; ---! @brief Blocker for @> on eql_v2_int4_ord. ---! @param a eql_v2_int4_ord ---! @param b eql_v2_int4_ord +--! @brief Blocker for @> on eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contains(a eql_v2_int4_ord, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.contains(a eql_v3.int4_ord, b eql_v3.int4_ord) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord', '@>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '@>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @> on eql_v2_int4_ord (domain, jsonb). ---! @param a eql_v2_int4_ord +--! @brief Blocker for @> on eql_v3.int4_ord (domain, jsonb). +--! @param a eql_v3.int4_ord --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contains(a eql_v2_int4_ord, b jsonb) +CREATE FUNCTION eql_v3.contains(a eql_v3.int4_ord, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord', '@>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '@>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @> on eql_v2_int4_ord (jsonb, domain). +--! @brief Blocker for @> on eql_v3.int4_ord (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord +--! @param b eql_v3.int4_ord --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contains(a jsonb, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.int4_ord) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord', '@>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '@>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <@ on eql_v2_int4_ord. ---! @param a eql_v2_int4_ord ---! @param b eql_v2_int4_ord +--! @brief Blocker for <@ on eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contained_by(a eql_v2_int4_ord, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4_ord, b eql_v3.int4_ord) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord', '<@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '<@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <@ on eql_v2_int4_ord (domain, jsonb). ---! @param a eql_v2_int4_ord +--! @brief Blocker for <@ on eql_v3.int4_ord (domain, jsonb). +--! @param a eql_v3.int4_ord --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contained_by(a eql_v2_int4_ord, b jsonb) +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4_ord, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord', '<@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '<@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <@ on eql_v2_int4_ord (jsonb, domain). +--! @brief Blocker for <@ on eql_v3.int4_ord (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord +--! @param b eql_v3.int4_ord --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contained_by(a jsonb, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.int4_ord) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord', '<@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '<@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for -> on eql_v2_int4_ord (domain, text). ---! @param a eql_v2_int4_ord +--! @brief Blocker for -> on eql_v3.int4_ord (domain, text). +--! @param a eql_v3.int4_ord --! @param selector text ---! @return eql_v2_int4_ord (never returns; always raises) -CREATE FUNCTION eql_v2."->"(a eql_v2_int4_ord, selector text) -RETURNS eql_v2_int4_ord IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v2_int4_ord'; END; $$ +--! @return eql_v3.int4_ord (never returns; always raises) +CREATE FUNCTION eql_v3."->"(a eql_v3.int4_ord, selector text) +RETURNS eql_v3.int4_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for -> on eql_v2_int4_ord (domain, integer). ---! @param a eql_v2_int4_ord +--! @brief Blocker for -> on eql_v3.int4_ord (domain, integer). +--! @param a eql_v3.int4_ord --! @param selector integer ---! @return eql_v2_int4_ord (never returns; always raises) -CREATE FUNCTION eql_v2."->"(a eql_v2_int4_ord, selector integer) -RETURNS eql_v2_int4_ord IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v2_int4_ord'; END; $$ +--! @return eql_v3.int4_ord (never returns; always raises) +CREATE FUNCTION eql_v3."->"(a eql_v3.int4_ord, selector integer) +RETURNS eql_v3.int4_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for -> on eql_v2_int4_ord (jsonb, domain). +--! @brief Blocker for -> on eql_v3.int4_ord (jsonb, domain). --! @param a jsonb ---! @param selector eql_v2_int4_ord ---! @return eql_v2_int4_ord (never returns; always raises) -CREATE FUNCTION eql_v2."->"(a jsonb, selector eql_v2_int4_ord) -RETURNS eql_v2_int4_ord IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v2_int4_ord'; END; $$ +--! @param selector eql_v3.int4_ord +--! @return eql_v3.int4_ord (never returns; always raises) +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int4_ord) +RETURNS eql_v3.int4_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ->> on eql_v2_int4_ord (domain, text). ---! @param a eql_v2_int4_ord +--! @brief Blocker for ->> on eql_v3.int4_ord (domain, text). +--! @param a eql_v3.int4_ord --! @param selector text --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."->>"(a eql_v2_int4_ord, selector text) +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4_ord, selector text) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v2_int4_ord'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ->> on eql_v2_int4_ord (domain, integer). ---! @param a eql_v2_int4_ord +--! @brief Blocker for ->> on eql_v3.int4_ord (domain, integer). +--! @param a eql_v3.int4_ord --! @param selector integer --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."->>"(a eql_v2_int4_ord, selector integer) +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4_ord, selector integer) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v2_int4_ord'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ->> on eql_v2_int4_ord (jsonb, domain). +--! @brief Blocker for ->> on eql_v3.int4_ord (jsonb, domain). --! @param a jsonb ---! @param selector eql_v2_int4_ord +--! @param selector eql_v3.int4_ord --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."->>"(a jsonb, selector eql_v2_int4_ord) +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.int4_ord) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v2_int4_ord'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ? on eql_v2_int4_ord (domain, text). ---! @param a eql_v2_int4_ord +--! @brief Blocker for ? on eql_v3.int4_ord (domain, text). +--! @param a eql_v3.int4_ord --! @param b text --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."?"(a eql_v2_int4_ord, b text) +CREATE FUNCTION eql_v3."?"(a eql_v3.int4_ord, b text) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord', '?'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '?'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ?| on eql_v2_int4_ord (domain, text[]). ---! @param a eql_v2_int4_ord +--! @brief Blocker for ?| on eql_v3.int4_ord (domain, text[]). +--! @param a eql_v3.int4_ord --! @param b text[] --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."?|"(a eql_v2_int4_ord, b text[]) +CREATE FUNCTION eql_v3."?|"(a eql_v3.int4_ord, b text[]) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord', '?|'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '?|'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ?& on eql_v2_int4_ord (domain, text[]). ---! @param a eql_v2_int4_ord +--! @brief Blocker for ?& on eql_v3.int4_ord (domain, text[]). +--! @param a eql_v3.int4_ord --! @param b text[] --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."?&"(a eql_v2_int4_ord, b text[]) +CREATE FUNCTION eql_v3."?&"(a eql_v3.int4_ord, b text[]) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord', '?&'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '?&'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @? on eql_v2_int4_ord (domain, jsonpath). ---! @param a eql_v2_int4_ord +--! @brief Blocker for @? on eql_v3.int4_ord (domain, jsonpath). +--! @param a eql_v3.int4_ord --! @param b jsonpath --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."@?"(a eql_v2_int4_ord, b jsonpath) +CREATE FUNCTION eql_v3."@?"(a eql_v3.int4_ord, b jsonpath) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord', '@?'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '@?'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @@ on eql_v2_int4_ord (domain, jsonpath). ---! @param a eql_v2_int4_ord +--! @brief Blocker for @@ on eql_v3.int4_ord (domain, jsonpath). +--! @param a eql_v3.int4_ord --! @param b jsonpath --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."@@"(a eql_v2_int4_ord, b jsonpath) +CREATE FUNCTION eql_v3."@@"(a eql_v3.int4_ord, b jsonpath) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord', '@@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '@@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for #> on eql_v2_int4_ord (domain, text[]). ---! @param a eql_v2_int4_ord +--! @brief Blocker for #> on eql_v3.int4_ord (domain, text[]). +--! @param a eql_v3.int4_ord --! @param b text[] --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."#>"(a eql_v2_int4_ord, b text[]) +CREATE FUNCTION eql_v3."#>"(a eql_v3.int4_ord, b text[]) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v2_int4_ord'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for #>> on eql_v2_int4_ord (domain, text[]). ---! @param a eql_v2_int4_ord +--! @brief Blocker for #>> on eql_v3.int4_ord (domain, text[]). +--! @param a eql_v3.int4_ord --! @param b text[] --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."#>>"(a eql_v2_int4_ord, b text[]) +CREATE FUNCTION eql_v3."#>>"(a eql_v3.int4_ord, b text[]) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v2_int4_ord'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for - on eql_v2_int4_ord (domain, text). ---! @param a eql_v2_int4_ord +--! @brief Blocker for - on eql_v3.int4_ord (domain, text). +--! @param a eql_v3.int4_ord --! @param b text --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."-"(a eql_v2_int4_ord, b text) +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_ord, b text) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v2_int4_ord'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for - on eql_v2_int4_ord (domain, integer). ---! @param a eql_v2_int4_ord +--! @brief Blocker for - on eql_v3.int4_ord (domain, integer). +--! @param a eql_v3.int4_ord --! @param b integer --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."-"(a eql_v2_int4_ord, b integer) +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_ord, b integer) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v2_int4_ord'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for - on eql_v2_int4_ord (domain, text[]). ---! @param a eql_v2_int4_ord +--! @brief Blocker for - on eql_v3.int4_ord (domain, text[]). +--! @param a eql_v3.int4_ord --! @param b text[] --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."-"(a eql_v2_int4_ord, b text[]) +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_ord, b text[]) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v2_int4_ord'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for #- on eql_v2_int4_ord (domain, text[]). ---! @param a eql_v2_int4_ord +--! @brief Blocker for #- on eql_v3.int4_ord (domain, text[]). +--! @param a eql_v3.int4_ord --! @param b text[] --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."#-"(a eql_v2_int4_ord, b text[]) +CREATE FUNCTION eql_v3."#-"(a eql_v3.int4_ord, b text[]) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v2_int4_ord'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for || on eql_v2_int4_ord. ---! @param a eql_v2_int4_ord ---! @param b eql_v2_int4_ord +--! @brief Blocker for || on eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."||"(a eql_v2_int4_ord, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3."||"(a eql_v3.int4_ord, b eql_v3.int4_ord) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v2_int4_ord'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for || on eql_v2_int4_ord (domain, jsonb). ---! @param a eql_v2_int4_ord +--! @brief Blocker for || on eql_v3.int4_ord (domain, jsonb). +--! @param a eql_v3.int4_ord --! @param b jsonb --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."||"(a eql_v2_int4_ord, b jsonb) +CREATE FUNCTION eql_v3."||"(a eql_v3.int4_ord, b jsonb) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v2_int4_ord'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for || on eql_v2_int4_ord (jsonb, domain). +--! @brief Blocker for || on eql_v3.int4_ord (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord +--! @param b eql_v3.int4_ord --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."||"(a jsonb, b eql_v2_int4_ord) +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int4_ord) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v2_int4_ord'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_ord'; END; $$ LANGUAGE plpgsql; diff --git a/tests/codegen/reference/int4/int4_ord_operators.sql b/tests/codegen/reference/int4/int4_ord_operators.sql index 3e3657f9..f52ecebb 100644 --- a/tests/codegen/reference/int4/int4_ord_operators.sql +++ b/tests/codegen/reference/int4/int4_ord_operators.sql @@ -1,5 +1,5 @@ -- REFERENCE: hand-written parity baseline for tasks/codegen/ — see ../README.md --- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql -- REQUIRE: src/encrypted_domain/int4/int4_types.sql -- REQUIRE: src/encrypted_domain/int4/int4_ord_functions.sql @@ -7,265 +7,265 @@ --! @brief Ordered domain of the int4 encrypted-domain family — operator declarations. CREATE OPERATOR = ( - FUNCTION = eql_v2.eq, - LEFTARG = eql_v2_int4_ord, RIGHTARG = eql_v2_int4_ord, + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord, COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel ); CREATE OPERATOR = ( - FUNCTION = eql_v2.eq, - LEFTARG = eql_v2_int4_ord, RIGHTARG = jsonb, + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb, COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel ); CREATE OPERATOR = ( - FUNCTION = eql_v2.eq, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord, + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord, COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel ); CREATE OPERATOR <> ( - FUNCTION = eql_v2.neq, - LEFTARG = eql_v2_int4_ord, RIGHTARG = eql_v2_int4_ord, + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord, COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel ); CREATE OPERATOR <> ( - FUNCTION = eql_v2.neq, - LEFTARG = eql_v2_int4_ord, RIGHTARG = jsonb, + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb, COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel ); CREATE OPERATOR <> ( - FUNCTION = eql_v2.neq, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord, + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord, COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel ); CREATE OPERATOR < ( - FUNCTION = eql_v2.lt, - LEFTARG = eql_v2_int4_ord, RIGHTARG = eql_v2_int4_ord, + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord, COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); CREATE OPERATOR < ( - FUNCTION = eql_v2.lt, - LEFTARG = eql_v2_int4_ord, RIGHTARG = jsonb, + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb, COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); CREATE OPERATOR < ( - FUNCTION = eql_v2.lt, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord, + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord, COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); CREATE OPERATOR <= ( - FUNCTION = eql_v2.lte, - LEFTARG = eql_v2_int4_ord, RIGHTARG = eql_v2_int4_ord, + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord, COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel ); CREATE OPERATOR <= ( - FUNCTION = eql_v2.lte, - LEFTARG = eql_v2_int4_ord, RIGHTARG = jsonb, + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb, COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel ); CREATE OPERATOR <= ( - FUNCTION = eql_v2.lte, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord, + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord, COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel ); CREATE OPERATOR > ( - FUNCTION = eql_v2.gt, - LEFTARG = eql_v2_int4_ord, RIGHTARG = eql_v2_int4_ord, + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord, COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); CREATE OPERATOR > ( - FUNCTION = eql_v2.gt, - LEFTARG = eql_v2_int4_ord, RIGHTARG = jsonb, + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb, COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); CREATE OPERATOR > ( - FUNCTION = eql_v2.gt, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord, + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord, COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); CREATE OPERATOR >= ( - FUNCTION = eql_v2.gte, - LEFTARG = eql_v2_int4_ord, RIGHTARG = eql_v2_int4_ord, + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord, COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel ); CREATE OPERATOR >= ( - FUNCTION = eql_v2.gte, - LEFTARG = eql_v2_int4_ord, RIGHTARG = jsonb, + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb, COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel ); CREATE OPERATOR >= ( - FUNCTION = eql_v2.gte, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord, + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord, COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel ); -- Placeholder: this domain's term set does not support @>; the backing function always raises. CREATE OPERATOR @> ( - FUNCTION = eql_v2.contains, - LEFTARG = eql_v2_int4_ord, RIGHTARG = eql_v2_int4_ord + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord ); -- Placeholder: this domain's term set does not support @>; the backing function always raises. CREATE OPERATOR @> ( - FUNCTION = eql_v2.contains, - LEFTARG = eql_v2_int4_ord, RIGHTARG = jsonb + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support @>; the backing function always raises. CREATE OPERATOR @> ( - FUNCTION = eql_v2.contains, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord ); -- Placeholder: this domain's term set does not support <@; the backing function always raises. CREATE OPERATOR <@ ( - FUNCTION = eql_v2.contained_by, - LEFTARG = eql_v2_int4_ord, RIGHTARG = eql_v2_int4_ord + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord ); -- Placeholder: this domain's term set does not support <@; the backing function always raises. CREATE OPERATOR <@ ( - FUNCTION = eql_v2.contained_by, - LEFTARG = eql_v2_int4_ord, RIGHTARG = jsonb + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support <@; the backing function always raises. CREATE OPERATOR <@ ( - FUNCTION = eql_v2.contained_by, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord ); -- Placeholder: this domain's term set does not support ->; the backing function always raises. CREATE OPERATOR -> ( - FUNCTION = eql_v2."->", - LEFTARG = eql_v2_int4_ord, RIGHTARG = text + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text ); -- Placeholder: this domain's term set does not support ->; the backing function always raises. CREATE OPERATOR -> ( - FUNCTION = eql_v2."->", - LEFTARG = eql_v2_int4_ord, RIGHTARG = integer + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4_ord, RIGHTARG = integer ); -- Placeholder: this domain's term set does not support ->; the backing function always raises. CREATE OPERATOR -> ( - FUNCTION = eql_v2."->", - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord ); -- Placeholder: this domain's term set does not support ->>; the backing function always raises. CREATE OPERATOR ->> ( - FUNCTION = eql_v2."->>", - LEFTARG = eql_v2_int4_ord, RIGHTARG = text + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text ); -- Placeholder: this domain's term set does not support ->>; the backing function always raises. CREATE OPERATOR ->> ( - FUNCTION = eql_v2."->>", - LEFTARG = eql_v2_int4_ord, RIGHTARG = integer + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4_ord, RIGHTARG = integer ); -- Placeholder: this domain's term set does not support ->>; the backing function always raises. CREATE OPERATOR ->> ( - FUNCTION = eql_v2."->>", - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord ); -- Placeholder: this domain's term set does not support ?; the backing function always raises. CREATE OPERATOR ? ( - FUNCTION = eql_v2."?", - LEFTARG = eql_v2_int4_ord, RIGHTARG = text + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text ); -- Placeholder: this domain's term set does not support ?|; the backing function always raises. CREATE OPERATOR ?| ( - FUNCTION = eql_v2."?|", - LEFTARG = eql_v2_int4_ord, RIGHTARG = text[] + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support ?&; the backing function always raises. CREATE OPERATOR ?& ( - FUNCTION = eql_v2."?&", - LEFTARG = eql_v2_int4_ord, RIGHTARG = text[] + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support @?; the backing function always raises. CREATE OPERATOR @? ( - FUNCTION = eql_v2."@?", - LEFTARG = eql_v2_int4_ord, RIGHTARG = jsonpath + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonpath ); -- Placeholder: this domain's term set does not support @@; the backing function always raises. CREATE OPERATOR @@ ( - FUNCTION = eql_v2."@@", - LEFTARG = eql_v2_int4_ord, RIGHTARG = jsonpath + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonpath ); -- Placeholder: this domain's term set does not support #>; the backing function always raises. CREATE OPERATOR #> ( - FUNCTION = eql_v2."#>", - LEFTARG = eql_v2_int4_ord, RIGHTARG = text[] + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support #>>; the backing function always raises. CREATE OPERATOR #>> ( - FUNCTION = eql_v2."#>>", - LEFTARG = eql_v2_int4_ord, RIGHTARG = text[] + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support -; the backing function always raises. CREATE OPERATOR - ( - FUNCTION = eql_v2."-", - LEFTARG = eql_v2_int4_ord, RIGHTARG = text + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text ); -- Placeholder: this domain's term set does not support -; the backing function always raises. CREATE OPERATOR - ( - FUNCTION = eql_v2."-", - LEFTARG = eql_v2_int4_ord, RIGHTARG = integer + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_ord, RIGHTARG = integer ); -- Placeholder: this domain's term set does not support -; the backing function always raises. CREATE OPERATOR - ( - FUNCTION = eql_v2."-", - LEFTARG = eql_v2_int4_ord, RIGHTARG = text[] + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support #-; the backing function always raises. CREATE OPERATOR #- ( - FUNCTION = eql_v2."#-", - LEFTARG = eql_v2_int4_ord, RIGHTARG = text[] + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support ||; the backing function always raises. CREATE OPERATOR || ( - FUNCTION = eql_v2."||", - LEFTARG = eql_v2_int4_ord, RIGHTARG = eql_v2_int4_ord + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord ); -- Placeholder: this domain's term set does not support ||; the backing function always raises. CREATE OPERATOR || ( - FUNCTION = eql_v2."||", - LEFTARG = eql_v2_int4_ord, RIGHTARG = jsonb + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support ||; the backing function always raises. CREATE OPERATOR || ( - FUNCTION = eql_v2."||", - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord ); diff --git a/tests/codegen/reference/int4/int4_ord_ore_aggregates.sql b/tests/codegen/reference/int4/int4_ord_ore_aggregates.sql index f2f1e81e..26396459 100644 --- a/tests/codegen/reference/int4/int4_ord_ore_aggregates.sql +++ b/tests/codegen/reference/int4/int4_ord_ore_aggregates.sql @@ -1,5 +1,5 @@ -- REFERENCE: hand-written parity baseline for tasks/codegen/ — see ../README.md --- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql -- REQUIRE: src/encrypted_domain/int4/int4_types.sql -- REQUIRE: src/encrypted_domain/int4/int4_ord_ore_functions.sql -- REQUIRE: src/encrypted_domain/int4/int4_ord_ore_operators.sql @@ -7,18 +7,18 @@ --! @file encrypted_domain/int4/int4_ord_ore_aggregates.sql --! @brief Ordered domain of the int4 encrypted-domain family — MIN/MAX aggregates. ---! @brief State function for min aggregate on eql_v2_int4_ord_ore. +--! @brief State function for min aggregate on eql_v3.int4_ord_ore. --! @internal --! ---! @param state eql_v2_int4_ord_ore running extremum ---! @param value eql_v2_int4_ord_ore next non-NULL value ---! @return eql_v2_int4_ord_ore the minimum of state and value +--! @param state eql_v3.int4_ord_ore running extremum +--! @param value eql_v3.int4_ord_ore next non-NULL value +--! @return eql_v3.int4_ord_ore the minimum of state and value -- LANGUAGE plpgsql, not sql: aggregate state functions are not index -- expressions, so opacity to the planner is fine, and a multi-statement -- BEGIN/IF/END body is the natural shape. (A LANGUAGE sql CASE would -- also work, but the procedural form mirrors the blocker convention.) -CREATE FUNCTION eql_v2.min_sfunc(state eql_v2_int4_ord_ore, value eql_v2_int4_ord_ore) -RETURNS eql_v2_int4_ord_ore +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.int4_ord_ore, value eql_v3.int4_ord_ore) +RETURNS eql_v3.int4_ord_ore LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE SET search_path = pg_catalog, extensions, public AS $$ @@ -30,34 +30,34 @@ BEGIN END; $$; ---! @brief Find the minimum encrypted value in a group of eql_v2_int4_ord_ore values. +--! @brief Find the minimum encrypted value in a group of eql_v3.int4_ord_ore values. --! --! Comparison routes through the domain's `<` operator, which uses the ORE block term — no decryption. --! ---! @param input eql_v2_int4_ord_ore encrypted values to aggregate ---! @return eql_v2_int4_ord_ore minimum of the group, or NULL if all inputs are NULL +--! @param input eql_v3.int4_ord_ore encrypted values to aggregate +--! @return eql_v3.int4_ord_ore minimum of the group, or NULL if all inputs are NULL -- combinefunc = sfunc: min/max are associative, so merging two partial -- extrema is the same comparison. PARALLEL SAFE enables partial and -- parallel aggregation on large GROUP BY workloads, with no decryption. -CREATE AGGREGATE eql_v2.min(eql_v2_int4_ord_ore) ( - sfunc = eql_v2.min_sfunc, - stype = eql_v2_int4_ord_ore, - combinefunc = eql_v2.min_sfunc, +CREATE AGGREGATE eql_v3.min(eql_v3.int4_ord_ore) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.int4_ord_ore, + combinefunc = eql_v3.min_sfunc, parallel = safe ); ---! @brief State function for max aggregate on eql_v2_int4_ord_ore. +--! @brief State function for max aggregate on eql_v3.int4_ord_ore. --! @internal --! ---! @param state eql_v2_int4_ord_ore running extremum ---! @param value eql_v2_int4_ord_ore next non-NULL value ---! @return eql_v2_int4_ord_ore the maximum of state and value +--! @param state eql_v3.int4_ord_ore running extremum +--! @param value eql_v3.int4_ord_ore next non-NULL value +--! @return eql_v3.int4_ord_ore the maximum of state and value -- LANGUAGE plpgsql, not sql: aggregate state functions are not index -- expressions, so opacity to the planner is fine, and a multi-statement -- BEGIN/IF/END body is the natural shape. (A LANGUAGE sql CASE would -- also work, but the procedural form mirrors the blocker convention.) -CREATE FUNCTION eql_v2.max_sfunc(state eql_v2_int4_ord_ore, value eql_v2_int4_ord_ore) -RETURNS eql_v2_int4_ord_ore +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.int4_ord_ore, value eql_v3.int4_ord_ore) +RETURNS eql_v3.int4_ord_ore LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE SET search_path = pg_catalog, extensions, public AS $$ @@ -69,18 +69,18 @@ BEGIN END; $$; ---! @brief Find the maximum encrypted value in a group of eql_v2_int4_ord_ore values. +--! @brief Find the maximum encrypted value in a group of eql_v3.int4_ord_ore values. --! --! Comparison routes through the domain's `>` operator, which uses the ORE block term — no decryption. --! ---! @param input eql_v2_int4_ord_ore encrypted values to aggregate ---! @return eql_v2_int4_ord_ore maximum of the group, or NULL if all inputs are NULL +--! @param input eql_v3.int4_ord_ore encrypted values to aggregate +--! @return eql_v3.int4_ord_ore maximum of the group, or NULL if all inputs are NULL -- combinefunc = sfunc: min/max are associative, so merging two partial -- extrema is the same comparison. PARALLEL SAFE enables partial and -- parallel aggregation on large GROUP BY workloads, with no decryption. -CREATE AGGREGATE eql_v2.max(eql_v2_int4_ord_ore) ( - sfunc = eql_v2.max_sfunc, - stype = eql_v2_int4_ord_ore, - combinefunc = eql_v2.max_sfunc, +CREATE AGGREGATE eql_v3.max(eql_v3.int4_ord_ore) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.int4_ord_ore, + combinefunc = eql_v3.max_sfunc, parallel = safe ); diff --git a/tests/codegen/reference/int4/int4_ord_ore_functions.sql b/tests/codegen/reference/int4/int4_ord_ore_functions.sql index bd6fe8b4..005bf672 100644 --- a/tests/codegen/reference/int4/int4_ord_ore_functions.sql +++ b/tests/codegen/reference/int4/int4_ord_ore_functions.sql @@ -1,5 +1,6 @@ -- REFERENCE: hand-written parity baseline for tasks/codegen/ — see ../README.md -- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql -- REQUIRE: src/encrypted_domain/int4/int4_types.sql -- REQUIRE: src/encrypted_domain/functions.sql -- REQUIRE: src/ore_block_u64_8_256/functions.sql @@ -8,388 +9,388 @@ --! @file encrypted_domain/int4/int4_ord_ore_functions.sql --! @brief Ordered domain of the int4 encrypted-domain family — comparison/path functions. ---! @brief Index extractor for the eql_v2_int4_ord_ore variant. ---! @param a eql_v2_int4_ord_ore +--! @brief Index extractor for the eql_v3.int4_ord_ore variant. +--! @param a eql_v3.int4_ord_ore --! @return eql_v2.ore_block_u64_8_256 -CREATE FUNCTION eql_v2.ord_term(a eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.ord_term(a eql_v3.int4_ord_ore) RETURNS eql_v2.ore_block_u64_8_256 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS $$ SELECT eql_v2.ore_block_u64_8_256(a::jsonb) $$; ---! @brief Equality wrapper for eql_v2_int4_ord_ore. ---! @param a eql_v2_int4_ord_ore ---! @param b eql_v2_int4_ord_ore +--! @brief Equality wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean -CREATE FUNCTION eql_v2.eq(a eql_v2_int4_ord_ore, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.eq(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) = eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; ---! @brief Equality wrapper for eql_v2_int4_ord_ore (domain, jsonb). ---! @param a eql_v2_int4_ord_ore +--! @brief Equality wrapper for eql_v3.int4_ord_ore (domain, jsonb). +--! @param a eql_v3.int4_ord_ore --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.eq(a eql_v2_int4_ord_ore, b jsonb) +CREATE FUNCTION eql_v3.eq(a eql_v3.int4_ord_ore, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) = eql_v2.ord_term(b::eql_v2_int4_ord_ore) $$; +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.int4_ord_ore) $$; ---! @brief Equality wrapper for eql_v2_int4_ord_ore (jsonb, domain). +--! @brief Equality wrapper for eql_v3.int4_ord_ore (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean -CREATE FUNCTION eql_v2.eq(a jsonb, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.int4_ord_ore) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a::eql_v2_int4_ord_ore) = eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord_ore) = eql_v3.ord_term(b) $$; ---! @brief Inequality wrapper for eql_v2_int4_ord_ore. ---! @param a eql_v2_int4_ord_ore ---! @param b eql_v2_int4_ord_ore +--! @brief Inequality wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean -CREATE FUNCTION eql_v2.neq(a eql_v2_int4_ord_ore, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.neq(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) <> eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; ---! @brief Inequality wrapper for eql_v2_int4_ord_ore (domain, jsonb). ---! @param a eql_v2_int4_ord_ore +--! @brief Inequality wrapper for eql_v3.int4_ord_ore (domain, jsonb). +--! @param a eql_v3.int4_ord_ore --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.neq(a eql_v2_int4_ord_ore, b jsonb) +CREATE FUNCTION eql_v3.neq(a eql_v3.int4_ord_ore, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) <> eql_v2.ord_term(b::eql_v2_int4_ord_ore) $$; +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.int4_ord_ore) $$; ---! @brief Inequality wrapper for eql_v2_int4_ord_ore (jsonb, domain). +--! @brief Inequality wrapper for eql_v3.int4_ord_ore (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean -CREATE FUNCTION eql_v2.neq(a jsonb, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.int4_ord_ore) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a::eql_v2_int4_ord_ore) <> eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord_ore) <> eql_v3.ord_term(b) $$; ---! @brief Less-than wrapper for eql_v2_int4_ord_ore. ---! @param a eql_v2_int4_ord_ore ---! @param b eql_v2_int4_ord_ore +--! @brief Less-than wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean -CREATE FUNCTION eql_v2.lt(a eql_v2_int4_ord_ore, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.lt(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) < eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; ---! @brief Less-than wrapper for eql_v2_int4_ord_ore (domain, jsonb). ---! @param a eql_v2_int4_ord_ore +--! @brief Less-than wrapper for eql_v3.int4_ord_ore (domain, jsonb). +--! @param a eql_v3.int4_ord_ore --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.lt(a eql_v2_int4_ord_ore, b jsonb) +CREATE FUNCTION eql_v3.lt(a eql_v3.int4_ord_ore, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) < eql_v2.ord_term(b::eql_v2_int4_ord_ore) $$; +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.int4_ord_ore) $$; ---! @brief Less-than wrapper for eql_v2_int4_ord_ore (jsonb, domain). +--! @brief Less-than wrapper for eql_v3.int4_ord_ore (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean -CREATE FUNCTION eql_v2.lt(a jsonb, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.int4_ord_ore) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a::eql_v2_int4_ord_ore) < eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord_ore) < eql_v3.ord_term(b) $$; ---! @brief Less-than-or-equal wrapper for eql_v2_int4_ord_ore. ---! @param a eql_v2_int4_ord_ore ---! @param b eql_v2_int4_ord_ore +--! @brief Less-than-or-equal wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean -CREATE FUNCTION eql_v2.lte(a eql_v2_int4_ord_ore, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.lte(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) <= eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; ---! @brief Less-than-or-equal wrapper for eql_v2_int4_ord_ore (domain, jsonb). ---! @param a eql_v2_int4_ord_ore +--! @brief Less-than-or-equal wrapper for eql_v3.int4_ord_ore (domain, jsonb). +--! @param a eql_v3.int4_ord_ore --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.lte(a eql_v2_int4_ord_ore, b jsonb) +CREATE FUNCTION eql_v3.lte(a eql_v3.int4_ord_ore, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) <= eql_v2.ord_term(b::eql_v2_int4_ord_ore) $$; +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.int4_ord_ore) $$; ---! @brief Less-than-or-equal wrapper for eql_v2_int4_ord_ore (jsonb, domain). +--! @brief Less-than-or-equal wrapper for eql_v3.int4_ord_ore (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean -CREATE FUNCTION eql_v2.lte(a jsonb, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.int4_ord_ore) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a::eql_v2_int4_ord_ore) <= eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord_ore) <= eql_v3.ord_term(b) $$; ---! @brief Greater-than wrapper for eql_v2_int4_ord_ore. ---! @param a eql_v2_int4_ord_ore ---! @param b eql_v2_int4_ord_ore +--! @brief Greater-than wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean -CREATE FUNCTION eql_v2.gt(a eql_v2_int4_ord_ore, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.gt(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) > eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; ---! @brief Greater-than wrapper for eql_v2_int4_ord_ore (domain, jsonb). ---! @param a eql_v2_int4_ord_ore +--! @brief Greater-than wrapper for eql_v3.int4_ord_ore (domain, jsonb). +--! @param a eql_v3.int4_ord_ore --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.gt(a eql_v2_int4_ord_ore, b jsonb) +CREATE FUNCTION eql_v3.gt(a eql_v3.int4_ord_ore, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) > eql_v2.ord_term(b::eql_v2_int4_ord_ore) $$; +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.int4_ord_ore) $$; ---! @brief Greater-than wrapper for eql_v2_int4_ord_ore (jsonb, domain). +--! @brief Greater-than wrapper for eql_v3.int4_ord_ore (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean -CREATE FUNCTION eql_v2.gt(a jsonb, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.int4_ord_ore) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a::eql_v2_int4_ord_ore) > eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord_ore) > eql_v3.ord_term(b) $$; ---! @brief Greater-than-or-equal wrapper for eql_v2_int4_ord_ore. ---! @param a eql_v2_int4_ord_ore ---! @param b eql_v2_int4_ord_ore +--! @brief Greater-than-or-equal wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean -CREATE FUNCTION eql_v2.gte(a eql_v2_int4_ord_ore, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.gte(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) >= eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; ---! @brief Greater-than-or-equal wrapper for eql_v2_int4_ord_ore (domain, jsonb). ---! @param a eql_v2_int4_ord_ore +--! @brief Greater-than-or-equal wrapper for eql_v3.int4_ord_ore (domain, jsonb). +--! @param a eql_v3.int4_ord_ore --! @param b jsonb --! @return boolean -CREATE FUNCTION eql_v2.gte(a eql_v2_int4_ord_ore, b jsonb) +CREATE FUNCTION eql_v3.gte(a eql_v3.int4_ord_ore, b jsonb) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a) >= eql_v2.ord_term(b::eql_v2_int4_ord_ore) $$; +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.int4_ord_ore) $$; ---! @brief Greater-than-or-equal wrapper for eql_v2_int4_ord_ore (jsonb, domain). +--! @brief Greater-than-or-equal wrapper for eql_v3.int4_ord_ore (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean -CREATE FUNCTION eql_v2.gte(a jsonb, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.int4_ord_ore) RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE -AS $$ SELECT eql_v2.ord_term(a::eql_v2_int4_ord_ore) >= eql_v2.ord_term(b) $$; +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord_ore) >= eql_v3.ord_term(b) $$; ---! @brief Blocker for @> on eql_v2_int4_ord_ore. ---! @param a eql_v2_int4_ord_ore ---! @param b eql_v2_int4_ord_ore +--! @brief Blocker for @> on eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contains(a eql_v2_int4_ord_ore, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.contains(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord_ore', '@>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord_ore', '@>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @> on eql_v2_int4_ord_ore (domain, jsonb). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for @> on eql_v3.int4_ord_ore (domain, jsonb). +--! @param a eql_v3.int4_ord_ore --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contains(a eql_v2_int4_ord_ore, b jsonb) +CREATE FUNCTION eql_v3.contains(a eql_v3.int4_ord_ore, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord_ore', '@>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord_ore', '@>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @> on eql_v2_int4_ord_ore (jsonb, domain). +--! @brief Blocker for @> on eql_v3.int4_ord_ore (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contains(a jsonb, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.int4_ord_ore) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord_ore', '@>'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord_ore', '@>'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <@ on eql_v2_int4_ord_ore. ---! @param a eql_v2_int4_ord_ore ---! @param b eql_v2_int4_ord_ore +--! @brief Blocker for <@ on eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contained_by(a eql_v2_int4_ord_ore, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord_ore', '<@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord_ore', '<@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <@ on eql_v2_int4_ord_ore (domain, jsonb). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for <@ on eql_v3.int4_ord_ore (domain, jsonb). +--! @param a eql_v3.int4_ord_ore --! @param b jsonb --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contained_by(a eql_v2_int4_ord_ore, b jsonb) +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4_ord_ore, b jsonb) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord_ore', '<@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord_ore', '<@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for <@ on eql_v2_int4_ord_ore (jsonb, domain). +--! @brief Blocker for <@ on eql_v3.int4_ord_ore (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2.contained_by(a jsonb, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.int4_ord_ore) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord_ore', '<@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord_ore', '<@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for -> on eql_v2_int4_ord_ore (domain, text). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for -> on eql_v3.int4_ord_ore (domain, text). +--! @param a eql_v3.int4_ord_ore --! @param selector text ---! @return eql_v2_int4_ord_ore (never returns; always raises) -CREATE FUNCTION eql_v2."->"(a eql_v2_int4_ord_ore, selector text) -RETURNS eql_v2_int4_ord_ore IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v2_int4_ord_ore'; END; $$ +--! @return eql_v3.int4_ord_ore (never returns; always raises) +CREATE FUNCTION eql_v3."->"(a eql_v3.int4_ord_ore, selector text) +RETURNS eql_v3.int4_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for -> on eql_v2_int4_ord_ore (domain, integer). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for -> on eql_v3.int4_ord_ore (domain, integer). +--! @param a eql_v3.int4_ord_ore --! @param selector integer ---! @return eql_v2_int4_ord_ore (never returns; always raises) -CREATE FUNCTION eql_v2."->"(a eql_v2_int4_ord_ore, selector integer) -RETURNS eql_v2_int4_ord_ore IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v2_int4_ord_ore'; END; $$ +--! @return eql_v3.int4_ord_ore (never returns; always raises) +CREATE FUNCTION eql_v3."->"(a eql_v3.int4_ord_ore, selector integer) +RETURNS eql_v3.int4_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for -> on eql_v2_int4_ord_ore (jsonb, domain). +--! @brief Blocker for -> on eql_v3.int4_ord_ore (jsonb, domain). --! @param a jsonb ---! @param selector eql_v2_int4_ord_ore ---! @return eql_v2_int4_ord_ore (never returns; always raises) -CREATE FUNCTION eql_v2."->"(a jsonb, selector eql_v2_int4_ord_ore) -RETURNS eql_v2_int4_ord_ore IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v2_int4_ord_ore'; END; $$ +--! @param selector eql_v3.int4_ord_ore +--! @return eql_v3.int4_ord_ore (never returns; always raises) +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int4_ord_ore) +RETURNS eql_v3.int4_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ->> on eql_v2_int4_ord_ore (domain, text). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for ->> on eql_v3.int4_ord_ore (domain, text). +--! @param a eql_v3.int4_ord_ore --! @param selector text --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."->>"(a eql_v2_int4_ord_ore, selector text) +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4_ord_ore, selector text) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v2_int4_ord_ore'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ->> on eql_v2_int4_ord_ore (domain, integer). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for ->> on eql_v3.int4_ord_ore (domain, integer). +--! @param a eql_v3.int4_ord_ore --! @param selector integer --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."->>"(a eql_v2_int4_ord_ore, selector integer) +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4_ord_ore, selector integer) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v2_int4_ord_ore'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ->> on eql_v2_int4_ord_ore (jsonb, domain). +--! @brief Blocker for ->> on eql_v3.int4_ord_ore (jsonb, domain). --! @param a jsonb ---! @param selector eql_v2_int4_ord_ore +--! @param selector eql_v3.int4_ord_ore --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."->>"(a jsonb, selector eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.int4_ord_ore) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v2_int4_ord_ore'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ? on eql_v2_int4_ord_ore (domain, text). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for ? on eql_v3.int4_ord_ore (domain, text). +--! @param a eql_v3.int4_ord_ore --! @param b text --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."?"(a eql_v2_int4_ord_ore, b text) +CREATE FUNCTION eql_v3."?"(a eql_v3.int4_ord_ore, b text) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord_ore', '?'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord_ore', '?'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ?| on eql_v2_int4_ord_ore (domain, text[]). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for ?| on eql_v3.int4_ord_ore (domain, text[]). +--! @param a eql_v3.int4_ord_ore --! @param b text[] --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."?|"(a eql_v2_int4_ord_ore, b text[]) +CREATE FUNCTION eql_v3."?|"(a eql_v3.int4_ord_ore, b text[]) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord_ore', '?|'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord_ore', '?|'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for ?& on eql_v2_int4_ord_ore (domain, text[]). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for ?& on eql_v3.int4_ord_ore (domain, text[]). +--! @param a eql_v3.int4_ord_ore --! @param b text[] --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."?&"(a eql_v2_int4_ord_ore, b text[]) +CREATE FUNCTION eql_v3."?&"(a eql_v3.int4_ord_ore, b text[]) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord_ore', '?&'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord_ore', '?&'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @? on eql_v2_int4_ord_ore (domain, jsonpath). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for @? on eql_v3.int4_ord_ore (domain, jsonpath). +--! @param a eql_v3.int4_ord_ore --! @param b jsonpath --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."@?"(a eql_v2_int4_ord_ore, b jsonpath) +CREATE FUNCTION eql_v3."@?"(a eql_v3.int4_ord_ore, b jsonpath) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord_ore', '@?'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord_ore', '@?'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for @@ on eql_v2_int4_ord_ore (domain, jsonpath). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for @@ on eql_v3.int4_ord_ore (domain, jsonpath). +--! @param a eql_v3.int4_ord_ore --! @param b jsonpath --! @return boolean (never returns; always raises) -CREATE FUNCTION eql_v2."@@"(a eql_v2_int4_ord_ore, b jsonpath) +CREATE FUNCTION eql_v3."@@"(a eql_v3.int4_ord_ore, b jsonpath) RETURNS boolean IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord_ore', '@@'); END; $$ +AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord_ore', '@@'); END; $$ LANGUAGE plpgsql; ---! @brief Blocker for #> on eql_v2_int4_ord_ore (domain, text[]). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for #> on eql_v3.int4_ord_ore (domain, text[]). +--! @param a eql_v3.int4_ord_ore --! @param b text[] --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."#>"(a eql_v2_int4_ord_ore, b text[]) +CREATE FUNCTION eql_v3."#>"(a eql_v3.int4_ord_ore, b text[]) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v2_int4_ord_ore'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for #>> on eql_v2_int4_ord_ore (domain, text[]). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for #>> on eql_v3.int4_ord_ore (domain, text[]). +--! @param a eql_v3.int4_ord_ore --! @param b text[] --! @return text (never returns; always raises) -CREATE FUNCTION eql_v2."#>>"(a eql_v2_int4_ord_ore, b text[]) +CREATE FUNCTION eql_v3."#>>"(a eql_v3.int4_ord_ore, b text[]) RETURNS text IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v2_int4_ord_ore'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for - on eql_v2_int4_ord_ore (domain, text). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for - on eql_v3.int4_ord_ore (domain, text). +--! @param a eql_v3.int4_ord_ore --! @param b text --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."-"(a eql_v2_int4_ord_ore, b text) +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_ord_ore, b text) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v2_int4_ord_ore'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for - on eql_v2_int4_ord_ore (domain, integer). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for - on eql_v3.int4_ord_ore (domain, integer). +--! @param a eql_v3.int4_ord_ore --! @param b integer --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."-"(a eql_v2_int4_ord_ore, b integer) +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_ord_ore, b integer) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v2_int4_ord_ore'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for - on eql_v2_int4_ord_ore (domain, text[]). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for - on eql_v3.int4_ord_ore (domain, text[]). +--! @param a eql_v3.int4_ord_ore --! @param b text[] --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."-"(a eql_v2_int4_ord_ore, b text[]) +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_ord_ore, b text[]) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v2_int4_ord_ore'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for #- on eql_v2_int4_ord_ore (domain, text[]). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for #- on eql_v3.int4_ord_ore (domain, text[]). +--! @param a eql_v3.int4_ord_ore --! @param b text[] --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."#-"(a eql_v2_int4_ord_ore, b text[]) +CREATE FUNCTION eql_v3."#-"(a eql_v3.int4_ord_ore, b text[]) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v2_int4_ord_ore'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for || on eql_v2_int4_ord_ore. ---! @param a eql_v2_int4_ord_ore ---! @param b eql_v2_int4_ord_ore +--! @brief Blocker for || on eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."||"(a eql_v2_int4_ord_ore, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3."||"(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v2_int4_ord_ore'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for || on eql_v2_int4_ord_ore (domain, jsonb). ---! @param a eql_v2_int4_ord_ore +--! @brief Blocker for || on eql_v3.int4_ord_ore (domain, jsonb). +--! @param a eql_v3.int4_ord_ore --! @param b jsonb --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."||"(a eql_v2_int4_ord_ore, b jsonb) +CREATE FUNCTION eql_v3."||"(a eql_v3.int4_ord_ore, b jsonb) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v2_int4_ord_ore'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; ---! @brief Blocker for || on eql_v2_int4_ord_ore (jsonb, domain). +--! @brief Blocker for || on eql_v3.int4_ord_ore (jsonb, domain). --! @param a jsonb ---! @param b eql_v2_int4_ord_ore +--! @param b eql_v3.int4_ord_ore --! @return jsonb (never returns; always raises) -CREATE FUNCTION eql_v2."||"(a jsonb, b eql_v2_int4_ord_ore) +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int4_ord_ore) RETURNS jsonb IMMUTABLE PARALLEL SAFE -AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v2_int4_ord_ore'; END; $$ +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_ord_ore'; END; $$ LANGUAGE plpgsql; diff --git a/tests/codegen/reference/int4/int4_ord_ore_operators.sql b/tests/codegen/reference/int4/int4_ord_ore_operators.sql index ee1f84cf..e6dc27e9 100644 --- a/tests/codegen/reference/int4/int4_ord_ore_operators.sql +++ b/tests/codegen/reference/int4/int4_ord_ore_operators.sql @@ -1,5 +1,5 @@ -- REFERENCE: hand-written parity baseline for tasks/codegen/ — see ../README.md --- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql -- REQUIRE: src/encrypted_domain/int4/int4_types.sql -- REQUIRE: src/encrypted_domain/int4/int4_ord_ore_functions.sql @@ -7,265 +7,265 @@ --! @brief Ordered domain of the int4 encrypted-domain family — operator declarations. CREATE OPERATOR = ( - FUNCTION = eql_v2.eq, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = eql_v2_int4_ord_ore, + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore, COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel ); CREATE OPERATOR = ( - FUNCTION = eql_v2.eq, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = jsonb, + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb, COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel ); CREATE OPERATOR = ( - FUNCTION = eql_v2.eq, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord_ore, + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore, COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel ); CREATE OPERATOR <> ( - FUNCTION = eql_v2.neq, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = eql_v2_int4_ord_ore, + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore, COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel ); CREATE OPERATOR <> ( - FUNCTION = eql_v2.neq, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = jsonb, + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb, COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel ); CREATE OPERATOR <> ( - FUNCTION = eql_v2.neq, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord_ore, + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore, COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel ); CREATE OPERATOR < ( - FUNCTION = eql_v2.lt, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = eql_v2_int4_ord_ore, + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore, COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); CREATE OPERATOR < ( - FUNCTION = eql_v2.lt, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = jsonb, + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb, COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); CREATE OPERATOR < ( - FUNCTION = eql_v2.lt, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord_ore, + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore, COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); CREATE OPERATOR <= ( - FUNCTION = eql_v2.lte, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = eql_v2_int4_ord_ore, + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore, COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel ); CREATE OPERATOR <= ( - FUNCTION = eql_v2.lte, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = jsonb, + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb, COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel ); CREATE OPERATOR <= ( - FUNCTION = eql_v2.lte, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord_ore, + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore, COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel ); CREATE OPERATOR > ( - FUNCTION = eql_v2.gt, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = eql_v2_int4_ord_ore, + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore, COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); CREATE OPERATOR > ( - FUNCTION = eql_v2.gt, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = jsonb, + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb, COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); CREATE OPERATOR > ( - FUNCTION = eql_v2.gt, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord_ore, + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore, COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); CREATE OPERATOR >= ( - FUNCTION = eql_v2.gte, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = eql_v2_int4_ord_ore, + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore, COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel ); CREATE OPERATOR >= ( - FUNCTION = eql_v2.gte, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = jsonb, + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb, COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel ); CREATE OPERATOR >= ( - FUNCTION = eql_v2.gte, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord_ore, + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore, COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel ); -- Placeholder: this domain's term set does not support @>; the backing function always raises. CREATE OPERATOR @> ( - FUNCTION = eql_v2.contains, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = eql_v2_int4_ord_ore + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore ); -- Placeholder: this domain's term set does not support @>; the backing function always raises. CREATE OPERATOR @> ( - FUNCTION = eql_v2.contains, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = jsonb + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support @>; the backing function always raises. CREATE OPERATOR @> ( - FUNCTION = eql_v2.contains, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord_ore + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore ); -- Placeholder: this domain's term set does not support <@; the backing function always raises. CREATE OPERATOR <@ ( - FUNCTION = eql_v2.contained_by, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = eql_v2_int4_ord_ore + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore ); -- Placeholder: this domain's term set does not support <@; the backing function always raises. CREATE OPERATOR <@ ( - FUNCTION = eql_v2.contained_by, - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = jsonb + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support <@; the backing function always raises. CREATE OPERATOR <@ ( - FUNCTION = eql_v2.contained_by, - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord_ore + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore ); -- Placeholder: this domain's term set does not support ->; the backing function always raises. CREATE OPERATOR -> ( - FUNCTION = eql_v2."->", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = text + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text ); -- Placeholder: this domain's term set does not support ->; the backing function always raises. CREATE OPERATOR -> ( - FUNCTION = eql_v2."->", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = integer + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = integer ); -- Placeholder: this domain's term set does not support ->; the backing function always raises. CREATE OPERATOR -> ( - FUNCTION = eql_v2."->", - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord_ore + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore ); -- Placeholder: this domain's term set does not support ->>; the backing function always raises. CREATE OPERATOR ->> ( - FUNCTION = eql_v2."->>", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = text + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text ); -- Placeholder: this domain's term set does not support ->>; the backing function always raises. CREATE OPERATOR ->> ( - FUNCTION = eql_v2."->>", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = integer + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = integer ); -- Placeholder: this domain's term set does not support ->>; the backing function always raises. CREATE OPERATOR ->> ( - FUNCTION = eql_v2."->>", - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord_ore + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore ); -- Placeholder: this domain's term set does not support ?; the backing function always raises. CREATE OPERATOR ? ( - FUNCTION = eql_v2."?", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = text + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text ); -- Placeholder: this domain's term set does not support ?|; the backing function always raises. CREATE OPERATOR ?| ( - FUNCTION = eql_v2."?|", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = text[] + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support ?&; the backing function always raises. CREATE OPERATOR ?& ( - FUNCTION = eql_v2."?&", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = text[] + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support @?; the backing function always raises. CREATE OPERATOR @? ( - FUNCTION = eql_v2."@?", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = jsonpath + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonpath ); -- Placeholder: this domain's term set does not support @@; the backing function always raises. CREATE OPERATOR @@ ( - FUNCTION = eql_v2."@@", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = jsonpath + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonpath ); -- Placeholder: this domain's term set does not support #>; the backing function always raises. CREATE OPERATOR #> ( - FUNCTION = eql_v2."#>", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = text[] + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support #>>; the backing function always raises. CREATE OPERATOR #>> ( - FUNCTION = eql_v2."#>>", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = text[] + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support -; the backing function always raises. CREATE OPERATOR - ( - FUNCTION = eql_v2."-", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = text + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text ); -- Placeholder: this domain's term set does not support -; the backing function always raises. CREATE OPERATOR - ( - FUNCTION = eql_v2."-", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = integer + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = integer ); -- Placeholder: this domain's term set does not support -; the backing function always raises. CREATE OPERATOR - ( - FUNCTION = eql_v2."-", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = text[] + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support #-; the backing function always raises. CREATE OPERATOR #- ( - FUNCTION = eql_v2."#-", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = text[] + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text[] ); -- Placeholder: this domain's term set does not support ||; the backing function always raises. CREATE OPERATOR || ( - FUNCTION = eql_v2."||", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = eql_v2_int4_ord_ore + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore ); -- Placeholder: this domain's term set does not support ||; the backing function always raises. CREATE OPERATOR || ( - FUNCTION = eql_v2."||", - LEFTARG = eql_v2_int4_ord_ore, RIGHTARG = jsonb + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb ); -- Placeholder: this domain's term set does not support ||; the backing function always raises. CREATE OPERATOR || ( - FUNCTION = eql_v2."||", - LEFTARG = jsonb, RIGHTARG = eql_v2_int4_ord_ore + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore ); diff --git a/tests/codegen/reference/int4/int4_types.sql b/tests/codegen/reference/int4/int4_types.sql index f7616539..0b33e740 100644 --- a/tests/codegen/reference/int4/int4_types.sql +++ b/tests/codegen/reference/int4/int4_types.sql @@ -1,5 +1,5 @@ -- REFERENCE: hand-written parity baseline for tasks/codegen/ — see ../README.md --- REQUIRE: src/schema.sql +-- REQUIRE: src/schema-v3.sql --! @file encrypted_domain/int4/int4_types.sql --! @brief Encrypted-domain type family for int4. @@ -9,9 +9,9 @@ BEGIN --! @brief Storage-only encrypted int4 domain. IF NOT EXISTS ( SELECT 1 FROM pg_type - WHERE typname = 'eql_v2_int4' AND typnamespace = 'public'::regnamespace + WHERE typname = 'int4' AND typnamespace = 'eql_v3'::regnamespace ) THEN - CREATE DOMAIN public.eql_v2_int4 AS jsonb + CREATE DOMAIN eql_v3.int4 AS jsonb CHECK ( jsonb_typeof(VALUE) = 'object' AND VALUE ? 'v' @@ -24,9 +24,9 @@ BEGIN --! @brief Equality-only encrypted int4 domain. IF NOT EXISTS ( SELECT 1 FROM pg_type - WHERE typname = 'eql_v2_int4_eq' AND typnamespace = 'public'::regnamespace + WHERE typname = 'int4_eq' AND typnamespace = 'eql_v3'::regnamespace ) THEN - CREATE DOMAIN public.eql_v2_int4_eq AS jsonb + CREATE DOMAIN eql_v3.int4_eq AS jsonb CHECK ( jsonb_typeof(VALUE) = 'object' AND VALUE ? 'v' @@ -40,9 +40,9 @@ BEGIN --! @brief Ordered encrypted int4 domain. Scheme-explicit twin pinning the ore scheme; prefer the converged int4_ord name. IF NOT EXISTS ( SELECT 1 FROM pg_type - WHERE typname = 'eql_v2_int4_ord_ore' AND typnamespace = 'public'::regnamespace + WHERE typname = 'int4_ord_ore' AND typnamespace = 'eql_v3'::regnamespace ) THEN - CREATE DOMAIN public.eql_v2_int4_ord_ore AS jsonb + CREATE DOMAIN eql_v3.int4_ord_ore AS jsonb CHECK ( jsonb_typeof(VALUE) = 'object' AND VALUE ? 'v' @@ -56,9 +56,9 @@ BEGIN --! @brief Ordered encrypted int4 domain. Recommended converged name for this role. IF NOT EXISTS ( SELECT 1 FROM pg_type - WHERE typname = 'eql_v2_int4_ord' AND typnamespace = 'public'::regnamespace + WHERE typname = 'int4_ord' AND typnamespace = 'eql_v3'::regnamespace ) THEN - CREATE DOMAIN public.eql_v2_int4_ord AS jsonb + CREATE DOMAIN eql_v3.int4_ord AS jsonb CHECK ( jsonb_typeof(VALUE) = 'object' AND VALUE ? 'v' diff --git a/tests/sqlx/src/matrix.rs b/tests/sqlx/src/matrix.rs index 0d277af9..8b8c0923 100644 --- a/tests/sqlx/src/matrix.rs +++ b/tests/sqlx/src/matrix.rs @@ -180,11 +180,11 @@ macro_rules! ordered_numeric_matrix { eq_ops = [(eq, "="), (neq, "<>")], ord_ops = [(lt, "<"), (lte, "<="), (gt, ">"), (gte, ">=")], index_combos = [ - (eq, Eq, "eql_v2.eq_term", "btree", [(eq, "=")]), - (eq, Eq, "eql_v2.eq_term", "hash", [(eq, "=")]), - (ord, Ord, "eql_v2.ord_term", "btree", + (eq, Eq, "eql_v3.eq_term", "btree", [(eq, "=")]), + (eq, Eq, "eql_v3.eq_term", "hash", [(eq, "=")]), + (ord, Ord, "eql_v3.ord_term", "btree", [(eq, "="), (lt, "<"), (lte, "<="), (gt, ">"), (gte, ">=")]), - (ord_ore, OrdOre, "eql_v2.ord_term", "btree", + (ord_ore, OrdOre, "eql_v3.ord_term", "btree", [(eq, "="), (lt, "<"), (lte, "<="), (gt, ">"), (gte, ">=")]), ], blocker_combos = [ @@ -246,8 +246,8 @@ macro_rules! eq_only_scalar_matrix { eq_ops = [(eq, "="), (neq, "<>")], ord_ops = [(lt, "<"), (lte, "<="), (gt, ">"), (gte, ">=")], index_combos = [ - (eq, Eq, "eql_v2.eq_term", "btree", [(eq, "=")]), - (eq, Eq, "eql_v2.eq_term", "hash", [(eq, "=")]), + (eq, Eq, "eql_v3.eq_term", "btree", [(eq, "=")]), + (eq, Eq, "eql_v3.eq_term", "hash", [(eq, "=")]), ], blocker_combos = [ (storage, Storage, [ @@ -1095,7 +1095,7 @@ macro_rules! __scalar_matrix_planner_metadata_case { JOIN pg_catalog.pg_type lt ON lt.oid = o.oprleft JOIN pg_catalog.pg_type rt ON rt.oid = o.oprright WHERE o.oprname IN ({op_list}) - AND (lt.typname = '{d}' OR rt.typname = '{d}') + AND ('{d}'::regtype = o.oprleft OR '{d}'::regtype = o.oprright) "# ); let rows: Vec<(String, String, String, bool, bool, bool, bool)> = @@ -1411,7 +1411,7 @@ macro_rules! __scalar_matrix_fixture_shape { // ============================================================================ // Ord-routes-through-ob category — ordered variants carry `c + ob` and // drop `hm`. Equality on an ord variant must therefore route through -// `eql_v2.ord_term` (the `ob` term), never HMAC. Strip `hm` from every +// `eql_v3.ord_term` (the `ob` term), never HMAC. Strip `hm` from every // fixture payload so an accidental regression to HMAC equality fails // rather than passing on the hm-carrying fixture. // ============================================================================ @@ -1474,7 +1474,7 @@ macro_rules! __scalar_matrix_ord_routes_case { anyhow::ensure!(with_hm == 0, "test rows must not carry hm"); sqlx::query(&format!( - "CREATE INDEX {index} ON {table} USING btree (eql_v2.ord_term(value))", + "CREATE INDEX {index} ON {table} USING btree (eql_v3.ord_term(value))", )).execute(&mut *tx).await?; sqlx::query(&format!("ANALYZE {table}")) .execute(&mut *tx).await?; @@ -1518,7 +1518,7 @@ macro_rules! __scalar_matrix_ord_routes_case { // VALIDITY, NOT PREFERENCE: this runs with // `enable_seqscan = off` (set above) on the ~17-row fixture, // so the planner picks the only usable alternative. A green - // assertion proves the `eql_v2.ord_term` functional btree is + // assertion proves the `eql_v3.ord_term` functional btree is // *usable* for `=` with no hm present, NOT that the planner // would *prefer* it at realistic scale. Cost-preference lives // in the `*_scale_preference_*` tests @@ -1534,7 +1534,7 @@ macro_rules! __scalar_matrix_ord_routes_case { &mut *tx, &format!("SELECT * FROM {table} WHERE value = '{lit}'::jsonb::{d}"), index, - "= must engage the eql_v2.ord_term functional btree with no hm", + "= must engage the eql_v3.ord_term functional btree with no hm", ).await?; tx.commit().await?; @@ -1786,7 +1786,7 @@ macro_rules! __scalar_matrix_order_by_case { <$scalar as $crate::scalar_domains::ScalarType>::fixture_table_name(); let sql = format!( "SELECT plaintext FROM {fixture}{where_clause} \ -ORDER BY eql_v2.ord_term(payload::{d}) {dir}", +ORDER BY eql_v3.ord_term(payload::{d}) {dir}", fixture = fixture_table, where_clause = $where_clause, d = &spec.sql_domain, dir = $direction, ); @@ -1816,7 +1816,7 @@ ORDER BY eql_v2.ord_term(payload::{d}) {dir}", // which has no NULL rows, so NULLS placement goes untested there. This arm // builds an isolated temp table mixing NULL-valued rows with the fixture rows // and pins that the NULL sort keys land at the requested end while the -// non-NULL rows stay in plaintext order. `eql_v2.ord_term` is STRICT, so a +// non-NULL rows stay in plaintext order. `eql_v3.ord_term` is STRICT, so a // NULL domain value yields a NULL sort key; a regression making it non-STRICT // would let NULL rows interleave — see the `family::mutations` negative // control for that dimension. @@ -1911,7 +1911,7 @@ SELECT NULL::{pg}, NULL::{d} FROM generate_series(1, {n})", n = NULL_ROWS, let sql = format!( "SELECT plaintext FROM {table} \ -ORDER BY eql_v2.ord_term(value) {dir} NULLS {nulls}", +ORDER BY eql_v3.ord_term(value) {dir} NULLS {nulls}", dir = $direction, nulls = $nulls, ); let actual: Vec> = @@ -2029,7 +2029,7 @@ domain by design) but succeeded", // Aggregate category — per (ord domain, op ∈ {min, max}), three tests: // extremum identity (payload of the min/max FIXTURE_VALUES row), all-NULL // returns NULL, and mixed NULL/non-NULL returns the correct extremum from -// the non-NULL subset. Pins that `eql_v2.min` / `eql_v2.max` aggregates +// the non-NULL subset. Pins that `eql_v3.min` / `eql_v3.max` aggregates // route through the domain's `<` / `>` and that the STRICT state function // correctly seeds + skips NULLs. Emits zero tests when ord_domains is // empty — eq-only umbrellas pick that up naturally. @@ -2103,13 +2103,13 @@ macro_rules! __scalar_matrix_aggregate_case { )).fetch_one(&pool).await?; let actual: String = sqlx::query_scalar(&format!( - "SELECT eql_v2.{agg}(payload::{d})::text FROM {fixture}", + "SELECT eql_v3.{agg}(payload::{d})::text FROM {fixture}", agg = $agg_fn, )).fetch_one(&pool).await?; assert_eq!( actual, expected, - "eql_v2.{}({}) must return the payload of plaintext={:?} (the fixture {})", + "eql_v3.{}({}) must return the payload of plaintext={:?} (the fixture {})", $agg_fn, d, extremum, $agg_fn, ); @@ -2120,8 +2120,8 @@ macro_rules! __scalar_matrix_aggregate_case { // where payload text matches but `ord_term` resolves to a // different value (e.g. due to payload-key reordering). let ord_terms_match: bool = sqlx::query_scalar(&format!( - "SELECT eql_v2.ord_term(eql_v2.{agg}(payload::{d})) \ - = eql_v2.ord_term($1::jsonb::{d}) \ + "SELECT eql_v3.ord_term(eql_v3.{agg}(payload::{d})) \ + = eql_v3.ord_term($1::jsonb::{d}) \ FROM {fixture}", agg = $agg_fn, )) @@ -2130,7 +2130,7 @@ macro_rules! __scalar_matrix_aggregate_case { .await?; anyhow::ensure!( ord_terms_match, - "eql_v2.ord_term(eql_v2.{}({})) must equal eql_v2.ord_term() \ + "eql_v3.ord_term(eql_v3.{}({})) must equal eql_v3.ord_term() \ for plaintext={:?}", $agg_fn, d, extremum, ); @@ -2152,12 +2152,12 @@ macro_rules! __scalar_matrix_aggregate_case { "CREATE TEMP TABLE empty_agg (value {d}) ON COMMIT DROP", )).execute(&mut *tx).await?; let result: Option = sqlx::query_scalar(&format!( - "SELECT eql_v2.{agg}(value)::text FROM empty_agg", + "SELECT eql_v3.{agg}(value)::text FROM empty_agg", agg = $agg_fn, )).fetch_one(&mut *tx).await?; anyhow::ensure!( result.is_none(), - "empty rowset to eql_v2.{} on {} must return NULL, got {:?}", + "empty rowset to eql_v3.{} on {} must return NULL, got {:?}", $agg_fn, d, result, ); tx.commit().await?; @@ -2173,7 +2173,7 @@ macro_rules! __scalar_matrix_aggregate_case { let spec = $crate::__scalar_matrix_spec!($scalar, $variant); let d = &spec.sql_domain; let sql = format!( - "SELECT eql_v2.{agg}(NULL::{d})::text FROM generate_series(1, 3)", + "SELECT eql_v3.{agg}(NULL::{d})::text FROM generate_series(1, 3)", agg = $agg_fn, ); let result: Option = sqlx::query_scalar(&sql) @@ -2181,7 +2181,7 @@ macro_rules! __scalar_matrix_aggregate_case { .await?; anyhow::ensure!( result.is_none(), - "all-NULL input to eql_v2.{} on {} must return NULL, got {:?}; SQL={}", + "all-NULL input to eql_v3.{} on {} must return NULL, got {:?}; SQL={}", $agg_fn, d, result, sql, ); Ok(()) @@ -2237,13 +2237,13 @@ macro_rules! __scalar_matrix_aggregate_case { )).fetch_one(&mut *tx).await?; let actual: Option = sqlx::query_scalar(&format!( - "SELECT eql_v2.{agg}(value)::text FROM mixed_null", + "SELECT eql_v3.{agg}(value)::text FROM mixed_null", agg = $agg_fn, )).fetch_one(&mut *tx).await?; anyhow::ensure!( actual.as_deref() == Some(expected.as_str()), - "eql_v2.{} on mixed NULL/non-NULL must return the {} non-NULL value (plaintext={:?}); want {expected:?}, got {actual:?}", + "eql_v3.{} on mixed NULL/non-NULL must return the {} non-NULL value (plaintext={:?}); want {expected:?}, got {actual:?}", $agg_fn, $agg_fn, expected_plaintext, ); @@ -2320,7 +2320,7 @@ macro_rules! __scalar_matrix_aggregate_parallel_case { // Aggregate GROUP BY category — per (ord domain, op ∈ {min, max}), build a // temp table partitioned into two groups, populate each with a known // subset of fixture rows, GROUP BY the group key, and assert that -// `eql_v2.(value)` returns the correct extremum payload per group. +// `eql_v3.(value)` returns the correct extremum payload per group. // Pins that the aggregate composes correctly under GROUP BY (state is // reset between groups, the sfunc routes through the variant's // comparator inside each partition). @@ -2430,7 +2430,7 @@ SELECT 2, payload::{d} FROM {fixture} WHERE plaintext = {lit}", )).fetch_one(&mut *tx).await?; let rows: Vec<(i32, String)> = sqlx::query_as(&format!( - "SELECT group_key, eql_v2.{agg}(value)::text \ + "SELECT group_key, eql_v3.{agg}(value)::text \ FROM group_test GROUP BY group_key ORDER BY group_key", agg = $agg_fn, )).fetch_all(&mut *tx).await?; @@ -2442,13 +2442,13 @@ FROM group_test GROUP BY group_key ORDER BY group_key", ); anyhow::ensure!( rows[0].0 == 1 && rows[0].1 == g1_expected, - "group 1 eql_v2.{}({}) must yield payload for plaintext={:?}; \ + "group 1 eql_v3.{}({}) must yield payload for plaintext={:?}; \ want ({}, {:?}), got {:?}", $agg_fn, d, group1_extremum, 1, g1_expected, rows[0], ); anyhow::ensure!( rows[1].0 == 2 && rows[1].1 == g2_expected, - "group 2 eql_v2.{}({}) must yield payload for plaintext={:?}; \ + "group 2 eql_v3.{}({}) must yield payload for plaintext={:?}; \ want ({}, {:?}), got {:?}", $agg_fn, d, group2_extremum, 2, g2_expected, rows[1], ); @@ -2462,7 +2462,7 @@ want ({}, {:?}), got {:?}", // ============================================================================ // Aggregate type-safety category — for variants that do NOT support ord -// (Storage, Eq), `eql_v2.min()` / `eql_v2.max(...)` must +// (Storage, Eq), `eql_v3.min()` / `eql_v3.max(...)` must // resolve to "function does not exist" (SQLSTATE 42883). Pins that // codegen correctly omits MIN/MAX wrappers for these variants — a // SQL-level regression test complementing the codegen unit test. @@ -2548,14 +2548,14 @@ macro_rules! __scalar_matrix_aggregate_typecheck_case { // can succeed cleanly. sqlx::query("SAVEPOINT probe").execute(&mut *tx).await?; let sql = format!( - "SELECT eql_v2.{agg}(value) FROM typecheck_table", + "SELECT eql_v3.{agg}(value) FROM typecheck_table", agg = $agg_fn, ); let err = sqlx::query_scalar::<_, String>(&sql) .fetch_one(&mut *tx) .await .expect_err(&format!( - "eql_v2.{} on non-ord variant {} must raise but succeeded", + "eql_v3.{} on non-ord variant {} must raise but succeeded", $agg_fn, d, )); // 42883 = undefined_function (no overload defined at all); @@ -2571,7 +2571,7 @@ macro_rules! __scalar_matrix_aggregate_typecheck_case { anyhow::ensure!( code.as_deref() == Some("42883") || code.as_deref() == Some("42725"), "expected SQLSTATE 42883 (undefined_function) or 42725 \ -(ambiguous_function) for eql_v2.{}({}), got {:?} (message: {})", +(ambiguous_function) for eql_v3.{}({}), got {:?} (message: {})", $agg_fn, d, code, db_err.message(), ); sqlx::query("ROLLBACK TO SAVEPOINT probe").execute(&mut *tx).await?; @@ -2594,7 +2594,7 @@ macro_rules! __scalar_matrix_aggregate_typecheck_case { // which only covered plain COUNT and only against the eql_v2_encrypted // type. Pinning per-variant DISTINCT catches the breakage class where // picking the wrong extractor would fail at runtime ("function -// eql_v2.eq_term(eql_v2_int4_ord) does not exist") — exactly the kind of +// eql_v3.eq_term(eql_v3.int4_ord) does not exist") — exactly the kind of // thing the variant-aware matrix is meant to surface mechanically. // ============================================================================ @@ -2689,8 +2689,8 @@ macro_rules! __scalar_matrix_count_case { // Dispatch on variant ident: Storage has no discriminating extractor, so // emits no DISTINCT test. The other three (Eq, Ord, OrdOre) each emit one // test that reads the extractor function name from the runtime -// `ScalarDomainSpec::extractor_fn()` accessor (Eq -> `eql_v2.eq_term`, -// Ord/OrdOre -> `eql_v2.ord_term`) and appends `(value)` at the call site. +// `ScalarDomainSpec::extractor_fn()` accessor (Eq -> `eql_v3.eq_term`, +// Ord/OrdOre -> `eql_v3.ord_term`) and appends `(value)` at the call site. #[macro_export] #[doc(hidden)] macro_rules! __scalar_matrix_count_distinct_dispatch { diff --git a/tests/sqlx/src/scalar_domains.rs b/tests/sqlx/src/scalar_domains.rs index b31c1a55..e7567584 100644 --- a/tests/sqlx/src/scalar_domains.rs +++ b/tests/sqlx/src/scalar_domains.rs @@ -143,20 +143,21 @@ impl Variant { /// or `None` if the variant carries no extractor (`Storage`). Returns /// just the function name — call sites append `(column)` themselves so /// the accessor is decoupled from any specific column-naming - /// convention. `Eq` resolves to `eql_v2.eq_term`; `Ord` and `OrdOre` - /// both resolve to `eql_v2.ord_term`. + /// convention. `Eq` resolves to `eql_v3.eq_term`; `Ord` and `OrdOre` + /// both resolve to `eql_v3.ord_term`. pub const fn extractor_fn(self) -> Option<&'static str> { match self { Variant::Storage => None, - Variant::Eq => Some("eql_v2.eq_term"), - Variant::Ord | Variant::OrdOre => Some("eql_v2.ord_term"), + Variant::Eq => Some("eql_v3.eq_term"), + Variant::Ord | Variant::OrdOre => Some("eql_v3.ord_term"), } } } /// Runtime spec built from `(T, Variant)`. The matrix macro consumes /// this; nothing here is `const` because `sql_domain` is derived via -/// `format!` from `T::PG_TYPE`. +/// `format!` from `T::PG_TYPE`. The domains live in the `eql_v3` schema, +/// so `sql_domain` is schema-qualified (e.g. `eql_v3.int4_eq`). #[derive(Debug, Clone)] pub struct ScalarDomainSpec { pub sql_domain: String, @@ -166,7 +167,7 @@ pub struct ScalarDomainSpec { impl ScalarDomainSpec { pub fn new(variant: Variant) -> Self { Self { - sql_domain: format!("eql_v2_{}{}", T::PG_TYPE, variant.suffix()), + sql_domain: format!("eql_v3.{}{}", T::PG_TYPE, variant.suffix()), variant, } } diff --git a/tests/sqlx/tests/encrypted_domain/family/inlinability.rs b/tests/sqlx/tests/encrypted_domain/family/inlinability.rs index 37347228..3cacb605 100644 --- a/tests/sqlx/tests/encrypted_domain/family/inlinability.rs +++ b/tests/sqlx/tests/encrypted_domain/family/inlinability.rs @@ -1,17 +1,18 @@ //! Global guard for the encrypted-domain inline-critical SQL surface. //! //! `tasks/pin_search_path.sql` runs after every build and pins a fixed -//! `search_path` on every `eql_v2` function — except the inline-critical -//! ones, which must stay unpinned so the planner can inline them and the -//! documented functional indexes (`eql_v2.eq_term(col)`, -//! `eql_v2.ord_term(col)`, …) engage. +//! `search_path` on every `eql_v2`/`eql_v3` function — except the +//! inline-critical ones, which must stay unpinned so the planner can +//! inline them and the documented functional indexes (`eql_v3.eq_term(col)`, +//! `eql_v3.ord_term(col)`, …) engage. //! //! The encrypted-domain family is skipped by a structural rule anchored //! on the *identity predicate*: a `LANGUAGE sql`, `IMMUTABLE` function -//! taking at least one argument typed as a jsonb-backed DOMAIN in -//! `public` named `eql_v2_*`. The identity predicate is -//! proconfig-independent — it describes what a function intrinsically -//! IS, not whether it has been pinned. +//! taking at least one argument typed as a jsonb-backed DOMAIN of the +//! encrypted-domain families — a domain in the `eql_v3` schema (e.g. +//! `eql_v3.int4_eq`) or the legacy `public.eql_v2_*` form. The identity +//! predicate is proconfig-independent — it describes what a function +//! intrinsically IS, not whether it has been pinned. //! //! This test is the global net for that rule. It uses the identity //! predicate VERBATIM and appends one offender filter: @@ -35,11 +36,12 @@ use sqlx::PgPool; async fn no_encrypted_domain_inline_critical_function_is_pinned(pool: PgPool) -> Result<()> { // The identity predicate is shared verbatim with the structural skip // clause in tasks/pin_search_path.sql: LANGUAGE sql, IMMUTABLE, and - // taking at least one argument typed as a `public.eql_v2_*` domain - // over jsonb. It is proconfig-independent. The ONLY addition here is - // the offender filter `p.proconfig IS NOT NULL` — a function that - // matches the identity predicate but DID get pinned. That set must be - // empty. + // taking at least one argument typed as an encrypted-domain-family + // domain over jsonb (an `eql_v3.*` domain or the legacy + // `public.eql_v2_*` form). It is proconfig-independent. The ONLY + // addition here is the offender filter `p.proconfig IS NOT NULL` — a + // function that matches the identity predicate but DID get pinned. + // That set must be empty. let offenders: Vec<(String, String)> = sqlx::query_as( r#" SELECT p.oid::regprocedure::text AS signature, @@ -47,7 +49,7 @@ async fn no_encrypted_domain_inline_critical_function_is_pinned(pool: PgPool) -> FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace JOIN pg_catalog.pg_language l ON l.oid = p.prolang - WHERE n.nspname = 'eql_v2' + WHERE n.nspname IN ('eql_v2', 'eql_v3') AND l.lanname = 'sql' AND p.provolatile = 'i' AND p.proconfig IS NOT NULL @@ -58,9 +60,11 @@ async fn no_encrypted_domain_inline_critical_function_is_pinned(pool: PgPool) -> JOIN pg_catalog.pg_namespace dn ON dn.oid = dt.typnamespace JOIN pg_catalog.pg_type bt ON bt.oid = dt.typbasetype WHERE dt.typtype = 'd' - AND dn.nspname = 'public' - AND dt.typname LIKE 'eql_v2\_%' AND bt.typname = 'jsonb' + AND ( + dn.nspname = 'eql_v3' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) ) ORDER BY signature "#, @@ -88,17 +92,18 @@ async fn every_inline_critical_eligible_domain_has_inline_critical_functions( pool: PgPool, ) -> Result<()> { // Stronger than a bare `count > 0`: if a future change accidentally - // narrows the structural predicate (e.g. hard-codes `eql_v2_int4_%`), - // a `count > 0` assertion would still pass while int8/bool/date + // narrows the structural predicate (e.g. hard-codes `int4_%`), a + // `count > 0` assertion would still pass while int8/bool/date // domains silently lose inline-critical coverage. Instead, assert - // that EVERY inline-critical-eligible domain (any `public.eql_v2_*` - // domain over jsonb that carries a capability suffix — `_eq`, `_ord`, - // `_ord_ore`) appears as an argument type of at least one - // inline-critical function. + // that EVERY inline-critical-eligible domain (any encrypted-domain + // family domain over jsonb — `eql_v3.*` or legacy `public.eql_v2_*` — + // that carries a capability suffix — `_eq`, `_ord`, `_ord_ore`) + // appears as an argument type of at least one inline-critical + // function. // - // Storage-only variants (the bare `eql_v2_` domain, with no - // capability suffix) intentionally have NO inline-critical surface - // and are excluded from the eligibility set. + // Storage-only variants (the bare `eql_v3.` / `eql_v2_` domain, + // with no capability suffix) intentionally have NO inline-critical + // surface and are excluded from the eligibility set. let unbound: Vec = sqlx::query_scalar( r#" SELECT dt.typname @@ -106,9 +111,11 @@ async fn every_inline_critical_eligible_domain_has_inline_critical_functions( JOIN pg_catalog.pg_namespace dn ON dn.oid = dt.typnamespace JOIN pg_catalog.pg_type bt ON bt.oid = dt.typbasetype WHERE dt.typtype = 'd' - AND dn.nspname = 'public' AND bt.typname = 'jsonb' - AND dt.typname LIKE 'eql_v2\_%' + AND ( + dn.nspname = 'eql_v3' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) AND ( dt.typname LIKE '%\_eq' OR dt.typname LIKE '%\_ord' @@ -119,7 +126,7 @@ async fn every_inline_critical_eligible_domain_has_inline_critical_functions( FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace JOIN pg_catalog.pg_language l ON l.oid = p.prolang - WHERE n.nspname = 'eql_v2' + WHERE n.nspname IN ('eql_v2', 'eql_v3') AND l.lanname = 'sql' AND p.provolatile = 'i' AND dt.oid = ANY(p.proargtypes::oid[]) @@ -158,7 +165,7 @@ async fn encrypted_domain_blockers_are_plpgsql_and_non_strict(pool: PgPool) -> R FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace JOIN pg_catalog.pg_language l ON l.oid = p.prolang - WHERE n.nspname = 'eql_v2' + WHERE n.nspname IN ('eql_v2', 'eql_v3') AND (p.prosrc LIKE '%encrypted_domain_unsupported_bool%' OR p.prosrc LIKE '%is not supported for%') AND EXISTS ( @@ -168,9 +175,11 @@ async fn encrypted_domain_blockers_are_plpgsql_and_non_strict(pool: PgPool) -> R JOIN pg_catalog.pg_namespace dn ON dn.oid = dt.typnamespace JOIN pg_catalog.pg_type bt ON bt.oid = dt.typbasetype WHERE dt.typtype = 'd' - AND dn.nspname = 'public' - AND dt.typname LIKE 'eql_v2\_%' AND bt.typname = 'jsonb' + AND ( + dn.nspname = 'eql_v3' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) ) AND (l.lanname <> 'plpgsql' OR p.proisstrict) ORDER BY signature @@ -187,10 +196,10 @@ async fn encrypted_domain_blockers_are_plpgsql_and_non_strict(pool: PgPool) -> R Ok(()) } -/// No `eql_v2_*` domain may be derived from another `eql_v2_*` domain — -/// operators resolve against the ultimate base type, so a derived domain -/// inherits jsonb's operator surface and not the base domain's blockers. -/// All family domains must be defined directly over jsonb. +/// No encrypted-domain family domain may be derived from another family +/// domain — operators resolve against the ultimate base type, so a derived +/// domain inherits jsonb's operator surface and not the base domain's +/// blockers. All family domains must be defined directly over jsonb. #[sqlx::test] async fn no_eql_v2_domain_is_derived_from_another_eql_v2_domain(pool: PgPool) -> Result<()> { let offenders: Vec<(String, String)> = sqlx::query_as( @@ -202,10 +211,15 @@ async fn no_eql_v2_domain_is_derived_from_another_eql_v2_domain(pool: PgPool) -> JOIN pg_catalog.pg_type bt ON bt.oid = dt.typbasetype JOIN pg_catalog.pg_namespace bn ON bn.oid = bt.typnamespace WHERE dt.typtype = 'd' - AND dn.nspname = 'public' - AND dt.typname LIKE 'eql_v2\_%' + AND ( + dn.nspname = 'eql_v3' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) AND bt.typtype = 'd' - AND bt.typname LIKE 'eql_v2\_%' + AND ( + bn.nspname = 'eql_v3' + OR (bn.nspname = 'public' AND bt.typname LIKE 'eql_v2\_%') + ) ORDER BY derived "#, ) @@ -214,16 +228,16 @@ async fn no_eql_v2_domain_is_derived_from_another_eql_v2_domain(pool: PgPool) -> assert!( offenders.is_empty(), - "eql_v2_* domains must be defined directly over jsonb, not derived \ - from another eql_v2_* domain. Offenders (derived, base): {offenders:#?}" + "encrypted-domain family domains must be defined directly over jsonb, \ + not derived from another family domain. Offenders (derived, base): {offenders:#?}" ); Ok(()) } -/// No operator class may be declared `FOR TYPE` on an `eql_v2_*` domain. -/// Opclasses on domains bypass the operator-resolution that storage -/// blockers depend on. The recommended index pattern is a functional -/// index on the extractor (e.g. `eql_v2.eq_term(col)`). +/// No operator class may be declared `FOR TYPE` on an encrypted-domain +/// family domain. Opclasses on domains bypass the operator-resolution that +/// storage blockers depend on. The recommended index pattern is a functional +/// index on the extractor (e.g. `eql_v3.eq_term(col)`). #[sqlx::test] async fn no_opclass_targets_eql_v2_domain(pool: PgPool) -> Result<()> { let offenders: Vec<(String, String)> = sqlx::query_as( @@ -235,8 +249,10 @@ async fn no_opclass_targets_eql_v2_domain(pool: PgPool) -> Result<()> { JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace JOIN pg_catalog.pg_namespace cn ON cn.oid = oc.opcnamespace WHERE t.typtype = 'd' - AND tn.nspname = 'public' - AND t.typname LIKE 'eql_v2\_%' + AND ( + tn.nspname = 'eql_v3' + OR (tn.nspname = 'public' AND t.typname LIKE 'eql_v2\_%') + ) ORDER BY opclass "#, ) @@ -245,8 +261,8 @@ async fn no_opclass_targets_eql_v2_domain(pool: PgPool) -> Result<()> { assert!( offenders.is_empty(), - "no operator class may target an eql_v2_* domain — use a functional \ - index on the extractor instead. Offenders (opclass, for_type): {offenders:#?}" + "no operator class may target an encrypted-domain family domain — use a \ + functional index on the extractor instead. Offenders (opclass, for_type): {offenders:#?}" ); Ok(()) } diff --git a/tests/sqlx/tests/encrypted_domain/family/jsonb_operator_surface.rs b/tests/sqlx/tests/encrypted_domain/family/jsonb_operator_surface.rs index 1a2fb95e..b10a848c 100644 --- a/tests/sqlx/tests/encrypted_domain/family/jsonb_operator_surface.rs +++ b/tests/sqlx/tests/encrypted_domain/family/jsonb_operator_surface.rs @@ -1,6 +1,6 @@ //! Structural guard for the blocked native-jsonb operator enumeration. //! -//! The storage-only domains (`eql_v2_int4`, future scalars) promise that +//! The storage-only domains (`eql_v3.int4`, future scalars) promise that //! *every* native jsonb operator is blocked, so an encrypted column can never //! fall through to plaintext-jsonb semantics. That promise rests on three //! hand-maintained lists in `tasks/codegen/operator_surface.py` diff --git a/tests/sqlx/tests/encrypted_domain/family/mutations.rs b/tests/sqlx/tests/encrypted_domain/family/mutations.rs index 2745e1ae..7be20853 100644 --- a/tests/sqlx/tests/encrypted_domain/family/mutations.rs +++ b/tests/sqlx/tests/encrypted_domain/family/mutations.rs @@ -36,23 +36,23 @@ async fn mutate(pool: &PgPool, ddl: &str) -> Result<()> { // catch a blocker that silently stopped raising. #[sqlx::test] async fn disabling_storage_eq_blocker_flips_blocker_arm(pool: PgPool) -> Result<()> { - let sql = "SELECT $1::jsonb::eql_v2_int4 = $2::jsonb::eql_v2_int4"; + let sql = "SELECT $1::jsonb::eql_v3.int4 = $2::jsonb::eql_v3.int4"; // Baseline: the storage `=` blocker raises. assert_raises( &pool, sql, &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], - &blocker_msg("eql_v2_int4", "="), + &blocker_msg("eql_v3.int4", "="), ) .await?; // Mutation: replace the plpgsql blocker with an inlinable SQL body that // returns true. CREATE OR REPLACE keeps the oid, so the `=` operator on - // (eql_v2_int4, eql_v2_int4) now resolves to this no-raise body. + // (eql_v3.int4, eql_v3.int4) now resolves to this no-raise body. mutate( &pool, - "CREATE OR REPLACE FUNCTION eql_v2.eq(a eql_v2_int4, b eql_v2_int4) \ + "CREATE OR REPLACE FUNCTION eql_v3.eq(a eql_v3.int4, b eql_v3.int4) \ RETURNS boolean LANGUAGE sql IMMUTABLE PARALLEL SAFE AS $$ SELECT true $$", ) .await?; @@ -84,8 +84,8 @@ async fn unsetting_restrict_flips_planner_metadata_arm(pool: PgPool) -> Result<( JOIN pg_catalog.pg_type lt ON lt.oid = o.oprleft JOIN pg_catalog.pg_type rt ON rt.oid = o.oprright WHERE o.oprname = '=' - AND lt.typname = 'eql_v2_int4_ord' - AND rt.typname = 'eql_v2_int4_ord' + AND lt.typname = 'int4_ord' + AND rt.typname = 'int4_ord' "#, ) .fetch_one(pool) @@ -96,14 +96,14 @@ async fn unsetting_restrict_flips_planner_metadata_arm(pool: PgPool) -> Result<( // Baseline: `=` on (ord, ord) declares a RESTRICT estimator. ensure!( restrict_present(&pool).await?, - "baseline: `=` on eql_v2_int4_ord must declare a RESTRICT estimator" + "baseline: `=` on eql_v3.int4_ord must declare a RESTRICT estimator" ); // Mutation: unset RESTRICT. DROP OPERATOR would hit COMMUTATOR/NEGATOR // dependency links; ALTER ... SET (RESTRICT = NONE) avoids that. mutate( &pool, - "ALTER OPERATOR = (eql_v2_int4_ord, eql_v2_int4_ord) SET (RESTRICT = NONE)", + "ALTER OPERATOR = (eql_v3.int4_ord, eql_v3.int4_ord) SET (RESTRICT = NONE)", ) .await?; @@ -130,7 +130,7 @@ async fn rerouting_ord_eq_through_hm_flips_ord_routes_arm(pool: PgPool) -> Resul .await?; let count_sql = "SELECT count(*) FROM fixtures.eql_v2_int4 \ - WHERE (payload - 'hm')::eql_v2_int4_ord = $1::jsonb::eql_v2_int4_ord"; + WHERE (payload - 'hm')::eql_v3.int4_ord = $1::jsonb::eql_v3.int4_ord"; // Baseline: with `hm` stripped, `=` still matches the pivot via `ord_term` // (the `ob` term survives) — exactly one row. @@ -148,7 +148,7 @@ async fn rerouting_ord_eq_through_hm_flips_ord_routes_arm(pool: PgPool) -> Resul // nothing. mutate( &pool, - "CREATE OR REPLACE FUNCTION eql_v2.eq(a eql_v2_int4_ord, b eql_v2_int4_ord) \ + "CREATE OR REPLACE FUNCTION eql_v3.eq(a eql_v3.int4_ord, b eql_v3.int4_ord) \ RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE \ AS $$ SELECT eql_v2.hmac_256(a::jsonb) = eql_v2.hmac_256(b::jsonb) $$", ) @@ -171,7 +171,7 @@ async fn rerouting_ord_eq_through_hm_flips_ord_routes_arm(pool: PgPool) -> Resul // the `supported_null` arm has teeth. #[sqlx::test] async fn dropping_strict_on_eq_flips_supported_null_arm(pool: PgPool) -> Result<()> { - let sql = "SELECT $1::jsonb::eql_v2_int4_eq = $2::jsonb::eql_v2_int4_eq"; + let sql = "SELECT $1::jsonb::eql_v3.int4_eq = $2::jsonb::eql_v3.int4_eq"; // Baseline: STRICT `=` propagates NULL when one side is NULL. assert_null(&pool, sql, &[Some(PLACEHOLDER_PAYLOAD), None]).await?; @@ -180,7 +180,7 @@ async fn dropping_strict_on_eq_flips_supported_null_arm(pool: PgPool) -> Result< // keeps the oid; the operator now ignores NULL semantics. mutate( &pool, - "CREATE OR REPLACE FUNCTION eql_v2.eq(a eql_v2_int4_eq, b eql_v2_int4_eq) \ + "CREATE OR REPLACE FUNCTION eql_v3.eq(a eql_v3.int4_eq, b eql_v3.int4_eq) \ RETURNS boolean LANGUAGE sql IMMUTABLE PARALLEL SAFE AS $$ SELECT true $$", ) .await?; @@ -205,9 +205,9 @@ async fn dropping_strict_on_eq_flips_supported_null_arm(pool: PgPool) -> Result< // sort key. Blocking `<` alone must not disturb ORDER BY. #[sqlx::test(fixtures(path = "../../../fixtures", scripts("eql_v2_int4")))] async fn blocking_lt_flips_lt_arm_but_not_order_by(pool: PgPool) -> Result<()> { - let lt_sql = "SELECT $1::jsonb::eql_v2_int4_ord < $2::jsonb::eql_v2_int4_ord"; + let lt_sql = "SELECT $1::jsonb::eql_v3.int4_ord < $2::jsonb::eql_v3.int4_ord"; let order_by_sql = "SELECT plaintext FROM fixtures.eql_v2_int4 \ - ORDER BY eql_v2.ord_term(payload::eql_v2_int4_ord) ASC"; + ORDER BY eql_v3.ord_term(payload::eql_v3.int4_ord) ASC"; let mut ascending: Vec = ::FIXTURE_VALUES.to_vec(); ascending.sort(); @@ -228,13 +228,13 @@ async fn blocking_lt_flips_lt_arm_but_not_order_by(pool: PgPool) -> Result<()> { "baseline: ORDER BY ord_term ASC must be plaintext-sorted" ); - // Mutation: turn `eql_v2.lt(_ord, _ord)` into a blocker. Must be + // Mutation: turn `eql_v3.lt(_ord, _ord)` into a blocker. Must be // LANGUAGE plpgsql and non-STRICT so the RAISE always fires. mutate( &pool, - "CREATE OR REPLACE FUNCTION eql_v2.lt(a eql_v2_int4_ord, b eql_v2_int4_ord) \ + "CREATE OR REPLACE FUNCTION eql_v3.lt(a eql_v3.int4_ord, b eql_v3.int4_ord) \ RETURNS boolean LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE \ - AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4_ord', '<'); END; $$", + AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '<'); END; $$", ) .await?; @@ -243,7 +243,7 @@ async fn blocking_lt_flips_lt_arm_but_not_order_by(pool: PgPool) -> Result<()> { &pool, lt_sql, &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], - &blocker_msg("eql_v2_int4_ord", "<"), + &blocker_msg("eql_v3.int4_ord", "<"), ) .await?; @@ -283,7 +283,7 @@ async fn rerouting_eq_eq_through_ob_flips_eq_arm(pool: PgPool) -> Result<()> { .await?; let count_sql = "SELECT count(*) FROM fixtures.eql_v2_int4 \ - WHERE (payload - 'ob')::eql_v2_int4_eq = $1::jsonb::eql_v2_int4_eq"; + WHERE (payload - 'ob')::eql_v3.int4_eq = $1::jsonb::eql_v3.int4_eq"; // Baseline: with `ob` stripped, `=` still matches the pivot via `eq_term` // (the `hm` term survives) — exactly one row. @@ -300,7 +300,7 @@ async fn rerouting_eq_eq_through_ob_flips_eq_arm(pool: PgPool) -> Result<()> { // `eql_v2.ore_block_u64_8_256(jsonb)` raises rather than matching. mutate( &pool, - "CREATE OR REPLACE FUNCTION eql_v2.eq(a eql_v2_int4_eq, b eql_v2_int4_eq) \ + "CREATE OR REPLACE FUNCTION eql_v3.eq(a eql_v3.int4_eq, b eql_v3.int4_eq) \ RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE \ AS $$ SELECT eql_v2.ore_block_u64_8_256(a::jsonb) = eql_v2.ore_block_u64_8_256(b::jsonb) $$", ) @@ -334,7 +334,7 @@ async fn rerouting_eq_eq_through_ob_flips_eq_arm(pool: PgPool) -> Result<()> { #[sqlx::test(fixtures(path = "../../../fixtures", scripts("eql_v2_int4")))] async fn collapsing_ord_term_flips_order_by_arm(pool: PgPool) -> Result<()> { let order_by_desc = "SELECT plaintext FROM fixtures.eql_v2_int4 \ - ORDER BY eql_v2.ord_term(payload::eql_v2_int4_ord) DESC"; + ORDER BY eql_v3.ord_term(payload::eql_v3.int4_ord) DESC"; let mut descending: Vec = ::FIXTURE_VALUES.to_vec(); descending.sort(); @@ -353,7 +353,7 @@ async fn collapsing_ord_term_flips_order_by_arm(pool: PgPool) -> Result<()> { // function body. let const_payload = fetch_fixture_payload::(&pool, 0).await?; let ddl = format!( - "CREATE OR REPLACE FUNCTION eql_v2.ord_term(a eql_v2_int4_ord) \ + "CREATE OR REPLACE FUNCTION eql_v3.ord_term(a eql_v3.int4_ord) \ RETURNS eql_v2.ore_block_u64_8_256 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE \ AS $mutbody$ SELECT eql_v2.ore_block_u64_8_256('{esc}'::jsonb) $mutbody$", esc = const_payload.replace('\'', "''"), @@ -384,11 +384,11 @@ async fn making_ord_term_non_strict_flips_order_by_nulls_arm(pool: PgPool) -> Re const NULL_ROWS: usize = 3; let order_by = format!( "SELECT plaintext FROM ( \ - SELECT plaintext, payload::eql_v2_int4_ord AS value FROM fixtures.eql_v2_int4 \ + SELECT plaintext, payload::eql_v3.int4_ord AS value FROM fixtures.eql_v2_int4 \ UNION ALL \ - SELECT NULL::int4, NULL::eql_v2_int4_ord FROM generate_series(1, {NULL_ROWS}) \ + SELECT NULL::int4, NULL::eql_v3.int4_ord FROM generate_series(1, {NULL_ROWS}) \ ) s \ - ORDER BY eql_v2.ord_term(value) ASC NULLS LAST" + ORDER BY eql_v3.ord_term(value) ASC NULLS LAST" ); let tail_all_none = @@ -408,10 +408,10 @@ async fn making_ord_term_non_strict_flips_order_by_nulls_arm(pool: PgPool) -> Re // unchanged. Unique dollar-quote tag guards the embedded jsonb literal. let const_payload = fetch_fixture_payload::(&pool, 0).await?; let ddl = format!( - "CREATE OR REPLACE FUNCTION eql_v2.ord_term(a eql_v2_int4_ord) \ + "CREATE OR REPLACE FUNCTION eql_v3.ord_term(a eql_v3.int4_ord) \ RETURNS eql_v2.ore_block_u64_8_256 LANGUAGE sql IMMUTABLE PARALLEL SAFE \ AS $mutbody$ SELECT eql_v2.ore_block_u64_8_256(\ - coalesce(a, '{esc}'::jsonb::eql_v2_int4_ord)::jsonb) $mutbody$", + coalesce(a, '{esc}'::jsonb::eql_v3.int4_ord)::jsonb) $mutbody$", esc = const_payload.replace('\'', "''"), ); mutate(&pool, &ddl).await?; diff --git a/tests/sqlx/tests/encrypted_domain/family/support.rs b/tests/sqlx/tests/encrypted_domain/family/support.rs index b062b9ce..08b19c04 100644 --- a/tests/sqlx/tests/encrypted_domain/family/support.rs +++ b/tests/sqlx/tests/encrypted_domain/family/support.rs @@ -13,29 +13,29 @@ use sqlx::PgPool; #[test] fn variant_derives_consistent_sql_domain_and_capabilities() { let storage = ScalarDomainSpec::new::(Variant::Storage); - assert_eq!(storage.sql_domain, "eql_v2_int4"); + assert_eq!(storage.sql_domain, "eql_v3.int4"); assert!(!storage.supports_eq()); assert!(!storage.supports_ord()); assert_eq!(storage.extractor_fn(), None); assert_eq!(Variant::Storage.required_term(), None); let eq = ScalarDomainSpec::new::(Variant::Eq); - assert_eq!(eq.sql_domain, "eql_v2_int4_eq"); + assert_eq!(eq.sql_domain, "eql_v3.int4_eq"); assert!(eq.supports_eq()); assert!(!eq.supports_ord()); - assert_eq!(eq.extractor_fn(), Some("eql_v2.eq_term")); + assert_eq!(eq.extractor_fn(), Some("eql_v3.eq_term")); assert_eq!(Variant::Eq.required_term(), Some("hm")); let ord = ScalarDomainSpec::new::(Variant::Ord); - assert_eq!(ord.sql_domain, "eql_v2_int4_ord"); + assert_eq!(ord.sql_domain, "eql_v3.int4_ord"); assert!(ord.supports_ord()); - assert_eq!(ord.extractor_fn(), Some("eql_v2.ord_term")); + assert_eq!(ord.extractor_fn(), Some("eql_v3.ord_term")); assert_eq!(Variant::Ord.required_term(), Some("ob")); let ord_ore = ScalarDomainSpec::new::(Variant::OrdOre); - assert_eq!(ord_ore.sql_domain, "eql_v2_int4_ord_ore"); + assert_eq!(ord_ore.sql_domain, "eql_v3.int4_ord_ore"); assert!(ord_ore.supports_ord()); - assert_eq!(ord_ore.extractor_fn(), Some("eql_v2.ord_term")); + assert_eq!(ord_ore.extractor_fn(), Some("eql_v3.ord_term")); } #[test] @@ -103,8 +103,8 @@ async fn fetch_fixture_payload_returns_keyed_row(pool: PgPool) -> Result<()> { #[sqlx::test(fixtures(path = "../../../fixtures", scripts("eql_v2_int4")))] async fn assert_scalar_plaintexts_reports_sql_context(pool: PgPool) -> Result<()> { let lit = sql_string_literal(&fetch_fixture_payload::(&pool, 42).await?); - let predicate = format!("payload::eql_v2_int4_ord_ore = {lit}::jsonb::eql_v2_int4_ord_ore"); - assert_scalar_plaintexts::(&pool, "eql_v2_int4_ord_ore", "=", &predicate, &[42]).await?; + let predicate = format!("payload::eql_v3.int4_ord_ore = {lit}::jsonb::eql_v3.int4_ord_ore"); + assert_scalar_plaintexts::(&pool, "eql_v3.int4_ord_ore", "=", &predicate, &[42]).await?; Ok(()) } @@ -134,10 +134,10 @@ async fn placeholder_payload_satisfies_every_variant_check(pool: PgPool) -> Resu #[sqlx::test] async fn assert_raises_two_bind_blocker(pool: PgPool) -> Result<()> { - let msg = blocker_msg("eql_v2_int4", "="); + let msg = blocker_msg("eql_v3.int4", "="); assert_raises( &pool, - "SELECT $1::jsonb::eql_v2_int4 = $2::jsonb::eql_v2_int4", + "SELECT $1::jsonb::eql_v3.int4 = $2::jsonb::eql_v3.int4", &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], &msg, ) @@ -146,10 +146,10 @@ async fn assert_raises_two_bind_blocker(pool: PgPool) -> Result<()> { #[sqlx::test] async fn assert_raises_one_bind_path_blocker(pool: PgPool) -> Result<()> { - let msg = blocker_msg("eql_v2_int4", "->"); + let msg = blocker_msg("eql_v3.int4", "->"); assert_raises( &pool, - "SELECT $1::jsonb::eql_v2_int4 -> 'field'::text", + "SELECT $1::jsonb::eql_v3.int4 -> 'field'::text", &[Some(PLACEHOLDER_PAYLOAD)], &msg, ) @@ -162,7 +162,7 @@ async fn assert_raises_native_operator_absent(pool: PgPool) -> Result<()> { // "operator does not exist", not an EQL blocker message. assert_raises( &pool, - "SELECT $1::jsonb::eql_v2_int4 ~~ $2::jsonb::eql_v2_int4", + "SELECT $1::jsonb::eql_v3.int4 ~~ $2::jsonb::eql_v3.int4", &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], "operator does not exist", ) @@ -173,79 +173,79 @@ async fn assert_raises_native_operator_absent(pool: PgPool) -> Result<()> { async fn omitted_native_jsonb_operators_raise_eql_blockers(pool: PgPool) -> Result<()> { let cases: &[(&str, &[Option<&str>], &str)] = &[ ( - "SELECT $1::jsonb::eql_v2_int4 ? 'c'::text", + "SELECT $1::jsonb::eql_v3.int4 ? 'c'::text", &[Some(PLACEHOLDER_PAYLOAD)], "?", ), ( - "SELECT $1::jsonb::eql_v2_int4 ?| ARRAY['c']", + "SELECT $1::jsonb::eql_v3.int4 ?| ARRAY['c']", &[Some(PLACEHOLDER_PAYLOAD)], "?|", ), ( - "SELECT $1::jsonb::eql_v2_int4 ?& ARRAY['c']", + "SELECT $1::jsonb::eql_v3.int4 ?& ARRAY['c']", &[Some(PLACEHOLDER_PAYLOAD)], "?&", ), ( - "SELECT $1::jsonb::eql_v2_int4 #> ARRAY['i']", + "SELECT $1::jsonb::eql_v3.int4 #> ARRAY['i']", &[Some(PLACEHOLDER_PAYLOAD)], "#>", ), ( - "SELECT $1::jsonb::eql_v2_int4 #>> ARRAY['i', 'c']", + "SELECT $1::jsonb::eql_v3.int4 #>> ARRAY['i', 'c']", &[Some(PLACEHOLDER_PAYLOAD)], "#>>", ), ( - "SELECT $1::jsonb::eql_v2_int4 @? '$.c'::jsonpath", + "SELECT $1::jsonb::eql_v3.int4 @? '$.c'::jsonpath", &[Some(PLACEHOLDER_PAYLOAD)], "@?", ), ( - "SELECT $1::jsonb::eql_v2_int4 @@ '$.c == \"placeholder\"'::jsonpath", + "SELECT $1::jsonb::eql_v3.int4 @@ '$.c == \"placeholder\"'::jsonpath", &[Some(PLACEHOLDER_PAYLOAD)], "@@", ), ( - "SELECT $1::jsonb::eql_v2_int4 - 'c'::text", + "SELECT $1::jsonb::eql_v3.int4 - 'c'::text", &[Some(PLACEHOLDER_PAYLOAD)], "-", ), ( - "SELECT $1::jsonb::eql_v2_int4 - 0", + "SELECT $1::jsonb::eql_v3.int4 - 0", &[Some(PLACEHOLDER_PAYLOAD)], "-", ), ( - "SELECT $1::jsonb::eql_v2_int4 - ARRAY['c']", + "SELECT $1::jsonb::eql_v3.int4 - ARRAY['c']", &[Some(PLACEHOLDER_PAYLOAD)], "-", ), ( - "SELECT $1::jsonb::eql_v2_int4 #- ARRAY['i']", + "SELECT $1::jsonb::eql_v3.int4 #- ARRAY['i']", &[Some(PLACEHOLDER_PAYLOAD)], "#-", ), ( - "SELECT $1::jsonb::eql_v2_int4 || $2::jsonb", + "SELECT $1::jsonb::eql_v3.int4 || $2::jsonb", &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], "||", ), ( - "SELECT $1::jsonb || $2::jsonb::eql_v2_int4", + "SELECT $1::jsonb || $2::jsonb::eql_v3.int4", &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], "||", ), ( - "SELECT $1::jsonb::eql_v2_int4 || $2::jsonb::eql_v2_int4", + "SELECT $1::jsonb::eql_v3.int4 || $2::jsonb::eql_v3.int4", &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], "||", ), ]; for (sql, binds, op) in cases { - assert_raises(&pool, sql, binds, &blocker_msg("eql_v2_int4", op)).await?; + assert_raises(&pool, sql, binds, &blocker_msg("eql_v3.int4", op)).await?; } Ok(()) } @@ -253,10 +253,10 @@ async fn omitted_native_jsonb_operators_raise_eql_blockers(pool: PgPool) -> Resu #[sqlx::test] async fn assert_raises_engages_on_all_null(pool: PgPool) -> Result<()> { // Non-STRICT blocker proof — must raise even with NULL on both sides. - let msg = blocker_msg("eql_v2_int4", "="); + let msg = blocker_msg("eql_v3.int4", "="); assert_raises( &pool, - "SELECT $1::jsonb::eql_v2_int4 = $2::jsonb::eql_v2_int4", + "SELECT $1::jsonb::eql_v3.int4 = $2::jsonb::eql_v3.int4", &[None, None], &msg, ) @@ -268,7 +268,7 @@ async fn assert_null_propagates_through_supported_op(pool: PgPool) -> Result<()> // STRICT supported op with one NULL operand yields NULL. assert_null( &pool, - "SELECT $1::jsonb::eql_v2_int4_eq = $2::jsonb::eql_v2_int4_eq", + "SELECT $1::jsonb::eql_v3.int4_eq = $2::jsonb::eql_v3.int4_eq", &[Some(PLACEHOLDER_PAYLOAD), None], ) .await @@ -286,7 +286,7 @@ async fn neq_propagates_null_under_three_valued_logic(pool: PgPool) -> Result<() ] { assert_null( &pool, - "SELECT $1::jsonb::eql_v2_int4_eq <> $2::jsonb::eql_v2_int4_eq", + "SELECT $1::jsonb::eql_v3.int4_eq <> $2::jsonb::eql_v3.int4_eq", binds, ) .await?; @@ -297,7 +297,7 @@ async fn neq_propagates_null_under_three_valued_logic(pool: PgPool) -> Result<() #[sqlx::test] async fn no_cross_variant_equality_operator_is_declared(pool: PgPool) -> Result<()> { // The family deliberately does NOT define operators that mix two - // different capability variants — `eql_v2_int4_eq = eql_v2_int4_ord` + // different capability variants — `eql_v3.int4_eq = eql_v3.int4_ord` // would resolve against jsonb (the ultimate base type) and silently // bypass the per-variant blockers. If someone accidentally adds such // an operator, this test fails. @@ -311,9 +311,11 @@ async fn no_cross_variant_equality_operator_is_declared(pool: PgPool) -> Result< o.oprname, lt.typname, rt.typname) FROM pg_catalog.pg_operator o JOIN pg_catalog.pg_type lt ON lt.oid = o.oprleft + JOIN pg_catalog.pg_namespace ln ON ln.oid = lt.typnamespace JOIN pg_catalog.pg_type rt ON rt.oid = o.oprright - WHERE lt.typname LIKE 'eql_v2\_%' - AND rt.typname LIKE 'eql_v2\_%' + JOIN pg_catalog.pg_namespace rn ON rn.oid = rt.typnamespace + WHERE ln.nspname = 'eql_v3' + AND rn.nspname = 'eql_v3' AND lt.typname <> rt.typname ORDER BY 1 "#, @@ -323,7 +325,7 @@ async fn no_cross_variant_equality_operator_is_declared(pool: PgPool) -> Result< assert!( cross_variant.is_empty(), - "no operator should mix two different eql_v2_* domain types, but found: {cross_variant:#?}" + "no operator should mix two different eql_v3 domain types, but found: {cross_variant:#?}" ); Ok(()) } diff --git a/tests/sqlx/tests/lint_tests.rs b/tests/sqlx/tests/lint_tests.rs index f9194b82..0387e396 100644 --- a/tests/sqlx/tests/lint_tests.rs +++ b/tests/sqlx/tests/lint_tests.rs @@ -96,15 +96,15 @@ async fn lint_categories_are_well_known(pool: PgPool) -> Result<()> { /// planner can fold or elide the call when the result is provably unused /// (a dead CASE branch, a folded predicate), silently bypassing the RAISE /// and re-enabling the operator. See CLAUDE.md footguns. This test plants -/// a fake LANGUAGE sql blocker on `eql_v2_int4` and asserts the lint +/// a fake LANGUAGE sql blocker on `eql_v3.int4` and asserts the lint /// surfaces it under category `blocker_language`. #[sqlx::test] async fn lint_flags_blocker_in_language_sql(pool: PgPool) -> Result<()> { sqlx::query( r#" - CREATE FUNCTION eql_v2.test_bad_blocker_sql(a eql_v2_int4, b eql_v2_int4) + CREATE FUNCTION eql_v2.test_bad_blocker_sql(a eql_v3.int4, b eql_v3.int4) RETURNS boolean LANGUAGE sql IMMUTABLE - AS $$ SELECT eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '=') $$; + AS $$ SELECT eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '=') $$; "#, ) .execute(&pool) @@ -134,15 +134,15 @@ async fn lint_flags_blocker_in_language_sql(pool: PgPool) -> Result<()> { /// A blocker marked `STRICT` lets PostgreSQL skip the body and return NULL /// on a NULL argument — silently bypassing the "operator not supported" /// RAISE. See CLAUDE.md footguns. This test plants a fake STRICT plpgsql -/// blocker on `eql_v2_int4` and asserts the lint surfaces it under +/// blocker on `eql_v3.int4` and asserts the lint surfaces it under /// `blocker_strict`. #[sqlx::test] async fn lint_flags_strict_blocker(pool: PgPool) -> Result<()> { sqlx::query( r#" - CREATE FUNCTION eql_v2.test_bad_blocker_strict(a eql_v2_int4, b eql_v2_int4) + CREATE FUNCTION eql_v2.test_bad_blocker_strict(a eql_v3.int4, b eql_v3.int4) RETURNS boolean LANGUAGE plpgsql IMMUTABLE STRICT - AS $$ BEGIN RETURN eql_v2.encrypted_domain_unsupported_bool('eql_v2_int4', '='); END; $$; + AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '='); END; $$; "#, ) .execute(&pool) @@ -186,7 +186,7 @@ async fn lint_does_not_report_generated_blockers_as_inlinability_errors( | "inlinability_volatility" | "inlinability_set_clause" | "inlinability_secdef" - ) && r.object_name.contains("eql_v2_int4") + ) && r.object_name.contains("eql_v3.int4") && (r.object_name.contains("operator =(") || r.object_name.contains("operator ->(") || r.object_name.contains("operator ?(")) @@ -209,7 +209,7 @@ async fn lint_does_not_report_generated_blockers_as_inlinability_errors( /// surfaces it under `domain_over_domain`. #[sqlx::test] async fn lint_flags_domain_over_domain(pool: PgPool) -> Result<()> { - sqlx::query(r#"CREATE DOMAIN public.eql_v2_test_baddom AS public.eql_v2_int4;"#) + sqlx::query(r#"CREATE DOMAIN public.eql_v2_test_baddom AS eql_v3.int4;"#) .execute(&pool) .await?; @@ -330,7 +330,7 @@ async fn scalar_family_inlinable_operators_are_clean(pool: PgPool) -> Result<()> if matches!(variant, Variant::Storage) { continue; } - let domain = format!("eql_v2_{pg_type}{}", variant.suffix()); + let domain = format!("eql_v3.{pg_type}{}", variant.suffix()); let supported_ops: &[&str] = if variant.supports_ord() { &["=", "<>", "<", "<=", ">", ">="] } else { From da300da33f24b5a00b2317b9a0d0776536638efc Mon Sep 17 00:00:00 2001 From: Toby Hede Date: Mon, 1 Jun 2026 15:21:31 +1000 Subject: [PATCH 2/6] test(encrypted-domain): point int4 matrix tests at eql_v3 schema The int4 domain family moved from eql_v2 to eql_v3, but three generated matrix tests still hardcoded eql_v2. Fixes the CI failures on PG 15/16/17: - scale_default_combos used eql_v2.ord_term as the index extractor, but the ord column is eql_v3.int4_ord (extractor is eql_v3.ord_term). - the aggregate parallel-safety introspection query filtered pg_proc on 'eql_v2'::regnamespace, finding no min/max aggregate (now in eql_v3). Test-only; no production SQL change. --- tests/sqlx/src/matrix.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/sqlx/src/matrix.rs b/tests/sqlx/src/matrix.rs index 8b8c0923..6227de53 100644 --- a/tests/sqlx/src/matrix.rs +++ b/tests/sqlx/src/matrix.rs @@ -204,7 +204,7 @@ macro_rules! ordered_numeric_matrix { // converged ordered domain, ord_term btree. One curated combo keeps // PR CI cost bounded. scale_default_combos = [ - (ord, Ord, "eql_v2.ord_term", "btree"), + (ord, Ord, "eql_v3.ord_term", "btree"), ], } }; @@ -2298,7 +2298,7 @@ macro_rules! __scalar_matrix_aggregate_parallel_case { FROM pg_proc p \ JOIN pg_aggregate a ON a.aggfnoid = p.oid \ WHERE p.proname = $1 \ - AND p.pronamespace = 'eql_v2'::regnamespace \ + AND p.pronamespace = 'eql_v3'::regnamespace \ AND p.proargtypes[0]::regtype = $2::regtype", ) .bind(agg) @@ -2306,9 +2306,9 @@ macro_rules! __scalar_matrix_aggregate_parallel_case { .fetch_one(&pool) .await?; anyhow::ensure!(proparallel == "s", - "eql_v2.{agg}({d}) must be PARALLEL SAFE (proparallel='s'), got {proparallel:?}"); + "eql_v3.{agg}({d}) must be PARALLEL SAFE (proparallel='s'), got {proparallel:?}"); anyhow::ensure!(has_combine, - "eql_v2.{agg}({d}) must declare a combinefunc for partial aggregation"); + "eql_v3.{agg}({d}) must declare a combinefunc for partial aggregation"); } Ok(()) } From 59f3a35bd5bde0e86e811c35802c6e53c222fab8 Mon Sep 17 00:00:00 2001 From: Toby Hede Date: Mon, 1 Jun 2026 16:01:45 +1000 Subject: [PATCH 3/6] fix(lint): describe encrypted-domains namespace-neutrally The domain_over_domain and domain_opclass lint messages hard-coded 'eql_v2_*' and recommended eql_v2.eq_term/ord_term. Now that these lints also target eql_v3 domains, a message firing on an eql_v3 domain pointed at the wrong surface. Drop the version-specific label ('another encrypted-domain', 'an encrypted-domain type') and build the extractor recommendation from the offending domain's own schema (%s.eq_term / %s.ord_term via tn.nspname) so remediation is correct in either namespace. Addresses CodeRabbit review feedback on #247. --- src/lint/lints.sql | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lint/lints.sql b/src/lint/lints.sql index bf38c1e6..cf66f7d4 100644 --- a/src/lint/lints.sql +++ b/src/lint/lints.sql @@ -304,7 +304,7 @@ AS $$ WHERE isstrict -- ┌─────────────────────────────────────────────────────────────────┐ - -- │ Domain identity: an eql_v2_* domain must be defined directly │ + -- │ Domain identity: an encrypted-domain must be defined directly │ -- │ over jsonb. Operators resolve against the ultimate base type, │ -- │ so domain-over-domain inherits jsonb's operator surface and not │ -- │ the base domain's blockers. │ @@ -317,7 +317,7 @@ AS $$ 'domain_over_domain', format('domain %I.%I', dn.nspname, dt.typname), format( - 'Domain `%s.%s` is derived from another eql_v2_* domain `%s.%s` rather than jsonb. Operators resolve against the ultimate base type, so the derived domain does not inherit the base domain''s operator surface and storage blockers do not engage. Define this domain directly over jsonb.', + 'Domain `%s.%s` is derived from another encrypted-domain `%s.%s` rather than jsonb. Operators resolve against the ultimate base type, so the derived domain does not inherit the base domain''s operator surface and storage blockers do not engage. Define this domain directly over jsonb.', dn.nspname, dt.typname, bn.nspname, bt.typname) FROM pg_catalog.pg_type dt JOIN pg_catalog.pg_namespace dn ON dn.oid = dt.typnamespace @@ -336,7 +336,7 @@ AS $$ -- ┌─────────────────────────────────────────────────────────────────┐ -- │ Domain opclass: an operator class declared FOR TYPE on an │ - -- │ eql_v2_* domain bypasses operator resolution at index time. │ + -- │ encrypted-domain bypasses operator resolution at index time. │ -- │ Use a functional index on the extractor instead. │ -- └─────────────────────────────────────────────────────────────────┘ @@ -347,8 +347,8 @@ AS $$ 'domain_opclass', format('opclass %I.%I FOR TYPE %s.%s', cn.nspname, oc.opcname, tn.nspname, t.typname), format( - 'Operator class `%s.%s` is declared FOR TYPE `%s.%s`, which is an eql_v2_* domain. Opclasses on domains bypass operator resolution. Use a functional index on the extractor (e.g. `eql_v2.eq_term(col)`, `eql_v2.ord_term(col)`) instead.', - cn.nspname, oc.opcname, tn.nspname, t.typname) + 'Operator class `%s.%s` is declared FOR TYPE `%s.%s`, which is an encrypted-domain type. Opclasses on domains bypass operator resolution. Use a functional index on the extractor (e.g. `%s.eq_term(col)`, `%s.ord_term(col)`) instead.', + cn.nspname, oc.opcname, tn.nspname, t.typname, tn.nspname, tn.nspname) FROM pg_catalog.pg_opclass oc JOIN pg_catalog.pg_type t ON t.oid = oc.opcintype JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace From 5576136b8b5cd8adc7a8916a3b15c57d9935fdc8 Mon Sep 17 00:00:00 2001 From: Toby Hede Date: Mon, 1 Jun 2026 16:01:45 +1000 Subject: [PATCH 4/6] test(matrix): assert real index-scan node in scale-preference sweep The feature-gated scale-preference sweep arm asserted plan_text.contains(index) on raw EXPLAIN text, which can false-pass on an incidental mention of the index name. Switch it to the JSON-plan helper assert_index_scan_uses, matching the always-on default-category arm and every other EXPLAIN assertion in the file, so the sweep proves a genuine Index/Index-Only/Bitmap-Index scan node rather than a substring. Addresses CodeRabbit review feedback on #247. --- tests/sqlx/src/matrix.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/sqlx/src/matrix.rs b/tests/sqlx/src/matrix.rs index 6227de53..ac690a16 100644 --- a/tests/sqlx/src/matrix.rs +++ b/tests/sqlx/src/matrix.rs @@ -1205,15 +1205,15 @@ SELECT $1::jsonb::{d} FROM generate_series(1, 5000)", .execute(&mut *tx).await?; let lit = pivot_payload.replace('\'', "''"); - let plan: Vec = sqlx::query_scalar(&format!( - "EXPLAIN SELECT * FROM {table} WHERE value = '{lit}'::jsonb::{d}", - )).fetch_all(&mut *tx).await?; - let plan_text = plan.join("\n"); - anyhow::ensure!(plan_text.contains(index), - "with seqscan enabled the planner must prefer the {extractor} \ -{using} index for a selective = ; plan:\n{plan_text}", - extractor = $extractor, using = $using, - ); + $crate::matrix::assert_index_scan_uses( + &mut *tx, + &format!("SELECT * FROM {table} WHERE value = '{lit}'::jsonb::{d}"), + index, + &format!( + "with seqscan enabled the planner must prefer the {extractor} {using} index for a selective =", + extractor = $extractor, using = $using, + ), + ).await?; tx.commit().await?; Ok(()) From 268181170c31db7e01864b1d9693a7e0f3503cee Mon Sep 17 00:00:00 2001 From: Toby Hede Date: Mon, 1 Jun 2026 14:16:51 +1000 Subject: [PATCH 5/6] feat(encrypted-domain): add int2 scalar domain family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the int2 ordered numeric scalar to the generated encrypted-domain family, stacked on the int4 reference. Four jsonb-backed domains (eql_v2_int2{,_eq,_ord,_ord_ore}) are generated from the new tasks/codegen/types/int2.toml manifest by the existing type-generic materializer — no generator behaviour changes. - Register the int2 ScalarKind (i16, MIN -32768 / MAX 32767 / zero) in tasks/codegen/scalars.py, with test_scalars.py coverage. - Commit the generated fixture-value const tests/sqlx/src/fixtures/int2_values.rs (single source of truth shared by the fixture generator and the matrix oracle). - Wire the SQLx matrix oracle: impl ScalarType for i16, the eql_v2_int2 fixture via the scalar_fixture! macro (mirroring eql_v2_int4), and the sealed EqlPlaintext impl for i16 (small_int cast, Plaintext::SmallInt, smallint oracle column). - Add the ordered_numeric_matrix! invocation and the int2 matrix test-name inventory snapshot. - Record the new family in CHANGELOG.md. Keep the codegen reference int4-only: it is a golden master for the type-generic generator, so one anchor detects all template/term drift. New scalar types add no per-type baseline; documented in the spec and tests/codegen/reference/README.md. int2 is guaranteed by the int4 reference, the int2_values.rs staleness guard + test_scalars.py, and the SQLx matrix. --- .github/workflows/test-eql.yml | 1 + CHANGELOG.md | 1 + CLAUDE.md | 1 + docs/reference/encrypted-domain-generator.md | 23 +- .../encrypted-domain-implementation-spec.md | 45 +++- mise.toml | 14 +- tasks/codegen/scalars.py | 9 + tasks/codegen/test_scalars.py | 18 ++ tasks/codegen/types/int2.toml | 19 ++ tests/codegen/reference/README.md | 12 +- tests/sqlx/snapshots/README.md | 53 +++++ tests/sqlx/snapshots/int2_matrix_tests.txt | 211 ++++++++++++++++++ tests/sqlx/src/fixtures/eql_plaintext.rs | 34 +++ tests/sqlx/src/fixtures/eql_v2_int2.rs | 12 + tests/sqlx/src/fixtures/int2_values.rs | 33 +++ tests/sqlx/src/fixtures/mod.rs | 6 + tests/sqlx/src/scalar_domains.rs | 9 + .../tests/encrypted_domain/scalars/int2.rs | 14 ++ .../tests/encrypted_domain/scalars/mod.rs | 2 + 19 files changed, 495 insertions(+), 22 deletions(-) create mode 100644 tasks/codegen/types/int2.toml create mode 100644 tests/sqlx/snapshots/README.md create mode 100644 tests/sqlx/snapshots/int2_matrix_tests.txt create mode 100644 tests/sqlx/src/fixtures/eql_v2_int2.rs create mode 100644 tests/sqlx/src/fixtures/int2_values.rs create mode 100644 tests/sqlx/tests/encrypted_domain/scalars/int2.rs diff --git a/.github/workflows/test-eql.yml b/.github/workflows/test-eql.yml index 436df886..ff82bb42 100644 --- a/.github/workflows/test-eql.yml +++ b/.github/workflows/test-eql.yml @@ -121,6 +121,7 @@ jobs: run: | mise run test:matrix:inventory git diff --exit-code -- tests/sqlx/snapshots/int4_matrix_tests.txt \ + tests/sqlx/snapshots/int2_matrix_tests.txt \ || { echo "Coverage inventory stale — run 'mise run test:matrix:inventory' and commit."; exit 1; } test: diff --git a/CHANGELOG.md b/CHANGELOG.md index 00215fd2..c75b70db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Each entry that ships in a published release links to the PR that introduced it. ### Added - **`eql_v3` encrypted-domain schema, with the `int4` family as its first member.** Encrypted-domain type families now live in a new, additional `eql_v3` schema (the existing `eql_v2` schema is unchanged — it keeps the core types/operators and stays the documented public API). Four jsonb-backed domains for encrypted `int4` columns: `eql_v3.int4` (storage-only), `eql_v3.int4_eq` (`=` / `<>` via HMAC), and `eql_v3.int4_ord` / `eql_v3.int4_ord_ore` (also `<` `<=` `>` `>=` via ORE block terms). Supported comparisons resolve to inlinable wrappers; the native `jsonb` operator surface reachable through domain fallback is blocked (raises rather than silently mis-resolving). Each domain's `CHECK` requires the EQL envelope (`v`, `i`), the ciphertext (`c`), and the variant's index term(s), and pins the payload version (`VALUE->>'v' = '2'`, matching `eql_v2._encrypted_check_v`) — so a missing key or wrong-version payload is rejected on insert or cast rather than surfacing later at query time. Index via a functional index on the `eql_v3.eq_term` / `eql_v3.ord_term` extractors, not an operator class on the domain. The extractors still return the core `eql_v2.hmac_256` / `eql_v2.ore_block_u64_8_256` index-term types, which remain in `eql_v2` and are referenced cross-schema. Why: a type-safe, per-capability encrypted integer column instead of the untyped `eql_v2_encrypted`, namespaced under its own schema. This is the reference scalar implementation for the generated domain family. ([#239](https://github.com/cipherstash/encrypt-query-language/pull/239), supersedes [#225](https://github.com/cipherstash/encrypt-query-language/pull/225)) +- **`eql_v3.int2` encrypted-domain type family.** Four jsonb-backed domains for encrypted `int2` columns — `eql_v3.int2` (storage-only), `eql_v3.int2_eq` (`=` / `<>` via HMAC), and `eql_v3.int2_ord` / `eql_v3.int2_ord_ore` (also `<` `<=` `>` `>=` via ORE block terms, with `MIN` / `MAX` aggregates) — generated from `tasks/codegen/types/int2.toml` by the same materializer as the `eql_v3.int4` reference. Index via a functional index on the `eql_v3.eq_term` / `eql_v3.ord_term` extractors, not an operator class on the domain. Why: a type-safe, per-capability encrypted `smallint` column, proving the scalar generator generalizes beyond the `int4` reference. ([#243](https://github.com/cipherstash/encrypt-query-language/pull/243)) - **Per-domain `MIN` / `MAX` aggregates for the encrypted-domain family.** `eql_v3.min(eql_v3._ord)` / `eql_v3.max(eql_v3._ord)` (and the `_ord_ore` twin) are generated for every ord-capable scalar variant, giving type-safe extrema on domain-typed columns — comparison routes through the variant's `<` / `>` operator (ORE block term, no decryption). The aggregates are declared `PARALLEL = SAFE` with a combine function (the state function itself — min/max are associative), so PostgreSQL can use partial/parallel aggregation on large `GROUP BY` workloads. Why: the new domain types previously had no equivalent of the composite-type aggregates. The existing `eql_v2.min(eql_v2_encrypted)` / `eql_v2.max(eql_v2_encrypted)` aggregates are **retained** and continue to work on `eql_v2_encrypted` columns; the per-domain aggregates are additive and coexist with them. ([#239](https://github.com/cipherstash/encrypt-query-language/pull/239)) ## [2.3.1] — 2026-05-21 diff --git a/CLAUDE.md b/CLAUDE.md index 1328a8b0..4b489123 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -29,6 +29,7 @@ This project uses `mise` for task management. Common commands: - Run SQLx tests directly: `mise run test:sqlx` - Run SQLx tests in watch mode: `mise run test:sqlx:watch` - Tests are located in `tests/sqlx/` using Rust and SQLx framework +- Regenerate the scalar matrix coverage snapshots: `mise run test:matrix:inventory` (no database required). These committed `tests/sqlx/snapshots/_matrix_tests.txt` baselines pin the set of `scalars::::*` test names so a silently dropped/renamed/`#[cfg]`-gated test fails CI's `matrix-coverage` job. When you add or remove matrix tests (or add a scalar type), regenerate and commit the affected snapshot in the same change. See `tests/sqlx/snapshots/README.md`. ### Build System - Dependencies are resolved using `-- REQUIRE:` comments in SQL files diff --git a/docs/reference/encrypted-domain-generator.md b/docs/reference/encrypted-domain-generator.md index bb6252be..9b2d6a07 100644 --- a/docs/reference/encrypted-domain-generator.md +++ b/docs/reference/encrypted-domain-generator.md @@ -377,12 +377,23 @@ The end-to-end shape from a generator perspective: 4. **Build picks it up automatically** — `tasks/build.sh` regenerates before computing the `tsort` graph, so the new files appear in the dependency walk via the `-- REQUIRE:` edges the generator emits. -5. **Baseline & test.** Create a hand-reviewed byte-parity baseline under - `tests/codegen/reference//` (each file marked `-- REFERENCE:` / - `// REFERENCE:`) so `test_against_reference.py` guards the new type — it - only covers types that have a baseline directory. Then run - `mise run test:codegen`, the relevant SQLx suites, and the PostgreSQL - matrix. +5. **Test.** Do **not** add a `tests/codegen/reference//` baseline. + `int4` is the sole golden master for the type-generic generator: the SQL + templates are pure token substitution and the only type-specific rendering + is `_values.rs`, so a per-type baseline can only fail where `int4`'s + already would. Drift protection for the new type comes from the `int4` + reference (shared templates + `terms.py`), the committed `_values.rs` + const guarded by the codegen staleness check, the `` cases in + `test_scalars.py`, and the `ordered_numeric_matrix!` SQLx suite (behaviour, + not bytes). Run `mise run test:codegen`, the relevant SQLx suites, and the + PostgreSQL matrix. +6. **Snapshot the matrix inventory.** Run `mise run test:matrix:inventory` + and commit the new `tests/sqlx/snapshots/_matrix_tests.txt` — the + sorted list of the type's `scalars::::*` test names. CI's + `matrix-coverage` job `git diff --exit-code`s it (like `_values.rs`) + to catch a silently dropped or renamed matrix test. The snapshot is a + committed test baseline, not gitignored generated SQL. See + `tests/sqlx/snapshots/README.md`. Adding a new **term** is a bigger move — edit `terms.py`, add tests, audit `splinter.sh` for a name collision, and update the reference diff --git a/docs/reference/encrypted-domain-implementation-spec.md b/docs/reference/encrypted-domain-implementation-spec.md index c6bec96a..e21c8d6a 100644 --- a/docs/reference/encrypted-domain-implementation-spec.md +++ b/docs/reference/encrypted-domain-implementation-spec.md @@ -83,13 +83,21 @@ future migration. - [ ] Put optional hand-written SQL in `src/encrypted_domain//_extensions.sql` with explicit `-- REQUIRE:` edges. This file IS committed. -- [ ] Create a hand-reviewed byte-parity baseline under - `tests/codegen/reference//` — one file per generated SQL output plus - `_values.rs`, each headed with the `-- REFERENCE:` / `// REFERENCE:` - marker. `tasks/codegen/test_against_reference.py` only guards types that - have a baseline directory, so without it the new type gets no - drift protection. The committed-fixture parity assertion is currently - `int4`-only; extend it to cover ``. +- [ ] Do **not** add a `tests/codegen/reference//` baseline. `int4` is the + single golden master for the type-generic generator: the SQL templates are + pure token substitution and the only type-specific rendering is + `_values.rs`, so a per-type baseline can only fail when `int4`'s already + would. Drift protection for the new type comes from the `int4` reference + (shared templates + `terms.py`), the committed `_values.rs` const guarded + by the CI staleness check (`mise run codegen:domain ` + `git diff + --exit-code`) and the `` cases in `tasks/codegen/test_scalars.py`, and + the `ordered_numeric_matrix!` SQLx suite (behaviour, not bytes). +- [ ] Run `mise run test:matrix:inventory` and commit the regenerated + `tests/sqlx/snapshots/_matrix_tests.txt` — the sorted inventory of every + `scalars::::*` test name in the `encrypted_domain` binary. CI diffs it + (same as `_values.rs`); a stale snapshot fails the `matrix-coverage` + job with "Coverage inventory stale". This baseline is what catches a + silently dropped, renamed, or `#[cfg]`-gated matrix test. See §8. - [ ] Run `mise run test:codegen`, the relevant SQLx suites, and the PostgreSQL matrix before merging. @@ -252,8 +260,9 @@ Cover each generated domain with SQLx tests appropriate to its terms: - domain `CHECK` rejects non-object and under-populated payloads; - real typed columns are tested, not only cast literals; - generated ordered-domain twins remain byte-identical modulo type name - (verified by `tasks/codegen/test_against_reference.py` against the - hand-reviewed baseline in `tests/codegen/reference//`). + (the shared generator is anchored by the `int4` golden master in + `tests/codegen/reference/int4/` via `tasks/codegen/test_against_reference.py`; + new types add no baseline of their own — see §2). For ordered numeric scalars this coverage is generated by the `ordered_numeric_matrix!` convention wrapper in `tests/sqlx/src/matrix.rs`: @@ -272,6 +281,24 @@ For ordered `int4`, keep the assertion that distinct plaintext values produce distinct ORE blocks. Do not add assertions for term behavior that the catalog does not promise. +### Matrix coverage inventory snapshot + +The *set of test names* the matrix emits is itself guarded. `mise run +test:matrix:inventory` lists every test in the `encrypted_domain` binary +under a pinned feature set (`--no-default-features`, which deliberately +excludes the `scale` arm — see the task comment in `mise.toml`), greps it to +each `scalars::::*` matrix, `LC_ALL=C sort`s for byte-stable ordering, and +writes one committed snapshot per scalar at +`tests/sqlx/snapshots/_matrix_tests.txt`. The CI `matrix-coverage` job +regenerates with the same feature set and `git diff --exit-code`s every +snapshot; a divergence fails with "Coverage inventory stale". This is the +guard that catches a silently dropped, renamed, or `#[cfg]`-gated matrix +test — a behaviour the SQLx assertions above cannot see, because a deleted +test simply stops running. When you add a scalar you add a new snapshot; +when you add or remove matrix tests you regenerate and commit the affected +snapshot in the same change. The files are a committed test baseline, **not** +gitignored generated SQL. See `tests/sqlx/snapshots/README.md`. + ## 9. Fixtures Fixture generation should use real encrypted payloads produced through diff --git a/mise.toml b/mise.toml index 270fab25..c513202f 100644 --- a/mise.toml +++ b/mise.toml @@ -96,7 +96,7 @@ mise exec python -- python -m pytest tasks/codegen -q """ [tasks."test:matrix:inventory"] -description = "Regenerate the int4 matrix test-name inventory snapshot (no database required)" +description = "Regenerate the int4/int2 matrix test-name inventory snapshots (no database required)" dir = "{{config_root}}/tests/sqlx" run = """ # Pin an explicit feature set so the inventory is deterministic regardless of @@ -105,14 +105,18 @@ run = """ # of this default-feature inventory, covered instead by the scale gate + the # family::mutations negative controls. `--list` enumerates the whole # encrypted_domain binary (family::support, family::inlinability, -# family::mutations, scalars::int4); `grep '^scalars::int4'` scopes the -# snapshot to the matrix only, so landing other family tests never dirties it. -# `LC_ALL=C sort` makes ordering byte-stable across locales (a bare `sort` is -# locale-dependent and yields spurious CI diffs). +# family::mutations, scalars::int4, scalars::int2); the per-scalar `grep` +# scopes each snapshot to that matrix only, so landing other family tests +# never dirties it. `LC_ALL=C sort` makes ordering byte-stable across locales +# (a bare `sort` is locale-dependent and yields spurious CI diffs). set -euo pipefail mkdir -p snapshots cargo test --no-default-features --test encrypted_domain -- --list | sed -n 's/: test$//p' | grep '^scalars::int4' | LC_ALL=C sort > snapshots/int4_matrix_tests.txt +cargo test --no-default-features --test encrypted_domain -- --list | + sed -n 's/: test$//p' | + grep '^scalars::int2' | + LC_ALL=C sort > snapshots/int2_matrix_tests.txt """ diff --git a/tasks/codegen/scalars.py b/tasks/codegen/scalars.py index a93df905..eee01dc4 100644 --- a/tasks/codegen/scalars.py +++ b/tasks/codegen/scalars.py @@ -79,6 +79,15 @@ def render_literal(self, value: str) -> str: min_value=-2147483648, max_value=2147483647, ), + "int2": ScalarKind( + token="int2", + rust_type="i16", + min_symbol="i16::MIN", + max_symbol="i16::MAX", + zero_symbol="0", + min_value=-32768, + max_value=32767, + ), } diff --git a/tasks/codegen/test_scalars.py b/tasks/codegen/test_scalars.py index 3ef7d0f0..1f15f1c3 100644 --- a/tasks/codegen/test_scalars.py +++ b/tasks/codegen/test_scalars.py @@ -62,3 +62,21 @@ def test_require_scalar_unknown_raises(): def test_int4_registered_in_catalog(): assert "int4" in SCALAR_KINDS + + +def test_int2_kind_resolves_and_renders(): + kind = require_scalar("int2") + assert kind.rust_type == "i16" + assert kind.numeric_value("MIN") == -32768 + assert kind.numeric_value("MAX") == 32767 + assert kind.numeric_value("ZERO") == 0 + assert kind.render_literal("MIN") == "i16::MIN" + assert kind.render_literal("MAX") == "i16::MAX" + assert kind.render_literal("ZERO") == "0" + assert kind.render_literal("30000") == "30000" + + +def test_int2_kind_rejects_out_of_range(): + kind = require_scalar("int2") + with pytest.raises(ScalarError, match="out of range"): + kind.numeric_value("40000") diff --git a/tasks/codegen/types/int2.toml b/tasks/codegen/types/int2.toml new file mode 100644 index 00000000..314bc698 --- /dev/null +++ b/tasks/codegen/types/int2.toml @@ -0,0 +1,19 @@ +# Encrypted-domain scalar manifest for int2. +# The filename supplies the type token. Each domain lists the index terms +# it carries; term capabilities are fixed in tasks/codegen/terms.py. + +[domain] +int2 = [] +int2_eq = ["hm"] +int2_ord_ore = ["ore"] +int2_ord = ["ore"] + +# Single source of truth for the int2 fixture plaintext list. Drives the +# generated tests/sqlx/src/fixtures/int2_values.rs const, shared by the fixture +# generator and the matrix oracle. Sentinels MIN/MAX/ZERO map to i16 named +# consts; the set MUST include MIN, MAX, and zero (matrix comparison pivots). +[fixture] +values = [ + "MIN", "-30000", "-100", "-1", "ZERO", "1", "2", "5", "10", "17", "25", + "42", "50", "100", "250", "1000", "9999", "30000", "MAX", +] diff --git a/tests/codegen/reference/README.md b/tests/codegen/reference/README.md index c1fa5118..58f01cc1 100644 --- a/tests/codegen/reference/README.md +++ b/tests/codegen/reference/README.md @@ -1,5 +1,13 @@ # Codegen reference -The SQL files under `/` are the original, hand-written reference implementation for each encrypted-domain scalar type. +The SQL files under `int4/` are the original, hand-written reference implementation for the encrypted-domain scalar generator. `int4` is the **single golden master**: the generator in `tasks/codegen/` is type-generic — its SQL templates are pure token substitution, and the only type-specific rendering is the `_values.rs` const — so one anchored type detects all template/term drift for every current and future scalar. -They are the parity baseline for the generator in `tasks/codegen/`. `tasks/codegen/test_against_reference.py` renders the generator's output and asserts it matches these files byte-for-byte. If the generator diverges, either it regressed (fix `tasks/codegen/`) or the reference is being updated deliberately (commit the new reference in the same PR). +`tasks/codegen/test_against_reference.py` renders the generator's output for `int4` and asserts it matches these files byte-for-byte. If the generator diverges, either it regressed (fix `tasks/codegen/`) or the reference is being updated deliberately (commit the new `int4` reference in the same PR). + +## New scalar types do not add a reference + +Adding a scalar type (`int2`, `int8`, …) does **not** add a `tests/codegen/reference//` directory. A per-type baseline would be redundant: the SQL is byte-identical to `int4` modulo the type token, so it can only fail when `int4`'s baseline already would. New types are guaranteed three other ways: + +- the `int4` reference here anchors the shared generator (templates + `terms.py`); +- the committed `tests/sqlx/src/fixtures/_values.rs` const is pinned by the CI staleness guard (`git diff --exit-code` after `mise run codegen:domain `) and by the `` cases in `tasks/codegen/test_scalars.py` (the only type-specific rendering, `i16::MIN` vs `i32::MIN`); +- the SQLx `ordered_numeric_matrix!` suite exercises the generated SQL's *behaviour* against a real database — a far stronger guarantee than a byte comparison. diff --git a/tests/sqlx/snapshots/README.md b/tests/sqlx/snapshots/README.md new file mode 100644 index 00000000..a4ce5ae9 --- /dev/null +++ b/tests/sqlx/snapshots/README.md @@ -0,0 +1,53 @@ +# Matrix coverage inventory snapshots + +This directory holds one committed snapshot per scalar encrypted-domain type: + +- `int4_matrix_tests.txt` +- `int2_matrix_tests.txt` + +Each file is a sorted, byte-stable list of every `scalars::::*` test name in +the `encrypted_domain` SQLx binary. They are a **committed test baseline**, not +gitignored generated SQL — keep them in version control. + +## What they guard + +The SQLx assertions verify that the tests which run produce the right results. +They cannot see a test that *stops running* — a matrix test that is deleted, +renamed, or hidden behind a `#[cfg]` gate simply vanishes silently, quietly +shrinking coverage. These snapshots close that gap: they pin the *set of test +names* so any such change shows up as an added/removed line in the PR diff. + +## How they are generated + +Run: + +```bash +mise run test:matrix:inventory +``` + +The task (`mise.toml`, `[tasks."test:matrix:inventory"]`) enumerates the binary +with `cargo test --test encrypted_domain -- --list`, greps each +`scalars::` matrix into its own file, and `LC_ALL=C sort`s for ordering +that is byte-stable across locales. No database is required — `--list` only +enumerates; the suite uses runtime queries. + +It pins `--no-default-features` so the inventory is deterministic regardless of +the caller's local flags. That deliberately excludes the `scale` feature arm +(`#[cfg(feature = "scale")]`) — a known blind spot of this inventory, covered +instead by the scale gate plus the `family::mutations` negative controls. + +## CI enforcement + +The `matrix-coverage` job in `.github/workflows/test-eql.yml` regenerates with +the same pinned feature set and runs `git diff --exit-code` against every +snapshot in this directory. A divergence fails the job with: + +> Coverage inventory stale — run 'mise run test:matrix:inventory' and commit. + +## When you must update these + +- **Adding a new scalar type** → a new `_matrix_tests.txt` appears; commit it. +- **Adding / removing / renaming matrix tests** → regenerate and commit the + affected snapshot in the same change. + +See `docs/reference/encrypted-domain-implementation-spec.md` §2 and §8. diff --git a/tests/sqlx/snapshots/int2_matrix_tests.txt b/tests/sqlx/snapshots/int2_matrix_tests.txt new file mode 100644 index 00000000..3b6ed674 --- /dev/null +++ b/tests/sqlx/snapshots/int2_matrix_tests.txt @@ -0,0 +1,211 @@ +scalars::int2::matrix_int2_eq_aggregate_typecheck_max +scalars::int2::matrix_int2_eq_aggregate_typecheck_min +scalars::int2::matrix_int2_eq_contained_by_blocker +scalars::int2::matrix_int2_eq_contains_blocker +scalars::int2::matrix_int2_eq_count_distinct_extractor +scalars::int2::matrix_int2_eq_count_path_cast +scalars::int2::matrix_int2_eq_count_typed_column +scalars::int2::matrix_int2_eq_eq_pivot_max_correctness +scalars::int2::matrix_int2_eq_eq_pivot_max_cross_shape +scalars::int2::matrix_int2_eq_eq_pivot_min_correctness +scalars::int2::matrix_int2_eq_eq_pivot_min_cross_shape +scalars::int2::matrix_int2_eq_eq_pivot_zero_correctness +scalars::int2::matrix_int2_eq_eq_pivot_zero_cross_shape +scalars::int2::matrix_int2_eq_eq_supported_null +scalars::int2::matrix_int2_eq_gt_blocker +scalars::int2::matrix_int2_eq_gte_blocker +scalars::int2::matrix_int2_eq_index_engages_btree +scalars::int2::matrix_int2_eq_index_engages_hash +scalars::int2::matrix_int2_eq_lt_blocker +scalars::int2::matrix_int2_eq_lte_blocker +scalars::int2::matrix_int2_eq_native_absent_ops +scalars::int2::matrix_int2_eq_neq_pivot_max_correctness +scalars::int2::matrix_int2_eq_neq_pivot_max_cross_shape +scalars::int2::matrix_int2_eq_neq_pivot_min_correctness +scalars::int2::matrix_int2_eq_neq_pivot_min_cross_shape +scalars::int2::matrix_int2_eq_neq_pivot_zero_correctness +scalars::int2::matrix_int2_eq_neq_pivot_zero_cross_shape +scalars::int2::matrix_int2_eq_neq_supported_null +scalars::int2::matrix_int2_eq_path_op_blockers +scalars::int2::matrix_int2_eq_payload_check +scalars::int2::matrix_int2_eq_planner_metadata_eq +scalars::int2::matrix_int2_eq_sanity +scalars::int2::matrix_int2_eq_typed_column_blocker +scalars::int2::matrix_int2_fixture_shape +scalars::int2::matrix_int2_ord_aggregate_group_by_max +scalars::int2::matrix_int2_ord_aggregate_group_by_min +scalars::int2::matrix_int2_ord_aggregate_max +scalars::int2::matrix_int2_ord_aggregate_max_all_null +scalars::int2::matrix_int2_ord_aggregate_max_empty +scalars::int2::matrix_int2_ord_aggregate_max_mixed_null +scalars::int2::matrix_int2_ord_aggregate_min +scalars::int2::matrix_int2_ord_aggregate_min_all_null +scalars::int2::matrix_int2_ord_aggregate_min_empty +scalars::int2::matrix_int2_ord_aggregate_min_mixed_null +scalars::int2::matrix_int2_ord_aggregate_parallel_safe +scalars::int2::matrix_int2_ord_contained_by_blocker +scalars::int2::matrix_int2_ord_contains_blocker +scalars::int2::matrix_int2_ord_count_distinct_extractor +scalars::int2::matrix_int2_ord_count_path_cast +scalars::int2::matrix_int2_ord_count_typed_column +scalars::int2::matrix_int2_ord_eq_pivot_max_correctness +scalars::int2::matrix_int2_ord_eq_pivot_max_cross_shape +scalars::int2::matrix_int2_ord_eq_pivot_min_correctness +scalars::int2::matrix_int2_ord_eq_pivot_min_cross_shape +scalars::int2::matrix_int2_ord_eq_pivot_zero_correctness +scalars::int2::matrix_int2_ord_eq_pivot_zero_cross_shape +scalars::int2::matrix_int2_ord_eq_supported_null +scalars::int2::matrix_int2_ord_gt_pivot_max_correctness +scalars::int2::matrix_int2_ord_gt_pivot_max_cross_shape +scalars::int2::matrix_int2_ord_gt_pivot_min_correctness +scalars::int2::matrix_int2_ord_gt_pivot_min_cross_shape +scalars::int2::matrix_int2_ord_gt_pivot_zero_correctness +scalars::int2::matrix_int2_ord_gt_pivot_zero_cross_shape +scalars::int2::matrix_int2_ord_gt_supported_null +scalars::int2::matrix_int2_ord_gte_pivot_max_correctness +scalars::int2::matrix_int2_ord_gte_pivot_max_cross_shape +scalars::int2::matrix_int2_ord_gte_pivot_min_correctness +scalars::int2::matrix_int2_ord_gte_pivot_min_cross_shape +scalars::int2::matrix_int2_ord_gte_pivot_zero_correctness +scalars::int2::matrix_int2_ord_gte_pivot_zero_cross_shape +scalars::int2::matrix_int2_ord_gte_supported_null +scalars::int2::matrix_int2_ord_index_engages_btree +scalars::int2::matrix_int2_ord_lt_pivot_max_correctness +scalars::int2::matrix_int2_ord_lt_pivot_max_cross_shape +scalars::int2::matrix_int2_ord_lt_pivot_min_correctness +scalars::int2::matrix_int2_ord_lt_pivot_min_cross_shape +scalars::int2::matrix_int2_ord_lt_pivot_zero_correctness +scalars::int2::matrix_int2_ord_lt_pivot_zero_cross_shape +scalars::int2::matrix_int2_ord_lt_supported_null +scalars::int2::matrix_int2_ord_lte_pivot_max_correctness +scalars::int2::matrix_int2_ord_lte_pivot_max_cross_shape +scalars::int2::matrix_int2_ord_lte_pivot_min_correctness +scalars::int2::matrix_int2_ord_lte_pivot_min_cross_shape +scalars::int2::matrix_int2_ord_lte_pivot_zero_correctness +scalars::int2::matrix_int2_ord_lte_pivot_zero_cross_shape +scalars::int2::matrix_int2_ord_lte_supported_null +scalars::int2::matrix_int2_ord_native_absent_ops +scalars::int2::matrix_int2_ord_neq_pivot_max_correctness +scalars::int2::matrix_int2_ord_neq_pivot_max_cross_shape +scalars::int2::matrix_int2_ord_neq_pivot_min_correctness +scalars::int2::matrix_int2_ord_neq_pivot_min_cross_shape +scalars::int2::matrix_int2_ord_neq_pivot_zero_correctness +scalars::int2::matrix_int2_ord_neq_pivot_zero_cross_shape +scalars::int2::matrix_int2_ord_neq_supported_null +scalars::int2::matrix_int2_ord_ord_routes_through_ob +scalars::int2::matrix_int2_ord_order_by_asc_no_where +scalars::int2::matrix_int2_ord_order_by_asc_nulls_first +scalars::int2::matrix_int2_ord_order_by_asc_nulls_last +scalars::int2::matrix_int2_ord_order_by_asc_with_where +scalars::int2::matrix_int2_ord_order_by_desc_no_where +scalars::int2::matrix_int2_ord_order_by_desc_nulls_first +scalars::int2::matrix_int2_ord_order_by_desc_nulls_last +scalars::int2::matrix_int2_ord_order_by_desc_with_where +scalars::int2::matrix_int2_ord_order_by_using_gt_rejects +scalars::int2::matrix_int2_ord_order_by_using_gte_rejects +scalars::int2::matrix_int2_ord_order_by_using_lt_rejects +scalars::int2::matrix_int2_ord_order_by_using_lte_rejects +scalars::int2::matrix_int2_ord_ore_aggregate_group_by_max +scalars::int2::matrix_int2_ord_ore_aggregate_group_by_min +scalars::int2::matrix_int2_ord_ore_aggregate_max +scalars::int2::matrix_int2_ord_ore_aggregate_max_all_null +scalars::int2::matrix_int2_ord_ore_aggregate_max_empty +scalars::int2::matrix_int2_ord_ore_aggregate_max_mixed_null +scalars::int2::matrix_int2_ord_ore_aggregate_min +scalars::int2::matrix_int2_ord_ore_aggregate_min_all_null +scalars::int2::matrix_int2_ord_ore_aggregate_min_empty +scalars::int2::matrix_int2_ord_ore_aggregate_min_mixed_null +scalars::int2::matrix_int2_ord_ore_aggregate_parallel_safe +scalars::int2::matrix_int2_ord_ore_contained_by_blocker +scalars::int2::matrix_int2_ord_ore_contains_blocker +scalars::int2::matrix_int2_ord_ore_count_distinct_extractor +scalars::int2::matrix_int2_ord_ore_count_path_cast +scalars::int2::matrix_int2_ord_ore_count_typed_column +scalars::int2::matrix_int2_ord_ore_eq_pivot_max_correctness +scalars::int2::matrix_int2_ord_ore_eq_pivot_max_cross_shape +scalars::int2::matrix_int2_ord_ore_eq_pivot_min_correctness +scalars::int2::matrix_int2_ord_ore_eq_pivot_min_cross_shape +scalars::int2::matrix_int2_ord_ore_eq_pivot_zero_correctness +scalars::int2::matrix_int2_ord_ore_eq_pivot_zero_cross_shape +scalars::int2::matrix_int2_ord_ore_eq_supported_null +scalars::int2::matrix_int2_ord_ore_gt_pivot_max_correctness +scalars::int2::matrix_int2_ord_ore_gt_pivot_max_cross_shape +scalars::int2::matrix_int2_ord_ore_gt_pivot_min_correctness +scalars::int2::matrix_int2_ord_ore_gt_pivot_min_cross_shape +scalars::int2::matrix_int2_ord_ore_gt_pivot_zero_correctness +scalars::int2::matrix_int2_ord_ore_gt_pivot_zero_cross_shape +scalars::int2::matrix_int2_ord_ore_gt_supported_null +scalars::int2::matrix_int2_ord_ore_gte_pivot_max_correctness +scalars::int2::matrix_int2_ord_ore_gte_pivot_max_cross_shape +scalars::int2::matrix_int2_ord_ore_gte_pivot_min_correctness +scalars::int2::matrix_int2_ord_ore_gte_pivot_min_cross_shape +scalars::int2::matrix_int2_ord_ore_gte_pivot_zero_correctness +scalars::int2::matrix_int2_ord_ore_gte_pivot_zero_cross_shape +scalars::int2::matrix_int2_ord_ore_gte_supported_null +scalars::int2::matrix_int2_ord_ore_index_engages_btree +scalars::int2::matrix_int2_ord_ore_lt_pivot_max_correctness +scalars::int2::matrix_int2_ord_ore_lt_pivot_max_cross_shape +scalars::int2::matrix_int2_ord_ore_lt_pivot_min_correctness +scalars::int2::matrix_int2_ord_ore_lt_pivot_min_cross_shape +scalars::int2::matrix_int2_ord_ore_lt_pivot_zero_correctness +scalars::int2::matrix_int2_ord_ore_lt_pivot_zero_cross_shape +scalars::int2::matrix_int2_ord_ore_lt_supported_null +scalars::int2::matrix_int2_ord_ore_lte_pivot_max_correctness +scalars::int2::matrix_int2_ord_ore_lte_pivot_max_cross_shape +scalars::int2::matrix_int2_ord_ore_lte_pivot_min_correctness +scalars::int2::matrix_int2_ord_ore_lte_pivot_min_cross_shape +scalars::int2::matrix_int2_ord_ore_lte_pivot_zero_correctness +scalars::int2::matrix_int2_ord_ore_lte_pivot_zero_cross_shape +scalars::int2::matrix_int2_ord_ore_lte_supported_null +scalars::int2::matrix_int2_ord_ore_native_absent_ops +scalars::int2::matrix_int2_ord_ore_neq_pivot_max_correctness +scalars::int2::matrix_int2_ord_ore_neq_pivot_max_cross_shape +scalars::int2::matrix_int2_ord_ore_neq_pivot_min_correctness +scalars::int2::matrix_int2_ord_ore_neq_pivot_min_cross_shape +scalars::int2::matrix_int2_ord_ore_neq_pivot_zero_correctness +scalars::int2::matrix_int2_ord_ore_neq_pivot_zero_cross_shape +scalars::int2::matrix_int2_ord_ore_neq_supported_null +scalars::int2::matrix_int2_ord_ore_ord_routes_through_ob +scalars::int2::matrix_int2_ord_ore_order_by_asc_no_where +scalars::int2::matrix_int2_ord_ore_order_by_asc_nulls_first +scalars::int2::matrix_int2_ord_ore_order_by_asc_nulls_last +scalars::int2::matrix_int2_ord_ore_order_by_asc_with_where +scalars::int2::matrix_int2_ord_ore_order_by_desc_no_where +scalars::int2::matrix_int2_ord_ore_order_by_desc_nulls_first +scalars::int2::matrix_int2_ord_ore_order_by_desc_nulls_last +scalars::int2::matrix_int2_ord_ore_order_by_desc_with_where +scalars::int2::matrix_int2_ord_ore_order_by_using_gt_rejects +scalars::int2::matrix_int2_ord_ore_order_by_using_gte_rejects +scalars::int2::matrix_int2_ord_ore_order_by_using_lt_rejects +scalars::int2::matrix_int2_ord_ore_order_by_using_lte_rejects +scalars::int2::matrix_int2_ord_ore_ore_injectivity +scalars::int2::matrix_int2_ord_ore_path_op_blockers +scalars::int2::matrix_int2_ord_ore_payload_check +scalars::int2::matrix_int2_ord_ore_planner_metadata_eq +scalars::int2::matrix_int2_ord_ore_planner_metadata_ord +scalars::int2::matrix_int2_ord_ore_sanity +scalars::int2::matrix_int2_ord_ore_typed_column_blocker +scalars::int2::matrix_int2_ord_path_op_blockers +scalars::int2::matrix_int2_ord_payload_check +scalars::int2::matrix_int2_ord_planner_metadata_eq +scalars::int2::matrix_int2_ord_planner_metadata_ord +scalars::int2::matrix_int2_ord_sanity +scalars::int2::matrix_int2_ord_scale_preference_default_btree +scalars::int2::matrix_int2_ord_typed_column_blocker +scalars::int2::matrix_int2_storage_aggregate_typecheck_max +scalars::int2::matrix_int2_storage_aggregate_typecheck_min +scalars::int2::matrix_int2_storage_contained_by_blocker +scalars::int2::matrix_int2_storage_contains_blocker +scalars::int2::matrix_int2_storage_count_path_cast +scalars::int2::matrix_int2_storage_count_typed_column +scalars::int2::matrix_int2_storage_eq_blocker +scalars::int2::matrix_int2_storage_gt_blocker +scalars::int2::matrix_int2_storage_gte_blocker +scalars::int2::matrix_int2_storage_lt_blocker +scalars::int2::matrix_int2_storage_lte_blocker +scalars::int2::matrix_int2_storage_native_absent_ops +scalars::int2::matrix_int2_storage_neq_blocker +scalars::int2::matrix_int2_storage_path_op_blockers +scalars::int2::matrix_int2_storage_payload_check +scalars::int2::matrix_int2_storage_sanity +scalars::int2::matrix_int2_storage_typed_column_blocker diff --git a/tests/sqlx/src/fixtures/eql_plaintext.rs b/tests/sqlx/src/fixtures/eql_plaintext.rs index 0db9482a..36b348fd 100644 --- a/tests/sqlx/src/fixtures/eql_plaintext.rs +++ b/tests/sqlx/src/fixtures/eql_plaintext.rs @@ -53,6 +53,7 @@ pub struct PlaintextSqlType(&'static str); impl PlaintextSqlType { pub const INTEGER: PlaintextSqlType = PlaintextSqlType("integer"); + pub const SMALLINT: PlaintextSqlType = PlaintextSqlType("smallint"); pub fn as_str(&self) -> &'static str { self.0 @@ -68,6 +69,7 @@ impl fmt::Display for PlaintextSqlType { mod sealed { pub trait Sealed {} impl Sealed for i32 {} + impl Sealed for i16 {} } /// A Rust type usable as a fixture `plaintext` value, carrying its EQL cast @@ -96,6 +98,15 @@ impl EqlPlaintext for i32 { } } +impl EqlPlaintext for i16 { + const CAST: Cast = Cast::SMALL_INT; + const PLAINTEXT_SQL_TYPE: PlaintextSqlType = PlaintextSqlType::SMALLINT; + + fn to_plaintext(&self) -> Plaintext { + Plaintext::SmallInt(Some(*self)) + } +} + #[cfg(test)] mod tests { use super::*; @@ -122,4 +133,27 @@ mod tests { other => panic!("expected Plaintext::Int(Some(42)), got {other:?}"), } } + + #[test] + fn i16_casts_to_small_int() { + assert_eq!(::CAST.as_str(), "small_int"); + } + + #[test] + fn i16_plaintext_sql_type_is_smallint() { + assert_eq!( + ::PLAINTEXT_SQL_TYPE.as_str(), + "smallint" + ); + } + + #[test] + fn i16_to_plaintext_wraps_in_small_int_variant() { + // i16 must lift into the SmallInt variant so the fixture driver + // encrypts it under the `small_int` cast, not `int`. + match 42_i16.to_plaintext() { + Plaintext::SmallInt(Some(value)) => assert_eq!(value, 42), + other => panic!("expected Plaintext::SmallInt(Some(42)), got {other:?}"), + } + } } diff --git a/tests/sqlx/src/fixtures/eql_v2_int2.rs b/tests/sqlx/src/fixtures/eql_v2_int2.rs new file mode 100644 index 00000000..ec4a1333 --- /dev/null +++ b/tests/sqlx/src/fixtures/eql_v2_int2.rs @@ -0,0 +1,12 @@ +//! The `eql_v2_int2` fixture — the int4 reference, clamped to 16 bits. +//! +//! 19 integers spanning a negative boundary, the i16 signed extremes +//! (`MIN`/`MAX`), zero, a pair near the ±32767 boundary, and +//! small/medium/large magnitudes. The generated +//! `tests/sqlx/fixtures/eql_v2_int2.sql` is a plain `jsonb`-payload table with +//! no EQL dependency; the `eql_v2_int2` domain is layered on top by casting +//! `payload` per query. + +use super::int2_values::VALUES; + +crate::scalar_fixture!("eql_v2_int2", i16, VALUES); diff --git a/tests/sqlx/src/fixtures/int2_values.rs b/tests/sqlx/src/fixtures/int2_values.rs new file mode 100644 index 00000000..74aff1c4 --- /dev/null +++ b/tests/sqlx/src/fixtures/int2_values.rs @@ -0,0 +1,33 @@ +// AUTO-GENERATED — DO NOT EDIT. +// Regenerated by `mise run build` (or `mise run codegen:domain `). +// Source of truth: tasks/codegen/types/.toml `[fixture] values`. +// This file IS committed and verified in CI (git diff --exit-code). +//! Fixture plaintext values for the int2 encrypted-domain family. +//! +//! Generated from tasks/codegen/types/int2.toml `[fixture] values` — +//! the single source of truth shared by the fixture generator +//! (`fixtures::eql_v2_int2`) and the matrix oracle +//! (`ScalarType::FIXTURE_VALUES`). + +/// Distinct plaintext values present in the `eql_v2_int2` fixture. +pub const VALUES: &[i16] = &[ + i16::MIN, + -30000, + -100, + -1, + 0, + 1, + 2, + 5, + 10, + 17, + 25, + 42, + 50, + 100, + 250, + 1000, + 9999, + 30000, + i16::MAX, +]; diff --git a/tests/sqlx/src/fixtures/mod.rs b/tests/sqlx/src/fixtures/mod.rs index ee087d1d..ac363a49 100644 --- a/tests/sqlx/src/fixtures/mod.rs +++ b/tests/sqlx/src/fixtures/mod.rs @@ -31,3 +31,9 @@ pub mod driver; pub mod int4_values; pub mod eql_v2_int4; + +/// Generated from tasks/codegen/types/int2.toml `[fixture] values`. +/// Committed and verified by CI; never hand-edit (`mise run codegen:domain int2`). +pub mod int2_values; + +pub mod eql_v2_int2; diff --git a/tests/sqlx/src/scalar_domains.rs b/tests/sqlx/src/scalar_domains.rs index e7567584..c3acc428 100644 --- a/tests/sqlx/src/scalar_domains.rs +++ b/tests/sqlx/src/scalar_domains.rs @@ -81,6 +81,15 @@ impl ScalarType for i32 { const FIXTURE_VALUES: &'static [i32] = crate::fixtures::int4_values::VALUES; } +impl ScalarType for i16 { + const PG_TYPE: &'static str = "int2"; + /// Single-sourced from `tasks/codegen/types/int2.toml` `[fixture] values` + /// via the generated `fixtures::int2_values::VALUES` const — the same list + /// the fixture generator encrypts, so the oracle cannot drift from the + /// fixture. Spans the negative boundary, the i16 signed extremes, and zero. + const FIXTURE_VALUES: &'static [i16] = crate::fixtures::int2_values::VALUES; +} + /// Per-domain capability + payload shape. Storage carries no terms, `Eq` /// adds `hm`, `Ord`/`OrdOre` add `ob`. `Ord` and `OrdOre` are deliberate /// twins — same operator surface, different SQL domain names — for the diff --git a/tests/sqlx/tests/encrypted_domain/scalars/int2.rs b/tests/sqlx/tests/encrypted_domain/scalars/int2.rs new file mode 100644 index 00000000..7a8e9331 --- /dev/null +++ b/tests/sqlx/tests/encrypted_domain/scalars/int2.rs @@ -0,0 +1,14 @@ +//! `eql_v2_int2` — the int4 reference scalar, clamped to 16 bits. +//! +//! Adding a new ordered numeric scalar (i64, f64, date, ...) is one +//! `impl ScalarType` in `tests/sqlx/src/scalar_domains.rs` plus an +//! `ordered_numeric_matrix!` invocation like this one. The matrix covers +//! everything generic over `T: ScalarType`. + +use eql_tests::ordered_numeric_matrix; + +ordered_numeric_matrix! { + suite = int2, + scalar = i16, + eql_type = "eql_v2_int2", +} diff --git a/tests/sqlx/tests/encrypted_domain/scalars/mod.rs b/tests/sqlx/tests/encrypted_domain/scalars/mod.rs index 8abc1857..f42cfb5f 100644 --- a/tests/sqlx/tests/encrypted_domain/scalars/mod.rs +++ b/tests/sqlx/tests/encrypted_domain/scalars/mod.rs @@ -2,3 +2,5 @@ //! additions (`int8`, `bool`, `date`, …) become sibling modules here. pub mod int4; + +pub mod int2; From 1d1dcc5f69db933b2175ac3ed303a8e63a796239 Mon Sep 17 00:00:00 2001 From: Toby Hede Date: Mon, 1 Jun 2026 15:17:44 +1000 Subject: [PATCH 6/6] ci(fixtures): regenerate all scalar fixtures via fixture:generate:all MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test task hand-listed only eql_v2_int4 for fixture regeneration, so the int2 matrix test's compile-time include_str! of eql_v2_int2.sql failed in CI (fixtures are gitignored and regenerated each run). Add a fixture:generate:all task that enumerates tasks/codegen/types/*.toml — the same manifests codegen:domain:all drives — and regenerates the fixture for every type declaring a [fixture] table, then call it from the test task. New scalar types are now picked up automatically. --- mise.toml | 5 ++++- tasks/fixtures.toml | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/mise.toml b/mise.toml index c513202f..8eecd6b6 100644 --- a/mise.toml +++ b/mise.toml @@ -51,6 +51,9 @@ cd tests/sqlx sqlx migrate run # Regenerate fixtures every run — they are not committed (see .gitignore). +# fixture:generate:all enumerates every scalar manifest in +# tasks/codegen/types/ that declares a [fixture] table, so new scalar types +# are picked up automatically without editing this task. # Generator encrypts via cipherstash-client directly, which needs BOTH a # ZeroKMS auth credential (CS_CLIENT_ACCESS_KEY + CS_WORKSPACE_CRN, via # AutoStrategy) AND a client key (CS_CLIENT_ID + CS_CLIENT_KEY, via @@ -58,7 +61,7 @@ sqlx migrate run # separate roles — the two pairs are not alternatives. echo "Regenerating SQLx fixtures..." cd "{{config_root}}" -mise run fixture:generate eql_v2_int4 +mise run fixture:generate:all echo "Running Rust tests..." cd tests/sqlx diff --git a/tasks/fixtures.toml b/tasks/fixtures.toml index acce7495..ecfe3ad9 100644 --- a/tasks/fixtures.toml +++ b/tasks/fixtures.toml @@ -27,3 +27,32 @@ cargo test --features fixture-gen --lib \ "fixtures::${fixture}::generate" \ -- --ignored --exact --nocapture """ + +["fixture:generate:all"] +description = "Regenerate every scalar SQLx fixture declared by a type manifest" +# Enumerates tasks/codegen/types/*.toml — the SAME manifests that +# `codegen:domain:all` drives — and regenerates the SQLx fixture for each type +# whose manifest declares a [fixture] table. This keeps the test fixtures in +# lockstep with the declared scalar types: adding a new scalar type (a new +# .toml with a [fixture] table) is picked up automatically, so the test +# task never has to hand-list each fixture. Same prerequisites as +# `fixture:generate` (Postgres up + CS_* credentials). +dir = "{{config_root}}" +run = """ +generated=0 +for manifest in tasks/codegen/types/*.toml; do + # Guard the no-match case (glob stays literal under POSIX sh). + [ -e "$manifest" ] || continue + # Only types that declare a [fixture] table have a SQLx fixture generator. + grep -qE '^\\[fixture\\]' "$manifest" || continue + token=$(basename "$manifest" .toml) + echo "Generating fixture eql_v2_${token}..." + mise run fixture:generate "eql_v2_${token}" + generated=$((generated + 1)) +done +if [ "$generated" -eq 0 ]; then + echo "No scalar manifests with a [fixture] table found in tasks/codegen/types/" >&2 + exit 1 +fi +echo "Regenerated ${generated} scalar fixture(s)." +"""