diff --git a/.changeset/eql-v3-bigint.md b/.changeset/eql-v3-bigint.md new file mode 100644 index 00000000..347c22ae --- /dev/null +++ b/.changeset/eql-v3-bigint.md @@ -0,0 +1,5 @@ +--- +'@cipherstash/stack': minor +--- + +Re-enable the EQL v3 bigint domain family now that native bigint round-tripping landed in `@cipherstash/protect-ffi` 0.28. Adds the `types.Bigint` / `types.BigintEq` / `types.BigintOrd` / `types.BigintOrdOre` factories (concrete Postgres domains `eql_v3.int8`, `eql_v3.int8_eq`, `eql_v3.int8_ord`, `eql_v3.int8_ord_ore`), their `EncryptedBigint*Column` classes, and full test-matrix + Drizzle operator coverage. Bigint columns take and decrypt to a JS `bigint`; i64 bounds (`-2^63 … 2^63 - 1`) are enforced at the protect-ffi boundary. diff --git a/.changeset/eql-v3-drizzle.md b/.changeset/eql-v3-drizzle.md new file mode 100644 index 00000000..d184c671 --- /dev/null +++ b/.changeset/eql-v3-drizzle.md @@ -0,0 +1,17 @@ +--- +"@cipherstash/stack": minor +--- + +Add EQL v3 Drizzle support at `@cipherstash/stack/eql/v3/drizzle`. A Drizzle-native +`types` namespace (same PascalCase names as `@cipherstash/stack/eql/v3`) declares +encrypted columns whose Postgres type is the semantic `eql_v3.`; the concrete +type drives the legal query operators. `createEncryptionOperatorsV3` provides +capability-checked `eq`/`ne`/`gt`/`gte`/`lt`/`lte`/`between`/`contains`/`inArray`/ +`asc`/`desc`/`and`/`or` that emit the latest two-argument `eql_v3` SQL functions with +full-envelope operands, and +`extractEncryptionSchemaV3` rebuilds the schema for `EncryptionV3`. The existing v2 +`@cipherstash/stack/drizzle` integration is unchanged. + +The v3 text-search helper is `contains`; obsolete `like`/`ilike` helpers are not +exposed because v3 free-text search is token containment rather than SQL wildcard +matching. diff --git a/.changeset/eql-v3-ffi-0-28-concrete-types.md b/.changeset/eql-v3-ffi-0-28-concrete-types.md new file mode 100644 index 00000000..8ee56528 --- /dev/null +++ b/.changeset/eql-v3-ffi-0-28-concrete-types.md @@ -0,0 +1,5 @@ +--- +'@cipherstash/stack': minor +--- + +Upgrade `@cipherstash/protect-ffi` to 0.28.0 and update EQL v3 concrete Postgres domain names to match the SQL fixture (`integer*`, `smallint*`, `bool`, `real*`, and `double*`). The public factories remain semantic (`Integer`, `Smallint`, `Boolean`, `Real`, `Double`) while their concrete domains change, so this is a minor release. diff --git a/.changeset/eql-v3-text-search.md b/.changeset/eql-v3-text-search.md new file mode 100644 index 00000000..1abbb191 --- /dev/null +++ b/.changeset/eql-v3-text-search.md @@ -0,0 +1,18 @@ +--- +"@cipherstash/stack": minor +--- + +Add the EQL v3 `text_search` authoring DSL on a new `@cipherstash/stack/eql/v3` +subpath (`types.TextSearch`, v3 `encryptedTable` / `buildEncryptConfig`). The v3 +builders emit the existing `EncryptConfig` shape, so encryption, payloads, and +query paths are unchanged at runtime. + +Also widens the public client types (`EncryptionClientConfig.schemas`, +`EncryptOptions`, `SearchTerm`/`EncryptQueryOptions`) to a structural contract so +both v2 and v3 builders are accepted by `Encryption` / `encrypt` / `decrypt` / +`encryptQuery`. This is a backward-compatible widening — existing v2 usage is +unaffected. The structural contracts themselves (`BuildableColumn`, +`BuildableQueryColumn`, `BuildableV3QueryableColumn`, `BuildableTable`, +`BuildableTableColumns`) and the `encryptModel` return-type mapper +(`EncryptedFromBuildableTable`) are exported from `@cipherstash/stack/types` so +consumers can name them. diff --git a/.changeset/eql-v3-typed-client.md b/.changeset/eql-v3-typed-client.md new file mode 100644 index 00000000..884b2ad8 --- /dev/null +++ b/.changeset/eql-v3-typed-client.md @@ -0,0 +1,29 @@ +--- +"@cipherstash/stack": minor +--- + +Add a strongly-typed EQL v3 client surface on a new `@cipherstash/stack/v3` +subpath (`EncryptionV3`, `typedClient`, `TypedEncryptionClient`). It re-exports +the v3 `types` namespace and table API (from `@cipherstash/stack/eql/v3`), so a +single import provides everything needed to author and use a v3 schema. + +Every method derives its types from the concrete `table` / `column` builder +arguments: + +- `encrypt` / `encryptQuery` pin the plaintext to the column's domain type + (`text → string`, `timestamp → Date`, …). +- `encryptQuery` constrains `queryType` to the column's capabilities and rejects + storage-only columns at compile time. +- `encryptModel` / `bulkEncryptModels` validate schema-column fields against their + inferred plaintext type (passthrough fields are untouched) and return a precise + encrypted model. +- `decryptModel` / `bulkDecryptModels` return the precise plaintext model, + reconstructing `Date` values from the encrypt-config `cast_as`. + +Because the typed methods bind to the concrete branded v3 classes, a hand-rolled +structural table/column is rejected — closing the soundness gap where a non-branded +table could be encrypted at runtime while typed as plaintext. + +Runtime behaviour is unchanged: the encrypt/query paths return the same operations +as the base client; only the model-decrypt paths add a per-column `Date` +reconstruction step. The v2 client surface (`Encryption`) is untouched. diff --git a/.changeset/eql-v3-typed-schema.md b/.changeset/eql-v3-typed-schema.md new file mode 100644 index 00000000..780e562d --- /dev/null +++ b/.changeset/eql-v3-typed-schema.md @@ -0,0 +1,7 @@ +--- +'@cipherstash/stack': minor +--- + +Add EQL v3 schema builders for supported generated SQL domains under `@cipherstash/stack/eql/v3`, exposed as the `types` namespace (one member per supported EQL v3 domain, e.g. `types.TextEq` / `types.IntegerOrd` / `types.Timestamp`), including explicit query capability metadata (`getQueryCapabilities()` / `isQueryable()`) and v3 table support in model encryption helpers (`encryptModel` / `bulkEncryptModels`). + +Also widen the accepted plaintext input type for `encrypt` / `encryptQuery` to include `Date` (via the new `Plaintext` type), so v3 `date` / `timestamp` domains can be encrypted and queried with their natural JavaScript values. diff --git a/.github/workflows/fta-v3.yml b/.github/workflows/fta-v3.yml new file mode 100644 index 00000000..15b2c1f9 --- /dev/null +++ b/.github/workflows/fta-v3.yml @@ -0,0 +1,65 @@ +name: "FTA Complexity (EQL v3)" + +# Blocking complexity gate for the EQL v3 text-search schema. Runs the Fast +# TypeScript Analyzer (fta-cli) against the v3 source directory only and fails +# the check when any file exceeds the score cap (`--score-cap` in the +# `analyze:complexity` script). FTA is pure static source analysis, so this job +# needs no build step, database, or credentials. + +on: + push: + branches: + - 'main' + paths: + - 'packages/stack/src/eql/v3/**' + # Shared match-index defaults live outside src/eql/v3 but shape every + # emitted v3 match block (load-bearing `k`/`m` ciphertext params), so edits + # here must trigger the v3 gate too. + - 'packages/stack/src/schema/match-defaults.ts' + - 'packages/stack/package.json' + - '.github/workflows/fta-v3.yml' + pull_request: + branches: + - "**" + paths: + - 'packages/stack/src/eql/v3/**' + - 'packages/stack/src/schema/match-defaults.ts' + - 'packages/stack/package.json' + - '.github/workflows/fta-v3.yml' + +permissions: + contents: read + +jobs: + fta: + name: Analyze v3 complexity + runs-on: blacksmith-4vcpu-ubuntu-2404 + + steps: + - name: Checkout Repo + uses: actions/checkout@v6 + + - uses: pnpm/action-setup@v6.0.8 + name: Install pnpm + with: + run_install: false + + - name: Install Node.js + uses: actions/setup-node@v6 + with: + node-version: 22 + cache: 'pnpm' + + # node-pty's install hook falls back to `node-gyp rebuild` when no + # linux-x64 prebuild matches. pnpm/action-setup v6 no longer ships + # node-gyp on PATH, so install it explicitly. + - name: Install node-gyp + run: npm install -g node-gyp + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + # Non-zero exit (score above the cap) fails the check — this is the + # blocking gate. No `continue-on-error`. + - name: Analyze v3 complexity + run: pnpm --filter @cipherstash/stack run analyze:complexity diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 26b874b6..fec9eaa2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -59,6 +59,9 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile + - name: Type tests (stack) + run: pnpm --filter @cipherstash/stack run test:types + - name: Lint — no hardcoded package-manager runners run: pnpm run lint:runners @@ -82,6 +85,11 @@ jobs: echo "CS_CLIENT_KEY=${{ secrets.CS_CLIENT_KEY }}" >> ./packages/stack/.env echo "CS_CLIENT_ACCESS_KEY=${{ secrets.CS_CLIENT_ACCESS_KEY }}" >> ./packages/stack/.env echo "DATABASE_URL=postgres://cipherstash:password@localhost:5432/cipherstash" >> ./packages/stack/.env + # Fail loudly if the live suites would silently skip (missing creds): + # the skip-guard in __tests__/live-gate-required.test.ts asserts the + # live gates are actually enabled when these are set. + echo "REQUIRE_LIVE=1" >> ./packages/stack/.env + echo "REQUIRE_LIVE_PG=1" >> ./packages/stack/.env - name: Create .env file in ./packages/protect-dynamodb/ run: | @@ -157,7 +165,7 @@ jobs: run: pnpm exec turbo run test:e2e --filter @cipherstash/e2e # Verifies @cipherstash/stack/wasm-inline works under Deno — i.e. the - # WASM build of protect-ffi 0.25+ and auth 0.38+ can round-trip an + # WASM build of protect-ffi 0.26+ and auth 0.40+ can round-trip an # encryption against ZeroKMS / CTS in a runtime with no native # bindings available. The deno.json deliberately omits --allow-ffi so # a silent fallback to the NAPI module is impossible. @@ -294,6 +302,11 @@ jobs: echo "CS_CLIENT_KEY=${{ secrets.CS_CLIENT_KEY }}" >> ./packages/stack/.env echo "CS_CLIENT_ACCESS_KEY=${{ secrets.CS_CLIENT_ACCESS_KEY }}" >> ./packages/stack/.env echo "DATABASE_URL=postgres://cipherstash:password@localhost:5432/cipherstash" >> ./packages/stack/.env + # Fail loudly if the live suites would silently skip (missing creds): + # the skip-guard in __tests__/live-gate-required.test.ts asserts the + # live gates are actually enabled when these are set. + echo "REQUIRE_LIVE=1" >> ./packages/stack/.env + echo "REQUIRE_LIVE_PG=1" >> ./packages/stack/.env - name: Create .env file in ./packages/protect-dynamodb/ run: | diff --git a/docs/query-api-walkthrough.md b/docs/query-api-walkthrough.md new file mode 100644 index 00000000..e582481e --- /dev/null +++ b/docs/query-api-walkthrough.md @@ -0,0 +1,77 @@ +# Query API Walkthrough — API → FFI → CipherStash Client + +How a query value travels from the public API down to the Rust SDK across the FFI boundary. Terse by design. + +## Flow + +```mermaid +flowchart TD + subgraph JS["@cipherstash/stack (TypeScript)"] + A["User query builder
ops.eq / Supabase filter / client.encryptQuery()"] + B["EncryptionClient.encryptQuery(value | terms[])
encryption/index.ts:259"] + C["EncryptQueryOperation.execute()
BatchEncryptQueryOperation.execute()"] + D["resolveIndexType() + queryTypeToFfi/QueryOp
build QueryPayload{plaintext,column,table,indexType,queryOp}"] + E["validate: validateNumericValue
assertValueIndexCompatibility"] + end + + subgraph FFI["@cipherstash/protect-ffi (Neon bindings)"] + F["JS wrapper encryptQuery / encryptQueryBulk
lib/index.cjs:155"] + G["native handle via @neon-rs/load
lib/load.cjs:9"] + H["platform .node addon
protect-ffi-darwin-arm64/index.node"] + end + + subgraph RUST["CipherStash Client (Rust SDK)"] + I["EQL term generation
ORE / match / unique / ste_vec"] + J["ZeroKMS key ops"] + end + + A --> B --> C --> E --> D --> F --> G --> H --> I + I --> J + I -- "Encrypted | EncryptedQuery" --> F + F -- "formatEncryptedResult()" --> C + C -- "SQL/PostgREST WHERE clause" --> A +``` + +## Layers + +| # | Layer | Entry point | Role | +|---|-------|-------------|------| +| 1 | Public API | `encryption/index.ts:259/270` `encryptQuery()` | Overloaded: single value → `EncryptQueryOperation`; `ScalarQueryTerm[]` → `BatchEncryptQueryOperation`. | +| 1a | Query builders | `drizzle/operators.ts:976`, `supabase/query-builder.ts:44` | `eq/gt/...` operators & deferred builders that batch-encrypt RHS values, then emit a WHERE clause. | +| 2 | Operations | `operations/encrypt-query.ts:41`, `operations/batch-encrypt-query.ts:115` | `execute()`: validate → resolve index → call FFI. `*WithLockContext` resolves `LockContextInput` via `resolveLockContext` before the FFI call. | +| 3 | EQL resolution | `helpers/infer-index-type.ts:89`, `types.ts:292` | `resolveIndexType` + `queryTypeToFfi`/`queryTypeToQueryOp` map public `QueryTypeName` → FFI `indexType`/`queryOp`. | +| 4 | FFI JS wrapper | `protect-ffi/lib/index.cjs:155` | `encryptQuery`/`encryptQueryBulk` → `wrapAsync(native.*)`. | +| 5 | Native loader | `protect-ffi/lib/load.cjs:9` | `@neon-rs/load` proxies to the platform prebuilt `.node`. | +| 6 | Rust SDK | compiled into `.node` | CipherStash Client: encryption, EQL/ORE/STE-vec term gen, ZeroKMS. Not a JS dep — shipped inside the addon. | + +## Query-type mapping (Layer 3) + +```mermaid +flowchart LR + subgraph Public["QueryTypeName"] + eq[equality] + ord[orderAndRange] + txt[freeTextSearch] + sel[steVecSelector] + trm[steVecTerm] + end + subgraph FFI["indexType / queryOp"] + u[unique] + o[ore] + m[match] + sv[ste_vec] + end + eq --> u + ord --> o + txt --> m + sel --> sv + trm --> sv +``` + +## Notes + +- **Client init:** `EncryptionClient.init()` (`encryption/index.ts:81`) calls FFI `newClient()` once; the returned `Client` handle is passed into every `encryptQuery` call. +- **`cipherstashclient`** = the CipherStash Client **Rust SDK**, compiled via Neon into the platform `.node` binary inside `@cipherstash/protect-ffi`. It performs the actual crypto and talks to ZeroKMS. +- **Result shape:** `EncryptedQueryResult` (`types.ts:175`); shaped by `formatEncryptedResult(..., returnType)` (`eql` vs raw). +- **Version:** `package.json` pins `@cipherstash/protect-ffi@0.27.0` for the current EQL v3 semantic-domain bundle. +- `packages/protect/src/ffi/*` mirrors this flow under the older `protect` package name. diff --git a/docs/superpowers/plans/2026-06-30-eql-v3-text-search-schema-plan.md b/docs/superpowers/plans/2026-06-30-eql-v3-text-search-schema-plan.md new file mode 100644 index 00000000..dfe6a84f --- /dev/null +++ b/docs/superpowers/plans/2026-06-30-eql-v3-text-search-schema-plan.md @@ -0,0 +1,1217 @@ +# EQL v3 `text_search` Schema DSL Implementation Plan + +> **Superseded (2026-07-03):** this plan built the DSL on `@cipherstash/stack/schema/v3` +> with `encryptedTextSearchColumn(...)`. That surface has since been renamed to +> `@cipherstash/stack/eql/v3` and the factories replaced by the `types` namespace +> (`types.TextSearch(...)`). Retained as a historical execution record — do not +> re-run against the current tree. + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add an EQL v3 authoring DSL (`encryptedTextSearchColumn`, plus v3 `encryptedTable` / `buildEncryptConfig`) on a new `@cipherstash/stack/schema/v3` subpath that emits the existing `EncryptConfig` shape with zero native-client changes. + +**Architecture:** A new, self-contained module at `packages/stack/src/schema/v3/index.ts` mirrors the v2 builder structure but exposes one concrete type — `EncryptedTextSearchColumn` — whose capabilities (equality + order/range + free-text match) are baked in. Its `build()` returns the **same** `ColumnSchema` a fully-configured v2 column produces, so the encryption client, payload, and query paths are untouched. The v2 module (`src/schema/index.ts`) is not modified. + +**Tech Stack:** TypeScript (ES2022, bundler module resolution), Zod 3.25.76, Vitest 3, tsup (dual ESM+CJS build), Biome (formatting/lint). + +## Review dispositions + +Code-review feedback verified against the actual files before incorporation. Verdicts and what changed: + +- **[VALID] `token_filters: []` nullish-merge edge is untested.** Confirmed `[] ?? x` evaluates to `[]` (an empty array is not nullish), so an explicit `token_filters: []` DOES override the downcase default through the `?? ` merge. v2 tests this (`schema-builders.test.ts:87-103` passes `token_filters: []` and asserts `[]` survives). The v3 plan's override test (Task 1, Step 1) deliberately omitted `token_filters` and never exercised the explicit-empty-array path. **Change:** added a dedicated `.freeTextSearch({ token_filters: [] })` override test asserting `match.token_filters === []`. +- **[VALID] Repeated `.freeTextSearch()` calls are untested.** Confirmed the sketched v3 `freeTextSearch()` (like v2 `src/schema/index.ts:353-367`) re-merges each call against a fresh defaults object (`defaultMatchOpts()` after the batch-2 factory change), NOT against current state — so `.freeTextSearch({ k: 8 }).freeTextSearch({ m: 4096 })` resets `k` back to `6` (last-call-wins-fully). This matches v2 exactly, so per the "mirror v2 exactly" global constraint we KEEP this behavior rather than switching to merge-against-current (which would diverge from v2). **Change:** added a repeated-call test that pins the v2-consistent last-call-wins-fully semantics. +- **[VALID] Type-level tests don't run in CI (pre-existing repo issue).** Confirmed `vitest.config.ts` has no `typecheck` block, `package.json` `test` script is `vitest run` (no `--typecheck`), and `.github/workflows/tests.yml` runs `pnpm run test`. Vitest only collects `*.test-d.ts` under typecheck mode, so the existing `__tests__/types.test-d.ts` is ALSO unenforced in CI today. **Change:** added Task 4, Step 4 — add a `test:types` package script. (Batch 2 finalizes the CI decision: scope typecheck + wire into CI — see below.) +- **[VALID] Dead-code remap in `InferPlaintext`/`InferEncrypted`.** In v3's flat single-type model `EncryptedV3TableColumn = { [key: string]: EncryptedTextSearchColumn }`, the `as C[K] extends EncryptedTextSearchColumn ? K : never` key-remap filters nothing (every value is already that type). v2 needs the filter because its column map also admits nested-object branches (`src/schema/index.ts:526`, `548`). **Change:** simplified both helpers to `{ [K in keyof C]: string }` / `{ [K in keyof C]: Encrypted }` with a comment marking the filter as a future extension point for when more v3 concrete types land. +- **[VALID] API surface bloat: three ways to read one literal.** v2 exposes column metadata via methods only (`getName()`, `build()` — no getters: `src/schema/index.ts:240-407`). The plan exposed the eql type via a `get eqlType` getter AND `getEqlType()` AND an exported const. **Change (partial):** dropped the `get eqlType` property getter; kept `getEqlType()` (method, matching v2 convention) and the exported `TEXT_SEARCH_EQL_TYPE` const (the single source-of-truth literal, useful for external comparison without instantiation). Updated the constraint, the interface list, and the test that asserted `col.eqlType`. +- **[VALID] Assertions.** **Changes:** switched the load-bearing/default `build()` assertions to `toStrictEqual` (catches stray `undefined` keys); switched the two column-instance type checks from the looser `toMatchTypeOf` to `toEqualTypeOf`; added a negative `@ts-expect-error` type test proving a v2 `EncryptedColumn` is rejected by the v3 `EncryptedV3TableColumn` constraint (v2/v3 column classes carry different private fields, so they are nominally non-assignable — the rejection is real). +- **[VALID] Type tightening.** **Changes:** tightened `InferPlaintext`/`InferEncrypted` constraints from `EncryptedTable` to `EncryptedTable`; inlined the pointless `const castAs: CastAs = 'string'` local into `cast_as: 'string'` (the `ColumnSchema` return type already checks the literal against `CastAs`), and dropped the now-unused `CastAs` import. + +### Batch 2 — scope decision + further review + +**SCOPE DECISION (Option A): v3 must WORK with the client.** This increment now includes widening the public client types so the v3 builders are accepted by `Encryption` / `encrypt` / `decrypt` / `encryptQuery`. Verified the runtime path is purely structural — no `instanceof` anywhere in `src/encryption/operations/*.ts`; the client only reads `column.getName()` (`encrypt.ts:53` etc.), `column.build()` (`encryption/helpers/infer-index-type.ts:11,58`), `table.tableName` (`encrypt.ts:52` etc.), `table.build().columns` (`encryption/helpers/model-helpers.ts:268,566`; dynamodb ops), and `buildEncryptConfig(...schemas)` which calls `tb.build()` (`encryption/index.ts:674`). The blocking types are in `src/types.ts`: `EncryptionClientConfig.schemas` (:98), `EncryptOptions.column`/`table` (:113-114), `SearchTerm` (:123-128) / `QueryTermBase` (:275-280) `.column`/`.table` — all typed against nominal v2 classes (private fields → v3 class not assignable). **Added Task 5** to widen these to a structural contract; runtime is untouched. + +- **[VALID — real latent bug] Shared mutable defaults.** Confirmed in the plan's sketch: `this.matchOpts = { ...DEFAULT_MATCH_OPTS }` is a SHALLOW copy, so the module-level `DEFAULT_MATCH_OPTS.tokenizer` and `.token_filters` (and the `{ kind: 'downcase' }` object inside) are shared by reference across every column built from defaults; `.freeTextSearch()` re-uses those same refs on the `?? ` fallback; and `build()` returns `this.matchOpts` directly. So a caller mutating one built config can mutate the shared defaults used by later columns (cross-column aliasing). **v2 comparison:** v2 (`src/schema/index.ts:353-367`) constructs FRESH inline object literals each `freeTextSearch()` call (no shared module-level const), so it has no cross-column aliasing — but its `build()` still returns `this.indexesValue` by reference, a milder self-aliasing latent issue. Not fixing v2 here. **Change (Task 1):** replaced the `DEFAULT_MATCH_OPTS` const with a `defaultMatchOpts()` factory (fresh nested objects per call) and made `build()` return a deep-cloned `match` block; added a two-column independent-mutation test. +- **[VALID] Missing changeset.** Confirmed the repo uses Changesets (`.changeset/config.json`, sample `.changeset/native-binary-guards.md`). Frontmatter key is the package `name`; `packages/stack/package.json` name is `@cipherstash/stack`. **Change: added Task 6** to create a `.changeset/*.md` with a **minor** bump (additive `./schema/v3` subpath + exports, plus backward-compatible type widening). +- **[VALID] Task 4 TDD label.** "Write the failing type test" contradicted "run to verify it passes" — these type tests are expected green on first run. **Change:** renamed Task 4 Step 1 to "Write type-level regression tests" and adjusted the surrounding wording so the sequencing is honest. +- **[CI — scoped path chosen, with finding] Enforce v3 type tests in CI.** Ran `pnpm exec vitest --run --typecheck __tests__/types.test-d.ts`: the `types.test-d.ts` assertions PASS (18 passed, "Type Errors: no errors"), but the package-wide typecheck surfaces **124 pre-existing "Unhandled Source Error"s** — `src/wasm-inline.ts` can't resolve `@cipherstash/auth/wasm-inline` / `@cipherstash/protect-ffi/wasm-inline` type decls, plus a type mismatch in `__tests__/wasm-inline-normalize.test.ts:69`. Root cause: `tsconfig.json` has NO `include`, so typecheck checks every file. Verified `@/encryption` does NOT import `wasm-inline.ts`, so a typecheck program rooted only at the `*.test-d.ts` files (which import `@/schema`, `@/schema/v3`, `@/types`, `@/encryption`) will not reach the broken modules. **Decision (per coordinator's "scope safely"):** SCOPE Vitest typecheck to the stack package's type-test files via a dedicated narrow `tsconfig.typecheck.json`, add a `test:types` script, and wire THAT into CI — so v3 (and the existing) type tests are enforced without forcing a repo-wide cleanup. The 124 latent wasm-inline typecheck errors are recorded as a flagged follow-up, NOT fixed here. (See Task 4 — scoped config/script in Steps 2-3, CI wiring in Step 5; flag refined in Batch 3 below.) + +### Batch 3 — widen internal consumers + tighten typecheck scoping + +- **[VALID — real gap] Task 5 widened only the public aliases, not the internal consumers.** Verified that widening `EncryptOptions` / `SearchTerm` / `QueryTermBase` to `BuildableColumn` / `BuildableTable` breaks internal code that stores those values into narrow v2-typed fields. Concretely: `operations/encrypt.ts` declares `private column: EncryptedColumn | EncryptedField` (:27) / `private table: EncryptedTable` (:28), assigns `opts.column`/`opts.table` into them (:38-39), and re-exposes them via `getOperation()` (:112-113); `operations/bulk-encrypt.ts` has the same fields (:66-67) plus the module-level `createEncryptPayloads(column: EncryptedColumn | EncryptedField, table: EncryptedTable)` (:28-29); `helpers/infer-index-type.ts` types `inferIndexType` (:10), `validateIndexType` (:55), `resolveIndexType` (:87) as `column: EncryptedColumn` and they are called with the now-widened `term.column` / `opts.column`. **Verified the contract is sufficient (no over-widening / no richer contract needed):** every one of these consumers only ever calls `.getName()`, `.tableName`, and `column.build().indexes` — all present on `BuildableColumn` / `BuildableTable` (`build(): ColumnSchema` exposes `.indexes`). **Verified NOT affected (so we don't over-reach):** `EncryptionClient` stores only `client` + `encryptConfig` (no narrow `schemas` field; methods pass `opts` straight to the operation constructors at `index.ts:203,575,298`), so no client-field change; `operations/encrypt-query.ts` / `batch-encrypt-query.ts` store the *public* widened types (`EncryptQueryOptions` / `ScalarQueryTerm[]`) with no narrow re-declaration, so they need no edit; and the MODEL path (`encrypt-model.ts`, `bulk-encrypt-models.ts`, `model-helpers.ts`) stays narrow (`EncryptedTable` / `EncryptedTable`) because the generic model methods are intentionally NOT widened — so those files are untouched. **Change:** expanded Task 5's file list + steps to also widen `operations/encrypt.ts`, `operations/bulk-encrypt.ts`, and `helpers/infer-index-type.ts` (each with the exact fields/signatures + line refs), with an explicit "do NOT widen the model path" guard. +- **[VALID] `test:types` could run runtime suites.** `vitest --run --typecheck` enables typecheck but still runs the runtime suites too (including credential/network-sensitive ones). Verified the repo's Vitest is **3.2.4** (`package.json` `"vitest": "catalog:repo"` → `3.2.4`), which supports `--typecheck.only`. **Change:** `test:types` is now `vitest --run --typecheck.only` (typecheck enabled, runtime suites skipped), with `tsconfig`/`include` set in `vitest.config.ts`; CI calls the same script. +- **[VALID] First typecheck run was unscoped.** Task 4's old Step 2 ran `vitest --run --typecheck __tests__/schema-v3.test-d.ts` BEFORE the scoped `tsconfig.typecheck.json` existed (created in the old Step 4), so the very first run would hit the 124 unrelated errors. **Change:** reordered Task 4 so the scoped `tsconfig.typecheck.json` + `vitest.config.ts` `typecheck` block + `test:types` script are created FIRST (new Step 2); every typecheck invocation (Task 4 and Task 5's failing-first run) goes through `pnpm run test:types`, which is scoped from the very first run. +- **[VALID] Duplicate `Encrypted` import.** Task 4 Step 1 already adds `import type { Encrypted } from '@/types'`; Task 5 Step 1 repeated it. **Change:** Task 5 now adds ONLY the genuinely new imports (`Encryption, EncryptionClient` from `@/encryption`; `encryptedTable as v2EncryptedTable` extending the existing `@/schema` import) and reuses the already-imported `Encrypted`. + +### Batch 4 — split the query column contract (encryptQuery must reject non-queryable fields) + +- **[VALID — type-safety regression in batch-2/3 widening] `encryptQuery` was widened too far.** Batch 2 widened `SearchTerm.column` / `QueryTermBase.column` from the nominal `EncryptedColumn` to the structural `BuildableColumn`. Verified the problem: `BuildableColumn` (`{ getName(): string; build(): ColumnSchema }`) is INTENTIONALLY also satisfied by v2 `EncryptedField` (confirmed `EncryptedField` at `src/schema/index.ts:197` has `getName()` (:235) and `build()` returning `{ cast_as, indexes: {} }` (:228)) — that structural match is REQUIRED so `encrypt()` can still target nested fields. Side effect: widening the query path to `BuildableColumn` would make `encryptQuery()` type-callable with an `encryptedField(...)`, which has no indexes and which the original nominal `EncryptedColumn` correctly rejected; it would only blow up at runtime ("no indexes configured"). **Fix:** keep `encrypt`'s storage path at `BuildableColumn` (columns AND fields), but give the query path its own narrower contract `BuildableQueryColumn = EncryptedColumn | (BuildableColumn & { getEqlType(): string })`. Verified `getEqlType()` is a sound discriminator: a `grep` for `getEqlType` across `src/` returns nothing today (v3 not implemented), v2 `EncryptedColumn`/`EncryptedField` do NOT declare it, and only v3 `EncryptedTextSearchColumn` will — so the nominal arm admits v2 queryable columns, the structural arm admits v3 queryable columns, and `EncryptedField` (no `getEqlType`, not an `EncryptedColumn`) is excluded. Verified the narrowing is safe for the storage path: the `infer-index-type.ts` functions batch-3 widened (`inferIndexType`/`validateIndexType`/`resolveIndexType`) are reached ONLY via `resolveIndexType`, imported solely by `operations/encrypt-query.ts` (:72,:165) and `operations/batch-encrypt-query.ts` (:51) — NOT by `encrypt.ts`/`bulk-encrypt.ts` — so narrowing them to `BuildableQueryColumn` cannot break field encryption. **Change:** `SearchTerm.column` + `QueryTermBase.column` → `BuildableQueryColumn`; `EncryptOptions.column` stays `BuildableColumn`; the three `infer-index-type.ts` signatures take `BuildableQueryColumn` (not `BuildableColumn`); added negative (`encryptQuery` rejects a field) + positive (`encrypt` accepts a field; `encryptQuery` accepts v2 column and v3 column) type tests. + - **Follow-up flagged (not blocking):** `getEqlType()` works as the queryability discriminator only because the sole v3 type shipping is `text_search`, which is queryable. If a future v3 *non-queryable* concrete type also carries `getEqlType()`, the structural arm would wrongly admit it. When such a type lands, switch the discriminator to a queryability-specific marker (e.g. a `readonly __queryable` brand or an explicit capability method) rather than the generic `getEqlType()`. Kept `getEqlType()` for now. + +### Batch 5 — pin the bulk-encrypt widen-site + note the WASM v3 boundary + +- **[VALID — should-fix] `bulk-encrypt.ts` widen-site was vague + mislabeled.** The batch-3 step covered the `column`/`table` re-exposure only via a conditional ("if the `*WithLockContext` variant re-exposes … widen those too") with no line ref and the wrong owning class. Verified the real site: it is `BulkEncryptOperation.getOperation()`'s RETURN TYPE at `src/encryption/operations/bulk-encrypt.ts:141-142` (`column: EncryptedColumn | EncryptedField` (:141), `table: EncryptedTable` (:142)) — destructured and consumed by `BulkEncryptOperationWithLockContext.execute()` at :168 (uses only `.getName()` / `.tableName`). It is NOT a member of the `*WithLockContext` class. **Change:** rewrote the `bulk-encrypt.ts` step to pin `:141-142` as a REQUIRED widen-site on `BulkEncryptOperation.getOperation()`, with the corrected class label, so an implementer can't leave `bulk-encrypt.ts` red. +- **[VALID — flag, not blocking] WASM-inline path does not accept v3 columns.** Verified `src/wasm-inline.ts:314-320`: `getColumnName(col: EncryptOptions['column'])` does `if (col instanceof EncryptedColumn || col instanceof EncryptedField) return col.getName(); throw …`. Confirmed (a) it STILL type-checks after the `EncryptOptions['column']` widening — an `instanceof` guard narrowing a wider union is valid TS; and (b) it is OUTSIDE the scoped typecheck graph (`@/encryption` doesn't import `wasm-inline.ts`; the `test:types` tsconfig roots only the `*.test-d.ts` files), so it does NOT make the package red. But a v3 column routed through the WASM-inline entry would hit the `else throw` at RUNTIME. This is consistent with the batch-2 "no `instanceof`" finding being explicitly scoped to `operations/*.ts`. **Change:** added a note to Task 5 (Step 3b) and the spec's known-boundaries that the WASM-inline entry does not yet accept v3 columns — a deferred, documented boundary, not a latent surprise. + +### Batch 6 — `Required` vs an explicit built type + +- **[REFUTED as a bug → applied as robustness] `Required` could fail typecheck.** The finding claimed that because `matchIndexOptsSchema` fields are `.default(...).optional()` (`src/schema/index.ts:99-105`), `Required<>` might not strip `undefined` and the plan's `defaultMatchOpts()` / `matchOpts` spread-clone could fail declaration/build typecheck. **Verified and refuted under this repo's actual config:** + - `tsconfig.json` sets `strict: true`, has **no `extends`** (no base tsconfig), and does **NOT** set `exactOptionalPropertyTypes`. + - TS's `-?` mapped modifier (`Required = { [K]-?: T[K] }`) DOES strip `undefined` when `exactOptionalPropertyTypes` is off. Reproduced empirically with the repo's TypeScript **5.9.3**: a faithful replica of the plan's exact pattern (`Required` factory + private field + the `build()` spread/clone of `tokenizer`/`token_filters` + `.map()` + non-`undefined` assignments) compiles with **ZERO errors** under `--strict` (no EOPT). It only errors (TS2532 / TS2322) when `--exactOptionalPropertyTypes` is forced on — which the repo does not use. + - **v2 precedent confirms it:** v2 already declares `match?: Required` (`src/schema/index.ts:246`, not `:247` — `:247` is `ste_vec`) and the package builds/ships under this tsconfig. So `Required` works in-repo today; the "can fail typecheck" premise is false here. + - **Decision (robustness, NOT a fix):** still adopted `BuiltMatchIndexOpts` (`{ tokenizer: NonNullable; … }`) for `defaultMatchOpts()`'s return type and the private `matchOpts` field, because it states non-null intent explicitly and is decoupled from `Required<>`'s `exactOptionalPropertyTypes`-dependent subtlety. Verified empirically that this explicit type compiles clean BOTH without AND with `exactOptionalPropertyTypes` (so it also future-proofs the new module against a later strictness bump, which `Required` would not survive). The public tuning input stays `MatchIndexOpts` (all-optional); only the internal resolved shape uses `BuiltMatchIndexOpts`. The emitted `build()` shape is unchanged (a fully-required object is assignable to the optional `ColumnSchema.indexes.match`). + +### Batch 7 — `@ts-expect-error` placement in the Batch-4 negative test + +- **[VALID — real defect] Batch-4 negative test placed `@ts-expect-error` on the wrong line.** The Batch-4 test put `// @ts-expect-error` directly above the `client.encryptQuery('…', {` call line, but the `EncryptedField`-not-assignable-to-`BuildableQueryColumn` error is a DEEP object-literal property mismatch that tsc reports on the inner `column:` argument line, not the call's first line. Since `@ts-expect-error` only suppresses the immediately-following line, the directive would be unused → **TS2578 "Unused '@ts-expect-error' directive"** AND the real error would leak from the `column:` line → `schema-v3.test-d.ts` goes red. (Hazard compounded: an implementer "fixing" the TS2578 by deleting the directive would silently delete the negative guarantee.) **Reproduced empirically** with the repo's TypeScript **5.9.3**: directive-above-the-call → TS2578 (at the directive line) + TS2741 (at the `column:` line); directive-directly-above-`column:` (multi-line) or a collapsed one-line call → both clean (no TS2578, no leak). **Fix (Variant B):** moved the `@ts-expect-error` to sit directly above the `column: v2usersWithField.profile.email,` line (kept the call multi-line), matching the placement style of Task 4's negative test, and added an inline comment explaining the deep-property-line requirement. +- **Audit of all other `@ts-expect-error` directives in the plan:** the only other one is Task 4's "rejects a v2 `EncryptedColumn` in a v3 table" test — verified it ALREADY sits directly above the offending `email: encryptedColumn('email'),` property line (the generic-constraint mismatch lands there), so it is correctly placed and needs no change. No other mis-placed directives found. + +## Global Constraints + +- **Do NOT change** the v2 module's (`packages/stack/src/schema/index.ts`) runtime behavior or the shape of its existing exported symbols. The DSL additions are purely additive. The ONLY permitted edit to this file is a backward-compatible **widening** of `buildEncryptConfig`'s parameter type to the shared structural `BuildableTable` contract (Task 5) — a pure widening (existing callers still type-check) required so the client accepts both v2 and v3 tables. (If the team prefers zero v2 edits, the documented fallback in Task 5 is to assemble the config inline in `Encryption()` instead.) +- **Runtime is structural and unchanged.** The encrypt/decrypt/query path reads only `column.getName()`, `column.build()`, `table.tableName`, `table.build().columns` — no `instanceof`. Client integration is achieved by widening the public TYPES (Task 5), not by a runtime rewrite. +- v3 builders MUST emit the existing `ColumnSchema` / `EncryptConfig` shape imported from `@/schema` — reuse the v2 types, do not redefine them. +- `cast_as` MUST be the SDK-facing literal `'string'` (NOT `'text'`). `toEqlCastAs` is a v2/wasm-inline concern and is out of scope here. +- Match-index defaults MUST mirror the v2 `freeTextSearch()` builder **exactly**: `tokenizer: { kind: 'ngram', token_length: 3 }`, `token_filters: [{ kind: 'downcase' }]`, `k: 6`, `m: 2048`, `include_original: true`. (Note: `include_original` is `true` — the v2 builder default, not the zod-schema default of `false`.) +- `unique.token_filters` defaults to `[]` (case-sensitive equality, matching v2). +- `.freeTextSearch(opts?)` is **tuning only** — it overrides match-index params and NEVER enables a capability. Merge semantics are per-top-level-key replace against the defaults (mirror v2's `opts?.x ?? default`). +- `EncryptedTextSearchColumn` records the eql type `'eql_v3.text_search'`, exposed via the `getEqlType()` method ONLY (no property getter — methods-not-getters matches the v2 builder convention). The single source-of-truth literal is the exported `TEXT_SEARCH_EQL_TYPE` const. This value is metadata for future increments and MUST be absent from `build()` output. +- v3 `encryptedTable` and `buildEncryptConfig` intentionally shadow the v2 symbol names; they live only on the `/v3` subpath. `buildEncryptConfig` emits `{ v: 1, tables }`. +- Tests live in `packages/stack/__tests__/`, named `*.test.ts` (runtime) and `*.test-d.ts` (type-level, run via the scoped `test:types` script with `--typecheck.only` — Task 4). Source imports use the `@/` alias (`@/schema`, `@/schema/v3`, `@/types`). +- Run all commands from `packages/stack/` unless noted. The test runner is `pnpm exec vitest`. +- Keep changes Biome-clean (2-space indent, single quotes, no semicolons — match the surrounding files). + +## File Structure + +- **Create:** `packages/stack/src/schema/v3/index.ts` — the entire v3 DSL: `EncryptedTextSearchColumn`, v3 `EncryptedTable`, `encryptedTextSearchColumn`, `encryptedTable`, `buildEncryptConfig`, `InferPlaintext`, `InferEncrypted`, and the `EncryptedV3TableColumn` shape type. Single focused file (the spec allows splitting later if it grows). +- **Create:** `packages/stack/__tests__/schema-v3.test.ts` — runtime behavior tests. +- **Create:** `packages/stack/__tests__/schema-v3.test-d.ts` — type-level inference tests. +- **Modify:** `packages/stack/tsup.config.ts` — add `src/schema/v3/index.ts` to the main config's `entry` array. +- **Modify:** `packages/stack/package.json` — add the `./schema/v3` export, `typesVersions` entry, and a `test:types` script. +- **Modify:** `packages/stack/src/types.ts` — define the structural `BuildableColumn` / `BuildableTable` contract and widen `EncryptionClientConfig.schemas`, `EncryptOptions`, `SearchTerm` / `QueryTermBase` to it (Task 5). +- **Modify:** `packages/stack/src/schema/index.ts` — backward-compatible widening of `buildEncryptConfig`'s parameter type ONLY (Task 5; see Global Constraints for the fallback). +- **Modify:** `packages/stack/src/encryption/operations/encrypt.ts`, `.../operations/bulk-encrypt.ts` (storage path → `BuildableColumn` / `BuildableTable`) and `.../helpers/infer-index-type.ts` (query path → `BuildableQueryColumn`) — widen the internal consumers of the widened public types (Task 5, Step 3b). +- **Create:** `packages/stack/tsconfig.typecheck.json` — narrow tsconfig (roots = `__tests__/**/*.test-d.ts`) so Vitest typecheck enforces the type tests without dragging in the 124 pre-existing wasm-inline errors (Task 4). +- **Modify:** `packages/stack/vitest.config.ts` — add a `typecheck` block (include `__tests__/**/*.test-d.ts`, `tsconfig: './tsconfig.typecheck.json'`) (Task 4). +- **Modify:** `.github/workflows/tests.yml` — run the scoped type tests in CI (Task 4). +- **Create:** `.changeset/.md` — minor bump for `@cipherstash/stack` (Task 6). + +--- + +### Task 1: `EncryptedTextSearchColumn` builder + +**Files:** +- Create: `packages/stack/src/schema/v3/index.ts` +- Test: `packages/stack/__tests__/schema-v3.test.ts` + +**Interfaces:** +- Consumes (from v2, `@/schema`): `type ColumnSchema`, `type MatchIndexOpts`, the runtime builder `encryptedColumn` (test only, for the equivalence assertion). (`CastAs` is NOT consumed — `build()` emits the bare `'string'` literal, checked by the `ColumnSchema` return type.) +- Produces: + - `class EncryptedTextSearchColumn` with: + - `constructor(columnName: string)` + - `freeTextSearch(opts?: MatchIndexOpts): this` + - `build(): ColumnSchema` + - `getName(): string` + - `getEqlType(): 'eql_v3.text_search'` (method only — no `get eqlType` property getter) + - `function encryptedTextSearchColumn(columnName: string): EncryptedTextSearchColumn` + - `const TEXT_SEARCH_EQL_TYPE = 'eql_v3.text_search'` (exported const literal) + +- [ ] **Step 1: Write the failing tests** + +Create `packages/stack/__tests__/schema-v3.test.ts`: + +```ts +import { describe, expect, it } from 'vitest' +import { encryptedColumn } from '@/schema' +import { + EncryptedTextSearchColumn, + encryptedTextSearchColumn, +} from '@/schema/v3' + +describe('eql_v3 text_search column', () => { + it('returns an EncryptedTextSearchColumn with the correct name', () => { + const col = encryptedTextSearchColumn('email') + expect(col).toBeInstanceOf(EncryptedTextSearchColumn) + expect(col.getName()).toBe('email') + }) + + it('.build() emits the pinned default config (cast_as: string + all three indexes)', () => { + const built = encryptedTextSearchColumn('email').build() + // toStrictEqual (not toEqual) so a stray `undefined` key would fail. + expect(built).toStrictEqual({ + cast_as: 'string', + indexes: { + unique: { token_filters: [] }, + ore: {}, + match: { + tokenizer: { kind: 'ngram', token_length: 3 }, + token_filters: [{ kind: 'downcase' }], + k: 6, + m: 2048, + include_original: true, + }, + }, + }) + }) + + it('LOAD-BEARING: default build() deep-equals the v2 equality+order+match column', () => { + const v3 = encryptedTextSearchColumn('email').build() + const v2 = encryptedColumn('email') + .equality() + .orderAndRange() + .freeTextSearch() + .build() + // toStrictEqual: byte-identical, no extra/undefined keys on either side. + expect(v3).toStrictEqual(v2) + }) + + it('.freeTextSearch(opts) overrides each provided key and keeps the rest as defaults', () => { + const built = encryptedTextSearchColumn('email') + .freeTextSearch({ + tokenizer: { kind: 'ngram', token_length: 4 }, + k: 8, + m: 4096, + include_original: false, + }) + .build() + expect(built.indexes.match).toEqual({ + tokenizer: { kind: 'ngram', token_length: 4 }, + // omitted -> default downcase filter retained + token_filters: [{ kind: 'downcase' }], + k: 8, + m: 4096, + include_original: false, + }) + }) + + it('.freeTextSearch({ token_filters: [] }) overrides the downcase default with an empty array', () => { + // LOAD-BEARING: `[] ?? default` evaluates to `[]` (an empty array is not + // nullish), so an explicit empty array must OVERRIDE the downcase default, + // not fall back to it. Mirrors v2 (schema-builders.test.ts). + const built = encryptedTextSearchColumn('email') + .freeTextSearch({ token_filters: [] }) + .build() + expect(built.indexes.match.token_filters).toEqual([]) + }) + + it('repeated .freeTextSearch() calls are last-call-wins-fully (each re-merges against defaults, not prior state)', () => { + // Each call re-merges against a fresh defaultMatchOpts(), not the + // accumulated matchOpts — so the second call resets k back to its default + // of 6. This is intentional: it mirrors v2 exactly. Pinned here so a future + // "merge against current state" change can't silently slip in. + const built = encryptedTextSearchColumn('email') + .freeTextSearch({ k: 8 }) + .freeTextSearch({ m: 4096 }) + .build() + expect(built.indexes.match.k).toBe(6) + expect(built.indexes.match.m).toBe(4096) + }) + + it('.freeTextSearch() is tuning-only: unique and ore indexes stay present', () => { + const built = encryptedTextSearchColumn('email') + .freeTextSearch({ k: 8 }) + .build() + expect(built.indexes.unique).toEqual({ token_filters: [] }) + expect(built.indexes.ore).toEqual({}) + }) + + it('getEqlType() returns the concrete domain name', () => { + const col = encryptedTextSearchColumn('email') + expect(col.getEqlType()).toBe('eql_v3.text_search') + }) + + it('eqlType metadata is absent from build() output', () => { + const built = encryptedTextSearchColumn('email').build() + expect(built).not.toHaveProperty('eqlType') + expect(Object.keys(built).sort()).toEqual(['cast_as', 'indexes']) + }) + + it('built columns share no mutable state: mutating one build() output does not affect another', () => { + // Guards against the shared-defaults aliasing bug: defaults come from a + // per-instance factory and build() deep-clones the match block. + const a = encryptedTextSearchColumn('a').build() + const b = encryptedTextSearchColumn('b').build() + + // Mutate every nested level of a's match block. + a.indexes.match.k = 999 + a.indexes.match.token_filters.push({ kind: 'downcase' }) + a.indexes.match.tokenizer = { kind: 'standard' } + + expect(b.indexes.match.k).toBe(6) + expect(b.indexes.match.token_filters).toEqual([{ kind: 'downcase' }]) + expect(b.indexes.match.tokenizer).toEqual({ kind: 'ngram', token_length: 3 }) + + // A second build() of an independent column is also pristine. + const c = encryptedTextSearchColumn('c').build() + expect(c.indexes.match.k).toBe(6) + expect(c.indexes.match.token_filters).toEqual([{ kind: 'downcase' }]) + }) +}) +``` + +- [ ] **Step 2: Run the tests to verify they fail** + +Run: `pnpm exec vitest run __tests__/schema-v3.test.ts` +Expected: FAIL — module resolution error `Failed to resolve import "@/schema/v3"` (the file does not exist yet). + +- [ ] **Step 3: Create the v3 module with the column builder** + +Create `packages/stack/src/schema/v3/index.ts`: + +```ts +import type { ColumnSchema, MatchIndexOpts } from '@/schema' + +/** + * The concrete EQL v3 domain name for a full-capability text column. + * Recorded as metadata for future DDL / query-dialect increments; it is + * intentionally absent from the emitted encrypt config. + */ +export const TEXT_SEARCH_EQL_TYPE = 'eql_v3.text_search' + +/** + * Fully-resolved match-index options: every field present and non-`undefined`. + * + * `MatchIndexOpts` (the user-facing tuning input) has all fields optional — + * each is `.default(...).optional()` in the zod schema, so its inferred type is + * `T | undefined`. This type pins the BUILT/resolved shape explicitly via + * `NonNullable<...>`, which states the non-null intent directly and is robust + * regardless of `Required<>`'s subtle, `exactOptionalPropertyTypes`-dependent + * stripping semantics. (v2 uses `Required` and that compiles + * fine under this repo's tsconfig — `strict: true`, NO `exactOptionalPropertyTypes` + * — so this is a clarity/robustness choice, not a fix for a present break.) + */ +type BuiltMatchIndexOpts = { + tokenizer: NonNullable + token_filters: NonNullable + k: NonNullable + m: NonNullable + include_original: NonNullable +} + +/** + * Default match-index parameters. These mirror the v2 `freeTextSearch()` + * builder defaults EXACTLY (note `include_original: true`, which is the v2 + * builder default rather than the zod-schema default of `false`). + * + * This is a FACTORY (not a shared `const`) so every caller gets fresh, unaliased + * nested objects (`tokenizer`, `token_filters` and the `{ kind: 'downcase' }` + * inside it). A shared const would be shallow-copied by `{ ...DEFAULT }`, leaving + * those nested objects aliased across every column — a caller mutating one built + * config could then corrupt the defaults used by later columns. + */ +function defaultMatchOpts(): BuiltMatchIndexOpts { + return { + tokenizer: { kind: 'ngram', token_length: 3 }, + token_filters: [{ kind: 'downcase' }], + k: 6, + m: 2048, + include_original: true, + } +} + +/** + * Builder for an `eql_v3.text_search` column. + * + * The concrete type inherently enables equality + order/range + free-text + * match — there are no capability-enabling methods. `.freeTextSearch(opts?)` + * tunes the match index only. + */ +export class EncryptedTextSearchColumn { + private readonly columnName: string + private matchOpts: BuiltMatchIndexOpts + + constructor(columnName: string) { + this.columnName = columnName + this.matchOpts = defaultMatchOpts() + } + + /** + * The concrete EQL v3 domain name. Metadata only; not emitted by `build()`. + * Method (not a property getter) to match the v2 builder convention. + */ + getEqlType(): typeof TEXT_SEARCH_EQL_TYPE { + return TEXT_SEARCH_EQL_TYPE + } + + /** + * Tune the match index. Each provided key replaces its default; omitted + * keys keep the default. This NEVER enables a capability — match is always + * on for this type. Merge semantics mirror v2's `opts?.x ?? default`. + */ + freeTextSearch(opts?: MatchIndexOpts): this { + // A fresh defaults object per call supplies the `?? ` fallbacks, so no + // nested default object is ever shared into `this.matchOpts` by reference. + const defaults = defaultMatchOpts() + this.matchOpts = { + tokenizer: opts?.tokenizer ?? defaults.tokenizer, + token_filters: opts?.token_filters ?? defaults.token_filters, + k: opts?.k ?? defaults.k, + m: opts?.m ?? defaults.m, + include_original: opts?.include_original ?? defaults.include_original, + } + return this + } + + /** Emit the encrypt-config column. Byte-identical to a v2 equality+order+match column. */ + build(): ColumnSchema { + // `cast_as` is typed `CastAs` by the `ColumnSchema` return type, so the + // literal is checked here without a redundant local annotation. + // + // Deep-clone the match block so the returned config NEVER aliases this + // builder's internal `matchOpts` (or any caller-supplied opts merged into + // it). A caller mutating the returned object cannot corrupt this builder's + // state or another column's defaults. + return { + cast_as: 'string', + indexes: { + unique: { token_filters: [] }, + ore: {}, + match: { + ...this.matchOpts, + tokenizer: { ...this.matchOpts.tokenizer }, + token_filters: this.matchOpts.token_filters.map((f) => ({ ...f })), + }, + }, + } + } + + getName(): string { + return this.columnName + } +} + +/** + * Define an `eql_v3.text_search` column. The concrete type carries all three + * capabilities (equality + order/range + free-text match). Chain + * `.freeTextSearch(opts)` to tune the match index. + */ +export function encryptedTextSearchColumn( + columnName: string, +): EncryptedTextSearchColumn { + return new EncryptedTextSearchColumn(columnName) +} +``` + +- [ ] **Step 4: Run the tests to verify they pass** + +Run: `pnpm exec vitest run __tests__/schema-v3.test.ts` +Expected: PASS (all 10 tests in this describe block green). + +- [ ] **Step 5: Commit** + +```bash +git add packages/stack/src/schema/v3/index.ts packages/stack/__tests__/schema-v3.test.ts +git commit -m "feat(stack): add eql_v3 text_search column builder" +``` + +--- + +### Task 2: v3 `encryptedTable`, `buildEncryptConfig`, and inference helpers + +**Files:** +- Modify: `packages/stack/src/schema/v3/index.ts` (append table + config + inference) +- Test: `packages/stack/__tests__/schema-v3.test.ts` (append `describe` blocks) + +**Interfaces:** +- Consumes (from v2, `@/schema`): `type ColumnSchema`, `type EncryptConfig`, `encryptConfigSchema` (test only). From `@/types`: `type Encrypted`. +- Consumes (from Task 1): `EncryptedTextSearchColumn`, `encryptedTextSearchColumn`. +- Produces: + - `type EncryptedV3TableColumn = { [key: string]: EncryptedTextSearchColumn }` + - `class EncryptedTable` with `tableName: string`, `columnBuilders: T`, and `build(): { tableName: string; columns: Record }` + - `function encryptedTable(tableName: string, columns: T): EncryptedTable & T` + - `function buildEncryptConfig(...tables: Array>): EncryptConfig` + - `type InferPlaintext>` → `{ [col]: string }` + - `type InferEncrypted>` → `{ [col]: Encrypted }` + +- [ ] **Step 1: Write the failing tests** + +Append to `packages/stack/__tests__/schema-v3.test.ts`. First add `encryptConfigSchema` to the existing `@/schema` import and the table symbols to the `@/schema/v3` import, so the file header becomes: + +```ts +import { describe, expect, it } from 'vitest' +import { encryptConfigSchema, encryptedColumn } from '@/schema' +import { + buildEncryptConfig, + EncryptedTable, + EncryptedTextSearchColumn, + encryptedTable, + encryptedTextSearchColumn, +} from '@/schema/v3' +``` + +Then append these `describe` blocks at the end of the file: + +```ts +describe('eql_v3 encryptedTable', () => { + it('creates a table exposing column builders as properties', () => { + const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), + }) + expect(users).toBeInstanceOf(EncryptedTable) + expect(users.tableName).toBe('users') + expect(users.email).toBeInstanceOf(EncryptedTextSearchColumn) + }) + + it('table.email returns the same builder instance passed in', () => { + const emailCol = encryptedTextSearchColumn('email') + const users = encryptedTable('users', { email: emailCol }) + expect(users.email).toBe(emailCol) + }) + + it('build() assembles { tableName, columns } with built column configs', () => { + const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), + }) + const built = users.build() + expect(built.tableName).toBe('users') + expect(built.columns).toStrictEqual({ + email: { + cast_as: 'string', + indexes: { + unique: { token_filters: [] }, + ore: {}, + match: { + tokenizer: { kind: 'ngram', token_length: 3 }, + token_filters: [{ kind: 'downcase' }], + k: 6, + m: 2048, + include_original: true, + }, + }, + }, + }) + }) +}) + +describe('eql_v3 buildEncryptConfig', () => { + it('produces a { v: 1, tables } config', () => { + const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), + }) + const config = buildEncryptConfig(users) + expect(config.v).toBe(1) + expect(config.tables).toHaveProperty('users') + expect(config.tables.users).toHaveProperty('email') + }) + + it('emits a config that passes encryptConfigSchema.parse()', () => { + const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), + }) + const config = buildEncryptConfig(users) + expect(() => encryptConfigSchema.parse(config)).not.toThrow() + }) + + it('supports multiple tables', () => { + const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), + }) + const posts = encryptedTable('posts', { + body: encryptedTextSearchColumn('body'), + }) + const config = buildEncryptConfig(users, posts) + expect(Object.keys(config.tables).sort()).toEqual(['posts', 'users']) + }) +}) +``` + +- [ ] **Step 2: Run the tests to verify they fail** + +Run: `pnpm exec vitest run __tests__/schema-v3.test.ts` +Expected: FAIL — `buildEncryptConfig`, `EncryptedTable`, and `encryptedTable` are not exported from `@/schema/v3` (import errors / `is not a function`). + +- [ ] **Step 3: Append the table, config builder, and inference helpers** + +Append to `packages/stack/src/schema/v3/index.ts`. First extend the import at the top of the file so it reads: + +```ts +import type { + ColumnSchema, + EncryptConfig, + MatchIndexOpts, +} from '@/schema' +import type { Encrypted } from '@/types' +``` + +Then append after `encryptedTextSearchColumn`: + +```ts +/** + * Shape of v3 table columns: every value is a top-level + * {@link EncryptedTextSearchColumn}. (Nested fields and other v3 concrete + * types are deferred to later increments.) + */ +export type EncryptedV3TableColumn = { + [key: string]: EncryptedTextSearchColumn +} + +interface TableDefinition { + tableName: string + columns: Record +} + +/** + * A v3 encrypted table. Mirrors the v2 `EncryptedTable` but only accepts v3 + * column builders. Emits the same `{ tableName, columns }` definition shape. + */ +export class EncryptedTable { + /** @internal Type-level brand so TypeScript can infer `T` from `EncryptedTable`. */ + declare readonly _columnType: T + + constructor( + public readonly tableName: string, + public readonly columnBuilders: T, + ) {} + + build(): TableDefinition { + const builtColumns: Record = {} + for (const [colName, builder] of Object.entries(this.columnBuilders)) { + builtColumns[colName] = builder.build() + } + return { + tableName: this.tableName, + columns: builtColumns, + } + } +} + +/** + * Define a v3 encrypted table. Intentionally shadows the v2 `encryptedTable` + * name but lives on the `/v3` subpath — the importer picks the model by import + * path. The returned object is also a column accessor (`users.email`). + */ +export function encryptedTable( + tableName: string, + columns: T, +): EncryptedTable & T { + const tableBuilder = new EncryptedTable( + tableName, + columns, + ) as EncryptedTable & T + + for (const [colName, colBuilder] of Object.entries(columns)) { + ;(tableBuilder as EncryptedV3TableColumn)[colName] = colBuilder + } + + return tableBuilder +} + +/** + * Build an `EncryptConfig` (`v: 1`) from one or more v3 tables. Emits the same + * shape as v2's `buildEncryptConfig`. + */ +export function buildEncryptConfig( + ...tables: Array> +): EncryptConfig { + const config: EncryptConfig = { + v: 1, + tables: {}, + } + + for (const tb of tables) { + const tableDef = tb.build() + config.tables[tableDef.tableName] = tableDef.columns + } + + return config +} + +/** + * Infer the plaintext (decrypted) shape from a v3 table schema. + * + * In v3's flat single-type column model every value is an + * {@link EncryptedTextSearchColumn}, so no key-remap filter is needed — every + * column maps to `string`. When future v3 increments add other concrete column + * types (or nested fields), reintroduce a `[K in keyof C as C[K] extends ... ]` + * filter here. + */ +export type InferPlaintext> = + T extends EncryptedTable ? { [K in keyof C]: string } : never + +/** + * Infer the encrypted shape from a v3 table schema. See {@link InferPlaintext} + * for why no key-remap filter is needed in the flat single-type model. + */ +export type InferEncrypted> = + T extends EncryptedTable ? { [K in keyof C]: Encrypted } : never +``` + +Note: `CastAs` is intentionally NOT imported — Task 1's `build()` emits the bare `'string'` literal (checked by the `ColumnSchema` return type), so no `CastAs` annotation is needed anywhere in this module. + +- [ ] **Step 4: Run the tests to verify they pass** + +Run: `pnpm exec vitest run __tests__/schema-v3.test.ts` +Expected: PASS (all runtime tests across both describe groups green). + +- [ ] **Step 5: Commit** + +```bash +git add packages/stack/src/schema/v3/index.ts packages/stack/__tests__/schema-v3.test.ts +git commit -m "feat(stack): add eql_v3 encryptedTable and buildEncryptConfig" +``` + +--- + +### Task 3: Wire the `./schema/v3` export subpath + +**Files:** +- Modify: `packages/stack/tsup.config.ts` (add the v3 entry) +- Modify: `packages/stack/package.json` (`exports` + `typesVersions`) + +**Interfaces:** +- Consumes: the module from Tasks 1-2 at `src/schema/v3/index.ts`. +- Produces: external import path `@cipherstash/stack/schema/v3` resolving to `dist/schema/v3/index.{js,cjs,d.ts,d.cts}`. + +- [ ] **Step 1: Add the v3 build entry to tsup** + +In `packages/stack/tsup.config.ts`, find the `entry` array of the FIRST (main) config object and add the v3 path. Change: + +```ts + 'src/schema/index.ts', + 'src/drizzle/index.ts', +``` + +to: + +```ts + 'src/schema/index.ts', + 'src/schema/v3/index.ts', + 'src/drizzle/index.ts', +``` + +- [ ] **Step 2: Add the `./schema/v3` export to package.json** + +In `packages/stack/package.json`, in the `exports` object, add a `./schema/v3` entry immediately after the existing `./schema` block: + +```json + "./schema/v3": { + "import": { + "types": "./dist/schema/v3/index.d.ts", + "default": "./dist/schema/v3/index.js" + }, + "require": { + "types": "./dist/schema/v3/index.d.cts", + "default": "./dist/schema/v3/index.cjs" + } + }, +``` + +(Place it between the `./schema` block and the `./types` block. Keep the existing tab indentation used in this file.) + +- [ ] **Step 3: Add the `schema/v3` typesVersions entry** + +In `packages/stack/package.json`, in the `typesVersions["*"]` object, add immediately after the existing `"schema"` entry: + +```json + "schema/v3": [ + "./dist/schema/v3/index.d.ts" + ], +``` + +- [ ] **Step 4: Build and verify the export resolves** + +Run: `pnpm run build` +Expected: build succeeds and emits `dist/schema/v3/index.js`, `dist/schema/v3/index.cjs`, `dist/schema/v3/index.d.ts`, `dist/schema/v3/index.d.cts`. + +Then verify the published export name resolves in both module systems (run from `packages/stack/`): + +```bash +node -e "const m = require('@cipherstash/stack/schema/v3'); if (typeof m.encryptedTextSearchColumn !== 'function') { throw new Error('CJS export missing'); } console.log('cjs ok')" +node --input-type=module -e "import('@cipherstash/stack/schema/v3').then(m => { if (typeof m.encryptedTextSearchColumn !== 'function') throw new Error('ESM export missing'); console.log('esm ok'); })" +``` + +Expected: prints `cjs ok` then `esm ok`. + +- [ ] **Step 5: Run the CJS-consumer regression test** + +The existing `__tests__/cjs-require.test.ts` auto-discovers every `dist/**/*.cjs` entry, so it now also exercises `dist/schema/v3/index.cjs` (no edit needed). + +Run: `pnpm exec vitest run __tests__/cjs-require.test.ts` +Expected: PASS — including the discovered `dist/schema/v3/index.cjs` entry (loads in a real Node CJS process, no externalized ESM-only `require`). + +- [ ] **Step 6: Commit** + +```bash +git add packages/stack/tsup.config.ts packages/stack/package.json +git commit -m "feat(stack): wire @cipherstash/stack/schema/v3 export subpath" +``` + +--- + +### Task 4: Type-level inference tests + CI enforcement + +**Files:** +- Create: `packages/stack/__tests__/schema-v3.test-d.ts` +- Create: `packages/stack/tsconfig.typecheck.json` (Step 4) +- Modify: `packages/stack/vitest.config.ts` (add a scoped `typecheck` block — Step 4) +- Modify: `packages/stack/package.json` (add a `test:types` script — Step 4) +- Modify: `.github/workflows/tests.yml` (run the scoped type tests in CI — Step 4) + +> Note: the v3 client-integration acceptance type-tests (`Encryption({ schemas: [v3users] })`, `client.encrypt`/`decrypt`/`encryptQuery` with v3 builders) are added in **Task 5**, which also appends to this same `schema-v3.test-d.ts`. They are enforced by the same CI wiring set up here. + +**Interfaces:** +- Consumes: `encryptedTable`, `encryptedTextSearchColumn`, `type EncryptedTextSearchColumn`, `type InferEncrypted`, `type InferPlaintext` from `@/schema/v3`; `type Encrypted` from `@/types`; `encryptedColumn` from `@/schema` (v2, for the negative `@ts-expect-error` rejection test). + +- [ ] **Step 1: Write type-level regression tests** + +These are regression/guard tests, expected to type-check green on first run (Tasks 1-2 already define the types they assert). Create `packages/stack/__tests__/schema-v3.test-d.ts`: + +```ts +import { describe, expectTypeOf, it } from 'vitest' +// v2 column builder — used only to prove the v3 table type rejects it. +import { encryptedColumn } from '@/schema' +import type { + EncryptedTextSearchColumn, + InferEncrypted, + InferPlaintext, +} from '@/schema/v3' +import { encryptedTable, encryptedTextSearchColumn } from '@/schema/v3' +import type { Encrypted } from '@/types' + +describe('eql_v3 schema type inference', () => { + it('encryptedTextSearchColumn returns an EncryptedTextSearchColumn', () => { + const col = encryptedTextSearchColumn('email') + expectTypeOf(col).toEqualTypeOf() + }) + + it('encryptedTable exposes column builders as typed properties', () => { + const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), + }) + expectTypeOf(users.email).toEqualTypeOf() + expectTypeOf(users.tableName).toBeString() + }) + + it('rejects a v2 EncryptedColumn in a v3 table (nominal private-field mismatch)', () => { + encryptedTable('users', { + // @ts-expect-error - a v2 EncryptedColumn is not an EncryptedTextSearchColumn + email: encryptedColumn('email'), + }) + }) + + it('InferPlaintext maps each column to string', () => { + const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), + name: encryptedTextSearchColumn('name'), + }) + type Plaintext = InferPlaintext + expectTypeOf().toEqualTypeOf<{ email: string; name: string }>() + }) + + it('InferEncrypted maps each column to Encrypted', () => { + const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), + }) + type Enc = InferEncrypted<typeof users> + expectTypeOf<Enc>().toEqualTypeOf<{ email: Encrypted }>() + }) +}) +``` + +- [ ] **Step 2: Create the SCOPED typecheck config + `test:types` script (BEFORE any typecheck run)** + +`.test-d.ts` files run ONLY in Vitest typecheck mode, and today nothing runs typecheck in CI (`package.json` `test` = `vitest run`; `tests.yml` runs `pnpm run test`). So neither this `schema-v3.test-d.ts` nor the pre-existing `types.test-d.ts` is enforced — a wrong inferred shape would NOT fail the build. + +**Verified finding (do not skip):** `tsconfig.json` has NO `include`, so a naive package-wide `vitest --typecheck` checks every file and surfaces **124 pre-existing "Unhandled Source Error"s** unrelated to v3 — `src/wasm-inline.ts` cannot resolve `@cipherstash/auth/wasm-inline` / `@cipherstash/protect-ffi/wasm-inline` type decls, plus a type mismatch at `__tests__/wasm-inline-normalize.test.ts:69`. (The `*.test-d.ts` assertions themselves pass.) So we set up the SCOPED config FIRST, so the very first typecheck a worker runs is already narrowed and green. Verified `@/encryption` does not import `wasm-inline.ts`, so a program rooted at the `*.test-d.ts` files does not reach the broken modules. + +a) Create `packages/stack/tsconfig.typecheck.json` — narrow roots so tsc only pulls the type-test files and what they actually import: + +```json +{ + "extends": "./tsconfig.json", + "include": ["__tests__/**/*.test-d.ts"] +} +``` + +b) Add a scoped `typecheck` block to `packages/stack/vitest.config.ts`: + +```ts +import { resolve } from 'node:path' +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + resolve: { + alias: { + '@/': resolve(__dirname, './src') + '/', + }, + }, + test: { + typecheck: { + // Scoped tsconfig keeps the 124 pre-existing wasm-inline typecheck errors + // out of scope (tracked as a follow-up). Run via the `test:types` script + // with `--typecheck.only` so the runtime suites do NOT also execute. + tsconfig: './tsconfig.typecheck.json', + include: ['__tests__/**/*.test-d.ts'], + }, + }, +}) +``` + +c) Add a `test:types` script to `packages/stack/package.json`. Use `--typecheck.only` (Vitest **3.2.4**, confirmed in the repo, supports it) so ONLY the type tests run — `--typecheck` alone would ALSO run the runtime suites (including the credential/network-sensitive ones): + +```json + "test:types": "vitest --run --typecheck.only", +``` + +- [ ] **Step 3: Run the scoped type tests to verify they pass** + +Run: `pnpm run test:types` +Expected: PASS — `schema-v3.test-d.ts` type-checks (and the existing `types.test-d.ts` does too); ZERO errors; no runtime suites executed. (If `@/schema/v3` types were missing or `InferPlaintext`/`InferEncrypted` produced the wrong shape, `toEqualTypeOf` would surface a type error here. Tasks 1-2 already define these, so it type-checks green on first run.) + +> **STOP-gate:** if this scoped run still reports the `wasm-inline` errors (e.g. a type-test transitively imports a broken module), narrow `tsconfig.typecheck.json` further (add an `exclude` for `src/wasm-inline.ts` / `__tests__/wasm-inline-normalize.test.ts`) until the run is clean BEFORE wiring CI. Do not wire a red command into CI. + +- [ ] **Step 4: Run the full v3 runtime suite as a guard** + +Run: `pnpm exec vitest run __tests__/schema-v3.test.ts` +Expected: PASS (all runtime tests still green — no regression from the type-test file). + +- [ ] **Step 5: Wire the scoped type tests into CI** + +In `.github/workflows/tests.yml`, add a step in the `run-tests` job (after `Install dependencies`): + +```yaml + - name: Type tests (stack) + run: pnpm --filter @cipherstash/stack run test:types +``` + +> **Flagged follow-up (NOT fixed here):** the 124 pre-existing package-wide typecheck errors (missing `@cipherstash/{auth,protect-ffi}/wasm-inline` type declarations + `wasm-inline-normalize.test.ts:69`) are a separate cleanup. Enabling typecheck repo-wide / unscoped should be a dedicated follow-up after those are resolved. + +- [ ] **Step 6: Commit** + +```bash +git add packages/stack/__tests__/schema-v3.test-d.ts packages/stack/tsconfig.typecheck.json packages/stack/vitest.config.ts packages/stack/package.json .github/workflows/tests.yml +git commit -m "test(stack): type-level tests for eql_v3 schema DSL + scoped CI typecheck" +``` + +--- + +### Task 5: Widen the public client types to a structural contract (Option A — v3 works with the client) + +**Goal:** make the v3 builders first-class with the client API (`Encryption`, `encrypt`, `decrypt`, `encryptQuery`) by widening the blocking public types to a structural contract that BOTH v2 and v3 builders satisfy. Runtime is untouched (verified structural — no `instanceof` on the encrypt/decrypt/query path). + +**Decision — v3 keeps its OWN `EncryptedTable` class** (not reuse v2's): v3 needs a different column constraint (`EncryptedV3TableColumn`) and a simpler `build()` (no nested-field / ste_vec rewriting). v2 and v3 classes are nominally distinct (private fields) but BOTH structurally satisfy `BuildableColumn` / `BuildableTable`, which is exactly what a single widened type can accept. Reusing v2's class would not help anyway — v3 columns don't satisfy v2's `EncryptedTableColumn` generic constraint. + +**Verified structural members the client actually touches** (so the contract is minimal and correct): +- Column: `getName(): string` (`operations/encrypt.ts:53` etc.), `build(): ColumnSchema` (`helpers/infer-index-type.ts:11,58`). +- Table: `tableName: string` (`operations/encrypt.ts:52` etc.), `build(): { tableName; columns }` (`helpers/model-helpers.ts:268,566`; dynamodb ops; and `buildEncryptConfig(...schemas)` → `tb.build()` at `encryption/index.ts:674`). + +**Files:** +- Modify: `packages/stack/src/types.ts` — define `BuildableColumn` / `BuildableTable`; widen `EncryptionClientConfig.schemas`, `EncryptOptions`, `SearchTerm`, `QueryTermBase`. +- Modify: `packages/stack/src/schema/index.ts` — widen `buildEncryptConfig`'s parameter type ONLY (backward-compatible; the file already does `import type { Encrypted } from '@/types'`, so referencing `BuildableTable` from `@/types` adds no new module cycle). +- Modify: `packages/stack/src/encryption/operations/encrypt.ts` — internal consumer of the widened `EncryptOptions` (Step 3b). +- Modify: `packages/stack/src/encryption/operations/bulk-encrypt.ts` — internal consumer of the widened `EncryptOptions` (Step 3b). +- Modify: `packages/stack/src/encryption/helpers/infer-index-type.ts` — internal consumer of the widened query-term `column` (Step 3b). +- Test: append a `describe` block to `packages/stack/__tests__/schema-v3.test-d.ts`. + +> **Internal-consumer note (verified):** widening the public aliases is NOT enough on its own — three internal files store/accept those values in narrow v2 types and would fail typecheck. They are widened in Step 3b. Verified NOT needing changes (do not over-widen): the `EncryptionClient` class (stores only `client` + `encryptConfig`, passes `opts` straight through); `operations/encrypt-query.ts` / `batch-encrypt-query.ts` (store the public widened types directly, no narrow re-declaration); and the entire MODEL path (`encrypt-model.ts`, `bulk-encrypt-models.ts`, `model-helpers.ts`), which intentionally stays narrow because the generic model methods are NOT widened in this increment. + +**Interfaces (define in `src/types.ts`, alongside the other public client types):** + +```ts +import type { + ColumnSchema, + EncryptedColumn, + // ...existing imports (EncryptedColumn already imported; EncryptedField, EncryptedTable, EncryptedTableColumn) +} from '@/schema' + +/** Structural contract for a column builder the client can consume for STORAGE + * (`encrypt`). Satisfied by v2 `EncryptedColumn` / `EncryptedField` AND v3 + * `EncryptedTextSearchColumn` — fields ARE encryptable, so this stays wide. */ +export interface BuildableColumn { + getName(): string + build(): ColumnSchema +} + +/** Structural contract for a column the client can consume for QUERIES + * (`encryptQuery` / search terms). Narrower than `BuildableColumn`: it must + * EXCLUDE non-queryable `EncryptedField` (a field has no indexes). A v2 + * `EncryptedColumn` qualifies via the nominal arm; a v3 queryable concrete + * type qualifies via the `getEqlType()` structural arm; `EncryptedField` (no + * `getEqlType`, not an `EncryptedColumn`) is rejected. */ +export type BuildableQueryColumn = + | EncryptedColumn + | (BuildableColumn & { getEqlType(): string }) + +/** Structural contract for a table builder the client can consume. Satisfied by + * v2 and v3 `EncryptedTable` alike. */ +export interface BuildableTable { + tableName: string + build(): { tableName: string; columns: Record<string, ColumnSchema> } +} +``` + +- [ ] **Step 1: Write the failing client-integration acceptance tests** + +Append to `packages/stack/__tests__/schema-v3.test-d.ts`. First extend its imports — `import type { Encrypted } from '@/types'` and `encryptedColumn` from `@/schema` are ALREADY present from Task 4, so add ONLY the genuinely new symbols: + +```ts +// NEW imports for Task 5 (Encrypted + encryptedColumn already imported in Task 4): +import { Encryption, EncryptionClient } from '@/encryption' +// extend the existing `import { encryptedColumn } from '@/schema'` to also bring in: +import { + encryptedColumn, + encryptedField, + encryptedTable as v2EncryptedTable, +} from '@/schema' +``` + +Then append: + +```ts +describe('eql_v3 client integration (type-level acceptance)', () => { + const v3users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), + }) + + it('Encryption accepts a v3 schema', () => { + expectTypeOf(Encryption).toBeCallableWith({ schemas: [v3users] }) + }) + + it('encrypt accepts a v3 table + column', () => { + const client = {} as EncryptionClient + expectTypeOf(client.encrypt).toBeCallableWith('alice@example.com', { + table: v3users, + column: v3users.email, + }) + }) + + it('encryptQuery accepts a v3 table + column', () => { + const client = {} as EncryptionClient + expectTypeOf(client.encryptQuery).toBeCallableWith('alice@example.com', { + table: v3users, + column: v3users.email, + }) + }) + + it('decrypt accepts an Encrypted value (round-trip target type; schema-independent)', () => { + const client = {} as EncryptionClient + expectTypeOf(client.decrypt).toBeCallableWith({} as Encrypted) + }) + + it('BACKWARD COMPAT: v2 tables/columns still satisfy the widened types', () => { + const v2users = v2EncryptedTable('users', { + email: encryptedColumn('email').equality(), + }) + expectTypeOf(Encryption).toBeCallableWith({ schemas: [v2users] }) + const client = {} as EncryptionClient + expectTypeOf(client.encrypt).toBeCallableWith('alice@example.com', { + table: v2users, + column: v2users.email, + }) + // a v2 EncryptedColumn is STILL queryable (nominal arm of BuildableQueryColumn) + expectTypeOf(client.encryptQuery).toBeCallableWith('alice@example.com', { + table: v2users, + column: v2users.email, + }) + }) + + it('a non-queryable v2 EncryptedField is encryptable but NOT queryable', () => { + const v2usersWithField = v2EncryptedTable('users', { + profile: { email: encryptedField('email') }, + }) + const client = {} as EncryptionClient + + // POSITIVE: a field IS encryptable (storage path = BuildableColumn) + expectTypeOf(client.encrypt).toBeCallableWith('alice@example.com', { + table: v2usersWithField, + column: v2usersWithField.profile.email, + }) + + // NEGATIVE: a field is NOT queryable. The query path uses + // BuildableQueryColumn, which excludes EncryptedField (no indexes). If the + // query path were instead widened to BuildableColumn (the rejected + // Batch-2/3 design), this call would compile and only fail at runtime with + // "no indexes configured" — so this test guards against that re-widening. + // + // The mismatch is a DEEP object-literal property error, so tsc reports it on + // the `column:` line — the `@ts-expect-error` MUST sit directly above that + // line (not above the call), or you get TS2578 "unused directive" + the real + // error leaking. (Mirror of Task 4's v2-column-rejected test placement.) + client.encryptQuery('alice@example.com', { + table: v2usersWithField, + // @ts-expect-error - EncryptedField is not assignable to BuildableQueryColumn + column: v2usersWithField.profile.email, + }) + }) +}) +``` + +- [ ] **Step 2: Run the type tests to verify they fail** + +Run: `pnpm run test:types` (script added in Task 4) +Expected: FAIL — the v3 `Encryption` / `encrypt` / `encryptQuery` assertions error because `EncryptedTextSearchColumn` / v3 `EncryptedTable` are not assignable to the still-nominal pre-Task-5 v2 types. These clear after Step 3. + +(The v2 backward-compat `encrypt`/`encryptQuery` assertions and `decrypt` already pass. The field tests also already pass: pre-Task-5 `QueryTermBase.column` is the original nominal `EncryptedColumn`, so the `@ts-expect-error` on querying a field is already a valid suppression — those tests stay green through Step 3, guarding against any future re-widening of the query path to `BuildableColumn`.) + +- [ ] **Step 3a: Define the structural contract and widen the public types** + +In `packages/stack/src/types.ts`: +1. Add `ColumnSchema` to the existing `@/schema` type import (`EncryptedColumn` is already imported there). +2. Add the `BuildableColumn` / `BuildableQueryColumn` / `BuildableTable` definitions (above). +3. Widen the blocking surfaces. Note the **storage vs query split**: `EncryptOptions` (encrypt) accepts `BuildableColumn` (columns AND fields), while `SearchTerm` / `QueryTermBase` (encryptQuery) accept the narrower `BuildableQueryColumn` so a non-queryable field is rejected at the type layer: + +```ts +export type EncryptionClientConfig = { + schemas: AtLeastOneCsTable<BuildableTable> + config?: ClientConfig +} + +export type EncryptOptions = { + column: BuildableColumn // storage: fields are encryptable, so stays wide + table: BuildableTable +} + +export type SearchTerm = { + value: JsPlaintext + column: BuildableQueryColumn // query: excludes non-queryable EncryptedField + table: BuildableTable + returnType?: EncryptedReturnType +} + +export type QueryTermBase = { + column: BuildableQueryColumn // query: excludes non-queryable EncryptedField + table: BuildableTable + queryType?: QueryTypeName + returnType?: EncryptedReturnType +} +``` + +In `packages/stack/src/schema/index.ts`, widen `buildEncryptConfig`'s parameter (the ONLY permitted edit to the v2 module — pure widening, no behavior change): + +```ts +import type { BuildableTable, Encrypted } from '@/types' + +export function buildEncryptConfig( + ...protectTables: Array<BuildableTable> +): EncryptConfig { + // body unchanged — already only calls tb.build() +} +``` + +> **Do NOT touch** the generic schema-aware model methods `encryptModel<S extends EncryptedTableColumn>` / `bulkEncryptModels` (`encryption/index.ts:394,489`) or `EncryptedFromSchema` / `InferPlaintext` / `EncryptedFields`. They must keep inferring `S` from `EncryptedTable<S>` so v2 field-level inference is preserved. v3 support for the model methods is a future increment (v3 columns don't satisfy `EncryptedTableColumn`). The `EncryptedTable<T> & T` accessor and v2 inference must be re-verified green (Step 4). +> +> **Fallback (if the team forbids ANY v2-module edit):** instead of widening `buildEncryptConfig`, leave it as-is and change `Encryption()` (`encryption/index.ts`) to assemble the config inline from the structural `schemas` (`for (const tb of schemas) { const d = tb.build(); config.tables[d.tableName] = d.columns }`). This keeps `src/schema/index.ts` pristine at the cost of ~6 duplicated lines in the client. + +- [ ] **Step 3b: Widen the internal consumers the public change forces** + +After Step 3a, the package will NOT typecheck until the internal consumers that store/accept the widened values are widened too. All three only call `.getName()`, `.tableName`, and `column.build().indexes` — so `BuildableColumn` / `BuildableTable` are sufficient (no richer contract). Widen exactly these, and nothing in the model path: + +1. **`src/encryption/operations/encrypt.ts`** — `EncryptOperation`: + - field `private column: EncryptedColumn | EncryptedField` (:27) → `private column: BuildableColumn` + - field `private table: EncryptedTable<EncryptedTableColumn>` (:28) → `private table: BuildableTable` + - `getOperation()` return type's `column` / `table` (:112-113) → `BuildableColumn` / `BuildableTable` + - imports: add `BuildableColumn, BuildableTable` to the `@/types` import; drop the now-unused `EncryptedColumn, EncryptedField, EncryptedTable, EncryptedTableColumn` from the `@/schema` import (if nothing else uses them). + - The constructor already takes `opts: EncryptOptions` (widened) — no signature change; only the field/return types. + +2. **`src/encryption/operations/bulk-encrypt.ts`** — `BulkEncryptOperation`: + - module fn `createEncryptPayloads(column: EncryptedColumn | EncryptedField, table: EncryptedTable<EncryptedTableColumn>, ...)` (:28-29) → `column: BuildableColumn, table: BuildableTable` + - fields `private column` (:66) / `private table` (:67) → `BuildableColumn` / `BuildableTable` + - **`BulkEncryptOperation.getOperation()` return type (:141-142)** — REQUIRED widen-site: it re-exposes `column: EncryptedColumn | EncryptedField` (:141) and `table: EncryptedTable<EncryptedTableColumn>` (:142) → `BuildableColumn` / `BuildableTable`. (This return value is destructured and consumed by `BulkEncryptOperationWithLockContext.execute()` at :168, which only uses `.getName()` / `.tableName`.) Do NOT miss this — leaving it narrow keeps `bulk-encrypt.ts` red. (Note: this is `getOperation()`'s return type on `BulkEncryptOperation`, NOT a member of the `*WithLockContext` class.) + - same import swap (`@/types` gains `BuildableColumn, BuildableTable`; drop unused `@/schema` narrow types). + +3. **`src/encryption/helpers/infer-index-type.ts`** — index inference (QUERY path only — verified reached solely via `resolveIndexType` from `encrypt-query.ts:72,165` and `batch-encrypt-query.ts:51`, NOT from the storage path): + - `inferIndexType(column: EncryptedColumn)` (:10), `validateIndexType(column: EncryptedColumn, ...)` (:55), `resolveIndexType(column: EncryptedColumn, ...)` (:87) → `column: BuildableQueryColumn` in all three (NOT `BuildableColumn` — these run only for queries, so they should reject non-queryable fields too). + - import: replace `import type { EncryptedColumn } from '@/schema'` with `import type { BuildableQueryColumn } from '@/types'`. + - Bodies are unchanged: they read `column.build().indexes` and `column.getName()`, both available on `BuildableQueryColumn` (its `EncryptedColumn` arm and its `BuildableColumn & …` arm each provide `getName()` + `build()`). + +> **Do NOT widen the model path.** `encrypt-model.ts`, `bulk-encrypt-models.ts`, and `model-helpers.ts` keep `EncryptedTable<EncryptedTableColumn>` / `EncryptedTable<S>` — they are fed by the generic `encryptModel<S extends EncryptedTableColumn>` methods which are intentionally left narrow (preserves v2 inference; v3 model support is a later increment). Widening them would over-reach and could disturb inference. +> +> **WASM-inline boundary (documented, not fixed here).** `src/wasm-inline.ts:314-320` has `getColumnName(col)` doing `if (col instanceof EncryptedColumn || col instanceof EncryptedField) … else throw`. After widening `EncryptOptions['column']` to `BuildableColumn` this still type-checks (an `instanceof` guard narrows a wider type fine) and `wasm-inline.ts` is outside the scoped typecheck graph (`@/encryption` does not import it; the `test:types` tsconfig roots only the `*.test-d.ts` files), so it does NOT turn the package red — but a v3 column routed through the WASM-inline entry would hit the `else throw` at RUNTIME. The batch-2 "no `instanceof`" finding was explicitly scoped to `operations/*.ts`; the WASM-inline entry does not yet accept v3 columns, which is a deferred, documented boundary (not a latent surprise). + +- [ ] **Step 4: Run the full suite to verify pass + no regression** + +```bash +pnpm run test:types # v3 acceptance + v2 backward-compat + existing types.test-d.ts all green +pnpm exec vitest run # all runtime tests still pass (encryptModel inference unaffected) +``` + +Expected: all green. In particular `__tests__/types.test-d.ts` (v2 inference, `EncryptedFromSchema`, `encryptModel` schema-aware return types) must still pass — proving the widening did not narrow or break v2. + +- [ ] **Step 5: Commit** + +```bash +git add packages/stack/src/types.ts packages/stack/src/schema/index.ts \ + packages/stack/src/encryption/operations/encrypt.ts \ + packages/stack/src/encryption/operations/bulk-encrypt.ts \ + packages/stack/src/encryption/helpers/infer-index-type.ts \ + packages/stack/__tests__/schema-v3.test-d.ts +git commit -m "feat(stack): widen public client types so v3 builders work with the client" +``` + +--- + +### Task 6: Changeset + +**Files:** +- Create: `.changeset/eql-v3-text-search.md` + +**Interfaces:** none (release metadata only). The repo uses Changesets (`.changeset/config.json`); frontmatter keys are package `name`s. `packages/stack/package.json` name is `@cipherstash/stack`. + +- [ ] **Step 1: Create the changeset** + +Create `.changeset/eql-v3-text-search.md` (minor — additive `./schema/v3` subpath + exports, plus backward-compatible public-type widening; no breaking changes): + +```md +--- +"@cipherstash/stack": minor +--- + +Add the EQL v3 `text_search` authoring DSL on a new `@cipherstash/stack/schema/v3` +subpath (`encryptedTextSearchColumn`, v3 `encryptedTable` / `buildEncryptConfig`). +The v3 builders emit the existing `EncryptConfig` shape, so encryption, payloads, +and query paths are unchanged at runtime. + +Also widens the public client types (`EncryptionClientConfig.schemas`, +`EncryptOptions`, `SearchTerm`/`EncryptQueryOptions`) to a structural contract so +both v2 and v3 builders are accepted by `Encryption` / `encrypt` / `decrypt` / +`encryptQuery`. This is a backward-compatible widening — existing v2 usage is +unaffected. +``` + +- [ ] **Step 2: Verify the changeset is valid** + +Run: `pnpm exec changeset status` (from the repo root) +Expected: lists a pending `minor` bump for `@cipherstash/stack`, no errors. (If `changeset status` is unavailable in this environment, confirm the frontmatter key exactly matches the package `name` and the bump keyword is one of `major`/`minor`/`patch`.) + +- [ ] **Step 3: Commit** + +```bash +git add .changeset/eql-v3-text-search.md +git commit -m "chore(stack): changeset for eql_v3 text_search DSL (minor)" +``` + +--- + +## Self-Review + +**Spec coverage:** +- Public API (`encryptedTextSearchColumn`, v3 `encryptedTable`, v3 `buildEncryptConfig`) → Tasks 1-2. +- `.freeTextSearch(opts?)` as tuning-only with per-key replace merge → Task 1, Steps 1 & 3 (override + tuning-only tests). +- Pinned `build()` output (`cast_as: 'string'` + three indexes, defaults) → Task 1, default-config test. +- Load-bearing v2/v3 equivalence assertion → Task 1, "LOAD-BEARING" test (imports v2 `encryptedColumn`). +- `'eql_v3.text_search'` via `getEqlType()` method (no property getter), absent from `build()` → Task 1, getEqlType + absence tests. +- `buildEncryptConfig` → valid `EncryptConfig` (`v: 1`) passing `encryptConfigSchema.parse` → Task 2. +- `InferPlaintext` / `InferEncrypted` → Task 4 (type) + Task 2 (definition). +- New `@cipherstash/stack/schema/v3` subpath (exports + tsup) → Task 3. +- No shared mutable state (per-instance defaults + cloned `build()`) → Task 1 (`defaultMatchOpts()` factory + independent-mutation test). +- **Client integration (Option A):** widen public types AND the internal consumers they force so v3 builders work with `Encryption` / `encrypt` / `decrypt` / `encryptQuery`; storage path (`encrypt`, `operations/encrypt.ts`, `operations/bulk-encrypt.ts`) uses `BuildableColumn` (accepts fields), query path (`encryptQuery`, `helpers/infer-index-type.ts`) uses the narrower `BuildableQueryColumn` (rejects non-queryable fields); model path left narrow; v2 backward-compat preserved → Task 5 (Steps 3a + 3b). +- Type tests enforced in CI (scoped typecheck, `--typecheck.only`) → Task 4, Steps 2-3 (scoped config + script) and Step 5 (CI wiring). +- Changeset (minor) for the public-surface change → Task 6. +- v2 module: runtime + existing exported shapes untouched; ONLY a backward-compatible `buildEncryptConfig` param widening (Task 5) — see Global Constraints. +- Non-goals (v3 in the generic model methods, DDL, transition tooling, query dialect, other concrete types, nested fields) → not implemented (correctly out of scope). + +**Placeholder scan:** No TBD/TODO/"handle edge cases" present; every code step contains complete, runnable code. + +**Type consistency:** `EncryptedTextSearchColumn`, `encryptedTextSearchColumn`, `EncryptedTable`, `encryptedTable`, `buildEncryptConfig`, `EncryptedV3TableColumn`, `InferPlaintext`, `InferEncrypted`, `TEXT_SEARCH_EQL_TYPE`, the `defaultMatchOpts()` factory, `getEqlType()` (method only — no property getter; also the query-path discriminator in `BuildableQueryColumn`), and the structural `BuildableColumn` / `BuildableQueryColumn` / `BuildableTable` contract (Task 5) are used identically across tasks and tests. `build()` returns `ColumnSchema`; `EncryptedTable.build()` returns `{ tableName, columns: Record<string, ColumnSchema> }`, matching both `buildEncryptConfig`'s consumption and the `BuildableTable` contract. + +--- + +## Execution Handoff + +Plan complete and saved to `docs/superpowers/plans/2026-06-30-eql-v3-text-search-schema-plan.md`. Two execution options: + +1. **Subagent-Driven (recommended)** — dispatch a fresh subagent per task, review between tasks, fast iteration. +2. **Inline Execution** — execute tasks in this session using executing-plans, batch execution with checkpoints. + +Which approach? +</content> +</invoke> diff --git a/docs/superpowers/plans/2026-07-01-eql-v3-typed-schema.md b/docs/superpowers/plans/2026-07-01-eql-v3-typed-schema.md new file mode 100644 index 00000000..98229d34 --- /dev/null +++ b/docs/superpowers/plans/2026-07-01-eql-v3-typed-schema.md @@ -0,0 +1,1541 @@ +# EQL v3 Typed Schema Implementation Plan + +> **Superseded (2026-07-03):** this plan added per-domain `encrypted<Domain>Column` +> builders on `@cipherstash/stack/schema/v3`. Those builders are now the `types` +> namespace (`types.TextEq` / `types.Int4Ord` / …) on `@cipherstash/stack/eql/v3`. +> Retained as a historical execution record — do not re-run against the current tree. + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Expand `@cipherstash/stack/schema/v3` from the current `text_search` slice to all generated EQL v3 SQL domains with domain-precise builders, explicit query capability metadata, and structurally widened client/model support while preserving v2 behavior. + +**Architecture:** Keep v3 isolated under `packages/stack/src/schema/v3/index.ts` and the `@cipherstash/stack/schema/v3` export. Implement one v3 column class/builder per EQL v3 domain using a shared internal column base parameterized by the full literal domain definition (`eqlType`, `castAs`, capabilities), not by capabilities alone. Client query typing should accept v3 columns only when they expose capability metadata and `isQueryable(): true`; storage-only v3 columns remain encryptable but not queryable. + +**Tech Stack:** TypeScript, Vitest runtime tests, Vitest type tests, tsup package build, `@cipherstash/protect-ffi`, existing `ColumnSchema`/`EncryptConfig` v1 config shape. + +--- + +## File Structure Map + +**Modify:** +- `packages/stack/src/schema/v3/index.ts` + - Owns all v3 builders, domain metadata, table builder, `buildEncryptConfig`, and v3 `InferPlaintext` / `InferEncrypted`. +- `packages/stack/src/types.ts` + - Tightens `BuildableQueryColumn`; widens model schema typing from v2-only columns to structural buildable table columns while preserving literal schema keys through each table's `_columnType` brand. +- `packages/stack/src/encryption/index.ts` + - Updates `encryptModel` and `bulkEncryptModels` generics and table parameter types to accept v3 tables. +- `packages/stack/src/encryption/helpers/model-helpers.ts` + - Replaces v2 `EncryptedTable<EncryptedTableColumn>` annotations with structural `BuildableTable`. +- `packages/stack/src/encryption/operations/encrypt-model.ts` + - Replaces v2 table annotations with `BuildableTable`. +- `packages/stack/src/encryption/operations/bulk-encrypt-models.ts` + - Replaces v2 table annotations with `BuildableTable`. +- `packages/stack/src/wasm-inline.ts` + - Widens WASM schema config type to structural buildable tables if needed; keeps structural `getColumnName`. +- `packages/stack/vitest.config.ts` + - Fixes or isolates `@cipherstash/protect-ffi/wasm-inline` import resolution for `wasm-inline-column-name.test.ts`. +- `packages/stack/package.json` + - Keep existing `./schema/v3` export and `db:eql-v3:install`; add no new subpath unless tests prove required. + +**Modify tests:** +- `packages/stack/__tests__/schema-v3.test.ts` + - Runtime builder/config/capability tests for all v3 domains. +- `packages/stack/__tests__/schema-v3.test-d.ts` + - Type-level tests for all builders, queryability, inferred plaintext/encrypted model shapes, and v2 compatibility. +- `packages/stack/__tests__/schema-v3-client.test.ts` + - Live env-gated client tests expanded to representative storage-only/equality/order/match/search columns. +- `packages/stack/__tests__/schema-v3-pg.test.ts` + - Keep guarded Postgres `text_search` coverage; add representative non-text EQL v3 domains when the SQL fixture supports them. +- `packages/stack/__tests__/wasm-inline-column-name.test.ts` + - Keep focused column-name test; update import style only if needed after Vitest resolution fix. + +**Create:** +- `.changeset/eql-v3-typed-schema.md` + - Public API addition for `@cipherstash/stack`. + +**Do not modify:** +- `packages/stack/src/schema/index.ts` + - v2 schema API remains stable. +- Payload contracts and Result shapes. +- Any code that logs plaintext. + +--- + +### Task 1: Baseline And Source-Of-Truth Snapshot + +**Files:** +- Read only: `packages/stack/src/schema/v3/index.ts` +- Read only: `<eql-v3-worktree>/crates/eql-bindings/src/v3/inventory.rs` +- Read only: `<eql-v3-worktree>/crates/eql-bindings/schema/v3/*.json` + +- [ ] **Step 1: Confirm branch and dirty state** + +Run: + +```bash +git status --short --branch +``` + +Expected: + +```text +## feat/eql-v3-text-search-schema...origin/feat/eql-v3-text-search-schema +``` + +Also expect currently untracked v3 live-test/helper files and the `packages/stack/package.json` script change. Do not revert them. + +- [ ] **Step 2: Confirm complete v3 domain inventory** + +Run: + +```bash +sed -n '1,140p' <eql-v3-worktree>/crates/eql-bindings/src/v3/inventory.rs +``` + +Expected: inventory includes exactly these domain identifiers: + +```text +int4 int4_eq int4_ord_ore int4_ord +int2 int2_eq int2_ord_ore int2_ord +int8 int8_eq int8_ord_ore int8_ord +date date_eq date_ord_ore date_ord +timestamptz timestamptz_eq timestamptz_ord_ore timestamptz_ord +numeric numeric_eq numeric_ord_ore numeric_ord +text text_eq text_match text_ord_ore text_ord text_search +bool +float4 float4_eq float4_ord_ore float4_ord +float8 float8_eq float8_ord_ore float8_ord +``` + +- [ ] **Step 3: Confirm capability rule from JSON schemas** + +Run: + +```bash +rg '"required"' <eql-v3-worktree>/crates/eql-bindings/schema/v3 -n +``` + +Expected: +- Schemas with required `hm` support equality. +- Schemas with required `ob` support order/range. +- Schemas with required `bf` support free-text search. +- Those exposing only `v`, `i`, `c` are storage-only. + +--- + +### Task 2: Write Failing Runtime Tests For All v3 Builders + +**Files:** +- Modify: `packages/stack/__tests__/schema-v3.test.ts` + +- [ ] **Step 1: Add import coverage for every new builder and class** + +Replace the v3 import block with this full import list: + +```ts +import { + buildEncryptConfig, + EncryptedBoolColumn, + EncryptedDateColumn, + EncryptedDateEqColumn, + EncryptedDateOrdColumn, + EncryptedDateOrdOreColumn, + EncryptedFloat4Column, + EncryptedFloat4EqColumn, + EncryptedFloat4OrdColumn, + EncryptedFloat4OrdOreColumn, + EncryptedFloat8Column, + EncryptedFloat8EqColumn, + EncryptedFloat8OrdColumn, + EncryptedFloat8OrdOreColumn, + EncryptedInt2Column, + EncryptedInt2EqColumn, + EncryptedInt2OrdColumn, + EncryptedInt2OrdOreColumn, + EncryptedInt4Column, + EncryptedInt4EqColumn, + EncryptedInt4OrdColumn, + EncryptedInt4OrdOreColumn, + EncryptedInt8Column, + EncryptedInt8EqColumn, + EncryptedInt8OrdColumn, + EncryptedInt8OrdOreColumn, + EncryptedNumericColumn, + EncryptedNumericEqColumn, + EncryptedNumericOrdColumn, + EncryptedNumericOrdOreColumn, + EncryptedTable, + EncryptedTextColumn, + EncryptedTextEqColumn, + EncryptedTextMatchColumn, + EncryptedTextOrdColumn, + EncryptedTextOrdOreColumn, + EncryptedTextSearchColumn, + EncryptedTimestamptzColumn, + EncryptedTimestamptzEqColumn, + EncryptedTimestamptzOrdColumn, + EncryptedTimestamptzOrdOreColumn, + encryptedBoolColumn, + encryptedDateColumn, + encryptedDateEqColumn, + encryptedDateOrdColumn, + encryptedDateOrdOreColumn, + encryptedFloat4Column, + encryptedFloat4EqColumn, + encryptedFloat4OrdColumn, + encryptedFloat4OrdOreColumn, + encryptedFloat8Column, + encryptedFloat8EqColumn, + encryptedFloat8OrdColumn, + encryptedFloat8OrdOreColumn, + encryptedInt2Column, + encryptedInt2EqColumn, + encryptedInt2OrdColumn, + encryptedInt2OrdOreColumn, + encryptedInt4Column, + encryptedInt4EqColumn, + encryptedInt4OrdColumn, + encryptedInt4OrdOreColumn, + encryptedInt8Column, + encryptedInt8EqColumn, + encryptedInt8OrdColumn, + encryptedInt8OrdOreColumn, + encryptedNumericColumn, + encryptedNumericEqColumn, + encryptedNumericOrdColumn, + encryptedNumericOrdOreColumn, + encryptedTable, + encryptedTextColumn, + encryptedTextEqColumn, + encryptedTextMatchColumn, + encryptedTextOrdColumn, + encryptedTextOrdOreColumn, + encryptedTextSearchColumn, + encryptedTimestamptzColumn, + encryptedTimestamptzEqColumn, + encryptedTimestamptzOrdColumn, + encryptedTimestamptzOrdOreColumn, +} from '@/schema/v3' +``` + +- [ ] **Step 2: Add a complete table-driven domain test** + +Add this test near the top of `schema-v3.test.ts`: + +```ts +const domainCases = [ + ['eql_v3.int4', encryptedInt4Column, EncryptedInt4Column, 'number', {}, { equality: false, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.int4_eq', encryptedInt4EqColumn, EncryptedInt4EqColumn, 'number', { unique: { token_filters: [] } }, { equality: true, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.int4_ord_ore', encryptedInt4OrdOreColumn, EncryptedInt4OrdOreColumn, 'number', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.int4_ord', encryptedInt4OrdColumn, EncryptedInt4OrdColumn, 'number', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.int2', encryptedInt2Column, EncryptedInt2Column, 'number', {}, { equality: false, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.int2_eq', encryptedInt2EqColumn, EncryptedInt2EqColumn, 'number', { unique: { token_filters: [] } }, { equality: true, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.int2_ord_ore', encryptedInt2OrdOreColumn, EncryptedInt2OrdOreColumn, 'number', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.int2_ord', encryptedInt2OrdColumn, EncryptedInt2OrdColumn, 'number', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.int8', encryptedInt8Column, EncryptedInt8Column, 'bigint', {}, { equality: false, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.int8_eq', encryptedInt8EqColumn, EncryptedInt8EqColumn, 'bigint', { unique: { token_filters: [] } }, { equality: true, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.int8_ord_ore', encryptedInt8OrdOreColumn, EncryptedInt8OrdOreColumn, 'bigint', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.int8_ord', encryptedInt8OrdColumn, EncryptedInt8OrdColumn, 'bigint', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.date', encryptedDateColumn, EncryptedDateColumn, 'date', {}, { equality: false, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.date_eq', encryptedDateEqColumn, EncryptedDateEqColumn, 'date', { unique: { token_filters: [] } }, { equality: true, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.date_ord_ore', encryptedDateOrdOreColumn, EncryptedDateOrdOreColumn, 'date', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.date_ord', encryptedDateOrdColumn, EncryptedDateOrdColumn, 'date', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.timestamptz', encryptedTimestamptzColumn, EncryptedTimestamptzColumn, 'date', {}, { equality: false, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.timestamptz_eq', encryptedTimestamptzEqColumn, EncryptedTimestamptzEqColumn, 'date', { unique: { token_filters: [] } }, { equality: true, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.timestamptz_ord_ore', encryptedTimestamptzOrdOreColumn, EncryptedTimestamptzOrdOreColumn, 'date', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.timestamptz_ord', encryptedTimestamptzOrdColumn, EncryptedTimestamptzOrdColumn, 'date', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.numeric', encryptedNumericColumn, EncryptedNumericColumn, 'number', {}, { equality: false, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.numeric_eq', encryptedNumericEqColumn, EncryptedNumericEqColumn, 'number', { unique: { token_filters: [] } }, { equality: true, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.numeric_ord_ore', encryptedNumericOrdOreColumn, EncryptedNumericOrdOreColumn, 'number', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.numeric_ord', encryptedNumericOrdColumn, EncryptedNumericOrdColumn, 'number', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.text', encryptedTextColumn, EncryptedTextColumn, 'string', {}, { equality: false, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.text_eq', encryptedTextEqColumn, EncryptedTextEqColumn, 'string', { unique: { token_filters: [] } }, { equality: true, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.text_match', encryptedTextMatchColumn, EncryptedTextMatchColumn, 'string', { match: { tokenizer: { kind: 'ngram', token_length: 3 }, token_filters: [{ kind: 'downcase' }], k: 6, m: 2048, include_original: true } }, { equality: false, orderAndRange: false, freeTextSearch: true }], + ['eql_v3.text_ord_ore', encryptedTextOrdOreColumn, EncryptedTextOrdOreColumn, 'string', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.text_ord', encryptedTextOrdColumn, EncryptedTextOrdColumn, 'string', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.bool', encryptedBoolColumn, EncryptedBoolColumn, 'boolean', {}, { equality: false, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.float4', encryptedFloat4Column, EncryptedFloat4Column, 'number', {}, { equality: false, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.float4_eq', encryptedFloat4EqColumn, EncryptedFloat4EqColumn, 'number', { unique: { token_filters: [] } }, { equality: true, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.float4_ord_ore', encryptedFloat4OrdOreColumn, EncryptedFloat4OrdOreColumn, 'number', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.float4_ord', encryptedFloat4OrdColumn, EncryptedFloat4OrdColumn, 'number', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.float8', encryptedFloat8Column, EncryptedFloat8Column, 'number', {}, { equality: false, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.float8_eq', encryptedFloat8EqColumn, EncryptedFloat8EqColumn, 'number', { unique: { token_filters: [] } }, { equality: true, orderAndRange: false, freeTextSearch: false }], + ['eql_v3.float8_ord_ore', encryptedFloat8OrdOreColumn, EncryptedFloat8OrdOreColumn, 'number', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], + ['eql_v3.float8_ord', encryptedFloat8OrdColumn, EncryptedFloat8OrdColumn, 'number', { ore: {} }, { equality: true, orderAndRange: true, freeTextSearch: false }], +] as const + +describe('eql_v3 concrete domain columns', () => { + it.each(domainCases)('%s builder exposes name, config, type, and capabilities', (eqlType, factory, Klass, castAs, indexes, capabilities) => { + const col = factory('value') + expect(col).toBeInstanceOf(Klass) + expect(col.getName()).toBe('value') + expect(col.getEqlType()).toBe(eqlType) + expect(col.getQueryCapabilities()).toStrictEqual(capabilities) + expect(col.isQueryable()).toBe(Object.values(capabilities).some(Boolean)) + expect(col.build()).toStrictEqual({ cast_as: castAs, indexes }) + expect(col.build()).not.toHaveProperty('eqlType') + expect(col.build()).not.toHaveProperty('queryCapabilities') + }) +}) +``` + +- [ ] **Step 3: Keep and adapt existing `text_search` tests** + +Keep existing `text_search` tests, but add: + +```ts +expect(encryptedTextSearchColumn('email').getQueryCapabilities()).toStrictEqual({ + equality: true, + orderAndRange: true, + freeTextSearch: true, +}) +expect(encryptedTextSearchColumn('email').isQueryable()).toBe(true) +``` + +- [ ] **Step 4: Run runtime test and confirm failure** + +Run: + +```bash +pnpm --filter @cipherstash/stack vitest run __tests__/schema-v3.test.ts +``` + +Expected: FAIL with missing exports such as `encryptedInt4Column` and missing methods `getQueryCapabilities` / `isQueryable`. + +--- + +### Task 3: Implement v3 Domain Column Base And Builders + +**Files:** +- Modify: `packages/stack/src/schema/v3/index.ts` + +- [ ] **Step 1: Add shared capability and full domain-definition types** + +Add near the top of `schema/v3/index.ts`: + +```ts +export type QueryCapabilities = Readonly<{ + equality: boolean + orderAndRange: boolean + freeTextSearch: boolean +}> + +type PlaintextKind = 'string' | 'number' | 'bigint' | 'boolean' | 'date' + +type V3DomainDefinition = Readonly<{ + eqlType: `eql_v3.${string}` + castAs: PlaintextKind + capabilities: QueryCapabilities +}> + +type QueryableFlag<D extends V3DomainDefinition> = + D['capabilities'] extends { equality: false; orderAndRange: false; freeTextSearch: false } + ? false + : true + +const STORAGE_ONLY = { + equality: false, + orderAndRange: false, + freeTextSearch: false, +} as const + +const EQUALITY_ONLY = { + equality: true, + orderAndRange: false, + freeTextSearch: false, +} as const + +const ORDER_AND_RANGE = { + equality: true, + orderAndRange: true, + freeTextSearch: false, +} as const + +const MATCH_ONLY = { + equality: false, + orderAndRange: false, + freeTextSearch: true, +} as const + +const TEXT_SEARCH = { + equality: true, + orderAndRange: true, + freeTextSearch: true, +} as const + +const INT4 = { eqlType: 'eql_v3.int4', castAs: 'number', capabilities: STORAGE_ONLY } as const +const INT4_EQ = { eqlType: 'eql_v3.int4_eq', castAs: 'number', capabilities: EQUALITY_ONLY } as const +const INT4_ORD_ORE = { eqlType: 'eql_v3.int4_ord_ore', castAs: 'number', capabilities: ORDER_AND_RANGE } as const +const INT4_ORD = { eqlType: 'eql_v3.int4_ord', castAs: 'number', capabilities: ORDER_AND_RANGE } as const +``` + +Every concrete domain must get its own `as const` domain definition object. This is load-bearing: empty subclasses are not nominal in TypeScript, so the base class must carry literal `eqlType`/`castAs` data in its private definition field. Do not type columns as `EncryptedV3Column<typeof STORAGE_ONLY>`; that makes all storage-only domains mutually assignable and breaks plaintext inference. + +- [ ] **Step 2: Add config helpers** + +Add these helpers before column classes: + +```ts +function indexesForCapabilities(capabilities: QueryCapabilities): ColumnSchema['indexes'] { + const indexes: ColumnSchema['indexes'] = {} + + if (capabilities.equality && !capabilities.orderAndRange) { + indexes.unique = { token_filters: [] } + } + + if (capabilities.orderAndRange) { + indexes.ore = {} + } + + if (capabilities.freeTextSearch) { + const match = defaultMatchOpts() + indexes.match = { + ...match, + tokenizer: { ...match.tokenizer }, + token_filters: match.token_filters.map((f) => ({ ...f })), + } + } + + return indexes +} + +function isQueryableCapabilities(capabilities: QueryCapabilities): boolean { + return capabilities.equality || capabilities.orderAndRange || capabilities.freeTextSearch +} +``` + +Important: `orderAndRange` domains use `{ ore: {} }` only. Do not also emit `unique`; the EQL v3 `ob` key supports equality and range. + +- [ ] **Step 3: Add generic base class** + +Add: + +```ts +class EncryptedV3Column<D extends V3DomainDefinition> { + constructor( + private readonly columnName: string, + private readonly definition: D, + ) {} + + getName(): string { + return this.columnName + } + + getEqlType(): D['eqlType'] { + return this.definition.eqlType + } + + getQueryCapabilities(): D['capabilities'] { + return this.definition.capabilities + } + + isQueryable(): QueryableFlag<D> { + return isQueryableCapabilities(this.definition.capabilities) as QueryableFlag<D> + } + + build(): ColumnSchema { + return { + cast_as: this.definition.castAs, + indexes: indexesForCapabilities(this.definition.capabilities), + } + } +} +``` + +Because `definition` is a private base field whose type includes literal `eqlType` and `castAs`, `EncryptedBoolColumn` is no longer assignable to `EncryptedInt8Column` even if both are storage-only. + +- [ ] **Step 4: Keep text-search override semantics** + +Change `EncryptedTextSearchColumn` to extend the base but keep its existing `matchOpts`, `freeTextSearch(opts?)`, and deep-clone behavior. + +Expected final shape: + +```ts +const TEXT_SEARCH_DOMAIN = { + eqlType: TEXT_SEARCH_EQL_TYPE, + castAs: 'string', + capabilities: TEXT_SEARCH, +} as const + +export class EncryptedTextSearchColumn extends EncryptedV3Column<typeof TEXT_SEARCH_DOMAIN> { + private matchOpts: BuiltMatchIndexOpts + + constructor(columnName: string) { + super(columnName, TEXT_SEARCH_DOMAIN) + this.matchOpts = defaultMatchOpts() + } + + freeTextSearch(opts?: MatchIndexOpts): this { + const defaults = defaultMatchOpts() + this.matchOpts = { + tokenizer: opts?.tokenizer ?? defaults.tokenizer, + token_filters: opts?.token_filters ?? defaults.token_filters, + k: opts?.k ?? defaults.k, + m: opts?.m ?? defaults.m, + include_original: opts?.include_original ?? defaults.include_original, + } + return this + } + + override build(): ColumnSchema { + return { + cast_as: 'string', + indexes: { + unique: { token_filters: [] }, + ore: {}, + match: { + ...this.matchOpts, + tokenizer: { ...this.matchOpts.tokenizer }, + token_filters: this.matchOpts.token_filters.map((f) => ({ ...f })), + }, + }, + } + } +} +``` + +- [ ] **Step 5: Add all concrete classes and builder functions** + +Add these class/function pairs exactly, using the domain constants from Step 1: + +```ts +export class EncryptedInt4Column extends EncryptedV3Column<typeof INT4> {} +export const encryptedInt4Column = (columnName: string) => new EncryptedInt4Column(columnName, INT4) + +export class EncryptedInt4EqColumn extends EncryptedV3Column<typeof INT4_EQ> {} +export const encryptedInt4EqColumn = (columnName: string) => new EncryptedInt4EqColumn(columnName, INT4_EQ) + +export class EncryptedInt4OrdOreColumn extends EncryptedV3Column<typeof INT4_ORD_ORE> {} +export const encryptedInt4OrdOreColumn = (columnName: string) => new EncryptedInt4OrdOreColumn(columnName, INT4_ORD_ORE) + +export class EncryptedInt4OrdColumn extends EncryptedV3Column<typeof INT4_ORD> {} +export const encryptedInt4OrdColumn = (columnName: string) => new EncryptedInt4OrdColumn(columnName, INT4_ORD) +``` + +Repeat this exact pattern for: + +```text +Int2: int2, int2_eq, int2_ord_ore, int2_ord -> castAs number +Int8: int8, int8_eq, int8_ord_ore, int8_ord -> castAs bigint +Date: date, date_eq, date_ord_ore, date_ord -> castAs date +Timestamptz: timestamptz, timestamptz_eq, timestamptz_ord_ore, timestamptz_ord -> castAs date +Numeric: numeric, numeric_eq, numeric_ord_ore, numeric_ord -> castAs number +Text: text, text_eq, text_match, text_ord_ore, text_ord -> castAs string +Bool: bool -> castAs boolean +Float4: float4, float4_eq, float4_ord_ore, float4_ord -> castAs number +Float8: float8, float8_eq, float8_ord_ore, float8_ord -> castAs number +``` + +For `text_match`, use `MATCH_ONLY`. + +After adding all classes, add a compile-time guard test in `schema-v3.test-d.ts`: + +```ts +it('v3 domain classes remain nominal by literal domain definition', () => { + const int8 = encryptedInt8Column('id64') + const bool = encryptedBoolColumn('active') + + expectTypeOf(int8).not.toEqualTypeOf<typeof bool>() + + // @ts-expect-error - storage-only bool is not assignable to storage-only int8 + const invalid: typeof int8 = bool + void invalid +}) +``` + +- [ ] **Step 6: Run runtime schema tests** + +Run: + +```bash +pnpm --filter @cipherstash/stack vitest run __tests__/schema-v3.test.ts +``` + +Expected: PASS for schema-v3 runtime tests. If class constructor visibility fails, make the base class constructor `public`. + +--- + +### Task 4: Generalize v3 Table Column Types And Inference + +**Files:** +- Modify: `packages/stack/src/schema/v3/index.ts` +- Modify: `packages/stack/__tests__/schema-v3.test-d.ts` + +- [ ] **Step 1: Replace single-column v3 table type** + +In `schema/v3/index.ts`, replace: + +```ts +export type EncryptedV3TableColumn = { + [key: string]: EncryptedTextSearchColumn +} +``` + +with: + +```ts +export type AnyEncryptedV3Column = + | EncryptedInt4Column + | EncryptedInt4EqColumn + | EncryptedInt4OrdOreColumn + | EncryptedInt4OrdColumn + | EncryptedInt2Column + | EncryptedInt2EqColumn + | EncryptedInt2OrdOreColumn + | EncryptedInt2OrdColumn + | EncryptedInt8Column + | EncryptedInt8EqColumn + | EncryptedInt8OrdOreColumn + | EncryptedInt8OrdColumn + | EncryptedDateColumn + | EncryptedDateEqColumn + | EncryptedDateOrdOreColumn + | EncryptedDateOrdColumn + | EncryptedTimestamptzColumn + | EncryptedTimestamptzEqColumn + | EncryptedTimestamptzOrdOreColumn + | EncryptedTimestamptzOrdColumn + | EncryptedNumericColumn + | EncryptedNumericEqColumn + | EncryptedNumericOrdOreColumn + | EncryptedNumericOrdColumn + | EncryptedTextColumn + | EncryptedTextEqColumn + | EncryptedTextMatchColumn + | EncryptedTextOrdOreColumn + | EncryptedTextOrdColumn + | EncryptedTextSearchColumn + | EncryptedBoolColumn + | EncryptedFloat4Column + | EncryptedFloat4EqColumn + | EncryptedFloat4OrdOreColumn + | EncryptedFloat4OrdColumn + | EncryptedFloat8Column + | EncryptedFloat8EqColumn + | EncryptedFloat8OrdOreColumn + | EncryptedFloat8OrdColumn + +export type EncryptedV3TableColumn = { + [key: string]: AnyEncryptedV3Column +} +``` + +- [ ] **Step 2: Add plaintext inference by literal domain definition** + +Add: + +```ts +type PlaintextFromKind<K extends PlaintextKind> = + K extends 'string' + ? string + : K extends 'number' + ? number + : K extends 'bigint' + ? bigint + : K extends 'boolean' + ? boolean + : K extends 'date' + ? Date + : never + +type PlaintextForColumn<C> = + C extends EncryptedV3Column<infer D> + ? PlaintextFromKind<D['castAs']> + : never +``` + +Do not infer plaintext from a long subclass conditional. Empty subclasses that share the same base generic are structurally assignable; the private base field carrying the full literal domain definition is the stable type discriminator. + +Then replace `InferPlaintext` with: + +```ts +export type InferPlaintext<T extends EncryptedTable<EncryptedV3TableColumn>> = + T extends EncryptedTable<infer C> + ? { [K in keyof C]: PlaintextForColumn<C[K]> } + : never +``` + +Keep `InferEncrypted` as `{ [K in keyof C]: Encrypted }`. + +- [ ] **Step 3: Add type tests for mixed v3 table inference** + +In `schema-v3.test-d.ts`, add: + +```ts +it('InferPlaintext maps v3 concrete domains to plaintext TypeScript types', () => { + const metrics = encryptedTable('metrics', { + name: encryptedTextColumn('name'), + age: encryptedInt4Column('age'), + id64: encryptedInt8Column('id64'), + active: encryptedBoolColumn('active'), + createdAt: encryptedTimestamptzColumn('created_at'), + score: encryptedFloat8Column('score'), + }) + + type Plaintext = InferPlaintext<typeof metrics> + + expectTypeOf<Plaintext>().toEqualTypeOf<{ + name: string + age: number + id64: bigint + active: boolean + createdAt: Date + score: number + }>() +}) +``` + +- [ ] **Step 4: Run type tests and confirm expected failure before query type fixes** + +Run: + +```bash +pnpm --filter @cipherstash/stack test:types +``` + +Expected at this point: may FAIL because `BuildableQueryColumn` still accepts storage-only v3 columns. Continue to Task 5 before requiring a full pass. + +--- + +### Task 5: Require v3 Query Capability Metadata For `encryptQuery` + +**Files:** +- Modify: `packages/stack/src/types.ts` +- Modify: `packages/stack/__tests__/schema-v3.test-d.ts` + +- [ ] **Step 1: Tighten `BuildableQueryColumn`** + +In `types.ts`, replace: + +```ts +export type BuildableQueryColumn = + | EncryptedColumn + | (BuildableColumn & { getEqlType(): string }) +``` + +with: + +```ts +export interface BuildableV3QueryableColumn extends BuildableColumn { + getEqlType(): string + getQueryCapabilities(): { + equality: boolean + orderAndRange: boolean + freeTextSearch: boolean + } + isQueryable(): true +} + +export type BuildableQueryColumn = EncryptedColumn | BuildableV3QueryableColumn +``` + +- [ ] **Step 2: Add positive and negative queryability type tests** + +In `schema-v3.test-d.ts`, add: + +```ts +it('encryptQuery accepts queryable v3 columns with explicit capability metadata', () => { + const users = encryptedTable('users', { + emailEq: encryptedTextEqColumn('email_eq'), + emailMatch: encryptedTextMatchColumn('email_match'), + emailSearch: encryptedTextSearchColumn('email_search'), + createdAt: encryptedTimestamptzOrdColumn('created_at'), + }) + const client = {} as EncryptionClient + + expectTypeOf(client.encryptQuery).toBeCallableWith('alice@example.com', { + table: users, + column: users.emailEq, + }) + expectTypeOf(client.encryptQuery).toBeCallableWith('ali', { + table: users, + column: users.emailMatch, + queryType: 'freeTextSearch', + }) + expectTypeOf(client.encryptQuery).toBeCallableWith(new Date(), { + table: users, + column: users.createdAt, + queryType: 'orderAndRange', + }) + expectTypeOf(client.encryptQuery).toBeCallableWith('alice@example.com', { + table: users, + column: users.emailSearch, + queryType: 'equality', + }) +}) + +it('encryptQuery rejects storage-only v3 columns at compile time', () => { + const users = encryptedTable('users', { + email: encryptedTextColumn('email'), + active: encryptedBoolColumn('active'), + }) + const client = {} as EncryptionClient + + client.encryptQuery('alice@example.com', { + table: users, + // @ts-expect-error - storage-only v3 text column is not queryable + column: users.email, + }) + + client.encryptQuery(true, { + table: users, + // @ts-expect-error - storage-only v3 bool column is not queryable + column: users.active, + }) +}) +``` + +- [ ] **Step 3: Preserve literal `isQueryable()` inference in the base class** + +In `schema/v3/index.ts`, storage-only class instances must have `isQueryable(): false` inferred through `QueryableFlag<D>`, and queryable class instances must have `isQueryable(): true`. Do not add per-class overrides unless TypeScript proves the base method fails; 40 overrides add noise and are not needed when domain constants remain `as const`. + +- [ ] **Step 4: Add runtime capability-misuse tests** + +In `schema-v3.test.ts`, import `resolveIndexType` from `@/encryption/helpers/infer-index-type` and add tests that call the query helper path with unsupported query types: + +```ts +it('throws when querying a storage-only v3 column at runtime', () => { + const raw = encryptedTextColumn('raw') + expect(() => resolveIndexType(raw as never)).toThrow(/no indexes configured/) +}) + +it('throws when a query type is not configured on a queryable v3 column', () => { + const matchOnly = encryptedTextMatchColumn('body') + expect(() => resolveIndexType(matchOnly, 'equality')).toThrow( + /Index type "unique" is not configured/, + ) + expect(() => resolveIndexType(matchOnly, 'orderAndRange')).toThrow( + /Index type "ore" is not configured/, + ) +}) +``` + +- [ ] **Step 5: Run type tests** + +Run: + +```bash +pnpm --filter @cipherstash/stack test:types +``` + +Expected: PASS for `schema-v3.test-d.ts` and existing v2 compatibility type tests. + +Do not make these tests green by weakening `toEqualTypeOf` assertions to `toMatchTypeOf`. The failure mode being guarded here is over-broad inference, so exact type equality is required. + +--- + +### Task 6: Structurally Widen Model Encryption For v3 Tables + +**Files:** +- Modify: `packages/stack/src/types.ts` +- Modify: `packages/stack/src/encryption/index.ts` +- Modify: `packages/stack/src/encryption/helpers/model-helpers.ts` +- Modify: `packages/stack/src/encryption/operations/encrypt-model.ts` +- Modify: `packages/stack/src/encryption/operations/bulk-encrypt-models.ts` +- Modify: `packages/stack/__tests__/schema-v3.test-d.ts` + +- [ ] **Step 1: Add structural model schema types** + +In `types.ts`, add after `BuildableTable`: + +```ts +export type BuildableTableColumns<T extends BuildableTable> = + T extends { readonly _columnType: infer C } + ? C extends Record<string, unknown> + ? C + : never + : never + +export type EncryptedFromBuildableTable<T, Table extends BuildableTable> = { + [K in keyof T]: [K] extends [keyof BuildableTableColumns<Table>] + ? null extends T[K] + ? Encrypted | null + : Encrypted + : T[K] +} +``` + +This must use the table's existing `_columnType` brand, not `build().columns`. `build()` intentionally returns `Record<string, ColumnSchema>`, which erases literal keys and would mark every model field as encrypted. Keep existing `EncryptedFromSchema` for v2 backward compatibility. + +- [ ] **Step 2: Update client model method signatures** + +In `encryption/index.ts`, change: + +```ts +encryptModel< + T extends Record<string, unknown>, + S extends EncryptedTableColumn = EncryptedTableColumn, +>( + input: T, + table: EncryptedTable<S>, +): EncryptModelOperation<EncryptedFromSchema<T, S>> +``` + +to: + +```ts +encryptModel< + T extends Record<string, unknown>, + Table extends BuildableTable, +>( + input: T, + table: Table, +): EncryptModelOperation<EncryptedFromBuildableTable<T, Table>> +``` + +Change `bulkEncryptModels` similarly: + +```ts +bulkEncryptModels< + T extends Record<string, unknown>, + Table extends BuildableTable, +>( + input: Array<T>, + table: Table, +): BulkEncryptModelsOperation<EncryptedFromBuildableTable<T, Table>> +``` + +Add imports for `BuildableTable` and `EncryptedFromBuildableTable`. + +- [ ] **Step 3: Update helper and operation table types** + +In all listed files, replace: + +```ts +EncryptedTable<EncryptedTableColumn> +``` + +with: + +```ts +BuildableTable +``` + +For imports, remove v2 schema table imports and import `BuildableTable` from `@/types`. + +Affected functions/properties: + +```ts +prepareFieldsForEncryption(..., table: BuildableTable) +encryptModelFields(..., table: BuildableTable) +encryptModelFieldsWithLockContext(..., table: BuildableTable) +prepareBulkModelsForOperation(..., table?: BuildableTable) +bulkEncryptModels(..., table: BuildableTable) +bulkEncryptModelsWithLockContext(..., table: BuildableTable) +EncryptModelOperation.table +EncryptModelOperation.constructor table +EncryptModelOperation.getOperation().table +BulkEncryptModelsOperation.table +BulkEncryptModelsOperation.constructor table +BulkEncryptModelsOperation.getOperation().table +``` + +- [ ] **Step 4: Add model type tests for v3 tables** + +In `schema-v3.test-d.ts`, add: + +```ts +it('encryptModel and bulkEncryptModels infer encrypted fields from v3 tables', () => { + const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), + active: encryptedBoolColumn('active'), + }) + const client = {} as EncryptionClient + + const encryptedOne = client.encryptModel( + { id: 'u1', email: 'alice@example.com', active: true, untouched: 42 }, + users, + ) + expectTypeOf(encryptedOne).toEqualTypeOf< + import('@/encryption').EncryptModelOperation<{ + id: string + email: Encrypted + active: Encrypted + untouched: number + }> + >() + + const encryptedMany = client.bulkEncryptModels( + [{ id: 'u1', email: 'alice@example.com', active: true }], + users, + ) + expectTypeOf(encryptedMany).toEqualTypeOf< + import('@/encryption').BulkEncryptModelsOperation< + { + id: string + email: Encrypted + active: Encrypted + } + > + >() +}) +``` + +Add nullable and v2 re-pinning cases: + +```ts +it('v3 encryptModel preserves unrelated and nullable fields', () => { + const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), + }) + const client = {} as EncryptionClient + + const encrypted = client.encryptModel( + { id: 'u1', email: null as string | null, untouched: 42 }, + users, + ) + + expectTypeOf(encrypted).toEqualTypeOf< + import('@/encryption').EncryptModelOperation<{ + id: string + email: Encrypted | null + untouched: number + }> + >() +}) + +it('v2 encryptModel inference still preserves non-schema fields after widening', () => { + const users = v2EncryptedTable('users', { + email: encryptedColumn('email').equality(), + }) + const client = {} as EncryptionClient + + const encrypted = client.encryptModel( + { id: 'u1', email: 'alice@example.com', age: 30 }, + users, + ) + + expectTypeOf(encrypted).toEqualTypeOf< + import('@/encryption').EncryptModelOperation<{ + id: string + email: Encrypted + age: number + }> + >() +}) +``` + +- [ ] **Step 5: Run targeted type tests** + +Run: + +```bash +pnpm --filter @cipherstash/stack test:types +``` + +Expected: PASS. Existing v2 model typing should remain accepted. + +--- + +### Task 7: Add Runtime Client Tests For Representative v3 Domains + +**Files:** +- Modify: `packages/stack/__tests__/schema-v3-client.test.ts` + +- [ ] **Step 1: Expand schema with representative domains** + +Replace the current `users` schema with: + +```ts +const users = encryptedTable('schema_v3_client_users', { + email: encryptedTextSearchColumn('email'), + age: encryptedInt4OrdColumn('age'), + nickname: encryptedTextEqColumn('nickname'), + body: encryptedTextMatchColumn('body'), + notes: encryptedTextColumn('notes'), + active: encryptedBoolColumn('active'), + externalId: encryptedInt8Column('external_id'), + createdOn: encryptedDateColumn('created_on'), + occurredAt: encryptedTimestamptzColumn('occurred_at'), +}) +``` + +- [ ] **Step 2: Add env-gated storage-only encryption tests** + +Add: + +```ts +it('encrypts and decrypts storage-only v3 columns', async () => { + const encryptedText = unwrapResult( + await protectClient.encrypt('private note', { + table: users, + column: users.notes, + }), + ) + expect(encryptedText).toMatchObject({ + i: { t: 'schema_v3_client_users', c: 'notes' }, + v: 2, + }) + expect(encryptedText).toHaveProperty('c') + expect(encryptedText).not.toHaveProperty('hm') + expect(encryptedText).not.toHaveProperty('bf') + expect(encryptedText).not.toHaveProperty('ob') + expect(unwrapResult(await protectClient.decrypt(encryptedText))).toBe('private note') + + const encryptedBool = unwrapResult( + await protectClient.encrypt(true, { + table: users, + column: users.active, + }), + ) + expect(encryptedBool).toHaveProperty('c') + expect(unwrapResult(await protectClient.decrypt(encryptedBool))).toBe(true) +}, 30000) +``` + +- [ ] **Step 3: Add representative query tests** + +Add: + +```ts +it('encrypts equality and order query terms for typed v3 columns', async () => { + const equalityTerm = unwrapResult( + await protectClient.encryptQuery('ada', { + table: users, + column: users.nickname, + }), + ) + expect(equalityTerm).toHaveProperty('hm') + expect(equalityTerm).not.toHaveProperty('c') + + const orderTerm = unwrapResult( + await protectClient.encryptQuery(37, { + table: users, + column: users.age, + queryType: 'orderAndRange', + }), + ) + expect(orderTerm).toHaveProperty('ob') + expect(orderTerm).not.toHaveProperty('c') +}, 30000) +``` + +- [ ] **Step 4: Add `text_match`, bigint, and Date live checks** + +Add: + +```ts +it('encrypts free-text terms for text_match columns', async () => { + const encrypted = unwrapResult( + await protectClient.encrypt('Ada Lovelace wrote notes', { + table: users, + column: users.body, + }), + ) + expect(encrypted).toHaveProperty('c') + expect(encrypted).toHaveProperty('bf') + expect(encrypted).not.toHaveProperty('hm') + expect(encrypted).not.toHaveProperty('ob') + + const matchTerm = unwrapResult( + await protectClient.encryptQuery('Lovelace', { + table: users, + column: users.body, + queryType: 'freeTextSearch', + }), + ) + expect(matchTerm).toHaveProperty('bf') + expect(matchTerm).not.toHaveProperty('c') +}, 30000) + +it('round-trips representative bigint and date-like v3 storage domains', async () => { + const int8Encrypted = unwrapResult( + await protectClient.encrypt(1234567890123456789n, { + table: users, + column: users.externalId, + }), + ) + expect(unwrapResult(await protectClient.decrypt(int8Encrypted))).toBe(1234567890123456789n) + + const day = new Date('2026-07-01T00:00:00.000Z') + const dateEncrypted = unwrapResult( + await protectClient.encrypt(day, { + table: users, + column: users.createdOn, + }), + ) + expect(unwrapResult(await protectClient.decrypt(dateEncrypted))).toEqual(day) +}, 30000) +``` + +- [ ] **Step 5: Run without credentials to verify skip behavior** + +Run: + +```bash +env -u CS_WORKSPACE_CRN -u CS_CLIENT_ID -u CS_CLIENT_KEY -u CS_CLIENT_ACCESS_KEY pnpm --filter @cipherstash/stack vitest run __tests__/schema-v3-client.test.ts +``` + +Expected: PASS with suite skipped; no module-load throw. + +- [ ] **Step 6: Run with credentials when available** + +Run: + +```bash +pnpm --filter @cipherstash/stack vitest run __tests__/schema-v3-client.test.ts +``` + +Expected: +- If `CS_*` env vars are missing: PASS skipped. +- If `CS_*` env vars are present: PASS all live tests. + +--- + +### Task 8: Preserve And Broaden Postgres v3 Tests Safely + +**Files:** +- Modify: `packages/stack/__tests__/schema-v3-pg.test.ts` + +- [ ] **Step 1: Keep `text_search` Postgres tests unchanged unless they fail** + +Preserve: + +```ts +const LIVE_EQL_V3_PG_ENABLED = Boolean( + process.env.DATABASE_URL && + process.env.CS_WORKSPACE_CRN && + process.env.CS_CLIENT_ID && + process.env.CS_CLIENT_KEY && + process.env.CS_CLIENT_ACCESS_KEY, +) +const describeLivePg = LIVE_EQL_V3_PG_ENABLED ? describe : describe.skip +``` + +- [ ] **Step 2: Add one representative typed-column table when fixture supports it** + +Before adding tests, run: + +```bash +rg "CREATE DOMAIN|CREATE TYPE" packages/stack/__tests__/fixtures/eql-v3/cipherstash-encrypt-v3.sql | rg "int4_ord|text_eq|bool" +``` + +Expected: output includes `eql_v3.int4_ord`, `eql_v3.text_eq`, and `eql_v3.bool`. + +If those exact domains are present, add a second schema: + +```ts +const typedTable = encryptedTable('protect_ci_v3_typed_domains', { + age: encryptedInt4OrdColumn('age'), + nickname: encryptedTextEqColumn('nickname'), + active: encryptedBoolColumn('active'), +}) +``` + +and create: + +```sql +CREATE TABLE IF NOT EXISTS protect_ci_v3_typed_domains ( + id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + age eql_v3.int4_ord NOT NULL, + nickname eql_v3.text_eq NOT NULL, + active eql_v3.bool NOT NULL, + test_run_id TEXT NOT NULL +) +``` + +- [ ] **Step 3: Add representative PG roundtrip/query test if fixture supports domains** + +Add: + +```ts +it('round-trips and queries representative typed v3 domains', async () => { + const age = unwrapResult(await protectClient.encrypt(37, { table: typedTable, column: typedTable.age })) + const nickname = unwrapResult(await protectClient.encrypt('ada', { table: typedTable, column: typedTable.nickname })) + const active = unwrapResult(await protectClient.encrypt(true, { table: typedTable, column: typedTable.active })) + + const [inserted] = await sql<{ id: number }[]>` + INSERT INTO protect_ci_v3_typed_domains (age, nickname, active, test_run_id) + VALUES ( + ${sql.json(age as postgres.JSONValue)}::eql_v3.int4_ord, + ${sql.json(nickname as postgres.JSONValue)}::eql_v3.text_eq, + ${sql.json(active as postgres.JSONValue)}::eql_v3.bool, + ${TEST_RUN_ID} + ) + RETURNING id + ` + + const ageTerm = unwrapResult(await protectClient.encryptQuery(30, { + table: typedTable, + column: typedTable.age, + queryType: 'orderAndRange', + })) as postgres.JSONValue + + const rows = await sql<{ id: number }[]>` + SELECT id + FROM protect_ci_v3_typed_domains + WHERE test_run_id = ${TEST_RUN_ID} + AND eql_v3.ord_term(age) >= eql_v3.ore_block_256(${sql.json(ageTerm)}::jsonb) + ` + + expect(rows.map((row) => row.id)).toContain(inserted.id) +}, 30000) +``` + +If the fixture does not expose these exact domains, do not add this test. Keep existing `text_search` PG coverage as the live SQL proof for this pass. + +- [ ] **Step 4: Verify skip and live behavior** + +Run: + +```bash +env -u DATABASE_URL pnpm --filter @cipherstash/stack vitest run __tests__/schema-v3-pg.test.ts +``` + +Expected: PASS skipped; no module-load throw. + +Run with DB/env only when available: + +```bash +pnpm --filter @cipherstash/stack vitest run __tests__/schema-v3-pg.test.ts +``` + +Expected: +- Missing env: PASS skipped. +- Present env and fixture installed: PASS. + +--- + +### Task 9: Fix Or Isolate `wasm-inline-column-name.test.ts` Import Resolution + +**Files:** +- Modify: `packages/stack/vitest.config.ts` +- Modify only if needed: `packages/stack/__tests__/wasm-inline-column-name.test.ts` + +- [ ] **Step 1: Reproduce current failure** + +Run: + +```bash +pnpm --filter @cipherstash/stack vitest run __tests__/wasm-inline-column-name.test.ts +``` + +Expected current failure: Vitest cannot resolve or load `@cipherstash/protect-ffi/wasm-inline`. + +- [ ] **Step 2: Prefer local mocks for this unit test** + +At the top of `wasm-inline-column-name.test.ts`, before importing `../src/wasm-inline`, add: + +```ts +import { vi } from 'vitest' + +vi.mock('@cipherstash/auth/wasm-inline', () => ({ + AccessKeyStrategy: { + create: vi.fn(), + }, +})) + +vi.mock('@cipherstash/protect-ffi/wasm-inline', () => ({ + decrypt: vi.fn(), + encrypt: vi.fn(), + isEncrypted: vi.fn(), + newClient: vi.fn(), +})) +``` + +This test only covers `getColumnName`; it does not need real WASM. + +- [ ] **Step 3: Add Vitest alias only if mocking does not resolve import evaluation** + +Inspect package path: + +```bash +node -p "require.resolve('@cipherstash/protect-ffi/package.json')" +``` + +Inspect exports: + +```bash +node -p "JSON.stringify(require('@cipherstash/protect-ffi/package.json').exports, null, 2)" +``` + +If the export points to a concrete JS file and mocks are insufficient, add an alias in `vitest.config.ts` using the actual export path. + +- [ ] **Step 4: Run the focused test** + +Run: + +```bash +pnpm --filter @cipherstash/stack vitest run __tests__/wasm-inline-column-name.test.ts +``` + +Expected: PASS. + +--- + +### Task 10: Validate Package Export And Build Compatibility + +**Files:** +- Modify only if failing: `packages/stack/package.json` +- Modify only if failing: `packages/stack/tsup.config.ts` + +- [ ] **Step 1: Confirm `schema/v3` remains exported for ESM and CJS** + +Run: + +```bash +node -p "const p=require('./packages/stack/package.json'); p.exports['./schema/v3']" +``` + +Expected includes both: + +```text +import.types ./dist/schema/v3/index.d.ts +import.default ./dist/schema/v3/index.js +require.types ./dist/schema/v3/index.d.cts +require.default ./dist/schema/v3/index.cjs +``` + +- [ ] **Step 2: Confirm tsup includes v3 entry** + +Run: + +```bash +rg "src/schema/v3/index.ts" packages/stack/tsup.config.ts +``` + +Expected: one match in the main dual-format entry list. + +- [ ] **Step 3: Build stack package** + +Run: + +```bash +pnpm --filter @cipherstash/stack build +``` + +Expected: PASS. `dist/schema/v3/index.d.ts`, `.d.cts`, `.js`, and `.cjs` are generated. + +- [ ] **Step 4: Verify CJS require remains supported** + +Run: + +```bash +pnpm --filter @cipherstash/stack vitest run __tests__/cjs-require.test.ts +``` + +Expected: PASS. If no v3 CJS assertion exists, add: + +```ts +const schemaV3 = require('@cipherstash/stack/schema/v3') +expect(typeof schemaV3.encryptedTextSearchColumn).toBe('function') +expect(typeof schemaV3.encryptedInt4Column).toBe('function') +``` + +--- + +### Task 11: Add Changeset + +**Files:** +- Create: `.changeset/eql-v3-typed-schema.md` + +- [ ] **Step 1: Add changeset file** + +Create: + +```md +--- +'@cipherstash/stack': minor +--- + +Add EQL v3 schema builders for all generated SQL domains under `@cipherstash/stack/schema/v3`, including explicit query capability metadata and v3 table support in model encryption helpers. +``` + +- [ ] **Step 2: Verify changeset format** + +Run: + +```bash +pnpm changeset status +``` + +Expected: command reports a pending minor changeset for `@cipherstash/stack`. + +--- + +### Task 12: Full Verification Pass + +**Files:** +- All changed files above. + +- [ ] **Step 1: Run formatter/fixer** + +Run: + +```bash +pnpm run code:fix +``` + +Expected: PASS; files may be formatted. + +- [ ] **Step 2: Run focused stack tests** + +Run: + +```bash +pnpm --filter @cipherstash/stack vitest run __tests__/schema-v3.test.ts __tests__/schema-v3-client.test.ts __tests__/schema-v3-pg.test.ts __tests__/wasm-inline-column-name.test.ts +``` + +Expected: +- Unit tests PASS. +- Live tests PASS skipped when env vars are missing. +- No module-load failures when env vars are missing. + +- [ ] **Step 3: Run type tests** + +Run: + +```bash +pnpm --filter @cipherstash/stack test:types +``` + +Expected: PASS. + +- [ ] **Step 4: Run package build** + +Run: + +```bash +pnpm --filter @cipherstash/stack build +``` + +Expected: PASS. + +- [ ] **Step 5: Run package test suite if credentials are available** + +Run: + +```bash +pnpm --filter @cipherstash/stack test +``` + +Expected: +- With credentials: PASS, including live tests. +- Without credentials: PASS for unit tests and env-gated live suites skipped. If unrelated existing live tests fail due to missing `CS_*`, record that explicitly in the final implementation notes. + +--- + +## Commit Plan + +- [ ] Commit 1: `test: cover eql v3 typed schema domains` + - Include `schema-v3.test.ts` and `schema-v3.test-d.ts` failing tests. +- [ ] Commit 2: `feat: add eql v3 domain builders` + - Include `schema/v3/index.ts`. +- [ ] Commit 3: `feat: support v3 tables in model encryption` + - Include `types.ts`, encryption client/helper/operation files, and model type tests. +- [ ] Commit 4: `test: stabilize v3 client and wasm-inline coverage` + - Include live test updates and Vitest/WASM test fix. +- [ ] Commit 5: `changeset: document eql v3 typed schema` + - Include `.changeset/eql-v3-typed-schema.md`. + +--- + +## Self-Review + +**Spec coverage:** This plan keeps v3 isolated under `@cipherstash/stack/schema/v3`, exports one builder per EQL v3 domain, preserves v2 schema, adds explicit `getQueryCapabilities()` and `isQueryable()`, tightens `BuildableQueryColumn`, widens model helpers structurally, preserves `text_search` byte-equivalent config, keeps `EncryptConfig` free of v3 metadata, env-gates live tests, and addresses `wasm-inline` Vitest resolution. + +**Review-driven corrections:** The design intentionally uses a full literal domain definition generic (`eqlType`, `castAs`, and capabilities), not a capability-only generic, because empty TypeScript subclasses are not nominal. Model encryption inference intentionally reads table keys from the existing `_columnType` brand, not `build().columns`, because the structural `BuildableTable.build()` contract erases literal keys to `Record<string, ColumnSchema>`. + +**Placeholder scan:** No task uses unresolved placeholders. Conditional Postgres expansion is tied to a concrete `rg` command and an explicit keep-existing-tests outcome. + +**Type consistency:** Public capability names are consistently `equality`, `orderAndRange`, and `freeTextSearch`. Queryable v3 columns require `isQueryable(): true`; storage-only columns return `false` and remain accepted by `encrypt` through `BuildableColumn`. diff --git a/docs/superpowers/specs/2026-06-30-eql-v3-text-search-schema-design.md b/docs/superpowers/specs/2026-06-30-eql-v3-text-search-schema-design.md new file mode 100644 index 00000000..2e452f04 --- /dev/null +++ b/docs/superpowers/specs/2026-06-30-eql-v3-text-search-schema-design.md @@ -0,0 +1,334 @@ +# EQL v3 Schema DSL — `text_search` (Increment 1) + +> **Superseded (2026-07-03):** the authoring surface described below has moved. +> The subpath is now `@cipherstash/stack/eql/v3` (not `schema/v3`) and columns +> are authored via the `types` namespace — `types.TextSearch('email')` replaces +> `encryptedTextSearchColumn('email')`. This document is retained as the original +> design record for the increment; the code examples show the historical API. + +**Date:** 2026-06-30 +**Status:** Approved (design) +**Package:** `@cipherstash/stack` +**Scope:** Authoring DSL + encrypt-config emission for the `eql_v3.text_search` +concrete type, **plus** a backward-compatible structural widening of the public +client types so v3 builders are first-class with the client API (`Encryption`, +`encrypt`, `decrypt`, `encryptQuery`). DDL and query-dialect work are explicitly +deferred (see Non-goals). + +--- + +## Goal + +Begin the EQL v3 version of the encryption SDK. EQL v3 removes the generic +"encrypted" concept in favour of **concrete types that carry their own +capabilities**. The first concrete type is `eql_v3.text_search`. + +Today: + +```ts +const users = encryptedTable('users', { + email: encryptedColumn('email').equality().freeTextSearch(), +}) +``` + +v3: + +```ts +const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), +}) +``` + +Because the concrete type carries capability, the capability-enabling calls +(`.equality()`, `.orderAndRange()`, `.freeTextSearch()` *as enablers*) disappear. +What remains is **tuning** of the match index: + +```ts +const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email').freeTextSearch({ + tokenizer: { kind: 'ngram', token_length: 4 }, + token_filters: [{ kind: 'downcase' }], + k: 8, + m: 4096, + include_original: false, + }), +}) +``` + +## Background — what `eql_v3.text_search` is + +Source of truth: +`<eql-v3-worktree>/release/cipherstash-encrypt-v3.sql`. + +`eql_v3.text_search` is a Postgres `CREATE DOMAIN ... AS jsonb` whose `CHECK` +requires an object containing `v, i, c, hm, ob, bf` (with `v = '2'`). The domain +defines **all three** index extractors as functions: + +- `eql_v3.eq_term(text_search)` → equality (`hm` = hmac) +- `eql_v3.ord_term(text_search)` → order/range (`ob` = ore blocks) +- `eql_v3.match_term(text_search)` → free-text match (`bf` = bloom filter) + +So `text_search` is the **full-capability** text type: equality + order + match. +EQL v3 also defines narrower text domains (`text`, `text_eq`, `text_match`, +`text_ord(_ore)`) and full families for `int*`/`float*`/`date`/`bool`/`numeric`/ +`timestamptz`/`json` — all out of scope for this increment. + +### The load-bearing fact: the payload is identical + +The encrypted envelope a v2 column produces (`{ v, i, c, hm, ob, bf }`) already +satisfies the `eql_v3.text_search` domain `CHECK`. Therefore: + +- A v2 `eql_v2_encrypted` column built with equality + order + match can be + retyped to `eql_v3.text_search` with **no re-encryption** — a future + `ALTER COLUMN ... TYPE` is a `jsonb → jsonb` metadata flip. +- The native cipherstash-client (`@cipherstash/protect-ffi` `newClient`) needs + **no changes**: the `EncryptConfig` it receives is unchanged. +- The SDK's **runtime** encrypt/decrypt/query path needs no changes either — it + is purely structural (it only reads `column.getName()`, `column.build()`, + `table.tableName`, `table.build().columns`; there is no `instanceof` on that + path). + +What this increment *does* change is the SDK's **public TYPES**: today they are +typed against the v2 `EncryptedTable<EncryptedTableColumn>` / `EncryptedColumn` +classes, which are nominal (private fields), so the separate v3 +`EncryptedTextSearchColumn` class is not assignable to them. To make v3 builders +work with the client (not just emit a config), the public client types are +**widened to a structural contract** in this increment (see "Client integration" +below). The widening is purely additive — existing v2 usage is unaffected. + +## Architecture & location + +- New module: `packages/stack/src/schema/v3/` (own `index.ts`; split into + focused files if it grows). +- New export subpath: `@cipherstash/stack/schema/v3` (added to `package.json` + `exports` + `tsup`/build entry as needed). +- The v2 schema module (`packages/stack/src/schema/index.ts`) keeps its runtime + behavior and existing exported symbol shapes; the only permitted edit there is + a backward-compatible **widening** of `buildEncryptConfig`'s parameter type to + the shared structural table contract (it already only calls `.build()`). +- v3 builders emit the existing `ColumnSchema` / `EncryptConfig` shape, so the + encryption client, payload, encrypt/decrypt, and query paths work at runtime + with **zero runtime changes**. Client integration at the **type** level is + achieved by widening the public types (next section), not by a runtime rewrite. + +## Public API + +```ts +import { encryptedTable, encryptedTextSearchColumn } from '@cipherstash/stack/schema/v3' + +// minimal — capability is carried by the type +const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email'), +}) + +// with match-index tuning +const users = encryptedTable('users', { + email: encryptedTextSearchColumn('email').freeTextSearch({ + tokenizer: { kind: 'ngram', token_length: 4 }, + token_filters: [{ kind: 'downcase' }], + k: 8, + m: 4096, + include_original: false, + }), +}) +``` + +- `encryptedTextSearchColumn(name)` → `EncryptedTextSearchColumn`. The concrete + type **inherently enables equality + order + match**. There are no + capability-enabling methods. +- `.freeTextSearch(opts?)` is **tuning only** — it overrides the match-index + parameters. It never "enables" a capability (match is always on for this type). +- `encryptedTable(tableName, columns)` (v3) accepts v3 column builders and + assembles `{ tableName, columns }`. +- `buildEncryptConfig(...tables)` (v3) assembles an `EncryptConfig` (`v: 1`). + +> Naming note: v3 `encryptedTable` / `buildEncryptConfig` intentionally shadow the +> v2 names but live on the `/v3` subpath, so an importer picks the model by import +> path, not by symbol name. + +## Client integration (in scope) + +v3 builders must be **accepted by the client API**, not merely emit a config. The +runtime already works (structural — see "load-bearing fact"); the blocker is the +public TYPES. This increment widens them to a shared **structural contract** so +both v2 and v3 builders satisfy them: + +```ts +// minimal structural shapes — exact members verified against the client's +// actual usage (column.getName/build, table.tableName/build): +interface BuildableColumn { getName(): string; build(): ColumnSchema } +interface BuildableTable { + tableName: string + build(): { tableName: string; columns: Record<string, ColumnSchema> } +} +// Query path is NARROWER: it must reject non-queryable EncryptedField (no +// indexes). A v2 EncryptedColumn qualifies nominally; a v3 queryable concrete +// type qualifies via getEqlType(); EncryptedField is excluded. +type BuildableQueryColumn = + | EncryptedColumn + | (BuildableColumn & { getEqlType(): string }) +``` + +Widened surfaces (in `packages/stack/src/types.ts`) — note the **storage vs query split**: + +- `EncryptionClientConfig.schemas` → `AtLeastOneCsTable<BuildableTable>` +- `EncryptOptions.column` / `.table` → `BuildableColumn` / `BuildableTable` — + the STORAGE path (`encrypt`) accepts columns AND nested fields. +- `SearchTerm` / `QueryTermBase.column` → `BuildableQueryColumn`; `.table` → + `BuildableTable` — the QUERY path (`encryptQuery`) accepts only queryable + columns, so a `BuildableQueryColumn` excludes `EncryptedField` (which the + nominal `EncryptedColumn` type rejected and must keep rejecting). +- Internally, the query-only index-inference helpers + (`inferIndexType`/`validateIndexType`/`resolveIndexType`) also take + `BuildableQueryColumn` (verified reached only from the `encryptQuery` path). + +Plus `buildEncryptConfig`'s parameter is widened to `BuildableTable` (pure +widening; it only calls `.build()`). + +**v3 keeps its own `EncryptedTable` class** (it needs a different column +constraint and a simpler `build()` than v2's nested-field/ste_vec logic). Both +the v2 and v3 table/column classes satisfy the structural contract, which is what +lets a single widened type accept either. + +**Backward compatibility:** widening only — existing v2 tables/columns still +satisfy the new types (a regression type-test asserts this). The **generic +schema-aware model methods** (`encryptModel<S extends EncryptedTableColumn>` / +`bulkEncryptModels`) are **left unchanged** so v2's field-level inference +(`InferPlaintext`, `EncryptedFields`, `EncryptedFromSchema`, the +`EncryptedTable<T> & T` accessor) is preserved. v3 support for the model methods +(its columns don't satisfy `EncryptedTableColumn`) is a **future increment**. + +**Acceptance (these must type-check with v3 builders):** +`Encryption({ schemas: [v3users] })`, `client.encrypt(v, { table: v3users, column: +v3users.email })`, `client.decrypt(...)` round-trip, and +`client.encryptQuery(v, { table: v3users, column: v3users.email })`. Plus the +storage/query split: a v2 `encryptedField` is `encrypt`-able but a `@ts-expect-error` +proves it is NOT `encryptQuery`-able, and a v2 `EncryptedColumn` stays queryable. + +> Discriminator follow-up: `getEqlType()` distinguishes queryable v3 types today +> only because the one v3 type shipping (`text_search`) is queryable. If a future +> v3 *non-queryable* type also carries `getEqlType()`, switch the query-path +> discriminator to a queryability-specific marker. Not blocking for this increment. + +## `build()` output — pinned to v2 + +`encryptedTextSearchColumn('email').build()` emits exactly: + +```ts +{ + cast_as: 'string', + indexes: { + unique: { token_filters: [] }, + ore: {}, + match: { + tokenizer: { kind: 'ngram', token_length: 3 }, + token_filters: [{ kind: 'downcase' }], + k: 6, + m: 2048, + include_original: true, + }, + }, +} +``` + +Notes: + +- **`cast_as: 'string'`**, not `'text'`. The native cipherstash-client receives + the SDK-facing value verbatim; `toEqlCastAs` ('string' → 'text') is applied + only on the `wasm-inline.ts` SQL-generation path, not the `newClient` path. +- Defaults mirror v2's `freeTextSearch()` **exactly**: ngram-3, downcase filter, + `k = 6`, `m = 2048`, `include_original = true` (note: `true`, matching the v2 + builder default, not the zod-schema default of `false`). +- `unique.token_filters` defaults to `[]` (case-sensitive equality, matching v2). +- `.freeTextSearch(opts)` overrides on a per-field basis using the same merge + semantics as v2 (each provided key replaces the default; omitted keys keep the + default). + +**The guarantee:** this output is byte-identical to + +```ts +encryptedColumn('email').equality().orderAndRange().freeTextSearch().build() +``` + +and a test asserts that equality directly (see Testing). This is what makes +"swap the column type and it just works" true at the config level. + +## v3 metadata for later increments + +`EncryptedTextSearchColumn` records its concrete domain name — +`'eql_v3.text_search'` — exposed via the `getEqlType()` method (method only, no +property getter, matching the v2 builder convention). + +- `build()` (the encrypt config) does **not** include `eqlType`; the wire config + stays identical to v2. +- The name is metadata that the *future* DDL and query-dialect increments read + (per-column Postgres type, `eql_v3.eq_term(...)` lowering). Recording it now + gives those increments a hook without changing today's config. + +## Type inference + +v3 `InferPlaintext` / `InferEncrypted` mirror v2: + +- `InferPlaintext<typeof users>` → `{ email: string }` +- `InferEncrypted<typeof users>` → `{ email: Encrypted }` + +## Non-goals (deferred to follow-up increments) + +> Note: "widen the public client types" was previously implied as out of scope +> ("zero client changes"). It is now **in scope** for this increment (see Client +> integration). The items below remain deferred. + +- **v3 support in the generic schema-aware model methods** (`encryptModel` / + `bulkEncryptModels` field-level inference) — v3 columns don't satisfy the v2 + `EncryptedTableColumn` constraint those generics use. Single-value + `encrypt`/`decrypt`/`encryptQuery` + `Encryption()` config DO work in this + increment; model-method inference for v3 is a follow-up. +- **v3 columns through the WASM-inline entry** (`wasm-inline.ts`) — known + boundary. `getColumnName()` (`src/wasm-inline.ts:314-320`) runtime-checks + `instanceof EncryptedColumn || instanceof EncryptedField` and throws otherwise, + so a v3 column passed to the WASM-inline client would throw at runtime. The + type widening still compiles (the `instanceof` guard narrows the wider union) + and this path is outside the scoped typecheck, so it is a documented deferred + boundary, not a regression. The batch-2 "no `instanceof`" / structural-runtime + claim is scoped to the native `operations/*.ts` path. +- **Per-column DDL type emission** — deriving each column's Postgres type from + its v3 builder. v2 hard-codes one native type (`eql_v2_encrypted`); v3 needs a + per-column type (`eql_v3.text_search`, etc.). Net-new, touches every adapter. +- **v2 → v3 transition tooling** — `ALTER TABLE ... ALTER COLUMN ... TYPE + eql_v3.text_search` and retiring the now-redundant `eql_v2_configuration` / + `add_search_config` rows for the column. +- **v3 query dialect** — `eql_v3.eq_term(col) = eql_v3.eq_term($1::eql_v3.text_search)` + in drizzle / supabase operator lowering. +- **Other v3 concrete types** — `int*`, `float*`, `date`, `bool`, `numeric`, + `timestamptz`, `text_eq`/`text_ord`, `json`, etc. The module is structured so + these slot in later (a domain → config mapping per type). +- **Nested `encryptedField` / structured columns** for v3 — only top-level + `text_search` columns ship in increment 1. + +## Testing + +- **Config-equivalence (load-bearing):** + `encryptedTextSearchColumn('email').build()` deep-equals + `encryptedColumn('email').equality().orderAndRange().freeTextSearch().build()`. +- **`.freeTextSearch()` override:** each provided opt replaces its default; + omitted opts retain defaults; verify the documented "additional config" example + produces the expected match block. +- **Defaults:** assert the exact default `build()` output above (catches any + silent default drift). +- **`buildEncryptConfig`:** a v3 table assembles into a valid `EncryptConfig` + (`v: 1`) that passes `encryptConfigSchema.parse(...)`. +- **`eqlType` metadata:** `getEqlType()` returns `'eql_v3.text_search'` and is + absent from `build()` output. +- **No shared mutable state:** two columns built independently must not alias — + mutating one column's `build()` output must not affect another's (defaults are + produced per-instance, `build()` returns a fresh clone). +- **Type-level:** `InferPlaintext` / `InferEncrypted` produce the expected shapes. +- **Client integration (type-level):** the acceptance snippets above type-check + with v3 builders, and a regression test asserts v2 tables/columns still satisfy + the widened public types. + +## Open questions + +None blocking. Future increments will decide how `eqlType` threads into DDL and +query lowering, and how the narrower text domains (`text_eq`, `text_match`, +`text_ord`) and other scalar families are expressed in the DSL. diff --git a/docs/superpowers/specs/2026-07-02-stryker-v3-ci-gate-design.md b/docs/superpowers/specs/2026-07-02-stryker-v3-ci-gate-design.md new file mode 100644 index 00000000..82eb2f41 --- /dev/null +++ b/docs/superpowers/specs/2026-07-02-stryker-v3-ci-gate-design.md @@ -0,0 +1,198 @@ +# Stryker mutation testing as a blocking CI gate for EQL v3 + +Date: 2026-07-02 +Status: Proposed (awaiting review) +Branch: feat/eql-v3-text-search-schema + +## Goal + +Add StrykerJS mutation testing scoped to **EQL v3 only** +(`packages/stack/src/eql/v3/`) and wire it into CI as a **blocking** check. +The gate mirrors the existing `fta-v3.yml` complexity gate: paths-filtered to v3, +directory-scoped, and blocking (no `continue-on-error`). + +Mutation testing verifies that the v3 test suite actually *detects* changes in +behaviour — it mutates the source and fails if the tests still pass ("surviving +mutants"). This complements the FTA complexity gate (static) with a +test-effectiveness gate (dynamic). + +## Context / prior art + +- **rundown** (`~/psrc/rundown`) runs Stryker 9.6.1 across a pnpm monorepo with a + **Jest** runner, per-package configs, incremental runs backed by the public + Stryker Dashboard, a native `break: 70` aggregate threshold, and a custom + `assert-mutation-score.mjs` per-file gate. Its PR run is advisory; only the + push-to-`main`/weekly "producer" run is blocking. +- **stack** differs in ways that simplify the design considerably (below). + +## Key facts driving the design + +1. **stack uses Vitest 3.2.4, not Jest.** rundown's Jest-runner config is not + reusable. We use `@stryker-mutator/vitest-runner`. +2. **v3 scope is a small directory:** `packages/stack/src/eql/v3/` — four + cohesive files (`columns.ts`, `types.ts`, `table.ts`, `index.ts`), split out + of the former single `schema/v3/index.ts`. NOTE: an earlier draft of this + spec assumed a *single file*, from which it concluded the project-wide + aggregate score *is* that file's score and no per-file gate script was needed. + That premise no longer holds — the mutate scope is now four files. With only + four small files the aggregate is still a faithful signal, so start with an + aggregate `break` threshold only (no `assert-mutation-score.mjs`), but add + per-file gating if any one file's score later diverges from the aggregate. +3. **Live/DB tests self-skip without env.** `schema-v3-pg.test.ts` (guarded by + `DATABASE_URL` + `CS_*`) and `schema-v3-client.test.ts` (guarded by `CS_*`) + skip their `describe` blocks when the env vars are absent. So a CI run with no + Postgres service and no `.env` still runs cleanly — the live blocks skip; the + pure `schema-v3.test.ts` (~21 KB) and `typed-client-v3.test.ts` provide the + coverage. The gate stays as lean as the FTA job (no DB, no credentials). +4. **No build step needed.** Vitest transpiles TS on the fly and the tests import + from `@/eql/v3` (source, via the `@/` alias), so Stryker instruments source + directly — no `pnpm build` required. +5. **Supply-chain rule.** Tooling must be a pinned devDependency installed via + `--frozen-lockfile` (no `pnpm dlx` / `npx`), matching how `fta-cli@3.0.0` is + handled. + +## Scope decisions + +- **Mutate scope: `eql/v3` only** (`src/eql/v3/**/*.ts`). Matches the FTA + gate exactly. `src/encryption/v3.ts` is also v3 but is outside the current FTA + scope and is **excluded here** to keep the gate consistent and lean. +- **Test execution: lean, no DB.** Stryker runs only the v3 runtime test files; + the live pg/client blocks self-skip. No Postgres service is provisioned. + +## Components + +### 1. Dependencies + +Add to `packages/stack/package.json` devDependencies (pinned, matching versions, +9.x line): + +- `@stryker-mutator/core` +- `@stryker-mutator/vitest-runner` + +Update `pnpm-lock.yaml` accordingly (installed via `--frozen-lockfile` in CI). + +### 2. `packages/stack/vitest.stryker.config.ts` + +A dedicated Vitest config for mutation runs that: + +- imports/extends the base `vitest.config.ts` (keeps the `@/` alias and the + `wasm-inline` stub aliases — required for the pure tests to load), +- sets `test.include` to only the v3 runtime tests + (`__tests__/*v3*.test.ts`) so Stryker does not run the whole repo suite, +- disables the `typecheck` block (mutation testing exercises runtime behaviour, + not type tests; the `*.test-d.ts` files are excluded). + +Rationale: without scoping, Stryker's initial dry run would execute every test in +the package, wasting time and coupling the v3 gate to unrelated tests. + +### 3. `packages/stack/stryker.config.mjs` + +```js +export default { + packageManager: 'pnpm', + testRunner: 'vitest', + plugins: ['@stryker-mutator/vitest-runner'], + vitest: { configFile: 'vitest.stryker.config.ts' }, + mutate: ['src/eql/v3/**/*.ts'], + coverageAnalysis: 'perTest', + reporters: ['clear-text', 'progress', 'html', 'json'], + htmlReporter: { fileName: 'reports/mutation/index.html' }, + jsonReporter: { fileName: 'reports/mutation/mutation-report.json' }, + thresholds: { high: <TBD>, low: <TBD>, break: <BASELINE> }, + concurrency: /* env-tunable, default 2 */, + timeoutMS: /* generous default, e.g. 60000 */, +} +``` + +- `break` is the **blocking mechanism**: Stryker exits non-zero when the score + drops below it. +- **No dashboard reporter and no incremental mode** initially (YAGNI for a single + file; avoids Stryker Dashboard API-key/project setup). Reporters kept local + (html + json for artifacts/debugging, clear-text + progress for logs). +- The explicit `plugins` list is required under pnpm's isolated `node_modules` + layout — Stryker's default `@stryker-mutator/*` auto-discovery fails there + (learned from rundown). + +### 4. Script + +Add to `packages/stack/package.json` scripts: + +```json +"test:mutation": "stryker run" +``` + +### 5. `.github/workflows/stryker-v3.yml` + +A near-clone of `fta-v3.yml`: + +- `on: push (main) / pull_request (**)` with `paths:`: + - `packages/stack/src/eql/v3/**` + - `packages/stack/package.json` + - `packages/stack/stryker.config.mjs` + - `packages/stack/vitest.stryker.config.ts` + - `.github/workflows/stryker-v3.yml` +- `permissions: contents: read` +- one job on `blacksmith-4vcpu-ubuntu-2404`, `timeout-minutes: 30` +- steps: checkout → `pnpm/action-setup@v6.0.8` → `setup-node@v6` (node 22, + `cache: pnpm`) → install `node-gyp` → `pnpm install --frozen-lockfile` → + `pnpm --filter @cipherstash/stack run test:mutation` +- **No `continue-on-error`** on the Stryker step → the check is blocking. + +## Threshold calibration (how "blocking" is made safe) + +We cannot know the current v3 mutation score until Stryker runs once. +Implementation therefore includes a **baseline step**: + +1. Install deps and run `pnpm --filter @cipherstash/stack run test:mutation` + locally. +2. Record the reported mutation score for `eql/v3`. +3. Set `thresholds.break` just **below** the measured score (a small buffer, the + way FTA sets `--score-cap 69` against a current worst-file score of 68.00 — + re-baselined from the pre-split monolith's 71.08/72 after `eql/v3` was split + into per-file modules). This ensures the current state passes while any + regression that lowers the score fails the gate. +4. Set `high`/`low` to reasonable display bands (do not affect pass/fail). + +If the measured baseline is very low (tests are weak), surface that to the user +before committing a `break` value — a near-zero gate provides little protection +and we may want to improve v3 tests first. This is a decision point during +implementation, not a silent choice. + +## Testing / verification + +- Run the Stryker gate locally and confirm it exits 0 at the chosen `break`. +- Confirm the run needs **no** Postgres/credentials (live blocks skip). +- Sanity-check the gate blocks: temporarily lower `break` above the score (or + delete an assertion) and confirm a non-zero exit. +- Confirm the workflow triggers only on v3-relevant paths. + +## Out of scope (YAGNI) + +- Stryker Dashboard reporter and incremental baseline. +- Per-file gate script (`assert-mutation-score.mjs`) — deferred: start with an + aggregate `break` across the four `src/eql/v3/**` files; add per-file gating + only if one file's score later diverges from the aggregate (see fact #2). +- Advisory PR comment job. +- Postgres-backed mutation runs / mutating `src/encryption/v3.ts`. + +These can be added later if the aggregate gate proves insufficient. + +## Decisions confirmed + +- **Test execution model: lean, no DB — confirmed by the user ("Start lean").** + Stryker runs only the pure v3 tests; the live pg/client blocks self-skip. A + full DB-backed run can be added later as a separate workflow if the lean + baseline proves too weak. +- **Single workflow, no split — confirmed.** rundown's two-workflow split + (blocking producer + advisory PR) is driven by its Stryker Dashboard + incremental baseline and its advisory-PR choice, neither of which applies here. + One `stryker-v3.yml` runs on both `push: main` and `pull_request`, blocking, in + the shape of `fta-v3.yml`. A second `stryker-v3-full.yml` (DB-backed, on + main/nightly) is only introduced if/when full accuracy is wanted. + +## Deferred to implementation + +- **Exact `break` value** — deferred to the baseline measurement step (run + Stryker once, set `break` just below the measured score). If the baseline is + very low, surface it before wiring the gate. +- **Stryker `9.x` exact patch version** — pinned at implementation time. diff --git a/docs/superpowers/specs/2026-07-06-eql-v3-drizzle-concrete-types-design.md b/docs/superpowers/specs/2026-07-06-eql-v3-drizzle-concrete-types-design.md new file mode 100644 index 00000000..5ee27120 --- /dev/null +++ b/docs/superpowers/specs/2026-07-06-eql-v3-drizzle-concrete-types-design.md @@ -0,0 +1,286 @@ +# EQL v3 Drizzle support — concrete-type authoring — design + +Status: proposed +Date: 2026-07-06 +Branch: `feat/eql-v3-text-search-schema` + +## 1. Goal + +Add EQL v3 support to the Drizzle integration inside `@cipherstash/stack`, mirroring +the existing v2 Drizzle integration (`@cipherstash/stack/drizzle`) but re-shaped +around the v3 **concrete-type** model. + +The defining change of v3: **the concrete type defines the search capabilities.** +A column declared `eql_v3.integer_eq` supports equality; `eql_v3.integer_ord` supports +order/range (and equality via ORE); `eql_v3.text_search` supports equality, order, +and free-text match. There is no separate `.equality()` / `.orderAndRange()` / +`.freeTextSearch()` index configuration as in v2 — everything the adapter needs +(SQL column domain, `cast_as`, and which operators are legal) is **derived from the +concrete type**, which already carries that metadata in +`@cipherstash/stack/eql/v3`. + +Success = a developer can declare a Drizzle `pgTable` with encrypted v3 columns, +feed the same schema to `EncryptionV3`, and run equality / range / free-text / +ordering queries through Drizzle using capability-checked operators that emit the +correct `eql_v3` term-function SQL. + +## 2. Background: why v3 is different from v2 + +Confirmed against this branch's SQL bundle +(`packages/stack/__tests__/fixtures/eql-v3/cipherstash-encrypt-v3.sql`) and the live +pg tests (`packages/stack/__tests__/schema-v3-pg.test.ts`). + +**Column type.** v2 uses a single composite type `eql_v2_encrypted` for every +encrypted column. v3 uses **one `CREATE DOMAIN … AS jsonb` per concrete type** — +`eql_v3.integer_ord`, `eql_v3.text_eq`, `eql_v3.text_search`, `eql_v3.boolean`, … There is +no single catch-all `eql_v3_encrypted`. + +**Wire form.** v2 writes a composite literal `("…")`. v3 domains are plain jsonb, so +the value is inserted as plain JSON cast to the domain (`$1::eql_v3.integer_ord`). + +**Query form.** v2 compares encrypted payloads directly (native `=` on +`eql_v2_encrypted`, or `eql_v2.gt/lt/like/order_by(...)` convenience functions). v3 +has **no convenience operators**; it compares **extracted index terms** on both +sides: + +| Capability | v3 SQL | +| --- | --- | +| equality (HMAC) | `eql_v3.eq_term(col) = eql_v3.hmac_256($::jsonb)` | +| equality (ORE, numeric/date order domains) | `eql_v3.ord_term(col) = eql_v3.ore_block_256($::jsonb)` | +| order/range | `eql_v3.ord_term(col) </<=/>/>= eql_v3.ore_block_256($::jsonb)` | +| free-text match | `eql_v3.match_term(col) @> eql_v3.bloom_filter($::jsonb)` | +| order by | `ORDER BY eql_v3.ord_term(col)` | + +The column-side extractor (`eq_term`/`ord_term`/`match_term`) takes the column +domain (its stored value has ciphertext `c`, so it passes the domain CHECK). The +search-side constructor (`hmac_256`/`ore_block_256`/`bloom_filter`) pulls the index +field straight out of the query-term jsonb with no domain coercion — this is why a +query term (which has no ciphertext) must be cast to `::jsonb`, never to the domain. + +**Concrete types already exist.** `@cipherstash/stack/eql/v3` ships the full +concrete-type system (`packages/stack/src/eql/v3/{columns,types,table,index}.ts`): +- `types.<Domain>(name)` factories for all 35 shipped domains. +- Each `EncryptedV3Column` carries `getEqlType()` (`eql_v3.integer_ord`), `castAs` + (`'string' | 'number' | 'boolean' | 'date'`), `getQueryCapabilities()` + (`{ equality, orderAndRange, freeTextSearch }`), and `build()` → + `{ cast_as, indexes: { unique?, ore?, match? } }`. +- `encryptedTable(name, columns)` builds the schema `EncryptionV3` consumes. +- `EncryptionV3(...).encryptQuery(value, { table, column, queryType })` produces the + query term; the FFI's `resolveIndexType` picks the index (including equality-via-ORE + for numeric/date order domains). + +This adapter **reuses** that system verbatim — it never re-declares domain or +capability data. + +## 3. Scope + +### In scope +- A new Drizzle v3 module in `@cipherstash/stack`, exported at + `@cipherstash/stack/eql/v3/drizzle` (nested under the existing `eql/v3` namespace). +- A Drizzle-native `types` namespace with the **identical PascalCase factory names** + as `@cipherstash/stack/eql/v3` (`types.TextSearch`, `types.IntegerOrd`, `types.Boolean`, + … all 35 shipped domains), each returning a Drizzle `customType` column. +- Plain-jsonb codec (`toDriver` / `fromDriver`). +- Schema extraction: Drizzle table → v3 `encryptedTable` for `EncryptionV3`. +- `createEncryptionOperatorsV3(client)` — capability-checked async operators: + `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `between`, `notBetween`, `like`, `ilike`, + `notIlike`, `inArray`, `notInArray`, `asc`, `desc`, `and`, `or`, plus the + pass-through non-encrypting operators (`isNull`, `isNotNull`, `not`, `exists`, + `notExists`). +- Detection: recover the concrete builder from a processed Drizzle column. +- A `.changeset/` entry (minor `@cipherstash/stack`). + +### Out of scope (explicit gaps, not silent omissions) +- **JSON / `ste_vec`** operators (`jsonbPathQueryFirst`, `jsonbGet`, + `jsonbPathExists`). No v3 JSON column builder ships yet (`eql_v3.json` / + `ste_vec` have no `types.*` factory), so these are simply absent from the v3 + operator surface — there is no v3 column they could target. Deferred until a v3 + JSON builder exists. +- **int8 / bigint** domains — intentionally absent from `eql/v3` pending lossless + FFI round-tripping. This adapter mirrors that: no int8 factory. +- **`like`/`ilike` pattern semantics.** v3's only text-match SQL is bloom-filter + containment (`match_term @> bloom_filter`), which is **token/substring matching, + not SQL `LIKE` patterns**. `like`/`ilike`/`notIlike` all map to containment + (`notIlike` = `NOT (…)`); wildcards in the argument are not interpreted. Documented + on each operator. +- **No changes to the v2 Drizzle module** (`@cipherstash/stack/drizzle`) or the + standalone `@cipherstash/drizzle` package. Zero v2 regression surface. +- **No dialect-seam refactor of the v2 `operators.ts`.** The v3 operators are a + self-contained module; the SQL-dialect seam (below) lives only inside v3. + +## 4. Architecture & location + +```text +packages/stack/src/eql/v3/drizzle/ + index.ts // barrel: types, createEncryptionOperatorsV3, extractEncryptionSchemaV3, errors + types.ts // Drizzle `types` namespace (PascalCase factories → customType columns) + column.ts // customType wrapper + detection + config stash + codec.ts // plain-jsonb toDriver / fromDriver + sql-dialect.ts // v3 term-function SQL emission (local seam) + operators.ts // createEncryptionOperatorsV3 + schema-extraction.ts // Drizzle table → eql/v3 encryptedTable +``` + +Package wiring: add `"./eql/v3/drizzle"` to `packages/stack/package.json` `exports` +and to the tsup entry list, following the existing `./eql/v3` and `./drizzle` +entries. + +The v3 module depends inward on `@/eql/v3` (concrete types + `encryptedTable`) and +the base `EncryptionClient` (`@/encryption`) — the same client the v2 Drizzle +operators use. It does **not** depend on the v2 Drizzle module. + +## 5. Components + +### 5.1 `types` namespace + column wrapper (`types.ts`, `column.ts`, `codec.ts`) + +`types.TextSearch(name)` (and the 34 siblings) returns a Drizzle column built via +`customType`. Each factory: + +1. Constructs the corresponding `eql/v3` builder — `v3.types.TextSearch(name)` — the + **single source of truth** for domain / `cast_as` / capabilities. No metadata is + re-declared here; this file is a name→delegate map. +2. Builds a `customType<{ data: Plaintext; driverData: string | null }>` whose + `dataType()` returns `builder.getEqlType()` (e.g. `eql_v3.integer_ord`), and whose + `toDriver`/`fromDriver` are the plain-jsonb codec. +3. Stashes the `eql/v3` builder on the column (`_eqlv3Column`) **and** in a + module-global map keyed by column name — mirroring v2's dual registration — so + detection and schema-extraction can recover it after `pgTable` strips custom + props. + +The decrypted TypeScript type is `PlaintextForColumn<typeof builder>` (string / +number / boolean / Date), so `users.age` decrypts to `number`, `users.createdAt` to +`Date`, etc. + +**Codec** (`codec.ts`), proven by the `eql-v3-drizzle-adapter` branch: +- `toDriver`: `null`/`undefined` → SQL `NULL` (JS `null`). The v3 domains + `CHECK jsonb_typeof(VALUE) = 'object'`, so a JSONB `null` literal would fail the + domain; SQL NULL is accepted. Otherwise `JSON.stringify(value)`. +- `fromDriver`: pass `null` through; return already-parsed objects as-is (the + postgres driver may hand back a parsed jsonb object); else `JSON.parse`. + +**Detection** (`column.ts`): `isEqlV3Column(column)` / `getEqlV3Column(name, column)` +check `_eqlv3Column`, falling back to the name-keyed map, and validate the +`dataType()` string is one of the known `eql_v3.*` domains (source: iterate the +`eql/v3` `types` factories once at module load to build the domain set — no +hand-maintained string list). + +### 5.2 SQL dialect (`sql-dialect.ts`) + +A small object that emits the v3 term-function SQL, keyed off which index the column +exposes. Gating and dialect both read `builder.build().indexes` — the authoritative +index set: + +- `indexes.unique` present → equality via `eql_v3.eq_term(col) = eql_v3.hmac_256($::jsonb)`. +- `indexes.ore` present → order/range via `eql_v3.ord_term(col) <op> eql_v3.ore_block_256($::jsonb)`; + order-by via `eql_v3.ord_term(col)`; **and** equality via ORE when `unique` is + absent (`eql_v3.ord_term(col) = eql_v3.ore_block_256($::jsonb)`). +- `indexes.match` present → free-text via `eql_v3.match_term(col) @> eql_v3.bloom_filter($::jsonb)`. + +Query terms are bound params already wrapped with `bindIfParam` by the caller, then +cast `::jsonb` inside the constructor call. Constructor names are pinned to this +branch's bundle: `hmac_256`, `ore_block_256`, `bloom_filter` (note: **not** the +`ore_block_u64_8_256` spelling from the older adapter branch — that predates this +bundle). + +### 5.3 Operators (`operators.ts`) + +`createEncryptionOperatorsV3(client: EncryptionClient)` returns the async-operator +object, same ergonomics as v2 (`await ops.eq(users.email, 'x')`, `ops.and(...)` / +`ops.or(...)` batch encryption, `ops.asc(...)` / `ops.desc(...)`, +`ops.inArray(...)`). Per operator: + +| Operator | Requires index | `queryType` sent to `encryptQuery` | Emitted SQL | +| --- | --- | --- | --- | +| `eq` / `ne` | `unique` or `ore` | `equality` | `unique` → `eq_term = hmac_256`; else `ord_term =/<> ore_block_256` | +| `gt`/`gte`/`lt`/`lte` | `ore` | `orderAndRange` | `ord_term </<=/>/>= ore_block_256` | +| `between` / `notBetween` | `ore` | `orderAndRange` | `ord_term >= ore_block_256($min) AND ord_term <= ore_block_256($max)`, NOT-wrapped for `notBetween` | +| `like`/`ilike`/`notIlike` | `match` | `freeTextSearch` | `match_term @> bloom_filter`, NOT-wrapped for `notIlike` | +| `inArray`/`notInArray` | `unique` or `ore` | `equality` | OR of `eq` terms / AND of `ne` terms | +| `asc` / `desc` | `ore` | — | `ORDER BY eql_v3.ord_term(col)` | +| `isNull`/`isNotNull`/`not`/`exists`/`notExists` | — | — | pass-through Drizzle operators | + +Term encryption reuses the column's recovered `eql/v3` builder + its owning +`encryptedTable` (rebuilt via schema-extraction and cached per table, exactly as v2 +caches the ProtectTable): `client.encryptQuery(value, { table, column, queryType })`. + +**Error handling — no silent fallback.** In v2, an operator on a non-encrypted +column falls through to the plain Drizzle operator. In v3 that is impossible: a v3 +domain column has no plaintext form, and using the wrong operator emits SQL the +domain CHECK rejects at runtime. So the operators **throw `EncryptionOperatorError`** +(reusing the v2 error class name) when a column lacks the required index — e.g. +`ops.gt` on a `types.TextEq` column (equality-only, no `ore`), or `ops.ilike` on a +column without `match`. The message names the column, operator, and the missing +capability. A non-v3 column passed to a v3 operator also throws (it can't be a v3 +domain), rather than silently degrading. + +### 5.4 Schema extraction (`schema-extraction.ts`) + +`extractEncryptionSchemaV3(drizzleTable)` iterates the Drizzle columns, recovers each +stashed `eql/v3` builder via detection, and returns +`encryptedTable(tableName, { <property>: builder, … })` — ready for +`EncryptionV3({ schemas: [users] })`. Throws if the table has no v3 columns (mirrors +v2's `extractEncryptionSchema`). Operators call this internally to resolve the +`encryptedTable` for a column's parent table, caching per table name. + +## 6. Data flow (per query) + +```text +types.IntegerOrd('age') // authoring + → customType dataType() = 'eql_v3.integer_ord', stash eql/v3 builder +pgTable('users', { age }) // Drizzle table + +extractEncryptionSchemaV3(users) // → encryptedTable('users', { age: <builder> }) +EncryptionV3({ schemas: [users-schema] }) // typed client + +await ops.gte(users.age, 30) + → recover builder (ore index present ✓) + → client.encryptQuery(30, { table, column, queryType: 'orderAndRange' }) // term + → sql`eql_v3.ord_term(${users.age}) >= eql_v3.ore_block_256(${term}::jsonb)` +``` + +## 7. Testing + +Mirror `packages/drizzle/__tests__` structure, plus the v3 live-pg pattern from +`packages/stack/__tests__/schema-v3-pg.test.ts`. Location: +`packages/stack/__tests__/drizzle-v3/` (or alongside the existing +`packages/stack/__tests__/drizzle-*.test.ts` files, matching whatever the v2 drizzle +tests in stack already use). + +**Unit (no DB):** +- `types.*` produce the correct `dataType()` domain string for a representative set + across every scalar family and capability tier. +- Codec round-trip (object ⇄ jsonb string; null ⇄ SQL NULL). +- `extractEncryptionSchemaV3` rebuilds the expected `encryptedTable` (`build()` + output equals the directly-authored `eql/v3` table's). +- Operator SQL emission via a mock client + `PgDialect`: assert exact + `eql_v3.eq_term/ord_term/match_term` + `hmac_256/ore_block_256/bloom_filter` + strings and the equality-via-ORE branch on an order-only numeric column. +- Gating errors: `gt` on equality-only, `ilike` on non-match column, and a non-v3 + column passed into a v3 operator. + +**Live pg** (gated by `LIVE_EQL_V3_PG_ENABLED`, install via `installEqlV3IfNeeded`): +- One `pgTable` with a representative column per tier: `types.TextSearch('email')`, + `types.IntegerOrd('age')`, `types.TextEq('nickname')`, `types.Boolean('active')`. +- Seed with `EncryptionV3(...).bulkEncryptModels` (or raw insert with + `$::eql_v3.<domain>` casts), then real Drizzle `select().where(await ops.eq(...))`, + `ops.gte(...)`, `ops.between(...)`, `ops.ilike(...)`, `orderBy(ops.asc(...))`; + decrypt; assert the selected rows. Use `test_run_id` isolation like the v2 suite. + +## 8. Open implementation details (resolved during build, not blocking) + +- Exact test directory name / whether to gate live tests behind the same env var the + stack v3 pg tests use (`LIVE_EQL_V3_PG_ENABLED`) — adopt the existing helper. +- Whether `between` on a text order domain (which has both `unique` and `ore`) needs + any special handling — it uses `ore`, same as numeric; verify against a live row. +- Confirm the postgres driver path Drizzle uses binds `$::jsonb` correctly for the + term param (the pg tests use `sql.json(...)`; Drizzle's `bindIfParam` + `::jsonb` + cast is the equivalent — assert in a live round-trip). + +## 9. Non-goals / follow-ups (tracked, not in this milestone) + +- v3 JSON / `ste_vec` operators once a v3 JSON column builder ships. +- int8 / bigint once the FFI round-trips losslessly. +- Mirroring into the standalone `@cipherstash/drizzle` package (only if it must ship + v3 independently of `@cipherstash/stack`). +- drizzle-kit migration generation for v3 domains (the v2 `generate-eql-migration` + path emits `eql_v2_encrypted`; a v3 equivalent is a separate effort). diff --git a/e2e/wasm/deno.json b/e2e/wasm/deno.json index 47901fe8..c4928e71 100644 --- a/e2e/wasm/deno.json +++ b/e2e/wasm/deno.json @@ -9,7 +9,7 @@ }, "imports": { "@cipherstash/stack/wasm-inline": "../../packages/stack/dist/wasm-inline.js", - "@cipherstash/protect-ffi/wasm-inline": "npm:@cipherstash/protect-ffi@0.26.0/wasm-inline", + "@cipherstash/protect-ffi/wasm-inline": "npm:@cipherstash/protect-ffi@0.28.0/wasm-inline", "@cipherstash/auth/wasm-inline": "npm:@cipherstash/auth@0.40.0/wasm-inline" } } diff --git a/packages/cli/tests/helpers/run.ts b/packages/cli/tests/helpers/run.ts index 91254296..38c6cf03 100644 --- a/packages/cli/tests/helpers/run.ts +++ b/packages/cli/tests/helpers/run.ts @@ -59,19 +59,24 @@ export function run(args: string[], opts: RunOptions = {}): Promise<RunResult> { let stdout = '' let stderr = '' + // Preserve the true interleaving order of the combined transcript by + // recording chunks as they arrive, while keeping stdout/stderr separate. + const chunks: string[] = [] child.stdout.setEncoding('utf8') child.stderr.setEncoding('utf8') child.stdout.on('data', (d: string) => { stdout += d + chunks.push(d) }) child.stderr.on('data', (d: string) => { stderr += d + chunks.push(d) }) return new Promise<RunResult>((res, rej) => { child.on('error', rej) child.on('close', (code, signal) => { - res(buildRunResult(code, signal, stdout, stderr)) + res(buildRunResult(code, signal, stdout, stderr, chunks.join(''))) }) }) } @@ -83,14 +88,20 @@ export function run(args: string[], opts: RunOptions = {}): Promise<RunResult> { * `code`/`signal` is non-null on `'close'` — this must never coerce a null * `code` to `0`, or a signal-terminated child (crash, SIGKILL, OOM) would be * misreported as a clean exit. + * + * `raw` defaults to `stdout + stderr` (fine for the unit tests below, which + * pass pre-baked strings with no real interleaving to preserve); `run()` + * itself always passes the chunk-interleaved transcript explicitly, since + * naive concatenation can reorder output relative to a real child process's + * actual stdout/stderr write sequence. */ export function buildRunResult( code: number | null, signal: NodeJS.Signals | null, stdout: string, stderr: string, + raw: string = stdout + stderr, ): RunResult { - const raw = stdout + stderr return { exitCode: code, signal, diff --git a/packages/stack/__tests__/cjs-require.test.ts b/packages/stack/__tests__/cjs-require.test.ts index 1a79ec46..b1b7c0ba 100644 --- a/packages/stack/__tests__/cjs-require.test.ts +++ b/packages/stack/__tests__/cjs-require.test.ts @@ -83,6 +83,46 @@ describe('CJS consumers can require the built bundles', () => { it('discovers at least the public entry points', () => { expect(cjsEntries).toContain('dist/index.cjs') expect(cjsEntries).toContain('dist/encryption/index.cjs') + expect(cjsEntries).toContain('dist/eql/v3/index.cjs') + expect(cjsEntries).toContain('dist/eql/v3/drizzle/index.cjs') + }) + + it('exposes the drizzle integration from the CJS bundle', () => { + const drizzleBundle = path.join( + distDir, + 'eql', + 'v3', + 'drizzle', + 'index.cjs', + ) + const script = [ + `const drizzle = require(${JSON.stringify(drizzleBundle)})`, + `if (typeof drizzle.createEncryptionOperatorsV3 !== 'function') { throw new Error('missing drizzle CJS export: createEncryptionOperatorsV3') }`, + `if (typeof drizzle.EncryptionOperatorError !== 'function') { throw new Error('missing drizzle CJS export: EncryptionOperatorError') }`, + `if (typeof drizzle.types !== 'object' || drizzle.types === null) { throw new Error('missing drizzle CJS export: types namespace') }`, + `if (typeof drizzle.types.IntegerOrd !== 'function') { throw new Error('missing drizzle types.IntegerOrd CJS export') }`, + ].join('\n') + execFileSync(process.execPath, ['-e', script]) + }) + + it('exposes the v3 `types` namespace + table API from the CJS bundle', () => { + const v3Bundle = path.join(distDir, 'eql', 'v3', 'index.cjs') + const script = [ + `const v3 = require(${JSON.stringify(v3Bundle)})`, + `if (typeof v3.encryptedTable !== 'function') { throw new Error('missing v3 CJS export: encryptedTable') }`, + `if (typeof v3.buildEncryptConfig !== 'function') { throw new Error('missing v3 CJS export: buildEncryptConfig') }`, + `if (typeof v3.types !== 'object' || v3.types === null) { throw new Error('missing v3 CJS export: types namespace') }`, + `const requiredTypes = ['TextSearch', 'TextEq', 'IntegerOrd', 'Boolean', 'Timestamp']`, + `const missing = requiredTypes.filter((k) => typeof v3.types[k] !== 'function')`, + `if (missing.length > 0) { throw new Error('missing v3 types.* CJS members: ' + missing.join(', ')) }`, + ].join('\n') + + expect(() => + execFileSync(process.execPath, ['-e', script], { + cwd: packageRoot, + stdio: 'pipe', + }), + ).not.toThrow() }) it.each( diff --git a/packages/stack/__tests__/drizzle-v3/codec.test.ts b/packages/stack/__tests__/drizzle-v3/codec.test.ts new file mode 100644 index 00000000..db50fea7 --- /dev/null +++ b/packages/stack/__tests__/drizzle-v3/codec.test.ts @@ -0,0 +1,27 @@ +import { describe, expect, it } from 'vitest' +import { v3FromDriver, v3ToDriver } from '@/eql/v3/drizzle/codec' + +describe('v3 codec', () => { + it('serialises an object to a jsonb string', () => { + expect(v3ToDriver({ v: 1, c: 'ct' })).toBe('{"v":1,"c":"ct"}') + }) + + it('maps null/undefined to SQL NULL (JS null), never the JSON null literal', () => { + expect(v3ToDriver(null)).toBeNull() + expect(v3ToDriver(undefined)).toBeNull() + }) + + it('parses a jsonb string back to an object', () => { + expect(v3FromDriver('{"v":1,"c":"ct"}')).toEqual({ v: 1, c: 'ct' }) + }) + + it('passes an already-parsed object through unchanged', () => { + const obj = { v: 1 } + expect(v3FromDriver(obj)).toBe(obj) + }) + + it('passes null/undefined through on read', () => { + expect(v3FromDriver(null)).toBeNull() + expect(v3FromDriver(undefined)).toBeUndefined() + }) +}) diff --git a/packages/stack/__tests__/drizzle-v3/column.test.ts b/packages/stack/__tests__/drizzle-v3/column.test.ts new file mode 100644 index 00000000..aaff1ea6 --- /dev/null +++ b/packages/stack/__tests__/drizzle-v3/column.test.ts @@ -0,0 +1,96 @@ +import { pgTable } from 'drizzle-orm/pg-core' +import { describe, expect, it } from 'vitest' +import { types as v3Types } from '@/eql/v3' +import { + EQL_V3_DOMAINS, + getEqlV3Column, + isEqlV3Column, + makeEqlV3Column, +} from '@/eql/v3/drizzle/column' +import { typedEntries, V3_MATRIX } from '../v3-matrix/catalog' + +const slug = (eqlType: string) => eqlType.replace('eql_v3.', '') + +describe('makeEqlV3Column', () => { + it('sets dataType() to the concrete eql_v3 domain', () => { + const col = makeEqlV3Column(v3Types.IntegerOrd('age')) + const table = pgTable('users', { age: col }) + + expect(table.age.getSQLType()).toBe('eql_v3.integer_ord') + }) + + it('recovers the stashed builder before and after pgTable processing', () => { + const col = makeEqlV3Column(v3Types.TextEq('nickname')) + expect(isEqlV3Column(col)).toBe(true) + expect(getEqlV3Column('nickname', col)?.getEqlType()).toBe('eql_v3.text_eq') + + const t = pgTable('users', { nickname: col }) + expect(getEqlV3Column('nickname', t.nickname)?.getEqlType()).toBe( + 'eql_v3.text_eq', + ) + }) + + it('EQL_V3_DOMAINS contains every concrete domain', () => { + const all = Object.values(v3Types).map((f) => f('x').getEqlType()) + for (const domain of all) expect(EQL_V3_DOMAINS.has(domain)).toBe(true) + }) + + it('isEqlV3Column is false for a plain value', () => { + expect(isEqlV3Column({})).toBe(false) + }) + + it('recognises v3 columns by the Drizzle getSQLType API', () => { + expect( + isEqlV3Column({ + getSQLType: () => 'eql_v3.text_eq', + }), + ).toBe(true) + }) + + it('recovers a v3 builder for columns recognised by getSQLType', () => { + const builder = getEqlV3Column('nickname', { + getSQLType: () => 'eql_v3.text_eq', + }) + + expect(builder?.getName()).toBe('nickname') + expect(builder?.getEqlType()).toBe('eql_v3.text_eq') + }) + + it('recognises v3 columns by dataType() when getSQLType is absent', () => { + const column = { dataType: () => 'eql_v3.text_eq' } + const builder = getEqlV3Column('nickname', column) + + expect(isEqlV3Column(column)).toBe(true) + expect(builder?.getName()).toBe('nickname') + expect(builder?.getEqlType()).toBe('eql_v3.text_eq') + }) + + it('recognises v3 columns by sqlName when getSQLType is absent', () => { + const column = { sqlName: 'eql_v3.integer_ord' } + const builder = getEqlV3Column('age', column) + + expect(isEqlV3Column(column)).toBe(true) + expect(builder?.getName()).toBe('age') + expect(builder?.getEqlType()).toBe('eql_v3.integer_ord') + }) + + it.each( + typedEntries(V3_MATRIX), + )('%s round-trips through makeEqlV3Column and pgTable', (eqlType, spec) => { + const columnName = slug(eqlType) + const builder = spec.builder(columnName) + const column = makeEqlV3Column(builder) + + expect(builder.getEqlType()).toBe(eqlType) + expect(builder).toBeInstanceOf(spec.ColumnClass) + expect(isEqlV3Column(column)).toBe(true) + expect(getEqlV3Column(columnName, column)?.getEqlType()).toBe(eqlType) + + const table = pgTable('users', { [columnName]: column } as never) + const pgColumn = (table as Record<string, { getSQLType(): string }>)[ + columnName + ] + expect(pgColumn?.getSQLType()).toBe(eqlType) + expect(getEqlV3Column(columnName, pgColumn)?.getEqlType()).toBe(eqlType) + }) +}) diff --git a/packages/stack/__tests__/drizzle-v3/exports.test.ts b/packages/stack/__tests__/drizzle-v3/exports.test.ts new file mode 100644 index 00000000..541c06fa --- /dev/null +++ b/packages/stack/__tests__/drizzle-v3/exports.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from 'vitest' +import * as barrel from '@/eql/v3/drizzle' + +describe('v3 drizzle barrel', () => { + it('exports the public surface', () => { + expect(typeof barrel.createEncryptionOperatorsV3).toBe('function') + expect(typeof barrel.extractEncryptionSchemaV3).toBe('function') + expect(typeof barrel.EncryptionOperatorError).toBe('function') + expect(typeof barrel.types.TextSearch).toBe('function') + expect(barrel.types.IntegerOrd('age')).toBeDefined() + }) +}) diff --git a/packages/stack/__tests__/drizzle-v3/operators-live-pg.test.ts b/packages/stack/__tests__/drizzle-v3/operators-live-pg.test.ts new file mode 100644 index 00000000..a5fea646 --- /dev/null +++ b/packages/stack/__tests__/drizzle-v3/operators-live-pg.test.ts @@ -0,0 +1,559 @@ +import 'dotenv/config' +import { + and, + asc as drizzleAsc, + eq as drizzleEq, + type SQL, + type SQLWrapper, +} from 'drizzle-orm' +import { integer, pgTable, text } from 'drizzle-orm/pg-core' +import { drizzle } from 'drizzle-orm/postgres-js' +import postgres from 'postgres' +import { afterAll, beforeAll, expect, it } from 'vitest' +import { EncryptionV3 } from '@/encryption/v3' +import { + createEncryptionOperatorsV3, + EncryptionOperatorError, + extractEncryptionSchemaV3, +} from '@/eql/v3/drizzle' +import { makeEqlV3Column } from '@/eql/v3/drizzle/column' +import { installEqlV3IfNeeded } from '../helpers/eql-v3' +import { describeLivePg, LIVE_EQL_V3_PG_ENABLED } from '../helpers/live-gate' +import { + type DomainSpec, + type EqlV3TypeName, + typedEntries, + V3_MATRIX, +} from '../v3-matrix/catalog' + +const url = process.env.DATABASE_URL +const sqlClient = LIVE_EQL_V3_PG_ENABLED + ? postgres(url as string, { prepare: false }) + : (undefined as unknown as postgres.Sql) + +const TABLE_NAME = 'protect_ci_v3_drizzle_matrix' +const ACCOUNT_TABLE_NAME = 'protect_ci_v3_drizzle_matrix_accounts' +const RUN = `run-${Date.now()}-${Math.random().toString(36).slice(2, 8)}` +const ROW_A = 'row-a' +const ROW_B = 'row-b' + +const slug = (eqlType: EqlV3TypeName): string => eqlType.replace('eql_v3.', '') +const matrixEntries = typedEntries(V3_MATRIX) +const matrixColumns = Object.fromEntries( + matrixEntries.map(([eqlType, spec]) => [ + slug(eqlType), + makeEqlV3Column(spec.builder(slug(eqlType))), + ]), +) + +const matrixTable = pgTable(TABLE_NAME, { + id: integer('id').primaryKey().generatedAlwaysAsIdentity(), + rowKey: text('row_key').notNull(), + testRunId: text('test_run_id').notNull(), + nullableTextEq: makeEqlV3Column( + V3_MATRIX['eql_v3.text_eq'].builder('nullable_text_eq'), + ), + ...matrixColumns, +} as never) + +const accountsTable = pgTable(ACCOUNT_TABLE_NAME, { + id: integer('id').primaryKey().generatedAlwaysAsIdentity(), + rowKey: text('row_key').notNull(), + label: text('label').notNull(), + testRunId: text('test_run_id').notNull(), +}) + +const schema = extractEncryptionSchemaV3(matrixTable) + +type PlainValue = string | number | boolean | Date +type RowKey = typeof ROW_A | typeof ROW_B +type MatrixPlainRow = Record<string, PlainValue | null | string> +type MatrixDbRow = Record<string, unknown> +type SelectRow = { rowKey: string } +type Db = ReturnType<typeof drizzle> +type Client = Awaited<ReturnType<typeof EncryptionV3>> +type Ops = ReturnType<typeof createEncryptionOperatorsV3> +type ComparisonOperator = 'gt' | 'gte' | 'lt' | 'lte' + +let client: Client +let ops: Ops +let db: Db + +const equalityDomains = matrixEntries.filter( + ([, spec]) => spec.indexes.unique || spec.indexes.ore, +) +const orderDomains = matrixEntries.filter(([, spec]) => spec.indexes.ore) +const matchDomains = matrixEntries.filter(([, spec]) => spec.indexes.match) +const noEqualityDomains = matrixEntries.filter( + ([, spec]) => !spec.indexes.unique && !spec.indexes.ore, +) +const noOrderDomains = matrixEntries.filter(([, spec]) => !spec.indexes.ore) +const noMatchDomains = matrixEntries.filter(([, spec]) => !spec.indexes.match) +const comparisonOperators: Array< + [ComparisonOperator, (cmp: number) => boolean] +> = [ + ['gt', (cmp) => cmp > 0], + ['gte', (cmp) => cmp >= 0], + ['lt', (cmp) => cmp < 0], + ['lte', (cmp) => cmp <= 0], +] +const comparisonDomains = orderDomains.flatMap(([eqlType, spec]) => + comparisonOperators.map( + ([operator, predicate]) => [eqlType, spec, operator, predicate] as const, + ), +) + +const matrixColumn = (eqlType: EqlV3TypeName): SQLWrapper => + (matrixTable as unknown as Record<string, SQLWrapper>)[slug(eqlType)] + +const scoped = (cond: SQL | undefined): SQL | undefined => + cond ? and(drizzleEq(matrixTable.testRunId, RUN), cond) : cond + +const plainValue = (spec: DomainSpec, rowKey: RowKey): PlainValue => + spec.samples[rowKey === ROW_A ? 0 : 1] + +function comparePlain(left: PlainValue, right: PlainValue): number { + if (left instanceof Date && right instanceof Date) { + return left.getTime() - right.getTime() + } + if (typeof left === 'number' && typeof right === 'number') { + return left - right + } + if (typeof left === 'string' && typeof right === 'string') { + // eql_v3 text ordering (ORE) is BYTEWISE, not locale-collated: the oracle + // must model codepoint order, not `localeCompare` (which folds case, + // reorders punctuation vs letters, and is locale-dependent). Text samples + // must stay ASCII/unambiguous so UTF-16 code-unit order == the byte order + // the DB actually sorts by. + return left < right ? -1 : left > right ? 1 : 0 + } + throw new Error( + `Unsupported ordered values: ${String(left)}, ${String(right)}`, + ) +} + +function expectedKeysFor( + spec: DomainSpec, + predicate: (value: PlainValue) => boolean, +): RowKey[] { + return ([ROW_A, ROW_B] as const).filter((rowKey) => + predicate(plainValue(spec, rowKey)), + ) +} + +function sortedKeysFor(spec: DomainSpec, direction: 'asc' | 'desc'): RowKey[] { + return ([ROW_A, ROW_B] as const).sort((left, right) => { + const cmp = comparePlain(plainValue(spec, left), plainValue(spec, right)) + return direction === 'asc' ? cmp : -cmp + }) +} + +async function selectRowKeys(condition: SQL | undefined): Promise<string[]> { + if (!condition) throw new Error('Expected query condition') + const rows = (await db + .select({ rowKey: matrixTable.rowKey }) + .from(matrixTable) + .where(scoped(condition)) + .orderBy(drizzleAsc(matrixTable.rowKey))) as SelectRow[] + return rows.map((row) => row.rowKey) +} + +function unwrap<T>(result: { data?: T; failure?: { message: string } }): T { + if (result.failure) throw new Error(result.failure.message) + return result.data as T +} + +function encryptedInsertRows(): MatrixPlainRow[] { + return ([ROW_A, ROW_B] as const).map((rowKey) => { + const row: MatrixPlainRow = { + rowKey, + testRunId: RUN, + nullableTextEq: rowKey === ROW_A ? null : 'nullable-present', + } + for (const [eqlType, spec] of matrixEntries) { + row[slug(eqlType)] = plainValue(spec, rowKey) + } + return row + }) +} + +beforeAll(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + await installEqlV3IfNeeded(sqlClient) + client = await EncryptionV3({ schemas: [schema] }) + ops = createEncryptionOperatorsV3(client) + db = drizzle({ client: sqlClient }) + + const columnDefs = matrixEntries + .map(([eqlType]) => `"${slug(eqlType)}" ${eqlType} NOT NULL`) + .join(',\n ') + + await sqlClient.unsafe(` + CREATE TABLE IF NOT EXISTS ${TABLE_NAME} ( + id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + row_key TEXT NOT NULL, + test_run_id TEXT NOT NULL, + nullable_text_eq eql_v3.text_eq, + ${columnDefs} + ) + `) + await sqlClient.unsafe(` + CREATE TABLE IF NOT EXISTS ${ACCOUNT_TABLE_NAME} ( + id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + row_key TEXT NOT NULL, + label TEXT NOT NULL, + test_run_id TEXT NOT NULL + ) + `) + + const encryptedRows = unwrap<MatrixDbRow[]>( + await client.bulkEncryptModels(encryptedInsertRows(), schema), + ) + await db.insert(matrixTable).values(encryptedRows) + await db.insert(accountsTable).values([ + { rowKey: ROW_A, label: 'primary', testRunId: RUN }, + { rowKey: ROW_B, label: 'secondary', testRunId: RUN }, + ]) +}, 120000) + +afterAll(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + await sqlClient`DELETE FROM ${sqlClient(TABLE_NAME)} WHERE test_run_id = ${RUN}` + await sqlClient`DELETE FROM ${sqlClient(ACCOUNT_TABLE_NAME)} WHERE test_run_id = ${RUN}` + await sqlClient.end() +}, 30000) + +describeLivePg('v3 drizzle operators (live pg matrix)', () => { + it.each(equalityDomains)( + '%s eq selects the exact row', + async (eqlType, spec) => { + const rows = await selectRowKeys( + await ops.eq(matrixColumn(eqlType), plainValue(spec, ROW_A)), + ) + expect(rows).toEqual([ROW_A]) + }, + 30000, + ) + + it.each(equalityDomains)( + '%s ne selects the complement row', + async (eqlType, spec) => { + const rows = await selectRowKeys( + await ops.ne(matrixColumn(eqlType), plainValue(spec, ROW_A)), + ) + expect(rows).toEqual([ROW_B]) + }, + 30000, + ) + + it.each(equalityDomains)( + '%s inArray selects all listed rows', + async (eqlType, spec) => { + const rows = await selectRowKeys( + await ops.inArray(matrixColumn(eqlType), [ + plainValue(spec, ROW_A), + plainValue(spec, ROW_B), + ]), + ) + expect(rows).toEqual([ROW_A, ROW_B]) + }, + 30000, + ) + + it.each(equalityDomains)( + '%s notInArray excludes listed rows', + async (eqlType, spec) => { + const rows = await selectRowKeys( + await ops.notInArray(matrixColumn(eqlType), [plainValue(spec, ROW_A)]), + ) + expect(rows).toEqual([ROW_B]) + }, + 30000, + ) + + it.each(comparisonDomains)( + '%s %s selects rows by encrypted ordering', + async (eqlType, spec, operator, predicate) => { + const bound = plainValue(spec, ROW_A) + const rows = await selectRowKeys( + await ops[operator](matrixColumn(eqlType), bound), + ) + expect(rows).toEqual( + expectedKeysFor(spec, (value) => predicate(comparePlain(value, bound))), + ) + }, + 30000, + ) + + it.each(orderDomains)( + '%s between selects the inclusive range', + async (eqlType, spec) => { + const sortedValues = [ + plainValue(spec, ROW_A), + plainValue(spec, ROW_B), + ].sort(comparePlain) + const rows = await selectRowKeys( + await ops.between( + matrixColumn(eqlType), + sortedValues[0], + sortedValues[1], + ), + ) + expect(rows).toEqual([ROW_A, ROW_B]) + }, + 30000, + ) + + it.each(orderDomains)( + '%s notBetween excludes the inclusive range', + async (eqlType, spec) => { + const sortedValues = [ + plainValue(spec, ROW_A), + plainValue(spec, ROW_B), + ].sort(comparePlain) + const rows = await selectRowKeys( + await ops.notBetween( + matrixColumn(eqlType), + sortedValues[0], + sortedValues[1], + ), + ) + expect(rows).toEqual([]) + }, + 30000, + ) + + // The spanning cases above only ever prove INCLUSION (both rows are inside + // the range, so `between` -> [A,B] and `notBetween` -> []). These narrow + // cases use a single-point range at ROW_A's value to prove the operators + // also EXCLUDE: `between` must drop ROW_B, `notBetween` must keep it. Without + // these, a `between` that matched everything (or a `notBetween` no-op) passes. + it.each(orderDomains)( + '%s between at a single point excludes the out-of-range row', + async (eqlType, spec) => { + const bound = plainValue(spec, ROW_A) + const rows = await selectRowKeys( + await ops.between(matrixColumn(eqlType), bound, bound), + ) + expect(rows).toEqual( + expectedKeysFor(spec, (value) => comparePlain(value, bound) === 0), + ) + }, + 30000, + ) + + it.each(orderDomains)( + '%s notBetween at a single point keeps the out-of-range row', + async (eqlType, spec) => { + const bound = plainValue(spec, ROW_A) + const rows = await selectRowKeys( + await ops.notBetween(matrixColumn(eqlType), bound, bound), + ) + expect(rows).toEqual( + expectedKeysFor(spec, (value) => comparePlain(value, bound) !== 0), + ) + }, + 30000, + ) + + it.each(orderDomains)( + '%s asc orders by encrypted order term', + async (eqlType, spec) => { + const rows = (await db + .select({ rowKey: matrixTable.rowKey }) + .from(matrixTable) + .where(drizzleEq(matrixTable.testRunId, RUN)) + .orderBy(ops.asc(matrixColumn(eqlType)))) as SelectRow[] + expect(rows.map((row) => row.rowKey)).toEqual(sortedKeysFor(spec, 'asc')) + }, + 30000, + ) + + it.each(orderDomains)( + '%s desc orders by encrypted order term', + async (eqlType, spec) => { + const rows = (await db + .select({ rowKey: matrixTable.rowKey }) + .from(matrixTable) + .where(drizzleEq(matrixTable.testRunId, RUN)) + .orderBy(ops.desc(matrixColumn(eqlType)))) as SelectRow[] + expect(rows.map((row) => row.rowKey)).toEqual(sortedKeysFor(spec, 'desc')) + }, + 30000, + ) + + it.each(matchDomains)( + '%s contains matches plaintext terms', + async (eqlType, spec) => { + const rows = await selectRowKeys( + await ops.contains(matrixColumn(eqlType), 'ada'), + ) + expect(rows).toEqual( + expectedKeysFor(spec, (value) => + String(value).toLowerCase().includes('ada'), + ), + ) + }, + 30000, + ) + + it.each( + noEqualityDomains, + )('%s eq rejects unsupported equality', async (eqlType, spec) => { + await expect( + ops.eq(matrixColumn(eqlType), plainValue(spec, ROW_A)), + ).rejects.toBeInstanceOf(EncryptionOperatorError) + }) + + it.each( + noOrderDomains, + )('%s gt rejects unsupported ordering', async (eqlType, spec) => { + await expect( + ops.gt(matrixColumn(eqlType), plainValue(spec, ROW_A)), + ).rejects.toBeInstanceOf(EncryptionOperatorError) + }) + + it.each(noOrderDomains)('%s asc rejects unsupported ordering', (eqlType) => { + expect(() => ops.asc(matrixColumn(eqlType))).toThrow( + EncryptionOperatorError, + ) + }) + + it.each( + noMatchDomains, + )('%s contains rejects unsupported match', async (eqlType, spec) => { + await expect( + ops.contains(matrixColumn(eqlType), plainValue(spec, ROW_A)), + ).rejects.toBeInstanceOf(EncryptionOperatorError) + }) + + it('and combines encrypted predicates', async () => { + const rows = await selectRowKeys( + await ops.and( + ops.eq(matrixColumn('eql_v3.text_eq'), 'ada@example.com'), + ops.lt(matrixColumn('eql_v3.integer_ord'), 0), + ), + ) + expect(rows).toEqual([ROW_B]) + }, 30000) + + it('or combines encrypted predicates', async () => { + const rows = await selectRowKeys( + await ops.or( + ops.eq(matrixColumn('eql_v3.text_eq'), ''), + ops.eq(matrixColumn('eql_v3.text_eq'), 'ada@example.com'), + ), + ) + expect(rows).toEqual([ROW_A, ROW_B]) + }, 30000) + + it('not negates an encrypted predicate', async () => { + const rows = await selectRowKeys( + ops.not(await ops.eq(matrixColumn('eql_v3.text_eq'), '')), + ) + expect(rows).toEqual([ROW_B]) + }, 30000) + + it('isNull and isNotNull work on nullable encrypted columns', async () => { + expect(await selectRowKeys(ops.isNull(matrixTable.nullableTextEq))).toEqual( + [ROW_A], + ) + expect( + await selectRowKeys(ops.isNotNull(matrixTable.nullableTextEq)), + ).toEqual([ROW_B]) + }, 30000) + + it('exists and notExists work with correlated subqueries', async () => { + const primaryAccount = db + .select({ id: accountsTable.id }) + .from(accountsTable) + .where( + and( + drizzleEq(accountsTable.testRunId, RUN), + drizzleEq(accountsTable.rowKey, matrixTable.rowKey), + drizzleEq(accountsTable.label, 'primary'), + ), + ) + const missingAccount = db + .select({ id: accountsTable.id }) + .from(accountsTable) + .where( + and( + drizzleEq(accountsTable.testRunId, RUN), + drizzleEq(accountsTable.rowKey, matrixTable.rowKey), + drizzleEq(accountsTable.label, 'missing'), + ), + ) + + expect(await selectRowKeys(ops.exists(primaryAccount))).toEqual([ROW_A]) + expect(await selectRowKeys(ops.notExists(missingAccount))).toEqual([ + ROW_A, + ROW_B, + ]) + }, 30000) + + it('joins plain tables while filtering encrypted columns', async () => { + const rows = (await db + .select({ rowKey: matrixTable.rowKey }) + .from(matrixTable) + .innerJoin( + accountsTable, + and( + drizzleEq(accountsTable.testRunId, RUN), + drizzleEq(accountsTable.rowKey, matrixTable.rowKey), + ), + ) + .where( + scoped(await ops.eq(matrixColumn('eql_v3.text_eq'), 'ada@example.com')), + )) as SelectRow[] + expect(rows.map((row) => row.rowKey)).toEqual([ROW_B]) + }, 30000) + + it('paginates encrypted ordering results with limit and offset', async () => { + const spec = V3_MATRIX['eql_v3.integer_ord'] + const rows = (await db + .select({ rowKey: matrixTable.rowKey }) + .from(matrixTable) + .where(drizzleEq(matrixTable.testRunId, RUN)) + .orderBy(ops.asc(matrixColumn('eql_v3.integer_ord'))) + .limit(1) + .offset(1)) as SelectRow[] + expect(rows.map((row) => row.rowKey)).toEqual( + sortedKeysFor(spec, 'asc').slice(1, 2), + ) + }, 30000) + + // The matrix inArray/notInArray cases above use 2-element lists, so the + // MAX_IN_ARRAY_CONCURRENCY=4 worker pool (operators.ts) never actually + // concurrently encrypts more terms than the serial path would. These cross + // the pool boundary: 5 values (> 4) forces the pool to reuse workers, and + // must still produce the correct OR/AND of eq/ne terms. + it('inArray encrypts a >4-value list through the concurrency pool', async () => { + const rows = await selectRowKeys( + await ops.inArray(matrixColumn('eql_v3.text_eq'), [ + 'ada@example.com', + '', + 'nobody-1@example.com', + 'nobody-2@example.com', + 'nobody-3@example.com', + ]), + ) + // '' -> ROW_A, 'ada@example.com' -> ROW_B; the three "nobody" terms match + // nothing, exercising the pool without changing the expected set. + expect(rows).toEqual([ROW_A, ROW_B]) + }, 30000) + + it('notInArray encrypts a >4-value list through the concurrency pool', async () => { + const rows = await selectRowKeys( + await ops.notInArray(matrixColumn('eql_v3.text_eq'), [ + '', + 'nobody-1@example.com', + 'nobody-2@example.com', + 'nobody-3@example.com', + 'nobody-4@example.com', + ]), + ) + // Only '' is excluded (ROW_A); ROW_B ('ada@example.com') survives. + expect(rows).toEqual([ROW_B]) + }, 30000) +}) diff --git a/packages/stack/__tests__/drizzle-v3/operators-lock-context-live-pg.test.ts b/packages/stack/__tests__/drizzle-v3/operators-lock-context-live-pg.test.ts new file mode 100644 index 00000000..49c59b71 --- /dev/null +++ b/packages/stack/__tests__/drizzle-v3/operators-lock-context-live-pg.test.ts @@ -0,0 +1,181 @@ +/** + * Live, identity-bound querying through the v3 Drizzle operator path. + * + * `matrix-identity-live.test.ts` proves lock context round-trips through the + * typed CLIENT (`encryptModel`/`decryptModel`), and `operators.test.ts` proves + * the Drizzle operators FORWARD `lockContext`/`audit` — but only against a + * MOCKED FFI. Nothing exercises the one end-to-end shape that matters most: + * seed rows bound to an identity, then query them with `ops.eq(col, value, + * { lockContext })` against a real database and assert the encrypted term + * actually matches the stored row and decrypts. + * + * Wiring mirrors `lock-context.test.ts` (the current, non-deprecated + * strategy-based flow): the client authenticates as the end user via + * `OidcFederationStrategy` and binds the key to the `sub` claim with a plain + * `.withLockContext({ identityClaim })`. + * + * Gated twice: `describeLivePg` (needs `DATABASE_URL` + CS creds) and an inner + * `USER_JWT` guard (soft-skip, matching the existing identity/lock-context + * suites). Whether the searchable index terms are themselves identity-bound is + * decided inside `@cipherstash/protect-ffi`, not this repo — so we assert the + * SYMMETRIC behaviour (same lock context on seed + query matches and decrypts), + * not a cross-identity non-match. + */ +import 'dotenv/config' +import { OidcFederationStrategy } from '@cipherstash/auth' +import { and, asc as drizzleAsc, eq as drizzleEq, type SQL } from 'drizzle-orm' +import { integer, pgTable, text } from 'drizzle-orm/pg-core' +import { drizzle } from 'drizzle-orm/postgres-js' +import postgres from 'postgres' +import { afterAll, beforeAll, expect, it } from 'vitest' +import { EncryptionV3 } from '@/encryption/v3' +import { + createEncryptionOperatorsV3, + extractEncryptionSchemaV3, +} from '@/eql/v3/drizzle' +import { makeEqlV3Column } from '@/eql/v3/drizzle/column' +import { installEqlV3IfNeeded } from '../helpers/eql-v3' +import { describeLivePg, LIVE_EQL_V3_PG_ENABLED } from '../helpers/live-gate' +import { V3_MATRIX } from '../v3-matrix/catalog' + +const url = process.env.DATABASE_URL +const sqlClient = LIVE_EQL_V3_PG_ENABLED + ? postgres(url as string, { prepare: false }) + : (undefined as unknown as postgres.Sql) + +const TABLE_NAME = 'protect_ci_v3_drizzle_lock_context' +const RUN = `run-${Date.now()}-${Math.random().toString(36).slice(2, 8)}` +const ROW_A = 'row-a' +const ROW_B = 'row-b' +const SECRET_A = 'ada@example.com' +const SECRET_B = 'grace@example.com' + +// A fixed identity claim; the same value must be supplied on encrypt and query +// for the terms/keys to reproduce. +const IDENTITY_CLAIM = { identityClaim: ['sub'] } + +const secretTable = pgTable(TABLE_NAME, { + id: integer('id').primaryKey().generatedAlwaysAsIdentity(), + rowKey: text('row_key').notNull(), + testRunId: text('test_run_id').notNull(), + secret: makeEqlV3Column(V3_MATRIX['eql_v3.text_eq'].builder('secret')), +} as never) + +const schema = extractEncryptionSchemaV3(secretTable) + +type SelectRow = { rowKey: string } + +let client: Awaited<ReturnType<typeof EncryptionV3>> +let ops: ReturnType<typeof createEncryptionOperatorsV3> +let db: ReturnType<typeof drizzle> +let userJwt: string | undefined + +function unwrap<T>(result: { data?: T; failure?: { message: string } }): T { + if (result.failure) throw new Error(result.failure.message) + return result.data as T +} + +/** Run-scoped SELECT of row keys under an already-encrypted SQL condition. */ +async function selectRowKeys(condition: SQL): Promise<string[]> { + const rows = (await db + .select({ rowKey: secretTable.rowKey }) + .from(secretTable) + .where(and(drizzleEq(secretTable.testRunId, RUN), condition)) + .orderBy(drizzleAsc(secretTable.rowKey))) as SelectRow[] + return rows.map((row) => row.rowKey) +} + +beforeAll(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + userJwt = process.env.USER_JWT + if (!userJwt) return + + const crn = process.env.CS_WORKSPACE_CRN + if (!crn) + throw new Error('CS_WORKSPACE_CRN must be set for lock-context tests') + + await installEqlV3IfNeeded(sqlClient) + client = await EncryptionV3({ + schemas: [schema], + config: { + strategy: OidcFederationStrategy.create(crn, () => + Promise.resolve(userJwt as string), + ), + }, + }) + ops = createEncryptionOperatorsV3(client) + db = drizzle({ client: sqlClient }) + + await sqlClient.unsafe(` + CREATE TABLE IF NOT EXISTS ${TABLE_NAME} ( + id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + row_key TEXT NOT NULL, + test_run_id TEXT NOT NULL, + secret eql_v3.text_eq NOT NULL + ) + `) + + // Seed BOTH rows bound to the same lock context. + const encryptedRows = unwrap<Array<Record<string, unknown>>>( + await client + .bulkEncryptModels( + [ + { rowKey: ROW_A, testRunId: RUN, secret: SECRET_A }, + { rowKey: ROW_B, testRunId: RUN, secret: SECRET_B }, + ] as never, + schema, + ) + .withLockContext(IDENTITY_CLAIM), + ) + await db.insert(secretTable).values(encryptedRows as never) +}, 120000) + +afterAll(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + if (userJwt) { + await sqlClient`DELETE FROM ${sqlClient(TABLE_NAME)} WHERE test_run_id = ${RUN}` + } + await sqlClient.end() +}, 30000) + +describeLivePg('v3 drizzle operators with lock context (live pg)', () => { + const skipUnlessJwt = (): boolean => { + if (!userJwt) { + console.log('Skipping lock-context operator test - no USER_JWT provided') + return true + } + return false + } + + it('eq with a matching lock context selects the exact row', async () => { + if (skipUnlessJwt()) return + const condition = await ops.eq(secretTable.secret, SECRET_A, { + // Runtime accepts a plain { identityClaim } (forwarded to + // withLockContext); the operator opts type is narrowed to LockContext. + lockContext: IDENTITY_CLAIM as never, + }) + expect(await selectRowKeys(condition)).toEqual([ROW_A]) + }, 30000) + + it('a lock-context-bound row decrypts with the same lock context', async () => { + if (skipUnlessJwt()) return + const [row] = await sqlClient.unsafe<Array<{ value: unknown }>>( + `SELECT secret::jsonb AS value FROM ${TABLE_NAME} + WHERE test_run_id = $1 AND row_key = $2`, + [RUN, ROW_A], + ) + const decrypted = unwrap( + await client.decrypt(row.value as never).withLockContext(IDENTITY_CLAIM), + ) + expect(decrypted).toBe(SECRET_A) + }, 30000) + + it('eq threads an audit config alongside the lock context', async () => { + if (skipUnlessJwt()) return + const condition = await ops.eq(secretTable.secret, SECRET_B, { + lockContext: IDENTITY_CLAIM as never, + audit: { metadata: { sub: 'toby@cipherstash.com', type: 'query' } }, + }) + expect(await selectRowKeys(condition)).toEqual([ROW_B]) + }, 30000) +}) diff --git a/packages/stack/__tests__/drizzle-v3/operators-null-live-pg.test.ts b/packages/stack/__tests__/drizzle-v3/operators-null-live-pg.test.ts new file mode 100644 index 00000000..263f73b0 --- /dev/null +++ b/packages/stack/__tests__/drizzle-v3/operators-null-live-pg.test.ts @@ -0,0 +1,177 @@ +/** + * Live NULL persistence for encrypted columns across every capability tier. + * + * `operators-live-pg.test.ts` proves `isNull`/`isNotNull` — but only for a + * single `text_eq` column (`nullableTextEq`). NULL storage and retrieval for + * the other tiers (storage-only, order/ORE, free-text match) is untested live: + * a bug that mangled a NULL cell, or a domain that rejected NULL, would only + * show up on those column kinds. + * + * This file seeds two rows — row A all-NULL, row B all-present — across one + * representative column per tier, then asserts, per column: `isNull` selects + * the NULL row, `isNotNull` selects the present row, the NULL cell reads back + * as SQL NULL, and the present cell still decrypts to its plaintext. + */ +import 'dotenv/config' +import { and, asc as drizzleAsc, eq as drizzleEq, type SQL } from 'drizzle-orm' +import { integer, pgTable, text } from 'drizzle-orm/pg-core' +import { drizzle } from 'drizzle-orm/postgres-js' +import postgres from 'postgres' +import { afterAll, beforeAll, expect, it } from 'vitest' +import { EncryptionV3 } from '@/encryption/v3' +import { + createEncryptionOperatorsV3, + extractEncryptionSchemaV3, +} from '@/eql/v3/drizzle' +import { makeEqlV3Column } from '@/eql/v3/drizzle/column' +import { installEqlV3IfNeeded } from '../helpers/eql-v3' +import { describeLivePg, LIVE_EQL_V3_PG_ENABLED } from '../helpers/live-gate' +import { V3_MATRIX } from '../v3-matrix/catalog' + +const url = process.env.DATABASE_URL +const sqlClient = LIVE_EQL_V3_PG_ENABLED + ? postgres(url as string, { prepare: false }) + : (undefined as unknown as postgres.Sql) + +const TABLE_NAME = 'protect_ci_v3_drizzle_nullable' +const RUN = `run-${Date.now()}-${Math.random().toString(36).slice(2, 8)}` +const ROW_A = 'row-a' // all NULL +const ROW_B = 'row-b' // all present + +// One representative column per capability tier, each NULLABLE. +const nullableTable = pgTable(TABLE_NAME, { + id: integer('id').primaryKey().generatedAlwaysAsIdentity(), + rowKey: text('row_key').notNull(), + testRunId: text('test_run_id').notNull(), + storageText: makeEqlV3Column( + V3_MATRIX['eql_v3.text'].builder('storage_text'), + ), + eqText: makeEqlV3Column(V3_MATRIX['eql_v3.text_eq'].builder('eq_text')), + ordInt: makeEqlV3Column(V3_MATRIX['eql_v3.integer_ord'].builder('ord_int')), + matchText: makeEqlV3Column( + V3_MATRIX['eql_v3.text_match'].builder('match_text'), + ), +} as never) + +// Tier metadata: property (drizzle) + DB column + a present-row plaintext. +const TIERS = [ + { + key: 'storageText', + db: 'storage_text', + domain: 'eql_v3.text', + sample: 'stored-secret', + }, + { + key: 'eqText', + db: 'eq_text', + domain: 'eql_v3.text_eq', + sample: 'ada@example.com', + }, + { key: 'ordInt', db: 'ord_int', domain: 'eql_v3.integer_ord', sample: 42 }, + { + key: 'matchText', + db: 'match_text', + domain: 'eql_v3.text_match', + sample: 'ada lovelace', + }, +] as const + +const schema = extractEncryptionSchemaV3(nullableTable) + +type SelectRow = { rowKey: string } + +let client: Awaited<ReturnType<typeof EncryptionV3>> +let ops: ReturnType<typeof createEncryptionOperatorsV3> +let db: ReturnType<typeof drizzle> + +function unwrap<T>(result: { data?: T; failure?: { message: string } }): T { + if (result.failure) throw new Error(result.failure.message) + return result.data as T +} + +const columnFor = (key: string): SQL => + (nullableTable as unknown as Record<string, SQL>)[key] + +async function selectRowKeys(condition: SQL): Promise<string[]> { + const rows = (await db + .select({ rowKey: nullableTable.rowKey }) + .from(nullableTable) + .where(and(drizzleEq(nullableTable.testRunId, RUN), condition)) + .orderBy(drizzleAsc(nullableTable.rowKey))) as SelectRow[] + return rows.map((row) => row.rowKey) +} + +beforeAll(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + await installEqlV3IfNeeded(sqlClient) + client = await EncryptionV3({ schemas: [schema] }) + ops = createEncryptionOperatorsV3(client) + db = drizzle({ client: sqlClient }) + + const columnDefs = TIERS.map((t) => `"${t.db}" ${t.domain}`).join(',\n ') + await sqlClient.unsafe(` + CREATE TABLE IF NOT EXISTS ${TABLE_NAME} ( + id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + row_key TEXT NOT NULL, + test_run_id TEXT NOT NULL, + ${columnDefs} + ) + `) + + // Row A: every encrypted column NULL. Row B: every column present. + const rowA: Record<string, unknown> = { rowKey: ROW_A, testRunId: RUN } + const rowB: Record<string, unknown> = { rowKey: ROW_B, testRunId: RUN } + for (const t of TIERS) { + rowA[t.key] = null + rowB[t.key] = t.sample + } + + const encryptedRows = unwrap<Array<Record<string, unknown>>>( + await client.bulkEncryptModels([rowA, rowB] as never, schema), + ) + await db.insert(nullableTable).values(encryptedRows as never) +}, 120000) + +afterAll(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + await sqlClient`DELETE FROM ${sqlClient(TABLE_NAME)} WHERE test_run_id = ${RUN}` + await sqlClient.end() +}, 30000) + +describeLivePg('v3 drizzle NULL persistence across tiers (live pg)', () => { + it.each(TIERS)('$domain isNull selects the NULL row', async (tier) => { + expect(await selectRowKeys(ops.isNull(columnFor(tier.key)))).toEqual([ + ROW_A, + ]) + }, 30000) + + it.each(TIERS)('$domain isNotNull selects the present row', async (tier) => { + expect(await selectRowKeys(ops.isNotNull(columnFor(tier.key)))).toEqual([ + ROW_B, + ]) + }, 30000) + + it.each( + TIERS, + )('$domain stores a real NULL for the null row', async (tier) => { + const [row] = await sqlClient.unsafe<Array<{ value: unknown }>>( + `SELECT "${tier.db}"::jsonb AS value FROM ${TABLE_NAME} + WHERE test_run_id = $1 AND row_key = $2`, + [RUN, ROW_A], + ) + expect(row.value).toBeNull() + }, 30000) + + it.each( + TIERS, + )('$domain present cell decrypts to its plaintext', async (tier) => { + const [row] = await sqlClient.unsafe<Array<{ value: unknown }>>( + `SELECT "${tier.db}"::jsonb AS value FROM ${TABLE_NAME} + WHERE test_run_id = $1 AND row_key = $2`, + [RUN, ROW_B], + ) + expect(row.value).toHaveProperty('c') + const decrypted = unwrap(await client.decrypt(row.value as never)) + expect(decrypted).toBe(tier.sample) + }, 30000) +}) diff --git a/packages/stack/__tests__/drizzle-v3/operators.test.ts b/packages/stack/__tests__/drizzle-v3/operators.test.ts new file mode 100644 index 00000000..4e680835 --- /dev/null +++ b/packages/stack/__tests__/drizzle-v3/operators.test.ts @@ -0,0 +1,459 @@ +import { + eq as drizzleEq, + exists, + isNotNull, + isNull, + not, + notExists, + type SQL, + type SQLWrapper, + sql, +} from 'drizzle-orm' +import { integer, PgDialect, pgTable } from 'drizzle-orm/pg-core' +import { describe, expect, it, vi } from 'vitest' +import type { EncryptionClient } from '@/encryption' +import { makeEqlV3Column } from '@/eql/v3/drizzle/column' +import { + createEncryptionOperatorsV3, + EncryptionOperatorError, +} from '@/eql/v3/drizzle/operators' +import { extractEncryptionSchemaV3 } from '@/eql/v3/drizzle/schema-extraction' +import { types } from '@/eql/v3/drizzle/types' +import { typedEntries, V3_MATRIX } from '../v3-matrix/catalog' + +const TERM = { c: 'ct', v: 1 } +const TERM_JSON = JSON.stringify(TERM) +const lockContext = { identityClaim: 'user-123' } +const audit = { metadata: { actor: 'test' } } + +type EncryptResult = Promise< + { data: typeof TERM } | { failure: { message: string } } +> + +function chainable(result: EncryptResult) { + const op = result as EncryptResult & { + withLockContext: ReturnType<typeof vi.fn> + audit: ReturnType<typeof vi.fn> + } + op.withLockContext = vi.fn(() => op) + op.audit = vi.fn(() => op) + return op +} + +function setup( + encryptImpl: (...args: unknown[]) => EncryptResult = async () => ({ + data: TERM, + }), +) { + const encrypt = vi.fn((...args: unknown[]) => chainable(encryptImpl(...args))) + const client = { encrypt } as unknown as EncryptionClient + const ops = createEncryptionOperatorsV3(client, { lockContext, audit }) + const dialect = new PgDialect() + const render = (s: unknown) => dialect.sqlToQuery(s as SQL) + return { ops, encrypt, render } +} + +const slug = (eqlType: string) => eqlType.replace('eql_v3.', '') +const matrixEntries = typedEntries(V3_MATRIX) +const matrixTable = pgTable( + 'matrix_users', + Object.fromEntries( + matrixEntries.map(([eqlType, spec]) => [ + slug(eqlType), + makeEqlV3Column(spec.builder(slug(eqlType))), + ]), + ) as never, +) +const matrixColumn = (eqlType: string) => + (matrixTable as Record<string, SQLWrapper>)[slug(eqlType)] +const sampleFor = (spec: (typeof V3_MATRIX)[keyof typeof V3_MATRIX]) => + spec.samples[0] + +const equalityDomains = matrixEntries.filter( + ([, spec]) => spec.indexes.unique || spec.indexes.ore, +) +const orderDomains = matrixEntries.filter(([, spec]) => spec.indexes.ore) +const matchDomains = matrixEntries.filter(([, spec]) => spec.indexes.match) +const storageDomains = matrixEntries.filter( + ([, spec]) => + !spec.indexes.unique && !spec.indexes.ore && !spec.indexes.match, +) + +const users = pgTable('users', { + id: integer().primaryKey(), + email: types.TextSearch('email'), + nickname: types.TextEq('nickname'), + textMatch: types.TextMatch('text_match'), + textOrd: types.TextOrd('text_ord'), + textOrdOre: types.TextOrdOre('text_ord_ore'), + int2Age: types.SmallintOrd('int2_age'), + age: types.IntegerOrd('age'), + createdOn: types.DateOrd('created_on'), + createdAt: types.TimestampOrd('created_at'), + amount: types.NumericOrd('amount'), + score4: types.RealOrd('score4'), + score8: types.DoubleOrd('score8'), + flag: types.Boolean('flag'), +}) + +describe('createEncryptionOperatorsV3 - equality', () => { + it.each( + equalityDomains, + )('%s eq emits the latest two-arg eql_v3.eq with a full-envelope operand', async (eqlType, spec) => { + const { ops, encrypt, render } = setup() + const q = render(await ops.eq(matrixColumn(eqlType), sampleFor(spec))) + + expect(q.sql).toContain( + `eql_v3.eq("matrix_users"."${slug(eqlType)}", $1::jsonb)`, + ) + expect(q.params).toEqual([TERM_JSON]) + expect(encrypt.mock.calls[0]?.[1]?.column.getName()).toBe(slug(eqlType)) + }) + + it.each(equalityDomains)('%s ne emits eql_v3.neq', async (eqlType, spec) => { + const { ops, encrypt, render } = setup() + const q = render(await ops.ne(matrixColumn(eqlType), sampleFor(spec))) + + expect(q.sql).toContain( + `eql_v3.neq("matrix_users"."${slug(eqlType)}", $1::jsonb)`, + ) + expect(q.params).toEqual([TERM_JSON]) + expect(encrypt.mock.calls[0]?.[1]?.column.getName()).toBe(slug(eqlType)) + }) + + it('same-named columns on different tables use their own equality capability', async () => { + const accounts = pgTable('accounts', { + email: types.TextEq('email'), + }) + pgTable('metrics', { + email: types.IntegerOrd('email'), + }) + const { ops, render } = setup() + + const q = render(await ops.eq(accounts.email, 'ada@example.com')) + + expect(q.sql).toContain('eql_v3.eq("accounts"."email", $1::jsonb)') + }) + + it('does not reuse a cached extracted schema across distinct pgTable objects with the same SQL name', async () => { + const first = pgTable('shared', { + email: types.TextEq('email'), + }) + const second = pgTable('shared', { + age: types.IntegerOrd('age'), + }) + const { ops, encrypt } = setup() + + await ops.eq(first.email, 'ada@example.com') + await ops.eq(second.age, 37) + + expect(encrypt.mock.calls[1]?.[1]?.table.build()).toEqual( + extractEncryptionSchemaV3(second).build(), + ) + }) + + it('passes default lock context and audit to operand encryption', async () => { + const { ops, encrypt } = setup() + await ops.eq(users.nickname, 'ada') + const op = encrypt.mock.results[0]?.value + expect(op.withLockContext).toHaveBeenCalledWith(lockContext) + expect(op.audit).toHaveBeenCalledWith(audit) + }) + + it('per-call lock context and audit override constructor defaults', async () => { + const { ops, encrypt } = setup() + const callLockContext = { identityClaim: 'user-456' } + const callAudit = { metadata: { actor: 'override' } } + + await ops.eq(users.nickname, 'ada', { + lockContext: callLockContext, + audit: callAudit, + }) + + const op = encrypt.mock.results[0]?.value + expect(op.withLockContext).toHaveBeenCalledWith(callLockContext) + expect(op.withLockContext).not.toHaveBeenCalledWith(lockContext) + expect(op.audit).toHaveBeenCalledWith(callAudit) + expect(op.audit).not.toHaveBeenCalledWith(audit) + }) +}) + +describe('createEncryptionOperatorsV3 - comparison & range', () => { + it.each([ + ['gt', 'eql_v3.gt'], + ['gte', 'eql_v3.gte'], + ['lt', 'eql_v3.lt'], + ['lte', 'eql_v3.lte'], + ] as const)('%s emits %s for every ORE domain', async (op, fn) => { + for (const [eqlType, spec] of orderDomains) { + const { ops, encrypt, render } = setup() + const q = render(await ops[op](matrixColumn(eqlType), sampleFor(spec))) + + expect(q.sql).toContain( + `${fn}("matrix_users"."${slug(eqlType)}", $1::jsonb)`, + ) + expect(q.params).toEqual([TERM_JSON]) + expect(encrypt.mock.calls[0]?.[1]?.column.getName()).toBe(slug(eqlType)) + } + }) + + it.each( + orderDomains, + )('%s between emits a bounded range with two full-envelope operands', async (eqlType, spec) => { + const { ops, render } = setup() + const value = sampleFor(spec) + const q = render(await ops.between(matrixColumn(eqlType), value, value)) + + expect(q.sql).toContain( + `eql_v3.gte("matrix_users"."${slug(eqlType)}", $1::jsonb)`, + ) + expect(q.sql).toContain( + `eql_v3.lte("matrix_users"."${slug(eqlType)}", $2::jsonb)`, + ) + expect(q.params).toEqual([TERM_JSON, TERM_JSON]) + }) + + it.each( + orderDomains, + )('%s notBetween wraps the range in NOT (...)', async (eqlType, spec) => { + const { ops, render } = setup() + const value = sampleFor(spec) + const q = render(await ops.notBetween(matrixColumn(eqlType), value, value)) + + expect(q.sql).toMatch(/^not \(/i) + expect(q.sql).toContain( + `eql_v3.gte("matrix_users"."${slug(eqlType)}", $1::jsonb)`, + ) + expect(q.sql).toContain( + `eql_v3.lte("matrix_users"."${slug(eqlType)}", $2::jsonb)`, + ) + expect(q.params).toEqual([TERM_JSON, TERM_JSON]) + }) + + it.each(orderDomains)('%s asc / desc extract the ord term', (eqlType) => { + const { ops, render } = setup() + const ascq = render(ops.asc(matrixColumn(eqlType))) + expect(ascq.sql).toContain( + `eql_v3.ord_term("matrix_users"."${slug(eqlType)}")`, + ) + expect(ascq.sql.toLowerCase()).toContain('asc') + + const descq = render(ops.desc(matrixColumn(eqlType))) + expect(descq.sql).toContain( + `eql_v3.ord_term("matrix_users"."${slug(eqlType)}")`, + ) + expect(descq.sql.toLowerCase()).toContain('desc') + }) +}) + +describe('createEncryptionOperatorsV3 - free-text match', () => { + it.each( + matchDomains, + )('%s contains emits latest eql_v3.contains with a full-envelope operand', async (eqlType, spec) => { + const { ops, encrypt, render } = setup() + const q = render(await ops.contains(matrixColumn(eqlType), sampleFor(spec))) + + expect(q.sql).toContain( + `eql_v3.contains("matrix_users"."${slug(eqlType)}", $1::jsonb)`, + ) + expect(q.params).toEqual([TERM_JSON]) + expect(encrypt.mock.calls[0]?.[1]?.column.getName()).toBe(slug(eqlType)) + }) + + it('negation is expressed through the passthrough Drizzle not operator', async () => { + const { ops, render } = setup() + const q = render(ops.not(await ops.contains(users.email, 'example.com'))) + expect(q.sql).toMatch(/^not /i) + expect(q.sql).toContain('eql_v3.contains("users"."email", $1::jsonb)') + }) + + it('does not expose obsolete like/ilike helpers', () => { + const { ops } = setup() + expect('like' in ops).toBe(false) + expect('ilike' in ops).toBe(false) + expect('notIlike' in ops).toBe(false) + }) +}) + +describe('createEncryptionOperatorsV3 - storage-only domains', () => { + it.each(storageDomains)('%s eq throws', async (eqlType, spec) => { + const { ops } = setup() + await expect( + ops.eq(matrixColumn(eqlType), sampleFor(spec)), + ).rejects.toBeInstanceOf(EncryptionOperatorError) + }) + + it.each(storageDomains)('%s contains throws', async (eqlType, spec) => { + const { ops } = setup() + await expect( + ops.contains(matrixColumn(eqlType), sampleFor(spec)), + ).rejects.toBeInstanceOf(EncryptionOperatorError) + }) + + it.each(storageDomains)('%s asc throws synchronously', (eqlType) => { + const { ops } = setup() + expect(() => ops.asc(matrixColumn(eqlType))).toThrow( + EncryptionOperatorError, + ) + }) +}) + +describe('createEncryptionOperatorsV3 - array, ordering, combinators', () => { + it('inArray ORs one eq term per value; empty array throws', async () => { + const { ops, render } = setup() + const q = render(await ops.inArray(users.nickname, ['ada', 'grace'])) + expect(q.sql).toContain(' or ') + expect((q.sql.match(/eql_v3\.eq/g) ?? []).length).toBe(2) + await expect(ops.inArray(users.nickname, [])).rejects.toThrow(/non-empty/) + }) + + it('inArray fans out more than MAX_IN_ARRAY_CONCURRENCY values exactly once', async () => { + const { ops, encrypt, render } = setup() + const values = [ + 'ada', + 'grace', + 'alan', + 'katherine', + 'dorothy', + 'mary', + 'joan', + ] + + const q = render(await ops.inArray(users.nickname, values)) + + expect((q.sql.match(/eql_v3\.eq/g) ?? []).length).toBe(values.length) + expect(q.params).toEqual(values.map(() => TERM_JSON)) + expect(encrypt).toHaveBeenCalledTimes(values.length) + expect(encrypt.mock.calls.map(([value]) => value).sort()).toEqual( + [...values].sort(), + ) + }) + + it('inArray on an ORE column uses ORE equality for each term', async () => { + const { ops, render } = setup() + const q = render(await ops.inArray(users.age, [30, 42])) + expect(q.sql).toContain(' or ') + expect((q.sql.match(/eql_v3\.eq/g) ?? []).length).toBe(2) + }) + + it('notInArray ANDs one ne term per value; empty array throws', async () => { + const { ops, render } = setup() + const q = render(await ops.notInArray(users.nickname, ['ada', 'grace'])) + expect(q.sql).toContain(' and ') + await expect(ops.notInArray(users.nickname, [])).rejects.toThrow( + /non-empty/, + ) + }) + + it('notInArray on an ORE column uses ORE inequality for each term', async () => { + const { ops, render } = setup() + const q = render(await ops.notInArray(users.age, [30, 42])) + expect(q.sql).toContain(' and ') + expect((q.sql.match(/eql_v3\.neq/g) ?? []).length).toBe(2) + }) + + it('and ignores undefined conditions and keeps the encrypted predicates', async () => { + const { ops, render } = setup() + const q = render( + await ops.and( + undefined, + ops.eq(users.nickname, 'ada'), + undefined, + ops.gte(users.age, 30), + ), + ) + expect(q.sql).toContain('eql_v3.eq("users"."nickname"') + expect(q.sql).toContain('eql_v3.gte("users"."age"') + expect(q.sql).toContain(' and ') + }) + + it('empty and/or resolve to their neutral predicates', async () => { + const { ops, render } = setup() + expect(render(await ops.and()).sql).toBe('true') + expect(render(await ops.or()).sql).toBe('false') + }) + + it('or combines encrypted and plain predicates', async () => { + const { ops, render } = setup() + const q = render( + await ops.or(ops.eq(users.nickname, 'ada'), drizzleEq(users.id, 1)), + ) + expect(q.sql).toContain(' or ') + expect(q.sql).toContain('eql_v3.eq("users"."nickname"') + expect(q.sql).toContain('"users"."id" = $2') + }) + + it('exports the passthrough Drizzle operators unchanged', () => { + const { ops } = setup() + expect(ops.isNull).toBe(isNull) + expect(ops.isNotNull).toBe(isNotNull) + expect(ops.not).toBe(not) + expect(ops.exists).toBe(exists) + expect(ops.notExists).toBe(notExists) + }) +}) + +describe('createEncryptionOperatorsV3 - gating errors', () => { + it('wraps encryption failures with operator context', async () => { + const { ops } = setup(async () => ({ + failure: { message: 'bad query term' }, + })) + + await expect(ops.eq(users.nickname, 'ada')).rejects.toMatchObject({ + name: 'EncryptionOperatorError', + }) + }) + + it('gt on an equality-only column throws', async () => { + const { ops } = setup() + await expect(ops.gt(users.nickname, 'ada')).rejects.toBeInstanceOf( + EncryptionOperatorError, + ) + }) + + it('contains on a column without match throws', async () => { + const { ops } = setup() + await expect(ops.contains(users.nickname, 'ada')).rejects.toBeInstanceOf( + EncryptionOperatorError, + ) + }) + + it('null operands throw and point callers to null checks', async () => { + const { ops } = setup() + await expect(ops.eq(users.nickname, null)).rejects.toThrow(/isNull/) + await expect(ops.contains(users.email, undefined)).rejects.toThrow(/isNull/) + }) + + it('eq on a storage-only column throws', async () => { + const { ops } = setup() + await expect(ops.eq(users.flag, true)).rejects.toBeInstanceOf( + EncryptionOperatorError, + ) + }) + + it('asc on a non-ore column throws synchronously', () => { + const { ops } = setup() + expect(() => ops.asc(users.nickname)).toThrow(EncryptionOperatorError) + }) + + it('a non-v3 column throws', async () => { + const { ops } = setup() + await expect(ops.eq(users.id, 1)).rejects.toBeInstanceOf( + EncryptionOperatorError, + ) + }) + + it('does not treat SQLWrapper objects with column-shaped fields as Drizzle columns', async () => { + const { ops } = setup() + const spoof = { + name: 'nickname', + table: users, + getSQL: () => sql`"users"."nickname"`, + } as unknown as SQLWrapper + + await expect(ops.eq(spoof, 'ada')).rejects.toMatchObject({ + name: 'EncryptionOperatorError', + context: { columnName: 'unknown', operator: 'eq' }, + }) + }) +}) diff --git a/packages/stack/__tests__/drizzle-v3/schema-extraction.test.ts b/packages/stack/__tests__/drizzle-v3/schema-extraction.test.ts new file mode 100644 index 00000000..85f22249 --- /dev/null +++ b/packages/stack/__tests__/drizzle-v3/schema-extraction.test.ts @@ -0,0 +1,111 @@ +import { integer, pgTable } from 'drizzle-orm/pg-core' +import { describe, expect, it } from 'vitest' +import { encryptedTable, types as v3Types } from '@/eql/v3' +import { extractEncryptionSchemaV3 } from '@/eql/v3/drizzle/schema-extraction' +import { types } from '@/eql/v3/drizzle/types' + +describe('extractEncryptionSchemaV3', () => { + it('rebuilds an equivalent eql/v3 encryptedTable from every drizzle v3 factory', () => { + const drizzleColumns = Object.fromEntries( + Object.entries(types).map(([factoryName, factory]) => [ + factoryName, + factory(factoryName), + ]), + ) + const authoredColumns = Object.fromEntries( + Object.entries(v3Types).map(([factoryName, factory]) => [ + factoryName, + factory(factoryName), + ]), + ) + + const extracted = extractEncryptionSchemaV3( + pgTable('users', drizzleColumns as never), + ) + const authored = encryptedTable('users', authoredColumns as never) + + expect(extracted.build()).toEqual(authored.build()) + }) + + it('rebuilds an equivalent eql/v3 encryptedTable from a drizzle table', () => { + const users = pgTable('users', { + id: integer().primaryKey(), + email: types.TextSearch('email'), + age: types.IntegerOrd('age'), + }) + + const extracted = extractEncryptionSchemaV3(users) + const authored = encryptedTable('users', { + email: v3Types.TextSearch('email'), + age: v3Types.IntegerOrd('age'), + }) + + expect(extracted.build()).toEqual(authored.build()) + }) + + it('keeps same-named columns on different tables bound to their own v3 domains', () => { + const accounts = pgTable('accounts', { + email: types.TextEq('email'), + }) + const metrics = pgTable('metrics', { + email: types.IntegerOrd('email'), + }) + + const accountsSchema = extractEncryptionSchemaV3(accounts) + const metricsSchema = extractEncryptionSchemaV3(metrics) + + expect(accountsSchema.build()).toEqual( + encryptedTable('accounts', { + email: v3Types.TextEq('email'), + }).build(), + ) + expect(metricsSchema.build()).toEqual( + encryptedTable('metrics', { + email: v3Types.IntegerOrd('email'), + }).build(), + ) + }) + + it('uses the JS property key while preserving distinct SQL column names', () => { + const users = pgTable('users', { + createdOn: types.Date('created_on'), + emailAddress: types.TextEq('email_address'), + }) + + expect(extractEncryptionSchemaV3(users).build()).toEqual( + encryptedTable('users', { + createdOn: v3Types.Date('created_on'), + emailAddress: v3Types.TextEq('email_address'), + }).build(), + ) + }) + + it('uses the Drizzle column name when rebuilding fallback SQL-type columns', () => { + const table = { + [Symbol.for('drizzle:Name')]: 'users', + createdOn: { + name: 'created_on', + getSQLType: () => 'eql_v3.date', + }, + } + + expect(extractEncryptionSchemaV3(table as never).build()).toEqual( + encryptedTable('users', { + createdOn: v3Types.Date('created_on'), + }).build(), + ) + }) + + it('throws when the table has no encrypted v3 columns', () => { + const plain = pgTable('plain', { id: integer() }) + expect(() => extractEncryptionSchemaV3(plain)).toThrow(/no encrypted v3/i) + }) + + it('throws the table-name error before checking for encrypted columns', () => { + expect(() => + extractEncryptionSchemaV3({ + secret: { getSQLType: () => 'eql_v3.text_eq', name: 'secret' }, + } as never), + ).toThrow('Unable to read table name from Drizzle table.') + }) +}) diff --git a/packages/stack/__tests__/drizzle-v3/sql-dialect.test.ts b/packages/stack/__tests__/drizzle-v3/sql-dialect.test.ts new file mode 100644 index 00000000..e3ad75c2 --- /dev/null +++ b/packages/stack/__tests__/drizzle-v3/sql-dialect.test.ts @@ -0,0 +1,47 @@ +import { sql } from 'drizzle-orm' +import { PgDialect } from 'drizzle-orm/pg-core' +import { describe, expect, it } from 'vitest' +import { v3Dialect } from '@/eql/v3/drizzle/sql-dialect' + +const dialect = new PgDialect() +const render = (s: ReturnType<typeof sql>) => dialect.sqlToQuery(s).sql +const col = sql`"users"."x"` +const enc = sql`${'{"v":"t"}'}` + +describe('v3Dialect', () => { + it('equality via HMAC', () => { + expect(render(v3Dialect.equality('eq', col, enc))).toBe( + 'eql_v3.eq("users"."x", $1::jsonb)', + ) + }) + + it('inequality via HMAC', () => { + expect(render(v3Dialect.equality('ne', col, enc))).toBe( + 'eql_v3.neq("users"."x", $1::jsonb)', + ) + }) + + it('comparison via ORE', () => { + expect(render(v3Dialect.comparison('gte', col, enc))).toBe( + 'eql_v3.gte("users"."x", $1::jsonb)', + ) + }) + + it('range via ORE', () => { + const lo = sql`${'{"v":"lo"}'}` + const hi = sql`${'{"v":"hi"}'}` + expect(render(v3Dialect.range(col, lo, hi))).toBe( + 'eql_v3.gte("users"."x", $1::jsonb) AND eql_v3.lte("users"."x", $2::jsonb)', + ) + }) + + it('contains via two-arg function', () => { + expect(render(v3Dialect.contains(col, enc))).toBe( + 'eql_v3.contains("users"."x", $1::jsonb)', + ) + }) + + it('orderBy extracts the ord term', () => { + expect(render(v3Dialect.orderBy(col))).toBe('eql_v3.ord_term("users"."x")') + }) +}) diff --git a/packages/stack/__tests__/drizzle-v3/types.test-d.ts b/packages/stack/__tests__/drizzle-v3/types.test-d.ts new file mode 100644 index 00000000..503157c9 --- /dev/null +++ b/packages/stack/__tests__/drizzle-v3/types.test-d.ts @@ -0,0 +1,62 @@ +import { describe, expectTypeOf, it } from 'vitest' +import type { types as v3Types } from '@/eql/v3' +import { types } from '@/eql/v3/drizzle/types' + +describe('v3 drizzle types - type-level', () => { + it('exposes exactly the same factory keys as @/eql/v3 types', () => { + expectTypeOf<keyof typeof types>().toEqualTypeOf<keyof typeof v3Types>() + }) + + it('columns infer their concrete plaintext type via the data type slot', () => { + const age = types.IntegerOrd('age') + const ageEq = types.IntegerEq('age_eq') + const smallint = types.SmallintOrd('smallint') + const date = types.DateOrd('created_at') + const dateOre = types.DateOrdOre('created_at_ore') + const created = types.Timestamp('created_at') + const tsOrd = types.TimestampOrd('created_at_ord') + const numOre = types.NumericOrdOre('amount_ore') + const flag = types.Boolean('flag') + const nick = types.TextEq('nickname') + const text = types.Text('text') + const match = types.TextMatch('bio') + const textOrd = types.TextOrd('text_ord') + const textOrdOre = types.TextOrdOre('text_ord_ore') + const search = types.TextSearch('search') + const realEq = types.RealEq('real_eq') + const doubleOrd = types.DoubleOrd('double_ord') + + expectTypeOf(age._.data).toEqualTypeOf<number>() + expectTypeOf(ageEq._.data).toEqualTypeOf<number>() + expectTypeOf(smallint._.data).toEqualTypeOf<number>() + expectTypeOf(date._.data).toEqualTypeOf<Date>() + expectTypeOf(dateOre._.data).toEqualTypeOf<Date>() + expectTypeOf(created._.data).toEqualTypeOf<Date>() + expectTypeOf(tsOrd._.data).toEqualTypeOf<Date>() + expectTypeOf(numOre._.data).toEqualTypeOf<number>() + expectTypeOf(flag._.data).toEqualTypeOf<boolean>() + expectTypeOf(nick._.data).toEqualTypeOf<string>() + expectTypeOf(text._.data).toEqualTypeOf<string>() + expectTypeOf(match._.data).toEqualTypeOf<string>() + expectTypeOf(textOrd._.data).toEqualTypeOf<string>() + expectTypeOf(textOrdOre._.data).toEqualTypeOf<string>() + expectTypeOf(search._.data).toEqualTypeOf<string>() + expectTypeOf(realEq._.data).toEqualTypeOf<number>() + expectTypeOf(doubleOrd._.data).toEqualTypeOf<number>() + }) + + it('does not expose obsolete pre-0.27 concrete domain names', () => { + // @ts-expect-error - use IntegerOrd + types.Int4Ord('age') + // @ts-expect-error - use SmallintOrd + types.Int2Ord('age') + // @ts-expect-error - use Timestamp + types.Timestamptz('created_at') + // @ts-expect-error - use Boolean + types.Bool('active') + // @ts-expect-error - use RealEq + types.Float4Eq('score') + // @ts-expect-error - use DoubleOrd + types.Float8Ord('score') + }) +}) diff --git a/packages/stack/__tests__/drizzle-v3/types.test.ts b/packages/stack/__tests__/drizzle-v3/types.test.ts new file mode 100644 index 00000000..c143fc17 --- /dev/null +++ b/packages/stack/__tests__/drizzle-v3/types.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, it } from 'vitest' +import { types as v3Types } from '@/eql/v3' +import { getEqlV3Column } from '@/eql/v3/drizzle/column' +import { types } from '@/eql/v3/drizzle/types' + +describe('v3 drizzle types namespace', () => { + it('exposes the same factory names as @/eql/v3 types', () => { + expect(Object.keys(types).sort()).toEqual(Object.keys(v3Types).sort()) + }) + + it.each( + Object.entries(types), + )('%s mirrors the authoring DSL and recovers the concrete eql type', (factoryName, factory) => { + const drizzleColumn = factory(factoryName) + const authoredColumn = + v3Types[factoryName as keyof typeof v3Types](factoryName) + + expect(getEqlV3Column(factoryName, drizzleColumn)?.getEqlType()).toBe( + authoredColumn.getEqlType(), + ) + }) +}) diff --git a/packages/stack/__tests__/encrypt-lock-context-guards.test.ts b/packages/stack/__tests__/encrypt-lock-context-guards.test.ts new file mode 100644 index 00000000..c610d608 --- /dev/null +++ b/packages/stack/__tests__/encrypt-lock-context-guards.test.ts @@ -0,0 +1,103 @@ +/** + * Offline guard tests for the lock-context encrypt path. + * + * `EncryptOperationWithLockContext.execute()` re-applies the NaN / Infinity + * runtime guards that the non-lock `EncryptOperation.execute()` has. The + * non-lock guards are exercised by the live `number-protect.test.ts` (its + * `beforeAll` builds a real client), but the lock-context arm — reached via + * `encrypt(value).withLockContext(...)` — had no coverage in any suite. These + * tests mock `@cipherstash/protect-ffi` so they run in CI without credentials + * and assert that: + * 1. NaN / +Infinity / -Infinity are rejected as failures with the same + * messages as the non-lock path, and + * 2. the guard short-circuits *before* the FFI encrypt call (a leaked NaN + * must never reach the ciphertext boundary). + * + * Every case runs against both a v2 fluent-builder column and a v3 domain + * column: the guards live on the shared `EncryptOperationWithLockContext`, so + * both schema styles must take the identical short-circuit path. + */ + +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { encryptedTable as encryptedTableV3, types } from '@/eql/v3' +import { LockContext } from '@/identity' +import { Encryption } from '@/index' +import { encryptedColumn, encryptedTable } from '@/schema' + +vi.mock('@cipherstash/protect-ffi', () => ({ + // `getErrorCode` does `error instanceof ProtectError` on the failure path, + // so the mock must export the class even though the guards throw plain Errors. + ProtectError: class ProtectError extends Error {}, + newClient: vi.fn(async () => ({ __mock: 'client' })), + encrypt: vi.fn(async () => ({ v: 2, c: 'ciphertext' })), + decrypt: vi.fn(async () => 'decrypted'), +})) + +import * as ffi from '@cipherstash/protect-ffi' + +const users = encryptedTable('users', { + score: encryptedColumn('score').dataType('number').equality().orderAndRange(), +}) + +const usersV3 = encryptedTableV3('users_v3', { + score: types.IntegerOrd('score'), +}) + +// biome-ignore lint/suspicious/noExplicitAny: test helper reads the Result union +const failure = (result: any) => result.failure + +let client: Awaited<ReturnType<typeof Encryption>> + +beforeEach(async () => { + vi.clearAllMocks() + process.env.CS_WORKSPACE_CRN = 'crn:ap-southeast-2.aws:test-workspace' + client = await Encryption({ schemas: [users, usersV3] }) +}) + +describe.each([ + ['v2 fluent builder', { column: users.score, table: users }], + ['v3 domain type', { column: usersV3.score, table: usersV3 }], +] as const)('encrypt with lock context rejects non-finite numbers (%s)', (_variant, target) => { + it('rejects NaN and never reaches the FFI', async () => { + const result = await client + .encrypt(Number.NaN, target) + .withLockContext(new LockContext()) + + expect(failure(result)).toBeDefined() + expect(failure(result)?.message).toContain('Cannot encrypt NaN value') + expect(vi.mocked(ffi.encrypt)).not.toHaveBeenCalled() + }) + + it('rejects +Infinity and never reaches the FFI', async () => { + const result = await client + .encrypt(Number.POSITIVE_INFINITY, target) + .withLockContext(new LockContext()) + + expect(failure(result)).toBeDefined() + expect(failure(result)?.message).toContain('Cannot encrypt Infinity value') + expect(vi.mocked(ffi.encrypt)).not.toHaveBeenCalled() + }) + + it('rejects -Infinity and never reaches the FFI', async () => { + const result = await client + .encrypt(Number.NEGATIVE_INFINITY, target) + .withLockContext(new LockContext()) + + expect(failure(result)).toBeDefined() + expect(failure(result)?.message).toContain('Cannot encrypt Infinity value') + expect(vi.mocked(ffi.encrypt)).not.toHaveBeenCalled() + }) + + it('accepts a finite number and forwards it to the FFI', async () => { + // Positive control: proves the guards above reject *because* of the value, + // not because the lock-context path is broken for all numbers. + const result = await client + .encrypt(42, target) + .withLockContext(new LockContext()) + + expect(failure(result)).toBeUndefined() + expect(vi.mocked(ffi.encrypt)).toHaveBeenCalledTimes(1) + const opts = vi.mocked(ffi.encrypt).mock.calls[0][1] + expect(opts.plaintext).toBe(42) + }) +}) diff --git a/packages/stack/__tests__/error-codes.test.ts b/packages/stack/__tests__/error-codes.test.ts index 80ecbc0f..ad1c7de4 100644 --- a/packages/stack/__tests__/error-codes.test.ts +++ b/packages/stack/__tests__/error-codes.test.ts @@ -5,6 +5,7 @@ import type { EncryptionClient } from '@/encryption' import { EncryptionErrorTypes } from '@/errors' import { Encryption } from '@/index' import { encryptedColumn, encryptedTable } from '@/schema' +import type { BulkDecryptPayload } from '@/types' /** FFI tests require longer timeout due to client initialization */ const FFI_TEST_TIMEOUT = 30_000 @@ -246,26 +247,30 @@ describe('FFI Error Code Preservation', () => { describe('bulkDecrypt error codes', () => { it( - 'returns undefined code for malformed ciphertexts (non-FFI validation)', + 'returns per-item errors for malformed ciphertexts', async () => { - // bulkDecrypt uses the "fallible" FFI API (decryptBulkFallible) which normally: - // - Succeeds at the operation level - // - Returns per-item results with either { data } or { error } - // - // However, malformed ciphertexts cause parsing errors BEFORE the fallible API, - // which throws and triggers a top-level failure (not per-item errors). - // These pre-FFI errors don't have structured FFI error codes. + // bulkDecrypt uses the fallible FFI API, so malformed items are + // reported per item instead of failing the whole operation. const invalidCiphertexts = [ { data: { i: { t: 'test_table', c: 'email' }, v: 2, c: 'invalid1' } }, { data: { i: { t: 'test_table', c: 'email' }, v: 2, c: 'invalid2' } }, - ] + ] as unknown as BulkDecryptPayload const result = await protectClient.bulkDecrypt(invalidCiphertexts) - expect(result.failure).toBeDefined() - expect(result.failure?.type).toBe(EncryptionErrorTypes.DecryptionError) - // FFI parsing errors don't have structured error codes - expect(result.failure?.code).toBeUndefined() + if (result.failure) { + throw new Error( + `Expected per-item errors, got ${result.failure.type}`, + ) + } + + expect(result.data).toHaveLength(2) + expect(result.data.every((item) => 'error' in item)).toBe(true) + + for (const item of result.data) { + expect(item.error).toBeDefined() + expect('code' in item).toBe(false) + } }, FFI_TEST_TIMEOUT, ) diff --git a/packages/stack/__tests__/fixtures/eql-v3/cipherstash-encrypt-v3.sql b/packages/stack/__tests__/fixtures/eql-v3/cipherstash-encrypt-v3.sql new file mode 100644 index 00000000..8baecafb --- /dev/null +++ b/packages/stack/__tests__/fixtures/eql-v3/cipherstash-encrypt-v3.sql @@ -0,0 +1,29777 @@ +--! @file v3/schema.sql +--! @brief EQL v3 schema creation +--! +--! Creates the eql_v3 schema, which houses the self-contained encrypted-domain +--! type families (eql_v3.integer, eql_v3.int8, and future scalar domains): their +--! jsonb-backed domains, the searchable-encrypted-metadata (SEM) index-term +--! types they use (eql_v3.hmac_256, eql_v3.ore_block_256), the index-term +--! extractors, comparison wrappers, blockers, and aggregates. The v3 surface is +--! self-contained — it owns every type it needs and has no runtime dependency +--! on another EQL 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 the encrypted-domain families. + +--! @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; + +--! @file v3/sem/ore_block_256/types.sql +--! @brief ORE block index-term types (eql_v3 SEM). +--! +--! Self-contained eql_v3 copies of the Order-Revealing Encryption block types +--! (design D1/D3). The eql_v2 originals are unchanged. + +--! @brief ORE block term type for Order-Revealing Encryption +--! +--! Composite type representing a single ORE block term. Stores encrypted data +--! as bytea that enables range comparisons without decryption. +CREATE TYPE eql_v3.ore_block_256_term AS ( + bytes bytea +); + + +--! @brief ORE block index term type for range queries +--! +--! Composite type containing an array of ORE block terms. The array is stored +--! in the 'ob' field of encrypted data payloads. +--! +--! @note Transient type used only during query execution. +CREATE TYPE eql_v3.ore_block_256 AS ( + terms eql_v3.ore_block_256_term[] +); + +--! @file v3/crypto.sql +--! @brief PostgreSQL pgcrypto extension enablement (eql_v3 fork) +--! +--! Forked from src/crypto.sql (design D8) so the entire eql_v3 dependency +--! closure lives under src/v3/. Enables the pgcrypto extension which provides +--! cryptographic functions used by the eql_v3 ORE comparison path. +--! +--! Installs pgcrypto into the `extensions` schema (Supabase convention) to +--! avoid the `extension_in_public` lint. Every EQL function that uses pgcrypto +--! has `pg_catalog, extensions, public` on its `search_path`, so a pre-existing +--! install in `public` keeps working — and a pre-existing install anywhere else +--! will be rejected at install time. The body is idempotent +--! (`CREATE SCHEMA IF NOT EXISTS`, `pg_extension` guard), so running it +--! alongside the eql_v2 copy in a combined install is safe. +--! +--! @note pgcrypto provides functions like digest(), hmac(), gen_random_bytes() + +--! @brief Create extensions schema (Supabase convention) +CREATE SCHEMA IF NOT EXISTS extensions; + +--! @brief Enable pgcrypto extension and validate its schema +DO $$ +DECLARE + pgcrypto_schema name; +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'pgcrypto') THEN + CREATE EXTENSION pgcrypto WITH SCHEMA extensions; + END IF; + + SELECT n.nspname INTO pgcrypto_schema + FROM pg_extension e + JOIN pg_namespace n ON n.oid = e.extnamespace + WHERE e.extname = 'pgcrypto'; + + IF pgcrypto_schema = 'extensions' THEN + -- expected location, nothing to say + NULL; + ELSIF pgcrypto_schema = 'public' THEN + RAISE NOTICE + 'pgcrypto is installed in the `public` schema. EQL works against this layout, ' + 'but Supabase splinter will flag it as `extension_in_public`. Move it with: ' + 'ALTER EXTENSION pgcrypto SET SCHEMA extensions'; + ELSE + RAISE EXCEPTION + 'pgcrypto is installed in schema `%`, which is not on the EQL function search_path ' + '(pg_catalog, extensions, public). EQL cryptographic operations would fail at ' + 'runtime. Relocate the extension before installing EQL: ' + 'ALTER EXTENSION pgcrypto SET SCHEMA extensions', + pgcrypto_schema; + END IF; +END $$; + +--! @file v3/common.sql +--! @brief Common utility functions for the self-contained eql_v3 surface. +--! +--! Forked from src/common.sql (design D7) so the eql_v3 ORE constructor owns the +--! one transitive helper it needs without reaching into another schema. The +--! eql_v2 original is unchanged. + +--! @brief Convert JSONB hex array to bytea array +--! @internal +--! +--! Converts a JSONB array of hex-encoded strings into a PostgreSQL bytea array. +--! Used for deserializing binary data (like ORE terms) from JSONB storage. +--! +--! @param val jsonb JSONB array of hex-encoded strings +--! @return bytea[] Array of decoded binary values +--! +--! @note Returns NULL if input is JSON null +--! @note Each array element is hex-decoded to bytea +--! @note Inlinable `LANGUAGE sql` IMMUTABLE form (no `SET search_path`) so the +--! planner can fold this per-encrypted-value helper into the calling query. +--! This deliberately diverges from the v2 plpgsql equivalent (intentionally +--! left unchanged): the `CASE WHEN jsonb_typeof(val) = 'array'` guard only +--! evaluates the set-returning `jsonb_array_elements_text` for an array, so a +--! non-array JSON scalar returns NULL here instead of raising "cannot extract +--! elements from a scalar". Both callers only ever pass an array or JSON null +--! (`val->'ob'`), so the divergence is unreachable in practice; JSON null and +--! empty array still return NULL exactly as before. +CREATE FUNCTION eql_v3.jsonb_array_to_bytea_array(val jsonb) +RETURNS bytea[] + IMMUTABLE +AS $$ + SELECT CASE WHEN jsonb_typeof(val) = 'array' + THEN ( + SELECT array_agg(decode(value::text, 'hex')::bytea) + FROM jsonb_array_elements_text(val) AS value + ) + ELSE NULL + END; +$$ LANGUAGE sql; + +--! @internal Mark this hand-written helper inline-critical so the post-install +--! pin_search_path pass leaves it unpinned (no `SET search_path`), preserving +--! SQL-function inlining. It takes a bare `jsonb` arg (not a jsonb-backed +--! encrypted DOMAIN), so the structural skip in tasks/pin_search_path_v3.sql does +--! not recognise it; this marker is the documented manual opt-in. +COMMENT ON FUNCTION eql_v3.jsonb_array_to_bytea_array(jsonb) IS + 'eql-inline-critical: per-encrypted-value ORE helper; must stay inlinable (unpinned search_path)'; + +--! @file v3/sem/hmac_256/types.sql +--! @brief HMAC-SHA256 index term type (eql_v3 SEM) +--! +--! Domain type representing HMAC-SHA256 hash values. Used for exact-match +--! encrypted searches. The hash is stored in the 'hm' field of encrypted data +--! payloads. Self-contained eql_v3 copy (design D1/D3); the eql_v2 original is +--! unchanged. +--! +--! @note Transient type used only during query execution. +CREATE DOMAIN eql_v3.hmac_256 AS text; + +--! @file v3/sem/bloom_filter/types.sql +--! @brief Self-contained eql_v3 Bloom-filter SEM index-term type. + +--! @brief Bloom-filter index term: a bit array stored as smallint[]. +--! +--! Backs the `match` capability (`@>` / `<@`) on `eql_v3.text_match`. The +--! filter is read from the `bf` field of an encrypted jsonb payload. Native +--! `smallint[]` array-containment (`@>`/`<@`) is inherited through the domain, +--! so this type needs no custom operators. +--! +--! @note Self-contained: references no eql_v2 symbol. +CREATE DOMAIN eql_v3.bloom_filter AS smallint[]; + +--! @file v3/scalars/functions.sql +--! @brief Shared blocker helper for the eql_v3 encrypted-domain families. +--! +--! Per-domain wrapper functions live in src/v3/scalars/<T>/. +--! 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 +--! behaviour. + +--! @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_v3.<T>*) +--! @param operator_name Operator symbol (=, <, @>, ->, etc.) +--! @return boolean (never returns; always raises) +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 +AS $$ +BEGIN + RAISE EXCEPTION 'operator % is not supported for %', operator_name, type_name; +END; +$$ LANGUAGE plpgsql; + +--! @brief Shared blocker helper returning jsonb. Identical to +--! encrypted_domain_unsupported_bool but typed for blockers shadowing +--! native operators whose result is jsonb (#>, -, #-, ||), so composed +--! expressions resolve and the body raises rather than failing earlier +--! with a misleading 'operator does not exist' on a boolean result. +--! @param type_name Domain type name (eql_v3.<T>*) +--! @param operator_name Operator symbol (#>, -, #-, ||, etc.) +--! @return jsonb (never returns; always raises) +CREATE FUNCTION eql_v3.encrypted_domain_unsupported_jsonb(type_name text, operator_name text) +RETURNS jsonb +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RAISE EXCEPTION 'operator % is not supported for %', operator_name, type_name; +END; +$$ LANGUAGE plpgsql; + +--! @brief Shared blocker helper returning text. Identical to +--! encrypted_domain_unsupported_bool but typed for blockers shadowing +--! the native #>> operator whose result is text. +--! @param type_name Domain type name (eql_v3.<T>*) +--! @param operator_name Operator symbol (#>>) +--! @return text (never returns; always raises) +CREATE FUNCTION eql_v3.encrypted_domain_unsupported_text(type_name text, operator_name text) +RETURNS text +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RAISE EXCEPTION 'operator % is not supported for %', operator_name, type_name; +END; +$$ LANGUAGE plpgsql; + +--! @file v3/sem/ore_block_256/functions.sql +--! @brief ORE block construction, extraction, and comparison (eql_v3 SEM). +--! +--! jsonb-only subset of src/ore_block_u64_8_256/functions.sql. The +--! encrypted-column overloads are omitted; the helper jsonb_array_to_bytea_array +--! and pgcrypto encrypt() are reached via the forked src/v3/common.sql and +--! src/v3/crypto.sql so the whole closure stays under src/v3. (Doc comments +--! deliberately avoid naming eql_v2 symbols so the self-containment grep stays +--! clean.) + +--! @brief Convert JSONB array to ORE block composite type +--! @internal +--! @param val jsonb Array of hex-encoded ORE block terms +--! @return eql_v3.ore_block_256 ORE block composite, or NULL if input is null +--! @note Inlinable `LANGUAGE sql` IMMUTABLE form (no `SET search_path`) so the +--! planner can fold this per-encrypted-value helper into the calling query. +--! This deliberately diverges from the v2 plpgsql equivalent (intentionally +--! left unchanged): the `CASE WHEN jsonb_typeof(val) = 'array'` guard only +--! evaluates the array path for an array, so a non-array JSON scalar returns +--! NULL here instead of raising. The sole caller (`ore_block_256`) only reaches +--! this when `has_ore_block_256(val)` is true, which now requires `val->'ob'` +--! to be a JSON array, so the non-array branch is unreachable in practice. +--! An empty array (`ob: []`, what encrypting the empty string `""` produces) +--! yields a non-NULL composite with an EMPTY `terms` array — NOT NULL terms. +--! The `COALESCE` is load-bearing: `array_agg` over zero rows returns NULL, and +--! NULL terms make the comparator return NULL (so an empty-text row silently +--! drops out of ordered queries). An empty array instead engages the +--! comparator's `cardinality = 0` guard, which sorts empty BEFORE every +--! non-empty term. See issue #262 (pinned by T7). +CREATE FUNCTION eql_v3.jsonb_array_to_ore_block_256(val jsonb) +RETURNS eql_v3.ore_block_256 + IMMUTABLE +AS $$ + SELECT CASE WHEN jsonb_typeof(val) = 'array' + THEN ROW(COALESCE( + ( + SELECT array_agg(ROW(b)::eql_v3.ore_block_256_term) + FROM unnest(eql_v3.jsonb_array_to_bytea_array(val)) AS b + ), + ARRAY[]::eql_v3.ore_block_256_term[] + ))::eql_v3.ore_block_256 + ELSE NULL + END; +$$ LANGUAGE sql; + +--! @internal Mark this hand-written helper inline-critical so the post-install +--! pin_search_path pass leaves it unpinned (no `SET search_path`), preserving +--! SQL-function inlining. It takes a bare `jsonb` arg (not a jsonb-backed +--! encrypted DOMAIN), so the structural skip in tasks/pin_search_path_v3.sql does +--! not recognise it; this marker is the documented manual opt-in. +COMMENT ON FUNCTION eql_v3.jsonb_array_to_ore_block_256(jsonb) IS + 'eql-inline-critical: per-encrypted-value ORE helper; must stay inlinable (unpinned search_path)'; + + +--! @brief Extract ORE block index term from JSONB payload +--! @param val jsonb containing encrypted EQL payload +--! @return eql_v3.ore_block_256 ORE block index term +--! @throws Exception if 'ob' field is missing +CREATE FUNCTION eql_v3.ore_block_256(val jsonb) + RETURNS eql_v3.ore_block_256 + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + BEGIN + -- Declared STRICT: PostgreSQL returns NULL for a NULL argument without + -- entering the body, so no explicit `val IS NULL` guard is needed. + IF eql_v3.has_ore_block_256(val) THEN + RETURN eql_v3.jsonb_array_to_ore_block_256(val->'ob'); + END IF; + RAISE 'Expected an ore index (ob) value in json: %', val; + END; +$$ LANGUAGE plpgsql; + + +--! @brief Check if JSONB payload contains an ORE block index term +--! @param val jsonb containing encrypted EQL payload +--! @return boolean True only if the 'ob' field is present and is a JSON array +--! @note A well-formed ORE index term is always a JSON array of block terms, so +--! this guard treats a present-but-non-array `ob` (a scalar or object) as +--! absent. That makes the extractor `ore_block_256(val)` RAISE on a +--! structurally invalid `ob` payload at the boundary instead of silently +--! degrading it to a NULL index term in `jsonb_array_to_ore_block_256`. The +--! previous `val ->> 'ob' IS NOT NULL` form stringified scalars/objects and so +--! reported them as present. `{}` (absent `ob`) and `{"ob": null}` (JSON null) +--! both remain `false`. +CREATE FUNCTION eql_v3.has_ore_block_256(val jsonb) + RETURNS boolean + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + BEGIN + RETURN COALESCE(jsonb_typeof(val -> 'ob') = 'array', false); + END; +$$ LANGUAGE plpgsql; + + +--! @brief Compare two ORE block terms using cryptographic comparison +--! @internal +--! @param a eql_v3.ore_block_256_term First ORE term +--! @param b eql_v3.ore_block_256_term Second ORE term +--! @return integer -1 if a < b, 0 if a = b, 1 if a > b +--! @throws Exception if ciphertexts are different lengths +--! @note Marked `IMMUTABLE` (the three `compare_ore_block_256_term(s)` +--! overloads all are). This deliberately diverges from the v2 originals, +--! which carry no volatility marker and so default to `VOLATILE`. The +--! comparison is deterministic — its only crypto call, pgcrypto `encrypt()`, +--! is itself `IMMUTABLE STRICT PARALLEL SAFE` — so `IMMUTABLE` lets the +--! planner fold/cache these in ordering and index contexts. NOT `STRICT`: +--! the NULL-handling branches below are load-bearing for the array overload. +CREATE FUNCTION eql_v3.compare_ore_block_256_term(a eql_v3.ore_block_256_term, b eql_v3.ore_block_256_term) + RETURNS integer + IMMUTABLE + SET search_path = pg_catalog, extensions, public +AS $$ + DECLARE + eq boolean := true; + unequal_block smallint := 0; + hash_key bytea; + data_block bytea; + encrypt_block bytea; + target_block bytea; + + left_block_size CONSTANT smallint := 16; + right_block_size CONSTANT smallint := 32; + + -- Block count N is DERIVED from the ciphertext length, not hardcoded to 8. + -- Wire format per term: + -- [ N PRP bytes ][ N*16B left blocks ][ 16B hash key ][ N*32B right blocks ] + -- octet_length = 17*N + 16 + 32*N = 49*N + 16 => N = (octet_length - 16) / 49 + -- This serves integer (N=8, 408B), timestamp (N=12, 604B), and numeric + -- (N=14, 702B) with one comparator. + n integer; + left_offset integer; -- ordinal offset of the first left block (1 + N PRP bytes) + right_offset integer; -- ordinal start of the right CT (= total left CT length = 17*N) + + indicator smallint := 0; + BEGIN + IF a IS NULL AND b IS NULL THEN + RETURN 0; + END IF; + + IF a IS NULL THEN + RETURN -1; + END IF; + + IF b IS NULL THEN + RETURN 1; + END IF; + + IF bit_length(a.bytes) != bit_length(b.bytes) THEN + RAISE EXCEPTION 'Ciphertexts are different lengths'; + END IF; + + -- Well-formedness: length must be exactly 49*N + 16 for some N >= 1. The + -- modulo alone is insufficient -- a 16-byte term passes (16 - 16) % 49 = 0 + -- and derives N = 0, which would fall through to the all-blocks-equal path + -- and return 0 instead of raising. The `<= 16` clause is load-bearing. + IF octet_length(a.bytes) <= 16 OR (octet_length(a.bytes) - 16) % 49 != 0 THEN + RAISE EXCEPTION 'Malformed ORE term: % bytes', octet_length(a.bytes); + END IF; + + n := (octet_length(a.bytes) - 16) / 49; + left_offset := 1 + n; -- left blocks begin right after the N PRP bytes + right_offset := 17 * n; -- right CT begins right after the 17*N-byte left CT + + FOR block IN 0..n-1 LOOP + -- Compare each PRP byte (the first N bytes) and its 16-byte left block. + IF + substr(a.bytes, 1 + block, 1) != substr(b.bytes, 1 + block, 1) + OR substr(a.bytes, left_offset + left_block_size * block, left_block_size) != substr(b.bytes, left_offset + left_block_size * block, left_block_size) + THEN + IF eq THEN + unequal_block := block; + END IF; + eq = false; + END IF; + END LOOP; + + IF eq THEN + RETURN 0::integer; + END IF; + + -- Hash key is the IV from the right CT of b. + hash_key := substr(b.bytes, right_offset + 1, 16); + + -- First right block is at right_offset + nonce_size (ordinally indexed). + target_block := substr(b.bytes, right_offset + 17 + (unequal_block * right_block_size), right_block_size); + + data_block := substr(a.bytes, left_offset + (left_block_size * unequal_block), left_block_size); + + encrypt_block := encrypt(data_block::bytea, hash_key::bytea, 'aes-ecb'); + + indicator := ( + get_bit( + encrypt_block, + 0 + ) + get_bit(target_block, get_byte(a.bytes, unequal_block))) % 2; + + IF indicator = 1 THEN + RETURN 1::integer; + ELSE + RETURN -1::integer; + END IF; + END; +$$ LANGUAGE plpgsql; + + +--! @brief Compare arrays of ORE block terms recursively +--! @internal +--! @param a eql_v3.ore_block_256_term[] First array +--! @param b eql_v3.ore_block_256_term[] Second array +--! @return integer -1/0/1, or NULL if either array is NULL +CREATE FUNCTION eql_v3.compare_ore_block_256_terms(a eql_v3.ore_block_256_term[], b eql_v3.ore_block_256_term[]) +RETURNS integer + IMMUTABLE + SET search_path = pg_catalog, extensions, public +AS $$ + DECLARE + cmp_result integer; + BEGIN + IF a IS NULL OR b IS NULL THEN + RETURN NULL; + END IF; + + IF cardinality(a) = 0 AND cardinality(b) = 0 THEN + RETURN 0; + END IF; + + IF (cardinality(a) = 0) AND cardinality(b) > 0 THEN + RETURN -1; + END IF; + + IF cardinality(a) > 0 AND (cardinality(b) = 0) THEN + RETURN 1; + END IF; + + cmp_result := eql_v3.compare_ore_block_256_term(a[1], b[1]); + + IF cmp_result = 0 THEN + RETURN eql_v3.compare_ore_block_256_terms(a[2:array_length(a,1)], b[2:array_length(b,1)]); + END IF; + + RETURN cmp_result; + END +$$ LANGUAGE plpgsql; + + +--! @brief Compare ORE block composite types +--! @internal +--! @param a eql_v3.ore_block_256 First ORE block +--! @param b eql_v3.ore_block_256 Second ORE block +--! @return integer -1/0/1 +CREATE FUNCTION eql_v3.compare_ore_block_256_terms(a eql_v3.ore_block_256, b eql_v3.ore_block_256) +RETURNS integer + IMMUTABLE + SET search_path = pg_catalog, extensions, public +AS $$ + BEGIN + RETURN eql_v3.compare_ore_block_256_terms(a.terms, b.terms); + END +$$ LANGUAGE plpgsql; + +--! @file v3/sem/ore_block_256/operators.sql +--! @brief Comparison operators on eql_v3.ore_block_256. +--! +--! The six backing functions are inlinable single-statement SQL so the planner +--! can fold the eql_v3 comparison wrappers through to functional-index matching. + +--! @brief Equality backing function for ORE block types +--! @internal +--! +--! @param a eql_v3.ore_block_256 Left operand +--! @param b eql_v3.ore_block_256 Right operand +--! @return boolean True if the ORE blocks are equal +--! +--! @see eql_v3.compare_ore_block_256_terms +CREATE FUNCTION eql_v3.ore_block_256_eq(a eql_v3.ore_block_256, b eql_v3.ore_block_256) +RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_block_256_terms(a, b) = 0 +$$; + +--! @brief Not-equal backing function for ORE block types +--! @internal +--! +--! @param a eql_v3.ore_block_256 Left operand +--! @param b eql_v3.ore_block_256 Right operand +--! @return boolean True if the ORE blocks are not equal +--! +--! @see eql_v3.compare_ore_block_256_terms +CREATE FUNCTION eql_v3.ore_block_256_neq(a eql_v3.ore_block_256, b eql_v3.ore_block_256) +RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_block_256_terms(a, b) <> 0 +$$; + +--! @brief Less-than backing function for ORE block types +--! @internal +--! +--! @param a eql_v3.ore_block_256 Left operand +--! @param b eql_v3.ore_block_256 Right operand +--! @return boolean True if the left operand is less than the right operand +--! +--! @see eql_v3.compare_ore_block_256_terms +CREATE FUNCTION eql_v3.ore_block_256_lt(a eql_v3.ore_block_256, b eql_v3.ore_block_256) +RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_block_256_terms(a, b) = -1 +$$; + +--! @brief Less-than-or-equal backing function for ORE block types +--! @internal +--! +--! @param a eql_v3.ore_block_256 Left operand +--! @param b eql_v3.ore_block_256 Right operand +--! @return boolean True if the left operand is less than or equal to the right operand +--! +--! @see eql_v3.compare_ore_block_256_terms +CREATE FUNCTION eql_v3.ore_block_256_lte(a eql_v3.ore_block_256, b eql_v3.ore_block_256) +RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_block_256_terms(a, b) != 1 +$$; + +--! @brief Greater-than backing function for ORE block types +--! @internal +--! +--! @param a eql_v3.ore_block_256 Left operand +--! @param b eql_v3.ore_block_256 Right operand +--! @return boolean True if the left operand is greater than the right operand +--! +--! @see eql_v3.compare_ore_block_256_terms +CREATE FUNCTION eql_v3.ore_block_256_gt(a eql_v3.ore_block_256, b eql_v3.ore_block_256) +RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_block_256_terms(a, b) = 1 +$$; + +--! @brief Greater-than-or-equal backing function for ORE block types +--! @internal +--! +--! @param a eql_v3.ore_block_256 Left operand +--! @param b eql_v3.ore_block_256 Right operand +--! @return boolean True if the left operand is greater than or equal to the right operand +--! +--! @see eql_v3.compare_ore_block_256_terms +CREATE FUNCTION eql_v3.ore_block_256_gte(a eql_v3.ore_block_256, b eql_v3.ore_block_256) +RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_block_256_terms(a, b) != -1 +$$; + + +--! @brief = operator for ORE block types +--! +--! COMMUTATOR is the operator itself: equality is symmetric. Required for the +--! MERGES flag — without it the planner raises "could not find commutator" the +--! first time an ore_block equality is used as a join qual (e.g. via the inlined +--! eql_v3.<T>_ord_ore equality wrappers). +CREATE OPERATOR = ( + FUNCTION=eql_v3.ore_block_256_eq, + LEFTARG=eql_v3.ore_block_256, + RIGHTARG=eql_v3.ore_block_256, + COMMUTATOR = =, + NEGATOR = <>, + RESTRICT = eqsel, + JOIN = eqjoinsel, + HASHES, + MERGES +); + +--! @brief <> operator for ORE block types +CREATE OPERATOR <> ( + FUNCTION=eql_v3.ore_block_256_neq, + LEFTARG=eql_v3.ore_block_256, + RIGHTARG=eql_v3.ore_block_256, + COMMUTATOR = <>, + NEGATOR = =, + RESTRICT = neqsel, + JOIN = neqjoinsel, + MERGES +); + +--! @brief > operator for ORE block types +CREATE OPERATOR > ( + FUNCTION=eql_v3.ore_block_256_gt, + LEFTARG=eql_v3.ore_block_256, + RIGHTARG=eql_v3.ore_block_256, + COMMUTATOR = <, + NEGATOR = <=, + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel +); + +--! @brief < operator for ORE block types +CREATE OPERATOR < ( + FUNCTION=eql_v3.ore_block_256_lt, + LEFTARG=eql_v3.ore_block_256, + RIGHTARG=eql_v3.ore_block_256, + COMMUTATOR = >, + NEGATOR = >=, + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel +); + +--! @brief <= operator for ORE block types +CREATE OPERATOR <= ( + FUNCTION=eql_v3.ore_block_256_lte, + LEFTARG=eql_v3.ore_block_256, + RIGHTARG=eql_v3.ore_block_256, + COMMUTATOR = >=, + NEGATOR = >, + RESTRICT = scalarlesel, + JOIN = scalarlejoinsel +); + +--! @brief >= operator for ORE block types +CREATE OPERATOR >= ( + FUNCTION=eql_v3.ore_block_256_gte, + LEFTARG=eql_v3.ore_block_256, + RIGHTARG=eql_v3.ore_block_256, + COMMUTATOR = <=, + NEGATOR = <, + RESTRICT = scalargesel, + JOIN = scalargejoinsel +); + +--! @file v3/sem/hmac_256/functions.sql +--! @brief HMAC-SHA256 index-term extraction from a jsonb payload (eql_v3 SEM). +--! +--! jsonb-only subset of src/hmac_256/functions.sql. The encrypted-column and +--! ste_vec-entry overloads are intentionally omitted — the eql_v3 scalar +--! domains extract from the jsonb payload directly via a cast to the domain. +--! (Doc comments deliberately avoid naming eql_v2 symbols so the +--! self-containment grep stays clean.) + +--! @brief Extract HMAC-SHA256 index term from JSONB payload +--! +--! Inlinable single-statement SQL — the planner can fold this into the calling +--! query so functional hash/btree indexes built on `eql_v3.eq_term(col)` +--! (which calls this) engage structurally. +--! +--! @param val jsonb containing encrypted EQL payload +--! @return eql_v3.hmac_256 HMAC-SHA256 hash value, or NULL when `hm` is absent +CREATE FUNCTION eql_v3.hmac_256(val jsonb) + RETURNS eql_v3.hmac_256 + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT (val ->> 'hm')::eql_v3.hmac_256 +$$; + + +--! @brief Check if JSONB payload contains HMAC-SHA256 index term +--! +--! @param val jsonb containing encrypted EQL payload +--! @return boolean True if 'hm' field is present and non-null +CREATE FUNCTION eql_v3.has_hmac_256(val jsonb) + RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT (val ->> 'hm') IS NOT NULL +$$; + +--! @file v3/sem/bloom_filter/functions.sql +--! @brief Extractor for the eql_v3 Bloom-filter SEM index term. +--! +--! jsonb-only subset of src/bloom_filter/functions.sql. The encrypted-column +--! overloads are intentionally omitted — the eql_v3 scalar domains extract from +--! the jsonb payload directly via a cast to the domain. (Doc comments +--! deliberately avoid naming eql_v2 symbols so the self-containment grep stays +--! clean.) + +--! @brief Test whether a jsonb payload carries a Bloom-filter (`bf`) term. +--! +--! @param val jsonb The encrypted payload. +--! @return boolean True when the `bf` key is present and non-null. +--! +--! @internal Defined for parity with the eql_v3 SEM index-term predicates +--! (`has_hmac_256` / `has_ore_block_256`); it is not currently called by +--! the extractor below, which gates on value-shape inline, nor by the generated +--! domain CHECK, which tests `bf` presence via the envelope-key skeleton. Kept +--! as the canonical presence test for callers that need one. +CREATE FUNCTION eql_v3.has_bloom_filter(val jsonb) + RETURNS boolean + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + BEGIN + RETURN val ? 'bf' AND val ->> 'bf' IS NOT NULL; + END; +$$ LANGUAGE plpgsql; + +--! @brief Extract the Bloom-filter index term from a jsonb payload. +--! +--! Inlinable single-statement SQL — the planner can fold this into the calling +--! query so the functional GIN index built on `eql_v3.match_term(col)` (which +--! calls this) engages structurally. Mirrors `eql_v3.hmac_256(jsonb)`: no RAISE +--! and no pinned `search_path`. Returns NULL when `bf` is absent or present but +--! not a json array, rather than raising. The `text_match` domain CHECK +--! guarantees the `bf` *key* is present but not that it is an array, so a +--! non-array `bf` (e.g. `{"bf": null}`) can reach here even on a typed value; +--! gating on `jsonb_typeof(...) = 'array'` returns NULL for that case — and for +--! raw jsonb outside the domain — instead of erroring inside +--! `jsonb_array_elements`. NULL, like the HMAC extractor, is the right answer. An +--! empty `bf` array yields an empty filter (contains nothing, contained by +--! everything), matching set-containment semantics. +--! +--! @param val jsonb The encrypted payload. +--! @return eql_v3.bloom_filter The `bf` array as a smallint[] domain value, or +--! NULL when `bf` is absent or not a json array. +CREATE FUNCTION eql_v3.bloom_filter(val jsonb) + RETURNS eql_v3.bloom_filter + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT CASE WHEN jsonb_typeof(val -> 'bf') = 'array' + THEN ARRAY(SELECT jsonb_array_elements(val -> 'bf'))::eql_v3.bloom_filter + END +$$; +-- AUTOMATICALLY GENERATED FILE. + +--! @file v3/scalars/timestamp/timestamp_types.sql +--! @brief Encrypted-domain types for timestamp. + +DO $$ +BEGIN + --! @brief Encrypted domain eql_v3.timestamp. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'timestamp' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.timestamp AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.timestamp_eq. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'timestamp_eq' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.timestamp_eq AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'hm' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.timestamp_ord_ore. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'timestamp_ord_ore' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.timestamp_ord_ore AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.timestamp_ord. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'timestamp_ord' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.timestamp_ord AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; +END +$$; +-- AUTOMATICALLY GENERATED FILE. + +--! @file v3/scalars/integer/integer_types.sql +--! @brief Encrypted-domain types for integer. + +DO $$ +BEGIN + --! @brief Encrypted domain eql_v3.integer. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'integer' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.integer AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.integer_eq. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'integer_eq' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.integer_eq AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'hm' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.integer_ord_ore. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'integer_ord_ore' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.integer_ord_ore AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.integer_ord. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'integer_ord' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.integer_ord AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; +END +$$; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/integer/integer_ord_functions.sql +--! @brief Functions for eql_v3.integer_ord. + +--! @brief Index extractor for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.integer_ord) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.integer_ord, b eql_v3.integer_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.integer_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.integer_ord) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a jsonb +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.integer_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.integer_ord) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.integer_ord, b eql_v3.integer_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.integer_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.integer_ord) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a jsonb +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.integer_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.integer_ord) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.integer_ord, b eql_v3.integer_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.integer_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.integer_ord) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a jsonb +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.integer_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.integer_ord) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.integer_ord, b eql_v3.integer_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.integer_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.integer_ord) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a jsonb +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.integer_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.integer_ord) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.integer_ord, b eql_v3.integer_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.integer_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.integer_ord) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a jsonb +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.integer_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.integer_ord) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.integer_ord, b eql_v3.integer_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.integer_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.integer_ord) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord. +--! @param a jsonb +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.integer_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.integer_ord) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.integer_ord, b eql_v3.integer_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.integer_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a jsonb +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.integer_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.integer_ord, b eql_v3.integer_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.integer_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a jsonb +--! @param b eql_v3.integer_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.integer_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param selector text +--! @return eql_v3.integer_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.integer_ord, selector text) +RETURNS eql_v3.integer_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param selector integer +--! @return eql_v3.integer_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.integer_ord, selector integer) +RETURNS eql_v3.integer_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a jsonb +--! @param selector eql_v3.integer_ord +--! @return eql_v3.integer_ord +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.integer_ord) +RETURNS eql_v3.integer_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.integer_ord, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.integer_ord, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a jsonb +--! @param selector eql_v3.integer_ord +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.integer_ord) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.integer_ord, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.integer_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.integer_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.integer_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.integer_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.integer_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.integer_ord, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.integer_ord, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.integer_ord, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.integer_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.integer_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b eql_v3.integer_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.integer_ord, b eql_v3.integer_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a eql_v3.integer_ord +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.integer_ord, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord. +--! @param a jsonb +--! @param b eql_v3.integer_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.integer_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.integer_ord'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/integer/integer_ord_operators.sql +--! @brief Operators for eql_v3.integer_ord. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.integer_ord, RIGHTARG = eql_v3.integer_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.integer_ord, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.integer_ord, RIGHTARG = eql_v3.integer_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.integer_ord, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.integer_ord, RIGHTARG = eql_v3.integer_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.integer_ord, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.integer_ord, RIGHTARG = eql_v3.integer_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.integer_ord, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.integer_ord, RIGHTARG = eql_v3.integer_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.integer_ord, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.integer_ord, RIGHTARG = eql_v3.integer_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.integer_ord, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.integer_ord, RIGHTARG = eql_v3.integer_ord +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.integer_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.integer_ord, RIGHTARG = eql_v3.integer_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.integer_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.integer_ord, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.integer_ord, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.integer_ord, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.integer_ord, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.integer_ord, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.integer_ord, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.integer_ord, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.integer_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.integer_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.integer_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.integer_ord, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.integer_ord, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.integer_ord, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.integer_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.integer_ord, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.integer_ord, RIGHTARG = eql_v3.integer_ord +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.integer_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/integer/integer_eq_functions.sql +--! @brief Functions for eql_v3.integer_eq. + +--! @brief Index extractor for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.integer_eq) +RETURNS eql_v3.hmac_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.hmac_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.integer_eq, b eql_v3.integer_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.integer_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.integer_eq) $$; + +--! @brief Operator wrapper for eql_v3.integer_eq. +--! @param a jsonb +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.integer_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.integer_eq) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.integer_eq, b eql_v3.integer_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.integer_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.integer_eq) $$; + +--! @brief Operator wrapper for eql_v3.integer_eq. +--! @param a jsonb +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.integer_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.integer_eq) <> eql_v3.eq_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.integer_eq, b eql_v3.integer_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.integer_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a jsonb +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.integer_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.integer_eq, b eql_v3.integer_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.integer_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a jsonb +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.integer_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.integer_eq, b eql_v3.integer_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.integer_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a jsonb +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.integer_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.integer_eq, b eql_v3.integer_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.integer_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a jsonb +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.integer_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.integer_eq, b eql_v3.integer_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.integer_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a jsonb +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.integer_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.integer_eq, b eql_v3.integer_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.integer_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a jsonb +--! @param b eql_v3.integer_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.integer_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param selector text +--! @return eql_v3.integer_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.integer_eq, selector text) +RETURNS eql_v3.integer_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param selector integer +--! @return eql_v3.integer_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.integer_eq, selector integer) +RETURNS eql_v3.integer_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a jsonb +--! @param selector eql_v3.integer_eq +--! @return eql_v3.integer_eq +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.integer_eq) +RETURNS eql_v3.integer_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.integer_eq, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.integer_eq, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a jsonb +--! @param selector eql_v3.integer_eq +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.integer_eq) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.integer_eq, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.integer_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.integer_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.integer_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.integer_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.integer_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.integer_eq, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.integer_eq, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.integer_eq, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.integer_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.integer_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b eql_v3.integer_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.integer_eq, b eql_v3.integer_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a eql_v3.integer_eq +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.integer_eq, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_eq. +--! @param a jsonb +--! @param b eql_v3.integer_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.integer_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.integer_eq'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file v3/scalars/smallint/smallint_types.sql +--! @brief Encrypted-domain types for smallint. + +DO $$ +BEGIN + --! @brief Encrypted domain eql_v3.smallint. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'smallint' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.smallint AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.smallint_eq. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'smallint_eq' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.smallint_eq AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'hm' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.smallint_ord_ore. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'smallint_ord_ore' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.smallint_ord_ore AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.smallint_ord. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'smallint_ord' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.smallint_ord AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; +END +$$; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/smallint/smallint_ord_ore_functions.sql +--! @brief Functions for eql_v3.smallint_ord_ore. + +--! @brief Index extractor for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.smallint_ord_ore) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.smallint_ord_ore, b eql_v3.smallint_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.smallint_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.smallint_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a jsonb +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.smallint_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.smallint_ord_ore) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.smallint_ord_ore, b eql_v3.smallint_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.smallint_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.smallint_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a jsonb +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.smallint_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.smallint_ord_ore) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.smallint_ord_ore, b eql_v3.smallint_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.smallint_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.smallint_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a jsonb +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.smallint_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.smallint_ord_ore) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.smallint_ord_ore, b eql_v3.smallint_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.smallint_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.smallint_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a jsonb +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.smallint_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.smallint_ord_ore) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.smallint_ord_ore, b eql_v3.smallint_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.smallint_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.smallint_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a jsonb +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.smallint_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.smallint_ord_ore) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.smallint_ord_ore, b eql_v3.smallint_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.smallint_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.smallint_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord_ore. +--! @param a jsonb +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.smallint_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.smallint_ord_ore) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.smallint_ord_ore, b eql_v3.smallint_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.smallint_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a jsonb +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.smallint_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.smallint_ord_ore, b eql_v3.smallint_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.smallint_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a jsonb +--! @param b eql_v3.smallint_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.smallint_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param selector text +--! @return eql_v3.smallint_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.smallint_ord_ore, selector text) +RETURNS eql_v3.smallint_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param selector integer +--! @return eql_v3.smallint_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.smallint_ord_ore, selector integer) +RETURNS eql_v3.smallint_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.smallint_ord_ore +--! @return eql_v3.smallint_ord_ore +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.smallint_ord_ore) +RETURNS eql_v3.smallint_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.smallint_ord_ore, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.smallint_ord_ore, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.smallint_ord_ore +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.smallint_ord_ore) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.smallint_ord_ore, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.smallint_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.smallint_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.smallint_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.smallint_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.smallint_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.smallint_ord_ore, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.smallint_ord_ore, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.smallint_ord_ore, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.smallint_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.smallint_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b eql_v3.smallint_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.smallint_ord_ore, b eql_v3.smallint_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a eql_v3.smallint_ord_ore +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.smallint_ord_ore, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord_ore. +--! @param a jsonb +--! @param b eql_v3.smallint_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.smallint_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.smallint_ord_ore'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/smallint/smallint_ord_functions.sql +--! @brief Functions for eql_v3.smallint_ord. + +--! @brief Index extractor for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.smallint_ord) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.smallint_ord, b eql_v3.smallint_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.smallint_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.smallint_ord) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a jsonb +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.smallint_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.smallint_ord) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.smallint_ord, b eql_v3.smallint_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.smallint_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.smallint_ord) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a jsonb +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.smallint_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.smallint_ord) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.smallint_ord, b eql_v3.smallint_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.smallint_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.smallint_ord) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a jsonb +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.smallint_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.smallint_ord) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.smallint_ord, b eql_v3.smallint_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.smallint_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.smallint_ord) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a jsonb +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.smallint_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.smallint_ord) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.smallint_ord, b eql_v3.smallint_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.smallint_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.smallint_ord) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a jsonb +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.smallint_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.smallint_ord) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.smallint_ord, b eql_v3.smallint_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.smallint_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.smallint_ord) $$; + +--! @brief Operator wrapper for eql_v3.smallint_ord. +--! @param a jsonb +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.smallint_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.smallint_ord) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.smallint_ord, b eql_v3.smallint_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.smallint_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a jsonb +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.smallint_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.smallint_ord, b eql_v3.smallint_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.smallint_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a jsonb +--! @param b eql_v3.smallint_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.smallint_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param selector text +--! @return eql_v3.smallint_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.smallint_ord, selector text) +RETURNS eql_v3.smallint_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param selector integer +--! @return eql_v3.smallint_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.smallint_ord, selector integer) +RETURNS eql_v3.smallint_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a jsonb +--! @param selector eql_v3.smallint_ord +--! @return eql_v3.smallint_ord +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.smallint_ord) +RETURNS eql_v3.smallint_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.smallint_ord, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.smallint_ord, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a jsonb +--! @param selector eql_v3.smallint_ord +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.smallint_ord) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.smallint_ord, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.smallint_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.smallint_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.smallint_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.smallint_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.smallint_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.smallint_ord, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.smallint_ord, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.smallint_ord, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.smallint_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.smallint_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b eql_v3.smallint_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.smallint_ord, b eql_v3.smallint_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a eql_v3.smallint_ord +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.smallint_ord, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_ord. +--! @param a jsonb +--! @param b eql_v3.smallint_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.smallint_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.smallint_ord'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/smallint/smallint_ord_operators.sql +--! @brief Operators for eql_v3.smallint_ord. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = eql_v3.smallint_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = eql_v3.smallint_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = eql_v3.smallint_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = eql_v3.smallint_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = eql_v3.smallint_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = eql_v3.smallint_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = eql_v3.smallint_ord +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = eql_v3.smallint_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.smallint_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = eql_v3.smallint_ord +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.smallint_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/smallint/smallint_functions.sql +--! @brief Functions for eql_v3.smallint. + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.smallint, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.smallint, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a jsonb +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.smallint, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.smallint, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a jsonb +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.smallint, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.smallint, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a jsonb +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.smallint, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.smallint, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a jsonb +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.smallint, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.smallint, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a jsonb +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.smallint, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.smallint, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a jsonb +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.smallint, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.smallint, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a jsonb +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.smallint, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.smallint, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a jsonb +--! @param b eql_v3.smallint +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.smallint) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param selector text +--! @return eql_v3.smallint +CREATE FUNCTION eql_v3."->"(a eql_v3.smallint, selector text) +RETURNS eql_v3.smallint IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param selector integer +--! @return eql_v3.smallint +CREATE FUNCTION eql_v3."->"(a eql_v3.smallint, selector integer) +RETURNS eql_v3.smallint IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a jsonb +--! @param selector eql_v3.smallint +--! @return eql_v3.smallint +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.smallint) +RETURNS eql_v3.smallint IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.smallint, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.smallint, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a jsonb +--! @param selector eql_v3.smallint +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.smallint) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.smallint, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.smallint, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.smallint, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.smallint, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.smallint, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.smallint, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.smallint, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.smallint, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.smallint, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.smallint, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.smallint, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b eql_v3.smallint +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.smallint, b eql_v3.smallint) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a eql_v3.smallint +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.smallint, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint. +--! @param a jsonb +--! @param b eql_v3.smallint +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.smallint) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.smallint'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/smallint/smallint_ord_ore_operators.sql +--! @brief Operators for eql_v3.smallint_ord_ore. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = eql_v3.smallint_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = eql_v3.smallint_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = eql_v3.smallint_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = eql_v3.smallint_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = eql_v3.smallint_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = eql_v3.smallint_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = eql_v3.smallint_ord_ore +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = eql_v3.smallint_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord_ore +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord_ore +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord_ore +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = eql_v3.smallint_ord_ore +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.smallint_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_ord_ore +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file v3/scalars/double/double_types.sql +--! @brief Encrypted-domain types for double. + +DO $$ +BEGIN + --! @brief Encrypted domain eql_v3.double. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'double' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.double AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.double_eq. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'double_eq' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.double_eq AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'hm' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.double_ord_ore. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'double_ord_ore' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.double_ord_ore AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.double_ord. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'double_ord' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.double_ord AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; +END +$$; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/double/double_ord_ore_functions.sql +--! @brief Functions for eql_v3.double_ord_ore. + +--! @brief Index extractor for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.double_ord_ore) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.double_ord_ore, b eql_v3.double_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.double_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.double_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a jsonb +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.double_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.double_ord_ore) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.double_ord_ore, b eql_v3.double_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.double_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.double_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a jsonb +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.double_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.double_ord_ore) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.double_ord_ore, b eql_v3.double_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.double_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.double_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a jsonb +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.double_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.double_ord_ore) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.double_ord_ore, b eql_v3.double_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.double_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.double_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a jsonb +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.double_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.double_ord_ore) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.double_ord_ore, b eql_v3.double_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.double_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.double_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a jsonb +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.double_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.double_ord_ore) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.double_ord_ore, b eql_v3.double_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.double_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.double_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.double_ord_ore. +--! @param a jsonb +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.double_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.double_ord_ore) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.double_ord_ore, b eql_v3.double_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.double_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a jsonb +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.double_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.double_ord_ore, b eql_v3.double_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.double_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a jsonb +--! @param b eql_v3.double_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.double_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param selector text +--! @return eql_v3.double_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.double_ord_ore, selector text) +RETURNS eql_v3.double_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param selector integer +--! @return eql_v3.double_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.double_ord_ore, selector integer) +RETURNS eql_v3.double_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.double_ord_ore +--! @return eql_v3.double_ord_ore +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.double_ord_ore) +RETURNS eql_v3.double_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.double_ord_ore, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.double_ord_ore, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.double_ord_ore +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.double_ord_ore) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.double_ord_ore, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.double_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.double_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.double_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.double_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.double_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.double_ord_ore, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.double_ord_ore, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.double_ord_ore, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.double_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.double_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b eql_v3.double_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.double_ord_ore, b eql_v3.double_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a eql_v3.double_ord_ore +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.double_ord_ore, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord_ore. +--! @param a jsonb +--! @param b eql_v3.double_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.double_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.double_ord_ore'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/double/double_ord_ore_operators.sql +--! @brief Operators for eql_v3.double_ord_ore. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = eql_v3.double_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = eql_v3.double_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = eql_v3.double_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = eql_v3.double_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = eql_v3.double_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = eql_v3.double_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = eql_v3.double_ord_ore +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = eql_v3.double_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord_ore +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord_ore +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord_ore +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = eql_v3.double_ord_ore +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.double_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord_ore +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/double/double_ord_functions.sql +--! @brief Functions for eql_v3.double_ord. + +--! @brief Index extractor for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.double_ord) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.double_ord, b eql_v3.double_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.double_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.double_ord) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a jsonb +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.double_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.double_ord) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.double_ord, b eql_v3.double_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.double_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.double_ord) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a jsonb +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.double_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.double_ord) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.double_ord, b eql_v3.double_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.double_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.double_ord) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a jsonb +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.double_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.double_ord) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.double_ord, b eql_v3.double_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.double_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.double_ord) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a jsonb +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.double_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.double_ord) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.double_ord, b eql_v3.double_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.double_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.double_ord) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a jsonb +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.double_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.double_ord) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.double_ord, b eql_v3.double_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.double_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.double_ord) $$; + +--! @brief Operator wrapper for eql_v3.double_ord. +--! @param a jsonb +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.double_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.double_ord) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.double_ord, b eql_v3.double_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.double_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a jsonb +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.double_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.double_ord, b eql_v3.double_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.double_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a jsonb +--! @param b eql_v3.double_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.double_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param selector text +--! @return eql_v3.double_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.double_ord, selector text) +RETURNS eql_v3.double_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param selector integer +--! @return eql_v3.double_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.double_ord, selector integer) +RETURNS eql_v3.double_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a jsonb +--! @param selector eql_v3.double_ord +--! @return eql_v3.double_ord +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.double_ord) +RETURNS eql_v3.double_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.double_ord, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.double_ord, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a jsonb +--! @param selector eql_v3.double_ord +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.double_ord) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.double_ord, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.double_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.double_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.double_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.double_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.double_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.double_ord, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.double_ord, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.double_ord, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.double_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.double_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b eql_v3.double_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.double_ord, b eql_v3.double_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a eql_v3.double_ord +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.double_ord, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_ord. +--! @param a jsonb +--! @param b eql_v3.double_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.double_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.double_ord'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/double/double_functions.sql +--! @brief Functions for eql_v3.double. + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.double, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.double, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a jsonb +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.double, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.double, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a jsonb +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.double, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.double, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a jsonb +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.double, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.double, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a jsonb +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.double, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.double, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a jsonb +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.double, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.double, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a jsonb +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.double, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.double, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a jsonb +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.double, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.double, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a jsonb +--! @param b eql_v3.double +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.double) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param selector text +--! @return eql_v3.double +CREATE FUNCTION eql_v3."->"(a eql_v3.double, selector text) +RETURNS eql_v3.double IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param selector integer +--! @return eql_v3.double +CREATE FUNCTION eql_v3."->"(a eql_v3.double, selector integer) +RETURNS eql_v3.double IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a jsonb +--! @param selector eql_v3.double +--! @return eql_v3.double +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.double) +RETURNS eql_v3.double IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.double, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.double, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a jsonb +--! @param selector eql_v3.double +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.double) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.double, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.double, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.double, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.double, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.double, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.double, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.double, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.double, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.double, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.double, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.double, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b eql_v3.double +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.double, b eql_v3.double) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a eql_v3.double +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.double, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double. +--! @param a jsonb +--! @param b eql_v3.double +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.double) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.double'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file v3/scalars/date/date_types.sql +--! @brief Encrypted-domain types for date. + +DO $$ +BEGIN + --! @brief Encrypted domain eql_v3.date. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'date' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.date AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.date_eq. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'date_eq' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.date_eq AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'hm' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.date_ord_ore. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'date_ord_ore' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.date_ord_ore AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.date_ord. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'date_ord' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.date_ord AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; +END +$$; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/date/date_ord_ore_functions.sql +--! @brief Functions for eql_v3.date_ord_ore. + +--! @brief Index extractor for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.date_ord_ore) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.date_ord_ore, b eql_v3.date_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.date_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.date_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a jsonb +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.date_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.date_ord_ore) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.date_ord_ore, b eql_v3.date_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.date_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.date_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a jsonb +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.date_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.date_ord_ore) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.date_ord_ore, b eql_v3.date_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.date_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.date_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a jsonb +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.date_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.date_ord_ore) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.date_ord_ore, b eql_v3.date_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.date_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.date_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a jsonb +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.date_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.date_ord_ore) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.date_ord_ore, b eql_v3.date_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.date_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.date_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a jsonb +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.date_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.date_ord_ore) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.date_ord_ore, b eql_v3.date_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.date_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.date_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.date_ord_ore. +--! @param a jsonb +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.date_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.date_ord_ore) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.date_ord_ore, b eql_v3.date_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.date_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a jsonb +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.date_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.date_ord_ore, b eql_v3.date_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.date_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a jsonb +--! @param b eql_v3.date_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.date_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param selector text +--! @return eql_v3.date_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.date_ord_ore, selector text) +RETURNS eql_v3.date_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param selector integer +--! @return eql_v3.date_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.date_ord_ore, selector integer) +RETURNS eql_v3.date_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.date_ord_ore +--! @return eql_v3.date_ord_ore +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.date_ord_ore) +RETURNS eql_v3.date_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.date_ord_ore, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.date_ord_ore, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.date_ord_ore +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.date_ord_ore) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.date_ord_ore, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.date_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.date_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.date_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.date_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.date_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.date_ord_ore, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.date_ord_ore, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.date_ord_ore, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.date_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.date_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b eql_v3.date_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.date_ord_ore, b eql_v3.date_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a eql_v3.date_ord_ore +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.date_ord_ore, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord_ore. +--! @param a jsonb +--! @param b eql_v3.date_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.date_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.date_ord_ore'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/date/date_eq_functions.sql +--! @brief Functions for eql_v3.date_eq. + +--! @brief Index extractor for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.date_eq) +RETURNS eql_v3.hmac_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.hmac_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.date_eq, b eql_v3.date_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.date_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.date_eq) $$; + +--! @brief Operator wrapper for eql_v3.date_eq. +--! @param a jsonb +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.date_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.date_eq) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.date_eq, b eql_v3.date_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.date_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.date_eq) $$; + +--! @brief Operator wrapper for eql_v3.date_eq. +--! @param a jsonb +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.date_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.date_eq) <> eql_v3.eq_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.date_eq, b eql_v3.date_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.date_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a jsonb +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.date_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.date_eq, b eql_v3.date_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.date_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a jsonb +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.date_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.date_eq, b eql_v3.date_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.date_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a jsonb +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.date_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.date_eq, b eql_v3.date_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.date_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a jsonb +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.date_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.date_eq, b eql_v3.date_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.date_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a jsonb +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.date_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.date_eq, b eql_v3.date_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.date_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a jsonb +--! @param b eql_v3.date_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.date_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param selector text +--! @return eql_v3.date_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.date_eq, selector text) +RETURNS eql_v3.date_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param selector integer +--! @return eql_v3.date_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.date_eq, selector integer) +RETURNS eql_v3.date_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a jsonb +--! @param selector eql_v3.date_eq +--! @return eql_v3.date_eq +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.date_eq) +RETURNS eql_v3.date_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.date_eq, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.date_eq, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a jsonb +--! @param selector eql_v3.date_eq +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.date_eq) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.date_eq, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.date_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.date_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.date_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.date_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.date_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.date_eq, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.date_eq, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.date_eq, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.date_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.date_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b eql_v3.date_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.date_eq, b eql_v3.date_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a eql_v3.date_eq +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.date_eq, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_eq. +--! @param a jsonb +--! @param b eql_v3.date_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.date_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.date_eq'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/date/date_functions.sql +--! @brief Functions for eql_v3.date. + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.date, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.date, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a jsonb +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.date, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.date, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a jsonb +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.date, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.date, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a jsonb +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.date, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.date, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a jsonb +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.date, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.date, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a jsonb +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.date, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.date, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a jsonb +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.date, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.date, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a jsonb +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.date, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.date, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a jsonb +--! @param b eql_v3.date +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.date) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param selector text +--! @return eql_v3.date +CREATE FUNCTION eql_v3."->"(a eql_v3.date, selector text) +RETURNS eql_v3.date IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param selector integer +--! @return eql_v3.date +CREATE FUNCTION eql_v3."->"(a eql_v3.date, selector integer) +RETURNS eql_v3.date IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a jsonb +--! @param selector eql_v3.date +--! @return eql_v3.date +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.date) +RETURNS eql_v3.date IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.date, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.date, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a jsonb +--! @param selector eql_v3.date +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.date) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.date, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.date, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.date, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.date, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.date, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.date, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.date, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.date, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.date, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.date, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.date, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b eql_v3.date +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.date, b eql_v3.date) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a eql_v3.date +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.date, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date. +--! @param a jsonb +--! @param b eql_v3.date +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.date) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.date'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/date/date_ord_ore_operators.sql +--! @brief Operators for eql_v3.date_ord_ore. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = eql_v3.date_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = eql_v3.date_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = eql_v3.date_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = eql_v3.date_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = eql_v3.date_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = eql_v3.date_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = eql_v3.date_ord_ore +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = eql_v3.date_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord_ore +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord_ore +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord_ore +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = eql_v3.date_ord_ore +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.date_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord_ore +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file v3/scalars/numeric/numeric_types.sql +--! @brief Encrypted-domain types for numeric. + +DO $$ +BEGIN + --! @brief Encrypted domain eql_v3.numeric. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'numeric' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.numeric AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.numeric_eq. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'numeric_eq' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.numeric_eq AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'hm' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.numeric_ord_ore. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'numeric_ord_ore' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.numeric_ord_ore AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.numeric_ord. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'numeric_ord' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.numeric_ord AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; +END +$$; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/numeric/numeric_ord_ore_functions.sql +--! @brief Functions for eql_v3.numeric_ord_ore. + +--! @brief Index extractor for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.numeric_ord_ore) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.numeric_ord_ore, b eql_v3.numeric_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.numeric_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.numeric_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a jsonb +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.numeric_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.numeric_ord_ore) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.numeric_ord_ore, b eql_v3.numeric_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.numeric_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.numeric_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a jsonb +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.numeric_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.numeric_ord_ore) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.numeric_ord_ore, b eql_v3.numeric_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.numeric_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.numeric_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a jsonb +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.numeric_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.numeric_ord_ore) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.numeric_ord_ore, b eql_v3.numeric_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.numeric_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.numeric_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a jsonb +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.numeric_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.numeric_ord_ore) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.numeric_ord_ore, b eql_v3.numeric_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.numeric_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.numeric_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a jsonb +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.numeric_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.numeric_ord_ore) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.numeric_ord_ore, b eql_v3.numeric_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.numeric_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.numeric_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord_ore. +--! @param a jsonb +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.numeric_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.numeric_ord_ore) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.numeric_ord_ore, b eql_v3.numeric_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.numeric_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a jsonb +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.numeric_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.numeric_ord_ore, b eql_v3.numeric_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.numeric_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a jsonb +--! @param b eql_v3.numeric_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.numeric_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param selector text +--! @return eql_v3.numeric_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.numeric_ord_ore, selector text) +RETURNS eql_v3.numeric_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param selector integer +--! @return eql_v3.numeric_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.numeric_ord_ore, selector integer) +RETURNS eql_v3.numeric_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.numeric_ord_ore +--! @return eql_v3.numeric_ord_ore +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.numeric_ord_ore) +RETURNS eql_v3.numeric_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.numeric_ord_ore, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.numeric_ord_ore, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.numeric_ord_ore +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.numeric_ord_ore) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.numeric_ord_ore, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.numeric_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.numeric_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.numeric_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.numeric_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.numeric_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.numeric_ord_ore, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.numeric_ord_ore, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.numeric_ord_ore, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.numeric_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.numeric_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b eql_v3.numeric_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.numeric_ord_ore, b eql_v3.numeric_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a eql_v3.numeric_ord_ore +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.numeric_ord_ore, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord_ore. +--! @param a jsonb +--! @param b eql_v3.numeric_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.numeric_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.numeric_ord_ore'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/numeric/numeric_eq_functions.sql +--! @brief Functions for eql_v3.numeric_eq. + +--! @brief Index extractor for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.numeric_eq) +RETURNS eql_v3.hmac_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.hmac_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.numeric_eq, b eql_v3.numeric_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.numeric_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.numeric_eq) $$; + +--! @brief Operator wrapper for eql_v3.numeric_eq. +--! @param a jsonb +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.numeric_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.numeric_eq) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.numeric_eq, b eql_v3.numeric_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.numeric_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.numeric_eq) $$; + +--! @brief Operator wrapper for eql_v3.numeric_eq. +--! @param a jsonb +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.numeric_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.numeric_eq) <> eql_v3.eq_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.numeric_eq, b eql_v3.numeric_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.numeric_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a jsonb +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.numeric_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.numeric_eq, b eql_v3.numeric_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.numeric_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a jsonb +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.numeric_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.numeric_eq, b eql_v3.numeric_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.numeric_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a jsonb +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.numeric_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.numeric_eq, b eql_v3.numeric_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.numeric_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a jsonb +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.numeric_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.numeric_eq, b eql_v3.numeric_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.numeric_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a jsonb +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.numeric_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.numeric_eq, b eql_v3.numeric_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.numeric_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a jsonb +--! @param b eql_v3.numeric_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.numeric_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param selector text +--! @return eql_v3.numeric_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.numeric_eq, selector text) +RETURNS eql_v3.numeric_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param selector integer +--! @return eql_v3.numeric_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.numeric_eq, selector integer) +RETURNS eql_v3.numeric_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a jsonb +--! @param selector eql_v3.numeric_eq +--! @return eql_v3.numeric_eq +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.numeric_eq) +RETURNS eql_v3.numeric_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.numeric_eq, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.numeric_eq, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a jsonb +--! @param selector eql_v3.numeric_eq +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.numeric_eq) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.numeric_eq, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.numeric_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.numeric_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.numeric_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.numeric_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.numeric_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.numeric_eq, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.numeric_eq, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.numeric_eq, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.numeric_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.numeric_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b eql_v3.numeric_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.numeric_eq, b eql_v3.numeric_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a eql_v3.numeric_eq +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.numeric_eq, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_eq. +--! @param a jsonb +--! @param b eql_v3.numeric_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.numeric_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.numeric_eq'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/numeric/numeric_ord_ore_operators.sql +--! @brief Operators for eql_v3.numeric_ord_ore. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = eql_v3.numeric_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = eql_v3.numeric_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = eql_v3.numeric_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = eql_v3.numeric_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = eql_v3.numeric_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = eql_v3.numeric_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = eql_v3.numeric_ord_ore +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = eql_v3.numeric_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord_ore +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord_ore +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord_ore +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = eql_v3.numeric_ord_ore +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.numeric_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord_ore +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file v3/scalars/bool/bool_types.sql +--! @brief Encrypted-domain types for bool. + +DO $$ +BEGIN + --! @brief Encrypted domain eql_v3.bool. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'bool' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.bool AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE->>'v' = '2' + ); + END IF; +END +$$; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/bool/bool_functions.sql +--! @brief Functions for eql_v3.bool. + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.bool, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.bool, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a jsonb +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.bool, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.bool, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a jsonb +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.bool, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.bool, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a jsonb +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.bool, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.bool, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a jsonb +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.bool, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.bool, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a jsonb +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.bool, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.bool, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a jsonb +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.bool, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.bool, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a jsonb +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.bool, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.bool, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a jsonb +--! @param b eql_v3.bool +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.bool) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param selector text +--! @return eql_v3.bool +CREATE FUNCTION eql_v3."->"(a eql_v3.bool, selector text) +RETURNS eql_v3.bool IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param selector integer +--! @return eql_v3.bool +CREATE FUNCTION eql_v3."->"(a eql_v3.bool, selector integer) +RETURNS eql_v3.bool IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a jsonb +--! @param selector eql_v3.bool +--! @return eql_v3.bool +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.bool) +RETURNS eql_v3.bool IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.bool, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.bool, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a jsonb +--! @param selector eql_v3.bool +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.bool) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.bool, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.bool, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.bool, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.bool, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.bool, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.bool, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.bool, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.bool, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.bool, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.bool, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.bool, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b eql_v3.bool +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.bool, b eql_v3.bool) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a eql_v3.bool +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.bool, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.bool. +--! @param a jsonb +--! @param b eql_v3.bool +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.bool) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.bool'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file v3/scalars/int8/int8_types.sql +--! @brief Encrypted-domain types for int8. + +DO $$ +BEGIN + --! @brief Encrypted domain eql_v3.int8. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'int8' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.int8 AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.int8_eq. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'int8_eq' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.int8_eq AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'hm' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.int8_ord_ore. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'int8_ord_ore' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.int8_ord_ore AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.int8_ord. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'int8_ord' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.int8_ord AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; +END +$$; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/int8/int8_functions.sql +--! @brief Functions for eql_v3.int8. + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int8, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int8, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a jsonb +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int8, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int8, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a jsonb +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int8, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int8, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a jsonb +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int8, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int8, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a jsonb +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int8, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int8, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a jsonb +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int8, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int8, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a jsonb +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int8, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int8, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a jsonb +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int8, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int8, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a jsonb +--! @param b eql_v3.int8 +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.int8) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param selector text +--! @return eql_v3.int8 +CREATE FUNCTION eql_v3."->"(a eql_v3.int8, selector text) +RETURNS eql_v3.int8 IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param selector integer +--! @return eql_v3.int8 +CREATE FUNCTION eql_v3."->"(a eql_v3.int8, selector integer) +RETURNS eql_v3.int8 IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a jsonb +--! @param selector eql_v3.int8 +--! @return eql_v3.int8 +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int8) +RETURNS eql_v3.int8 IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int8, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int8, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a jsonb +--! @param selector eql_v3.int8 +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.int8) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.int8, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.int8, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.int8, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.int8, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.int8, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.int8, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.int8, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int8, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int8, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int8, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.int8, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b eql_v3.int8 +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int8, b eql_v3.int8) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a eql_v3.int8 +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int8, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8. +--! @param a jsonb +--! @param b eql_v3.int8 +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int8) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int8'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/int8/int8_ord_functions.sql +--! @brief Functions for eql_v3.int8_ord. + +--! @brief Index extractor for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.int8_ord) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int8_ord, b eql_v3.int8_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int8_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.int8_ord) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a jsonb +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.int8_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int8_ord) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int8_ord, b eql_v3.int8_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int8_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.int8_ord) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a jsonb +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.int8_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int8_ord) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int8_ord, b eql_v3.int8_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int8_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.int8_ord) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a jsonb +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.int8_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int8_ord) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int8_ord, b eql_v3.int8_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int8_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.int8_ord) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a jsonb +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.int8_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int8_ord) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int8_ord, b eql_v3.int8_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int8_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.int8_ord) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a jsonb +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.int8_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int8_ord) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int8_ord, b eql_v3.int8_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int8_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.int8_ord) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord. +--! @param a jsonb +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.int8_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int8_ord) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int8_ord, b eql_v3.int8_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int8_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a jsonb +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.int8_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int8_ord, b eql_v3.int8_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int8_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a jsonb +--! @param b eql_v3.int8_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.int8_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param selector text +--! @return eql_v3.int8_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.int8_ord, selector text) +RETURNS eql_v3.int8_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param selector integer +--! @return eql_v3.int8_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.int8_ord, selector integer) +RETURNS eql_v3.int8_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a jsonb +--! @param selector eql_v3.int8_ord +--! @return eql_v3.int8_ord +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int8_ord) +RETURNS eql_v3.int8_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int8_ord, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int8_ord, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a jsonb +--! @param selector eql_v3.int8_ord +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.int8_ord) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.int8_ord, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.int8_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.int8_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.int8_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.int8_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.int8_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.int8_ord, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int8_ord, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int8_ord, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int8_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.int8_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b eql_v3.int8_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int8_ord, b eql_v3.int8_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a eql_v3.int8_ord +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int8_ord, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord. +--! @param a jsonb +--! @param b eql_v3.int8_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int8_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int8_ord'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file v3/scalars/text/text_types.sql +--! @brief Encrypted-domain types for text. + +DO $$ +BEGIN + --! @brief Encrypted domain eql_v3.text. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'text' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.text AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.text_eq. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'text_eq' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.text_eq AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'hm' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.text_match. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'text_match' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.text_match AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'bf' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.text_ord_ore. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'text_ord_ore' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.text_ord_ore AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'hm' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.text_ord. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'text_ord' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.text_ord AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'hm' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.text_search. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'text_search' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.text_search AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'hm' + AND VALUE ? 'ob' + AND VALUE ? 'bf' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; +END +$$; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_ord_functions.sql +--! @brief Functions for eql_v3.text_ord. + +--! @brief Index extractor for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.text_ord) +RETURNS eql_v3.hmac_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.hmac_256(a::jsonb) $$; + +--! @brief Index extractor for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.text_ord) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.text_ord, b eql_v3.text_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.text_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.text_ord) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a jsonb +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.text_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.text_ord) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.text_ord, b eql_v3.text_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.text_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.text_ord) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a jsonb +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.text_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.text_ord) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.text_ord, b eql_v3.text_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.text_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.text_ord) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a jsonb +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.text_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.text_ord) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.text_ord, b eql_v3.text_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.text_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.text_ord) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a jsonb +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.text_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.text_ord) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.text_ord, b eql_v3.text_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.text_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.text_ord) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a jsonb +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.text_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.text_ord) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.text_ord, b eql_v3.text_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.text_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.text_ord) $$; + +--! @brief Operator wrapper for eql_v3.text_ord. +--! @param a jsonb +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.text_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.text_ord) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.text_ord, b eql_v3.text_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.text_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a jsonb +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.text_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.text_ord, b eql_v3.text_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.text_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a jsonb +--! @param b eql_v3.text_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.text_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param selector text +--! @return eql_v3.text_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.text_ord, selector text) +RETURNS eql_v3.text_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param selector integer +--! @return eql_v3.text_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.text_ord, selector integer) +RETURNS eql_v3.text_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a jsonb +--! @param selector eql_v3.text_ord +--! @return eql_v3.text_ord +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.text_ord) +RETURNS eql_v3.text_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.text_ord, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.text_ord, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a jsonb +--! @param selector eql_v3.text_ord +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.text_ord) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.text_ord, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.text_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.text_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.text_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.text_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.text_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.text_ord, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_ord, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_ord, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.text_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b eql_v3.text_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.text_ord, b eql_v3.text_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a eql_v3.text_ord +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.text_ord, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord. +--! @param a jsonb +--! @param b eql_v3.text_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.text_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_ord'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_ord_ore_functions.sql +--! @brief Functions for eql_v3.text_ord_ore. + +--! @brief Index extractor for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.text_ord_ore) +RETURNS eql_v3.hmac_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.hmac_256(a::jsonb) $$; + +--! @brief Index extractor for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.text_ord_ore) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.text_ord_ore, b eql_v3.text_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.text_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.text_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a jsonb +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.text_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.text_ord_ore) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.text_ord_ore, b eql_v3.text_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.text_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.text_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a jsonb +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.text_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.text_ord_ore) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.text_ord_ore, b eql_v3.text_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.text_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.text_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a jsonb +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.text_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.text_ord_ore) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.text_ord_ore, b eql_v3.text_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.text_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.text_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a jsonb +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.text_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.text_ord_ore) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.text_ord_ore, b eql_v3.text_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.text_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.text_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a jsonb +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.text_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.text_ord_ore) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.text_ord_ore, b eql_v3.text_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.text_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.text_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.text_ord_ore. +--! @param a jsonb +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.text_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.text_ord_ore) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.text_ord_ore, b eql_v3.text_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.text_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a jsonb +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.text_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.text_ord_ore, b eql_v3.text_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.text_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a jsonb +--! @param b eql_v3.text_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.text_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param selector text +--! @return eql_v3.text_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.text_ord_ore, selector text) +RETURNS eql_v3.text_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param selector integer +--! @return eql_v3.text_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.text_ord_ore, selector integer) +RETURNS eql_v3.text_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.text_ord_ore +--! @return eql_v3.text_ord_ore +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.text_ord_ore) +RETURNS eql_v3.text_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.text_ord_ore, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.text_ord_ore, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.text_ord_ore +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.text_ord_ore) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.text_ord_ore, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.text_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.text_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.text_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.text_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.text_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.text_ord_ore, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_ord_ore, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_ord_ore, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.text_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b eql_v3.text_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.text_ord_ore, b eql_v3.text_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a eql_v3.text_ord_ore +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.text_ord_ore, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_ord_ore. +--! @param a jsonb +--! @param b eql_v3.text_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.text_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_ord_ore'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_match_functions.sql +--! @brief Functions for eql_v3.text_match. + +--! @brief Index extractor for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @return eql_v3.bloom_filter +CREATE FUNCTION eql_v3.match_term(a eql_v3.text_match) +RETURNS eql_v3.bloom_filter +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.bloom_filter(a::jsonb) $$; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.text_match, b eql_v3.text_match) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.text_match, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a jsonb +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.text_match) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.text_match, b eql_v3.text_match) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.text_match, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a jsonb +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.text_match) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.text_match, b eql_v3.text_match) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.text_match, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a jsonb +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.text_match) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.text_match, b eql_v3.text_match) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.text_match, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a jsonb +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.text_match) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.text_match, b eql_v3.text_match) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.text_match, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a jsonb +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.text_match) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.text_match, b eql_v3.text_match) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.text_match, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a jsonb +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.text_match) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Operator wrapper for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.text_match, b eql_v3.text_match) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.match_term(a) @> eql_v3.match_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.text_match, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.match_term(a) @> eql_v3.match_term(b::eql_v3.text_match) $$; + +--! @brief Operator wrapper for eql_v3.text_match. +--! @param a jsonb +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.text_match) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.match_term(a::eql_v3.text_match) @> eql_v3.match_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.text_match, b eql_v3.text_match) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.match_term(a) <@ eql_v3.match_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.text_match, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.match_term(a) <@ eql_v3.match_term(b::eql_v3.text_match) $$; + +--! @brief Operator wrapper for eql_v3.text_match. +--! @param a jsonb +--! @param b eql_v3.text_match +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.text_match) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.match_term(a::eql_v3.text_match) <@ eql_v3.match_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param selector text +--! @return eql_v3.text_match +CREATE FUNCTION eql_v3."->"(a eql_v3.text_match, selector text) +RETURNS eql_v3.text_match IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param selector integer +--! @return eql_v3.text_match +CREATE FUNCTION eql_v3."->"(a eql_v3.text_match, selector integer) +RETURNS eql_v3.text_match IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a jsonb +--! @param selector eql_v3.text_match +--! @return eql_v3.text_match +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.text_match) +RETURNS eql_v3.text_match IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.text_match, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.text_match, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a jsonb +--! @param selector eql_v3.text_match +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.text_match) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.text_match, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.text_match, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.text_match, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.text_match, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.text_match, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.text_match, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.text_match, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_match, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_match, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_match, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.text_match, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b eql_v3.text_match +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.text_match, b eql_v3.text_match) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a eql_v3.text_match +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.text_match, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_match. +--! @param a jsonb +--! @param b eql_v3.text_match +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.text_match) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_match'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_search_functions.sql +--! @brief Functions for eql_v3.text_search. + +--! @brief Index extractor for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.text_search) +RETURNS eql_v3.hmac_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.hmac_256(a::jsonb) $$; + +--! @brief Index extractor for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.text_search) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Index extractor for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @return eql_v3.bloom_filter +CREATE FUNCTION eql_v3.match_term(a eql_v3.text_search) +RETURNS eql_v3.bloom_filter +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.bloom_filter(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.text_search, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.text_search, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.text_search) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a jsonb +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.text_search) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.text_search, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.text_search, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.text_search) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a jsonb +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.text_search) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.text_search, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.text_search, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.text_search) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a jsonb +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.text_search) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.text_search, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.text_search, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.text_search) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a jsonb +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.text_search) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.text_search, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.text_search, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.text_search) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a jsonb +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.text_search) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.text_search, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.text_search, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.text_search) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a jsonb +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.text_search) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.text_search, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.match_term(a) @> eql_v3.match_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.text_search, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.match_term(a) @> eql_v3.match_term(b::eql_v3.text_search) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a jsonb +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.match_term(a::eql_v3.text_search) @> eql_v3.match_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.text_search, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.match_term(a) <@ eql_v3.match_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.text_search, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.match_term(a) <@ eql_v3.match_term(b::eql_v3.text_search) $$; + +--! @brief Operator wrapper for eql_v3.text_search. +--! @param a jsonb +--! @param b eql_v3.text_search +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.text_search) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.match_term(a::eql_v3.text_search) <@ eql_v3.match_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param selector text +--! @return eql_v3.text_search +CREATE FUNCTION eql_v3."->"(a eql_v3.text_search, selector text) +RETURNS eql_v3.text_search IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param selector integer +--! @return eql_v3.text_search +CREATE FUNCTION eql_v3."->"(a eql_v3.text_search, selector integer) +RETURNS eql_v3.text_search IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a jsonb +--! @param selector eql_v3.text_search +--! @return eql_v3.text_search +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.text_search) +RETURNS eql_v3.text_search IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.text_search, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.text_search, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a jsonb +--! @param selector eql_v3.text_search +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.text_search) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.text_search, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.text_search, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.text_search, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.text_search, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.text_search, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.text_search, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.text_search, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_search, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_search, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_search, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.text_search, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b eql_v3.text_search +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.text_search, b eql_v3.text_search) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a eql_v3.text_search +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.text_search, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_search. +--! @param a jsonb +--! @param b eql_v3.text_search +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.text_search) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_search'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_eq_functions.sql +--! @brief Functions for eql_v3.text_eq. + +--! @brief Index extractor for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.text_eq) +RETURNS eql_v3.hmac_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.hmac_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.text_eq, b eql_v3.text_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.text_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.text_eq) $$; + +--! @brief Operator wrapper for eql_v3.text_eq. +--! @param a jsonb +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.text_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.text_eq) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.text_eq, b eql_v3.text_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.text_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.text_eq) $$; + +--! @brief Operator wrapper for eql_v3.text_eq. +--! @param a jsonb +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.text_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.text_eq) <> eql_v3.eq_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.text_eq, b eql_v3.text_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.text_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a jsonb +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.text_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.text_eq, b eql_v3.text_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.text_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a jsonb +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.text_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.text_eq, b eql_v3.text_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.text_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a jsonb +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.text_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.text_eq, b eql_v3.text_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.text_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a jsonb +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.text_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.text_eq, b eql_v3.text_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.text_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a jsonb +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.text_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.text_eq, b eql_v3.text_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.text_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a jsonb +--! @param b eql_v3.text_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.text_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param selector text +--! @return eql_v3.text_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.text_eq, selector text) +RETURNS eql_v3.text_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param selector integer +--! @return eql_v3.text_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.text_eq, selector integer) +RETURNS eql_v3.text_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a jsonb +--! @param selector eql_v3.text_eq +--! @return eql_v3.text_eq +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.text_eq) +RETURNS eql_v3.text_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.text_eq, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.text_eq, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a jsonb +--! @param selector eql_v3.text_eq +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.text_eq) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.text_eq, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.text_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.text_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.text_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.text_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.text_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.text_eq, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_eq, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_eq, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.text_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b eql_v3.text_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.text_eq, b eql_v3.text_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a eql_v3.text_eq +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.text_eq, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text_eq. +--! @param a jsonb +--! @param b eql_v3.text_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.text_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text_eq'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_ord_ore_operators.sql +--! @brief Operators for eql_v3.text_ord_ore. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = eql_v3.text_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = eql_v3.text_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = eql_v3.text_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = eql_v3.text_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = eql_v3.text_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = eql_v3.text_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = eql_v3.text_ord_ore +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = eql_v3.text_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord_ore +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord_ore +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord_ore +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = eql_v3.text_ord_ore +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.text_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord_ore +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_ord_operators.sql +--! @brief Operators for eql_v3.text_ord. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.text_ord, RIGHTARG = eql_v3.text_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.text_ord, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.text_ord, RIGHTARG = eql_v3.text_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.text_ord, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.text_ord, RIGHTARG = eql_v3.text_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.text_ord, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.text_ord, RIGHTARG = eql_v3.text_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.text_ord, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.text_ord, RIGHTARG = eql_v3.text_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.text_ord, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.text_ord, RIGHTARG = eql_v3.text_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.text_ord, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.text_ord, RIGHTARG = eql_v3.text_ord +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.text_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.text_ord, RIGHTARG = eql_v3.text_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.text_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.text_ord, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.text_ord, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.text_ord, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.text_ord, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.text_ord, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.text_ord, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.text_ord, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.text_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.text_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.text_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.text_ord, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_ord, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_ord, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.text_ord, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.text_ord, RIGHTARG = eql_v3.text_ord +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.text_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_ord +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file v3/scalars/real/real_types.sql +--! @brief Encrypted-domain types for real. + +DO $$ +BEGIN + --! @brief Encrypted domain eql_v3.real. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'real' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.real AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.real_eq. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'real_eq' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.real_eq AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'hm' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.real_ord_ore. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'real_ord_ore' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.real_ord_ore AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.real_ord. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'real_ord' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.real_ord AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND jsonb_typeof(VALUE -> 'ob') = 'array' + AND jsonb_array_length(VALUE -> 'ob') > 0 + AND VALUE->>'v' = '2' + ); + END IF; +END +$$; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/real/real_ord_ore_functions.sql +--! @brief Functions for eql_v3.real_ord_ore. + +--! @brief Index extractor for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.real_ord_ore) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.real_ord_ore, b eql_v3.real_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.real_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.real_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a jsonb +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.real_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.real_ord_ore) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.real_ord_ore, b eql_v3.real_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.real_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.real_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a jsonb +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.real_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.real_ord_ore) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.real_ord_ore, b eql_v3.real_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.real_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.real_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a jsonb +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.real_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.real_ord_ore) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.real_ord_ore, b eql_v3.real_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.real_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.real_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a jsonb +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.real_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.real_ord_ore) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.real_ord_ore, b eql_v3.real_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.real_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.real_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a jsonb +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.real_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.real_ord_ore) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.real_ord_ore, b eql_v3.real_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.real_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.real_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.real_ord_ore. +--! @param a jsonb +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.real_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.real_ord_ore) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.real_ord_ore, b eql_v3.real_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.real_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a jsonb +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.real_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.real_ord_ore, b eql_v3.real_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.real_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a jsonb +--! @param b eql_v3.real_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.real_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param selector text +--! @return eql_v3.real_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.real_ord_ore, selector text) +RETURNS eql_v3.real_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param selector integer +--! @return eql_v3.real_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.real_ord_ore, selector integer) +RETURNS eql_v3.real_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.real_ord_ore +--! @return eql_v3.real_ord_ore +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.real_ord_ore) +RETURNS eql_v3.real_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.real_ord_ore, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.real_ord_ore, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.real_ord_ore +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.real_ord_ore) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.real_ord_ore, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.real_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.real_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.real_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.real_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.real_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.real_ord_ore, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.real_ord_ore, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.real_ord_ore, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.real_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.real_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b eql_v3.real_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.real_ord_ore, b eql_v3.real_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a eql_v3.real_ord_ore +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.real_ord_ore, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord_ore. +--! @param a jsonb +--! @param b eql_v3.real_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.real_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.real_ord_ore'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/real/real_eq_functions.sql +--! @brief Functions for eql_v3.real_eq. + +--! @brief Index extractor for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.real_eq) +RETURNS eql_v3.hmac_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.hmac_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.real_eq, b eql_v3.real_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.real_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.real_eq) $$; + +--! @brief Operator wrapper for eql_v3.real_eq. +--! @param a jsonb +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.real_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.real_eq) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.real_eq, b eql_v3.real_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.real_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.real_eq) $$; + +--! @brief Operator wrapper for eql_v3.real_eq. +--! @param a jsonb +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.real_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.real_eq) <> eql_v3.eq_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.real_eq, b eql_v3.real_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.real_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a jsonb +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.real_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.real_eq, b eql_v3.real_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.real_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a jsonb +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.real_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.real_eq, b eql_v3.real_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.real_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a jsonb +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.real_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.real_eq, b eql_v3.real_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.real_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a jsonb +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.real_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.real_eq, b eql_v3.real_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.real_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a jsonb +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.real_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.real_eq, b eql_v3.real_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.real_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a jsonb +--! @param b eql_v3.real_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.real_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param selector text +--! @return eql_v3.real_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.real_eq, selector text) +RETURNS eql_v3.real_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param selector integer +--! @return eql_v3.real_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.real_eq, selector integer) +RETURNS eql_v3.real_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a jsonb +--! @param selector eql_v3.real_eq +--! @return eql_v3.real_eq +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.real_eq) +RETURNS eql_v3.real_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.real_eq, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.real_eq, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a jsonb +--! @param selector eql_v3.real_eq +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.real_eq) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.real_eq, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.real_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.real_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.real_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.real_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.real_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.real_eq, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.real_eq, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.real_eq, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.real_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.real_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b eql_v3.real_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.real_eq, b eql_v3.real_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a eql_v3.real_eq +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.real_eq, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_eq. +--! @param a jsonb +--! @param b eql_v3.real_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.real_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.real_eq'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/real/real_ord_functions.sql +--! @brief Functions for eql_v3.real_ord. + +--! @brief Index extractor for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.real_ord) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.real_ord, b eql_v3.real_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.real_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.real_ord) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a jsonb +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.real_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.real_ord) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.real_ord, b eql_v3.real_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.real_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.real_ord) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a jsonb +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.real_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.real_ord) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.real_ord, b eql_v3.real_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.real_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.real_ord) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a jsonb +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.real_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.real_ord) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.real_ord, b eql_v3.real_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.real_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.real_ord) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a jsonb +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.real_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.real_ord) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.real_ord, b eql_v3.real_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.real_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.real_ord) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a jsonb +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.real_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.real_ord) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.real_ord, b eql_v3.real_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.real_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.real_ord) $$; + +--! @brief Operator wrapper for eql_v3.real_ord. +--! @param a jsonb +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.real_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.real_ord) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.real_ord, b eql_v3.real_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.real_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a jsonb +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.real_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.real_ord, b eql_v3.real_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.real_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a jsonb +--! @param b eql_v3.real_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.real_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param selector text +--! @return eql_v3.real_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.real_ord, selector text) +RETURNS eql_v3.real_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param selector integer +--! @return eql_v3.real_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.real_ord, selector integer) +RETURNS eql_v3.real_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a jsonb +--! @param selector eql_v3.real_ord +--! @return eql_v3.real_ord +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.real_ord) +RETURNS eql_v3.real_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.real_ord, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.real_ord, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a jsonb +--! @param selector eql_v3.real_ord +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.real_ord) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.real_ord, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.real_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.real_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.real_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.real_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.real_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.real_ord, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.real_ord, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.real_ord, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.real_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.real_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b eql_v3.real_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.real_ord, b eql_v3.real_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a eql_v3.real_ord +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.real_ord, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real_ord. +--! @param a jsonb +--! @param b eql_v3.real_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.real_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.real_ord'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/real/real_ord_ore_operators.sql +--! @brief Operators for eql_v3.real_ord_ore. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = eql_v3.real_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = eql_v3.real_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = eql_v3.real_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = eql_v3.real_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = eql_v3.real_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = eql_v3.real_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = eql_v3.real_ord_ore +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = eql_v3.real_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord_ore +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord_ore +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord_ore +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = eql_v3.real_ord_ore +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.real_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord_ore +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/real/real_ord_operators.sql +--! @brief Operators for eql_v3.real_ord. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.real_ord, RIGHTARG = eql_v3.real_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.real_ord, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.real_ord, RIGHTARG = eql_v3.real_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.real_ord, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.real_ord, RIGHTARG = eql_v3.real_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.real_ord, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.real_ord, RIGHTARG = eql_v3.real_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.real_ord, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.real_ord, RIGHTARG = eql_v3.real_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.real_ord, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.real_ord, RIGHTARG = eql_v3.real_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.real_ord, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.real_ord, RIGHTARG = eql_v3.real_ord +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.real_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.real_ord, RIGHTARG = eql_v3.real_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.real_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.real_ord, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.real_ord, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.real_ord, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.real_ord, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.real_ord, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.real_ord, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.real_ord, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.real_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.real_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.real_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.real_ord, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.real_ord, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.real_ord, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.real_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.real_ord, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.real_ord, RIGHTARG = eql_v3.real_ord +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.real_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.real_ord +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/timestamp/timestamp_ord_ore_functions.sql +--! @brief Functions for eql_v3.timestamp_ord_ore. + +--! @brief Index extractor for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.timestamp_ord_ore) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.timestamp_ord_ore, b eql_v3.timestamp_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.timestamp_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.timestamp_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.timestamp_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.timestamp_ord_ore) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.timestamp_ord_ore, b eql_v3.timestamp_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.timestamp_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.timestamp_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.timestamp_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.timestamp_ord_ore) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.timestamp_ord_ore, b eql_v3.timestamp_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.timestamp_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.timestamp_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.timestamp_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.timestamp_ord_ore) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.timestamp_ord_ore, b eql_v3.timestamp_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.timestamp_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.timestamp_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.timestamp_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.timestamp_ord_ore) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.timestamp_ord_ore, b eql_v3.timestamp_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.timestamp_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.timestamp_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.timestamp_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.timestamp_ord_ore) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.timestamp_ord_ore, b eql_v3.timestamp_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.timestamp_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.timestamp_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord_ore. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.timestamp_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.timestamp_ord_ore) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.timestamp_ord_ore, b eql_v3.timestamp_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.timestamp_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.timestamp_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.timestamp_ord_ore, b eql_v3.timestamp_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.timestamp_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.timestamp_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param selector text +--! @return eql_v3.timestamp_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.timestamp_ord_ore, selector text) +RETURNS eql_v3.timestamp_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param selector integer +--! @return eql_v3.timestamp_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.timestamp_ord_ore, selector integer) +RETURNS eql_v3.timestamp_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.timestamp_ord_ore +--! @return eql_v3.timestamp_ord_ore +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.timestamp_ord_ore) +RETURNS eql_v3.timestamp_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.timestamp_ord_ore, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.timestamp_ord_ore, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.timestamp_ord_ore +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.timestamp_ord_ore) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.timestamp_ord_ore, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.timestamp_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.timestamp_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.timestamp_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.timestamp_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.timestamp_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.timestamp_ord_ore, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.timestamp_ord_ore, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.timestamp_ord_ore, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.timestamp_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.timestamp_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b eql_v3.timestamp_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.timestamp_ord_ore, b eql_v3.timestamp_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a eql_v3.timestamp_ord_ore +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.timestamp_ord_ore, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord_ore. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.timestamp_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.timestamp_ord_ore'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/timestamp/timestamp_ord_functions.sql +--! @brief Functions for eql_v3.timestamp_ord. + +--! @brief Index extractor for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.timestamp_ord) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.timestamp_ord, b eql_v3.timestamp_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.timestamp_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.timestamp_ord) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.timestamp_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.timestamp_ord) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.timestamp_ord, b eql_v3.timestamp_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.timestamp_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.timestamp_ord) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.timestamp_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.timestamp_ord) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.timestamp_ord, b eql_v3.timestamp_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.timestamp_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.timestamp_ord) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.timestamp_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.timestamp_ord) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.timestamp_ord, b eql_v3.timestamp_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.timestamp_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.timestamp_ord) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.timestamp_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.timestamp_ord) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.timestamp_ord, b eql_v3.timestamp_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.timestamp_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.timestamp_ord) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.timestamp_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.timestamp_ord) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.timestamp_ord, b eql_v3.timestamp_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.timestamp_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.timestamp_ord) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_ord. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.timestamp_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.timestamp_ord) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.timestamp_ord, b eql_v3.timestamp_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.timestamp_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.timestamp_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.timestamp_ord, b eql_v3.timestamp_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.timestamp_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.timestamp_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param selector text +--! @return eql_v3.timestamp_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.timestamp_ord, selector text) +RETURNS eql_v3.timestamp_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param selector integer +--! @return eql_v3.timestamp_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.timestamp_ord, selector integer) +RETURNS eql_v3.timestamp_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a jsonb +--! @param selector eql_v3.timestamp_ord +--! @return eql_v3.timestamp_ord +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.timestamp_ord) +RETURNS eql_v3.timestamp_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.timestamp_ord, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.timestamp_ord, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a jsonb +--! @param selector eql_v3.timestamp_ord +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.timestamp_ord) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.timestamp_ord, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.timestamp_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.timestamp_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.timestamp_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.timestamp_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.timestamp_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.timestamp_ord, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.timestamp_ord, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.timestamp_ord, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.timestamp_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.timestamp_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b eql_v3.timestamp_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.timestamp_ord, b eql_v3.timestamp_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a eql_v3.timestamp_ord +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.timestamp_ord, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_ord. +--! @param a jsonb +--! @param b eql_v3.timestamp_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.timestamp_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.timestamp_ord'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/timestamp/timestamp_ord_operators.sql +--! @brief Operators for eql_v3.timestamp_ord. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = eql_v3.timestamp_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = eql_v3.timestamp_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = eql_v3.timestamp_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = eql_v3.timestamp_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = eql_v3.timestamp_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = eql_v3.timestamp_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = eql_v3.timestamp_ord +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = eql_v3.timestamp_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = eql_v3.timestamp_ord +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.timestamp_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/timestamp/timestamp_eq_functions.sql +--! @brief Functions for eql_v3.timestamp_eq. + +--! @brief Index extractor for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.timestamp_eq) +RETURNS eql_v3.hmac_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.hmac_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.timestamp_eq, b eql_v3.timestamp_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.timestamp_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.timestamp_eq) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_eq. +--! @param a jsonb +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.timestamp_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.timestamp_eq) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.timestamp_eq, b eql_v3.timestamp_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.timestamp_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.timestamp_eq) $$; + +--! @brief Operator wrapper for eql_v3.timestamp_eq. +--! @param a jsonb +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.timestamp_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.timestamp_eq) <> eql_v3.eq_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.timestamp_eq, b eql_v3.timestamp_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.timestamp_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a jsonb +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.timestamp_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.timestamp_eq, b eql_v3.timestamp_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.timestamp_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a jsonb +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.timestamp_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.timestamp_eq, b eql_v3.timestamp_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.timestamp_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a jsonb +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.timestamp_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.timestamp_eq, b eql_v3.timestamp_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.timestamp_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a jsonb +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.timestamp_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.timestamp_eq, b eql_v3.timestamp_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.timestamp_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a jsonb +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.timestamp_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.timestamp_eq, b eql_v3.timestamp_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.timestamp_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a jsonb +--! @param b eql_v3.timestamp_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.timestamp_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param selector text +--! @return eql_v3.timestamp_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.timestamp_eq, selector text) +RETURNS eql_v3.timestamp_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param selector integer +--! @return eql_v3.timestamp_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.timestamp_eq, selector integer) +RETURNS eql_v3.timestamp_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a jsonb +--! @param selector eql_v3.timestamp_eq +--! @return eql_v3.timestamp_eq +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.timestamp_eq) +RETURNS eql_v3.timestamp_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.timestamp_eq, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.timestamp_eq, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a jsonb +--! @param selector eql_v3.timestamp_eq +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.timestamp_eq) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.timestamp_eq, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.timestamp_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.timestamp_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.timestamp_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.timestamp_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.timestamp_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.timestamp_eq, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.timestamp_eq, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.timestamp_eq, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.timestamp_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.timestamp_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b eql_v3.timestamp_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.timestamp_eq, b eql_v3.timestamp_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a eql_v3.timestamp_eq +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.timestamp_eq, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp_eq. +--! @param a jsonb +--! @param b eql_v3.timestamp_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.timestamp_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.timestamp_eq'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/timestamp/timestamp_ord_ore_operators.sql +--! @brief Operators for eql_v3.timestamp_ord_ore. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = eql_v3.timestamp_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = eql_v3.timestamp_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = eql_v3.timestamp_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = eql_v3.timestamp_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = eql_v3.timestamp_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = eql_v3.timestamp_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = eql_v3.timestamp_ord_ore +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = eql_v3.timestamp_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord_ore +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord_ore +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord_ore +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = eql_v3.timestamp_ord_ore +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.timestamp_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_ord_ore +); + +--! @file v3/sem/ore_cllw/types.sql +--! @brief CLLW ORE index term type for STE-vec range queries (eql_v3 SEM) +--! +--! Composite type for CLLW (Copyless Logarithmic Width) Order-Revealing +--! Encryption. The ciphertext is stored in the `oc` field of encrypted data +--! payloads (Standard-mode `ste_vec` elements). Used by the range operators +--! (`<`, `<=`, `>`, `>=`) when an sv element carries an `oc` term. +--! +--! The wire-format `oc` value is a hex string with a leading domain-tag byte +--! (`0x00` numeric, `0x01` string) followed by the CLLW ciphertext. The +--! decoded `bytes` field carries the full byte string including the tag — the +--! comparator is variable-length capable, so numeric and string values within +--! the same column order correctly: the domain tag separates the ranges +--! (numeric < string) and the within-domain comparison falls through to the +--! CLLW per-byte protocol. +--! +--! @note This is a transient type used only during query execution. +--! @see eql_v3.compare_ore_cllw_term +CREATE TYPE eql_v3.ore_cllw AS ( + bytes bytea +); + +--! @file v3/sem/ore_cllw/functions.sql +--! @brief CLLW ORE index-term extraction and comparison (eql_v3 SEM). + +--! @brief Extract CLLW ORE index term from raw jsonb +--! +--! Returns the CLLW ORE ciphertext from the `oc` field of a single sv element +--! supplied as raw jsonb. Inlinable single-statement SQL — the planner folds +--! the body into the calling query. +--! +--! **Missing-`oc` semantics**: returns SQL-level NULL (not a composite with +--! NULL bytes) when `oc` is absent, so btree's NULL handling filters those +--! rows from range queries. +--! +--! @param val jsonb An object carrying an `oc` field +--! @return eql_v3.ore_cllw Composite carrying the CLLW ciphertext, or NULL +--! when the `oc` field is absent. +--! @see eql_v3.has_ore_cllw +--! @see eql_v3.compare_ore_cllw_term +CREATE FUNCTION eql_v3.ore_cllw(val jsonb) + RETURNS eql_v3.ore_cllw + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT CASE WHEN val ->> 'oc' IS NULL THEN NULL + ELSE ROW(decode(val ->> 'oc', 'hex'))::eql_v3.ore_cllw + END +$$; + +COMMENT ON FUNCTION eql_v3.ore_cllw(jsonb) IS + 'eql-inline-critical: raw-jsonb CLLW extractor; must stay inlinable (unpinned search_path)'; + +--! @brief Check if a raw jsonb value contains a CLLW ORE index term +--! @param val jsonb An object that may carry an `oc` field +--! @return boolean True if `oc` field is present and non-null +CREATE FUNCTION eql_v3.has_ore_cllw(val jsonb) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT val ->> 'oc' IS NOT NULL +$$; + +COMMENT ON FUNCTION eql_v3.has_ore_cllw(jsonb) IS + 'eql-inline-critical: raw-jsonb CLLW presence helper; must stay inlinable (unpinned search_path)'; + +--! @brief CLLW per-byte comparison helper +--! @internal +--! +--! Byte-by-byte comparison implementing the CLLW order-revealing protocol. +--! Identify the index of the first differing byte; if `(y_byte + 1) == x_byte` +--! (mod 256) there, then x > y; otherwise x < y. Equal inputs return 0. Inputs +--! MUST be the same length (the caller guarantees this). Stays `LANGUAGE +--! plpgsql` — the per-byte loop can't be a single inlinable SQL expression. +--! +--! @param a bytea First CLLW ciphertext slice +--! @param b bytea Second CLLW ciphertext slice +--! @return integer -1, 0, or 1 +--! @throws Exception if inputs are different lengths +--! @see eql_v3.compare_ore_cllw_term +CREATE FUNCTION eql_v3.compare_ore_cllw_term_bytes(a bytea, b bytea) +RETURNS int + SET search_path = pg_catalog, extensions, public +AS $$ +DECLARE + len_a INT; + len_b INT; + i INT; + first_diff INT := 0; +BEGIN + + len_a := LENGTH(a); + len_b := LENGTH(b); + + IF len_a != len_b THEN + RAISE EXCEPTION 'ore_cllw index terms are not the same length'; + END IF; + + FOR i IN 1..len_a LOOP + IF first_diff = 0 AND get_byte(a, i - 1) != get_byte(b, i - 1) THEN + first_diff := i; + END IF; + END LOOP; + + IF first_diff = 0 THEN + RETURN 0; + END IF; + + IF ((get_byte(b, first_diff - 1) + 1) & 255) = get_byte(a, first_diff - 1) THEN + RETURN 1; + ELSE + RETURN -1; + END IF; +END; +$$ LANGUAGE plpgsql; + +--! @brief Variable-length CLLW ORE term comparison +--! @internal +--! +--! Three-way comparison of two CLLW ORE ciphertext terms of potentially +--! different lengths. Compares the shared prefix via the CLLW per-byte +--! protocol; on equal prefixes, the shorter input sorts first. The leading +--! domain-tag byte makes numeric (`0x00`) sort before string (`0x01`). Stays +--! `LANGUAGE plpgsql` because it dispatches to `compare_ore_cllw_term_bytes`. +--! +--! btree filters NULL composites at the row level, so this should never see a +--! NULL composite under normal operation; the IS-NULL guard returns NULL +--! defensively. A non-NULL composite with NULL `bytes` is a contract violation +--! — the extractor returns SQL NULL (not ROW(NULL)) on missing `oc`, so raise +--! loudly rather than silently misorder. +--! +--! @param a eql_v3.ore_cllw First term +--! @param b eql_v3.ore_cllw Second term +--! @return integer -1, 0, or 1; NULL if either composite is NULL +--! @throws Exception if either composite has a NULL `bytes` field +--! @see eql_v3.compare_ore_cllw_term_bytes +CREATE FUNCTION eql_v3.compare_ore_cllw_term(a eql_v3.ore_cllw, b eql_v3.ore_cllw) +RETURNS int + SET search_path = pg_catalog, extensions, public +AS $$ +DECLARE + len_a INT; + len_b INT; + common_len INT; + cmp_result INT; +BEGIN + -- The `::text` cast is load-bearing, not a stylistic choice. For the + -- single-field `ore_cllw` composite, `ROW(NULL)::ore_cllw IS NULL` is TRUE + -- but `(ROW(NULL)::ore_cllw)::text IS NULL` is FALSE. Casting to text first + -- means a NULL-component composite falls THROUGH to the RAISE below (the + -- extractor-invariant violation) instead of silently returning NULL and + -- masking it. A plain `a IS NULL` would reintroduce that masking bug. + IF a::text IS NULL OR b::text IS NULL THEN + RETURN NULL; + END IF; + + IF a.bytes IS NULL OR b.bytes IS NULL THEN + RAISE EXCEPTION 'eql_v3.compare_ore_cllw_term: composite has NULL bytes field — extractor invariant violated. Check that the index expression uses eql_v3.ore_cllw(...) and not a hand-crafted ROW(NULL).'; + END IF; + + len_a := LENGTH(a.bytes); + len_b := LENGTH(b.bytes); + + IF len_a = 0 AND len_b = 0 THEN + RETURN 0; + ELSIF len_a = 0 THEN + RETURN -1; + ELSIF len_b = 0 THEN + RETURN 1; + END IF; + + IF len_a < len_b THEN + common_len := len_a; + ELSE + common_len := len_b; + END IF; + + cmp_result := eql_v3.compare_ore_cllw_term_bytes( + SUBSTRING(a.bytes FROM 1 FOR common_len), + SUBSTRING(b.bytes FROM 1 FOR common_len) + ); + + IF cmp_result = -1 THEN + RETURN -1; + ELSIF cmp_result = 1 THEN + RETURN 1; + END IF; + + IF len_a < len_b THEN + RETURN -1; + ELSIF len_a > len_b THEN + RETURN 1; + ELSE + RETURN 0; + END IF; +END; +$$ LANGUAGE plpgsql; + +--! @file v3/jsonb/types.sql +--! @brief Domain types for the eql_v3 encrypted-JSONB (SteVec) surface. +--! +--! Three jsonb-backed domains (none over another domain — operators resolve +--! against the ultimate base type jsonb, so the native-jsonb firewall in +--! blockers.sql can attach): +--! - eql_v3.json — storage/root: an EQL envelope object ({i, v, ...}). +--! - eql_v3.jsonb_entry — a single sv element (returned by `->`). +--! - eql_v3.jsonb_query — a containment needle (sv elements, no ciphertext). + +--! @brief Validate a single SteVec entry payload. +--! @internal +--! @param val jsonb Candidate entry payload. +--! @return boolean True when `val` is an sv entry with string `s`, string `c`, +--! and exactly one string deterministic term (`hm` XOR `oc`). +CREATE FUNCTION eql_v3.is_valid_ste_vec_entry_payload(val jsonb) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT COALESCE( + jsonb_typeof(val) = 'object' + AND jsonb_typeof(val -> 's') = 'string' + AND jsonb_typeof(val -> 'c') = 'string' + AND ( + (jsonb_typeof(val -> 'hm') = 'string' AND NOT (val ? 'oc')) + OR + (jsonb_typeof(val -> 'oc') = 'string' AND NOT (val ? 'hm')) + ), + false + ) +$$; + +--! @brief Validate a SteVec containment query payload. +--! @internal +--! @param val jsonb Candidate query payload. +--! @return boolean True when `val` is `{"sv":[...]}` and every element carries +--! string `s`, no ciphertext, and exactly one string term (`hm` XOR +--! `oc`). +CREATE FUNCTION eql_v3.is_valid_ste_vec_query_payload(val jsonb) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT COALESCE( + jsonb_typeof(val) = 'object' + AND jsonb_typeof(val -> 'sv') = 'array' + AND NOT EXISTS ( + SELECT 1 + FROM jsonb_array_elements( + CASE WHEN jsonb_typeof(val -> 'sv') = 'array' THEN val -> 'sv' ELSE '[]'::jsonb END + ) AS elem + WHERE NOT COALESCE(( + jsonb_typeof(elem) = 'object' + AND jsonb_typeof(elem -> 's') = 'string' + AND NOT (elem ? 'c') + AND ( + (jsonb_typeof(elem -> 'hm') = 'string' AND NOT (elem ? 'oc')) + OR + (jsonb_typeof(elem -> 'oc') = 'string' AND NOT (elem ? 'hm')) + ) + ), false) + ), + false + ) +$$; + +--! @brief Validate a root SteVec document payload. +--! @internal +--! @param val jsonb Candidate document payload. +--! @return boolean True when `val` is an encrypted document envelope with +--! `v = 2`, `i`, an `sv` array, and valid sv entry elements. +CREATE FUNCTION eql_v3.is_valid_ste_vec_document_payload(val jsonb) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT COALESCE( + jsonb_typeof(val) = 'object' + AND val ? 'v' + AND val ->> 'v' = '2' + AND val ? 'i' + AND jsonb_typeof(val -> 'sv') = 'array' + AND NOT EXISTS ( + SELECT 1 + FROM jsonb_array_elements( + CASE WHEN jsonb_typeof(val -> 'sv') = 'array' THEN val -> 'sv' ELSE '[]'::jsonb END + ) AS elem + WHERE NOT eql_v3.is_valid_ste_vec_entry_payload(elem) + ), + false + ) +$$; + +--! @brief Storage/root domain for an encrypted JSONB column. +--! +--! CHECK: a JSON object carrying the EQL envelope (`v = 2` version and `i` index +--! metadata). Root `c` is intentionally NOT required — an sv-array root payload +--! is `{i, v, sv}` with no root ciphertext. The CHECK now also requires an `sv` +--! array, so the domain accepts only SteVec **document** payloads and rejects +--! encrypted *scalar* payloads (which carry `c`/`hm`/`ob` but no `sv`) — this is +--! what keeps `eql_v3.json` a typed document domain rather than a generic +--! encrypted envelope. The firewall in blockers.sql attaches to this domain to +--! stop native jsonb operators from reaching a column value. +--! +--! @note Constructing from inline JSON uses the standard DOMAIN cast: +--! `'{"i":{},"v":2,"sv":[...]}'::eql_v3.json`. +CREATE DOMAIN eql_v3.json AS jsonb + CHECK ( + eql_v3.is_valid_ste_vec_document_payload(VALUE) + ); + +--! @brief Domain type for an individual sv element. +--! +--! A single element inside an `sv` array: a JSON object that carries a selector +--! (`s`), a ciphertext (`c`), and **exactly one** of `hm` (HMAC-256, for +--! hash-equality) or `oc` (CLLW ORE, for ordered queries) — they are mutually +--! exclusive. This is the type returned by `->` and accepted by the per-entry +--! extractors `eql_v3.eq_term` / `eql_v3.ore_cllw`. Extra fields (`a`, root +--! `i`/`v` merged in by `->`) are allowed. +--! +--! @see src/v3/jsonb/operators.sql +CREATE DOMAIN eql_v3.jsonb_entry AS jsonb + CHECK ( + eql_v3.is_valid_ste_vec_entry_payload(VALUE) + ); + +--! @brief Domain type for an STE-vec containment needle. +--! +--! A query-shaped payload `{"sv":[...]}` whose elements carry selector + index +--! term but **never** a ciphertext (`c`). Each element must carry `s` and +--! exactly one deterministic term (`hm` XOR `oc`). Typing the needle this way +--! stops selector-only needles from casting and matching every row via bare +--! `jsonb @>`. +--! +--! @note Construct from inline JSON via the DOMAIN cast: +--! `'{"sv":[{"s":"<sel>","hm":"<hm>"}]}'::eql_v3.jsonb_query`. +--! @see eql_v3.to_ste_vec_query +CREATE DOMAIN eql_v3.jsonb_query AS jsonb + CHECK ( + eql_v3.is_valid_ste_vec_query_payload(VALUE) + ); + +--! @brief Convert an eql_v3.json to a jsonb_query needle. +--! +--! Normalises each sv element down to the matching-relevant fields: `s` plus +--! exactly one of `hm` / `oc`. Other fields (`c`, `a`, `i`/`v`, anything else) +--! are stripped. This is the canonical needle shape for `@>` containment. +--! Designed for use as a functional GIN index expression: +--! `GIN (eql_v3.to_ste_vec_query(col)::jsonb jsonb_path_ops)`. +--! +--! @param e eql_v3.json Source encrypted payload +--! @return eql_v3.jsonb_query Query-shaped needle, sv elements normalised. +--! @see eql_v3.jsonb_query +CREATE FUNCTION eql_v3.to_ste_vec_query(e eql_v3.json) + RETURNS eql_v3.jsonb_query + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT jsonb_build_object( + 'sv', + coalesce( + (SELECT jsonb_agg( + jsonb_strip_nulls( + jsonb_build_object( + 's', elem -> 's', + 'hm', elem -> 'hm', + 'oc', elem -> 'oc' + ) + ) + ) + FROM jsonb_array_elements(e::jsonb -> 'sv') AS elem), + '[]'::jsonb + ) + )::eql_v3.jsonb_query +$$; + +CREATE CAST (eql_v3.json AS eql_v3.jsonb_query) + WITH FUNCTION eql_v3.to_ste_vec_query + AS ASSIGNMENT; + +--! @file v3/jsonb/functions.sql +--! @brief Extractors, containment engine, and path/array functions for the +--! eql_v3 encrypted-JSONB (SteVec) surface. +--! +--! `selector` parameters here are *encrypted-side* selector hashes — the +--! deterministic hash the crypto layer emits in the `s` field of each sv +--! element. Plaintext JSONPaths are never accepted at runtime. + +------------------------------------------------------------------------------ +-- Envelope helpers (eql_v3 owns these; jsonb-only) +------------------------------------------------------------------------------ + +--! @brief Extract metadata (i, v) from a raw jsonb encrypted value. +--! @param val jsonb encrypted EQL payload +--! @return jsonb Metadata object with `i` and `v` fields. +CREATE FUNCTION eql_v3.meta_data(val jsonb) + RETURNS jsonb + IMMUTABLE STRICT PARALLEL SAFE + LANGUAGE SQL +AS $$ + SELECT jsonb_build_object('i', val->'i', 'v', val->'v'); +$$; + +COMMENT ON FUNCTION eql_v3.meta_data(jsonb) IS + 'eql-inline-critical: raw-jsonb envelope helper used by v3 jsonb wrappers; must stay inlinable (unpinned search_path)'; + +--! @brief Extract ciphertext (c) from a raw jsonb encrypted value. +--! @param val jsonb encrypted EQL payload +--! @return text Base64-encoded ciphertext. +--! @throws Exception if `c` is absent. +CREATE FUNCTION eql_v3.ciphertext(val jsonb) + RETURNS text + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + BEGIN + IF val ? 'c' THEN + RETURN val->>'c'; + END IF; + RAISE 'Expected a ciphertext (c) value in json: %', val; + END; +$$ LANGUAGE plpgsql; + +------------------------------------------------------------------------------ +-- Selector extractors +------------------------------------------------------------------------------ + +--! @brief Extract selector (s) from a raw jsonb encrypted value. +--! @param val jsonb encrypted EQL payload +--! @return text The selector value. +--! @throws Exception if `s` is absent. +CREATE FUNCTION eql_v3.selector(val jsonb) + RETURNS text + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + BEGIN + IF val ? 's' THEN + RETURN val->>'s'; + END IF; + RAISE 'Expected a selector index (s) value in json: %', val; + END; +$$ LANGUAGE plpgsql; + +--! @brief Extract selector (s) from a ste_vec entry. The DOMAIN CHECK +--! guarantees `s` is present, so this is a simple field access. +--! @param entry eql_v3.jsonb_entry +--! @return text The selector value. +CREATE FUNCTION eql_v3.selector(entry eql_v3.jsonb_entry) + RETURNS text + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT entry ->> 's' +$$; + +------------------------------------------------------------------------------ +-- Equality-term extractor (XOR-aware: coalesce(hm, oc)) +------------------------------------------------------------------------------ + +--! @brief XOR-aware equality term extractor for eql_v3.jsonb_entry. +--! +--! Returns the bytea of whichever deterministic term the sv entry carries — +--! `hm` (HMAC-256) or `oc` (CLLW ORE). The two byte distributions are disjoint +--! by construction, so byte equality on the coalesce is unambiguous. Canonical +--! equality extractor used by `=` / `<>` on jsonb_entry. +--! +--! @param entry eql_v3.jsonb_entry +--! @return bytea Decoded `hm` or `oc` bytes (NULL if entry is NULL). +CREATE FUNCTION eql_v3.eq_term(entry eql_v3.jsonb_entry) + RETURNS bytea + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT decode(coalesce(entry ->> 'hm', entry ->> 'oc'), 'hex') +$$; + +------------------------------------------------------------------------------ +-- ORE CLLW per-entry overloads (live here so sem/ore_cllw stays a leaf) +------------------------------------------------------------------------------ + +--! @brief Extract CLLW ORE index term from a ste_vec entry. +--! +--! `oc` is only ever present on an sv element, never at a root encrypted value, +--! so the typed overload accepts eql_v3.jsonb_entry. Returns SQL NULL when +--! `oc` is absent (btree NULL-filters such rows from range queries). +--! +--! @param entry eql_v3.jsonb_entry +--! @return eql_v3.ore_cllw Composite carrying the CLLW ciphertext, or NULL. +--! @see eql_v3.has_ore_cllw +CREATE FUNCTION eql_v3.ore_cllw(entry eql_v3.jsonb_entry) + RETURNS eql_v3.ore_cllw + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT CASE WHEN entry ->> 'oc' IS NULL THEN NULL + ELSE ROW(decode(entry ->> 'oc', 'hex'))::eql_v3.ore_cllw + END +$$; + +--! @brief Check if a ste_vec entry contains a CLLW ORE index term. +--! @param entry eql_v3.jsonb_entry +--! @return boolean True if `oc` is present and non-null. +CREATE FUNCTION eql_v3.has_ore_cllw(entry eql_v3.jsonb_entry) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT entry ->> 'oc' IS NOT NULL +$$; + +------------------------------------------------------------------------------ +-- sv-array helpers +------------------------------------------------------------------------------ + +--! @brief Extract the sv element array as raw jsonb[]. +--! +--! Returns the elements of `sv` (or a single-element array wrapping the value +--! when there is no `sv`). No envelope re-wrapping — raw jsonb elements. +--! +--! @param val jsonb encrypted EQL payload +--! @return jsonb[] Array of sv elements. +CREATE FUNCTION eql_v3.ste_vec(val jsonb) + RETURNS jsonb[] + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + DECLARE + sv jsonb; + ary jsonb[]; + BEGIN + IF val ? 'sv' THEN + sv := val->'sv'; + ELSE + sv := jsonb_build_array(val); + END IF; + + SELECT array_agg(elem) + INTO ary + FROM jsonb_array_elements(sv) AS elem; + + RETURN ary; + END; +$$ LANGUAGE plpgsql; + +--! @brief Check if a jsonb payload is marked as an sv array (`a` flag true). +--! @param val jsonb encrypted EQL payload +--! @return boolean True if `a` is present and true. +CREATE FUNCTION eql_v3.is_ste_vec_array(val jsonb) + RETURNS boolean + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + BEGIN + IF val ? 'a' THEN + RETURN (val->>'a')::boolean; + END IF; + RETURN false; + END; +$$ LANGUAGE plpgsql; + +------------------------------------------------------------------------------ +-- Deterministic-fields array for GIN containment +------------------------------------------------------------------------------ + +--! @brief Extract deterministic search fields (s, hm, oc, op) per sv element. +--! +--! Excludes non-deterministic ciphertext so PostgreSQL's native jsonb `@>` can +--! compare for containment. Use for GIN indexes and containment queries. +--! +--! @param val jsonb encrypted EQL payload +--! @return jsonb[] Array of objects with only deterministic fields. +CREATE FUNCTION eql_v3.jsonb_array(val jsonb) +RETURNS jsonb[] +IMMUTABLE STRICT PARALLEL SAFE +LANGUAGE SQL +AS $$ + SELECT ARRAY( + SELECT jsonb_object_agg(kv.key, kv.value) + FROM jsonb_array_elements( + CASE WHEN val ? 'sv' THEN val->'sv' ELSE jsonb_build_array(val) END + ) AS elem, + LATERAL jsonb_each(elem) AS kv(key, value) + WHERE kv.key IN ('s', 'hm', 'oc', 'op') + GROUP BY elem + ); +$$; + +COMMENT ON FUNCTION eql_v3.jsonb_array(jsonb) IS + 'eql-inline-critical: raw-jsonb deterministic-field array helper; must stay inlinable (unpinned search_path)'; + +------------------------------------------------------------------------------ +-- Containment +------------------------------------------------------------------------------ + +--! @brief GIN-indexable containment check: does `a` contain all of `b`? +--! @param a jsonb Container payload. +--! @param b jsonb Search payload. +--! @return boolean True if a contains all deterministic elements of b. +--! @note Convenience helper for hand-rolled GIN index expressions over the +--! raw extracted `jsonb[]` array (see database-indexes.md). The typed +--! `eql_v3.json` `@>`/`<@` operators do NOT call this function — they +--! bind to `eql_v3.ste_vec_contains` instead. Public API, reachable +--! only from caller-authored SQL. +CREATE FUNCTION eql_v3.jsonb_contains(a jsonb, b jsonb) +RETURNS boolean +IMMUTABLE STRICT PARALLEL SAFE +LANGUAGE SQL +AS $$ + SELECT eql_v3.jsonb_array(a) @> eql_v3.jsonb_array(b); +$$; + +COMMENT ON FUNCTION eql_v3.jsonb_contains(jsonb, jsonb) IS + 'eql-inline-critical: raw-jsonb containment helper; must stay inlinable (unpinned search_path)'; + +--! @brief GIN-indexable "is contained by" check. +--! @param a jsonb Payload to check. +--! @param b jsonb Container payload. +--! @return boolean True if all elements of a are contained in b. +--! @note Convenience helper for hand-rolled GIN index expressions over the +--! raw extracted `jsonb[]` array (see database-indexes.md). The typed +--! `eql_v3.json` `@>`/`<@` operators do NOT call this function — they +--! bind to `eql_v3.ste_vec_contains` instead. Public API, reachable +--! only from caller-authored SQL. +CREATE FUNCTION eql_v3.jsonb_contained_by(a jsonb, b jsonb) +RETURNS boolean +IMMUTABLE STRICT PARALLEL SAFE +LANGUAGE SQL +AS $$ + SELECT eql_v3.jsonb_array(a) <@ eql_v3.jsonb_array(b); +$$; + +COMMENT ON FUNCTION eql_v3.jsonb_contained_by(jsonb, jsonb) IS + 'eql-inline-critical: raw-jsonb contained-by helper; must stay inlinable (unpinned search_path)'; + +--! @brief Check if an sv array contains a specific sv element. +--! +--! Match = selector equal AND eq_term equal (byte-equality over coalesce(hm, +--! oc)). This collapses the v2 hm/oc CASE: under the XOR contract both terms +--! are deterministic and byte-disjoint, so either one is a valid equality +--! discriminator and a single byte comparison is correct. +--! +--! ASSUMPTION (locked by a negative test in v3_jsonb_tests.rs): hm and oc byte +--! distributions never collide at a given selector. The crypto layer configures +--! a selector for eq XOR ordered, so both sides of a real comparison carry the +--! same term type; and an oc value carries a leading domain-tag byte an hm never +--! has. Unlike v2's explicit `has_hmac(both)`/`has_ore_cllw(both)`/`ELSE false` +--! CASE, this collapse would wrongly match an hm needle against an oc leaf if +--! their hex bytes were ever identical — which the contract prevents. The +--! negative-containment test guards against regression. +--! +--! @param a jsonb[] sv array to search within. +--! @param b jsonb sv element to search for. +--! @return boolean True if b is found in any element of a. +CREATE FUNCTION eql_v3.ste_vec_contains(a jsonb[], b jsonb) + RETURNS boolean + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + DECLARE + result boolean; + _a jsonb; + BEGIN + result := false; + + FOR idx IN 1..array_length(a, 1) LOOP + _a := a[idx]; + result := result OR ( + eql_v3.selector(_a) = eql_v3.selector(b) + AND eql_v3.eq_term(_a::eql_v3.jsonb_entry) = eql_v3.eq_term(b::eql_v3.jsonb_entry) + ); + EXIT WHEN result; + END LOOP; + + RETURN result; + END; +$$ LANGUAGE plpgsql; + +--! @brief Does encrypted value `a` contain all sv elements of `b`? +--! +--! Empty b is always contained. Each element of b must match selector + eq_term +--! in some element of a. +--! +--! @param a eql_v3.json Container. +--! @param b eql_v3.json Elements to find. +--! @return boolean True if all elements of b are contained in a. +--! @see eql_v3.ste_vec_contains(jsonb[], jsonb) +CREATE FUNCTION eql_v3.ste_vec_contains(a eql_v3.json, b eql_v3.json) + RETURNS boolean + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + DECLARE + result boolean; + sv_a jsonb[]; + sv_b jsonb[]; + _b jsonb; + BEGIN + sv_a := eql_v3.ste_vec(a); + sv_b := eql_v3.ste_vec(b); + + IF array_length(sv_b, 1) IS NULL THEN + RETURN true; + END IF; + + IF array_length(sv_a, 1) IS NULL THEN + RETURN false; + END IF; + + result := true; + + FOR idx IN 1..array_length(sv_b, 1) LOOP + _b := sv_b[idx]; + result := result AND eql_v3.ste_vec_contains(sv_a, _b); + END LOOP; + + RETURN result; + END; +$$ LANGUAGE plpgsql; + +------------------------------------------------------------------------------ +-- Path queries (text selector only) +------------------------------------------------------------------------------ + +--! @brief Query encrypted JSONB for sv elements matching `selector`. +--! +--! Returns one jsonb_entry row per matching encrypted element. Returns empty +--! set on no match. It deliberately does not wrap multiple matches as an +--! eql_v3.json document, because the root document domain requires an `sv` +--! array and single leaves belong to eql_v3.jsonb_entry. +--! +--! @param val jsonb encrypted EQL payload with `sv`. +--! @param selector text Selector hash (`s` value). +--! @return SETOF eql_v3.jsonb_entry Matching encrypted entries. +--! @see eql_v3.jsonb_path_query_first +CREATE FUNCTION eql_v3.jsonb_path_query(val jsonb, selector text) + RETURNS SETOF eql_v3.jsonb_entry + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT (eql_v3.meta_data(val) || elem)::eql_v3.jsonb_entry + FROM jsonb_array_elements(val -> 'sv') elem + WHERE elem ->> 's' = selector +$$; + +COMMENT ON FUNCTION eql_v3.jsonb_path_query(jsonb, text) IS + 'eql-inline-critical: raw-jsonb path query helper; must stay inlinable (unpinned search_path)'; + +--! @brief Check if a selector path exists in encrypted JSONB. +--! @param val jsonb encrypted EQL payload. +--! @param selector text Selector hash to test. +--! @return boolean True if a matching element exists. +CREATE FUNCTION eql_v3.jsonb_path_exists(val jsonb, selector text) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT EXISTS ( + SELECT 1 FROM jsonb_array_elements(val -> 'sv') elem + WHERE elem ->> 's' = selector + ); +$$; + +COMMENT ON FUNCTION eql_v3.jsonb_path_exists(jsonb, text) IS + 'eql-inline-critical: raw-jsonb path exists helper; must stay inlinable (unpinned search_path)'; + +--! @brief Get the first sv element matching `selector`, or NULL. +--! @param val jsonb encrypted EQL payload. +--! @param selector text Selector hash to match. +--! @return eql_v3.jsonb_entry First matching element or NULL. +CREATE FUNCTION eql_v3.jsonb_path_query_first(val jsonb, selector text) + RETURNS eql_v3.jsonb_entry + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT (eql_v3.meta_data(val) || elem)::eql_v3.jsonb_entry + FROM jsonb_array_elements(val -> 'sv') elem + WHERE elem ->> 's' = selector + LIMIT 1 +$$; + +COMMENT ON FUNCTION eql_v3.jsonb_path_query_first(jsonb, text) IS + 'eql-inline-critical: raw-jsonb path first helper; must stay inlinable (unpinned search_path)'; + +------------------------------------------------------------------------------ +-- Array functions +------------------------------------------------------------------------------ + +--! @brief Get the length of an encrypted JSONB array. +--! @param val jsonb encrypted EQL payload (must have `a` flag true). +--! @return integer Number of elements. +--! @throws Exception 'cannot get array length of a non-array' if not an array. +CREATE FUNCTION eql_v3.jsonb_array_length(val jsonb) + RETURNS integer + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + DECLARE + sv jsonb[]; + BEGIN + IF eql_v3.is_ste_vec_array(val) THEN + sv := eql_v3.ste_vec(val); + RETURN array_length(sv, 1); + END IF; + + RAISE 'cannot get array length of a non-array'; + END; +$$ LANGUAGE plpgsql; + +--! @brief Extract elements of an encrypted JSONB array as rows. +--! @param val jsonb encrypted EQL payload (must have `a` flag true). +--! @return SETOF eql_v3.jsonb_entry One row per element (metadata preserved). +--! @throws Exception 'cannot extract elements from non-array' if not an array. +CREATE FUNCTION eql_v3.jsonb_array_elements(val jsonb) + RETURNS SETOF eql_v3.jsonb_entry + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + DECLARE + sv jsonb[]; + meta jsonb; + item jsonb; + BEGIN + IF NOT eql_v3.is_ste_vec_array(val) THEN + RAISE 'cannot extract elements from non-array'; + END IF; + + meta := eql_v3.meta_data(val); + sv := eql_v3.ste_vec(val); + + FOR idx IN 1..array_length(sv, 1) LOOP + item = sv[idx]; + RETURN NEXT (meta || item)::eql_v3.jsonb_entry; + END LOOP; + + RETURN; + END; +$$ LANGUAGE plpgsql; + +--! @brief Extract elements of an encrypted JSONB array as ciphertext text. +--! @param val jsonb encrypted EQL payload (must have `a` flag true). +--! @return SETOF text One ciphertext per element. +--! @throws Exception 'cannot extract elements from non-array' if not an array. +CREATE FUNCTION eql_v3.jsonb_array_elements_text(val jsonb) + RETURNS SETOF text + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + DECLARE + sv jsonb[]; + BEGIN + IF NOT eql_v3.is_ste_vec_array(val) THEN + RAISE 'cannot extract elements from non-array'; + END IF; + + sv := eql_v3.ste_vec(val); + + FOR idx IN 1..array_length(sv, 1) LOOP + RETURN NEXT eql_v3.ciphertext(sv[idx]); + END LOOP; + + RETURN; + END; +$$ LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE +-- Source is src/v3/version.template + +DROP FUNCTION IF EXISTS eql_v3.version(); + +--! @file v3/version.sql +--! @brief EQL version reporting (self-contained eql_v3 surface) +--! +--! This file is auto-generated from src/v3/version.template during build. +--! The DEV placeholder is replaced with the actual release +--! version (bare semver, e.g. "3.0.0") supplied via `mise run build --version`, +--! or "DEV" for development builds. + +--! @brief Get the installed EQL version string +--! +--! Returns the version string for the installed EQL library. This value is +--! baked in at build time from the release tag. +--! +--! @return text Version string (e.g. "3.0.0" or "DEV" for development builds) +--! +--! @note Auto-generated during build from src/v3/version.template +--! +--! @example +--! -- Check installed EQL version +--! SELECT eql_v3.version(); +--! -- Returns: '3.0.0' +CREATE FUNCTION eql_v3.version() + RETURNS text + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT 'DEV'; +$$ LANGUAGE SQL; + +--! @brief Schema-level version marker for obj_description() discoverability +--! +--! Mirrors eql_v3.version() as a comment on the schema so the installed +--! version can also be read via obj_description('eql_v3'::regnamespace). +COMMENT ON SCHEMA eql_v3 IS 'DEV'; + +--! @brief EQL lint: detect non-inlinable operator implementation functions +--! +--! Returns one row per violation found in the installed `eql_v3` surface. The +--! Postgres planner can only inline a function during index matching when: +--! +--! * `LANGUAGE sql` (plpgsql / C / etc. cannot be inlined) +--! * `IMMUTABLE` or `STABLE` volatility (VOLATILE cannot be inlined into +--! index expressions) +--! * No `SET` clauses (e.g. `SET search_path = ...`) +--! * Not `SECURITY DEFINER` +--! * Single-statement SELECT body +--! +--! @note The single-statement SELECT body condition is **not yet checked** by +--! this lint. A `LANGUAGE sql` function with a multi-statement body, a CTE, +--! or any pre-SELECT statement will pass all four implemented checks while +--! remaining non-inlinable. Implementing the check requires walking `prosrc` +--! (or `pg_get_functiondef`); tracked as a follow-up. +--! +--! Operators on `eql_v3` types (the jsonb-backed encrypted-domain families and +--! the SEM index-term types `eql_v3.ore_block_256`, `eql_v3.ore_cllw`) whose +--! implementation functions fail any of these rules silently fall back to seq +--! scan when the documented functional indexes (`eql_v3.eq_term(col)`, +--! `eql_v3.ord_term(col)`) are in place. This lint surfaces every such case. +--! +--! Severity: +--! `error` — fixable, blocks index matching, ship-blocking. +--! `warning` — likely-fixable, may not block matching but signals intent. +--! `info` — observational; useful for review, not a defect on its own. +--! +--! Categories: +--! `inlinability_language` — implementation function isn't `LANGUAGE sql`. +--! `inlinability_volatility` — implementation function is VOLATILE. +--! `inlinability_set_clause` — implementation function has a `SET` clause. +--! `inlinability_secdef` — implementation function is `SECURITY DEFINER`. +--! `inlinability_transitive` — implementation function is itself inlinable +--! but its body invokes a non-inlinable function +--! (depth 1; the planner can't peek through +--! that boundary). +--! `blocker_language` — encrypted-domain blocker is not LANGUAGE +--! plpgsql. The planner can inline / elide a +--! LANGUAGE sql body when the result is +--! provably unused, silently bypassing the +--! RAISE that the blocker exists to perform. +--! `blocker_strict` — encrypted-domain blocker is STRICT. +--! PostgreSQL skips the body and returns NULL +--! on NULL arguments, silently bypassing the +--! RAISE. +--! `domain_over_domain` — an `eql_v3` encrypted domain is derived from +--! another encrypted domain rather than jsonb. +--! Operators resolve against the ultimate base +--! type, so the derived domain does not +--! inherit the base domain's blocker surface. +--! `domain_opclass` — an operator class is declared FOR TYPE on an +--! `eql_v3` encrypted domain. Opclasses on +--! domains bypass operator resolution; use a +--! functional index on the extractor instead. +--! +--! @example +--! ``` +--! SELECT severity, category, object_name, message +--! FROM eql_v3.lints() +--! WHERE severity = 'error' +--! ORDER BY category, object_name; +--! ``` +--! +--! @return SETOF record (severity text, category text, object_name text, message text) +CREATE OR REPLACE FUNCTION eql_v3.lints() +RETURNS TABLE ( + severity text, + category text, + object_name text, + message text +) +LANGUAGE sql STABLE +AS $$ + WITH + -- All operators where at least one operand is an `eql_v3` type. Limits + -- the scope of the lint to the operator surface customers actually hit + -- via SQL (`col = val`, `col @> '...'` and friends). + eql_operators AS ( + SELECT + op.oid AS oprid, + op.oprname AS opname, + op.oprcode AS implfunc, + op.oprleft::regtype AS lhs, + op.oprright::regtype AS rhs, + op.oprcode::regprocedure AS impl_signature + FROM pg_operator op + WHERE EXISTS ( + SELECT 1 FROM pg_type t + WHERE t.oid IN (op.oprleft, op.oprright) + AND t.typnamespace = 'eql_v3'::regnamespace + ) + ), + + -- Cross-join with each operator's implementation function metadata. + -- One row per operator; columns describe the inlinability of the impl. + op_impl AS ( + SELECT + eo.opname, + eo.lhs, + eo.rhs, + eo.implfunc AS impl_oid, + eo.impl_signature::text AS impl_signature, + lang_l.lanname AS lang, + p.provolatile AS volatility, + p.proconfig AS config, + p.prosecdef AS secdef, + p.prosrc AS body + FROM eql_operators eo + JOIN pg_proc p ON p.oid = eo.implfunc + JOIN pg_language lang_l ON lang_l.oid = p.prolang + ), + + -- Encrypted-domain blockers: functions in `eql_v3` whose body contains + -- a blocker marker emitted by the codegen (any of the + -- `encrypted_domain_unsupported_*` helper calls — `_bool` for boolean + -- blockers, `_jsonb` for the native-jsonb-operator blockers; plus the + -- literal `is not supported for` for older path-operator blockers) AND + -- that take at least one `eql_v3` domain over jsonb argument. The argument + -- filter excludes the shared `encrypted_domain_unsupported_*(text, text)` + -- helpers themselves, which contain the marker in their body but are not + -- blockers (they take text arguments, not a domain). + encrypted_domain_blockers AS ( + SELECT + p.oid AS oid, + p.oid::regprocedure::text AS signature, + lang_l.lanname AS lang, + p.proisstrict AS isstrict + 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_v3' + AND (p.prosrc LIKE '%encrypted_domain_unsupported%' + OR p.prosrc LIKE '%is not supported for%') + AND EXISTS ( + SELECT 1 + FROM pg_catalog.unnest(p.proargtypes::oid[]) AS arg(typ) + JOIN pg_catalog.pg_type dt ON dt.oid = arg.typ + 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 bt.typname = 'jsonb' + AND dn.nspname = 'eql_v3' + ) + ) + + -- ┌─────────────────────────────────────────────────────────────────┐ + -- │ Direct inlinability checks: each row examines one operator's │ + -- │ implementation function and emits a violation if any rule is │ + -- │ broken. Multiple violations on the same function become │ + -- │ multiple rows (developers see every reason it doesn't inline). │ + -- └─────────────────────────────────────────────────────────────────┘ + + SELECT + 'error' AS severity, + 'inlinability_language' AS category, + format('operator %s(%s, %s) -> %s', + opname, lhs, rhs, impl_signature) AS object_name, + format( + 'Operator implementation function is `LANGUAGE %s`; only `LANGUAGE sql` functions can be inlined by the planner. Bare `col %s val` queries fall back to seq scan even when a matching functional index exists.', + lang, opname) AS message + FROM op_impl + WHERE lang <> 'sql' + AND NOT EXISTS ( + SELECT 1 FROM encrypted_domain_blockers b + WHERE b.oid = op_impl.impl_oid + ) + + UNION ALL + + SELECT + 'error', + 'inlinability_volatility', + format('operator %s(%s, %s) -> %s', opname, lhs, rhs, impl_signature), + format( + 'Operator implementation function is `VOLATILE`. The Postgres planner refuses to inline volatile functions into index expressions, so functional indexes never engage. Mark the function `IMMUTABLE` (or `STABLE` if it depends on session state).', + opname) + FROM op_impl + WHERE volatility = 'v' + AND NOT EXISTS ( + SELECT 1 FROM encrypted_domain_blockers b + WHERE b.oid = op_impl.impl_oid + ) + + UNION ALL + + SELECT + 'error', + 'inlinability_set_clause', + format('operator %s(%s, %s) -> %s', opname, lhs, rhs, impl_signature), + format( + 'Operator implementation function has a `SET` clause (e.g. `SET search_path = ...`). Per Postgres function-inlining rules, any `SET` clause blocks inlining. Use schema-qualified identifiers in the body and remove the `SET` clause to allow the planner to inline.') + FROM op_impl + WHERE config IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM encrypted_domain_blockers b + WHERE b.oid = op_impl.impl_oid + ) + + UNION ALL + + SELECT + 'error', + 'inlinability_secdef', + format('operator %s(%s, %s) -> %s', opname, lhs, rhs, impl_signature), + 'Operator implementation function is `SECURITY DEFINER`. Such functions cannot be inlined; remove `SECURITY DEFINER` or use a non-inlinable wrapper layer.' + FROM op_impl + WHERE secdef + AND NOT EXISTS ( + SELECT 1 FROM encrypted_domain_blockers b + WHERE b.oid = op_impl.impl_oid + ) + + -- ┌─────────────────────────────────────────────────────────────────┐ + -- │ Transitive inlinability: an operator implementation function │ + -- │ that's itself inlinable can still fail to inline if its body │ + -- │ calls a non-inlinable function. Walk one level via pg_depend. │ + -- │ │ + -- │ Postgres records function-to-function dependencies in │ + -- │ pg_depend with deptype 'n' (normal) when one function references│ + -- │ another in its body — but only at CREATE time and only for │ + -- │ direct calls. This is good enough for v1; deeper transitive │ + -- │ analysis is a follow-up. │ + -- └─────────────────────────────────────────────────────────────────┘ + + UNION ALL + + SELECT + 'error', + 'inlinability_transitive', + format('operator %s(%s, %s) -> %s', oi.opname, oi.lhs, oi.rhs, + oi.impl_signature), + format( + 'Operator implementation function is inlinable but invokes non-inlinable function `%s` (lang=%s, volatility=%s%s). The chain blocks at depth 1: the planner inlines the outer call but cannot reduce the inner call into an index expression.', + called.proname, + called_lang.lanname, + CASE called.provolatile + WHEN 'i' THEN 'IMMUTABLE' + WHEN 's' THEN 'STABLE' + WHEN 'v' THEN 'VOLATILE' + END, + CASE WHEN called.proconfig IS NOT NULL + THEN ', has SET clause' + ELSE '' END) + FROM op_impl oi + -- Only worth the transitive check if the outer function is otherwise + -- inlinable — otherwise the direct lints above already report it. + JOIN pg_proc outer_p ON outer_p.oid = oi.impl_signature::regprocedure + JOIN pg_depend d + ON d.classid = 'pg_proc'::regclass + AND d.objid = outer_p.oid + AND d.refclassid = 'pg_proc'::regclass + AND d.deptype = 'n' + JOIN pg_proc called ON called.oid = d.refobjid + JOIN pg_language called_lang ON called_lang.oid = called.prolang + WHERE oi.lang = 'sql' + AND oi.volatility IN ('i', 's') + AND oi.config IS NULL + AND NOT oi.secdef + AND called.oid <> outer_p.oid + AND ( + called_lang.lanname <> 'sql' + OR called.provolatile = 'v' + OR called.proconfig IS NOT NULL + OR called.prosecdef + ) + + -- ┌─────────────────────────────────────────────────────────────────┐ + -- │ Encrypted-domain footguns: blockers exist to RAISE, so they │ + -- │ have inverted inlinability requirements vs operator impls. │ + -- │ A LANGUAGE sql blocker can be elided by the planner; a STRICT │ + -- │ blocker returns NULL on NULL args. Both silently re-enable │ + -- │ operators the storage variant is supposed to block. │ + -- └─────────────────────────────────────────────────────────────────┘ + + UNION ALL + + SELECT + 'error', + 'blocker_language', + format('function %s', signature), + format( + 'Encrypted-domain blocker is `LANGUAGE %s`; must be `LANGUAGE plpgsql` so the RAISE is opaque to the planner. A `LANGUAGE sql` body is inlinable and may be elided when the result is provably unused, silently re-enabling the operator.', + lang) + FROM encrypted_domain_blockers + WHERE lang <> 'plpgsql' + + UNION ALL + + SELECT + 'error', + 'blocker_strict', + format('function %s', signature), + 'Encrypted-domain blocker is `STRICT`. PostgreSQL skips the body and returns NULL on a NULL argument, silently bypassing the RAISE. Remove `STRICT`.' + FROM encrypted_domain_blockers + WHERE isstrict + + -- ┌─────────────────────────────────────────────────────────────────┐ + -- │ 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. │ + -- └─────────────────────────────────────────────────────────────────┘ + + UNION ALL + + SELECT + 'error', + 'domain_over_domain', + format('domain %I.%I', dn.nspname, dt.typname), + format( + '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 + 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 = 'eql_v3' + AND bt.typtype = 'd' + AND bn.nspname = 'eql_v3' + + -- ┌─────────────────────────────────────────────────────────────────┐ + -- │ Domain opclass: an operator class declared FOR TYPE on an │ + -- │ encrypted-domain bypasses operator resolution at index time. │ + -- │ Use a functional index on the extractor instead. │ + -- └─────────────────────────────────────────────────────────────────┘ + + UNION ALL + + SELECT + 'error', + '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 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 + JOIN pg_catalog.pg_namespace cn ON cn.oid = oc.opcnamespace + WHERE t.typtype = 'd' + AND tn.nspname = 'eql_v3' + + ORDER BY 1, 2, 3; +$$; + +COMMENT ON FUNCTION eql_v3.lints() IS + 'EQL lint: returns one row per non-inlinable operator implementation. ' + 'Run `SELECT * FROM eql_v3.lints() WHERE severity = ''error''` for a ' + 'CI-gateable check that all operator implementations on eql_v3 types are ' + 'eligible for planner inlining.'; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/integer/integer_ord_aggregates.sql +--! @brief Aggregates for eql_v3.integer_ord. + +--! @brief State function for min on eql_v3.integer_ord. +--! @param state eql_v3.integer_ord +--! @param value eql_v3.integer_ord +--! @return eql_v3.integer_ord +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.integer_ord, value eql_v3.integer_ord) +RETURNS eql_v3.integer_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.integer_ord. +--! @param input eql_v3.integer_ord +--! @return eql_v3.integer_ord +CREATE AGGREGATE eql_v3.min(eql_v3.integer_ord) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.integer_ord, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.integer_ord. +--! @param state eql_v3.integer_ord +--! @param value eql_v3.integer_ord +--! @return eql_v3.integer_ord +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.integer_ord, value eql_v3.integer_ord) +RETURNS eql_v3.integer_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.integer_ord. +--! @param input eql_v3.integer_ord +--! @return eql_v3.integer_ord +CREATE AGGREGATE eql_v3.max(eql_v3.integer_ord) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.integer_ord, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/integer/integer_functions.sql +--! @brief Functions for eql_v3.integer. + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.integer, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.integer, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a jsonb +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.integer, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.integer, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a jsonb +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.integer, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.integer, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a jsonb +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.integer, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.integer, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a jsonb +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.integer, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.integer, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a jsonb +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.integer, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.integer, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a jsonb +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.integer, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.integer, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a jsonb +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.integer, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.integer, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a jsonb +--! @param b eql_v3.integer +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.integer) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param selector text +--! @return eql_v3.integer +CREATE FUNCTION eql_v3."->"(a eql_v3.integer, selector text) +RETURNS eql_v3.integer IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param selector integer +--! @return eql_v3.integer +CREATE FUNCTION eql_v3."->"(a eql_v3.integer, selector integer) +RETURNS eql_v3.integer IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a jsonb +--! @param selector eql_v3.integer +--! @return eql_v3.integer +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.integer) +RETURNS eql_v3.integer IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.integer, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.integer, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a jsonb +--! @param selector eql_v3.integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.integer, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.integer, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.integer, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.integer, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.integer, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.integer, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.integer, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.integer, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.integer, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.integer, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.integer, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b eql_v3.integer +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.integer, b eql_v3.integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a eql_v3.integer +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.integer, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer. +--! @param a jsonb +--! @param b eql_v3.integer +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.integer'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/integer/integer_eq_operators.sql +--! @brief Operators for eql_v3.integer_eq. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.integer_eq, RIGHTARG = eql_v3.integer_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.integer_eq, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.integer_eq, RIGHTARG = eql_v3.integer_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.integer_eq, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.integer_eq, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.integer_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.integer_eq, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.integer_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.integer_eq, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.integer_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.integer_eq, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.integer_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.integer_eq, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.integer_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.integer_eq, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.integer_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.integer_eq, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.integer_eq, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.integer_eq, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.integer_eq, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.integer_eq, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.integer_eq, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.integer_eq, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.integer_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.integer_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.integer_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.integer_eq, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.integer_eq, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.integer_eq, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.integer_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.integer_eq, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.integer_eq, RIGHTARG = eql_v3.integer_eq +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.integer_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_eq +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/integer/integer_ord_ore_functions.sql +--! @brief Functions for eql_v3.integer_ord_ore. + +--! @brief Index extractor for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.integer_ord_ore) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.integer_ord_ore, b eql_v3.integer_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.integer_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.integer_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a jsonb +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.integer_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.integer_ord_ore) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.integer_ord_ore, b eql_v3.integer_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.integer_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.integer_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a jsonb +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.integer_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.integer_ord_ore) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.integer_ord_ore, b eql_v3.integer_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.integer_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.integer_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a jsonb +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.integer_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.integer_ord_ore) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.integer_ord_ore, b eql_v3.integer_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.integer_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.integer_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a jsonb +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.integer_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.integer_ord_ore) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.integer_ord_ore, b eql_v3.integer_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.integer_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.integer_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a jsonb +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.integer_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.integer_ord_ore) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.integer_ord_ore, b eql_v3.integer_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.integer_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.integer_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.integer_ord_ore. +--! @param a jsonb +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.integer_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.integer_ord_ore) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.integer_ord_ore, b eql_v3.integer_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.integer_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a jsonb +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.integer_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.integer_ord_ore, b eql_v3.integer_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.integer_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a jsonb +--! @param b eql_v3.integer_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.integer_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param selector text +--! @return eql_v3.integer_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.integer_ord_ore, selector text) +RETURNS eql_v3.integer_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param selector integer +--! @return eql_v3.integer_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.integer_ord_ore, selector integer) +RETURNS eql_v3.integer_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.integer_ord_ore +--! @return eql_v3.integer_ord_ore +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.integer_ord_ore) +RETURNS eql_v3.integer_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.integer_ord_ore, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.integer_ord_ore, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.integer_ord_ore +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.integer_ord_ore) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.integer_ord_ore, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.integer_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.integer_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.integer_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.integer_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.integer_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.integer_ord_ore, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.integer_ord_ore, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.integer_ord_ore, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.integer_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.integer_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b eql_v3.integer_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.integer_ord_ore, b eql_v3.integer_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a eql_v3.integer_ord_ore +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.integer_ord_ore, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.integer_ord_ore. +--! @param a jsonb +--! @param b eql_v3.integer_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.integer_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.integer_ord_ore'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/integer/integer_ord_ore_operators.sql +--! @brief Operators for eql_v3.integer_ord_ore. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = eql_v3.integer_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = eql_v3.integer_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = eql_v3.integer_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = eql_v3.integer_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = eql_v3.integer_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = eql_v3.integer_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = eql_v3.integer_ord_ore +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = eql_v3.integer_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord_ore +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord_ore +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord_ore +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = eql_v3.integer_ord_ore +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.integer_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.integer_ord_ore +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/integer/integer_operators.sql +--! @brief Operators for eql_v3.integer. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.integer, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.integer, RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.integer, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.integer, RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.integer, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.integer, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.integer, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.integer, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.integer, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.integer, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.integer, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.integer, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.integer, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.integer, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.integer, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.integer, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.integer, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.integer, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.integer, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.integer, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.integer, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.integer, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.integer, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.integer, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.integer, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.integer, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.integer, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.integer, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.integer, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.integer, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.integer, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.integer, RIGHTARG = eql_v3.integer +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.integer, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.integer +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/integer/integer_ord_ore_aggregates.sql +--! @brief Aggregates for eql_v3.integer_ord_ore. + +--! @brief State function for min on eql_v3.integer_ord_ore. +--! @param state eql_v3.integer_ord_ore +--! @param value eql_v3.integer_ord_ore +--! @return eql_v3.integer_ord_ore +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.integer_ord_ore, value eql_v3.integer_ord_ore) +RETURNS eql_v3.integer_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.integer_ord_ore. +--! @param input eql_v3.integer_ord_ore +--! @return eql_v3.integer_ord_ore +CREATE AGGREGATE eql_v3.min(eql_v3.integer_ord_ore) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.integer_ord_ore, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.integer_ord_ore. +--! @param state eql_v3.integer_ord_ore +--! @param value eql_v3.integer_ord_ore +--! @return eql_v3.integer_ord_ore +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.integer_ord_ore, value eql_v3.integer_ord_ore) +RETURNS eql_v3.integer_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.integer_ord_ore. +--! @param input eql_v3.integer_ord_ore +--! @return eql_v3.integer_ord_ore +CREATE AGGREGATE eql_v3.max(eql_v3.integer_ord_ore) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.integer_ord_ore, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/smallint/smallint_eq_functions.sql +--! @brief Functions for eql_v3.smallint_eq. + +--! @brief Index extractor for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.smallint_eq) +RETURNS eql_v3.hmac_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.hmac_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.smallint_eq, b eql_v3.smallint_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.smallint_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.smallint_eq) $$; + +--! @brief Operator wrapper for eql_v3.smallint_eq. +--! @param a jsonb +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.smallint_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.smallint_eq) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.smallint_eq, b eql_v3.smallint_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.smallint_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.smallint_eq) $$; + +--! @brief Operator wrapper for eql_v3.smallint_eq. +--! @param a jsonb +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.smallint_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.smallint_eq) <> eql_v3.eq_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.smallint_eq, b eql_v3.smallint_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.smallint_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a jsonb +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.smallint_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.smallint_eq, b eql_v3.smallint_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.smallint_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a jsonb +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.smallint_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.smallint_eq, b eql_v3.smallint_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.smallint_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a jsonb +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.smallint_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.smallint_eq, b eql_v3.smallint_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.smallint_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a jsonb +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.smallint_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.smallint_eq, b eql_v3.smallint_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.smallint_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a jsonb +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.smallint_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.smallint_eq, b eql_v3.smallint_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.smallint_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a jsonb +--! @param b eql_v3.smallint_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.smallint_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param selector text +--! @return eql_v3.smallint_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.smallint_eq, selector text) +RETURNS eql_v3.smallint_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param selector integer +--! @return eql_v3.smallint_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.smallint_eq, selector integer) +RETURNS eql_v3.smallint_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a jsonb +--! @param selector eql_v3.smallint_eq +--! @return eql_v3.smallint_eq +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.smallint_eq) +RETURNS eql_v3.smallint_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.smallint_eq, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.smallint_eq, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a jsonb +--! @param selector eql_v3.smallint_eq +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.smallint_eq) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.smallint_eq, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.smallint_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.smallint_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.smallint_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.smallint_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.smallint_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.smallint_eq, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.smallint_eq, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.smallint_eq, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.smallint_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.smallint_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b eql_v3.smallint_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.smallint_eq, b eql_v3.smallint_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a eql_v3.smallint_eq +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.smallint_eq, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.smallint_eq. +--! @param a jsonb +--! @param b eql_v3.smallint_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.smallint_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.smallint_eq'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/smallint/smallint_ord_aggregates.sql +--! @brief Aggregates for eql_v3.smallint_ord. + +--! @brief State function for min on eql_v3.smallint_ord. +--! @param state eql_v3.smallint_ord +--! @param value eql_v3.smallint_ord +--! @return eql_v3.smallint_ord +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.smallint_ord, value eql_v3.smallint_ord) +RETURNS eql_v3.smallint_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.smallint_ord. +--! @param input eql_v3.smallint_ord +--! @return eql_v3.smallint_ord +CREATE AGGREGATE eql_v3.min(eql_v3.smallint_ord) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.smallint_ord, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.smallint_ord. +--! @param state eql_v3.smallint_ord +--! @param value eql_v3.smallint_ord +--! @return eql_v3.smallint_ord +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.smallint_ord, value eql_v3.smallint_ord) +RETURNS eql_v3.smallint_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.smallint_ord. +--! @param input eql_v3.smallint_ord +--! @return eql_v3.smallint_ord +CREATE AGGREGATE eql_v3.max(eql_v3.smallint_ord) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.smallint_ord, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/smallint/smallint_operators.sql +--! @brief Operators for eql_v3.smallint. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.smallint, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.smallint, RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.smallint, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.smallint, RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.smallint, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.smallint, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.smallint, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.smallint, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.smallint, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.smallint, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.smallint, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.smallint, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.smallint, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.smallint, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.smallint, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.smallint, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.smallint, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.smallint, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.smallint, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.smallint, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.smallint, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.smallint, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.smallint, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.smallint, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.smallint, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.smallint, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.smallint, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.smallint, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.smallint, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.smallint, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.smallint, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.smallint, RIGHTARG = eql_v3.smallint +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.smallint, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/smallint/smallint_eq_operators.sql +--! @brief Operators for eql_v3.smallint_eq. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = eql_v3.smallint_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = eql_v3.smallint_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.smallint_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = eql_v3.smallint_eq +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.smallint_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.smallint_eq +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/smallint/smallint_ord_ore_aggregates.sql +--! @brief Aggregates for eql_v3.smallint_ord_ore. + +--! @brief State function for min on eql_v3.smallint_ord_ore. +--! @param state eql_v3.smallint_ord_ore +--! @param value eql_v3.smallint_ord_ore +--! @return eql_v3.smallint_ord_ore +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.smallint_ord_ore, value eql_v3.smallint_ord_ore) +RETURNS eql_v3.smallint_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.smallint_ord_ore. +--! @param input eql_v3.smallint_ord_ore +--! @return eql_v3.smallint_ord_ore +CREATE AGGREGATE eql_v3.min(eql_v3.smallint_ord_ore) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.smallint_ord_ore, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.smallint_ord_ore. +--! @param state eql_v3.smallint_ord_ore +--! @param value eql_v3.smallint_ord_ore +--! @return eql_v3.smallint_ord_ore +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.smallint_ord_ore, value eql_v3.smallint_ord_ore) +RETURNS eql_v3.smallint_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.smallint_ord_ore. +--! @param input eql_v3.smallint_ord_ore +--! @return eql_v3.smallint_ord_ore +CREATE AGGREGATE eql_v3.max(eql_v3.smallint_ord_ore) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.smallint_ord_ore, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/double/double_ord_ore_aggregates.sql +--! @brief Aggregates for eql_v3.double_ord_ore. + +--! @brief State function for min on eql_v3.double_ord_ore. +--! @param state eql_v3.double_ord_ore +--! @param value eql_v3.double_ord_ore +--! @return eql_v3.double_ord_ore +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.double_ord_ore, value eql_v3.double_ord_ore) +RETURNS eql_v3.double_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.double_ord_ore. +--! @param input eql_v3.double_ord_ore +--! @return eql_v3.double_ord_ore +CREATE AGGREGATE eql_v3.min(eql_v3.double_ord_ore) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.double_ord_ore, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.double_ord_ore. +--! @param state eql_v3.double_ord_ore +--! @param value eql_v3.double_ord_ore +--! @return eql_v3.double_ord_ore +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.double_ord_ore, value eql_v3.double_ord_ore) +RETURNS eql_v3.double_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.double_ord_ore. +--! @param input eql_v3.double_ord_ore +--! @return eql_v3.double_ord_ore +CREATE AGGREGATE eql_v3.max(eql_v3.double_ord_ore) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.double_ord_ore, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/double/double_eq_functions.sql +--! @brief Functions for eql_v3.double_eq. + +--! @brief Index extractor for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.double_eq) +RETURNS eql_v3.hmac_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.hmac_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.double_eq, b eql_v3.double_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.double_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.double_eq) $$; + +--! @brief Operator wrapper for eql_v3.double_eq. +--! @param a jsonb +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.double_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.double_eq) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.double_eq, b eql_v3.double_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.double_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.double_eq) $$; + +--! @brief Operator wrapper for eql_v3.double_eq. +--! @param a jsonb +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.double_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.double_eq) <> eql_v3.eq_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.double_eq, b eql_v3.double_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.double_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a jsonb +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.double_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.double_eq, b eql_v3.double_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.double_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a jsonb +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.double_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.double_eq, b eql_v3.double_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.double_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a jsonb +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.double_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.double_eq, b eql_v3.double_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.double_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a jsonb +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.double_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.double_eq, b eql_v3.double_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.double_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a jsonb +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.double_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.double_eq, b eql_v3.double_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.double_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a jsonb +--! @param b eql_v3.double_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.double_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param selector text +--! @return eql_v3.double_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.double_eq, selector text) +RETURNS eql_v3.double_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param selector integer +--! @return eql_v3.double_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.double_eq, selector integer) +RETURNS eql_v3.double_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a jsonb +--! @param selector eql_v3.double_eq +--! @return eql_v3.double_eq +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.double_eq) +RETURNS eql_v3.double_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.double_eq, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.double_eq, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a jsonb +--! @param selector eql_v3.double_eq +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.double_eq) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.double_eq, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.double_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.double_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.double_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.double_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.double_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.double_eq, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.double_eq, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.double_eq, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.double_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.double_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b eql_v3.double_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.double_eq, b eql_v3.double_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a eql_v3.double_eq +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.double_eq, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.double_eq. +--! @param a jsonb +--! @param b eql_v3.double_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.double_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.double_eq'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/double/double_ord_operators.sql +--! @brief Operators for eql_v3.double_ord. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.double_ord, RIGHTARG = eql_v3.double_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.double_ord, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.double_ord, RIGHTARG = eql_v3.double_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.double_ord, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.double_ord, RIGHTARG = eql_v3.double_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.double_ord, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.double_ord, RIGHTARG = eql_v3.double_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.double_ord, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.double_ord, RIGHTARG = eql_v3.double_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.double_ord, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.double_ord, RIGHTARG = eql_v3.double_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.double_ord, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.double_ord, RIGHTARG = eql_v3.double_ord +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.double_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.double_ord, RIGHTARG = eql_v3.double_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.double_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.double_ord, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.double_ord, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.double_ord, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.double_ord, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.double_ord, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.double_ord, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.double_ord, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.double_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.double_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.double_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.double_ord, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.double_ord, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.double_ord, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.double_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.double_ord, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.double_ord, RIGHTARG = eql_v3.double_ord +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.double_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.double_ord +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/double/double_ord_aggregates.sql +--! @brief Aggregates for eql_v3.double_ord. + +--! @brief State function for min on eql_v3.double_ord. +--! @param state eql_v3.double_ord +--! @param value eql_v3.double_ord +--! @return eql_v3.double_ord +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.double_ord, value eql_v3.double_ord) +RETURNS eql_v3.double_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.double_ord. +--! @param input eql_v3.double_ord +--! @return eql_v3.double_ord +CREATE AGGREGATE eql_v3.min(eql_v3.double_ord) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.double_ord, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.double_ord. +--! @param state eql_v3.double_ord +--! @param value eql_v3.double_ord +--! @return eql_v3.double_ord +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.double_ord, value eql_v3.double_ord) +RETURNS eql_v3.double_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.double_ord. +--! @param input eql_v3.double_ord +--! @return eql_v3.double_ord +CREATE AGGREGATE eql_v3.max(eql_v3.double_ord) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.double_ord, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/double/double_operators.sql +--! @brief Operators for eql_v3.double. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.double, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.double, RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.double, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.double, RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.double, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.double, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.double, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.double, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.double, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.double, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.double, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.double, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.double, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.double, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.double, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.double, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.double, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.double, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.double, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.double, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.double, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.double, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.double, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.double, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.double, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.double, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.double, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.double, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.double, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.double, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.double, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.double, RIGHTARG = eql_v3.double +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.double, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.double +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/double/double_eq_operators.sql +--! @brief Operators for eql_v3.double_eq. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.double_eq, RIGHTARG = eql_v3.double_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.double_eq, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.double_eq, RIGHTARG = eql_v3.double_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.double_eq, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.double_eq, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.double_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.double_eq, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.double_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.double_eq, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.double_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.double_eq, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.double_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.double_eq, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.double_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.double_eq, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.double_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.double_eq, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.double_eq, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.double_eq, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.double_eq, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.double_eq, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.double_eq, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.double_eq, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.double_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.double_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.double_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.double_eq, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.double_eq, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.double_eq, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.double_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.double_eq, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.double_eq, RIGHTARG = eql_v3.double_eq +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.double_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.double_eq +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/date/date_ord_functions.sql +--! @brief Functions for eql_v3.date_ord. + +--! @brief Index extractor for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.date_ord) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.date_ord, b eql_v3.date_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.date_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.date_ord) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a jsonb +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.date_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.date_ord) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.date_ord, b eql_v3.date_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.date_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.date_ord) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a jsonb +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.date_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.date_ord) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.date_ord, b eql_v3.date_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.date_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.date_ord) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a jsonb +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.date_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.date_ord) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.date_ord, b eql_v3.date_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.date_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.date_ord) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a jsonb +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.date_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.date_ord) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.date_ord, b eql_v3.date_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.date_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.date_ord) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a jsonb +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.date_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.date_ord) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.date_ord, b eql_v3.date_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.date_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.date_ord) $$; + +--! @brief Operator wrapper for eql_v3.date_ord. +--! @param a jsonb +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.date_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.date_ord) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.date_ord, b eql_v3.date_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.date_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a jsonb +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.date_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.date_ord, b eql_v3.date_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.date_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a jsonb +--! @param b eql_v3.date_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.date_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param selector text +--! @return eql_v3.date_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.date_ord, selector text) +RETURNS eql_v3.date_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param selector integer +--! @return eql_v3.date_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.date_ord, selector integer) +RETURNS eql_v3.date_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a jsonb +--! @param selector eql_v3.date_ord +--! @return eql_v3.date_ord +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.date_ord) +RETURNS eql_v3.date_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.date_ord, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.date_ord, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a jsonb +--! @param selector eql_v3.date_ord +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.date_ord) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.date_ord, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.date_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.date_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.date_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.date_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.date_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.date_ord, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.date_ord, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.date_ord, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.date_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.date_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b eql_v3.date_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.date_ord, b eql_v3.date_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a eql_v3.date_ord +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.date_ord, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.date_ord. +--! @param a jsonb +--! @param b eql_v3.date_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.date_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.date_ord'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/date/date_eq_operators.sql +--! @brief Operators for eql_v3.date_eq. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.date_eq, RIGHTARG = eql_v3.date_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.date_eq, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.date_eq, RIGHTARG = eql_v3.date_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.date_eq, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.date_eq, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.date_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.date_eq, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.date_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.date_eq, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.date_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.date_eq, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.date_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.date_eq, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.date_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.date_eq, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.date_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.date_eq, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.date_eq, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.date_eq, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.date_eq, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.date_eq, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.date_eq, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.date_eq, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.date_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.date_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.date_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.date_eq, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.date_eq, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.date_eq, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.date_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.date_eq, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.date_eq, RIGHTARG = eql_v3.date_eq +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.date_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.date_eq +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/date/date_operators.sql +--! @brief Operators for eql_v3.date. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.date, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.date, RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.date, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.date, RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.date, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.date, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.date, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.date, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.date, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.date, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.date, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.date, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.date, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.date, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.date, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.date, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.date, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.date, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.date, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.date, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.date, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.date, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.date, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.date, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.date, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.date, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.date, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.date, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.date, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.date, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.date, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.date, RIGHTARG = eql_v3.date +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.date, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.date +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/date/date_ord_ore_aggregates.sql +--! @brief Aggregates for eql_v3.date_ord_ore. + +--! @brief State function for min on eql_v3.date_ord_ore. +--! @param state eql_v3.date_ord_ore +--! @param value eql_v3.date_ord_ore +--! @return eql_v3.date_ord_ore +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.date_ord_ore, value eql_v3.date_ord_ore) +RETURNS eql_v3.date_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.date_ord_ore. +--! @param input eql_v3.date_ord_ore +--! @return eql_v3.date_ord_ore +CREATE AGGREGATE eql_v3.min(eql_v3.date_ord_ore) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.date_ord_ore, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.date_ord_ore. +--! @param state eql_v3.date_ord_ore +--! @param value eql_v3.date_ord_ore +--! @return eql_v3.date_ord_ore +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.date_ord_ore, value eql_v3.date_ord_ore) +RETURNS eql_v3.date_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.date_ord_ore. +--! @param input eql_v3.date_ord_ore +--! @return eql_v3.date_ord_ore +CREATE AGGREGATE eql_v3.max(eql_v3.date_ord_ore) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.date_ord_ore, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/date/date_ord_operators.sql +--! @brief Operators for eql_v3.date_ord. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.date_ord, RIGHTARG = eql_v3.date_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.date_ord, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.date_ord, RIGHTARG = eql_v3.date_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.date_ord, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.date_ord, RIGHTARG = eql_v3.date_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.date_ord, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.date_ord, RIGHTARG = eql_v3.date_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.date_ord, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.date_ord, RIGHTARG = eql_v3.date_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.date_ord, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.date_ord, RIGHTARG = eql_v3.date_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.date_ord, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.date_ord, RIGHTARG = eql_v3.date_ord +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.date_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.date_ord, RIGHTARG = eql_v3.date_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.date_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.date_ord, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.date_ord, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.date_ord, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.date_ord, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.date_ord, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.date_ord, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.date_ord, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.date_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.date_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.date_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.date_ord, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.date_ord, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.date_ord, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.date_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.date_ord, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.date_ord, RIGHTARG = eql_v3.date_ord +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.date_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.date_ord +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/date/date_ord_aggregates.sql +--! @brief Aggregates for eql_v3.date_ord. + +--! @brief State function for min on eql_v3.date_ord. +--! @param state eql_v3.date_ord +--! @param value eql_v3.date_ord +--! @return eql_v3.date_ord +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.date_ord, value eql_v3.date_ord) +RETURNS eql_v3.date_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.date_ord. +--! @param input eql_v3.date_ord +--! @return eql_v3.date_ord +CREATE AGGREGATE eql_v3.min(eql_v3.date_ord) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.date_ord, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.date_ord. +--! @param state eql_v3.date_ord +--! @param value eql_v3.date_ord +--! @return eql_v3.date_ord +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.date_ord, value eql_v3.date_ord) +RETURNS eql_v3.date_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.date_ord. +--! @param input eql_v3.date_ord +--! @return eql_v3.date_ord +CREATE AGGREGATE eql_v3.max(eql_v3.date_ord) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.date_ord, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/numeric/numeric_ord_functions.sql +--! @brief Functions for eql_v3.numeric_ord. + +--! @brief Index extractor for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.numeric_ord) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.numeric_ord, b eql_v3.numeric_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.numeric_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.numeric_ord) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a jsonb +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.numeric_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.numeric_ord) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.numeric_ord, b eql_v3.numeric_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.numeric_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.numeric_ord) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a jsonb +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.numeric_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.numeric_ord) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.numeric_ord, b eql_v3.numeric_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.numeric_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.numeric_ord) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a jsonb +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.numeric_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.numeric_ord) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.numeric_ord, b eql_v3.numeric_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.numeric_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.numeric_ord) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a jsonb +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.numeric_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.numeric_ord) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.numeric_ord, b eql_v3.numeric_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.numeric_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.numeric_ord) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a jsonb +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.numeric_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.numeric_ord) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.numeric_ord, b eql_v3.numeric_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.numeric_ord, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.numeric_ord) $$; + +--! @brief Operator wrapper for eql_v3.numeric_ord. +--! @param a jsonb +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.numeric_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.numeric_ord) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.numeric_ord, b eql_v3.numeric_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.numeric_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a jsonb +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.numeric_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.numeric_ord, b eql_v3.numeric_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.numeric_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a jsonb +--! @param b eql_v3.numeric_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.numeric_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param selector text +--! @return eql_v3.numeric_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.numeric_ord, selector text) +RETURNS eql_v3.numeric_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param selector integer +--! @return eql_v3.numeric_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.numeric_ord, selector integer) +RETURNS eql_v3.numeric_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a jsonb +--! @param selector eql_v3.numeric_ord +--! @return eql_v3.numeric_ord +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.numeric_ord) +RETURNS eql_v3.numeric_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.numeric_ord, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.numeric_ord, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a jsonb +--! @param selector eql_v3.numeric_ord +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.numeric_ord) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.numeric_ord, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.numeric_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.numeric_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.numeric_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.numeric_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.numeric_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.numeric_ord, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.numeric_ord, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.numeric_ord, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.numeric_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.numeric_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b eql_v3.numeric_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.numeric_ord, b eql_v3.numeric_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a eql_v3.numeric_ord +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.numeric_ord, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric_ord. +--! @param a jsonb +--! @param b eql_v3.numeric_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.numeric_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.numeric_ord'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/numeric/numeric_functions.sql +--! @brief Functions for eql_v3.numeric. + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.numeric, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.numeric, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a jsonb +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.numeric, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.numeric, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a jsonb +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.numeric, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.numeric, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a jsonb +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.numeric, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.numeric, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a jsonb +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.numeric, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.numeric, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a jsonb +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.numeric, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.numeric, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a jsonb +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.numeric, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.numeric, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a jsonb +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.numeric, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.numeric, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a jsonb +--! @param b eql_v3.numeric +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.numeric) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param selector text +--! @return eql_v3.numeric +CREATE FUNCTION eql_v3."->"(a eql_v3.numeric, selector text) +RETURNS eql_v3.numeric IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param selector integer +--! @return eql_v3.numeric +CREATE FUNCTION eql_v3."->"(a eql_v3.numeric, selector integer) +RETURNS eql_v3.numeric IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a jsonb +--! @param selector eql_v3.numeric +--! @return eql_v3.numeric +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.numeric) +RETURNS eql_v3.numeric IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.numeric, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.numeric, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a jsonb +--! @param selector eql_v3.numeric +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.numeric) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.numeric, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.numeric, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.numeric, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.numeric, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.numeric, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.numeric, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.numeric, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.numeric, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.numeric, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.numeric, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.numeric, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b eql_v3.numeric +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.numeric, b eql_v3.numeric) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a eql_v3.numeric +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.numeric, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.numeric. +--! @param a jsonb +--! @param b eql_v3.numeric +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.numeric) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.numeric'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/numeric/numeric_eq_operators.sql +--! @brief Operators for eql_v3.numeric_eq. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = eql_v3.numeric_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = eql_v3.numeric_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.numeric_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = eql_v3.numeric_eq +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.numeric_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_eq +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/numeric/numeric_ord_ore_aggregates.sql +--! @brief Aggregates for eql_v3.numeric_ord_ore. + +--! @brief State function for min on eql_v3.numeric_ord_ore. +--! @param state eql_v3.numeric_ord_ore +--! @param value eql_v3.numeric_ord_ore +--! @return eql_v3.numeric_ord_ore +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.numeric_ord_ore, value eql_v3.numeric_ord_ore) +RETURNS eql_v3.numeric_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.numeric_ord_ore. +--! @param input eql_v3.numeric_ord_ore +--! @return eql_v3.numeric_ord_ore +CREATE AGGREGATE eql_v3.min(eql_v3.numeric_ord_ore) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.numeric_ord_ore, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.numeric_ord_ore. +--! @param state eql_v3.numeric_ord_ore +--! @param value eql_v3.numeric_ord_ore +--! @return eql_v3.numeric_ord_ore +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.numeric_ord_ore, value eql_v3.numeric_ord_ore) +RETURNS eql_v3.numeric_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.numeric_ord_ore. +--! @param input eql_v3.numeric_ord_ore +--! @return eql_v3.numeric_ord_ore +CREATE AGGREGATE eql_v3.max(eql_v3.numeric_ord_ore) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.numeric_ord_ore, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/numeric/numeric_operators.sql +--! @brief Operators for eql_v3.numeric. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.numeric, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.numeric, RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.numeric, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.numeric, RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.numeric, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.numeric, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.numeric, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.numeric, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.numeric, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.numeric, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.numeric, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.numeric, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.numeric, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.numeric, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.numeric, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.numeric, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.numeric, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.numeric, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.numeric, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.numeric, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.numeric, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.numeric, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.numeric, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.numeric, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.numeric, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.numeric, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.numeric, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.numeric, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.numeric, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.numeric, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.numeric, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.numeric, RIGHTARG = eql_v3.numeric +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.numeric, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/numeric/numeric_ord_operators.sql +--! @brief Operators for eql_v3.numeric_ord. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = eql_v3.numeric_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = eql_v3.numeric_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = eql_v3.numeric_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = eql_v3.numeric_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = eql_v3.numeric_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = eql_v3.numeric_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = eql_v3.numeric_ord +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = eql_v3.numeric_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.numeric_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = eql_v3.numeric_ord +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.numeric_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.numeric_ord +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/numeric/numeric_ord_aggregates.sql +--! @brief Aggregates for eql_v3.numeric_ord. + +--! @brief State function for min on eql_v3.numeric_ord. +--! @param state eql_v3.numeric_ord +--! @param value eql_v3.numeric_ord +--! @return eql_v3.numeric_ord +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.numeric_ord, value eql_v3.numeric_ord) +RETURNS eql_v3.numeric_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.numeric_ord. +--! @param input eql_v3.numeric_ord +--! @return eql_v3.numeric_ord +CREATE AGGREGATE eql_v3.min(eql_v3.numeric_ord) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.numeric_ord, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.numeric_ord. +--! @param state eql_v3.numeric_ord +--! @param value eql_v3.numeric_ord +--! @return eql_v3.numeric_ord +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.numeric_ord, value eql_v3.numeric_ord) +RETURNS eql_v3.numeric_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.numeric_ord. +--! @param input eql_v3.numeric_ord +--! @return eql_v3.numeric_ord +CREATE AGGREGATE eql_v3.max(eql_v3.numeric_ord) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.numeric_ord, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/bool/bool_operators.sql +--! @brief Operators for eql_v3.bool. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.bool, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.bool, RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.bool, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.bool, RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.bool, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.bool, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.bool, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.bool, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.bool, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.bool, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.bool, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.bool, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.bool, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.bool, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.bool, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.bool, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.bool, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.bool, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.bool, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.bool, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.bool, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.bool, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.bool, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.bool, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.bool, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.bool, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.bool, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.bool, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.bool, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.bool, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.bool, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.bool, RIGHTARG = eql_v3.bool +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.bool, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.bool +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/int8/int8_operators.sql +--! @brief Operators for eql_v3.int8. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int8, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int8, RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int8, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int8, RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int8, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int8, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int8, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int8, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int8, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int8, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int8, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int8, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int8, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int8, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int8, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int8, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int8, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int8, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int8, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int8, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.int8, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.int8, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.int8, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.int8, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.int8, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.int8, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.int8, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int8, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int8, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int8, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.int8, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int8, RIGHTARG = eql_v3.int8 +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int8, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.int8 +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/int8/int8_eq_functions.sql +--! @brief Functions for eql_v3.int8_eq. + +--! @brief Index extractor for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.int8_eq) +RETURNS eql_v3.hmac_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.hmac_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int8_eq, b eql_v3.int8_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int8_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b::eql_v3.int8_eq) $$; + +--! @brief Operator wrapper for eql_v3.int8_eq. +--! @param a jsonb +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.int8_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.int8_eq) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int8_eq, b eql_v3.int8_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int8_eq, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b::eql_v3.int8_eq) $$; + +--! @brief Operator wrapper for eql_v3.int8_eq. +--! @param a jsonb +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.int8_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.int8_eq) <> eql_v3.eq_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int8_eq, b eql_v3.int8_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int8_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a jsonb +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.int8_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int8_eq, b eql_v3.int8_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int8_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a jsonb +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.int8_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int8_eq, b eql_v3.int8_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int8_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a jsonb +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.int8_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int8_eq, b eql_v3.int8_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int8_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a jsonb +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.int8_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int8_eq, b eql_v3.int8_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int8_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a jsonb +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.int8_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int8_eq, b eql_v3.int8_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int8_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a jsonb +--! @param b eql_v3.int8_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.int8_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param selector text +--! @return eql_v3.int8_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.int8_eq, selector text) +RETURNS eql_v3.int8_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param selector integer +--! @return eql_v3.int8_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.int8_eq, selector integer) +RETURNS eql_v3.int8_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a jsonb +--! @param selector eql_v3.int8_eq +--! @return eql_v3.int8_eq +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int8_eq) +RETURNS eql_v3.int8_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int8_eq, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int8_eq, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a jsonb +--! @param selector eql_v3.int8_eq +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.int8_eq) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.int8_eq, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.int8_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.int8_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.int8_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.int8_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.int8_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.int8_eq, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int8_eq, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int8_eq, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int8_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.int8_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b eql_v3.int8_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int8_eq, b eql_v3.int8_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a eql_v3.int8_eq +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int8_eq, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_eq. +--! @param a jsonb +--! @param b eql_v3.int8_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int8_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int8_eq'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/int8/int8_ord_ore_functions.sql +--! @brief Functions for eql_v3.int8_ord_ore. + +--! @brief Index extractor for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @return eql_v3.ore_block_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.int8_ord_ore) +RETURNS eql_v3.ore_block_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int8_ord_ore, b eql_v3.int8_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int8_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b::eql_v3.int8_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.int8_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int8_ord_ore) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int8_ord_ore, b eql_v3.int8_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int8_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b::eql_v3.int8_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.int8_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int8_ord_ore) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int8_ord_ore, b eql_v3.int8_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int8_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b::eql_v3.int8_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.int8_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int8_ord_ore) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int8_ord_ore, b eql_v3.int8_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int8_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b::eql_v3.int8_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.int8_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int8_ord_ore) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int8_ord_ore, b eql_v3.int8_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int8_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b::eql_v3.int8_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.int8_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int8_ord_ore) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int8_ord_ore, b eql_v3.int8_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int8_ord_ore, b jsonb) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b::eql_v3.int8_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.int8_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.int8_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int8_ord_ore) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int8_ord_ore, b eql_v3.int8_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int8_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.int8_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int8_ord_ore, b eql_v3.int8_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int8_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int8_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.int8_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param selector text +--! @return eql_v3.int8_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.int8_ord_ore, selector text) +RETURNS eql_v3.int8_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param selector integer +--! @return eql_v3.int8_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.int8_ord_ore, selector integer) +RETURNS eql_v3.int8_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.int8_ord_ore +--! @return eql_v3.int8_ord_ore +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int8_ord_ore) +RETURNS eql_v3.int8_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int8_ord_ore, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int8_ord_ore, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.int8_ord_ore +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.int8_ord_ore) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.int8_ord_ore, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.int8_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.int8_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.int8_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.int8_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.int8_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.int8_ord_ore, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int8_ord_ore, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int8_ord_ore, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int8_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.int8_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b eql_v3.int8_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int8_ord_ore, b eql_v3.int8_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a eql_v3.int8_ord_ore +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int8_ord_ore, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int8_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int8_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int8_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int8_ord_ore'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/int8/int8_ord_operators.sql +--! @brief Operators for eql_v3.int8_ord. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int8_ord, RIGHTARG = eql_v3.int8_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int8_ord, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int8_ord, RIGHTARG = eql_v3.int8_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int8_ord, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int8_ord, RIGHTARG = eql_v3.int8_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int8_ord, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int8_ord, RIGHTARG = eql_v3.int8_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int8_ord, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int8_ord, RIGHTARG = eql_v3.int8_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int8_ord, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int8_ord, RIGHTARG = eql_v3.int8_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int8_ord, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int8_ord, RIGHTARG = eql_v3.int8_ord +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int8_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int8_ord, RIGHTARG = eql_v3.int8_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int8_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int8_ord, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int8_ord, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int8_ord, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int8_ord, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.int8_ord, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.int8_ord, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.int8_ord, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.int8_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.int8_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.int8_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.int8_ord, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int8_ord, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int8_ord, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int8_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.int8_ord, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int8_ord, RIGHTARG = eql_v3.int8_ord +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int8_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/int8/int8_ord_ore_operators.sql +--! @brief Operators for eql_v3.int8_ord_ore. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = eql_v3.int8_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = eql_v3.int8_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = eql_v3.int8_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = eql_v3.int8_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = eql_v3.int8_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = eql_v3.int8_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = eql_v3.int8_ord_ore +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = eql_v3.int8_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord_ore +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord_ore +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord_ore +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = eql_v3.int8_ord_ore +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int8_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_ord_ore +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/int8/int8_ord_ore_aggregates.sql +--! @brief Aggregates for eql_v3.int8_ord_ore. + +--! @brief State function for min on eql_v3.int8_ord_ore. +--! @param state eql_v3.int8_ord_ore +--! @param value eql_v3.int8_ord_ore +--! @return eql_v3.int8_ord_ore +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.int8_ord_ore, value eql_v3.int8_ord_ore) +RETURNS eql_v3.int8_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.int8_ord_ore. +--! @param input eql_v3.int8_ord_ore +--! @return eql_v3.int8_ord_ore +CREATE AGGREGATE eql_v3.min(eql_v3.int8_ord_ore) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.int8_ord_ore, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.int8_ord_ore. +--! @param state eql_v3.int8_ord_ore +--! @param value eql_v3.int8_ord_ore +--! @return eql_v3.int8_ord_ore +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.int8_ord_ore, value eql_v3.int8_ord_ore) +RETURNS eql_v3.int8_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.int8_ord_ore. +--! @param input eql_v3.int8_ord_ore +--! @return eql_v3.int8_ord_ore +CREATE AGGREGATE eql_v3.max(eql_v3.int8_ord_ore) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.int8_ord_ore, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/int8/int8_ord_aggregates.sql +--! @brief Aggregates for eql_v3.int8_ord. + +--! @brief State function for min on eql_v3.int8_ord. +--! @param state eql_v3.int8_ord +--! @param value eql_v3.int8_ord +--! @return eql_v3.int8_ord +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.int8_ord, value eql_v3.int8_ord) +RETURNS eql_v3.int8_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.int8_ord. +--! @param input eql_v3.int8_ord +--! @return eql_v3.int8_ord +CREATE AGGREGATE eql_v3.min(eql_v3.int8_ord) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.int8_ord, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.int8_ord. +--! @param state eql_v3.int8_ord +--! @param value eql_v3.int8_ord +--! @return eql_v3.int8_ord +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.int8_ord, value eql_v3.int8_ord) +RETURNS eql_v3.int8_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.int8_ord. +--! @param input eql_v3.int8_ord +--! @return eql_v3.int8_ord +CREATE AGGREGATE eql_v3.max(eql_v3.int8_ord) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.int8_ord, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/int8/int8_eq_operators.sql +--! @brief Operators for eql_v3.int8_eq. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int8_eq, RIGHTARG = eql_v3.int8_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int8_eq, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int8_eq, RIGHTARG = eql_v3.int8_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int8_eq, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int8_eq, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int8_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int8_eq, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int8_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int8_eq, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int8_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int8_eq, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int8_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int8_eq, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int8_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int8_eq, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int8_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int8_eq, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int8_eq, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int8_eq, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int8_eq, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.int8_eq, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.int8_eq, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.int8_eq, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.int8_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.int8_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.int8_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.int8_eq, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int8_eq, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int8_eq, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int8_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.int8_eq, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int8_eq, RIGHTARG = eql_v3.int8_eq +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int8_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.int8_eq +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_functions.sql +--! @brief Functions for eql_v3.text. + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.text, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.text, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a jsonb +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.text, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.text, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a jsonb +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.text, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.text, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a jsonb +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.text, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.text, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a jsonb +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.text, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.text, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a jsonb +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.text, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.text, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a jsonb +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.text, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.text, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a jsonb +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.text, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.text, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a jsonb +--! @param b eql_v3.text +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param selector text +--! @return eql_v3.text +CREATE FUNCTION eql_v3."->"(a eql_v3.text, selector text) +RETURNS eql_v3.text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param selector integer +--! @return eql_v3.text +CREATE FUNCTION eql_v3."->"(a eql_v3.text, selector integer) +RETURNS eql_v3.text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a jsonb +--! @param selector eql_v3.text +--! @return eql_v3.text +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.text) +RETURNS eql_v3.text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.text, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.text, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a jsonb +--! @param selector eql_v3.text +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.text, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.text, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.text, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.text, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.text, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.text, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.text, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.text, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.text, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b eql_v3.text +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.text, b eql_v3.text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a eql_v3.text +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.text, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.text. +--! @param a jsonb +--! @param b eql_v3.text +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.text'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_match_operators.sql +--! @brief Operators for eql_v3.text_match. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.text_match, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.text_match, RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.text_match, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.text_match, RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.text_match, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.text_match, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.text_match, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.text_match, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.text_match, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.text_match, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.text_match, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.text_match, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.text_match, RIGHTARG = eql_v3.text_match, + COMMUTATOR = <@, RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.text_match, RIGHTARG = jsonb, + COMMUTATOR = <@, RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_match, + COMMUTATOR = <@, RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.text_match, RIGHTARG = eql_v3.text_match, + COMMUTATOR = @>, RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.text_match, RIGHTARG = jsonb, + COMMUTATOR = @>, RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_match, + COMMUTATOR = @>, RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.text_match, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.text_match, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.text_match, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.text_match, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.text_match, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.text_match, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.text_match, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.text_match, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.text_match, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.text_match, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.text_match, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_match, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_match, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_match, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.text_match, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.text_match, RIGHTARG = eql_v3.text_match +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.text_match, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_match +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_search_operators.sql +--! @brief Operators for eql_v3.text_search. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.text_search, RIGHTARG = eql_v3.text_search, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.text_search, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_search, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.text_search, RIGHTARG = eql_v3.text_search, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.text_search, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_search, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.text_search, RIGHTARG = eql_v3.text_search, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.text_search, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_search, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.text_search, RIGHTARG = eql_v3.text_search, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.text_search, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_search, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.text_search, RIGHTARG = eql_v3.text_search, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.text_search, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_search, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.text_search, RIGHTARG = eql_v3.text_search, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.text_search, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_search, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.text_search, RIGHTARG = eql_v3.text_search, + COMMUTATOR = <@, RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.text_search, RIGHTARG = jsonb, + COMMUTATOR = <@, RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_search, + COMMUTATOR = <@, RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.text_search, RIGHTARG = eql_v3.text_search, + COMMUTATOR = @>, RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.text_search, RIGHTARG = jsonb, + COMMUTATOR = @>, RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_search, + COMMUTATOR = @>, RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.text_search, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.text_search, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_search +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.text_search, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.text_search, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_search +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.text_search, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.text_search, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.text_search, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.text_search, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.text_search, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.text_search, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.text_search, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_search, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_search, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_search, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.text_search, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.text_search, RIGHTARG = eql_v3.text_search +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.text_search, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_search +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_eq_operators.sql +--! @brief Operators for eql_v3.text_eq. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.text_eq, RIGHTARG = eql_v3.text_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.text_eq, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.text_eq, RIGHTARG = eql_v3.text_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.text_eq, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.text_eq, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.text_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.text_eq, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.text_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.text_eq, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.text_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.text_eq, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.text_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.text_eq, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.text_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.text_eq, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.text_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.text_eq, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.text_eq, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.text_eq, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.text_eq, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.text_eq, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.text_eq, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.text_eq, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.text_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.text_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.text_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.text_eq, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_eq, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_eq, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.text_eq, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.text_eq, RIGHTARG = eql_v3.text_eq +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.text_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.text_eq +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_ord_ore_aggregates.sql +--! @brief Aggregates for eql_v3.text_ord_ore. + +--! @brief State function for min on eql_v3.text_ord_ore. +--! @param state eql_v3.text_ord_ore +--! @param value eql_v3.text_ord_ore +--! @return eql_v3.text_ord_ore +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.text_ord_ore, value eql_v3.text_ord_ore) +RETURNS eql_v3.text_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.text_ord_ore. +--! @param input eql_v3.text_ord_ore +--! @return eql_v3.text_ord_ore +CREATE AGGREGATE eql_v3.min(eql_v3.text_ord_ore) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.text_ord_ore, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.text_ord_ore. +--! @param state eql_v3.text_ord_ore +--! @param value eql_v3.text_ord_ore +--! @return eql_v3.text_ord_ore +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.text_ord_ore, value eql_v3.text_ord_ore) +RETURNS eql_v3.text_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.text_ord_ore. +--! @param input eql_v3.text_ord_ore +--! @return eql_v3.text_ord_ore +CREATE AGGREGATE eql_v3.max(eql_v3.text_ord_ore) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.text_ord_ore, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_ord_aggregates.sql +--! @brief Aggregates for eql_v3.text_ord. + +--! @brief State function for min on eql_v3.text_ord. +--! @param state eql_v3.text_ord +--! @param value eql_v3.text_ord +--! @return eql_v3.text_ord +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.text_ord, value eql_v3.text_ord) +RETURNS eql_v3.text_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.text_ord. +--! @param input eql_v3.text_ord +--! @return eql_v3.text_ord +CREATE AGGREGATE eql_v3.min(eql_v3.text_ord) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.text_ord, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.text_ord. +--! @param state eql_v3.text_ord +--! @param value eql_v3.text_ord +--! @return eql_v3.text_ord +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.text_ord, value eql_v3.text_ord) +RETURNS eql_v3.text_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.text_ord. +--! @param input eql_v3.text_ord +--! @return eql_v3.text_ord +CREATE AGGREGATE eql_v3.max(eql_v3.text_ord) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.text_ord, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_operators.sql +--! @brief Operators for eql_v3.text. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.text, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.text, RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.text, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.text, RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.text, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.text, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.text, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.text, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.text, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.text, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.text, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.text, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.text, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.text, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.text, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.text, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.text, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.text, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.text, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.text, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.text, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.text, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.text, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.text, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.text, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.text, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.text, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.text, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.text, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.text, RIGHTARG = eql_v3.text +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.text, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.text +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/text/text_search_aggregates.sql +--! @brief Aggregates for eql_v3.text_search. + +--! @brief State function for min on eql_v3.text_search. +--! @param state eql_v3.text_search +--! @param value eql_v3.text_search +--! @return eql_v3.text_search +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.text_search, value eql_v3.text_search) +RETURNS eql_v3.text_search +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.text_search. +--! @param input eql_v3.text_search +--! @return eql_v3.text_search +CREATE AGGREGATE eql_v3.min(eql_v3.text_search) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.text_search, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.text_search. +--! @param state eql_v3.text_search +--! @param value eql_v3.text_search +--! @return eql_v3.text_search +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.text_search, value eql_v3.text_search) +RETURNS eql_v3.text_search +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.text_search. +--! @param input eql_v3.text_search +--! @return eql_v3.text_search +CREATE AGGREGATE eql_v3.max(eql_v3.text_search) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.text_search, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/real/real_eq_operators.sql +--! @brief Operators for eql_v3.real_eq. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.real_eq, RIGHTARG = eql_v3.real_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.real_eq, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.real_eq, RIGHTARG = eql_v3.real_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.real_eq, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.real_eq, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.real_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.real_eq, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.real_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.real_eq, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.real_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.real_eq, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.real_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.real_eq, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.real_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.real_eq, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.real_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.real_eq, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.real_eq, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.real_eq, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.real_eq, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.real_eq, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.real_eq, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.real_eq, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.real_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.real_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.real_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.real_eq, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.real_eq, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.real_eq, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.real_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.real_eq, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.real_eq, RIGHTARG = eql_v3.real_eq +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.real_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.real_eq +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/real/real_ord_ore_aggregates.sql +--! @brief Aggregates for eql_v3.real_ord_ore. + +--! @brief State function for min on eql_v3.real_ord_ore. +--! @param state eql_v3.real_ord_ore +--! @param value eql_v3.real_ord_ore +--! @return eql_v3.real_ord_ore +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.real_ord_ore, value eql_v3.real_ord_ore) +RETURNS eql_v3.real_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.real_ord_ore. +--! @param input eql_v3.real_ord_ore +--! @return eql_v3.real_ord_ore +CREATE AGGREGATE eql_v3.min(eql_v3.real_ord_ore) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.real_ord_ore, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.real_ord_ore. +--! @param state eql_v3.real_ord_ore +--! @param value eql_v3.real_ord_ore +--! @return eql_v3.real_ord_ore +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.real_ord_ore, value eql_v3.real_ord_ore) +RETURNS eql_v3.real_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.real_ord_ore. +--! @param input eql_v3.real_ord_ore +--! @return eql_v3.real_ord_ore +CREATE AGGREGATE eql_v3.max(eql_v3.real_ord_ore) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.real_ord_ore, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/real/real_functions.sql +--! @brief Functions for eql_v3.real. + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.real, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.real, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a jsonb +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.real, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.real, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a jsonb +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.real, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.real, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a jsonb +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.real, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.real, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a jsonb +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.real, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.real, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a jsonb +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.real, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.real, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a jsonb +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.real, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.real, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a jsonb +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.real, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.real, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a jsonb +--! @param b eql_v3.real +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.real) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param selector text +--! @return eql_v3.real +CREATE FUNCTION eql_v3."->"(a eql_v3.real, selector text) +RETURNS eql_v3.real IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param selector integer +--! @return eql_v3.real +CREATE FUNCTION eql_v3."->"(a eql_v3.real, selector integer) +RETURNS eql_v3.real IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a jsonb +--! @param selector eql_v3.real +--! @return eql_v3.real +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.real) +RETURNS eql_v3.real IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.real, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.real, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a jsonb +--! @param selector eql_v3.real +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.real) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.real, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.real, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.real, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.real, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.real, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.real, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.real, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.real, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.real, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.real, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.real, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b eql_v3.real +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.real, b eql_v3.real) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a eql_v3.real +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.real, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.real. +--! @param a jsonb +--! @param b eql_v3.real +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.real) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.real'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/real/real_ord_aggregates.sql +--! @brief Aggregates for eql_v3.real_ord. + +--! @brief State function for min on eql_v3.real_ord. +--! @param state eql_v3.real_ord +--! @param value eql_v3.real_ord +--! @return eql_v3.real_ord +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.real_ord, value eql_v3.real_ord) +RETURNS eql_v3.real_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.real_ord. +--! @param input eql_v3.real_ord +--! @return eql_v3.real_ord +CREATE AGGREGATE eql_v3.min(eql_v3.real_ord) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.real_ord, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.real_ord. +--! @param state eql_v3.real_ord +--! @param value eql_v3.real_ord +--! @return eql_v3.real_ord +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.real_ord, value eql_v3.real_ord) +RETURNS eql_v3.real_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.real_ord. +--! @param input eql_v3.real_ord +--! @return eql_v3.real_ord +CREATE AGGREGATE eql_v3.max(eql_v3.real_ord) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.real_ord, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/real/real_operators.sql +--! @brief Operators for eql_v3.real. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.real, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.real, RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.real, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.real, RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.real, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.real, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.real, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.real, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.real, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.real, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.real, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.real, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.real, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.real, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.real, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.real, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.real, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.real, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.real, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.real, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.real, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.real, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.real, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.real, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.real, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.real, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.real, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.real, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.real, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.real, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.real, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.real, RIGHTARG = eql_v3.real +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.real, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.real +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/timestamp/timestamp_functions.sql +--! @brief Functions for eql_v3.timestamp. + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.timestamp, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.timestamp, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a jsonb +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.timestamp, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.timestamp, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a jsonb +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.timestamp, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.timestamp, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a jsonb +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.timestamp, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.timestamp, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a jsonb +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.timestamp, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.timestamp, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a jsonb +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.timestamp, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.timestamp, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a jsonb +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.timestamp, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.timestamp, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a jsonb +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.timestamp, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.timestamp, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a jsonb +--! @param b eql_v3.timestamp +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.timestamp) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param selector text +--! @return eql_v3.timestamp +CREATE FUNCTION eql_v3."->"(a eql_v3.timestamp, selector text) +RETURNS eql_v3.timestamp IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param selector integer +--! @return eql_v3.timestamp +CREATE FUNCTION eql_v3."->"(a eql_v3.timestamp, selector integer) +RETURNS eql_v3.timestamp IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a jsonb +--! @param selector eql_v3.timestamp +--! @return eql_v3.timestamp +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.timestamp) +RETURNS eql_v3.timestamp IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.timestamp, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.timestamp, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a jsonb +--! @param selector eql_v3.timestamp +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.timestamp) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.timestamp, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.timestamp, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.timestamp, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.timestamp, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.timestamp, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.timestamp, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.timestamp, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.timestamp, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.timestamp, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.timestamp, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.timestamp, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b eql_v3.timestamp +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.timestamp, b eql_v3.timestamp) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a eql_v3.timestamp +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.timestamp, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.timestamp. +--! @param a jsonb +--! @param b eql_v3.timestamp +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.timestamp) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.timestamp'; END; $$ +LANGUAGE plpgsql; +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/timestamp/timestamp_ord_aggregates.sql +--! @brief Aggregates for eql_v3.timestamp_ord. + +--! @brief State function for min on eql_v3.timestamp_ord. +--! @param state eql_v3.timestamp_ord +--! @param value eql_v3.timestamp_ord +--! @return eql_v3.timestamp_ord +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.timestamp_ord, value eql_v3.timestamp_ord) +RETURNS eql_v3.timestamp_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.timestamp_ord. +--! @param input eql_v3.timestamp_ord +--! @return eql_v3.timestamp_ord +CREATE AGGREGATE eql_v3.min(eql_v3.timestamp_ord) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.timestamp_ord, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.timestamp_ord. +--! @param state eql_v3.timestamp_ord +--! @param value eql_v3.timestamp_ord +--! @return eql_v3.timestamp_ord +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.timestamp_ord, value eql_v3.timestamp_ord) +RETURNS eql_v3.timestamp_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.timestamp_ord. +--! @param input eql_v3.timestamp_ord +--! @return eql_v3.timestamp_ord +CREATE AGGREGATE eql_v3.max(eql_v3.timestamp_ord) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.timestamp_ord, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/timestamp/timestamp_eq_operators.sql +--! @brief Operators for eql_v3.timestamp_eq. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = eql_v3.timestamp_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = eql_v3.timestamp_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = eql_v3.timestamp_eq +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.timestamp_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp_eq +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/timestamp/timestamp_ord_ore_aggregates.sql +--! @brief Aggregates for eql_v3.timestamp_ord_ore. + +--! @brief State function for min on eql_v3.timestamp_ord_ore. +--! @param state eql_v3.timestamp_ord_ore +--! @param value eql_v3.timestamp_ord_ore +--! @return eql_v3.timestamp_ord_ore +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.timestamp_ord_ore, value eql_v3.timestamp_ord_ore) +RETURNS eql_v3.timestamp_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.timestamp_ord_ore. +--! @param input eql_v3.timestamp_ord_ore +--! @return eql_v3.timestamp_ord_ore +CREATE AGGREGATE eql_v3.min(eql_v3.timestamp_ord_ore) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.timestamp_ord_ore, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.timestamp_ord_ore. +--! @param state eql_v3.timestamp_ord_ore +--! @param value eql_v3.timestamp_ord_ore +--! @return eql_v3.timestamp_ord_ore +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.timestamp_ord_ore, value eql_v3.timestamp_ord_ore) +RETURNS eql_v3.timestamp_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.timestamp_ord_ore. +--! @param input eql_v3.timestamp_ord_ore +--! @return eql_v3.timestamp_ord_ore +CREATE AGGREGATE eql_v3.max(eql_v3.timestamp_ord_ore) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.timestamp_ord_ore, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); +-- AUTOMATICALLY GENERATED FILE. + +--! @file encrypted_domain/timestamp/timestamp_operators.sql +--! @brief Operators for eql_v3.timestamp. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.timestamp, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.timestamp, RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.timestamp, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.timestamp, RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.timestamp, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.timestamp, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.timestamp, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.timestamp, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.timestamp, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.timestamp, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.timestamp, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.timestamp, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.timestamp, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.timestamp, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.timestamp, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.timestamp, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.timestamp, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.timestamp, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.timestamp, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.timestamp, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.timestamp, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.timestamp, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.timestamp, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.timestamp, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.timestamp, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.timestamp, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.timestamp, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.timestamp, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.timestamp, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.timestamp, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.timestamp, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.timestamp, RIGHTARG = eql_v3.timestamp +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.timestamp, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.timestamp +); + +--! @file v3/sem/ore_block_256/operator_class.sql +--! @brief B-tree operator family + default class on eql_v3.ore_block_256. +--! +--! Gives the composite type its DEFAULT btree opclass so the recommended +--! functional index `CREATE INDEX ON t (eql_v3.ord_term(col))` engages without +--! an explicit opclass annotation (design D4). Excluded from the Supabase build +--! variant by the `**/*operator_class.sql` glob. + +--! @brief B-tree operator family for ORE block types +CREATE OPERATOR FAMILY eql_v3.ore_block_256_operator_family USING btree; + +--! @brief B-tree operator class for ORE block encrypted values +--! +--! Supports operators: <, <=, =, >=, >. Uses comparison function +--! compare_ore_block_256_terms. +CREATE OPERATOR CLASS eql_v3.ore_block_256_operator_class DEFAULT FOR TYPE eql_v3.ore_block_256 USING btree FAMILY eql_v3.ore_block_256_operator_family AS + OPERATOR 1 <, + OPERATOR 2 <=, + OPERATOR 3 =, + OPERATOR 4 >=, + OPERATOR 5 >, + FUNCTION 1 eql_v3.compare_ore_block_256_terms(a eql_v3.ore_block_256, b eql_v3.ore_block_256); + +--! @file v3/sem/ore_cllw/operators.sql +--! @brief Comparison operators on the eql_v3.ore_cllw composite type. +--! +--! Each backing function reduces to a single SELECT over +--! eql_v3.compare_ore_cllw_term(a, b) and is inlinable so the planner can fold +--! it through to functional-index matching. The inner comparator is plpgsql +--! (per-byte loop) and is not inlined — fine for index *match*. +--! +--! @note Deliberately no HASHES / MERGES — the CLLW protocol gives ordering, +--! not a hash; there is no merge-joinable opclass on the other side. +--! @see eql_v3.compare_ore_cllw_term + +--! @brief Equality backing function for eql_v3.ore_cllw. +--! @internal +--! +--! @param a eql_v3.ore_cllw Left operand +--! @param b eql_v3.ore_cllw Right operand +--! @return boolean True if the CLLW ORE terms are equal +--! +--! @see eql_v3.compare_ore_cllw_term +CREATE FUNCTION eql_v3.ore_cllw_eq(a eql_v3.ore_cllw, b eql_v3.ore_cllw) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_cllw_term(a, b) = 0 +$$; + +--! @brief Not-equal backing function for eql_v3.ore_cllw. +--! @internal +--! +--! @param a eql_v3.ore_cllw Left operand +--! @param b eql_v3.ore_cllw Right operand +--! @return boolean True if the CLLW ORE terms are not equal +--! +--! @see eql_v3.compare_ore_cllw_term +CREATE FUNCTION eql_v3.ore_cllw_neq(a eql_v3.ore_cllw, b eql_v3.ore_cllw) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_cllw_term(a, b) <> 0 +$$; + +--! @brief Less-than backing function for eql_v3.ore_cllw. +--! @internal +--! +--! @param a eql_v3.ore_cllw Left operand +--! @param b eql_v3.ore_cllw Right operand +--! @return boolean True if the left operand is less than the right operand +--! +--! @see eql_v3.compare_ore_cllw_term +CREATE FUNCTION eql_v3.ore_cllw_lt(a eql_v3.ore_cllw, b eql_v3.ore_cllw) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_cllw_term(a, b) = -1 +$$; + +--! @brief Less-than-or-equal backing function for eql_v3.ore_cllw. +--! @internal +--! +--! @param a eql_v3.ore_cllw Left operand +--! @param b eql_v3.ore_cllw Right operand +--! @return boolean True if the left operand is less than or equal to the right operand +--! +--! @see eql_v3.compare_ore_cllw_term +CREATE FUNCTION eql_v3.ore_cllw_lte(a eql_v3.ore_cllw, b eql_v3.ore_cllw) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_cllw_term(a, b) <> 1 +$$; + +--! @brief Greater-than backing function for eql_v3.ore_cllw. +--! @internal +--! +--! @param a eql_v3.ore_cllw Left operand +--! @param b eql_v3.ore_cllw Right operand +--! @return boolean True if the left operand is greater than the right operand +--! +--! @see eql_v3.compare_ore_cllw_term +CREATE FUNCTION eql_v3.ore_cllw_gt(a eql_v3.ore_cllw, b eql_v3.ore_cllw) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_cllw_term(a, b) = 1 +$$; + +--! @brief Greater-than-or-equal backing function for eql_v3.ore_cllw. +--! @internal +--! +--! @param a eql_v3.ore_cllw Left operand +--! @param b eql_v3.ore_cllw Right operand +--! @return boolean True if the left operand is greater than or equal to the right operand +--! +--! @see eql_v3.compare_ore_cllw_term +CREATE FUNCTION eql_v3.ore_cllw_gte(a eql_v3.ore_cllw, b eql_v3.ore_cllw) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_cllw_term(a, b) <> -1 +$$; + + +CREATE OPERATOR = ( + FUNCTION = eql_v3.ore_cllw_eq, + LEFTARG = eql_v3.ore_cllw, + RIGHTARG = eql_v3.ore_cllw, + COMMUTATOR = =, + NEGATOR = <>, + RESTRICT = eqsel, + JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.ore_cllw_neq, + LEFTARG = eql_v3.ore_cllw, + RIGHTARG = eql_v3.ore_cllw, + COMMUTATOR = <>, + NEGATOR = =, + RESTRICT = neqsel, + JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.ore_cllw_lt, + LEFTARG = eql_v3.ore_cllw, + RIGHTARG = eql_v3.ore_cllw, + COMMUTATOR = >, + NEGATOR = >=, + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.ore_cllw_lte, + LEFTARG = eql_v3.ore_cllw, + RIGHTARG = eql_v3.ore_cllw, + COMMUTATOR = >=, + NEGATOR = >, + RESTRICT = scalarlesel, + JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.ore_cllw_gt, + LEFTARG = eql_v3.ore_cllw, + RIGHTARG = eql_v3.ore_cllw, + COMMUTATOR = <, + NEGATOR = <=, + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.ore_cllw_gte, + LEFTARG = eql_v3.ore_cllw, + RIGHTARG = eql_v3.ore_cllw, + COMMUTATOR = <=, + NEGATOR = <, + RESTRICT = scalargesel, + JOIN = scalargejoinsel +); + +--! @file v3/sem/ore_cllw/operator_class.sql +--! @brief Btree operator class on the eql_v3.ore_cllw composite type. +--! +--! DEFAULT FOR TYPE so a functional btree index on eql_v3.ore_cllw(expr) +--! engages without an explicit opclass annotation. FUNCTION 1 is the three-way +--! comparator btree's internal sort uses; it is plpgsql by design (per-byte +--! CLLW protocol needs iteration) and is called once per index-entry pair +--! during build / search, not per-row in the outer query. +--! +--! @note Excluded from the Supabase build variant by the build glob +--! `**/*operator_class.sql`. +--! @see eql_v3.compare_ore_cllw_term + +CREATE OPERATOR FAMILY eql_v3.ore_cllw_ops USING btree; + +CREATE OPERATOR CLASS eql_v3.ore_cllw_ops + DEFAULT FOR TYPE eql_v3.ore_cllw + USING btree FAMILY eql_v3.ore_cllw_ops AS + OPERATOR 1 < (eql_v3.ore_cllw, eql_v3.ore_cllw), + OPERATOR 2 <= (eql_v3.ore_cllw, eql_v3.ore_cllw), + OPERATOR 3 = (eql_v3.ore_cllw, eql_v3.ore_cllw), + OPERATOR 4 >= (eql_v3.ore_cllw, eql_v3.ore_cllw), + OPERATOR 5 > (eql_v3.ore_cllw, eql_v3.ore_cllw), + FUNCTION 1 eql_v3.compare_ore_cllw_term(eql_v3.ore_cllw, eql_v3.ore_cllw); + +--! @file v3/jsonb/aggregates.sql +--! @brief min / max aggregates over eql_v3.jsonb_entry. +--! +--! SteVec document entries extracted at a selector (`doc -> 'sel'`) order by +--! their CLLW ORE (`oc`) term, so the extremum is picked by comparing +--! `eql_v3.ore_cllw(entry)` rather than the scalar Block-ORE `ord_term` the +--! generated scalar ord aggregates use. Same STRICT + PARALLEL SAFE shape as the +--! generated scalar `min`/`max` so partial/parallel aggregation is available on +--! large GROUP BY workloads. +--! +--! Per the encrypted-domain footgun rules the state functions are +--! `LANGUAGE plpgsql` with the pinned `search_path` — a `LANGUAGE sql` body would +--! be inlinable and the planner could elide it. +--! +--! @note **Only `oc`-carrying entries are orderable.** `eql_v3.ore_cllw(entry)` +--! returns NULL when an entry has no `oc` (CLLW ORE) term — the same entries a +--! `eql_v3.ore_cllw` btree NULL-filters from range scans. The state functions +--! therefore IGNORE `oc`-less entries (they never become or survive as the +--! extremum), so `min`/`max` is well-defined over a mix of `oc`-carrying and +--! `oc`-less entries and is not corrupted by an `oc`-less seed. A naive +--! `ore_cllw(value) < ore_cllw(state)` would be NULL whenever either side +--! lacks `oc`, pinning a wrong (`oc`-less) extremum when the first aggregated +--! row is `oc`-less. An all-`oc`-less input has no orderable extremum and +--! returns the (arbitrary) STRICT seed. + +--! @brief State function for min on eql_v3.jsonb_entry. +--! +--! Keeps whichever orderable entry has the lesser CLLW ORE term. STRICT, so SQL +--! NULL entries are skipped by the aggregate machinery; `oc`-less (non-orderable) +--! entries are skipped explicitly (see the @note on this file). +--! +--! @param state eql_v3.jsonb_entry Running extremum. +--! @param value eql_v3.jsonb_entry Candidate entry. +--! @return eql_v3.jsonb_entry The lesser orderable entry by `ore_cllw`. +CREATE FUNCTION eql_v3.jsonb_entry_min_sfunc( + state eql_v3.jsonb_entry, + value eql_v3.jsonb_entry +) +RETURNS eql_v3.jsonb_entry +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +DECLARE + value_ore eql_v3.ore_cllw := eql_v3.ore_cllw(value); + state_ore eql_v3.ore_cllw := eql_v3.ore_cllw(state); +BEGIN + -- A non-orderable (oc-less) candidate never replaces the running extremum. + IF value_ore IS NULL THEN + RETURN state; + END IF; + -- Adopt the candidate when the running extremum is itself non-orderable + -- (e.g. an oc-less STRICT seed) or strictly greater. + IF state_ore IS NULL OR value_ore < state_ore THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate over eql_v3.jsonb_entry. +--! @param input eql_v3.jsonb_entry +--! @return eql_v3.jsonb_entry The entry with the smallest CLLW ORE term. +CREATE AGGREGATE eql_v3.min(eql_v3.jsonb_entry) ( + sfunc = eql_v3.jsonb_entry_min_sfunc, + stype = eql_v3.jsonb_entry, + combinefunc = eql_v3.jsonb_entry_min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.jsonb_entry. +--! +--! Keeps whichever orderable entry has the greater CLLW ORE term. `oc`-less +--! entries are skipped, mirroring `jsonb_entry_min_sfunc` (see the file @note). +--! +--! @param state eql_v3.jsonb_entry Running extremum. +--! @param value eql_v3.jsonb_entry Candidate entry. +--! @return eql_v3.jsonb_entry The greater orderable entry by `ore_cllw`. +CREATE FUNCTION eql_v3.jsonb_entry_max_sfunc( + state eql_v3.jsonb_entry, + value eql_v3.jsonb_entry +) +RETURNS eql_v3.jsonb_entry +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +DECLARE + value_ore eql_v3.ore_cllw := eql_v3.ore_cllw(value); + state_ore eql_v3.ore_cllw := eql_v3.ore_cllw(state); +BEGIN + -- A non-orderable (oc-less) candidate never replaces the running extremum. + IF value_ore IS NULL THEN + RETURN state; + END IF; + -- Adopt the candidate when the running extremum is itself non-orderable + -- (e.g. an oc-less STRICT seed) or strictly lesser. + IF state_ore IS NULL OR value_ore > state_ore THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate over eql_v3.jsonb_entry. +--! @param input eql_v3.jsonb_entry +--! @return eql_v3.jsonb_entry The entry with the largest CLLW ORE term. +CREATE AGGREGATE eql_v3.max(eql_v3.jsonb_entry) ( + sfunc = eql_v3.jsonb_entry_max_sfunc, + stype = eql_v3.jsonb_entry, + combinefunc = eql_v3.jsonb_entry_max_sfunc, + parallel = safe +); + +--! @file v3/jsonb/operators.sql +--! @brief Operators on eql_v3.json and eql_v3.jsonb_entry. + +------------------------------------------------------------------------------ +-- -> field accessor (returns jsonb_entry) +------------------------------------------------------------------------------ + +--! @brief -> operator with text selector. +--! +--! Returns the sv entry whose `s` equals @p selector, with root `i`/`v` merged +--! in. Inlinable: `WHERE col -> 'sel' = $1` reduces structurally to +--! `eql_v3.eq_term(col -> 'sel') = eql_v3.eq_term($1)` and matches a functional +--! index on `eql_v3.eq_term(col -> 'sel')`. +--! +--! @warning The selector operand MUST carry a known type — a text-typed +--! parameter (`$1`, the Proxy interface) or an explicit cast (`col -> 'sel'::text`). +--! A bare untyped literal (`col -> 'sel'`) resolves to the NATIVE `jsonb -> text` +--! operator and silently returns native jsonb semantics (a root-key lookup, +--! typically NULL), NOT this operator: PostgreSQL reduces the `eql_v3.json` +--! domain to its base type `jsonb` when resolving an unknown-typed RHS, and the +--! native base-type operator wins the exact-match tiebreak. This is intrinsic to +--! the domain type-kind and applies to the native-jsonb blockers too. See +--! the "Typed operands" caveat in docs/reference/json-support.md. +--! +--! @param e eql_v3.json Root encrypted payload. +--! @param selector text Selector hash. +--! @return eql_v3.jsonb_entry Matching entry merged with root meta, or NULL. +CREATE FUNCTION eql_v3."->"(e eql_v3.json, selector text) + RETURNS eql_v3.jsonb_entry + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT ( + eql_v3.meta_data(e) || + jsonb_path_query_first( + e, + '$.sv[*] ? (@.s == $sel)'::jsonpath, + jsonb_build_object('sel', selector) + ) + )::eql_v3.jsonb_entry +$$; + +CREATE OPERATOR ->( + FUNCTION=eql_v3."->", + LEFTARG=eql_v3.json, + RIGHTARG=text +); + +--! @brief -> operator with integer array index (0-based, JSONB convention). +--! @param e eql_v3.json Encrypted sv-array payload. +--! @param selector integer Array index. +--! @return eql_v3.jsonb_entry Matching entry merged with root meta, or NULL. +CREATE FUNCTION eql_v3."->"(e eql_v3.json, selector integer) + RETURNS eql_v3.jsonb_entry + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT CASE + WHEN eql_v3.is_ste_vec_array(e) THEN + -- NOTE: `e::jsonb` makes the native-jsonb traversal explicit. `'sv'` is an + -- unknown-typed literal, so `e -> 'sv'` already flattens `eql_v3.json` to + -- its base type and binds native `jsonb -> text` (see the @warning above) — + -- the custom `->(eql_v3.json, text)` operator does NOT capture a bare + -- untyped literal. The cast documents that intent and guards the `-> selector` + -- (integer) hop from ever resolving to the v3 `->(eql_v3.json, integer)` + -- operator instead of native array access. + (eql_v3.meta_data(e) || (e::jsonb -> 'sv' -> selector))::eql_v3.jsonb_entry + ELSE NULL + END +$$; + +CREATE OPERATOR ->( + FUNCTION=eql_v3."->", + LEFTARG=eql_v3.json, + RIGHTARG=integer +); + +------------------------------------------------------------------------------ +-- ->> field accessor (alias of -> coerced to text) +------------------------------------------------------------------------------ + +--! @brief ->> operator with text selector. Inlinable alias of -> coerced to +--! text. +--! +--! Intentional v2 parity: this serializes the entire matched jsonb_entry +--! object as JSON text. It does not decrypt or return scalar plaintext like +--! native `jsonb ->>`. +--! @param e eql_v3.json Encrypted payload. +--! @param selector text Field selector hash. +--! @return text The matching entry as text. +CREATE FUNCTION eql_v3."->>"(e eql_v3.json, selector text) + RETURNS text + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3."->"(e, selector)::jsonb::text +$$; + +CREATE OPERATOR ->> ( + FUNCTION=eql_v3."->>", + LEFTARG=eql_v3.json, + RIGHTARG=text +); + +--! @brief ->> operator with integer array index. Inlinable alias of +--! ->(json, integer) coerced to text. +--! @param e eql_v3.json Encrypted sv-array payload. +--! @param selector integer Array index. +--! @return text The matching entry as text. +CREATE FUNCTION eql_v3."->>"(e eql_v3.json, selector integer) + RETURNS text + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3."->"(e, selector)::jsonb::text +$$; + +CREATE OPERATOR ->> ( + FUNCTION=eql_v3."->>", + LEFTARG=eql_v3.json, + RIGHTARG=integer +); + +------------------------------------------------------------------------------ +-- @> containment +------------------------------------------------------------------------------ + +--! @brief @> contains operator (document, document). +--! @param a eql_v3.json Container. +--! @param b eql_v3.json Contained value. +--! @return boolean True if a contains b. +--! @see eql_v3.ste_vec_contains +CREATE FUNCTION eql_v3."@>"(a eql_v3.json, b eql_v3.json) +RETURNS boolean +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.ste_vec_contains(a, b) +$$; + +CREATE OPERATOR @>( + FUNCTION=eql_v3."@>", + LEFTARG=eql_v3.json, + RIGHTARG=eql_v3.json +); + +--! @brief @> contains operator with an jsonb_query needle. +--! +--! Inlines to native `jsonb @>` over `eql_v3.to_ste_vec_query(a)::jsonb`, so a +--! functional GIN index on the same expression engages. +--! +--! @param a eql_v3.json Container. +--! @param b eql_v3.jsonb_query Query payload. +--! @return boolean True if a contains b. +CREATE FUNCTION eql_v3."@>"(a eql_v3.json, b eql_v3.jsonb_query) +RETURNS boolean +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.to_ste_vec_query(a)::jsonb @> b::jsonb +$$; + +CREATE OPERATOR @>( + FUNCTION=eql_v3."@>", + LEFTARG=eql_v3.json, + RIGHTARG=eql_v3.jsonb_query +); + +--! @brief @> contains operator with a single jsonb_entry needle. +--! +--! Wraps the entry into a single-element sv array (stripping `c`) and reduces +--! to the same `to_ste_vec_query(a)::jsonb @> needle::jsonb` form. +--! +--! @param a eql_v3.json Container. +--! @param b eql_v3.jsonb_entry Single entry. +--! @return boolean True if a contains an sv entry matching b. +CREATE FUNCTION eql_v3."@>"(a eql_v3.json, b eql_v3.jsonb_entry) +RETURNS boolean +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.to_ste_vec_query(a)::jsonb + @> jsonb_build_object( + 'sv', + jsonb_build_array( + jsonb_strip_nulls( + jsonb_build_object( + 's', b -> 's', + 'hm', b -> 'hm', + 'oc', b -> 'oc' + ) + ) + ) + ) +$$; + +CREATE OPERATOR @>( + FUNCTION=eql_v3."@>", + LEFTARG=eql_v3.json, + RIGHTARG=eql_v3.jsonb_entry +); + +------------------------------------------------------------------------------ +-- <@ contained-by (reverse of @>) +------------------------------------------------------------------------------ + +--! @brief <@ contained-by operator (document, document). +--! @param a eql_v3.json Contained value. +--! @param b eql_v3.json Container. +--! @return boolean True if a is contained by b. +CREATE FUNCTION eql_v3."<@"(a eql_v3.json, b eql_v3.json) +RETURNS boolean +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.ste_vec_contains(b, a) +$$; + +CREATE OPERATOR <@( + FUNCTION=eql_v3."<@", + LEFTARG=eql_v3.json, + RIGHTARG=eql_v3.json +); + +--! @brief <@ contained-by operator with an jsonb_query LHS. +--! @param a eql_v3.jsonb_query Query payload. +--! @param b eql_v3.json Container. +--! @return boolean True if b contains a. +CREATE FUNCTION eql_v3."<@"(a eql_v3.jsonb_query, b eql_v3.json) +RETURNS boolean +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3."@>"(b, a) +$$; + +CREATE OPERATOR <@( + FUNCTION=eql_v3."<@", + LEFTARG=eql_v3.jsonb_query, + RIGHTARG=eql_v3.json +); + +--! @brief <@ contained-by operator with a jsonb_entry LHS. +--! @param a eql_v3.jsonb_entry Single entry. +--! @param b eql_v3.json Container. +--! @return boolean True if b contains a. +CREATE FUNCTION eql_v3."<@"(a eql_v3.jsonb_entry, b eql_v3.json) +RETURNS boolean +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3."@>"(b, a) +$$; + +CREATE OPERATOR <@( + FUNCTION=eql_v3."<@", + LEFTARG=eql_v3.jsonb_entry, + RIGHTARG=eql_v3.json +); + +------------------------------------------------------------------------------ +-- jsonb_entry comparisons +------------------------------------------------------------------------------ + +--! @brief Equality on jsonb_entry via eq_term (hm-or-oc byte equality). +--! @internal +--! @param a eql_v3.jsonb_entry Left operand +--! @param b eql_v3.jsonb_entry Right operand +--! @return boolean True if the entries are equal +CREATE FUNCTION eql_v3.eq(a eql_v3.jsonb_entry, b eql_v3.jsonb_entry) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) +$$; + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.jsonb_entry, + RIGHTARG = eql_v3.jsonb_entry, + COMMUTATOR = =, + NEGATOR = <>, + RESTRICT = eqsel, + JOIN = eqjoinsel +); + +--! @brief Inequality on jsonb_entry via eq_term. +--! @internal +--! @param a eql_v3.jsonb_entry Left operand +--! @param b eql_v3.jsonb_entry Right operand +--! @return boolean True if the entries are not equal +CREATE FUNCTION eql_v3.neq(a eql_v3.jsonb_entry, b eql_v3.jsonb_entry) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) +$$; + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.jsonb_entry, + RIGHTARG = eql_v3.jsonb_entry, + COMMUTATOR = <>, + NEGATOR = =, + RESTRICT = neqsel, + JOIN = neqjoinsel +); + +--! @brief Less-than on jsonb_entry via ore_cllw. +--! @internal +--! @param a eql_v3.jsonb_entry Left operand +--! @param b eql_v3.jsonb_entry Right operand +--! @return boolean True if a is less than b +CREATE FUNCTION eql_v3.lt(a eql_v3.jsonb_entry, b eql_v3.jsonb_entry) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.ore_cllw(a) < eql_v3.ore_cllw(b) +$$; + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.jsonb_entry, + RIGHTARG = eql_v3.jsonb_entry, + COMMUTATOR = >, + NEGATOR = >=, + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel +); + +--! @brief Less-than-or-equal on jsonb_entry via ore_cllw. +--! @internal +--! @param a eql_v3.jsonb_entry Left operand +--! @param b eql_v3.jsonb_entry Right operand +--! @return boolean True if a is less than or equal to b +CREATE FUNCTION eql_v3.lte(a eql_v3.jsonb_entry, b eql_v3.jsonb_entry) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.ore_cllw(a) <= eql_v3.ore_cllw(b) +$$; + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.jsonb_entry, + RIGHTARG = eql_v3.jsonb_entry, + COMMUTATOR = >=, + NEGATOR = >, + RESTRICT = scalarlesel, + JOIN = scalarlejoinsel +); + +--! @brief Greater-than on jsonb_entry via ore_cllw. +--! @internal +--! @param a eql_v3.jsonb_entry Left operand +--! @param b eql_v3.jsonb_entry Right operand +--! @return boolean True if a is greater than b +CREATE FUNCTION eql_v3.gt(a eql_v3.jsonb_entry, b eql_v3.jsonb_entry) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.ore_cllw(a) > eql_v3.ore_cllw(b) +$$; + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.jsonb_entry, + RIGHTARG = eql_v3.jsonb_entry, + COMMUTATOR = <, + NEGATOR = <=, + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel +); + +--! @brief Greater-than-or-equal on jsonb_entry via ore_cllw. +--! @internal +--! @param a eql_v3.jsonb_entry Left operand +--! @param b eql_v3.jsonb_entry Right operand +--! @return boolean True if a is greater than or equal to b +CREATE FUNCTION eql_v3.gte(a eql_v3.jsonb_entry, b eql_v3.jsonb_entry) + RETURNS boolean + LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.ore_cllw(a) >= eql_v3.ore_cllw(b) +$$; + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.jsonb_entry, + RIGHTARG = eql_v3.jsonb_entry, + COMMUTATOR = <=, + NEGATOR = <, + RESTRICT = scalargesel, + JOIN = scalargejoinsel +); + +--! @file v3/jsonb/blockers.sql +--! @brief Native-jsonb firewall for eql_v3.json. +--! +--! eql_v3.json SUPPORTS @> <@ -> ->> (see operators.sql). Comparisons +--! = <> < <= > >= are supported on eql_v3.jsonb_entry only, not on the root +--! document domain. +--! Every OTHER native jsonb operator reachable via domain fallback against the +--! base type jsonb is BLOCKED here so an encrypted column can never silently +--! route to plaintext-jsonb semantics. The blocked set is KNOWN_JSONB_OPERATORS +--! minus the supported ops: ? ?| ?& @? @@ #> #>> - #- ||. +--! +--! Each blocker is LANGUAGE plpgsql (NEVER STRICT — a STRICT blocker would let +--! PostgreSQL skip the body and return NULL on a NULL argument, bypassing the +--! exception) and delegates to the shared eql_v3.encrypted_domain_unsupported_* +--! helpers. Each blocker's RETURNS type matches the native operator it shadows +--! (#> -> jsonb, #>> -> text, - / #- / || -> jsonb; the rest are boolean) so a +--! composed expression resolves and the body raises 'operator not supported', +--! rather than failing earlier with a misleading 'operator does not exist' on a +--! boolean intermediate. The bound operator must resolve before native fallback, +--! so the firewall fires. + +--! @brief Blocker: ? (key/element exists). +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b text Native RHS operand. +--! @return boolean Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_exists(a eql_v3.json, b text) +RETURNS boolean +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.json', '?'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR ? ( + FUNCTION = eql_v3.jsonb_blocked_exists, + LEFTARG = eql_v3.json, + RIGHTARG = text +); + +--! @brief Blocker: ?| (any key exists). +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b text[] Native RHS operand. +--! @return boolean Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_exists_any(a eql_v3.json, b text[]) +RETURNS boolean +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.json', '?|'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3.jsonb_blocked_exists_any, + LEFTARG = eql_v3.json, + RIGHTARG = text[] +); + +--! @brief Blocker: ?& (all keys exist). +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b text[] Native RHS operand. +--! @return boolean Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_exists_all(a eql_v3.json, b text[]) +RETURNS boolean +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.json', '?&'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3.jsonb_blocked_exists_all, + LEFTARG = eql_v3.json, + RIGHTARG = text[] +); + +--! @brief Blocker: @? (jsonpath exists). +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b jsonpath Native RHS operand. +--! @return boolean Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_jsonpath_exists(a eql_v3.json, b jsonpath) +RETURNS boolean +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.json', '@?'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR @? ( + FUNCTION = eql_v3.jsonb_blocked_jsonpath_exists, + LEFTARG = eql_v3.json, + RIGHTARG = jsonpath +); + +--! @brief Blocker: @@ (jsonpath predicate). +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b jsonpath Native RHS operand. +--! @return boolean Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_jsonpath_match(a eql_v3.json, b jsonpath) +RETURNS boolean +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.json', '@@'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3.jsonb_blocked_jsonpath_match, + LEFTARG = eql_v3.json, + RIGHTARG = jsonpath +); + +--! @brief Blocker: #> (path extract, native returns jsonb). +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b text[] Native RHS operand. +--! @return jsonb Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_path_extract(a eql_v3.json, b text[]) +RETURNS jsonb +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_jsonb('eql_v3.json', '#>'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR #> ( + FUNCTION = eql_v3.jsonb_blocked_path_extract, + LEFTARG = eql_v3.json, + RIGHTARG = text[] +); + +--! @brief Blocker: #>> (path extract as text). +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b text[] Native RHS operand. +--! @return text Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_path_extract_text(a eql_v3.json, b text[]) +RETURNS text +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_text('eql_v3.json', '#>>'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3.jsonb_blocked_path_extract_text, + LEFTARG = eql_v3.json, + RIGHTARG = text[] +); + +--! @brief Blocker: - (delete key, text RHS; native returns jsonb). +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b text Native RHS operand. +--! @return jsonb Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_delete_text(a eql_v3.json, b text) +RETURNS jsonb +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_jsonb('eql_v3.json', '-'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR - ( + FUNCTION = eql_v3.jsonb_blocked_delete_text, + LEFTARG = eql_v3.json, + RIGHTARG = text +); + +--! @brief Blocker: - (delete index, integer RHS). +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b integer Native RHS operand. +--! @return jsonb Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_delete_int(a eql_v3.json, b integer) +RETURNS jsonb +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_jsonb('eql_v3.json', '-'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR - ( + FUNCTION = eql_v3.jsonb_blocked_delete_int, + LEFTARG = eql_v3.json, + RIGHTARG = integer +); + +--! @brief Blocker: - (delete keys, text[] RHS). +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b text[] Native RHS operand. +--! @return jsonb Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_delete_array(a eql_v3.json, b text[]) +RETURNS jsonb +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_jsonb('eql_v3.json', '-'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR - ( + FUNCTION = eql_v3.jsonb_blocked_delete_array, + LEFTARG = eql_v3.json, + RIGHTARG = text[] +); + +--! @brief Blocker: #- (delete at path). +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b text[] Native RHS operand. +--! @return jsonb Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_delete_path(a eql_v3.json, b text[]) +RETURNS jsonb +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_jsonb('eql_v3.json', '#-'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR #- ( + FUNCTION = eql_v3.jsonb_blocked_delete_path, + LEFTARG = eql_v3.json, + RIGHTARG = text[] +); + +--! @brief Blocker: || (concatenate, encrypted on the left). +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b jsonb Native RHS operand. +--! @return jsonb Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_concat(a eql_v3.json, b jsonb) +RETURNS jsonb +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_jsonb('eql_v3.json', '||'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR || ( + FUNCTION = eql_v3.jsonb_blocked_concat, + LEFTARG = eql_v3.json, + RIGHTARG = jsonb +); + +--! @brief Blocker: || (concatenate, encrypted on the right). +--! @param a jsonb Native LHS operand. +--! @param b eql_v3.json Right operand (encrypted payload). +--! @return jsonb Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_concat_rhs(a jsonb, b eql_v3.json) +RETURNS jsonb +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_jsonb('eql_v3.json', '||'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR || ( + FUNCTION = eql_v3.jsonb_blocked_concat_rhs, + LEFTARG = jsonb, + RIGHTARG = eql_v3.json +); + +------------------------------------------------------------------------------ +-- Root-document comparison blockers. +------------------------------------------------------------------------------ + +--! @brief Blocker: root eql_v3.json document comparisons. +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b eql_v3.json Right operand (encrypted payload). +--! @return boolean Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_compare_json_json(a eql_v3.json, b eql_v3.json) +RETURNS boolean +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.json', 'comparison'); +END; +$$ LANGUAGE plpgsql; + +--! @brief Blocker: root eql_v3.json-to-jsonb comparisons. +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b jsonb Native RHS operand. +--! @return boolean Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_compare_json_jsonb(a eql_v3.json, b jsonb) +RETURNS boolean +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.json', 'comparison'); +END; +$$ LANGUAGE plpgsql; + +--! @brief Blocker: root jsonb-to-eql_v3.json comparisons. +--! @param a jsonb Native LHS operand. +--! @param b eql_v3.json Right operand (encrypted payload). +--! @return boolean Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_compare_jsonb_json(a jsonb, b eql_v3.json) +RETURNS boolean +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.json', 'comparison'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR = ( + FUNCTION = eql_v3.jsonb_blocked_compare_json_json, + LEFTARG = eql_v3.json, + RIGHTARG = eql_v3.json +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.jsonb_blocked_compare_json_jsonb, + LEFTARG = eql_v3.json, + RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.jsonb_blocked_compare_jsonb_json, + LEFTARG = jsonb, + RIGHTARG = eql_v3.json +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.jsonb_blocked_compare_json_json, + LEFTARG = eql_v3.json, + RIGHTARG = eql_v3.json +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.jsonb_blocked_compare_json_jsonb, + LEFTARG = eql_v3.json, + RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.jsonb_blocked_compare_jsonb_json, + LEFTARG = jsonb, + RIGHTARG = eql_v3.json +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.jsonb_blocked_compare_json_json, + LEFTARG = eql_v3.json, + RIGHTARG = eql_v3.json +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.jsonb_blocked_compare_json_jsonb, + LEFTARG = eql_v3.json, + RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.jsonb_blocked_compare_jsonb_json, + LEFTARG = jsonb, + RIGHTARG = eql_v3.json +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.jsonb_blocked_compare_json_json, + LEFTARG = eql_v3.json, + RIGHTARG = eql_v3.json +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.jsonb_blocked_compare_json_jsonb, + LEFTARG = eql_v3.json, + RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.jsonb_blocked_compare_jsonb_json, + LEFTARG = jsonb, + RIGHTARG = eql_v3.json +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.jsonb_blocked_compare_json_json, + LEFTARG = eql_v3.json, + RIGHTARG = eql_v3.json +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.jsonb_blocked_compare_json_jsonb, + LEFTARG = eql_v3.json, + RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.jsonb_blocked_compare_jsonb_json, + LEFTARG = jsonb, + RIGHTARG = eql_v3.json +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.jsonb_blocked_compare_json_json, + LEFTARG = eql_v3.json, + RIGHTARG = eql_v3.json +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.jsonb_blocked_compare_json_jsonb, + LEFTARG = eql_v3.json, + RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.jsonb_blocked_compare_jsonb_json, + LEFTARG = jsonb, + RIGHTARG = eql_v3.json +); + +------------------------------------------------------------------------------ +-- Mixed jsonb containment blockers. +------------------------------------------------------------------------------ + +--! @brief Blocker: @> with encrypted root document and native jsonb. +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b jsonb Native RHS operand. +--! @return boolean Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_contains_json_jsonb(a eql_v3.json, b jsonb) +RETURNS boolean +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.json', '@>'); +END; +$$ LANGUAGE plpgsql; + +--! @brief Blocker: @> with native jsonb and encrypted root document. +--! @param a jsonb Native LHS operand. +--! @param b eql_v3.json Right operand (encrypted payload). +--! @return boolean Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_contains_jsonb_json(a jsonb, b eql_v3.json) +RETURNS boolean +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.json', '@>'); +END; +$$ LANGUAGE plpgsql; + +--! @brief Blocker: <@ with encrypted root document and native jsonb. +--! @param a eql_v3.json Left operand (encrypted payload). +--! @param b jsonb Native RHS operand. +--! @return boolean Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_contained_json_jsonb(a eql_v3.json, b jsonb) +RETURNS boolean +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.json', '<@'); +END; +$$ LANGUAGE plpgsql; + +--! @brief Blocker: <@ with native jsonb and encrypted root document. +--! @param a jsonb Native LHS operand. +--! @param b eql_v3.json Right operand (encrypted payload). +--! @return boolean Never returns; always raises 'operator not supported'. +CREATE FUNCTION eql_v3.jsonb_blocked_contained_jsonb_json(a jsonb, b eql_v3.json) +RETURNS boolean +IMMUTABLE PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.json', '<@'); +END; +$$ LANGUAGE plpgsql; + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.jsonb_blocked_contains_json_jsonb, + LEFTARG = eql_v3.json, + RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.jsonb_blocked_contains_jsonb_json, + LEFTARG = jsonb, + RIGHTARG = eql_v3.json +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.jsonb_blocked_contained_json_jsonb, + LEFTARG = eql_v3.json, + RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.jsonb_blocked_contained_jsonb_json, + LEFTARG = jsonb, + RIGHTARG = eql_v3.json +); +--! @file pin_search_path_v3.sql +--! @brief Post-install: pin search_path on every eql_v3.* function. +--! +--! Appended verbatim by `tasks/build.sh` to the end of the v3-only release +--! artifact, AFTER all src/v3/**/*.sql files have been concatenated. It lives +--! outside src/ so it stays out of the dependency graph. +--! +--! Iterates over functions in the `eql_v3` schema and applies a fixed +--! `search_path` via `ALTER FUNCTION ... SET search_path = ...`, satisfying +--! Supabase splinter's `function_search_path_mutable` lint. +--! +--! @note A SET clause disables SQL-function inlining. The inline-critical SEM +--! helpers (ore_block_256_*, ore_cllw_*, ore_cllw/has_ore_cllw, +--! hmac_256, bloom_filter over jsonb) and the encrypted-domain family +--! (recognised structurally) are deliberately left unpinned. +--! @see tasks/test/splinter.sh +--! @see tasks/build.sh + +DO $$ +DECLARE + fn_oid oid; + inline_critical_oids oid[]; + jsonb_oid oid; +BEGIN + SELECT t.oid INTO jsonb_oid + FROM pg_catalog.pg_type t + JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace + WHERE n.nspname = 'pg_catalog' AND t.typname = 'jsonb'; + + IF jsonb_oid IS NULL THEN + RAISE EXCEPTION 'pin_search_path_v3: type pg_catalog.jsonb not found'; + END IF; + + -- eql_v3 SEM index-term functions that must stay inlinable for + -- functional-index matching (no SET, IMMUTABLE). Mirrors the eql_v3 clause + -- in the legacy combined pin_search_path.sql. + SELECT pg_catalog.array_agg(p.oid) INTO inline_critical_oids + FROM pg_catalog.pg_proc p + JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace + WHERE n.nspname = 'eql_v3' + AND ( + (p.pronargs = 2 + AND p.proname IN ('ore_block_256_eq', 'ore_block_256_neq', + 'ore_block_256_lt', 'ore_block_256_lte', + 'ore_block_256_gt', 'ore_block_256_gte')) + OR (p.pronargs = 2 + AND p.proname IN ('ore_cllw_eq', 'ore_cllw_neq', + 'ore_cllw_lt', 'ore_cllw_lte', + 'ore_cllw_gt', 'ore_cllw_gte')) + OR (p.pronargs = 1 + AND p.proname IN ('ore_cllw', 'has_ore_cllw') + AND p.proargtypes[0] = jsonb_oid) + OR (p.pronargs = 1 + AND p.proname = 'hmac_256' + AND p.proargtypes[0] = jsonb_oid) + OR (p.pronargs = 1 + AND p.proname = 'bloom_filter' + AND p.proargtypes[0] = jsonb_oid) + ); + + FOR fn_oid IN + SELECT p.oid + FROM pg_catalog.pg_proc p + JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace + WHERE n.nspname = 'eql_v3' + AND p.prokind IN ('f', 'w') + AND NOT EXISTS ( + SELECT 1 FROM pg_catalog.unnest(coalesce(p.proconfig, '{}'::text[])) c + WHERE c LIKE 'search_path=%' + ) + AND NOT (p.oid = ANY (coalesce(inline_critical_oids, '{}'::oid[]))) + -- Encrypted-domain family — structural skip: LANGUAGE sql, IMMUTABLE, + -- taking >=1 argument typed as a jsonb-backed DOMAIN in eql_v3. + AND NOT ( + p.prolang = (SELECT l.oid FROM pg_catalog.pg_language l + WHERE l.lanname = 'sql') + AND p.provolatile = 'i' + AND EXISTS ( + SELECT 1 + FROM pg_catalog.unnest(p.proargtypes::oid[]) AS arg(typ) + 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 dt.typbasetype = jsonb_oid + AND dn.nspname = 'eql_v3' + ) + ) + -- Comment-marker fallback for hand-written inline-critical extension + -- functions that take no domain argument. + AND NOT EXISTS ( + SELECT 1 FROM pg_catalog.pg_description d + WHERE d.objoid = p.oid + AND d.classoid = 'pg_catalog.pg_proc'::regclass + AND d.description LIKE 'eql-inline-critical%' + ) + LOOP + EXECUTE pg_catalog.format( + 'ALTER FUNCTION %s SET search_path = pg_catalog, extensions, public', + fn_oid::regprocedure + ); + END LOOP; +END $$; diff --git a/packages/stack/__tests__/helpers/eql-v3.ts b/packages/stack/__tests__/helpers/eql-v3.ts new file mode 100644 index 00000000..ab9e4f57 --- /dev/null +++ b/packages/stack/__tests__/helpers/eql-v3.ts @@ -0,0 +1,60 @@ +import { readFile } from 'node:fs/promises' +import { dirname, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' +import type postgres from 'postgres' + +const EQL_V3_ADVISORY_LOCK_ID = 3_733_003 + +const helperDir = dirname(fileURLToPath(import.meta.url)) +const eqlV3SqlPath = resolve( + helperDir, + '../fixtures/eql-v3/cipherstash-encrypt-v3.sql', +) + +// The sentinel must be a type that exists ONLY in the currently vendored +// bundle, so a database still carrying an older EQL v3 install is detected as +// stale and reinstalled (the bundle's leading DROP SCHEMA … CASCADE replaces +// the old install wholesale). eql_v3.timestamp is new in the current bundle +// (the timestamptz → timestamp rename, encrypt-query-language@2e64ca73); the +// previous sentinel, eql_v3.text_search, exists in both generations and would +// leave a stale install in place. +async function hasCurrentEqlV3(sql: postgres.Sql): Promise<boolean> { + const [row] = await sql<{ installed: boolean }[]>` + SELECT to_regtype('eql_v3.timestamp') IS NOT NULL AS installed + ` + return row?.installed ?? false +} + +/** + * Install the generated EQL v3 SQL bundle only when the target database does + * not already expose the current bundle's sentinel type (see hasCurrentEqlV3). + * + * The bundle starts with DROP SCHEMA IF EXISTS eql_v3 CASCADE, so callers must + * never run it unconditionally against a shared test database. + */ +export async function installEqlV3IfNeeded(sql: postgres.Sql): Promise<void> { + // Advisory locks are session-scoped, so the whole check/install/unlock flow + // must run on a single reserved connection. Issuing the lock/unlock via the + // pool can land them on different pooled backends — allowing an install race + // and unlocking a backend that never held the lock. + const reserved = await sql.reserve() + + try { + await reserved`SELECT pg_advisory_lock(${EQL_V3_ADVISORY_LOCK_ID})` + + try { + if (await hasCurrentEqlV3(reserved)) return + + const eqlV3Sql = await readFile(eqlV3SqlPath, 'utf8') + await reserved.unsafe(eqlV3Sql) + + if (!(await hasCurrentEqlV3(reserved))) { + throw new Error('EQL v3 installation did not create eql_v3.timestamp') + } + } finally { + await reserved`SELECT pg_advisory_unlock(${EQL_V3_ADVISORY_LOCK_ID})` + } + } finally { + reserved.release() + } +} diff --git a/packages/stack/__tests__/helpers/live-gate.ts b/packages/stack/__tests__/helpers/live-gate.ts new file mode 100644 index 00000000..8ad3675e --- /dev/null +++ b/packages/stack/__tests__/helpers/live-gate.ts @@ -0,0 +1,28 @@ +import { describe } from 'vitest' + +/** + * Shared env gates for the live (network-touching) suites. Previously each + * live suite re-declared these; one definition keeps the credential list — + * and therefore what "live" means — from drifting between files. + * + * Callers must `import 'dotenv/config'` BEFORE importing this module (all + * live suites already do, as their first import) so the env is populated + * when these are evaluated. + */ + +/** True when live CipherStash (ZeroKMS/CTS) credentials are configured. */ +export const LIVE_CIPHERSTASH_ENABLED = Boolean( + process.env.CS_WORKSPACE_CRN && + process.env.CS_CLIENT_ID && + process.env.CS_CLIENT_KEY && + process.env.CS_CLIENT_ACCESS_KEY, +) + +/** True when live credentials AND a Postgres `DATABASE_URL` are configured. */ +export const LIVE_EQL_V3_PG_ENABLED = Boolean( + process.env.DATABASE_URL && LIVE_CIPHERSTASH_ENABLED, +) + +export const describeLive = LIVE_CIPHERSTASH_ENABLED ? describe : describe.skip + +export const describeLivePg = LIVE_EQL_V3_PG_ENABLED ? describe : describe.skip diff --git a/packages/stack/__tests__/helpers/stub-auth-wasm-inline.ts b/packages/stack/__tests__/helpers/stub-auth-wasm-inline.ts new file mode 100644 index 00000000..23711105 --- /dev/null +++ b/packages/stack/__tests__/helpers/stub-auth-wasm-inline.ts @@ -0,0 +1,23 @@ +/** + * Test stub for `@cipherstash/auth/wasm-inline`. + * + * See {@link file://./stub-protect-ffi-wasm-inline.ts} — the `/wasm-inline` + * subpath is not exported by the installed `@cipherstash/auth`, so this stub + * lets Vitest load `src/wasm-inline` for pure-helper unit tests. Aliased in via + * `vitest.config.ts`. + */ +export const AccessKeyStrategy = { + create: (): never => { + throw new Error( + '[test stub]: auth/wasm-inline AccessKeyStrategy.create not implemented', + ) + }, +} + +export const OidcFederationStrategy = { + create: (): never => { + throw new Error( + '[test stub]: auth/wasm-inline OidcFederationStrategy.create not implemented', + ) + }, +} diff --git a/packages/stack/__tests__/helpers/stub-protect-ffi-wasm-inline.ts b/packages/stack/__tests__/helpers/stub-protect-ffi-wasm-inline.ts new file mode 100644 index 00000000..e26d34df --- /dev/null +++ b/packages/stack/__tests__/helpers/stub-protect-ffi-wasm-inline.ts @@ -0,0 +1,29 @@ +/** + * Test stub for `@cipherstash/protect-ffi/wasm-inline`. + * + * The installed `@cipherstash/protect-ffi` only exports `.` — the `/wasm-inline` + * subpath does not exist, so Vitest cannot resolve `src/wasm-inline` (which + * imports it). These no-op stubs let the unit tests that only exercise pure + * helpers (`getColumnName`, `normalizeCastAs`) load the module. Aliased in via + * `vitest.config.ts`. Any test that actually needs WASM behaviour must mock it + * explicitly (see `wasm-inline-column-name.test.ts`). + */ +export const decrypt = (): never => { + throw new Error( + '[test stub]: protect-ffi/wasm-inline decrypt not implemented', + ) +} + +export const encrypt = (): never => { + throw new Error( + '[test stub]: protect-ffi/wasm-inline encrypt not implemented', + ) +} + +export const isEncrypted = (): boolean => false + +export const newClient = (): never => { + throw new Error( + '[test stub]: protect-ffi/wasm-inline newClient not implemented', + ) +} diff --git a/packages/stack/__tests__/live-gate-required.test.ts b/packages/stack/__tests__/live-gate-required.test.ts new file mode 100644 index 00000000..c7211b62 --- /dev/null +++ b/packages/stack/__tests__/live-gate-required.test.ts @@ -0,0 +1,30 @@ +/** + * Guard against silent "live green": the live matrices (`matrix-live*`, + * `operators-*-live-pg`, `matrix-boundary-live-pg`, `matrix-identity-live`) + * all `describe.skip` when credentials are absent — so a CI job that lost its + * `DATABASE_URL` / `CS_*` secrets would still pass, having run NONE of them. + * + * These guards turn that into a hard failure ONLY when the environment opts in: + * - `REQUIRE_LIVE` -> live CipherStash suites must be enabled + * - `REQUIRE_LIVE_PG` -> live Postgres suites must be enabled + * Set both in CI (see `.github/workflows/tests.yml`). Locally, with neither set, + * these are no-ops, so a dev machine without creds still runs green. + */ +import 'dotenv/config' +import { describe, expect, it } from 'vitest' +import { + LIVE_CIPHERSTASH_ENABLED, + LIVE_EQL_V3_PG_ENABLED, +} from './helpers/live-gate' + +describe('live-suite skip guard', () => { + it('live CipherStash suites are enabled when REQUIRE_LIVE is set', () => { + if (!process.env.REQUIRE_LIVE) return + expect(LIVE_CIPHERSTASH_ENABLED).toBe(true) + }) + + it('live Postgres suites are enabled when REQUIRE_LIVE_PG is set', () => { + if (!process.env.REQUIRE_LIVE_PG) return + expect(LIVE_EQL_V3_PG_ENABLED).toBe(true) + }) +}) diff --git a/packages/stack/__tests__/model-column-mapping.test.ts b/packages/stack/__tests__/model-column-mapping.test.ts new file mode 100644 index 00000000..55c19002 --- /dev/null +++ b/packages/stack/__tests__/model-column-mapping.test.ts @@ -0,0 +1,39 @@ +import { describe, expect, it } from 'vitest' +import { resolveEncryptColumnMap } from '@/encryption/helpers/model-helpers' +import { encryptedTable, types } from '@/eql/v3' +import { encryptedColumn, encryptedTable as encryptedTableV2 } from '@/schema' + +// `resolveEncryptColumnMap` is how the model path reconciles the two keyings a +// table can use: models are matched by JS property name, but the FFI / encrypt +// config is addressed by DB column name. A mismatch here is a real data-leak +// bug — a schema field that fails to match is passed through as plaintext. +describe('resolveEncryptColumnMap', () => { + it('v3: matches by JS property, addresses the FFI by DB name', () => { + const users = encryptedTable('users', { + createdOn: types.Date('created_on'), + notes: types.Text('notes'), // property == name + }) + + const { columnPaths, toColumnName } = resolveEncryptColumnMap(users) + + // Fields are matched against JS property names (what a model is keyed by)… + expect(columnPaths.sort()).toEqual(['createdOn', 'notes']) + // …and each maps to the DB name the config/FFI is keyed by. + expect(toColumnName('createdOn')).toBe('created_on') + expect(toColumnName('notes')).toBe('notes') + }) + + it('v2: no property→DB map, so both keying schemes are the JS property', () => { + // v2 `build()` keys columns by the JS property, so matching and addressing + // use that same key — the resolver must fall back to identity and leave the + // v2 model path unchanged. + const legacy = encryptedTableV2('legacy', { + fooBar: encryptedColumn('foo_bar'), + }) + + const { columnPaths, toColumnName } = resolveEncryptColumnMap(legacy) + + expect(columnPaths).toEqual(['fooBar']) + expect(toColumnName('fooBar')).toBe('fooBar') + }) +}) diff --git a/packages/stack/__tests__/schema-v3-client.test.ts b/packages/stack/__tests__/schema-v3-client.test.ts new file mode 100644 index 00000000..950a53f0 --- /dev/null +++ b/packages/stack/__tests__/schema-v3-client.test.ts @@ -0,0 +1,252 @@ +import 'dotenv/config' +import { beforeAll, expect, it } from 'vitest' +import type { EncryptionClient } from '@/encryption' +import { typedClient } from '@/encryption/v3' +import { encryptedTable, types } from '@/eql/v3' +import { Encryption } from '@/index' +import { unwrapResult } from './fixtures' +import { describeLive } from './helpers/live-gate' + +const users = encryptedTable('schema_v3_client_users', { + email: types.TextSearch('email'), + age: types.IntegerOrd('age'), + nickname: types.TextEq('nickname'), + body: types.TextMatch('body'), + notes: types.Text('notes'), + active: types.Boolean('active'), + // camelCase JS property → snake_case DB name on purpose: the model path must + // match models by JS property (`createdOn`) yet address the FFI/config by DB + // name (`created_on`). The round-trip tests below exercise that mapping. + createdOn: types.Date('created_on'), + occurredAt: types.Timestamp('occurred_at'), +}) + +describeLive('eql_v3 client integration', () => { + let protectClient: EncryptionClient + + beforeAll(async () => { + protectClient = await Encryption({ schemas: [users] }) + }) + + it('encrypts and decrypts a text_search column', async () => { + const encrypted = unwrapResult( + await protectClient.encrypt('ada@example.com', { + table: users, + column: users.email, + }), + ) + + expect(encrypted).toMatchObject({ + i: { t: 'schema_v3_client_users', c: 'email' }, + v: 2, + }) + expect(encrypted).toHaveProperty('c') + expect(encrypted).toHaveProperty('hm') + expect(encrypted).toHaveProperty('bf') + expect(encrypted).toHaveProperty('ob') + + const decrypted = unwrapResult(await protectClient.decrypt(encrypted)) + expect(decrypted).toBe('ada@example.com') + }, 30000) + + it('auto-infers equality query terms for text_search columns', async () => { + const queryTerm = unwrapResult( + await protectClient.encryptQuery('ada@example.com', { + table: users, + column: users.email, + }), + ) + + expect(queryTerm).toMatchObject({ + i: { t: 'schema_v3_client_users', c: 'email' }, + v: 2, + }) + expect(queryTerm).toHaveProperty('hm') + expect(queryTerm).not.toHaveProperty('c') + }, 30000) + + it('encrypts explicit freeTextSearch and orderAndRange query terms', async () => { + const matchTerm = unwrapResult( + await protectClient.encryptQuery('Ada Lovelace', { + table: users, + column: users.email, + queryType: 'freeTextSearch', + }), + ) + + const orderTerm = unwrapResult( + await protectClient.encryptQuery('ada@example.com', { + table: users, + column: users.email, + queryType: 'orderAndRange', + }), + ) + + expect(matchTerm).toHaveProperty('bf') + expect(matchTerm).not.toHaveProperty('c') + expect(orderTerm).toHaveProperty('ob') + expect(orderTerm).not.toHaveProperty('c') + }, 30000) + + it('encrypts and decrypts storage-only v3 columns', async () => { + const encryptedText = unwrapResult( + await protectClient.encrypt('private note', { + table: users, + column: users.notes, + }), + ) + expect(encryptedText).toMatchObject({ + i: { t: 'schema_v3_client_users', c: 'notes' }, + v: 2, + }) + expect(encryptedText).toHaveProperty('c') + expect(encryptedText).not.toHaveProperty('hm') + expect(encryptedText).not.toHaveProperty('bf') + expect(encryptedText).not.toHaveProperty('ob') + expect(unwrapResult(await protectClient.decrypt(encryptedText))).toBe( + 'private note', + ) + + const encryptedBoolean = unwrapResult( + await protectClient.encrypt(true, { + table: users, + column: users.active, + }), + ) + expect(encryptedBoolean).toHaveProperty('c') + expect(unwrapResult(await protectClient.decrypt(encryptedBoolean))).toBe( + true, + ) + }, 30000) + + it('encrypts equality and order query terms for typed v3 columns', async () => { + const equalityTerm = unwrapResult( + await protectClient.encryptQuery('ada', { + table: users, + column: users.nickname, + }), + ) + expect(equalityTerm).toHaveProperty('hm') + expect(equalityTerm).not.toHaveProperty('c') + + const orderTerm = unwrapResult( + await protectClient.encryptQuery(37, { + table: users, + column: users.age, + queryType: 'orderAndRange', + }), + ) + expect(orderTerm).toHaveProperty('ob') + expect(orderTerm).not.toHaveProperty('c') + }, 30000) + + it('encrypts free-text terms for text_match columns', async () => { + const encrypted = unwrapResult( + await protectClient.encrypt('Ada Lovelace wrote notes', { + table: users, + column: users.body, + }), + ) + expect(encrypted).toHaveProperty('c') + expect(encrypted).toHaveProperty('bf') + expect(encrypted).not.toHaveProperty('hm') + expect(encrypted).not.toHaveProperty('ob') + + const matchTerm = unwrapResult( + await protectClient.encryptQuery('Lovelace', { + table: users, + column: users.body, + queryType: 'freeTextSearch', + }), + ) + expect(matchTerm).toHaveProperty('bf') + expect(matchTerm).not.toHaveProperty('c') + }, 30000) + + // int8 (bigint) storage domains are omitted from the v3 SDK until the native + // protect-ffi supports lossless bigint round-tripping — a `bigint` fails JSON + // serialization and a `string` is rejected for a `big_int` column. Re-add a + // round-trip test alongside the domain builders when the FFI lands. + + // A `date` domain decrypts to an ISO 8601 string from the native FFI, so the + // single-value `decrypt` path returns a string (a lone ciphertext carries no + // column context). The typed client's `decryptModel` reconstructs a real + // `Date` from the encrypt-config `cast_as` (`reconstructRow`), keyed by the + // JS property (`createdOn`) even though the DB column is `created_on`. + it('round-trips a representative date storage domain via decryptModel', async () => { + const typed = typedClient(protectClient, users) + // Zero milliseconds so the FFI dropping sub-second precision (`...00Z` vs + // `...000Z`) does not perturb the reconstructed instant. + const day = new Date('2026-07-01T00:00:00.000Z') + + // Encrypt via the single-value path (the proven route for a `Date` domain), + // then decrypt through the model path so `reconstructRow` rebuilds a `Date` + // from the encrypt-config `cast_as`. + const dateEncrypted = unwrapResult( + await protectClient.encrypt(day, { + table: users, + column: users.createdOn, + }), + ) + // Guard against a false pass: the value must be an actual ciphertext, not a + // plaintext `Date` that would trivially satisfy the assertions below. + expect(dateEncrypted).toHaveProperty('c') + + const decrypted = unwrapResult( + await typed.decryptModel({ createdOn: dateEncrypted }, users), + ) + expect(decrypted.createdOn).toBeInstanceOf(Date) + expect(decrypted.createdOn).toEqual(day) + }, 30000) + + // Regression: a camelCase JS property mapping to a snake_case DB column + // (`nickname` is name==key, but `createdOn`→`created_on` is not) must be + // ENCRYPTED by the model path — not silently passed through as plaintext + // because the field key (`createdOn`) fails to match the DB-keyed config. + it('encrypts a property-vs-DB-name column through encryptModel (no plaintext leak)', async () => { + const typed = typedClient(protectClient, users) + const day = new Date('2026-07-01T00:00:00.000Z') + + const encrypted = unwrapResult( + await typed.encryptModel({ createdOn: day, notes: 'hello' }, users), + ) + // The schema field must become a ciphertext (has `c`), NOT remain a Date. + expect(encrypted.createdOn).not.toBeInstanceOf(Date) + expect(encrypted.createdOn).toHaveProperty('c') + expect(encrypted.notes).toHaveProperty('c') + + const decrypted = unwrapResult(await typed.decryptModel(encrypted, users)) + expect(decrypted.createdOn).toBeInstanceOf(Date) + expect(decrypted.createdOn).toEqual(day) + expect(decrypted.notes).toBe('hello') + }, 30000) + + // Hygiene: `occurredAt` (a timestamp column, camelCase property → + // snake_case DB name `occurred_at`) was declared in the test table but never + // asserted. Give it a real round-trip through the model path, complementing + // the `createdOn` date case above. (`matrix-live.test.ts` is the canonical + // generic coverage for all timestamp tiers; this pins the named column.) + // + // Time-of-day preservation: every `timestamp` domain now sets + // `cast_as: 'timestamp'` (distinct from `'date'`), so the native FFI keeps the + // full instant instead of truncating to midnight. This test pins that — a + // ms-zeroed `12:34:56` value must round-trip exactly. (Was skipped while every + // timestamp domain wrongly set `cast_as: 'date'`; re-enabled with that fix.) + it('round-trips a timestamp occurredAt column through the model path', async () => { + const typed = typedClient(protectClient, users) + // Zero milliseconds: the FFI drops sub-second precision, so a ms-bearing + // instant would perturb the reconstructed value. + const moment = new Date('2026-07-01T12:34:56.000Z') + + const encrypted = unwrapResult( + await typed.encryptModel({ occurredAt: moment, notes: 'seen' }, users), + ) + // Must become a ciphertext, not remain a Date (no plaintext passthrough). + expect(encrypted.occurredAt).not.toBeInstanceOf(Date) + expect(encrypted.occurredAt).toHaveProperty('c') + + const decrypted = unwrapResult(await typed.decryptModel(encrypted, users)) + expect(decrypted.occurredAt).toBeInstanceOf(Date) + expect(decrypted.occurredAt).toEqual(moment) + }, 30000) +}) diff --git a/packages/stack/__tests__/schema-v3-pg.test.ts b/packages/stack/__tests__/schema-v3-pg.test.ts new file mode 100644 index 00000000..49799085 --- /dev/null +++ b/packages/stack/__tests__/schema-v3-pg.test.ts @@ -0,0 +1,390 @@ +import 'dotenv/config' +import postgres from 'postgres' +import { afterAll, beforeAll, beforeEach, expect, it } from 'vitest' +import type { EncryptionClient } from '@/encryption' +import { encryptedTable, types } from '@/eql/v3' +import { Encryption } from '@/index' +import type { Encrypted } from '@/types' +import { unwrapResult } from './fixtures' +import { installEqlV3IfNeeded } from './helpers/eql-v3' +import { describeLivePg, LIVE_EQL_V3_PG_ENABLED } from './helpers/live-gate' + +const databaseUrl = process.env.DATABASE_URL +const sql = LIVE_EQL_V3_PG_ENABLED + ? postgres(databaseUrl as string, { prepare: false }) + : (undefined as unknown as postgres.Sql) + +const table = encryptedTable('protect_ci_v3_text_search', { + email: types.TextSearch('email'), +}) + +const typedTable = encryptedTable('protect_ci_v3_typed_domains', { + age: types.IntegerOrd('age'), + nickname: types.TextEq('nickname'), + active: types.Boolean('active'), +}) + +const TEST_RUN_ID = `test-run-${Date.now()}-${Math.random().toString(36).slice(2, 8)}` + +type InsertedRow = { + id: number + email: unknown + label: string +} + +type EncryptionPayload = postgres.JSONValue + +let protectClient: EncryptionClient + +async function encryptValue(value: string): Promise<EncryptionPayload> { + return unwrapResult( + await protectClient.encrypt(value, { + table, + column: table.email, + }), + ) as EncryptionPayload +} + +async function encryptQueryTerm( + value: string, + queryType?: 'equality' | 'freeTextSearch' | 'orderAndRange', +): Promise<EncryptionPayload> { + return unwrapResult( + await protectClient.encryptQuery(value, { + table, + column: table.email, + queryType, + }), + ) as EncryptionPayload +} + +async function insertRow(label: string, email: string): Promise<number> { + const encrypted = await encryptValue(email) + + const [inserted] = await sql<{ id: number }[]>` + INSERT INTO protect_ci_v3_text_search (email, label, test_run_id) + VALUES (${sql.json(encrypted)}::eql_v3.text_search, ${label}, ${TEST_RUN_ID}) + RETURNING id + ` + + return inserted.id +} + +async function decryptRow(row: InsertedRow): Promise<string> { + const decrypted = unwrapResult( + await protectClient.decrypt(row.email as Encrypted), + ) + expect(typeof decrypted).toBe('string') + return decrypted as string +} + +async function seedRows(): Promise<Record<string, number>> { + const rows = { + ada: await insertRow('ada', 'ada@example.com'), + grace: await insertRow('grace', 'grace@example.com'), + alan: await insertRow('alan', 'alan@example.net'), + zora: await insertRow('zora', 'zora@example.org'), + } + + return rows +} + +beforeAll(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + + await installEqlV3IfNeeded(sql) + protectClient = await Encryption({ schemas: [table, typedTable] }) + + await sql` + CREATE TABLE IF NOT EXISTS protect_ci_v3_text_search ( + id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + email eql_v3.text_search NOT NULL, + label TEXT NOT NULL, + test_run_id TEXT NOT NULL + ) + ` + + await sql` + CREATE TABLE IF NOT EXISTS protect_ci_v3_typed_domains ( + id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + age eql_v3.integer_ord NOT NULL, + nickname eql_v3.text_eq NOT NULL, + active eql_v3.bool NOT NULL, + test_run_id TEXT NOT NULL + ) + ` +}, 30000) + +beforeEach(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + + await sql` + DELETE FROM protect_ci_v3_text_search + WHERE test_run_id = ${TEST_RUN_ID} + ` + await sql` + DELETE FROM protect_ci_v3_typed_domains + WHERE test_run_id = ${TEST_RUN_ID} + ` +}, 30000) + +afterAll(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + + await sql` + DELETE FROM protect_ci_v3_text_search + WHERE test_run_id = ${TEST_RUN_ID} + ` + await sql` + DELETE FROM protect_ci_v3_typed_domains + WHERE test_run_id = ${TEST_RUN_ID} + ` + await sql.end() +}, 30000) + +describeLivePg('eql_v3 text_search postgres integration', () => { + it('round-trips an encrypted value through an eql_v3.text_search column', async () => { + const id = await insertRow('roundtrip', 'roundtrip@example.com') + + const [row] = await sql<InsertedRow[]>` + SELECT id, email::jsonb AS email, label + FROM protect_ci_v3_text_search + WHERE id = ${id} + ` + + expect(row).toBeDefined() + await expect(decryptRow(row)).resolves.toBe('roundtrip@example.com') + }, 30000) + + it('queries equality terms with eql_v3.eq_term and eql_v3.hmac_256', async () => { + const ids = await seedRows() + const equalityTerm = await encryptQueryTerm('grace@example.com', 'equality') + + const rows = await sql<InsertedRow[]>` + SELECT id, email::jsonb AS email, label + FROM protect_ci_v3_text_search + WHERE test_run_id = ${TEST_RUN_ID} + AND eql_v3.eq_term(email) = eql_v3.hmac_256(${sql.json(equalityTerm)}::jsonb) + ORDER BY id + ` + + expect(rows.map((row) => row.id)).toEqual([ids.grace]) + await expect(decryptRow(rows[0])).resolves.toBe('grace@example.com') + }, 30000) + + it('queries free-text terms with eql_v3.match_term and eql_v3.bloom_filter', async () => { + await seedRows() + const matchTerm = await encryptQueryTerm('example.com', 'freeTextSearch') + + const rows = await sql<InsertedRow[]>` + SELECT id, email::jsonb AS email, label + FROM protect_ci_v3_text_search + WHERE test_run_id = ${TEST_RUN_ID} + AND eql_v3.match_term(email) @> eql_v3.bloom_filter(${sql.json(matchTerm)}::jsonb) + ORDER BY label + ` + + expect(rows.map((row) => row.label)).toEqual(['ada', 'grace']) + }, 30000) + + it('queries range terms with eql_v3.ord_term and eql_v3.ore_block_256', async () => { + await seedRows() + const lower = await encryptQueryTerm('grace@example.com', 'orderAndRange') + const upper = await encryptQueryTerm('zora@example.org', 'orderAndRange') + + const rows = await sql<InsertedRow[]>` + SELECT id, email::jsonb AS email, label + FROM protect_ci_v3_text_search + WHERE test_run_id = ${TEST_RUN_ID} + AND eql_v3.ord_term(email) >= eql_v3.ore_block_256(${sql.json(lower)}::jsonb) + AND eql_v3.ord_term(email) <= eql_v3.ore_block_256(${sql.json(upper)}::jsonb) + ORDER BY eql_v3.ord_term(email) + ` + + expect(rows.map((row) => row.label)).toEqual(['grace', 'zora']) + }, 30000) + + it('creates functional indexes for equality, match, and order terms', async () => { + await sql` + CREATE INDEX IF NOT EXISTS protect_ci_v3_text_search_email_eq_idx + ON protect_ci_v3_text_search USING btree (eql_v3.eq_term(email)) + ` + await sql` + CREATE INDEX IF NOT EXISTS protect_ci_v3_text_search_email_match_idx + ON protect_ci_v3_text_search USING gin (eql_v3.match_term(email)) + ` + await sql` + CREATE INDEX IF NOT EXISTS protect_ci_v3_text_search_email_ord_idx + ON protect_ci_v3_text_search USING btree (eql_v3.ord_term(email)) + ` + + const indexes = await sql<{ indexname: string; indexdef: string }[]>` + SELECT indexname, indexdef + FROM pg_indexes + WHERE schemaname = 'public' + AND tablename = 'protect_ci_v3_text_search' + AND indexname IN ( + 'protect_ci_v3_text_search_email_eq_idx', + 'protect_ci_v3_text_search_email_match_idx', + 'protect_ci_v3_text_search_email_ord_idx' + ) + ` + + expect(indexes).toHaveLength(3) + expect(indexes.map((idx) => idx.indexdef).join('\n')).toContain( + 'eql_v3.eq_term', + ) + expect(indexes.map((idx) => idx.indexdef).join('\n')).toContain( + 'eql_v3.match_term', + ) + expect(indexes.map((idx) => idx.indexdef).join('\n')).toContain( + 'eql_v3.ord_term', + ) + }, 30000) + + it('rejects query-only payloads cast as eql_v3.text_search values', async () => { + const equalityTerm = await encryptQueryTerm('ada@example.com', 'equality') + + await expect( + sql` + INSERT INTO protect_ci_v3_text_search (email, label, test_run_id) + VALUES ( + ${sql.json(equalityTerm)}::eql_v3.text_search, + 'query-only', + ${TEST_RUN_ID} + ) + `, + ).rejects.toThrow() + }, 30000) + + it('round-trips and queries representative typed v3 domains', async () => { + const age = unwrapResult( + await protectClient.encrypt(37, { + table: typedTable, + column: typedTable.age, + }), + ) + const nickname = unwrapResult( + await protectClient.encrypt('ada', { + table: typedTable, + column: typedTable.nickname, + }), + ) + const active = unwrapResult( + await protectClient.encrypt(true, { + table: typedTable, + column: typedTable.active, + }), + ) + + const [inserted] = await sql<{ id: number }[]>` + INSERT INTO protect_ci_v3_typed_domains (age, nickname, active, test_run_id) + VALUES ( + ${sql.json(age as postgres.JSONValue)}::eql_v3.integer_ord, + ${sql.json(nickname as postgres.JSONValue)}::eql_v3.text_eq, + ${sql.json(active as postgres.JSONValue)}::eql_v3.bool, + ${TEST_RUN_ID} + ) + RETURNING id + ` + + const ageTerm = unwrapResult( + await protectClient.encryptQuery(30, { + table: typedTable, + column: typedTable.age, + queryType: 'orderAndRange', + }), + ) as postgres.JSONValue + + const rows = await sql<{ id: number }[]>` + SELECT id + FROM protect_ci_v3_typed_domains + WHERE test_run_id = ${TEST_RUN_ID} + AND eql_v3.ord_term(age) >= eql_v3.ore_block_256(${sql.json(ageTerm)}::jsonb) + ` + + expect(rows.map((row) => row.id)).toContain(inserted.id) + }, 30000) + + // Correctness proof for the equality-via-ORE fix (Part A). The deterministic + // regression proves `resolveIndexType` resolves equality to `ore` instead of + // throwing; this proves the resulting term actually SELECTS the right rows + // against real Postgres, using the SQL `=` operator on the ORE term. + it('selects the exact row for an equality term via ORE on an integer_ord column', async () => { + async function insertAge(age: number): Promise<number> { + const ageCt = unwrapResult( + await protectClient.encrypt(age, { + table: typedTable, + column: typedTable.age, + }), + ) as postgres.JSONValue + const nick = unwrapResult( + await protectClient.encrypt(`nick-${age}`, { + table: typedTable, + column: typedTable.nickname, + }), + ) as postgres.JSONValue + const act = unwrapResult( + await protectClient.encrypt(true, { + table: typedTable, + column: typedTable.active, + }), + ) as postgres.JSONValue + const [row] = await sql<{ id: number }[]>` + INSERT INTO protect_ci_v3_typed_domains (age, nickname, active, test_run_id) + VALUES ( + ${sql.json(ageCt)}::eql_v3.integer_ord, + ${sql.json(nick)}::eql_v3.text_eq, + ${sql.json(act)}::eql_v3.bool, + ${TEST_RUN_ID} + ) + RETURNING id + ` + return row.id + } + + const ids = { + thirty: await insertAge(30), + thirtySeven: await insertAge(37), + fortyTwo: await insertAge(42), + } + + // Equality term encrypted with queryType:'equality' — post-fix this resolves + // to the ore (`ob`) term; the SQL `=` operator makes it an equality match. + const equalityTerm = unwrapResult( + await protectClient.encryptQuery(37, { + table: typedTable, + column: typedTable.age, + queryType: 'equality', + }), + ) as postgres.JSONValue + + const matched = await sql<{ id: number }[]>` + SELECT id + FROM protect_ci_v3_typed_domains + WHERE test_run_id = ${TEST_RUN_ID} + AND eql_v3.ord_term(age) = eql_v3.ore_block_256(${sql.json(equalityTerm)}::jsonb) + ORDER BY id + ` + // Exactly the age=37 row — not the 30 or 42 rows. + expect(matched.map((row) => row.id)).toEqual([ids.thirtySeven]) + expect(matched.map((row) => row.id)).not.toContain(ids.thirty) + expect(matched.map((row) => row.id)).not.toContain(ids.fortyTwo) + + // A non-matching value selects nothing. + const missTerm = unwrapResult( + await protectClient.encryptQuery(99, { + table: typedTable, + column: typedTable.age, + queryType: 'equality', + }), + ) as postgres.JSONValue + const none = await sql<{ id: number }[]>` + SELECT id + FROM protect_ci_v3_typed_domains + WHERE test_run_id = ${TEST_RUN_ID} + AND eql_v3.ord_term(age) = eql_v3.ore_block_256(${sql.json(missTerm)}::jsonb) + ` + expect(none).toHaveLength(0) + }, 30000) +}) diff --git a/packages/stack/__tests__/schema-v3.test-d.ts b/packages/stack/__tests__/schema-v3.test-d.ts new file mode 100644 index 00000000..0abe34ca --- /dev/null +++ b/packages/stack/__tests__/schema-v3.test-d.ts @@ -0,0 +1,369 @@ +import { describe, expectTypeOf, it } from 'vitest' +import { Encryption, type EncryptionClient } from '@/encryption' +import type { + EncryptedBigintColumn, + EncryptedBigintOrdColumn, + EncryptedTextSearchColumn, + InferEncrypted, + InferPlaintext, +} from '@/eql/v3' +import { encryptedTable, types } from '@/eql/v3' +// v2 column builders — used to prove the v3 table type rejects a v2 column and +// to assert v2 backward-compat against the widened client types. +import { + encryptedColumn, + encryptedField, + encryptedTable as v2EncryptedTable, +} from '@/schema' +import type { Encrypted } from '@/types' + +describe('eql_v3 schema type inference', () => { + it('types.TextSearch returns an EncryptedTextSearchColumn', () => { + const col = types.TextSearch('email') + expectTypeOf(col).toEqualTypeOf<EncryptedTextSearchColumn>() + }) + + it('exposes bigint factories (native round-tripping landed in protect-ffi 0.28)', () => { + expectTypeOf(types.Bigint('large')).toEqualTypeOf<EncryptedBigintColumn>() + expectTypeOf(types.BigintOrd('large')).toEqualTypeOf<EncryptedBigintOrdColumn>() + }) + + it('encryptedTable exposes column builders as typed properties', () => { + const users = encryptedTable('users', { + email: types.TextSearch('email'), + }) + expectTypeOf(users.email).toEqualTypeOf<EncryptedTextSearchColumn>() + expectTypeOf(users.tableName).toBeString() + }) + + it('rejects a v2 EncryptedColumn in a v3 table (nominal private-field mismatch)', () => { + encryptedTable('users', { + // @ts-expect-error - a v2 EncryptedColumn is not an EncryptedTextSearchColumn + email: encryptedColumn('email'), + }) + }) + + it('InferPlaintext maps each column to string', () => { + const users = encryptedTable('users', { + email: types.TextSearch('email'), + name: types.TextSearch('name'), + }) + type Plaintext = InferPlaintext<typeof users> + expectTypeOf<Plaintext>().toEqualTypeOf<{ email: string; name: string }>() + }) + + it('InferEncrypted maps each column to Encrypted', () => { + const users = encryptedTable('users', { + email: types.TextSearch('email'), + }) + type Enc = InferEncrypted<typeof users> + expectTypeOf<Enc>().toEqualTypeOf<{ email: Encrypted }>() + }) + + it('InferPlaintext maps v3 concrete domains to plaintext TypeScript types', () => { + const metrics = encryptedTable('metrics', { + name: types.Text('name'), + age: types.Integer('age'), + active: types.Boolean('active'), + createdAt: types.Timestamp('created_at'), + score: types.Double('score'), + }) + + type Plaintext = InferPlaintext<typeof metrics> + + expectTypeOf<Plaintext>().toEqualTypeOf<{ + name: string + age: number + active: boolean + createdAt: Date + score: number + }>() + }) + + it('v3 domain classes remain nominal by literal domain definition', () => { + const date = types.Date('created_on') + const boolean = types.Boolean('active') + + expectTypeOf(date).not.toEqualTypeOf<typeof boolean>() + + // @ts-expect-error - storage-only boolean is not assignable to storage-only date + const invalid: typeof date = boolean + void invalid + }) +}) + +describe('eql_v3 client integration (type-level acceptance)', () => { + const v3users = encryptedTable('users', { + email: types.TextSearch('email'), + }) + + it('Encryption accepts a v3 schema', () => { + expectTypeOf(Encryption).toBeCallableWith({ schemas: [v3users] }) + }) + + it('encrypt accepts a v3 table + column', () => { + const client = {} as EncryptionClient + expectTypeOf(client.encrypt).toBeCallableWith('alice@example.com', { + table: v3users, + column: v3users.email, + }) + }) + + it('encrypt and encryptQuery accept bigint plaintext (native round-tripping landed in protect-ffi 0.28)', () => { + const client = {} as EncryptionClient + + expectTypeOf(client.encrypt).toBeCallableWith(1n, { + table: v3users, + column: v3users.email, + }) + + expectTypeOf(client.encryptQuery).toBeCallableWith(1n, { + table: v3users, + column: v3users.email, + }) + }) + + it('encryptQuery accepts a v3 table + column', () => { + const client = {} as EncryptionClient + expectTypeOf(client.encryptQuery).toBeCallableWith('alice@example.com', { + table: v3users, + column: v3users.email, + }) + }) + + it('decrypt accepts an Encrypted value (round-trip target type; schema-independent)', () => { + const client = {} as EncryptionClient + expectTypeOf(client.decrypt).toBeCallableWith({} as Encrypted) + }) + + it('BACKWARD COMPAT: v2 tables/columns still satisfy the widened types', () => { + const v2users = v2EncryptedTable('users', { + email: encryptedColumn('email').equality(), + }) + expectTypeOf(Encryption).toBeCallableWith({ schemas: [v2users] }) + const client = {} as EncryptionClient + expectTypeOf(client.encrypt).toBeCallableWith('alice@example.com', { + table: v2users, + column: v2users.email, + }) + // a v2 EncryptedColumn is STILL queryable (nominal arm of BuildableQueryColumn) + expectTypeOf(client.encryptQuery).toBeCallableWith('alice@example.com', { + table: v2users, + column: v2users.email, + }) + }) + + it('a non-queryable v2 EncryptedField is encryptable but NOT queryable', () => { + const v2usersWithField = v2EncryptedTable('users', { + profile: { email: encryptedField('email') }, + }) + const client = {} as EncryptionClient + + // POSITIVE: a field IS encryptable (storage path = BuildableColumn) + expectTypeOf(client.encrypt).toBeCallableWith('alice@example.com', { + table: v2usersWithField, + column: v2usersWithField.profile.email, + }) + + // NEGATIVE: a field is NOT queryable. The query path uses + // BuildableQueryColumn, which excludes EncryptedField (no indexes). If the + // query path were instead widened to BuildableColumn (the rejected + // Batch-2/3 design), this call would compile and only fail at runtime with + // "no indexes configured" — so this test guards against that re-widening. + // + // The mismatch is a DEEP object-literal property error, so tsc reports it on + // the `column:` line — the `@ts-expect-error` MUST sit directly above that + // line (not above the call), or you get TS2578 "unused directive" + the real + // error leaking. (Mirror of Task 4's v2-column-rejected test placement.) + client.encryptQuery('alice@example.com', { + table: v2usersWithField, + // @ts-expect-error - EncryptedField is not assignable to BuildableQueryColumn + column: v2usersWithField.profile.email, + }) + }) + + it('encryptQuery accepts queryable v3 columns with explicit capability metadata', () => { + const users = encryptedTable('users', { + emailEq: types.TextEq('email_eq'), + emailMatch: types.TextMatch('email_match'), + emailSearch: types.TextSearch('email_search'), + createdAt: types.TimestampOrd('created_at'), + }) + const client = {} as EncryptionClient + + expectTypeOf(client.encryptQuery).toBeCallableWith('alice@example.com', { + table: users, + column: users.emailEq, + }) + expectTypeOf(client.encryptQuery).toBeCallableWith('ali', { + table: users, + column: users.emailMatch, + queryType: 'freeTextSearch', + }) + expectTypeOf(client.encryptQuery).toBeCallableWith(new Date(), { + table: users, + column: users.createdAt, + queryType: 'orderAndRange', + }) + expectTypeOf(client.encryptQuery).toBeCallableWith('alice@example.com', { + table: users, + column: users.emailSearch, + queryType: 'equality', + }) + }) + + it('encryptQuery rejects storage-only v3 columns at compile time', () => { + const users = encryptedTable('users', { + email: types.Text('email'), + active: types.Boolean('active'), + }) + const client = {} as EncryptionClient + + client.encryptQuery('alice@example.com', { + table: users, + // @ts-expect-error - storage-only v3 text column is not queryable + column: users.email, + }) + + client.encryptQuery(true, { + table: users, + // @ts-expect-error - storage-only v3 boolean column is not queryable + column: users.active, + }) + }) +}) + +describe('eql_v3 model encryption inference', () => { + it('encryptModel and bulkEncryptModels infer encrypted fields from v3 tables', () => { + const users = encryptedTable('users', { + email: types.TextSearch('email'), + active: types.Boolean('active'), + }) + const client = {} as EncryptionClient + + const encryptedOne = client.encryptModel( + { id: 'u1', email: 'alice@example.com', active: true, untouched: 42 }, + users, + ) + expectTypeOf(encryptedOne).toEqualTypeOf< + import('@/encryption').EncryptModelOperation<{ + id: string + email: Encrypted + active: Encrypted + untouched: number + }> + >() + + const encryptedMany = client.bulkEncryptModels( + [{ id: 'u1', email: 'alice@example.com', active: true }], + users, + ) + expectTypeOf(encryptedMany).toEqualTypeOf< + import('@/encryption').BulkEncryptModelsOperation<{ + id: string + email: Encrypted + active: Encrypted + }> + >() + }) + + it('v3 encryptModel preserves unrelated and nullable fields', () => { + const users = encryptedTable('users', { + email: types.TextSearch('email'), + }) + const client = {} as EncryptionClient + + const encrypted = client.encryptModel( + { id: 'u1', email: null as string | null, untouched: 42 }, + users, + ) + + expectTypeOf(encrypted).toEqualTypeOf< + import('@/encryption').EncryptModelOperation<{ + id: string + email: Encrypted | null + untouched: number + }> + >() + }) + + it('encryptModel degrades gracefully for a bare BuildableTable-typed value (no brand)', () => { + // A table passed through a value/param annotated as the structural + // `BuildableTable` (no `_columnType` brand) cannot recover its literal + // column keys. It must degrade to the model unchanged — NOT mark every + // field `Encrypted`. Regression guard: `keyof BuildableTableColumns<...>` + // must resolve to `never` here, not `keyof never` (= string|number|symbol), + // which would wrongly encrypt all fields including `id` and `untouched`. + const usersConcrete = encryptedTable('users', { + email: types.TextSearch('email'), + }) + const table: import('@/types').BuildableTable = usersConcrete + const client = {} as EncryptionClient + + const encrypted = client.encryptModel( + { id: 'u1', email: 'alice@example.com', untouched: 42 }, + table, + ) + expectTypeOf(encrypted).toEqualTypeOf< + import('@/encryption').EncryptModelOperation<{ + id: string + email: string + untouched: number + }> + >() + }) + + it('model inference keys off the property name, not the DB column name (aliased columns)', () => { + // The column's DB name ('created_at') differs from the object property name + // ('occurredAt'). Model inference keys off the PROPERTY name, so `occurredAt` + // must become `Encrypted` while unrelated fields are preserved verbatim. + const events = encryptedTable('events', { + occurredAt: types.Timestamp('created_at'), + }) + const client = {} as EncryptionClient + + const encryptedOne = client.encryptModel( + { id: 'e1', occurredAt: new Date(), label: 'signup' }, + events, + ) + expectTypeOf(encryptedOne).toEqualTypeOf< + import('@/encryption').EncryptModelOperation<{ + id: string + occurredAt: Encrypted + label: string + }> + >() + + const encryptedMany = client.bulkEncryptModels( + [{ id: 'e1', occurredAt: new Date(), label: 'signup' }], + events, + ) + expectTypeOf(encryptedMany).toEqualTypeOf< + import('@/encryption').BulkEncryptModelsOperation<{ + id: string + occurredAt: Encrypted + label: string + }> + >() + }) + + it('v2 encryptModel inference still preserves non-schema fields after widening', () => { + const users = v2EncryptedTable('users', { + email: encryptedColumn('email').equality(), + }) + const client = {} as EncryptionClient + + const encrypted = client.encryptModel( + { id: 'u1', email: 'alice@example.com', age: 30 }, + users, + ) + + expectTypeOf(encrypted).toEqualTypeOf< + import('@/encryption').EncryptModelOperation<{ + id: string + email: Encrypted + age: number + }> + >() + }) +}) diff --git a/packages/stack/__tests__/schema-v3.test.ts b/packages/stack/__tests__/schema-v3.test.ts new file mode 100644 index 00000000..9a5b4bb2 --- /dev/null +++ b/packages/stack/__tests__/schema-v3.test.ts @@ -0,0 +1,507 @@ +import { describe, expect, it } from 'vitest' +import { resolveIndexType } from '@/encryption/helpers/infer-index-type' +import { + buildEncryptConfig, + EncryptedTable, + EncryptedTextSearchColumn, + encryptedTable, + types, +} from '@/eql/v3' +import { encryptConfigSchema, encryptedColumn } from '@/schema' +import { type DomainSpec, typedEntries, V3_MATRIX } from './v3-matrix/catalog' + +describe('eql_v3 text_search column', () => { + it('LOAD-BEARING: default build() deep-equals the v2 equality+order+match column', () => { + const v3 = types.TextSearch('email').build() + const v2 = encryptedColumn('email') + .equality() + .orderAndRange() + .freeTextSearch() + .build() + // toStrictEqual: byte-identical, no extra/undefined keys on either side. + expect(v3).toStrictEqual(v2) + }) + + it('.freeTextSearch(opts) overrides each provided key and keeps the rest as defaults', () => { + const built = types + .TextSearch('email') + .freeTextSearch({ + tokenizer: { kind: 'ngram', token_length: 4 }, + k: 8, + m: 4096, + include_original: false, + }) + .build() + expect(built.indexes.match).toEqual({ + tokenizer: { kind: 'ngram', token_length: 4 }, + // omitted -> default downcase filter retained + token_filters: [{ kind: 'downcase' }], + k: 8, + m: 4096, + include_original: false, + }) + }) + + it('.freeTextSearch({ token_filters: [] }) overrides the downcase default with an empty array', () => { + // LOAD-BEARING: `[] ?? default` evaluates to `[]` (an empty array is not + // nullish), so an explicit empty array must OVERRIDE the downcase default, + // not fall back to it. Mirrors v2 (schema-builders.test.ts). + const built = types + .TextSearch('email') + .freeTextSearch({ token_filters: [] }) + .build() + expect(built.indexes.match.token_filters).toEqual([]) + }) + + it('repeated .freeTextSearch() calls are last-call-wins-fully (each re-merges against defaults, not prior state)', () => { + // Each call re-merges against a fresh defaultMatchOpts(), not the + // accumulated matchOpts — so the second call resets k back to its default + // of 6. This is intentional: it mirrors v2 exactly. Pinned here so a future + // "merge against current state" change can't silently slip in. + const built = types + .TextSearch('email') + .freeTextSearch({ k: 8 }) + .freeTextSearch({ m: 4096 }) + .build() + expect(built.indexes.match.k).toBe(6) + expect(built.indexes.match.m).toBe(4096) + }) + + it('.freeTextSearch() with no argument is a no-op: build() equals the default build()', () => { + // Pins the opts === undefined branch: every `opts?.x ?? default` falls + // through, so a bare call must emit exactly the default match block. + expect(types.TextSearch('email').freeTextSearch().build()).toStrictEqual( + types.TextSearch('email').build(), + ) + }) + + it('.freeTextSearch() is tuning-only: unique and ore indexes stay present', () => { + const built = types.TextSearch('email').freeTextSearch({ k: 8 }).build() + expect(built.indexes.unique).toEqual({ token_filters: [] }) + expect(built.indexes.ore).toEqual({}) + }) + + it('built columns share no mutable state: mutating one build() output does not affect another', () => { + // Guards against the shared-defaults aliasing bug: defaults come from a + // per-instance factory and build() deep-clones the match block. + const a = types.TextSearch('a').build() + const b = types.TextSearch('b').build() + + // Mutate every nested level of a's match block. + a.indexes.match.k = 999 + a.indexes.match.token_filters.push({ kind: 'downcase' }) + a.indexes.match.tokenizer = { kind: 'standard' } + + expect(b.indexes.match.k).toBe(6) + expect(b.indexes.match.token_filters).toEqual([{ kind: 'downcase' }]) + expect(b.indexes.match.tokenizer).toEqual({ + kind: 'ngram', + token_length: 3, + }) + + // A second build() of an independent column is also pristine. + const c = types.TextSearch('c').build() + expect(c.indexes.match.k).toBe(6) + expect(c.indexes.match.token_filters).toEqual([{ kind: 'downcase' }]) + }) + + it('clones caller opts on freeTextSearch(): mutating them before build() does not leak', () => { + // build() deep-clones at build time, but if freeTextSearch stored the + // caller's nested tokenizer / token_filters by reference, a caller mutating + // their own opts object between freeTextSearch(opts) and build() would leak + // the mutation into the emitted config. freeTextSearch must clone on write. + const opts = { + tokenizer: { kind: 'ngram' as const, token_length: 3 }, + token_filters: [{ kind: 'downcase' as const }], + } + const col = types.TextSearch('email').freeTextSearch(opts) + + // Mutate the caller's own opts AFTER freeTextSearch but BEFORE build(). + opts.tokenizer.token_length = 999 + opts.token_filters.push({ kind: 'downcase' as const }) + + const built = col.build() + expect(built.indexes.match.tokenizer).toEqual({ + kind: 'ngram', + token_length: 3, + }) + expect(built.indexes.match.token_filters).toEqual([{ kind: 'downcase' }]) + }) +}) + +describe('eql_v3 text_match column', () => { + it('built columns share no mutable state: mutating one build() output does not affect another', () => { + // Same aliasing guard as the text_search test above, but through the base + // class indexesForCapabilities() match clone — text_match has no build() + // override, so a regression there (e.g. sharing a defaultMatchOpts() result + // across builds) would slip past the text_search-only test. + const a = types.TextMatch('a').build() + const b = types.TextMatch('b').build() + + a.indexes.match.k = 999 + a.indexes.match.token_filters.push({ kind: 'downcase' }) + a.indexes.match.tokenizer = { kind: 'standard' } + + expect(b.indexes.match.k).toBe(6) + expect(b.indexes.match.token_filters).toEqual([{ kind: 'downcase' }]) + expect(b.indexes.match.tokenizer).toEqual({ + kind: 'ngram', + token_length: 3, + }) + + // A fresh build() of an independent column is also pristine. + const c = types.TextMatch('c').build() + expect(c.indexes.match.k).toBe(6) + expect(c.indexes.match.token_filters).toEqual([{ kind: 'downcase' }]) + }) +}) + +describe('eql_v3 concrete type names', () => { + it('preserves public factory names while exposing concrete Postgres domain names', () => { + expect(types.Integer('n').getEqlType()).toBe('eql_v3.integer') + expect(types.IntegerEq('n').getEqlType()).toBe('eql_v3.integer_eq') + expect(types.IntegerOrdOre('n').getEqlType()).toBe('eql_v3.integer_ord_ore') + expect(types.IntegerOrd('n').getEqlType()).toBe('eql_v3.integer_ord') + + expect(types.Smallint('n').getEqlType()).toBe('eql_v3.smallint') + expect(types.SmallintEq('n').getEqlType()).toBe('eql_v3.smallint_eq') + expect(types.SmallintOrdOre('n').getEqlType()).toBe( + 'eql_v3.smallint_ord_ore', + ) + expect(types.SmallintOrd('n').getEqlType()).toBe('eql_v3.smallint_ord') + + expect(types.Boolean('b').getEqlType()).toBe('eql_v3.bool') + expect(types.Real('n').getEqlType()).toBe('eql_v3.real') + expect(types.RealEq('n').getEqlType()).toBe('eql_v3.real_eq') + expect(types.RealOrdOre('n').getEqlType()).toBe('eql_v3.real_ord_ore') + expect(types.RealOrd('n').getEqlType()).toBe('eql_v3.real_ord') + expect(types.Double('n').getEqlType()).toBe('eql_v3.double') + expect(types.DoubleEq('n').getEqlType()).toBe('eql_v3.double_eq') + expect(types.DoubleOrdOre('n').getEqlType()).toBe('eql_v3.double_ord_ore') + expect(types.DoubleOrd('n').getEqlType()).toBe('eql_v3.double_ord') + }) +}) + +describe('eql_v3 encryptedTable', () => { + it('creates a table exposing column builders as properties', () => { + const users = encryptedTable('users', { + email: types.TextSearch('email'), + }) + expect(users).toBeInstanceOf(EncryptedTable) + expect(users.tableName).toBe('users') + expect(users.email).toBeInstanceOf(EncryptedTextSearchColumn) + }) + + it('table.email returns the same builder instance passed in', () => { + const emailCol = types.TextSearch('email') + const users = encryptedTable('users', { email: emailCol }) + expect(users.email).toBe(emailCol) + }) + + it.each([ + 'build', + 'tableName', + 'columnBuilders', + '_columnType', + // Inherited Object.prototype members: assigning these as own properties + // would shadow the prototype method/accessor. Guard them too so the + // table object stays well-behaved for reflection / serialization. + 'constructor', + 'toString', + 'valueOf', + 'hasOwnProperty', + ])('throws when a column name (%s) collides with a reserved property', (reserved) => { + expect(() => + encryptedTable('users', { + [reserved]: types.TextSearch(reserved), + }), + ).toThrow(/reserved EncryptedTable property/) + }) + + it('build() assembles { tableName, columns } with built column configs', () => { + const users = encryptedTable('users', { + email: types.TextSearch('email'), + }) + const built = users.build() + expect(built.tableName).toBe('users') + expect(built.columns).toStrictEqual({ + email: { + cast_as: 'string', + indexes: { + unique: { token_filters: [] }, + ore: {}, + match: { + tokenizer: { kind: 'ngram', token_length: 3 }, + token_filters: [{ kind: 'downcase' }], + k: 6, + m: 2048, + include_original: true, + }, + }, + }, + }) + }) + + it('build() throws when two columns resolve to the same DB name (no silent overwrite)', () => { + // Columns are keyed in the built config by DB name (`getName()`), so two JS + // properties whose builders resolve to the same name would silently + // overwrite — the later one wins and the first column's config is lost. + // Fail loudly, matching the reserved-key and duplicate-tableName guards. + const users = encryptedTable('users', { + email: types.TextEq('contact'), + contactEmail: types.TextMatch('contact'), + }) + expect(() => users.build()).toThrow(/duplicate column name "contact"/) + }) + + it('build() surfaces the duplicate DB name through buildEncryptConfig', () => { + const users = encryptedTable('users', { + email: types.TextEq('contact'), + contactEmail: types.TextMatch('contact'), + }) + expect(() => buildEncryptConfig(users)).toThrow( + /duplicate column name "contact"/, + ) + }) +}) + +describe('eql_v3 buildEncryptConfig', () => { + it('zero tables yields an empty config (client-boundary Encryption() still rejects it)', () => { + expect(buildEncryptConfig()).toStrictEqual({ v: 1, tables: {} }) + }) + + it('produces a { v: 1, tables } config', () => { + const users = encryptedTable('users', { + email: types.TextSearch('email'), + }) + const config = buildEncryptConfig(users) + expect(config.v).toBe(1) + expect(config.tables).toHaveProperty('users') + expect(config.tables.users).toHaveProperty('email') + }) + + it('emits a config that passes encryptConfigSchema.parse()', () => { + const users = encryptedTable('users', { + email: types.TextSearch('email'), + }) + const config = buildEncryptConfig(users) + expect(() => encryptConfigSchema.parse(config)).not.toThrow() + }) + + it('supports multiple tables', () => { + const users = encryptedTable('users', { + email: types.TextSearch('email'), + }) + const posts = encryptedTable('posts', { + body: types.TextSearch('body'), + }) + const config = buildEncryptConfig(users, posts) + expect(Object.keys(config.tables).sort()).toEqual(['posts', 'users']) + }) + + it('keys columns by DB name (getName), not the JS property name', () => { + // A camelCase JS key mapping to a snake_case DB column must register the + // config under the DB name — `encrypt`/`decrypt` look columns up by + // `column.getName()`, so keying by the JS property name makes the FFI + // report "column not found in Encrypt config" at encrypt time. + const users = encryptedTable('accounts', { + createdOn: types.Date('created_on'), + lastSeen: types.Timestamp('last_seen'), + }) + const config = buildEncryptConfig(users) + expect(Object.keys(config.tables.accounts).sort()).toEqual([ + 'created_on', + 'last_seen', + ]) + expect(config.tables.accounts).not.toHaveProperty('createdOn') + expect(config.tables.accounts).not.toHaveProperty('lastSeen') + }) + + it('buildColumnKeyMap maps JS property → DB column name', () => { + // The model path matches user models by JS property but must address the + // FFI/config by DB name. `build()` discards the property→name relationship + // (it keys by DB name); `buildColumnKeyMap()` recovers it. + const users = encryptedTable('accounts', { + createdOn: types.Date('created_on'), + lastSeen: types.Timestamp('last_seen'), + email: types.TextSearch('email'), + }) + expect(users.buildColumnKeyMap()).toEqual({ + createdOn: 'created_on', + lastSeen: 'last_seen', + email: 'email', + }) + }) + + it('throws when two tables share the same tableName (no silent drop)', () => { + // v3-only additive guard: keying config.tables by name means a duplicate + // would silently overwrite the earlier table. Fail loudly instead so the + // footgun surfaces at build time. (v2 keeps its silent-overwrite behavior + // unchanged — the no-v2-change constraint.) + const a = encryptedTable('users', { + email: types.TextSearch('email'), + }) + const b = encryptedTable('users', { + name: types.TextSearch('name'), + }) + expect(() => buildEncryptConfig(a, b)).toThrow( + /duplicate table name "users"/, + ) + }) +}) + +// The scalar query types a caller can request against a v3 domain. `searchableJson` +// / steVec are JSONB-only and out of scope for the scalar matrix. +const SCALAR_QUERY_TYPES = [ + 'equality', + 'orderAndRange', + 'freeTextSearch', +] as const + +// The ground-truth for whether `resolveIndexType` accepts a (domain, queryType) +// pair: does the domain carry the index that query resolves to? Derived from the +// catalog's `indexes` data, AMENDED for the equality-via-ORE rule — an +// order-capable column answers equality via its `ore` index, not `unique`. This +// mirrors `resolveIndexType`'s real logic, so it needs no live FFI. +function queryTypeAllowed( + indexes: DomainSpec['indexes'], + queryType: (typeof SCALAR_QUERY_TYPES)[number], +): boolean { + const idx = indexes ?? {} + if (queryType === 'equality') return Boolean(idx.unique || idx.ore) + if (queryType === 'orderAndRange') return Boolean(idx.ore) + return Boolean(idx.match) // freeTextSearch +} + +describe('eql_v3 catalog-driven query capability sweep', () => { + // The Rust harness's `blocker_combos` analog: attempt every scalar queryType + // against every domain and assert the throw/allow outcome the domain's + // configured indexes dictate. Supersedes the two hand-picked cases that used + // to live here — they are now just two of the generated rows. + it.each( + typedEntries(V3_MATRIX).flatMap(([eqlType, spec]) => + SCALAR_QUERY_TYPES.map( + (queryType) => [eqlType, spec, queryType] as const, + ), + ), + )('%s + queryType=%s: gating matches configured indexes', (_eqlType, spec, queryType) => { + const col = spec.builder('value') + if (queryTypeAllowed(spec.indexes, queryType)) { + expect(() => resolveIndexType(col as never, queryType)).not.toThrow() + } else { + // Broad message match: for a blocked equality the resolver reports the + // missing `unique`; for orderAndRange/freeTextSearch the missing ore/match. + expect(() => resolveIndexType(col as never, queryType)).toThrow( + /not configured/, + ) + } + }) + + it.each( + typedEntries(V3_MATRIX).filter( + ([, spec]) => Object.keys(spec.indexes ?? {}).length === 0, + ), + )('%s: querying a storage-only column with no queryType throws', (_eqlType, spec) => { + expect(() => resolveIndexType(spec.builder('value') as never)).toThrow( + /no indexes configured/, + ) + }) + + // Spot-check the exact messages for a queryable-but-misused column, so the + // broad regex above doesn't let a message regression slip through. + it('reports the specific missing index for a match-only column', () => { + const matchOnly = types.TextMatch('body') + expect(() => resolveIndexType(matchOnly, 'equality')).toThrow( + /Index type "unique" is not configured/, + ) + expect(() => resolveIndexType(matchOnly, 'orderAndRange')).toThrow( + /Index type "ore" is not configured/, + ) + }) +}) + +describe('eql_v3 equality via ORE on order-capable columns (regression)', () => { + // The capability contract documents equality as answerable "via `ob`", so a + // numeric/date order-capable column (which has NO `hm`) resolves equality to + // its `ore` index (same term as orderAndRange, distinguished by the SQL `=` + // operator) instead of throwing on the absent `unique` index. (Text order + // domains DO carry `hm` and resolve equality to `unique` instead — see the + // text-order regression below.) + // Keep these labels aligned with the checked-in EQL build; a mismatch here + // means the stack package is out of sync with the underlying domain surface. + it.each([ + ['IntegerOrd', types.IntegerOrd], + ['date_ord', types.DateOrd], + ['numeric_ord', types.NumericOrd], + ] as const)('%s resolves equality to the ore index', (_name, builder) => { + expect(resolveIndexType(builder('value'), 'equality')).toEqual({ + indexType: 'ore', + }) + }) + + it('preserves v2: an orderAndRange-only column still throws on equality (no-v2-change)', () => { + // v2 EncryptedColumn has no getQueryCapabilities, so the equality-via-ORE + // branch never fires for it — the equality-without-unique throw is unchanged. + const v2OrderOnly = encryptedColumn('x').orderAndRange() + expect(() => resolveIndexType(v2OrderOnly, 'equality')).toThrow( + /Index type "unique" is not configured/, + ) + }) +}) + +describe('eql_v3 text order domains carry the hm (unique) index (regression)', () => { + // The `eql_v3.text_ord` and `eql_v3.text_ord_ore` SQL domains require BOTH + // `hm` (HMAC) and `ob` (ORE) in the stored ciphertext: text equality is + // HMAC-based (their `eql_v3.eq_term` extracts `hm`), unlike numeric/date order + // domains which answer equality via `ob` and need only ORE. So text order + // columns must emit `unique` (hm) IN ADDITION to `ore` (ob), or a real INSERT + // fails with `value for domain eql_v3.text_ord_ore violates check constraint`. + it.each([ + ['text_ord_ore', types.TextOrdOre], + ['text_ord', types.TextOrd], + ] as const)('%s emits both unique (hm) and ore (ob)', (_name, builder) => { + expect(builder('c').build().indexes).toStrictEqual({ + unique: { token_filters: [] }, + ore: {}, + }) + }) + + it.each([ + ['IntegerOrdOre', types.IntegerOrdOre], + ['IntegerOrd', types.IntegerOrd], + ['date_ord_ore', types.DateOrdOre], + ['numeric_ord', types.NumericOrd], + ] as const)('%s (numeric/date order) emits ore only — no unique', (_name, builder) => { + expect(builder('c').build().indexes).toStrictEqual({ ore: {} }) + }) + + // With `unique` present, text order equality resolves to the hm index (not + // ORE): `resolvesEqualityViaOre` only fires when `unique` is ABSENT. + it.each([ + ['text_ord_ore', types.TextOrdOre], + ['text_ord', types.TextOrd], + ] as const)('%s resolves equality to the unique (hm) index', (_name, builder) => { + expect(resolveIndexType(builder('value'), 'equality')).toEqual({ + indexType: 'unique', + }) + }) +}) + +describe('eql_v3 timestamp domains emit cast_as "timestamp" (time-of-day preserved)', () => { + // The FFI has a distinct `timestamp` cast (full date+time) separate from + // `date` (calendar-date only). Every timestamp domain must emit + // `cast_as: 'timestamp'` so the native layer keeps the time-of-day instead of + // truncating to midnight (see schema-v3-client occurredAt round-trip). + it.each([ + ['timestamp', types.Timestamp], + ['timestamp_eq', types.TimestampEq], + ['timestamp_ord_ore', types.TimestampOrdOre], + ['timestamp_ord', types.TimestampOrd], + ] as const)('%s emits cast_as "timestamp"', (_name, builder) => { + expect(builder('c').build().cast_as).toBe('timestamp') + }) + + it('the plain date domain still emits cast_as "date"', () => { + expect(types.Date('c').build().cast_as).toBe('date') + }) +}) diff --git a/packages/stack/__tests__/typed-client-v3.test-d.ts b/packages/stack/__tests__/typed-client-v3.test-d.ts new file mode 100644 index 00000000..03b929c9 --- /dev/null +++ b/packages/stack/__tests__/typed-client-v3.test-d.ts @@ -0,0 +1,173 @@ +import { describe, expectTypeOf, it } from 'vitest' +import type { EncryptionClient } from '@/encryption' +// Everything comes from the single `@cipherstash/stack/v3` surface (re-exported +// from src/encryption/v3.ts), exercising the re-export at the same time. +import { + encryptedTable, + typedClient, + types, + type V3DecryptedModel, + type V3EncryptedModel, +} from '@/encryption/v3' +import type { Encrypted } from '@/types' + +// A v3 table mixing every relevant capability tier: +const users = encryptedTable('users', { + email: types.TextEq('email'), // equality only + bio: types.TextSearch('bio'), // equality + order + free-text + note: types.Text('note'), // storage only (not queryable) + createdAt: types.TimestampOrd('created_at'), // equality + order +}) + +// A second registered table whose `weight` domain (integer_ord) is NOT present in +// `users`, so borrowing it is a genuine cross-table type error. +const other = encryptedTable('other', { + weight: types.IntegerOrd('weight'), +}) + +const client = typedClient({} as EncryptionClient, users, other) + +describe('typed v3 client — encrypt plaintext is pinned to the column domain', () => { + it('accepts the matching plaintext type per domain', () => { + expectTypeOf(client.encrypt).toBeCallableWith('alice@example.com', { + table: users, + column: users.email, + }) + expectTypeOf(client.encrypt).toBeCallableWith(new Date(), { + table: users, + column: users.createdAt, + }) + }) + + it('rejects a wrong-typed plaintext', () => { + client.encrypt( + // @ts-expect-error - number is not valid plaintext for a text column + 123, + { table: users, column: users.email }, + ) + }) +}) + +describe('typed v3 client — encryptQuery constrains queryType to capabilities', () => { + it('accepts capability-matched query types', () => { + expectTypeOf(client.encryptQuery).toBeCallableWith('alice@example.com', { + table: users, + column: users.email, + queryType: 'equality', + }) + expectTypeOf(client.encryptQuery).toBeCallableWith(new Date(), { + table: users, + column: users.createdAt, + queryType: 'orderAndRange', + }) + // text_search supports all three + expectTypeOf(client.encryptQuery).toBeCallableWith('needle', { + table: users, + column: users.bio, + queryType: 'freeTextSearch', + }) + }) + + it('rejects a query type the column does not support', () => { + client.encryptQuery('alice@example.com', { + table: users, + column: users.email, // equality only + // @ts-expect-error - text_eq column does not support 'orderAndRange' + queryType: 'orderAndRange', + }) + client.encryptQuery(new Date(), { + table: users, + column: users.createdAt, // equality + order, no free-text + // @ts-expect-error - timestamp_ord column does not support 'freeTextSearch' + queryType: 'freeTextSearch', + }) + }) + + it('rejects a storage-only column on the query path', () => { + client.encryptQuery('x', { + table: users, + // @ts-expect-error - storage-only text column is not queryable + column: users.note, + }) + }) +}) + +describe('typed v3 client — model encrypt validates schema fields', () => { + it('accepts a model whose schema fields match and allows passthrough fields', () => { + expectTypeOf(client.encryptModel).toBeCallableWith( + { id: 'u1', email: 'a@b.com', createdAt: new Date() }, + users, + ) + }) + + it('rejects a wrong-typed schema field', () => { + client.encryptModel( + { + id: 'u1', + // @ts-expect-error - email expects string, got number + email: 123, + }, + users, + ) + }) + + it('maps schema columns to Encrypted and preserves passthrough + nullability', () => { + // Passthrough `id` stays string; schema `email` becomes Encrypted. + expectTypeOf< + V3EncryptedModel<typeof users, { id: string; email: string }> + >().toEqualTypeOf<{ id: string; email: Encrypted }>() + + // Nullable schema field → Encrypted | null. + expectTypeOf< + V3EncryptedModel<typeof users, { id: string; email: string | null }> + >().toEqualTypeOf<{ id: string; email: Encrypted | null }>() + }) +}) + +describe('typed v3 client — model decrypt yields precise plaintext', () => { + it('reconstructs schema columns to their plaintext type regardless of the input field type', () => { + // Input is the encrypted row; output pins each schema column to its plaintext + // type (Date for timestamp, string for text). + expectTypeOf< + V3DecryptedModel< + typeof users, + { id: string; email: Encrypted; createdAt: Encrypted } + > + >().toEqualTypeOf<{ + id: string + email: string + createdAt: Date + }>() + }) + + it('decryptModel is callable with an encrypted row and the table', () => { + expectTypeOf(client.decryptModel).toBeCallableWith( + { id: 'u1', email: {} as Encrypted }, + users, + ) + }) +}) + +describe('typed v3 client — soundness', () => { + it('rejects a hand-rolled structural table (no brand / private field)', () => { + const fakeTable = { + tableName: 'users', + build: () => ({ tableName: 'users', columns: {} }), + } + client.encrypt('x', { + // @ts-expect-error - a structural object is not a registered branded v3 table + table: fakeTable, + column: users.email, + }) + }) + + it('rejects a column whose domain is not present in the table', () => { + // Plaintext is a string (valid for every `users` column domain) so the only + // error is the column itself failing the `ColumnsOf<typeof users>` constraint. + client.encrypt('x', { + table: users, + // @ts-expect-error - integer_ord column from `other` is not in ColumnsOf<typeof users> + column: other.weight, + }) + }) +}) diff --git a/packages/stack/__tests__/typed-client-v3.test.ts b/packages/stack/__tests__/typed-client-v3.test.ts new file mode 100644 index 00000000..e80cb1a6 --- /dev/null +++ b/packages/stack/__tests__/typed-client-v3.test.ts @@ -0,0 +1,117 @@ +import { describe, expect, it } from 'vitest' +import type { EncryptionClient } from '@/encryption' +import { encryptedTable, typedClient, types } from '@/encryption/v3' + +const table = encryptedTable('t', { + when: types.Timestamp('when'), + note: types.Text('note'), + // camelCase JS property → snake_case DB name: reconstruction must key by the + // JS property (how the decrypted row is keyed), not the DB column name. + createdOn: types.Date('created_on'), +}) + +/** + * A minimal client stub whose model-decrypt methods resolve to a fixed + * `Result` payload. `typedClient` only `await`s these, so a plain Promise is a + * sufficient thenable. + */ +function fakeClient(data: Record<string, unknown>): EncryptionClient { + return { + decryptModel: () => Promise.resolve({ data }), + bulkDecryptModels: () => Promise.resolve({ data: [data] }), + } as unknown as EncryptionClient +} + +describe('typedClient — decrypt reconstruction', () => { + it('reconstructs Date columns from cast_as', async () => { + const client = typedClient( + fakeClient({ + when: '2020-01-02T03:04:05.000Z', + note: 'hi', + createdOn: '2026-07-01T00:00:00.000Z', + }), + table, + ) + + const result = await client.decryptModel({}, table) + expect(result.failure).toBeFalsy() + if (result.failure) return + + const data = result.data as Record<string, unknown> + expect(data.when).toBeInstanceOf(Date) + expect((data.when as Date).toISOString()).toBe('2020-01-02T03:04:05.000Z') + // Reconstructed by JS property (`createdOn`), though the DB column is + // `created_on` — a regression here would leave it an unparsed string. + expect(data.createdOn).toBeInstanceOf(Date) + expect((data.createdOn as Date).toISOString()).toBe( + '2026-07-01T00:00:00.000Z', + ) + expect(data.note).toBe('hi') // string column untouched + }) + + it('leaves null column values untouched', async () => { + const client = typedClient(fakeClient({ when: null, note: null }), table) + + const result = await client.decryptModel({}, table) + if (result.failure) return + + const data = result.data as Record<string, unknown> + expect(data.when).toBeNull() + expect(data.note).toBeNull() + }) + + it('reconstructs each row for bulkDecryptModels', async () => { + const client = typedClient( + fakeClient({ when: '2021-06-01T00:00:00.000Z', note: 'x' }), + table, + ) + + const result = await client.bulkDecryptModels([{}], table) + if (result.failure) return + + const rows = result.data as Array<Record<string, unknown>> + expect(rows).toHaveLength(1) + expect(rows[0].when).toBeInstanceOf(Date) + }) + + it('propagates a failure result unchanged', async () => { + const failing = { + decryptModel: () => + Promise.resolve({ + failure: { type: 'DecryptionError', message: 'boom' }, + }), + } as unknown as EncryptionClient + + const client = typedClient(failing, table) + const result = await client.decryptModel({}, table) + expect(result.failure).toBeTruthy() + }) + + it('returns DecryptionError when decryptModel receives an uninitialized table', async () => { + const client = typedClient(fakeClient({}), table) + const otherTable = encryptedTable('other', { + note: types.Text('note'), + }) + + const result = await client.decryptModel({}, otherTable as never) + + expect(result.failure?.type).toBe('DecryptionError') + expect(result.failure?.message).toContain( + 'received a table this client was not initialized with', + ) + }) + + it('returns DecryptionError when bulkDecryptModels receives an uninitialized table', async () => { + const client = typedClient(fakeClient({}), table) + const otherTable = encryptedTable('other', { + note: types.Text('note'), + }) + + const result = await client.bulkDecryptModels([{}], otherTable as never) + + expect(result.failure?.type).toBe('DecryptionError') + expect(result.failure?.message).toContain( + 'received a table this client was not initialized with', + ) + }) +}) diff --git a/packages/stack/__tests__/types-public-surface.test-d.ts b/packages/stack/__tests__/types-public-surface.test-d.ts new file mode 100644 index 00000000..7bd45890 --- /dev/null +++ b/packages/stack/__tests__/types-public-surface.test-d.ts @@ -0,0 +1,42 @@ +import { describe, expectTypeOf, it } from 'vitest' +// Regression guard for the public `@cipherstash/stack/types` entrypoint +// (src/types-public.ts). The structural builder contracts and the +// `encryptModel` / `bulkEncryptModels` return-type mapper appear in PUBLIC +// return positions (encryption/index.ts), so consumers must be able to NAME +// them from the public path. Importing a member that is not re-exported fails +// typecheck — so this file compiling green proves the surface is complete. +import type { + BuildableColumn, + BuildableQueryColumn, + BuildableTable, + BuildableTableColumns, + BuildableV3QueryableColumn, + Encrypted, + EncryptedFromBuildableTable, +} from '@/types-public' + +describe('public @cipherstash/stack/types surface', () => { + it('exposes the structural builder contracts', () => { + // A v3 queryable column IS a BuildableColumn (interface extension). + expectTypeOf<BuildableV3QueryableColumn>().toMatchTypeOf<BuildableColumn>() + // The query-column union is nameable and non-trivial. + expectTypeOf<BuildableQueryColumn>().not.toBeNever() + // The client table contract is nameable. + expectTypeOf<BuildableTable['tableName']>().toBeString() + }) + + it('exposes EncryptedFromBuildableTable (the encryptModel return mapper)', () => { + interface Users extends BuildableTable { + readonly _columnType: { email: unknown } + } + type Row = { id: number; email: string } + type Enc = EncryptedFromBuildableTable<Row, Users> + + // Schema-column fields become Encrypted; passthrough fields keep their type. + expectTypeOf<Enc['email']>().toEqualTypeOf<Encrypted>() + expectTypeOf<Enc['id']>().toEqualTypeOf<number>() + + // The column-map helper is nameable too. + expectTypeOf<keyof BuildableTableColumns<Users>>().toEqualTypeOf<'email'>() + }) +}) diff --git a/packages/stack/__tests__/v3-matrix/catalog.ts b/packages/stack/__tests__/v3-matrix/catalog.ts new file mode 100644 index 00000000..27cff54b --- /dev/null +++ b/packages/stack/__tests__/v3-matrix/catalog.ts @@ -0,0 +1,274 @@ +/** + * Type-driven v3 test matrix — single source of truth. + * + * The TypeScript analog of the Rust `eql_v3` `scalar_matrix!` harness + * (`encrypt-query-language/tests/sqlx`): one declarative catalog drives both a + * runtime `it.each` matrix (`matrix.test.ts`) and type-level assertions + * (`matrix.test-d.ts`), instead of hand-rolling per-domain test bodies. + * + * COVERAGE IS MANDATORY. The catalog is `satisfies Record<EqlV3TypeName, + * DomainSpec>`, and `EqlV3TypeName` is derived from the real column union + * (`AnyEncryptedV3Column`). Add a domain to the SDK and this file fails to + * compile until it has a row — the compile-time analog of, and stronger than, + * the Rust `test:matrix:inventory` cross-check (it names each missing domain). + * + * Every field here is consumed by a test: `builder`/`ColumnClass` by the + * instanceof check, `castAs` + `indexes` by the `build()` `toStrictEqual`, and + * `capabilities` by `getQueryCapabilities()`/`isQueryable()`. + */ + +import type { + AnyEncryptedV3Column, + EqlTypeForColumn, + QueryCapabilities, +} from '@/eql/v3' +import { + EncryptedBigintColumn, + EncryptedBigintEqColumn, + EncryptedBigintOrdColumn, + EncryptedBigintOrdOreColumn, + EncryptedBooleanColumn, + EncryptedDateColumn, + EncryptedDateEqColumn, + EncryptedDateOrdColumn, + EncryptedDateOrdOreColumn, + EncryptedDoubleColumn, + EncryptedDoubleEqColumn, + EncryptedDoubleOrdColumn, + EncryptedDoubleOrdOreColumn, + EncryptedIntegerColumn, + EncryptedIntegerEqColumn, + EncryptedIntegerOrdColumn, + EncryptedIntegerOrdOreColumn, + EncryptedNumericColumn, + EncryptedNumericEqColumn, + EncryptedNumericOrdColumn, + EncryptedNumericOrdOreColumn, + EncryptedRealColumn, + EncryptedRealEqColumn, + EncryptedRealOrdColumn, + EncryptedRealOrdOreColumn, + EncryptedSmallintColumn, + EncryptedSmallintEqColumn, + EncryptedSmallintOrdColumn, + EncryptedSmallintOrdOreColumn, + EncryptedTextColumn, + EncryptedTextEqColumn, + EncryptedTextMatchColumn, + EncryptedTextOrdColumn, + EncryptedTextOrdOreColumn, + EncryptedTextSearchColumn, + EncryptedTimestampColumn, + EncryptedTimestampEqColumn, + EncryptedTimestampOrdColumn, + EncryptedTimestampOrdOreColumn, + types, +} from '@/eql/v3' +import type { ColumnSchema } from '@/schema' + +/** + * The canonical union of every v3 domain name — derived STRAIGHT from the real + * column union (`AnyEncryptedV3Column`) via the exported `EqlTypeForColumn` + * helper, not hand-copied. This is the key set the `Record` below must cover. + */ +export type EqlV3TypeName = EqlTypeForColumn<AnyEncryptedV3Column> + +/** One row of the type-driven matrix: everything a test needs about a domain. */ +export type DomainSpec = Readonly<{ + /** Column builder under test. */ + builder: (name: string) => AnyEncryptedV3Column + /** Concrete class the builder must instantiate (`toBeInstanceOf`). */ + ColumnClass: new ( + ...args: never[] + ) => AnyEncryptedV3Column + /** Plaintext axis emitted by `build().cast_as`. */ + castAs: ColumnSchema['cast_as'] + /** Semantic capability flags (`getQueryCapabilities()`). */ + capabilities: QueryCapabilities + /** + * The full `build().indexes` output — stored as DATA per row (like the Rust + * harness) rather than derived from `capabilities`, because `text_search` + * overrides `build()` to emit `unique + ore + match` where the capability → + * index rule would omit `unique` for an order-capable column. + */ + indexes: ColumnSchema['indexes'] + /** + * Representative + edge plaintext values that MUST round-trip through live + * encrypt/decrypt (consumed by `matrix-live.test.ts`). Typed as the loose + * plaintext union rather than per-row: the precise `castAs → plaintext` axis + * is already proven at the type level in `matrix.test-d.ts` (`InferPlaintext`), + * and a per-row generic would break the single `satisfies Record<…>` that is + * this file's coverage mechanism. Numeric samples are split integer-vs- + * fractional: `build()` emits `cast_as:'number'` uniformly so the FFI can't + * tell `integer` from `double`, and a fractional value on an int-named domain is + * untested territory (it would truncate against a real narrow PG column). + */ + samples: ReadonlyArray<string | number | bigint | boolean | Date> + /** + * Values that MUST fail encryption. Number domains reject `NaN`/`±Infinity` + * via a global guard; other domains omit this. + */ + errorSamples?: ReadonlyArray<number> +}> + +/** + * `Object.entries` that preserves the literal key union instead of widening to + * `string` — so `eqlType` in the runtime matrix stays `EqlV3TypeName`. + */ +export function typedEntries<K extends string, V>( + obj: Record<K, V>, +): Array<[K, V]> { + return Object.entries(obj) as Array<[K, V]> +} + +// Capability shorthands (mirror the SDK's internal presets). +const STORAGE = { + equality: false, + orderAndRange: false, + freeTextSearch: false, +} as const +const EQ = { + equality: true, + orderAndRange: false, + freeTextSearch: false, +} as const +const ORD = { + equality: true, + orderAndRange: true, + freeTextSearch: false, +} as const +const MATCH_ONLY = { + equality: false, + orderAndRange: false, + freeTextSearch: true, +} as const +const FULL = { + equality: true, + orderAndRange: true, + freeTextSearch: true, +} as const + +// Index shorthands (mirror `build().indexes`). Type-annotated rather than +// `as const`: annotation contextually types the literals so enum fields like +// `kind: 'ngram'` stay checked against the schema while arrays remain MUTABLE +// — `ColumnSchema['indexes']` rejects the `readonly` arrays `as const` produces. +type Indexes = ColumnSchema['indexes'] +const NONE: Indexes = {} +const UNIQUE_IDX: Indexes = { unique: { token_filters: [] } } +const ORE_IDX: Indexes = { ore: {} } +// Text order domains (`text_ord`, `text_ord_ore`) carry BOTH `hm` (unique) and +// `ob` (ore): their eql_v3 SQL domains require `hm` because text equality is +// HMAC-based, unlike numeric/date order domains which answer equality via `ob`. +const TEXT_ORD_IDX: Indexes = { unique: { token_filters: [] }, ore: {} } +const MATCH_BLOCK: NonNullable<Indexes>['match'] = { + tokenizer: { kind: 'ngram', token_length: 3 }, + token_filters: [{ kind: 'downcase' }], + k: 6, + m: 2048, + include_original: true, +} +const MATCH_IDX: Indexes = { match: MATCH_BLOCK } +const TEXT_SEARCH_IDX: Indexes = { + unique: { token_filters: [] }, + ore: {}, + match: MATCH_BLOCK, +} + +// Sample plaintexts per plaintext axis, consumed by `matrix-live.test.ts`. +// Numeric sets are split by domain width: integers (incl. type bounds) for +// smallint/integer, fractionals for real/double/numeric. See `DomainSpec.samples`. +const SMALLINT_S = [0, -1, 32767, -32768] as const +const INTEGER_S = [0, -42, 2147483647, -2147483648] as const +// bigint (int8) plaintexts: i64 bounds, 0, and a value beyond +// Number.MAX_SAFE_INTEGER (2^53 - 1) that would lose precision as a JS `number`. +const BIGINT_S = [ + 0n, + 9223372036854775807n, + -9223372036854775808n, + 9007199254740993n, +] as const +const REAL_S = [0, 77.5, -117.25, 0.5] as const +const DOUBLE_S = [0, -117.123456, 1e15, -1e15] as const +const NUMERIC_S = [0, 12345.678, -42, -0.5] as const +const TEXT_S = ['', 'ada@example.com', 'Ada Lovelace'] as const +// Text domains with an ORE (`ob`) term require non-empty positive samples to +// satisfy the real Postgres domain checks. Empty-string rejection is covered in +// matrix-live-pg. +const TEXT_ORE_S = [ + 'ada@example.com', + 'grace@example.com', + 'zora@example.org', +] as const +const BOOLEAN_S = [true, false] as const +const DATE_S = [ + new Date('2026-07-01T00:00:00.000Z'), + new Date('1970-01-01T00:00:00.000Z'), +] as const +// Timestamp domains (`cast_as: 'timestamp'`) preserve the full instant, unlike +// `date` which truncates to midnight. These samples deliberately carry a +// NON-ZERO time-of-day so the live round-trip actually detects a regression +// that truncates to the day boundary — reusing the midnight-only `DATE_S` here +// would let such a regression pass silently (see matrix.test.ts). +const TS_S = [ + new Date('2026-07-01T12:34:56.000Z'), + new Date('1970-01-01T23:59:59.000Z'), +] as const +// Every number domain rejects these via the global encrypt guard. +const NUM_ERR = [ + Number.NaN, + Number.POSITIVE_INFINITY, + Number.NEGATIVE_INFINITY, +] as const + +// biome-ignore format: one row per domain reads as a table; keep it dense. +export const V3_MATRIX = { + // integer + 'eql_v3.integer': { builder: types.Integer, ColumnClass: EncryptedIntegerColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: INTEGER_S, errorSamples: NUM_ERR }, + 'eql_v3.integer_eq': { builder: types.IntegerEq, ColumnClass: EncryptedIntegerEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: INTEGER_S, errorSamples: NUM_ERR }, + 'eql_v3.integer_ord_ore': { builder: types.IntegerOrdOre, ColumnClass: EncryptedIntegerOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: INTEGER_S, errorSamples: NUM_ERR }, + 'eql_v3.integer_ord': { builder: types.IntegerOrd, ColumnClass: EncryptedIntegerOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: INTEGER_S, errorSamples: NUM_ERR }, + // smallint + 'eql_v3.smallint': { builder: types.Smallint, ColumnClass: EncryptedSmallintColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: SMALLINT_S, errorSamples: NUM_ERR }, + 'eql_v3.smallint_eq': { builder: types.SmallintEq, ColumnClass: EncryptedSmallintEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: SMALLINT_S, errorSamples: NUM_ERR }, + 'eql_v3.smallint_ord_ore': { builder: types.SmallintOrdOre, ColumnClass: EncryptedSmallintOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: SMALLINT_S, errorSamples: NUM_ERR }, + 'eql_v3.smallint_ord': { builder: types.SmallintOrd, ColumnClass: EncryptedSmallintOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: SMALLINT_S, errorSamples: NUM_ERR }, + // bigint (int8) — plaintext is a JS `bigint`; no errorSamples (bigint has no NaN/Infinity) + 'eql_v3.int8': { builder: types.Bigint, ColumnClass: EncryptedBigintColumn, castAs: 'bigint', capabilities: STORAGE, indexes: NONE, samples: BIGINT_S }, + 'eql_v3.int8_eq': { builder: types.BigintEq, ColumnClass: EncryptedBigintEqColumn, castAs: 'bigint', capabilities: EQ, indexes: UNIQUE_IDX, samples: BIGINT_S }, + 'eql_v3.int8_ord_ore': { builder: types.BigintOrdOre, ColumnClass: EncryptedBigintOrdOreColumn, castAs: 'bigint', capabilities: ORD, indexes: ORE_IDX, samples: BIGINT_S }, + 'eql_v3.int8_ord': { builder: types.BigintOrd, ColumnClass: EncryptedBigintOrdColumn, castAs: 'bigint', capabilities: ORD, indexes: ORE_IDX, samples: BIGINT_S }, + // date + 'eql_v3.date': { builder: types.Date, ColumnClass: EncryptedDateColumn, castAs: 'date', capabilities: STORAGE, indexes: NONE, samples: DATE_S }, + 'eql_v3.date_eq': { builder: types.DateEq, ColumnClass: EncryptedDateEqColumn, castAs: 'date', capabilities: EQ, indexes: UNIQUE_IDX, samples: DATE_S }, + 'eql_v3.date_ord_ore': { builder: types.DateOrdOre, ColumnClass: EncryptedDateOrdOreColumn, castAs: 'date', capabilities: ORD, indexes: ORE_IDX, samples: DATE_S }, + 'eql_v3.date_ord': { builder: types.DateOrd, ColumnClass: EncryptedDateOrdColumn, castAs: 'date', capabilities: ORD, indexes: ORE_IDX, samples: DATE_S }, + // timestamp + 'eql_v3.timestamp': { builder: types.Timestamp, ColumnClass: EncryptedTimestampColumn, castAs: 'timestamp', capabilities: STORAGE, indexes: NONE, samples: TS_S }, + 'eql_v3.timestamp_eq': { builder: types.TimestampEq, ColumnClass: EncryptedTimestampEqColumn, castAs: 'timestamp', capabilities: EQ, indexes: UNIQUE_IDX, samples: TS_S }, + 'eql_v3.timestamp_ord_ore': { builder: types.TimestampOrdOre, ColumnClass: EncryptedTimestampOrdOreColumn, castAs: 'timestamp', capabilities: ORD, indexes: ORE_IDX, samples: TS_S }, + 'eql_v3.timestamp_ord': { builder: types.TimestampOrd, ColumnClass: EncryptedTimestampOrdColumn, castAs: 'timestamp', capabilities: ORD, indexes: ORE_IDX, samples: TS_S }, + // numeric + 'eql_v3.numeric': { builder: types.Numeric, ColumnClass: EncryptedNumericColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: NUMERIC_S, errorSamples: NUM_ERR }, + 'eql_v3.numeric_eq': { builder: types.NumericEq, ColumnClass: EncryptedNumericEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: NUMERIC_S, errorSamples: NUM_ERR }, + 'eql_v3.numeric_ord_ore': { builder: types.NumericOrdOre, ColumnClass: EncryptedNumericOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: NUMERIC_S, errorSamples: NUM_ERR }, + 'eql_v3.numeric_ord': { builder: types.NumericOrd, ColumnClass: EncryptedNumericOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: NUMERIC_S, errorSamples: NUM_ERR }, + // text + 'eql_v3.text': { builder: types.Text, ColumnClass: EncryptedTextColumn, castAs: 'string', capabilities: STORAGE, indexes: NONE, samples: TEXT_S }, + 'eql_v3.text_eq': { builder: types.TextEq, ColumnClass: EncryptedTextEqColumn, castAs: 'string', capabilities: EQ, indexes: UNIQUE_IDX, samples: TEXT_S }, + 'eql_v3.text_match': { builder: types.TextMatch, ColumnClass: EncryptedTextMatchColumn, castAs: 'string', capabilities: MATCH_ONLY, indexes: MATCH_IDX, samples: TEXT_S }, + 'eql_v3.text_ord_ore': { builder: types.TextOrdOre, ColumnClass: EncryptedTextOrdOreColumn, castAs: 'string', capabilities: ORD, indexes: TEXT_ORD_IDX, samples: TEXT_ORE_S }, + 'eql_v3.text_ord': { builder: types.TextOrd, ColumnClass: EncryptedTextOrdColumn, castAs: 'string', capabilities: ORD, indexes: TEXT_ORD_IDX, samples: TEXT_ORE_S }, + 'eql_v3.text_search': { builder: types.TextSearch, ColumnClass: EncryptedTextSearchColumn, castAs: 'string', capabilities: FULL, indexes: TEXT_SEARCH_IDX, samples: TEXT_ORE_S }, + // boolean + 'eql_v3.bool': { builder: types.Boolean, ColumnClass: EncryptedBooleanColumn, castAs: 'boolean', capabilities: STORAGE, indexes: NONE, samples: BOOLEAN_S }, + // real + 'eql_v3.real': { builder: types.Real, ColumnClass: EncryptedRealColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: REAL_S, errorSamples: NUM_ERR }, + 'eql_v3.real_eq': { builder: types.RealEq, ColumnClass: EncryptedRealEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: REAL_S, errorSamples: NUM_ERR }, + 'eql_v3.real_ord_ore': { builder: types.RealOrdOre, ColumnClass: EncryptedRealOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: REAL_S, errorSamples: NUM_ERR }, + 'eql_v3.real_ord': { builder: types.RealOrd, ColumnClass: EncryptedRealOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: REAL_S, errorSamples: NUM_ERR }, + // double + 'eql_v3.double': { builder: types.Double, ColumnClass: EncryptedDoubleColumn, castAs: 'number', capabilities: STORAGE, indexes: NONE, samples: DOUBLE_S, errorSamples: NUM_ERR }, + 'eql_v3.double_eq': { builder: types.DoubleEq, ColumnClass: EncryptedDoubleEqColumn, castAs: 'number', capabilities: EQ, indexes: UNIQUE_IDX, samples: DOUBLE_S, errorSamples: NUM_ERR }, + 'eql_v3.double_ord_ore': { builder: types.DoubleOrdOre, ColumnClass: EncryptedDoubleOrdOreColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: DOUBLE_S, errorSamples: NUM_ERR }, + 'eql_v3.double_ord': { builder: types.DoubleOrd, ColumnClass: EncryptedDoubleOrdColumn, castAs: 'number', capabilities: ORD, indexes: ORE_IDX, samples: DOUBLE_S, errorSamples: NUM_ERR }, +} as const satisfies Record<EqlV3TypeName, DomainSpec> diff --git a/packages/stack/__tests__/v3-matrix/matrix-audit.test-d.ts b/packages/stack/__tests__/v3-matrix/matrix-audit.test-d.ts new file mode 100644 index 00000000..cdaa95db --- /dev/null +++ b/packages/stack/__tests__/v3-matrix/matrix-audit.test-d.ts @@ -0,0 +1,31 @@ +/** + * Type-level pin of a real v3 asymmetry: audit metadata is available on the + * encrypt-side operations (which are chainable) but NOT on `decryptModel` / + * `bulkDecryptModels`, which return a bare `Promise<Result<…>>` rather than a + * chainable operation. Documented here as an executable invariant so the gap + * (v2's `decryptModel().audit(...)` has no v3 equivalent) can't silently change. + * + * Runs via `pnpm test:types`. + */ +import { describe, expectTypeOf, it } from 'vitest' +import type { EncryptionClient } from '@/encryption' +import { encryptedTable, typedClient, types } from '@/encryption/v3' + +const users = encryptedTable('u', { email: types.TextEq('email') }) +declare const client: EncryptionClient +const typed = typedClient(client, users) + +describe('v3 typed client audit/lock-context chainability (types)', () => { + it('exposes .audit() and .withLockContext() on the encrypt operation', () => { + const op = typed.encrypt('x', { table: users, column: users.email }) + expectTypeOf(op).toHaveProperty('audit') + expectTypeOf(op).toHaveProperty('withLockContext') + }) + + it('does NOT expose .audit()/.withLockContext() on decryptModel (bare Promise)', () => { + const result = typed.decryptModel({ email: {} as never }, users) + // A Promise, not a chainable operation — no audit/lock-context hook. + expectTypeOf(result).not.toHaveProperty('audit') + expectTypeOf(result).not.toHaveProperty('withLockContext') + }) +}) diff --git a/packages/stack/__tests__/v3-matrix/matrix-boundary-live-pg.test.ts b/packages/stack/__tests__/v3-matrix/matrix-boundary-live-pg.test.ts new file mode 100644 index 00000000..a01b91fa --- /dev/null +++ b/packages/stack/__tests__/v3-matrix/matrix-boundary-live-pg.test.ts @@ -0,0 +1,153 @@ +/** + * Boundary-value coverage through REAL narrow Postgres domain columns. + * + * `matrix-live.test.ts` round-trips every catalog sample — including the type + * EDGE values (INT4 max/min, smallint bounds, `1e15`) — but only through the + * FFI: it never inserts them into an actual `eql_v3.*` column. `matrix-live-pg` + * inserts real columns but only decrypts `samples[0]`. So the boundary samples + * (`samples[2]`/`[3]` in the catalog) have never made the full trip through a + * real, domain-typed Postgres column. + * + * eql_v3 domains store the ENCRYPTED envelope (not a narrow int4/float4), so + * this is not an at-rest overflow test — the value is encrypted client-side. + * What it DOES prove, in the same defence-in-depth spirit as `matrix-live-pg` + * ("an SDK-side bug can hide behind a clean FFI round-trip and only surface + * against real Postgres"): each boundary value passes the domain's CHECK + * constraints and survives the real encrypt -> INSERT (cast to `eql_v3.<type>`) + * -> SELECT -> decrypt path — catching envelope/encoding edge cases (e.g. int32 + * vs int64 handling, `1e15` precision) that only bite at the PG boundary. + */ +import 'dotenv/config' +import postgres from 'postgres' +import { afterAll, beforeAll, expect, it } from 'vitest' +import { EncryptionV3, encryptedTable } from '@/encryption/v3' +import { unwrapResult } from '../fixtures' +import { installEqlV3IfNeeded } from '../helpers/eql-v3' +import { describeLivePg, LIVE_EQL_V3_PG_ENABLED } from '../helpers/live-gate' +import { type EqlV3TypeName, typedEntries, V3_MATRIX } from './catalog' + +const databaseUrl = process.env.DATABASE_URL +const sql = LIVE_EQL_V3_PG_ENABLED + ? postgres(databaseUrl as string, { prepare: false }) + : (undefined as unknown as postgres.Sql) + +const TABLE_NAME = 'v3_matrix_boundary_live_pg' +const TEST_RUN_ID = `matrix-boundary-${Date.now()}-${Math.random().toString(36).slice(2, 8)}` + +/** `eql_v3.integer_ord` -> `int4_ord`: a valid, unique Postgres column name. */ +const slug = (t: EqlV3TypeName): string => t.replace('eql_v3.', '') + +// Only domains that actually carry boundary samples (index >= 2). Numeric +// domains have 4 samples (the type bounds live at [2]/[3]); the 3-sample text +// domains contribute [2]. Boolean/date/timestamp have just two and are absent. +const boundaryDomains = typedEntries(V3_MATRIX).filter( + ([, spec]) => spec.samples.length > 2, +) + +// One case per (domain, boundary sample index >= 2), labelled so a failure +// names the exact domain + sample. +const boundaryCases = boundaryDomains.flatMap(([t, spec]) => + spec.samples + .map((sample, i) => [t, sample, i] as const) + .filter(([, , i]) => i >= 2) + .map(([, sample, i]) => [`${t} #${i}`, slug(t), sample, i] as const), +) + +// The distinct boundary indices we need to seed (2 for text, 2 and 3 for +// numeric). Row `i` carries every boundary domain's `samples[i]` where present. +const boundaryIndices = [...new Set(boundaryCases.map(([, , , i]) => i))].sort( + (a, b) => a - b, +) + +const columns = Object.fromEntries( + boundaryDomains.map(([t, spec]) => [slug(t), spec.builder(slug(t))]), +) +const table = encryptedTable(TABLE_NAME, columns as never) + +type Row = { id: number } + +let client: Awaited<ReturnType<typeof EncryptionV3>> +// Postgres row id per boundary sample index. +const rowIdByIndex: Record<number, number> = {} + +beforeAll(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + + await installEqlV3IfNeeded(sql) + client = await EncryptionV3({ schemas: [table] as never }) + + // Columns are NULLABLE: an index-3 row has no value for a 3-sample text + // domain, so that column must be allowed to be NULL for that row. + const columnDefs = boundaryDomains + .map(([t]) => `"${slug(t)}" ${t}`) + .join(',\n ') + + await sql.unsafe(` + CREATE TABLE IF NOT EXISTS ${TABLE_NAME} ( + id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + test_run_id TEXT NOT NULL, + ${columnDefs} + ) + `) + + // One model row per boundary index, carrying only the domains that HAVE a + // sample at that index (encryptModel skips absent fields — matches + // matrix-live.test.ts's batching). + const modelRows = boundaryIndices.map((i) => { + const row: Record<string, unknown> = {} + for (const [t, spec] of boundaryDomains) { + if (i < spec.samples.length) row[slug(t)] = spec.samples[i] + } + return row + }) + + const encryptedRows = unwrapResult( + await client.bulkEncryptModels(modelRows as never, table as never), + ) as Array<Record<string, unknown>> + + // Insert each seeded row, populating only the columns present for that index + // and RETURNING the id so each case can target its exact row. + for (let r = 0; r < boundaryIndices.length; r++) { + const index = boundaryIndices[r] + const enc = encryptedRows[r] + const present = boundaryDomains.filter( + ([, spec]) => index < spec.samples.length, + ) + const colNames = present.map(([t]) => `"${slug(t)}"`) + const casts = present.map(([t], i) => `$${i + 2}::${t}`) + const values = present.map(([t]) => sql.json(enc[slug(t)] as never)) + const [row] = await sql.unsafe<Row[]>( + `INSERT INTO ${TABLE_NAME} (test_run_id, ${colNames.join(', ')}) + VALUES ($1, ${casts.join(', ')}) + RETURNING id`, + [TEST_RUN_ID, ...values], + ) + rowIdByIndex[index] = row.id + } +}, 120000) + +afterAll(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + await sql.unsafe(`DELETE FROM ${TABLE_NAME} WHERE test_run_id = $1`, [ + TEST_RUN_ID, + ]) + await sql.end() +}, 30000) + +describeLivePg('v3 boundary-value coverage through real domain columns', () => { + it.each( + boundaryCases, + )('%s survives a real INSERT/SELECT and decrypts', async (_label, col, sample, index) => { + const [row] = await sql.unsafe<Array<{ value: unknown }>>( + `SELECT "${col}"::jsonb AS value FROM ${TABLE_NAME} WHERE id = $1`, + [rowIdByIndex[index]], + ) + // Guard against a false pass: the stored cell must be real ciphertext. + expect(row.value).toHaveProperty('c') + + const decrypted = unwrapResult(await client.decrypt(row.value as never)) + // Boundary domains are numeric or text only (no date/timestamp), so the + // single-value decrypt returns the primitive directly. + expect(decrypted).toBe(sample) + }) +}) diff --git a/packages/stack/__tests__/v3-matrix/matrix-bulk.test.ts b/packages/stack/__tests__/v3-matrix/matrix-bulk.test.ts new file mode 100644 index 00000000..88a13266 --- /dev/null +++ b/packages/stack/__tests__/v3-matrix/matrix-bulk.test.ts @@ -0,0 +1,47 @@ +/** + * Bulk-at-scale proof for the v3 typed client (mirrors v2 `bulk-protect.test.ts`). + * The only pre-existing v3 bulk test ran against a hand-written stub; this one + * round-trips 100 models through the v3 typed client's `bulkEncryptModels` / + * `bulkDecryptModels` against real FFI, exercising v3 model reconstruction at + * scale. Live soft-skip. + */ +import 'dotenv/config' +import { beforeAll, expect, it } from 'vitest' +import { EncryptionV3, encryptedTable, types } from '@/encryption/v3' +import { unwrapResult } from '../fixtures' +import { describeLive } from '../helpers/live-gate' + +const people = encryptedTable('v3_bulk_people', { + nickname: types.TextEq('nickname'), + age: types.IntegerOrd('age'), +}) + +describeLive('v3 typed client bulk-at-scale (live)', () => { + let client: Awaited<ReturnType<typeof EncryptionV3<[typeof people]>>> + + beforeAll(async () => { + client = await EncryptionV3({ schemas: [people] }) + }, 30000) + + it('round-trips 100 models through bulkEncryptModels/bulkDecryptModels', async () => { + const rows = Array.from({ length: 100 }, (_, i) => ({ + nickname: `user-${i}`, + age: i, + })) + + const encrypted = unwrapResult(await client.bulkEncryptModels(rows, people)) + expect(encrypted).toHaveLength(100) + // Guard: every model field is a real ciphertext, not a plaintext passthrough. + expect(encrypted[0].nickname).toHaveProperty('c') + expect(encrypted[0].age).toHaveProperty('c') + + const decrypted = unwrapResult( + await client.bulkDecryptModels(encrypted, people), + ) + expect(decrypted).toHaveLength(100) + for (let i = 0; i < 100; i++) { + expect(decrypted[i].nickname).toBe(`user-${i}`) + expect(decrypted[i].age).toBe(i) + } + }, 60000) +}) diff --git a/packages/stack/__tests__/v3-matrix/matrix-identity-live.test.ts b/packages/stack/__tests__/v3-matrix/matrix-identity-live.test.ts new file mode 100644 index 00000000..8f047706 --- /dev/null +++ b/packages/stack/__tests__/v3-matrix/matrix-identity-live.test.ts @@ -0,0 +1,65 @@ +/** + * Live identity-aware coverage for the v3 typed client: lock-context round-trips + * and audit metadata. Kept separate from `matrix-lock-context.test.ts` because + * that file mocks `@cipherstash/protect-ffi` file-wide — a mock would neutralize + * a "live" assertion. No mock here: these hit a real CipherStash workspace and + * soft-skip when credentials (and, for lock context, `USER_JWT`) are absent, + * mirroring the v2 `audit.test.ts` / lock-context pattern. + */ +import 'dotenv/config' +import { beforeAll, describe, expect, it } from 'vitest' +import { EncryptionV3, encryptedTable, types } from '@/encryption/v3' +import { LockContext } from '@/identity' +import { unwrapResult } from '../fixtures' +import { describeLive, LIVE_CIPHERSTASH_ENABLED } from '../helpers/live-gate' + +const users = encryptedTable('v3_identity_live_users', { + email: types.TextEq('email'), +}) + +describeLive('v3 typed client identity-aware operations (live)', () => { + let client: Awaited<ReturnType<typeof EncryptionV3<[typeof users]>>> + + beforeAll(async () => { + client = await EncryptionV3({ schemas: [users] }) + }, 30000) + + it('round-trips a model with a lock context (encrypt + decrypt bound to identity)', async () => { + const userJwt = process.env.USER_JWT + if (!userJwt) { + console.log('Skipping lock context test - no USER_JWT provided') + return + } + + const lc = new LockContext() + const lockContext = await lc.identify(userJwt) + if (lockContext.failure) { + throw new Error(`[protect]: ${lockContext.failure.message}`) + } + + const encrypted = unwrapResult( + await client + .encryptModel({ email: 'ada@example.com' }, users) + .withLockContext(lockContext.data), + ) + expect(encrypted.email).toHaveProperty('c') + + // decryptModel takes the lock context as a positional 3rd arg. + const decrypted = unwrapResult( + await client.decryptModel(encrypted, users, lockContext.data), + ) + expect(decrypted.email).toBe('ada@example.com') + }, 30000) + + it('accepts .audit({ metadata }) on the encrypt path and still round-trips', async () => { + const encrypted = unwrapResult( + await client + .encrypt('secret@example.com', { table: users, column: users.email }) + .audit({ metadata: { sub: 'toby@cipherstash.com', type: 'encrypt' } }), + ) + expect(encrypted).toHaveProperty('c') + + const decrypted = unwrapResult(await client.decrypt(encrypted)) + expect(decrypted).toBe('secret@example.com') + }, 30000) +}) diff --git a/packages/stack/__tests__/v3-matrix/matrix-keyset.test.ts b/packages/stack/__tests__/v3-matrix/matrix-keyset.test.ts new file mode 100644 index 00000000..cd6c2a77 --- /dev/null +++ b/packages/stack/__tests__/v3-matrix/matrix-keyset.test.ts @@ -0,0 +1,55 @@ +/** + * Keyset configuration for the v3 typed client (mirrors v2 `keysets.test.ts`). + * The invalid-UUID case is deterministic — validation happens before any network + * — so it runs in CI without credentials; the round-trip case is live soft-skip. + */ +import 'dotenv/config' +import { ensureKeyset } from '@cipherstash/protect-ffi' +import { beforeAll, describe, expect, it } from 'vitest' +import { EncryptionV3, encryptedTable, types } from '@/encryption/v3' +import { unwrapResult } from '../fixtures' +import { describeLive, LIVE_CIPHERSTASH_ENABLED } from '../helpers/live-gate' + +const users = encryptedTable('v3_keyset_users', { + email: types.TextEq('email'), +}) + +describe('EncryptionV3 keyset config (deterministic)', () => { + it('rejects an invalid keyset id before touching the network', async () => { + await expect( + EncryptionV3({ + schemas: [users], + config: { keyset: { id: 'invalid-uuid' } }, + }), + ).rejects.toThrow( + '[encryption]: Invalid UUID provided for keyset id. Must be a valid UUID.', + ) + }) +}) + +describeLive('EncryptionV3 keyset config (live)', () => { + let keysetId: string + + beforeAll(async () => { + const keyset = await ensureKeyset({ name: 'Test' }) + keysetId = keyset.id + }, 30000) + + it('round-trips a value using an explicit keyset id', async () => { + const client = await EncryptionV3({ + schemas: [users], + config: { keyset: { id: keysetId } }, + }) + + const encrypted = unwrapResult( + await client.encrypt('hello@example.com', { + table: users, + column: users.email, + }), + ) + expect(encrypted).toHaveProperty('c') + + const decrypted = unwrapResult(await client.decrypt(encrypted)) + expect(decrypted).toBe('hello@example.com') + }, 30000) +}) diff --git a/packages/stack/__tests__/v3-matrix/matrix-live-pg.test.ts b/packages/stack/__tests__/v3-matrix/matrix-live-pg.test.ts new file mode 100644 index 00000000..80cf3f9d --- /dev/null +++ b/packages/stack/__tests__/v3-matrix/matrix-live-pg.test.ts @@ -0,0 +1,175 @@ +/** + * Live Postgres coverage for the v3 domains against a real installed eql_v3 + * extension. + * + * `matrix-live.test.ts` proves every domain round-trips through live FFI + * ciphertext, but never touches SQL. This file proves each domain's + * ciphertext, cast to the concrete Postgres domain type, survives a real + * INSERT/SELECT and still decrypts. Drizzle query behavior is covered at the + * public operator layer in `drizzle-v3/operators-live-pg.test.ts`. + * + * ONE mega table (every domain, one column each, like `matrix-live.test.ts`), + * two seeded rows (`samples[0]` / `samples[1]` from the catalog — every domain + * has at least two), and one storage proof per domain. + */ +import 'dotenv/config' +import postgres from 'postgres' +import { afterAll, beforeAll, expect, it } from 'vitest' +import { EncryptionV3, encryptedTable } from '@/encryption/v3' +import { unwrapResult } from '../fixtures' +import { assertV3WireEnvelope, installEqlV3IfNeeded } from '../helpers/eql-v3' +import { describeLivePg, LIVE_EQL_V3_PG_ENABLED } from '../helpers/live-gate' +import { + type DomainSpec, + type EqlV3TypeName, + typedEntries, + V3_MATRIX, +} from './catalog' + +// Previously force-skipped (CI run 28569708268, PR #540): `beforeAll` crashed +// with `PostgresError: invalid input syntax for type json` on the dynamic +// 35-column INSERT. Root cause was a postgres.js serialization gap — a bare +// ciphertext object stringified to `"[object Object]"` — now fixed by wrapping +// every INSERT param in `sql.json(...)` (see `beforeAll`; the fix landed right +// after the skip and the skip was simply left stale). Re-enabled here as an +// ordinary credential-gated suite: it runs in CI (which supplies DATABASE_URL + +// CS_* creds) and self-skips locally when they are absent. + +const databaseUrl = process.env.DATABASE_URL +const sql = LIVE_EQL_V3_PG_ENABLED + ? postgres(databaseUrl as string, { prepare: false }) + : (undefined as unknown as postgres.Sql) + +const TABLE_NAME = 'v3_matrix_live_pg' +const TEST_RUN_ID = `matrix-live-pg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}` + +/** `eql_v3.integer_ord` -> `integer_ord`: a valid, unique Postgres column name. */ +const slug = (t: EqlV3TypeName): string => t.replace('eql_v3.', '') + +const domains = typedEntries<EqlV3TypeName, DomainSpec>(V3_MATRIX) + +const columns = Object.fromEntries( + domains.map(([t, spec]) => [slug(t), spec.builder(slug(t))]), +) +const table = encryptedTable(TABLE_NAME, columns as never) + +const textOreDomains = domains.filter( + ([t]) => + t === 'eql_v3.text_ord_ore' || + t === 'eql_v3.text_ord' || + t === 'eql_v3.text_search', +) + +type Row = { id: number } + +let client: Awaited<ReturnType<typeof EncryptionV3>> +let idA: number + +beforeAll(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + + await installEqlV3IfNeeded(sql) + client = await EncryptionV3({ schemas: [table] as never }) + + const columnDefs = domains + .map(([t]) => `"${slug(t)}" ${t} NOT NULL`) + .join(',\n ') + + await sql.unsafe(` + CREATE TABLE IF NOT EXISTS ${TABLE_NAME} ( + id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + test_run_id TEXT NOT NULL, + ${columnDefs} + ) + `) + + // Two model rows: row A carries samples[0], row B carries samples[1], for + // every domain — every catalog `samples` array has at least two entries. + const rowA: Record<string, unknown> = {} + const rowB: Record<string, unknown> = {} + for (const [t, spec] of domains) { + rowA[slug(t)] = spec.samples[0] + rowB[slug(t)] = spec.samples[1] + } + + const [encA, encB] = unwrapResult( + await client.bulkEncryptModels([rowA, rowB] as never, table as never), + ) as Array<Record<string, unknown>> + + // Generation handshake: fail loudly on client/bundle wire-format skew + // before the wide multi-column INSERT turns it into an opaque 23514. + for (const [name, value] of Object.entries(encA)) { + assertV3WireEnvelope(value, `matrix-live-pg seed column ${name}`) + } + + const colNames = domains.map(([t]) => `"${slug(t)}"`) + const insertRow = async (enc: Record<string, unknown>): Promise<number> => { + const casts = domains.map(([t], i) => `$${i + 2}::${t}`) + // `sql.json(...)` (not the bare ciphertext object): postgres.js only infers + // an explicit wire type for `Parameter`/`Date`/`Uint8Array`/boolean/bigint — + // a plain object falls through to `'' + x` (`Bind()` in + // postgres/src/connection.js), i.e. the literal string `"[object Object]"`, + // which Postgres rejects as invalid JSON before the domain cast ever runs. + const values = domains.map(([t]) => sql.json(enc[slug(t)] as never)) + const [row] = await sql.unsafe<Row[]>( + `INSERT INTO ${TABLE_NAME} (test_run_id, ${colNames.join(', ')}) + VALUES ($1, ${casts.join(', ')}) + RETURNING id`, + [TEST_RUN_ID, ...values], + ) + return row.id + } + idA = await insertRow(encA) + await insertRow(encB) +}, 120000) + +afterAll(async () => { + if (!LIVE_EQL_V3_PG_ENABLED) return + await sql.unsafe(`DELETE FROM ${TABLE_NAME} WHERE test_run_id = $1`, [ + TEST_RUN_ID, + ]) + await sql.end() +}, 30000) + +describeLivePg( + 'v3 matrix live Postgres coverage (all domains)', + () => { + it.each( + textOreDomains, + )('%s: encrypted empty string is rejected by the Postgres domain', async (eqlType) => { + const col = slug(eqlType) + const column = (table as unknown as Record<string, unknown>)[col] as never + const encrypted = unwrapResult( + await client.encrypt('', { + table: table as never, + column, + }), + ) + + await expect( + sql.unsafe(`SELECT $1::${eqlType}`, [sql.json(encrypted as never)]), + ).rejects.toThrow(/violates check constraint/) + }) + + it.each( + domains, + )('%s: ciphertext survives a real INSERT/SELECT and still decrypts', async (eqlType, spec) => { + const col = slug(eqlType) + const [row] = await sql.unsafe<Array<{ value: unknown }>>( + `SELECT "${col}"::jsonb AS value FROM ${TABLE_NAME} WHERE id = $1`, + [idA], + ) + const decrypted = unwrapResult(await client.decrypt(row.value as never)) + const expected = spec.samples[0] + if (expected instanceof Date) { + // Lone-ciphertext decrypt has no column identity, so the cast_as-driven + // Date reconstruction (a decrypt-MODEL feature) cannot apply — the FFI + // returns the serialized instant (e.g. '2026-07-01T00:00:00Z'). Parse + // before comparing; toEqual on Dates compares the time value. + expect(new Date(decrypted as string)).toEqual(expected) + } else { + expect(decrypted).toBe(expected) + } + }) + }, +) diff --git a/packages/stack/__tests__/v3-matrix/matrix-live.test.ts b/packages/stack/__tests__/v3-matrix/matrix-live.test.ts new file mode 100644 index 00000000..8ea9eb52 --- /dev/null +++ b/packages/stack/__tests__/v3-matrix/matrix-live.test.ts @@ -0,0 +1,118 @@ +/** + * Live round-trip half of the type-driven v3 matrix — closes the "live cliff". + * + * The structural `matrix.test.ts` proves builder/eqlType/capabilities/`build()` + * wiring for all 35 domains WITHOUT ever touching real FFI ciphertext. This file + * completes the picture: every domain × every catalog `sample` is encrypted and + * decrypted through a live CipherStash client, so all 35 domains gain live + * behavioral proof (the Rust harness's whole premise) — not just 7. + * + * Round-trips go through the MODEL path (`encryptModel`/`decryptModel`) so + * `reconstructRow` rebuilds `Date` values uniformly for every plaintext axis; a + * lone single-value `decrypt` of a `date` domain returns an ISO string instead. + * + * The live work is BATCHED: one mega table spans every domain (one column each), + * and the whole sample set round-trips in a single `bulkEncryptModels` + + * `bulkDecryptModels` pair (2 network calls), not ~120 sequential ones. Error + * samples (NaN/±Infinity) use the single-value path — the guard throws + * client-side before any network — and so stay cheap even one at a time. + */ +import 'dotenv/config' +import { beforeAll, expect, it } from 'vitest' +import { EncryptionV3, encryptedTable } from '@/encryption/v3' +import { unwrapResult } from '../fixtures' +import { describeLive } from '../helpers/live-gate' +import { + type DomainSpec, + type EqlV3TypeName, + typedEntries, + V3_MATRIX, +} from './catalog' + +/** `eql_v3.integer_ord` -> `integer_ord`: a valid, per-domain-unique column name. */ +const slug = (t: EqlV3TypeName): string => t.replace('eql_v3.', '') + +// `as const satisfies Record<...>` gives `V3_MATRIX` a narrower type than +// `Record<EqlV3TypeName, DomainSpec>` (rows that omit the optional +// `errorSamples` field literally lack that key, rather than typing it +// `undefined`). Explicit type arguments pin `typedEntries`'s inferred `V` back +// to the declared `DomainSpec` shape — without them, `spec` below is inferred +// as the union of all 35 distinct row literals, and `.errorSamples` fails to +// resolve on members that omit the key (`tsc` catches this; `vitest run` +// alone would not, since it only transpiles `.test.ts` files, never +// typechecks them). +const domains = typedEntries<EqlV3TypeName, DomainSpec>(V3_MATRIX) + +// One mega table: one column per catalog domain. Column names (the slugs) are +// unique and never collide with `EncryptedTable` reserved property names. +const columns = Object.fromEntries( + domains.map(([t, spec]) => [slug(t), spec.builder(slug(t))]), +) +const table = encryptedTable('v3_matrix_live', columns as never) + +// Batch the samples into as few model rows as the widest sample set requires: +// row `i` carries every domain's `samples[i]` (domains with fewer samples are +// simply absent from later rows, and `encryptModel` skips absent fields). +const maxSamples = Math.max(...domains.map(([, spec]) => spec.samples.length)) +const modelRows = Array.from({ length: maxSamples }, (_, i) => { + const row: Record<string, unknown> = {} + for (const [t, spec] of domains) { + if (i < spec.samples.length) row[slug(t)] = spec.samples[i] + } + return row +}) + +// Flatten to one assertion per (domain, sample) — labelled so vitest reports the +// exact domain + sample index that fails. +const roundTripCases = domains.flatMap(([t, spec]) => + spec.samples.map((sample, i) => [`${t} #${i}`, slug(t), sample, i] as const), +) +const errorCases = domains.flatMap(([t, spec]) => + (spec.errorSamples ?? []).map( + (bad) => [`${t} (${bad})`, slug(t), bad] as const, + ), +) + +describeLive('v3 matrix live round-trip (all domains × samples)', () => { + let client: Awaited<ReturnType<typeof EncryptionV3>> + let encrypted: Array<Record<string, unknown>> + let decrypted: Array<Record<string, unknown>> + + beforeAll(async () => { + client = await EncryptionV3({ schemas: [table] as never }) + encrypted = unwrapResult( + await client.bulkEncryptModels(modelRows as never, table as never), + ) as Array<Record<string, unknown>> + decrypted = unwrapResult( + await client.bulkDecryptModels(encrypted as never, table as never), + ) as Array<Record<string, unknown>> + }, 60000) + + it.each( + roundTripCases, + )('%s round-trips through the model path', (_label, col, sample, i) => { + // Guard against a false pass: the field must be a real ciphertext (`c`), + // not a plaintext value that slipped through un-encrypted. + expect(encrypted[i][col]).toHaveProperty('c') + + const actual = decrypted[i][col] + if (sample instanceof Date) { + expect(actual).toBeInstanceOf(Date) + expect(actual).toEqual(sample) + } else { + expect(actual).toStrictEqual(sample) + } + }) + + // Mirrors number-protect.test.ts: NaN/±Infinity must be rejected. The guard + // (encrypt.ts) throws client-side, so the single-value path is the honest place + // to prove where the rejection fires. + it.each(errorCases)('%s is rejected at encrypt', async (_label, col, bad) => { + const column = (table as unknown as Record<string, unknown>)[col] + const result = await client.encrypt(bad as never, { + table: table as never, + column: column as never, + }) + expect(result.failure).toBeDefined() + }) +}) diff --git a/packages/stack/__tests__/v3-matrix/matrix-lock-context.test.ts b/packages/stack/__tests__/v3-matrix/matrix-lock-context.test.ts new file mode 100644 index 00000000..d8041e33 --- /dev/null +++ b/packages/stack/__tests__/v3-matrix/matrix-lock-context.test.ts @@ -0,0 +1,158 @@ +/** + * Offline lock-context wiring for the v3 TYPED client. + * + * `lock-context-wiring.test.ts` proves the base (v2) client forwards + * `identityClaim` and never sends a `serviceToken`. This file proves the same + * for the v3 typed client — and specifically covers the one shape the v2 wiring + * cannot: `typedClient.decryptModel(model, table, lockContext)` takes the lock + * context as a POSITIONAL arg (not a `.withLockContext()` chain), and must still + * thread `identityClaim` through to the FFI. Mocks `@cipherstash/protect-ffi` so + * it runs deterministically in CI without credentials. + */ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { LockContext } from '@/identity' +import { Encryption } from '@/index' + +// A protect-ffi-shaped encrypted payload (passes `isEncryptedPayload`). +const enc = () => ({ v: 2, i: { t: 'users', c: 'email' }, c: 'ciphertext' }) + +vi.mock('@cipherstash/protect-ffi', () => ({ + newClient: vi.fn(async () => ({ __mock: 'client' })), + encrypt: vi.fn(async () => enc()), + decrypt: vi.fn(async () => 'decrypted'), + encryptBulk: vi.fn(async (_c: unknown, opts: { plaintexts: unknown[] }) => + opts.plaintexts.map(enc), + ), + decryptBulk: vi.fn(async (_c: unknown, opts: { ciphertexts: unknown[] }) => + opts.ciphertexts.map(() => 'decrypted'), + ), + decryptBulkFallible: vi.fn( + async (_c: unknown, opts: { ciphertexts: unknown[] }) => + opts.ciphertexts.map(() => ({ data: 'decrypted' })), + ), + encryptQuery: vi.fn(async () => enc()), + encryptQueryBulk: vi.fn(async (_c: unknown, opts: { queries: unknown[] }) => + opts.queries.map(enc), + ), +})) + +import * as ffi from '@cipherstash/protect-ffi' +import { encryptedTable, typedClient, types } from '@/encryption/v3' + +const users = encryptedTable('users', { + email: types.TextEq('email'), +}) + +const IDENTITY_CLAIM = { identityClaim: ['sub'] } +const lockCtx = () => new LockContext() + +/** Deep scan for a `serviceToken` key anywhere in a value. */ +function hasServiceToken(value: unknown): boolean { + if (Array.isArray(value)) return value.some(hasServiceToken) + if (value && typeof value === 'object') { + if ('serviceToken' in value) return true + return Object.values(value).some(hasServiceToken) + } + return false +} + +// biome-ignore lint/suspicious/noExplicitAny: test helper unwraps Result +function unwrap(result: any) { + if (result.failure) { + throw new Error(`operation failed: ${result.failure.message}`) + } + return result.data +} + +/** Options the operation was last called with (second arg to the ffi fn). */ +// biome-ignore lint/suspicious/noExplicitAny: reading recorded mock args +const lastOpts = (fn: any) => fn.mock.calls.at(-1)[1] + +let typed: ReturnType<typeof typedClient> +let prevWorkspaceCrn: string | undefined + +beforeEach(async () => { + vi.clearAllMocks() + prevWorkspaceCrn = process.env.CS_WORKSPACE_CRN + process.env.CS_WORKSPACE_CRN = 'crn:ap-southeast-2.aws:test-workspace' + typed = typedClient(await Encryption({ schemas: [users] as never }), users) +}) + +afterEach(() => { + // Restore the prior value so this suite doesn't leak env state into + // other Vitest suites sharing the worker. + if (prevWorkspaceCrn === undefined) { + delete process.env.CS_WORKSPACE_CRN + } else { + process.env.CS_WORKSPACE_CRN = prevWorkspaceCrn + } +}) + +describe('v3 typed client lock-context wiring', () => { + it('encrypt().withLockContext() forwards identityClaim, no serviceToken', async () => { + unwrap( + await typed + .encrypt('alice@example.com', { table: users, column: users.email }) + .withLockContext(lockCtx()), + ) + const opts = lastOpts(ffi.encrypt) + expect(opts.lockContext).toEqual(IDENTITY_CLAIM) + expect(hasServiceToken(opts)).toBe(false) + }) + + it('encrypt().withLockContext() accepts a plain { identityClaim } object', async () => { + unwrap( + await typed + .encrypt('alice@example.com', { table: users, column: users.email }) + .withLockContext({ identityClaim: ['sub'] }), + ) + const opts = lastOpts(ffi.encrypt) + expect(opts.lockContext).toEqual(IDENTITY_CLAIM) + expect(hasServiceToken(opts)).toBe(false) + }) + + it('encryptModel().withLockContext() forwards per-payload identityClaim', async () => { + unwrap( + await typed + .encryptModel({ email: 'alice@example.com' }, users) + .withLockContext(lockCtx()), + ) + const opts = lastOpts(ffi.encryptBulk) + expect(opts.plaintexts[0].lockContext).toEqual(IDENTITY_CLAIM) + expect(hasServiceToken(opts)).toBe(false) + }) + + // The v3-specific path: lockContext supplied as a POSITIONAL 3rd arg, not a + // chain. Must still reach the FFI. + it('decryptModel(model, table, { identityClaim }) forwards identityClaim positionally', async () => { + unwrap( + await typed.decryptModel({ email: enc() }, users, { + identityClaim: ['sub'], + }), + ) + const opts = lastOpts(ffi.decryptBulk) + expect(opts.ciphertexts[0].lockContext).toEqual(IDENTITY_CLAIM) + expect(hasServiceToken(opts)).toBe(false) + }) + + it('decryptModel(model, table, lockContext) accepts a LockContext instance positionally', async () => { + unwrap(await typed.decryptModel({ email: enc() }, users, lockCtx())) + const opts = lastOpts(ffi.decryptBulk) + expect(opts.ciphertexts[0].lockContext).toEqual(IDENTITY_CLAIM) + expect(hasServiceToken(opts)).toBe(false) + }) + + it('bulkDecryptModels(rows, table, lockContext) forwards per-row identityClaim', async () => { + unwrap(await typed.bulkDecryptModels([{ email: enc() }], users, lockCtx())) + const opts = lastOpts(ffi.decryptBulk) + expect(opts.ciphertexts[0].lockContext).toEqual(IDENTITY_CLAIM) + expect(hasServiceToken(opts)).toBe(false) + }) + + it('decryptModel WITHOUT a lock context sends neither lockContext nor serviceToken', async () => { + unwrap(await typed.decryptModel({ email: enc() }, users)) + const opts = lastOpts(ffi.decryptBulk) + expect(opts.ciphertexts[0].lockContext).toBeUndefined() + expect(hasServiceToken(opts)).toBe(false) + }) +}) diff --git a/packages/stack/__tests__/v3-matrix/matrix.test-d.ts b/packages/stack/__tests__/v3-matrix/matrix.test-d.ts new file mode 100644 index 00000000..bd6cff8a --- /dev/null +++ b/packages/stack/__tests__/v3-matrix/matrix.test-d.ts @@ -0,0 +1,97 @@ +/** + * Type-level half of the type-driven v3 matrix. + * + * Runtime `.each` cannot parameterise a compile-time `expectTypeOf<T>()` by row + * data, so the type-level surface is asserted against a concrete mixed-tier + * table. The columns under test are constructed FROM the `V3_MATRIX` builders + * (via specific keys) rather than hand-copied — `as const satisfies` preserves + * each builder's precise return type, so one catalog genuinely drives both the + * runtime and type-level surfaces. + * + * Runs via `pnpm test:types` (picked up by the `.test-d.ts` typecheck glob). + */ +import { describe, expectTypeOf, it } from 'vitest' +import { + encryptedTable, + type InferPlaintext, + type QueryableColumnsOf, + type QueryTypesForColumn, +} from '@/eql/v3' +import { type EqlV3TypeName, V3_MATRIX } from './catalog' + +// One mixed-tier table spanning every capability tier + plaintext axis, built +// from the catalog's own builders. +const records = encryptedTable('records', { + count: V3_MATRIX['eql_v3.integer'].builder('count'), // number, storage-only + score: V3_MATRIX['eql_v3.integer_eq'].builder('score'), // number, equality + rank: V3_MATRIX['eql_v3.integer_ord'].builder('rank'), // number, order + range + createdAt: V3_MATRIX['eql_v3.timestamp_ord'].builder('created_at'), // date + email: V3_MATRIX['eql_v3.text_search'].builder('email'), // string, full-text + active: V3_MATRIX['eql_v3.bool'].builder('active'), // boolean, storage-only +}) + +describe('eql_v3 type-driven matrix (types)', () => { + it('maps each column to its plaintext axis', () => { + expectTypeOf<InferPlaintext<typeof records>>().toEqualTypeOf<{ + count: number + score: number + rank: number + createdAt: Date + email: string + active: boolean + }>() + }) + + it('derives the queryType union per column from its capabilities', () => { + expectTypeOf< + QueryTypesForColumn<typeof records.count> + >().toEqualTypeOf<never>() + expectTypeOf< + QueryTypesForColumn<typeof records.score> + >().toEqualTypeOf<'equality'>() + expectTypeOf<QueryTypesForColumn<typeof records.rank>>().toEqualTypeOf< + 'equality' | 'orderAndRange' + >() + expectTypeOf<QueryTypesForColumn<typeof records.createdAt>>().toEqualTypeOf< + 'equality' | 'orderAndRange' + >() + expectTypeOf<QueryTypesForColumn<typeof records.email>>().toEqualTypeOf< + 'equality' | 'orderAndRange' | 'freeTextSearch' + >() + expectTypeOf< + QueryTypesForColumn<typeof records.active> + >().toEqualTypeOf<never>() + }) + + it('excludes storage-only columns from the queryable set', () => { + type Queryable = QueryableColumnsOf<typeof records> + + // A queryable column is a member of the set... + const ok: Queryable = V3_MATRIX['eql_v3.integer_eq'].builder('score') + expectTypeOf(ok).toExtend<Queryable>() + + // ...but a storage-only column is not. + // @ts-expect-error - storage-only integer column is excluded from QueryableColumnsOf + const _notQueryable: Queryable = + V3_MATRIX['eql_v3.integer'].builder('count') + + // @ts-expect-error - storage-only boolean column is excluded from QueryableColumnsOf + const _boolNotQueryable: Queryable = + V3_MATRIX['eql_v3.bool'].builder('active') + }) + + it('anchors the catalog key union to the real column source of truth', () => { + // `EqlV3TypeName` is derived from `AnyEncryptedV3Column`, so every real + // domain name is a member — no hand-copied list. + expectTypeOf<'eql_v3.text_search'>().toExtend<EqlV3TypeName>() + expectTypeOf<'eql_v3.bool'>().toExtend<EqlV3TypeName>() + + // A key outside the real domain set is rejected — this is what makes the + // `Record<EqlV3TypeName, DomainSpec>` catalog a compile-time coverage check. + const bad: Partial<Record<EqlV3TypeName, number>> = { + // @ts-expect-error - 'eql_v3.nope' is not a member of EqlV3TypeName + 'eql_v3.nope': 1, + } + void bad + }) +}) diff --git a/packages/stack/__tests__/v3-matrix/matrix.test.ts b/packages/stack/__tests__/v3-matrix/matrix.test.ts new file mode 100644 index 00000000..cbecb2a0 --- /dev/null +++ b/packages/stack/__tests__/v3-matrix/matrix.test.ts @@ -0,0 +1,67 @@ +/** + * Runtime half of the type-driven v3 matrix. + * + * A single `it.each` over the `V3_MATRIX` catalog asserts the full per-domain + * contract for every EQL v3 scalar domain. This SUPERSEDES the hand-rolled + * `domainCases` loop that previously lived in `schema-v3.test.ts`: the `build()` + * `toStrictEqual` here is byte-for-byte the same assertion, driven off the + * shared source of truth. Adding a domain row extends coverage automatically. + */ +import { describe, expect, it } from 'vitest' +import { typedEntries, V3_MATRIX } from './catalog' + +describe('eql_v3 type-driven domain matrix (runtime)', () => { + // `typedEntries` keeps `eqlType` as `EqlV3TypeName` rather than widening to + // `string`, so the key stays precisely typed through the callback. + it.each( + typedEntries(V3_MATRIX), + )('%s: builder, eqlType, capabilities and build() are consistent', (eqlType, spec) => { + const col = spec.builder('value') + + expect(col).toBeInstanceOf(spec.ColumnClass) + expect(col.getName()).toBe('value') + expect(col.getEqlType()).toBe(eqlType) + expect(col.getQueryCapabilities()).toStrictEqual(spec.capabilities) + expect(col.isQueryable()).toBe( + Object.values(spec.capabilities).some(Boolean), + ) + + // Full-fidelity `build()` check: exactly `{ cast_as, indexes }`, no extra + // keys — so SDK-facing metadata (eqlType/capabilities) can never leak. + expect(col.build()).toStrictEqual({ + cast_as: spec.castAs, + indexes: spec.indexes, + }) + }) + + it.each([ + 'eql_v3.text_ord_ore', + 'eql_v3.text_ord', + 'eql_v3.text_search', + ] as const)('%s uses non-empty positive samples for live Postgres inserts', (eqlType) => { + expect(V3_MATRIX[eqlType].samples[0]).not.toBe('') + }) + + // `timestamp` domains set `cast_as: 'timestamp'` (not `'date'`) precisely to + // preserve the time-of-day. The live matrix can only PROVE that preservation + // if its samples actually carry a non-zero time-of-day: a regression back to + // `'date'` truncation collapses the instant to midnight, so midnight-only + // samples (`DATE_S`) would survive truncation and pass silently. This guards + // the live suite's truncation-detection power at build time — flip the + // timestamp rows back to `DATE_S` and this fails. + it.each([ + 'eql_v3.timestamp', + 'eql_v3.timestamp_eq', + 'eql_v3.timestamp_ord_ore', + 'eql_v3.timestamp_ord', + ] as const)('%s carries a sample with a non-zero time-of-day', (eqlType) => { + const samples = V3_MATRIX[eqlType].samples as readonly Date[] + const hasTimeOfDay = (d: Date) => + d.getUTCHours() + + d.getUTCMinutes() + + d.getUTCSeconds() + + d.getUTCMilliseconds() > + 0 + expect(samples.some(hasTimeOfDay)).toBe(true) + }) +}) diff --git a/packages/stack/__tests__/wasm-inline-column-name.test.ts b/packages/stack/__tests__/wasm-inline-column-name.test.ts new file mode 100644 index 00000000..ee03ecf1 --- /dev/null +++ b/packages/stack/__tests__/wasm-inline-column-name.test.ts @@ -0,0 +1,46 @@ +import { describe, expect, it, vi } from 'vitest' + +// This unit test only covers `getColumnName`, which resolves a column's name +// structurally and never touches WASM. Mock the `/wasm-inline` specifiers so +// Vitest can load `../src/wasm-inline` without resolving the real inlined WASM +// entries (which aren't exported for the test bundler). +vi.mock('@cipherstash/auth/wasm-inline', () => ({ + AccessKeyStrategy: { + create: vi.fn(), + }, +})) + +vi.mock('@cipherstash/protect-ffi/wasm-inline', () => ({ + decrypt: vi.fn(), + encrypt: vi.fn(), + isEncrypted: vi.fn(), + newClient: vi.fn(), +})) + +import { types } from '../src/eql/v3' +import { encryptedColumn, encryptedField } from '../src/schema' +import { getColumnName } from '../src/wasm-inline' + +describe('wasm-inline getColumnName', () => { + it('returns the name for a v2 EncryptedColumn', () => { + expect(getColumnName(encryptedColumn('email'))).toBe('email') + }) + + it('returns the name for a v2 EncryptedField', () => { + expect(getColumnName(encryptedField('profile'))).toBe('profile') + }) + + it('returns the name for a v3 EncryptedTextSearchColumn (structural, no instanceof)', () => { + // Regression: widening EncryptOptions.column to the structural + // BuildableColumn made v3 columns type-check at the wasm-inline encrypt + // entry, but the old `instanceof EncryptedColumn || EncryptedField` gate + // threw at runtime. The entry now resolves the name structurally so a v3 + // column genuinely round-trips through WasmEncryptionClient.encrypt(). + expect(getColumnName(types.TextSearch('email'))).toBe('email') + }) + + it('throws when given a value that does not expose getName()', () => { + // Plain JS callers can bypass the type system — guard at runtime. + expect(() => getColumnName({} as never)).toThrow(/getName/) + }) +}) diff --git a/packages/stack/__tests__/wasm-inline-new-client.test.ts b/packages/stack/__tests__/wasm-inline-new-client.test.ts new file mode 100644 index 00000000..b33c4d72 --- /dev/null +++ b/packages/stack/__tests__/wasm-inline-new-client.test.ts @@ -0,0 +1,115 @@ +/** + * Offline coverage for the WASM `Encryption` factory's `newClient` call shape. + * + * protect-ffi 0.25 changed `newClient` from a two-argument form + * (`newClient(strategy, options)`) to a single options object with the + * strategy nested under `strategy`: + * `newClient({ strategy, encryptConfig, clientId, clientKey })`. + * + * `wasm-inline.ts` performs that migration, but the only end-to-end exercise + * of the factory is the Deno e2e (`e2e/wasm/roundtrip.test.ts`), which skips + * without real `CS_*` secrets — so a regression in the call shape (e.g. + * reverting to the two-arg form, dropping `clientId`/`clientKey`, or failing to + * normalise `cast_as`) would pass the normal suite. These tests mock the WASM + * bindings and assert the exact argument object handed to `wasmNewClient`. + */ + +import { beforeEach, describe, expect, it, vi } from 'vitest' + +vi.mock('@cipherstash/auth/wasm-inline', () => ({ + AccessKeyStrategy: { + create: vi.fn(() => ({ __mock: 'access-key-strategy' })), + }, + OidcFederationStrategy: class {}, +})) + +vi.mock('@cipherstash/protect-ffi/wasm-inline', () => ({ + newClient: vi.fn(async () => ({ __mock: 'wasm-client' })), + encrypt: vi.fn(), + decrypt: vi.fn(), + isEncrypted: vi.fn(), +})) + +import { newClient as wasmNewClient } from '@cipherstash/protect-ffi/wasm-inline' +import { Encryption, encryptedColumn, encryptedTable } from '../src/wasm-inline' + +const CRN = 'crn:ap-southeast-2.aws:test-workspace' + +const users = encryptedTable('users', { + email: encryptedColumn('email'), +}) + +beforeEach(() => { + vi.clearAllMocks() +}) + +describe('wasm-inline Encryption → newClient (protect-ffi 0.25 single-object form)', () => { + it('calls newClient with a single options object, not the 0.24 two-arg form', async () => { + await Encryption({ + schemas: [users], + config: { + workspaceCrn: CRN, + accessKey: 'CSAK.test', + clientId: 'cid', + clientKey: 'ckey', + }, + }) + + expect(vi.mocked(wasmNewClient)).toHaveBeenCalledTimes(1) + // The 0.24 form passed the strategy as a separate first positional arg. + // The 0.25 form is a single object — guard against regressing to two args. + const call = vi.mocked(wasmNewClient).mock.calls[0] + expect(call).toHaveLength(1) + }) + + it('nests the resolved strategy and forwards clientId / clientKey', async () => { + await Encryption({ + schemas: [users], + config: { + workspaceCrn: CRN, + accessKey: 'CSAK.test', + clientId: 'cid', + clientKey: 'ckey', + }, + }) + + // biome-ignore lint/suspicious/noExplicitAny: reading the recorded single options object + const arg = vi.mocked(wasmNewClient).mock.calls[0][0] as any + expect(arg.strategy).toEqual({ __mock: 'access-key-strategy' }) + expect(arg.clientId).toBe('cid') + expect(arg.clientKey).toBe('ckey') + }) + + it('passes a cast_as-normalised encryptConfig (SDK "string" → EQL "text")', async () => { + // `encryptedColumn('email')` defaults to `cast_as: 'string'`; the WASM + // client only accepts EQL-native variants, so the factory must run the + // config through `normalizeCastAs` before handing it to `newClient`. + await Encryption({ + schemas: [users], + config: { + workspaceCrn: CRN, + accessKey: 'CSAK.test', + clientId: 'cid', + clientKey: 'ckey', + }, + }) + + // biome-ignore lint/suspicious/noExplicitAny: navigating the recorded encryptConfig + const arg = vi.mocked(wasmNewClient).mock.calls[0][0] as any + expect(arg.encryptConfig).toBeDefined() + expect(arg.encryptConfig.tables.users.email.cast_as).toBe('text') + }) + + it('uses an explicit config.strategy verbatim on the strategy path', async () => { + const explicit = { getToken: vi.fn() } + await Encryption({ + schemas: [users], + // biome-ignore lint/suspicious/noExplicitAny: exercise the strategy arm of the config union + config: { strategy: explicit, clientId: 'cid', clientKey: 'ckey' } as any, + }) + + // biome-ignore lint/suspicious/noExplicitAny: reading the recorded single options object + const arg = vi.mocked(wasmNewClient).mock.calls[0][0] as any + expect(arg.strategy).toBe(explicit) + }) +}) diff --git a/packages/stack/__tests__/wasm-inline-normalize.test.ts b/packages/stack/__tests__/wasm-inline-normalize.test.ts index 77afbb5e..5f6bfd56 100644 --- a/packages/stack/__tests__/wasm-inline-normalize.test.ts +++ b/packages/stack/__tests__/wasm-inline-normalize.test.ts @@ -10,6 +10,7 @@ const EXPECTED_MAPPING: Readonly<Record<string, string>> = { bigint: 'big_int', boolean: 'boolean', date: 'date', + timestamp: 'timestamp', number: 'double', string: 'text', json: 'jsonb', diff --git a/packages/stack/__tests__/wasm-inline-strategy.test.ts b/packages/stack/__tests__/wasm-inline-strategy.test.ts index b082b9fd..4880bc43 100644 --- a/packages/stack/__tests__/wasm-inline-strategy.test.ts +++ b/packages/stack/__tests__/wasm-inline-strategy.test.ts @@ -58,6 +58,26 @@ describe('wasm-inline resolveStrategy', () => { expect(vi.mocked(AccessKeyStrategy.create)).not.toHaveBeenCalled() }) + it('throws when the access-key arm is missing workspaceCrn or accessKey', () => { + // JS callers bypass the compile-time union, so the no-strategy arm must + // reject a missing CRN or access key instead of forwarding `undefined` + // into `AccessKeyStrategy.create`. + expect(() => + // biome-ignore lint/suspicious/noExplicitAny: deliberately invalid — no strategy, no accessKey + resolveStrategy({ workspaceCrn: CRN } as any), + ).toThrowError( + /`config\.workspaceCrn` and `config\.accessKey` are required/, + ) + expect(() => + // biome-ignore lint/suspicious/noExplicitAny: deliberately invalid — no strategy, no workspaceCrn + resolveStrategy({ accessKey: 'CSAK.test' } as any), + ).toThrowError( + /`config\.workspaceCrn` and `config\.accessKey` are required/, + ) + // The guard must short-circuit *before* building a strategy. + expect(vi.mocked(AccessKeyStrategy.create)).not.toHaveBeenCalled() + }) + it('throws when both strategy and accessKey are supplied', () => { const both = { workspaceCrn: CRN, diff --git a/packages/stack/package.json b/packages/stack/package.json index 60c00c1c..28ccc105 100644 --- a/packages/stack/package.json +++ b/packages/stack/package.json @@ -51,6 +51,15 @@ "schema": [ "./dist/schema/index.d.ts" ], + "eql/v3": [ + "./dist/eql/v3/index.d.ts" + ], + "eql/v3/drizzle": [ + "./dist/eql/v3/drizzle/index.d.ts" + ], + "v3": [ + "./dist/encryption/v3.d.ts" + ], "types": [ "./dist/types-public.d.ts" ], @@ -119,6 +128,36 @@ "default": "./dist/schema/index.cjs" } }, + "./eql/v3": { + "import": { + "types": "./dist/eql/v3/index.d.ts", + "default": "./dist/eql/v3/index.js" + }, + "require": { + "types": "./dist/eql/v3/index.d.cts", + "default": "./dist/eql/v3/index.cjs" + } + }, + "./eql/v3/drizzle": { + "import": { + "types": "./dist/eql/v3/drizzle/index.d.ts", + "default": "./dist/eql/v3/drizzle/index.js" + }, + "require": { + "types": "./dist/eql/v3/drizzle/index.d.cts", + "default": "./dist/eql/v3/drizzle/index.cjs" + } + }, + "./v3": { + "import": { + "types": "./dist/encryption/v3.d.ts", + "default": "./dist/encryption/v3.js" + }, + "require": { + "types": "./dist/encryption/v3.d.cts", + "default": "./dist/encryption/v3.cjs" + } + }, "./types": { "import": { "types": "./dist/types-public.d.ts", @@ -191,7 +230,10 @@ "prebuild": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"", "build": "tsup", "dev": "tsup --watch", + "analyze:complexity": "fta src/eql/v3 --score-cap 69", + "db:eql-v3:install": "tsx scripts/install-eql-v3.ts", "test": "vitest run", + "test:types": "vitest --run --typecheck.only", "release": "tsup" }, "devDependencies": { @@ -201,6 +243,7 @@ "dotenv": "17.4.2", "drizzle-orm": "^0.45.2", "execa": "^9.5.2", + "fta-cli": "3.0.0", "json-schema-to-typescript": "^15.0.2", "postgres": "^3.4.8", "tsup": "catalog:repo", @@ -214,7 +257,7 @@ "dependencies": { "@byteslice/result": "0.2.0", "@cipherstash/auth": "catalog:repo", - "@cipherstash/protect-ffi": "0.26.0", + "@cipherstash/protect-ffi": "0.28.0", "evlog": "1.11.0", "uuid": "14.0.0", "zod": "3.25.76" diff --git a/packages/stack/scripts/install-eql-v3.ts b/packages/stack/scripts/install-eql-v3.ts new file mode 100644 index 00000000..c94f65b6 --- /dev/null +++ b/packages/stack/scripts/install-eql-v3.ts @@ -0,0 +1,27 @@ +import { config } from 'dotenv' + +// Load env files in Next.js precedence order (.env.local wins over .env for the +// same key, since dotenv does not overwrite already-set vars). `quiet: true` +// suppresses dotenv v17's `injected env (N) from …` banner so this script does +// not print noisy, non-deterministic lines in CI. Mirrors the CLI entrypoint +// (packages/cli/src/bin/main.ts). +config({ path: '.env.local', quiet: true }) +config({ path: '.env.development.local', quiet: true }) +config({ path: '.env.development', quiet: true }) +config({ path: '.env', quiet: true }) + +import postgres from 'postgres' +import { installEqlV3IfNeeded } from '../__tests__/helpers/eql-v3' + +if (!process.env.DATABASE_URL) { + throw new Error('Missing env.DATABASE_URL') +} + +const sql = postgres(process.env.DATABASE_URL, { prepare: false }) + +try { + await installEqlV3IfNeeded(sql) + console.log('eql_v3 (current bundle) is installed') +} finally { + await sql.end() +} diff --git a/packages/stack/src/encryption/helpers/index.ts b/packages/stack/src/encryption/helpers/index.ts index 164da509..78c1371e 100644 --- a/packages/stack/src/encryption/helpers/index.ts +++ b/packages/stack/src/encryption/helpers/index.ts @@ -1,22 +1,27 @@ import type { Encrypted as CipherStashEncrypted, EncryptedQuery as CipherStashEncryptedQuery, + EncryptedV3Query as CipherStashEncryptedV3Query, KeysetIdentifier as KeysetIdentifierFfi, } from '@cipherstash/protect-ffi' import type { Encrypted, EncryptedQueryResult, KeysetIdentifier } from '@/types' /** * The shape `encryptQuery` / `encryptQueryBulk` can return: a full storage - * payload (returned for `ste_vec_term` containment queries) or a query-only + * payload (returned for v2 `ste_vec_term` containment queries), a query-only * payload with no ciphertext (scalar `unique`/`match`/`ore` lookups and - * `ste_vec_selector` path queries). + * `ste_vec_selector` path queries), or — under `eqlVersion: 3` — the + * `eql_v3.jsonb_query` containment needle. * * TODO: duplicated in `@cipherstash/protect` — see * `packages/protect/src/helpers/index.ts`. Both copies should be removed once * `@cipherstash/protect-ffi` exports a named alias for the `encryptQuery` * return type (https://github.com/cipherstash/stack/pull/473). */ -type EncryptedQueryTerm = CipherStashEncrypted | CipherStashEncryptedQuery +type EncryptedQueryTerm = + | CipherStashEncrypted + | CipherStashEncryptedQuery + | CipherStashEncryptedV3Query export type EncryptedPgComposite = { data: Encrypted diff --git a/packages/stack/src/encryption/helpers/infer-index-type.ts b/packages/stack/src/encryption/helpers/infer-index-type.ts index 80eaf6ad..3830136f 100644 --- a/packages/stack/src/encryption/helpers/infer-index-type.ts +++ b/packages/stack/src/encryption/helpers/infer-index-type.ts @@ -1,13 +1,17 @@ -import type { JsPlaintext, QueryOpName } from '@cipherstash/protect-ffi' -import type { EncryptedColumn } from '@/schema' -import type { FfiIndexTypeName, QueryTypeName } from '../../types' +import type { QueryOpName } from '@cipherstash/protect-ffi' +import type { + BuildableQueryColumn, + FfiIndexTypeName, + Plaintext, + QueryTypeName, +} from '../../types' import { queryTypeToFfi, queryTypeToQueryOp } from '../../types' /** * Infer the primary index type from a column's configured indexes. * Priority: unique > match > ore > ste_vec (for scalar queries) */ -export function inferIndexType(column: EncryptedColumn): FfiIndexTypeName { +export function inferIndexType(column: BuildableQueryColumn): FfiIndexTypeName { const config = column.build() const indexes = config.indexes @@ -31,16 +35,16 @@ export function inferIndexType(column: EncryptedColumn): FfiIndexTypeName { * - String → ste_vec_selector (JSONPath queries like '$.user.email') * - Object/Array/Number/Boolean → ste_vec_term (containment queries) */ -export function inferQueryOpFromPlaintext(plaintext: JsPlaintext): QueryOpName { +export function inferQueryOpFromPlaintext(plaintext: Plaintext): QueryOpName { if (typeof plaintext === 'string') { return 'ste_vec_selector' } - // Objects, arrays, numbers, booleans are all valid JSONB containment values + // Objects (incl. Date), arrays, numbers, booleans are all valid JSONB + // containment values if ( typeof plaintext === 'object' || typeof plaintext === 'number' || - typeof plaintext === 'boolean' || - typeof plaintext === 'bigint' + typeof plaintext === 'boolean' ) { return 'ste_vec_term' } @@ -52,7 +56,7 @@ export function inferQueryOpFromPlaintext(plaintext: JsPlaintext): QueryOpName { * Validate that the specified index type is configured on the column */ export function validateIndexType( - column: EncryptedColumn, + column: BuildableQueryColumn, indexType: FfiIndexTypeName, ): void { const config = column.build() @@ -72,6 +76,27 @@ export function validateIndexType( } } +/** + * v3-only: an order-capable column answers EQUALITY via its `ore` (`ob`) index. + * + * The v3 capability contract (`src/schema/v3`) documents `equality` as "exact-match + * lookups (EQL `hm`, or comparison via `ob`)", so an order-capable column with only + * an `ore` index still supports equality — the equality-vs-range distinction is made + * by the SQL comparison operator (`=` vs `>=`), NOT by the ciphertext (the FFI emits + * the same `ob` term either way). The default `equality → unique` mapping would + * wrongly reject these columns. + * + * Gated on `getQueryCapabilities`, which only v3 queryable columns expose — a v2 + * `EncryptedColumn` lacks it and so never matches, preserving v2's + * equality-without-unique throw unchanged (the no-v2-change constraint). + */ +function resolvesEqualityViaOre(column: BuildableQueryColumn): boolean { + if (!('getQueryCapabilities' in column)) return false + if (!column.getQueryCapabilities().equality) return false + const indexes = column.build().indexes ?? {} + return !indexes.unique && !!indexes.ore +} + /** * Resolve the index type and query operation for a query. * Validates the index type is configured on the column when queryType is explicit. @@ -84,15 +109,23 @@ export function validateIndexType( * @throws Error if ste_vec is inferred but queryOp cannot be determined */ export function resolveIndexType( - column: EncryptedColumn, + column: BuildableQueryColumn, queryType?: QueryTypeName, - plaintext?: JsPlaintext | null, + plaintext?: Plaintext | null, ): { indexType: FfiIndexTypeName; queryOp?: QueryOpName } { const indexType = queryType ? queryTypeToFfi[queryType] : inferIndexType(column) if (queryType) { + // An order-capable v3 column answers equality via its `ore` index (`ob` + // term) — the same term `orderAndRange` emits, distinguished only by the SQL + // `=` operator. Resolve to `ore` (queryOp undefined) instead of throwing on + // the missing `unique` index. v2 columns never enter here (see helper). + if (queryType === 'equality' && resolvesEqualityViaOre(column)) { + return { indexType: 'ore' } + } + validateIndexType(column, indexType) // For searchableJson, infer queryOp from plaintext type (not from mapping) diff --git a/packages/stack/src/encryption/helpers/model-helpers.ts b/packages/stack/src/encryption/helpers/model-helpers.ts index 1cf59d8d..17da7dc7 100644 --- a/packages/stack/src/encryption/helpers/model-helpers.ts +++ b/packages/stack/src/encryption/helpers/model-helpers.ts @@ -6,8 +6,7 @@ import { import { isEncryptedPayload } from '@/encryption/helpers' import type { AuditData } from '@/encryption/operations/base-operation' import type { Context } from '@/identity' -import type { EncryptedTable, EncryptedTableColumn } from '@/schema' -import type { Client, Decrypted, Encrypted } from '@/types' +import type { BuildableTable, Client, Decrypted, Encrypted } from '@/types' /** * Sets a value at a nested path in an object, creating intermediate objects as needed. @@ -205,9 +204,35 @@ function prepareFieldsForDecryption<T extends Record<string, unknown>>( /** * Helper function to prepare fields for encryption */ +/** + * Resolve how a table's model fields map onto encrypt-config columns. + * + * `columnPaths` are the keys used to MATCH a user model's fields (the JS + * property names); `toColumnName` maps a matched field to the name the FFI / + * encrypt config is keyed by (the DB name). + * + * When a table exposes `buildColumnKeyMap()` (v3), those two can differ, so we + * match by property but address by DB name. Otherwise (v2) `build()` already + * keys columns by the property name, so both are that same key (identity map). + */ +export function resolveEncryptColumnMap(table: BuildableTable): { + columnPaths: string[] + toColumnName: (path: string) => string +} { + const keyMap = table.buildColumnKeyMap?.() + if (keyMap) { + return { + columnPaths: Object.keys(keyMap), + toColumnName: (path) => keyMap[path] ?? path, + } + } + const columnPaths = Object.keys(table.build().columns) + return { columnPaths, toColumnName: (path) => path } +} + function prepareFieldsForEncryption<T extends Record<string, unknown>>( model: T, - table: EncryptedTable<EncryptedTableColumn>, + table: BuildableTable, ): { otherFields: Record<string, unknown> operationFields: Record<string, unknown> @@ -264,8 +289,8 @@ function prepareFieldsForEncryption<T extends Record<string, unknown>>( } } - // Get all column paths from the table schema - const columnPaths = Object.keys(table.build().columns) + // Get all column paths from the table schema (matched by JS property name). + const { columnPaths } = resolveEncryptColumnMap(table) processNestedFields(model, '', columnPaths) return { otherFields, operationFields, keyMap, nullFields } @@ -326,7 +351,7 @@ export async function decryptModelFields<T extends Record<string, unknown>>( */ export async function encryptModelFields( model: Record<string, unknown>, - table: EncryptedTable<EncryptedTableColumn>, + table: BuildableTable, client: Client, auditData?: AuditData, ): Promise<Record<string, unknown>> { @@ -337,12 +362,13 @@ export async function encryptModelFields( const { otherFields, operationFields, keyMap, nullFields } = prepareFieldsForEncryption(model, table) + const { toColumnName } = resolveEncryptColumnMap(table) const bulkEncryptPayload = Object.entries(operationFields).map( ([key, value]) => ({ id: key, plaintext: value as string, table: table.tableName, - column: key, + column: toColumnName(key), }), ) @@ -437,7 +463,7 @@ export async function decryptModelFieldsWithLockContext< */ export async function encryptModelFieldsWithLockContext( model: Record<string, unknown>, - table: EncryptedTable<EncryptedTableColumn>, + table: BuildableTable, client: Client, lockContext: Context, auditData?: AuditData, @@ -453,12 +479,13 @@ export async function encryptModelFieldsWithLockContext( const { otherFields, operationFields, keyMap, nullFields } = prepareFieldsForEncryption(model, table) + const { toColumnName } = resolveEncryptColumnMap(table) const bulkEncryptPayload = Object.entries(operationFields).map( ([key, value]) => ({ id: key, plaintext: value as string, table: table.tableName, - column: key, + column: toColumnName(key), lockContext, }), ) @@ -496,7 +523,7 @@ export async function encryptModelFieldsWithLockContext( */ function prepareBulkModelsForOperation<T extends Record<string, unknown>>( models: T[], - table?: EncryptedTable<EncryptedTableColumn>, + table?: BuildableTable, ): { otherFields: Record<string, unknown>[] operationFields: Record<string, unknown>[] @@ -560,8 +587,8 @@ function prepareBulkModelsForOperation<T extends Record<string, unknown>>( } if (table) { - // Get all column paths from the table schema - const columnPaths = Object.keys(table.build().columns) + // Get all column paths from the table schema (matched by JS property name). + const { columnPaths } = resolveEncryptColumnMap(table) processNestedFields(model, '', columnPaths) } else { // For decryption, process all encrypted fields @@ -622,7 +649,7 @@ function prepareBulkModelsForOperation<T extends Record<string, unknown>>( */ export async function bulkEncryptModels( models: Record<string, unknown>[], - table: EncryptedTable<EncryptedTableColumn>, + table: BuildableTable, client: Client, auditData?: AuditData, ): Promise<Record<string, unknown>[]> { @@ -637,12 +664,13 @@ export async function bulkEncryptModels( const { otherFields, operationFields, keyMap, nullFields } = prepareBulkModelsForOperation(models, table) + const { toColumnName } = resolveEncryptColumnMap(table) const bulkEncryptPayload = operationFields.flatMap((fields, modelIndex) => Object.entries(fields).map(([key, value]) => ({ id: `${modelIndex}-${key}`, plaintext: value as string, table: table.tableName, - column: key, + column: toColumnName(key), })), ) @@ -831,7 +859,7 @@ export async function bulkDecryptModelsWithLockContext< */ export async function bulkEncryptModelsWithLockContext( models: Record<string, unknown>[], - table: EncryptedTable<EncryptedTableColumn>, + table: BuildableTable, client: Client, lockContext: Context, auditData?: AuditData, @@ -847,12 +875,13 @@ export async function bulkEncryptModelsWithLockContext( const { otherFields, operationFields, keyMap, nullFields } = prepareBulkModelsForOperation(models, table) + const { toColumnName } = resolveEncryptColumnMap(table) const bulkEncryptPayload = operationFields.flatMap((fields, modelIndex) => Object.entries(fields).map(([key, value]) => ({ id: `${modelIndex}-${key}`, plaintext: value as string, table: table.tableName, - column: key, + column: toColumnName(key), lockContext, })), ) diff --git a/packages/stack/src/encryption/index.ts b/packages/stack/src/encryption/index.ts index ccf422e1..bf5a08ee 100644 --- a/packages/stack/src/encryption/index.ts +++ b/packages/stack/src/encryption/index.ts @@ -1,5 +1,5 @@ import { type Result, withResult } from '@byteslice/result' -import { type JsPlaintext, newClient } from '@cipherstash/protect-ffi' +import { newClient } from '@cipherstash/protect-ffi' import { validate as uuidValidate } from 'uuid' import { type EncryptionError, EncryptionErrorTypes } from '@/errors' // `LockContext` is imported type-only so the TSDoc {@link} references in the @@ -8,8 +8,6 @@ import type { LockContext } from '@/identity' import { buildEncryptConfig, type EncryptConfig, - type EncryptedTable, - type EncryptedTableColumn, encryptConfigSchema, // Imported type-only for the TSDoc {@link} references in the comments below. type encryptedColumn, @@ -18,15 +16,17 @@ import { } from '@/schema' import type { AuthStrategy, + BuildableTable, BulkDecryptPayload, BulkEncryptPayload, Client, Encrypted, - EncryptedFromSchema, + EncryptedFromBuildableTable, EncryptionClientConfig, EncryptOptions, EncryptQueryOptions, KeysetIdentifier, + Plaintext, ScalarQueryTerm, } from '@/types' import { logger } from '@/utils/logger' @@ -207,7 +207,7 @@ export class EncryptionClient { * @see {@link LockContext} * @see {@link EncryptOperation} */ - encrypt(plaintext: JsPlaintext, opts: EncryptOptions): EncryptOperation { + encrypt(plaintext: Plaintext, opts: EncryptOptions): EncryptOperation { return new EncryptOperation(this.client, plaintext, opts) } @@ -265,7 +265,7 @@ export class EncryptionClient { * - Object/Array plaintext → `steVecTerm` (containment queries like `{ role: 'admin' }`) */ encryptQuery( - plaintext: JsPlaintext, + plaintext: Plaintext, opts: EncryptQueryOptions, ): EncryptQueryOperation @@ -276,12 +276,14 @@ export class EncryptionClient { encryptQuery(terms: readonly ScalarQueryTerm[]): BatchEncryptQueryOperation encryptQuery( - plaintextOrTerms: JsPlaintext | readonly ScalarQueryTerm[], + plaintextOrTerms: Plaintext | readonly ScalarQueryTerm[], opts?: EncryptQueryOptions, ): EncryptQueryOperation | BatchEncryptQueryOperation { - // Discriminate between ScalarQueryTerm[] and JsPlaintext (which can also be an array) - // using a type guard function - if (isScalarQueryTermArray(plaintextOrTerms)) { + // Discriminate between ScalarQueryTerm[] and Plaintext (which can also be an + // array) using a type guard function. Only route to batch mode when no opts + // are supplied — an explicit EncryptQueryOptions forces the single-plaintext + // path even if the plaintext value happens to be an array. + if (!opts && isScalarQueryTermArray(plaintextOrTerms)) { return new BatchEncryptQueryOperation(this.client, plaintextOrTerms) } @@ -305,7 +307,7 @@ export class EncryptionClient { return new EncryptQueryOperation( this.client, - plaintextOrTerms as JsPlaintext, + plaintextOrTerms as Plaintext, opts, ) } @@ -399,13 +401,10 @@ export class EncryptionClient { * } * ``` */ - encryptModel< - T extends Record<string, unknown>, - S extends EncryptedTableColumn = EncryptedTableColumn, - >( + encryptModel<T extends Record<string, unknown>, Table extends BuildableTable>( input: T, - table: EncryptedTable<S>, - ): EncryptModelOperation<EncryptedFromSchema<T, S>> { + table: Table, + ): EncryptModelOperation<EncryptedFromBuildableTable<T, Table>> { return new EncryptModelOperation( this.client, input as Record<string, unknown>, @@ -494,11 +493,11 @@ export class EncryptionClient { */ bulkEncryptModels< T extends Record<string, unknown>, - S extends EncryptedTableColumn = EncryptedTableColumn, + Table extends BuildableTable, >( input: Array<T>, - table: EncryptedTable<S>, - ): BulkEncryptModelsOperation<EncryptedFromSchema<T, S>> { + table: Table, + ): BulkEncryptModelsOperation<EncryptedFromBuildableTable<T, Table>> { return new BulkEncryptModelsOperation( this.client, input as Array<Record<string, unknown>>, diff --git a/packages/stack/src/encryption/operations/batch-encrypt-query.ts b/packages/stack/src/encryption/operations/batch-encrypt-query.ts index 1c4bff5c..00f65a0b 100644 --- a/packages/stack/src/encryption/operations/batch-encrypt-query.ts +++ b/packages/stack/src/encryption/operations/batch-encrypt-query.ts @@ -82,13 +82,17 @@ function buildQueryPayload( */ function assembleResults( totalLength: number, - encryptedValues: (CipherStashEncrypted | CipherStashEncryptedQuery)[], + // Typed as the FFI bulk-query return so it tracks the upstream union. As of + // protect-ffi 0.27 that union also includes `SteVecQuery`, but scalar query + // terms (all this operation builds) never produce a ste_vec result, so each + // element is narrowed back to the scalar shape `formatEncryptedResult` takes. + encryptedValues: Awaited<ReturnType<typeof ffiEncryptQueryBulk>>, nonNullTerms: { term: ScalarQueryTerm; originalIndex: number }[], ): EncryptedQueryResult[] { const results: EncryptedQueryResult[] = new Array(totalLength).fill(null) nonNullTerms.forEach(({ term, originalIndex }, i) => { results[originalIndex] = formatEncryptedResult( - encryptedValues[i], + encryptedValues[i] as CipherStashEncrypted | CipherStashEncryptedQuery, term.returnType, ) }) diff --git a/packages/stack/src/encryption/operations/bulk-encrypt-models.ts b/packages/stack/src/encryption/operations/bulk-encrypt-models.ts index 20d68496..10c22633 100644 --- a/packages/stack/src/encryption/operations/bulk-encrypt-models.ts +++ b/packages/stack/src/encryption/operations/bulk-encrypt-models.ts @@ -2,8 +2,7 @@ import { type Result, withResult } from '@byteslice/result' import { getErrorCode } from '@/encryption/helpers/error-code' import { type EncryptionError, EncryptionErrorTypes } from '@/errors' import { type LockContextInput, resolveLockContext } from '@/identity' -import type { EncryptedTable, EncryptedTableColumn } from '@/schema' -import type { Client } from '@/types' +import type { BuildableTable, Client } from '@/types' import { createRequestLogger } from '@/utils/logger' import { bulkEncryptModels, @@ -17,12 +16,12 @@ export class BulkEncryptModelsOperation< > extends EncryptionOperation<T[]> { private client: Client private models: Record<string, unknown>[] - private table: EncryptedTable<EncryptedTableColumn> + private table: BuildableTable constructor( client: Client, models: Record<string, unknown>[], - table: EncryptedTable<EncryptedTableColumn>, + table: BuildableTable, ) { super() this.client = client @@ -76,7 +75,7 @@ export class BulkEncryptModelsOperation< public getOperation(): { client: Client models: Record<string, unknown>[] - table: EncryptedTable<EncryptedTableColumn> + table: BuildableTable } { return { client: this.client, diff --git a/packages/stack/src/encryption/operations/bulk-encrypt.ts b/packages/stack/src/encryption/operations/bulk-encrypt.ts index 9b01825a..6e3ec802 100644 --- a/packages/stack/src/encryption/operations/bulk-encrypt.ts +++ b/packages/stack/src/encryption/operations/bulk-encrypt.ts @@ -8,12 +8,8 @@ import { resolveLockContext, } from '@/identity' import type { - EncryptedColumn, - EncryptedField, - EncryptedTable, - EncryptedTableColumn, -} from '@/schema' -import type { + BuildableColumn, + BuildableTable, BulkEncryptedData, BulkEncryptPayload, Client, @@ -29,8 +25,8 @@ import { EncryptionOperation } from './base-operation' // re-inserted as null in `mapEncryptedDataToResult`. const createEncryptPayloads = ( plaintexts: BulkEncryptPayload, - column: EncryptedColumn | EncryptedField, - table: EncryptedTable<EncryptedTableColumn>, + column: BuildableColumn, + table: BuildableTable, lockContext?: Context, ) => { return plaintexts @@ -67,8 +63,8 @@ const mapEncryptedDataToResult = ( export class BulkEncryptOperation extends EncryptionOperation<BulkEncryptedData> { private client: Client private plaintexts: BulkEncryptPayload - private column: EncryptedColumn | EncryptedField - private table: EncryptedTable<EncryptedTableColumn> + private column: BuildableColumn + private table: BuildableTable constructor( client: Client, @@ -142,8 +138,8 @@ export class BulkEncryptOperation extends EncryptionOperation<BulkEncryptedData> public getOperation(): { client: Client plaintexts: BulkEncryptPayload - column: EncryptedColumn | EncryptedField - table: EncryptedTable<EncryptedTableColumn> + column: BuildableColumn + table: BuildableTable } { return { client: this.client, diff --git a/packages/stack/src/encryption/operations/encrypt-model.ts b/packages/stack/src/encryption/operations/encrypt-model.ts index 1c39d66e..0ac42f08 100644 --- a/packages/stack/src/encryption/operations/encrypt-model.ts +++ b/packages/stack/src/encryption/operations/encrypt-model.ts @@ -2,8 +2,7 @@ import { type Result, withResult } from '@byteslice/result' import { getErrorCode } from '@/encryption/helpers/error-code' import { type EncryptionError, EncryptionErrorTypes } from '@/errors' import { type LockContextInput, resolveLockContext } from '@/identity' -import type { EncryptedTable, EncryptedTableColumn } from '@/schema' -import type { Client } from '@/types' +import type { BuildableTable, Client } from '@/types' import { createRequestLogger } from '@/utils/logger' import { encryptModelFields, @@ -17,12 +16,12 @@ export class EncryptModelOperation< > extends EncryptionOperation<T> { private client: Client private model: Record<string, unknown> - private table: EncryptedTable<EncryptedTableColumn> + private table: BuildableTable constructor( client: Client, model: Record<string, unknown>, - table: EncryptedTable<EncryptedTableColumn>, + table: BuildableTable, ) { super() this.client = client @@ -75,7 +74,7 @@ export class EncryptModelOperation< public getOperation(): { client: Client model: Record<string, unknown> - table: EncryptedTable<EncryptedTableColumn> + table: BuildableTable } { return { client: this.client, diff --git a/packages/stack/src/encryption/operations/encrypt-query.ts b/packages/stack/src/encryption/operations/encrypt-query.ts index c2c17b36..9369b91d 100644 --- a/packages/stack/src/encryption/operations/encrypt-query.ts +++ b/packages/stack/src/encryption/operations/encrypt-query.ts @@ -7,7 +7,12 @@ import { formatEncryptedResult } from '@/encryption/helpers' import { getErrorCode } from '@/encryption/helpers/error-code' import { type EncryptionError, EncryptionErrorTypes } from '@/errors' import { type LockContextInput, resolveLockContext } from '@/identity' -import type { Client, EncryptedQueryResult, EncryptQueryOptions } from '@/types' +import type { + Client, + EncryptedQueryResult, + EncryptQueryOptions, + Plaintext, +} from '@/types' import { createRequestLogger } from '@/utils/logger' import { resolveIndexType } from '../helpers/infer-index-type' import { @@ -20,7 +25,7 @@ import { EncryptionOperation } from './base-operation' export class EncryptQueryOperation extends EncryptionOperation<EncryptedQueryResult> { constructor( private client: Client, - private plaintext: JsPlaintext | null | undefined, + private plaintext: Plaintext | null | undefined, private opts: EncryptQueryOptions, ) { super() @@ -55,7 +60,7 @@ export class EncryptQueryOperation extends EncryptionOperation<EncryptedQueryRes return { data: null } } - const plaintext: JsPlaintext = this.plaintext + const plaintext: Plaintext = this.plaintext const validationError = validateNumericValue(plaintext) if (validationError?.failure) { @@ -83,7 +88,10 @@ export class EncryptQueryOperation extends EncryptionOperation<EncryptedQueryRes ) const encrypted = await ffiEncryptQuery(this.client, { - plaintext, + // `Plaintext` widens the FFI `JsPlaintext` with `Date` (serialized via + // `toJSON` at the boundary); cast until the upstream input union is + // corrected to include it. + plaintext: plaintext as JsPlaintext, column: this.opts.column.getName(), table: this.opts.table.tableName, indexType, @@ -114,7 +122,7 @@ export class EncryptQueryOperation extends EncryptionOperation<EncryptedQueryRes export class EncryptQueryOperationWithLockContext extends EncryptionOperation<EncryptedQueryResult> { constructor( private client: Client, - private plaintext: JsPlaintext | null | undefined, + private plaintext: Plaintext | null | undefined, private opts: EncryptQueryOptions, private lockContext: LockContextInput, auditMetadata?: Record<string, unknown>, @@ -140,7 +148,7 @@ export class EncryptQueryOperationWithLockContext extends EncryptionOperation<En return { data: null } } - const plaintext: JsPlaintext = this.plaintext + const plaintext: Plaintext = this.plaintext const validationError = validateNumericValue(plaintext) if (validationError?.failure) { @@ -170,7 +178,10 @@ export class EncryptQueryOperationWithLockContext extends EncryptionOperation<En ) const encrypted = await ffiEncryptQuery(this.client, { - plaintext, + // `Plaintext` widens the FFI `JsPlaintext` with `Date` (serialized via + // `toJSON` at the boundary); cast until the upstream input union is + // corrected to include it. + plaintext: plaintext as JsPlaintext, column: this.opts.column.getName(), table: this.opts.table.tableName, indexType, diff --git a/packages/stack/src/encryption/operations/encrypt.ts b/packages/stack/src/encryption/operations/encrypt.ts index 55ad7a30..de380613 100644 --- a/packages/stack/src/encryption/operations/encrypt.ts +++ b/packages/stack/src/encryption/operations/encrypt.ts @@ -4,15 +4,17 @@ import { type JsPlaintext, } from '@cipherstash/protect-ffi' import { getErrorCode } from '@/encryption/helpers/error-code' +import { assertValidNumericValue } from '@/encryption/helpers/validation' import { type EncryptionError, EncryptionErrorTypes } from '@/errors' import { type LockContextInput, resolveLockContext } from '@/identity' import type { - EncryptedColumn, - EncryptedField, - EncryptedTable, - EncryptedTableColumn, -} from '@/schema' -import type { Client, Encrypted, EncryptOptions } from '@/types' + BuildableColumn, + BuildableTable, + Client, + Encrypted, + EncryptOptions, + Plaintext, +} from '@/types' import { createRequestLogger } from '@/utils/logger' import { noClientError } from '../index' import { EncryptionOperation } from './base-operation' @@ -23,13 +25,13 @@ export class EncryptOperation extends EncryptionOperation<Encrypted> { // short-circuit. The public `Encryption.encrypt()` signature still // rejects null at the type layer; this is defense in depth for callers // that reach this class through casts or dynamic field walking. - private plaintext: JsPlaintext | null - private column: EncryptedColumn | EncryptedField - private table: EncryptedTable<EncryptedTableColumn> + private plaintext: Plaintext | null + private column: BuildableColumn + private table: BuildableTable constructor( client: Client, - plaintext: JsPlaintext | null, + plaintext: Plaintext | null, opts: EncryptOptions, ) { super() @@ -70,24 +72,15 @@ export class EncryptOperation extends EncryptionOperation<Encrypted> { return null as unknown as Encrypted } - if ( - typeof this.plaintext === 'number' && - Number.isNaN(this.plaintext) - ) { - throw new Error('[encryption]: Cannot encrypt NaN value') - } - - if ( - typeof this.plaintext === 'number' && - !Number.isFinite(this.plaintext) - ) { - throw new Error('[encryption]: Cannot encrypt Infinity value') - } + assertValidNumericValue(this.plaintext) const { metadata } = this.getAuditData() return await ffiEncrypt(this.client, { - plaintext: this.plaintext, + // `Plaintext` widens the FFI `JsPlaintext` with `Date` (serialized via + // `toJSON` at the boundary); cast until the upstream `JsPlaintext` input + // union is corrected to include it. + plaintext: this.plaintext as JsPlaintext, column: this.column.getName(), table: this.table.tableName, unverifiedContext: metadata, @@ -108,9 +101,9 @@ export class EncryptOperation extends EncryptionOperation<Encrypted> { public getOperation(): { client: Client - plaintext: JsPlaintext | null - column: EncryptedColumn | EncryptedField - table: EncryptedTable<EncryptedTableColumn> + plaintext: Plaintext | null + column: BuildableColumn + table: BuildableTable } { return { client: this.client, @@ -156,11 +149,13 @@ export class EncryptOperationWithLockContext extends EncryptionOperation<Encrypt return null as unknown as Encrypted } + assertValidNumericValue(plaintext) + const { metadata } = this.getAuditData() const lockContext = resolveLockContext(this.lockContext) return await ffiEncrypt(client, { - plaintext, + plaintext: plaintext as JsPlaintext, column: column.getName(), table: table.tableName, lockContext, diff --git a/packages/stack/src/encryption/v3.ts b/packages/stack/src/encryption/v3.ts new file mode 100644 index 00000000..d9b8a963 --- /dev/null +++ b/packages/stack/src/encryption/v3.ts @@ -0,0 +1,272 @@ +import type { Result } from '@byteslice/result' +import type { + AnyV3Table, + ColumnsOf, + PlaintextForColumn, + QueryableColumnsOf, + QueryTypesForColumn, + V3DecryptedModel, + V3EncryptedModel, + V3ModelInput, +} from '@/eql/v3' +import { DATE_LIKE_CASTS } from '@/eql/v3/columns' +import { type EncryptionError, EncryptionErrorTypes } from '@/errors' +import type { LockContextInput } from '@/identity' +import type { + BulkDecryptPayload, + BulkEncryptPayload, + ClientConfig, + Encrypted, + EncryptedReturnType, + EncryptOptions, +} from '@/types' +import { + type BulkDecryptOperation, + type BulkEncryptModelsOperation, + type BulkEncryptOperation, + type DecryptOperation, + Encryption, + type EncryptionClient, + type EncryptModelOperation, + type EncryptOperation, + type EncryptQueryOperation, +} from './index' + +/** + * A strongly-typed view over an {@link EncryptionClient} for EQL v3 schemas. + * + * Every method derives its types from the concrete `table` / `column` builder + * arguments (which carry their branded types at the call site), so: + * - `encrypt` / `encryptQuery` pin the plaintext to the column's domain type + * (`text → string`, `timestamp → Date`, …); + * - `encryptQuery` additionally constrains `queryType` to the column's + * capabilities and rejects storage-only columns outright; + * - `encryptModel` / `bulkEncryptModels` validate schema-column fields against + * their inferred plaintext type (passthrough fields are untouched) and return + * a precise encrypted model; + * - `decryptModel` / `bulkDecryptModels` return the precise plaintext model, + * reconstructing `Date` values from the encrypt-config `cast_as`. + * + * @typeParam S - the tuple of registered v3 tables; `table` arguments must be a + * member of this tuple. + */ +export interface TypedEncryptionClient<S extends readonly AnyV3Table[]> { + encrypt<Table extends S[number], Col extends ColumnsOf<Table>>( + plaintext: PlaintextForColumn<Col>, + opts: { table: Table; column: Col }, + ): EncryptOperation + + encryptQuery< + Table extends S[number], + Col extends QueryableColumnsOf<Table>, + QT extends QueryTypesForColumn<Col> = QueryTypesForColumn<Col>, + >( + plaintext: PlaintextForColumn<Col>, + opts: { + table: Table + column: Col + queryType?: QT + returnType?: EncryptedReturnType + }, + ): EncryptQueryOperation + + encryptModel<Table extends S[number], T extends Record<string, unknown>>( + input: V3ModelInput<Table, T>, + table: Table, + ): EncryptModelOperation<V3EncryptedModel<Table, T>> + + bulkEncryptModels<Table extends S[number], T extends Record<string, unknown>>( + input: Array<V3ModelInput<Table, T>>, + table: Table, + ): BulkEncryptModelsOperation<V3EncryptedModel<Table, T>> + + /** + * Decrypt a single value. Cannot be strongly typed — a lone ciphertext carries + * no column identity — so it resolves to the FFI plaintext union unchanged. + */ + decrypt(encrypted: Encrypted): DecryptOperation + + /** + * Decrypt a model, returning the precise plaintext shape for `table`. `Date` + * columns are reconstructed from the encrypt-config `cast_as`. + * + * Pass `lockContext` to decrypt identity-bound data — the same context that + * was supplied at encrypt time must be provided here. + * + * Unlike the encrypt operations this returns a plain `Promise<Result<…>>` + * rather than a chainable operation, because it maps the resolved value. + */ + decryptModel<Table extends S[number], T extends Record<string, unknown>>( + input: T, + table: Table, + lockContext?: LockContextInput, + ): Promise<Result<V3DecryptedModel<Table, T>, EncryptionError>> + + bulkDecryptModels<Table extends S[number], T extends Record<string, unknown>>( + input: Array<T>, + table: Table, + lockContext?: LockContextInput, + ): Promise<Result<Array<V3DecryptedModel<Table, T>>, EncryptionError>> + + // Parity passthroughs — not v3-strengthened, delegated as-is. + bulkEncrypt( + plaintexts: BulkEncryptPayload, + opts: EncryptOptions, + ): BulkEncryptOperation + bulkDecrypt(payloads: BulkDecryptPayload): BulkDecryptOperation + getEncryptConfig(): ReturnType<EncryptionClient['getEncryptConfig']> +} + +/** + * Build a per-row reconstructor of `Date` values from the table's + * encrypt-config `cast_as`. The FFI returns `JsPlaintext` + * (string/number/boolean/…) with no `Date`, so those columns arrive as their + * serialized form and are rebuilt here. Safe (idempotent) if the FFI ever + * returns `Date` directly: `new Date(date)` is a no-op. + * + * A factory rather than a `(row, table)` function so the table config — + * row-invariant, but non-trivial to build — is derived once per call site, + * not once per row on the bulk path. + * + * NOTE: `bigint` (int8) columns need NO reconstruction here — protect-ffi 0.28 + * marshals a JS `bigint` across the Neon boundary and returns a real JS `bigint` + * on decrypt, which the model decrypt path passes through with no JSON + * round-trip that could destroy it. Only date-like domains are rebuilt below. + */ +function rowReconstructor( + table: AnyV3Table, +): (row: Record<string, unknown>) => Record<string, unknown> { + // The decrypted row is keyed by JS property name, but `cast_as` lives on the + // config keyed by DB name — bridge the two via the table's property→DB map. + const { columns } = table.build() + const propToDb = table.buildColumnKeyMap() + // Only date-like columns need per-row work; resolve them up front. + const dateProperties = Object.entries(propToDb) + .filter(([, dbName]) => { + const castAs = columns[dbName]?.cast_as + // Date-like casts share one source of truth with the type-level + // reconstruction (`PlaintextFromKind`) — see `DATE_LIKE_CASTS`. + return (DATE_LIKE_CASTS as readonly string[]).includes(castAs as string) + }) + .map(([property]) => property) + + return (row) => { + const out: Record<string, unknown> = { ...row } + for (const property of dateProperties) { + const value = out[property] + if (value == null) continue + out[property] = new Date(value as string | number | Date) + } + return out + } +} + +/** + * Wrap an already-built {@link EncryptionClient} in a {@link TypedEncryptionClient} + * for the given v3 schemas. Zero runtime cost for the encrypt/query paths (the + * underlying operations are returned unchanged); the decrypt-model paths add a + * per-column `Date` reconstruction step. + * + * The `schemas` are captured with a `const` type parameter so array-literal + * widening does not collapse per-table inference. + */ +export function typedClient<const S extends readonly AnyV3Table[]>( + client: EncryptionClient, + ...schemas: S +): TypedEncryptionClient<S> { + // Precompute one row reconstructor per schema table at construction. This runs + // each table's `build()` — which throws on duplicate DB column names — ONCE, + // here, off the Result-returning decrypt path. `decryptModel`/ + // `bulkDecryptModels` therefore never call `build()` (whose throw would surface + // as a promise rejection and break their `Promise<Result<…>>` contract) and no + // longer rebuild the row-invariant config on every call. + const reconstructors = new Map< + AnyV3Table, + (row: Record<string, unknown>) => Record<string, unknown> + >() + for (const table of schemas) { + reconstructors.set(table, rowReconstructor(table)) + } + + // A table not among the schemas this client was initialized with (only + // reachable by bypassing the `Table extends S[number]` type constraint) has no + // precomputed reconstructor. Return a Result failure rather than building one + // inline, which could throw and reject the Result-shaped decrypt promise. + const unknownTableFailure: { failure: EncryptionError } = { + failure: { + type: EncryptionErrorTypes.DecryptionError, + message: + '[eql/v3]: decryptModel received a table this client was not initialized with — pass the same table object(s) given to EncryptionV3/typedClient', + }, + } + + return { + encrypt: (plaintext, opts) => + client.encrypt(plaintext as never, opts as never), + encryptQuery: (plaintext, opts) => + client.encryptQuery(plaintext as never, opts as never), + encryptModel: (input, table) => + client.encryptModel(input as never, table as never) as never, + bulkEncryptModels: (input, table) => + client.bulkEncryptModels(input as never, table as never) as never, + decrypt: (encrypted) => client.decrypt(encrypted), + decryptModel: async (input, table, lockContext) => { + const reconstruct = reconstructors.get(table) + if (!reconstruct) return unknownTableFailure as never + const op = client.decryptModel(input as never) + const result = await (lockContext ? op.withLockContext(lockContext) : op) + if (result.failure) return result as never + return { data: reconstruct(result.data) } as never + }, + bulkDecryptModels: async (input, table, lockContext) => { + const reconstruct = reconstructors.get(table) + if (!reconstruct) return unknownTableFailure as never + const op = client.bulkDecryptModels(input as never) + const result = await (lockContext ? op.withLockContext(lockContext) : op) + if (result.failure) return result as never + return { + data: result.data.map((row) => + reconstruct(row as Record<string, unknown>), + ), + } as never + }, + bulkEncrypt: (plaintexts, opts) => client.bulkEncrypt(plaintexts, opts), + bulkDecrypt: (payloads) => client.bulkDecrypt(payloads), + getEncryptConfig: () => client.getEncryptConfig(), + } satisfies TypedEncryptionClient<S> +} + +/** + * Build a {@link TypedEncryptionClient} for EQL v3 schemas — the strongly-typed + * counterpart to {@link Encryption}. Mirrors its config, then retypes the client + * against the provided v3 `schemas`. + * + * @example + * ```typescript + * import { EncryptionV3, encryptedTable, types } from "@cipherstash/stack/v3" + * + * const users = encryptedTable("users", { email: types.TextSearch("email") }) + * const client = await EncryptionV3({ schemas: [users] }) + * + * await client.encrypt("a@b.com", { table: users, column: users.email }) + * ``` + */ +export async function EncryptionV3< + const S extends readonly AnyV3Table[], +>(config: { + schemas: S + config?: ClientConfig +}): Promise<TypedEncryptionClient<S>> { + const client = await Encryption({ + schemas: config.schemas as unknown as Parameters< + typeof Encryption + >[0]['schemas'], + config: config.config, + }) + return typedClient(client, ...config.schemas) +} + +// Single import surface: re-export the v3 `types` namespace + table API + type +// helpers so `@cipherstash/stack/v3` provides everything needed to author and +// use a schema. +export * from '@/eql/v3' diff --git a/packages/stack/src/eql/v3/columns.ts b/packages/stack/src/eql/v3/columns.ts new file mode 100644 index 00000000..92829ec3 --- /dev/null +++ b/packages/stack/src/eql/v3/columns.ts @@ -0,0 +1,717 @@ +import type { ColumnSchema, MatchIndexOpts } from '@/schema' +import { + type BuiltMatchIndexOpts, + cloneMatchOpts, + defaultMatchOpts, + resolveMatchOpts, +} from '@/schema/match-defaults' + +/** + * The query capabilities a v3 concrete domain exposes. These are SDK-facing + * semantic flags describing what kinds of query terms a column can produce — + * NOT the raw EQL index keys. They are metadata only and never emitted by + * `build()`. + * + * - `equality`: exact-match lookups (EQL `hm`, or comparison via `ob`). + * - `orderAndRange`: comparison / range lookups (EQL `ob`). + * - `freeTextSearch`: tokenised substring match (EQL `bf`). + */ +export type QueryCapabilities = Readonly<{ + equality: boolean + orderAndRange: boolean + freeTextSearch: boolean +}> + +/** + * The `cast_as` kinds whose decrypted plaintext reconstructs to a JS `Date`. + * + * SINGLE SOURCE OF TRUTH for the date-like set. Both the type-level + * {@link PlaintextFromKind} and the runtime `rowReconstructor` (encryption/v3.ts) + * derive their "reconstructs to `Date`" decision from this array, so the next + * `Date`-backed cast is added in exactly one place — never hand-synced across a + * type and a runtime guard that could silently drift. + * + * (`timestamp` reconstructs to `Date` just like `date`, but its `cast_as` tells + * the FFI not to truncate the time-of-day.) + */ +export const DATE_LIKE_CASTS = ['date', 'timestamp'] as const +/** A `cast_as` kind that reconstructs to `Date` — see {@link DATE_LIKE_CASTS}. */ +export type DateLikeCast = (typeof DATE_LIKE_CASTS)[number] + +/** The plaintext (TypeScript) kind a v3 domain decrypts to. A subset of the + * SDK `CastAs` enum, restricted to the scalar kinds v3 domains actually use. */ +type PlaintextKind = 'string' | 'number' | 'bigint' | 'boolean' | DateLikeCast + +/** + * The full, literal definition of a v3 domain. This is the LOAD-BEARING type: + * the base column class carries a private field of this type so that every + * concrete (otherwise-empty) subclass is discriminated by its literal + * `eqlType`/`castAs`/`capabilities` — TypeScript empty subclasses are NOT + * nominal, so without this a storage-only `boolean` column would be assignable to + * a storage-only `date` column and plaintext inference would collapse. + */ +type V3DomainDefinition = Readonly<{ + eqlType: `eql_v3.${string}` + castAs: PlaintextKind + capabilities: QueryCapabilities +}> + +/** Type-level mirror of {@link isQueryableCapabilities}: `false` for a + * storage-only domain (all capability flags `false`), `true` otherwise. */ +type QueryableFlag<D extends V3DomainDefinition> = D['capabilities'] extends { + equality: false + orderAndRange: false + freeTextSearch: false +} + ? false + : true + +const STORAGE_ONLY = { + equality: false, + orderAndRange: false, + freeTextSearch: false, +} as const + +const EQUALITY_ONLY = { + equality: true, + orderAndRange: false, + freeTextSearch: false, +} as const + +const ORDER_AND_RANGE = { + equality: true, + orderAndRange: true, + freeTextSearch: false, +} as const + +const MATCH_ONLY = { + equality: false, + orderAndRange: false, + freeTextSearch: true, +} as const + +const TEXT_SEARCH = { + equality: true, + orderAndRange: true, + freeTextSearch: true, +} as const + +/** + * The concrete EQL v3 domain name for a full-capability text column. + * Recorded as metadata for future DDL / query-dialect increments; it is + * intentionally absent from the emitted encrypt config. + */ +export const TEXT_SEARCH_EQL_TYPE = 'eql_v3.text_search' + +// Per-domain literal definitions. Each concrete column subclass is parameterised +// by `typeof <CONST>`; the literal `eqlType`/`castAs`/`capabilities` on each is +// what makes the otherwise-empty subclasses nominally distinct (see +// V3DomainDefinition). Order mirrors eql-bindings `CATALOG` order. +// +// Exported for the `types` namespace factory (see ./types); they are internal +// building blocks and are intentionally NOT re-exported from the public barrel. +export const INTEGER = { + eqlType: 'eql_v3.integer', + castAs: 'number', + capabilities: STORAGE_ONLY, +} as const +export const INTEGER_EQ = { + eqlType: 'eql_v3.integer_eq', + castAs: 'number', + capabilities: EQUALITY_ONLY, +} as const +export const INTEGER_ORD_ORE = { + eqlType: 'eql_v3.integer_ord_ore', + castAs: 'number', + capabilities: ORDER_AND_RANGE, +} as const +export const INTEGER_ORD = { + eqlType: 'eql_v3.integer_ord', + castAs: 'number', + capabilities: ORDER_AND_RANGE, +} as const + +export const SMALLINT = { + eqlType: 'eql_v3.smallint', + castAs: 'number', + capabilities: STORAGE_ONLY, +} as const +export const SMALLINT_EQ = { + eqlType: 'eql_v3.smallint_eq', + castAs: 'number', + capabilities: EQUALITY_ONLY, +} as const +export const SMALLINT_ORD_ORE = { + eqlType: 'eql_v3.smallint_ord_ore', + castAs: 'number', + capabilities: ORDER_AND_RANGE, +} as const +export const SMALLINT_ORD = { + eqlType: 'eql_v3.smallint_ord', + castAs: 'number', + capabilities: ORDER_AND_RANGE, +} as const + +// bigint (int8) domains. Plaintext is a JS `bigint` (always decrypts to +// `bigint`); bounds are the full i64 range, enforced at the protect-ffi +// boundary. Native round-tripping landed in protect-ffi 0.28 (`JsPlaintext` +// marshals a JS `bigint` across the Neon boundary), so live encrypt/decrypt is +// no longer gated (`*_ord_ope` variants are out of scope — CIP-3403). The +// concrete domain is the SQL fixture's `int8` name, not `bigint`. +export const BIGINT = { + eqlType: 'eql_v3.int8', + castAs: 'bigint', + capabilities: STORAGE_ONLY, +} as const +export const BIGINT_EQ = { + eqlType: 'eql_v3.int8_eq', + castAs: 'bigint', + capabilities: EQUALITY_ONLY, +} as const +export const BIGINT_ORD_ORE = { + eqlType: 'eql_v3.int8_ord_ore', + castAs: 'bigint', + capabilities: ORDER_AND_RANGE, +} as const +export const BIGINT_ORD = { + eqlType: 'eql_v3.int8_ord', + castAs: 'bigint', + capabilities: ORDER_AND_RANGE, +} as const + +export const DATE = { + eqlType: 'eql_v3.date', + castAs: 'date', + capabilities: STORAGE_ONLY, +} as const +export const DATE_EQ = { + eqlType: 'eql_v3.date_eq', + castAs: 'date', + capabilities: EQUALITY_ONLY, +} as const +export const DATE_ORD_ORE = { + eqlType: 'eql_v3.date_ord_ore', + castAs: 'date', + capabilities: ORDER_AND_RANGE, +} as const +export const DATE_ORD = { + eqlType: 'eql_v3.date_ord', + castAs: 'date', + capabilities: ORDER_AND_RANGE, +} as const + +export const TIMESTAMP = { + eqlType: 'eql_v3.timestamp', + castAs: 'timestamp', + capabilities: STORAGE_ONLY, +} as const +export const TIMESTAMP_EQ = { + eqlType: 'eql_v3.timestamp_eq', + castAs: 'timestamp', + capabilities: EQUALITY_ONLY, +} as const +export const TIMESTAMP_ORD_ORE = { + eqlType: 'eql_v3.timestamp_ord_ore', + castAs: 'timestamp', + capabilities: ORDER_AND_RANGE, +} as const +export const TIMESTAMP_ORD = { + eqlType: 'eql_v3.timestamp_ord', + castAs: 'timestamp', + capabilities: ORDER_AND_RANGE, +} as const + +export const NUMERIC = { + eqlType: 'eql_v3.numeric', + castAs: 'number', + capabilities: STORAGE_ONLY, +} as const +export const NUMERIC_EQ = { + eqlType: 'eql_v3.numeric_eq', + castAs: 'number', + capabilities: EQUALITY_ONLY, +} as const +export const NUMERIC_ORD_ORE = { + eqlType: 'eql_v3.numeric_ord_ore', + castAs: 'number', + capabilities: ORDER_AND_RANGE, +} as const +export const NUMERIC_ORD = { + eqlType: 'eql_v3.numeric_ord', + castAs: 'number', + capabilities: ORDER_AND_RANGE, +} as const + +export const TEXT = { + eqlType: 'eql_v3.text', + castAs: 'string', + capabilities: STORAGE_ONLY, +} as const +export const TEXT_EQ = { + eqlType: 'eql_v3.text_eq', + castAs: 'string', + capabilities: EQUALITY_ONLY, +} as const +export const TEXT_MATCH = { + eqlType: 'eql_v3.text_match', + castAs: 'string', + capabilities: MATCH_ONLY, +} as const +export const TEXT_ORD_ORE = { + eqlType: 'eql_v3.text_ord_ore', + castAs: 'string', + capabilities: ORDER_AND_RANGE, +} as const +export const TEXT_ORD = { + eqlType: 'eql_v3.text_ord', + castAs: 'string', + capabilities: ORDER_AND_RANGE, +} as const + +export const BOOLEAN = { + eqlType: 'eql_v3.bool', + castAs: 'boolean', + capabilities: STORAGE_ONLY, +} as const + +export const REAL = { + eqlType: 'eql_v3.real', + castAs: 'number', + capabilities: STORAGE_ONLY, +} as const +export const REAL_EQ = { + eqlType: 'eql_v3.real_eq', + castAs: 'number', + capabilities: EQUALITY_ONLY, +} as const +export const REAL_ORD_ORE = { + eqlType: 'eql_v3.real_ord_ore', + castAs: 'number', + capabilities: ORDER_AND_RANGE, +} as const +export const REAL_ORD = { + eqlType: 'eql_v3.real_ord', + castAs: 'number', + capabilities: ORDER_AND_RANGE, +} as const + +export const DOUBLE = { + eqlType: 'eql_v3.double', + castAs: 'number', + capabilities: STORAGE_ONLY, +} as const +export const DOUBLE_EQ = { + eqlType: 'eql_v3.double_eq', + castAs: 'number', + capabilities: EQUALITY_ONLY, +} as const +export const DOUBLE_ORD_ORE = { + eqlType: 'eql_v3.double_ord_ore', + castAs: 'number', + capabilities: ORDER_AND_RANGE, +} as const +export const DOUBLE_ORD = { + eqlType: 'eql_v3.double_ord', + castAs: 'number', + capabilities: ORDER_AND_RANGE, +} as const + +/** + * Translate a domain's semantic {@link QueryCapabilities} (plus its plaintext + * `castAs`, which decides how equality is answered) into the concrete EQL index + * block emitted by `build()`. + * + * - `unique` (the `hm` HMAC index) whenever equality is answered via HMAC: + * equality-only domains of ANY type, AND text order domains. Text equality is + * HMAC-based — the `eql_v3.text_ord` / `eql_v3.text_ord_ore` SQL domains + * REQUIRE `hm` in the stored ciphertext (their `eql_v3.eq_term` extracts it). + * - `ore` for any order/range domain (the `ob` term). For numeric/date order + * domains `ob` also answers equality (via the SQL `=` operator), so those emit + * `ore` ONLY — no `hm`. Text order domains emit BOTH `unique` and `ore`. + * - `match` (the `bf` bloom-filter index) for free-text search, deep-cloned from + * the per-call defaults so no nested object is ever shared across columns. + */ +function indexesForCapabilities( + capabilities: QueryCapabilities, + castAs: PlaintextKind, +): ColumnSchema['indexes'] { + const indexes: ColumnSchema['indexes'] = {} + + // Text equality is always HMAC-based, so a text order domain (`string` + + // order/range) still needs `unique`; numeric/date order domains answer + // equality via `ob` and must NOT emit `unique`. + if ( + capabilities.equality && + (!capabilities.orderAndRange || castAs === 'string') + ) { + indexes.unique = { token_filters: [] } + } + + if (capabilities.orderAndRange) { + indexes.ore = {} + } + + if (capabilities.freeTextSearch) { + // The factory returns fresh, unaliased nested objects per call, so no + // column's emitted match block ever shares state with another's. + indexes.match = defaultMatchOpts() + } + + return indexes +} + +/** Whether a domain's capabilities make it queryable at all (any flag set). */ +function isQueryableCapabilities(capabilities: QueryCapabilities): boolean { + return ( + capabilities.equality || + capabilities.orderAndRange || + capabilities.freeTextSearch + ) +} + +/** + * Shared base for every v3 concrete domain column. Parameterised by the FULL + * literal {@link V3DomainDefinition} (not by capabilities alone): the private + * `definition` field carries the literal `eqlType`/`castAs`/`capabilities`, so + * two otherwise-empty subclasses (e.g. `EncryptedBooleanColumn` and + * `EncryptedDateColumn`, both storage-only) are NOT mutually assignable. This + * nominality is what keeps plaintext inference precise. + */ +export class EncryptedV3Column<D extends V3DomainDefinition> { + constructor( + private readonly columnName: string, + private readonly definition: D, + ) {} + + getName(): string { + return this.columnName + } + + /** The concrete EQL v3 domain name. Metadata only; not emitted by `build()`. */ + getEqlType(): D['eqlType'] { + return this.definition.eqlType + } + + /** The semantic query capabilities this domain exposes. Metadata only. */ + getQueryCapabilities(): D['capabilities'] { + return this.definition.capabilities + } + + /** `true` when this domain can produce at least one kind of query term. */ + isQueryable(): QueryableFlag<D> { + return isQueryableCapabilities( + this.definition.capabilities, + ) as QueryableFlag<D> + } + + /** Emit the encrypt-config column: `cast_as` plus capability-derived indexes. */ + build(): ColumnSchema { + return { + cast_as: this.definition.castAs, + indexes: indexesForCapabilities( + this.definition.capabilities, + this.definition.castAs, + ), + } + } +} + +const TEXT_SEARCH_DOMAIN = { + eqlType: TEXT_SEARCH_EQL_TYPE, + castAs: 'string', + capabilities: TEXT_SEARCH, +} as const + +/** + * Builder for an `eql_v3.text_search` column. + * + * The concrete type inherently enables equality + order/range + free-text + * match — there are no capability-enabling methods. `.freeTextSearch(opts?)` + * tunes the match index only. + * + * NOTE — querying: a `text_search` column emits all three indexes (`unique`, + * `ore`, `match`), and the shared index-inference picks them by fixed priority + * `unique > match > ore`. So `encryptQuery(value, { column, table })` with NO + * explicit `queryType` builds an EQUALITY term (via `unique`), NOT a free-text + * match — a substring like `'joh'` then matches nothing. To run a free-text + * match query you MUST pass `queryType: 'freeTextSearch'`: + * + * ```typescript + * // equality (default): exact value only + * client.encryptQuery('john@example.com', { column: users.email, table: users }) + * // free-text match: substring/token search + * client.encryptQuery('joh', { column: users.email, table: users, queryType: 'freeTextSearch' }) + * ``` + */ +export class EncryptedTextSearchColumn extends EncryptedV3Column< + typeof TEXT_SEARCH_DOMAIN +> { + private matchOpts: BuiltMatchIndexOpts + + constructor(columnName: string) { + super(columnName, TEXT_SEARCH_DOMAIN) + this.matchOpts = defaultMatchOpts() + } + + /** + * Tune the match index. Each provided key replaces its default; omitted + * keys keep the default. This NEVER enables a capability — match is always + * on for this type. Merge semantics mirror v2's `opts?.x ?? default`. + */ + freeTextSearch(opts?: MatchIndexOpts): this { + // Shared merge+clone (schema/match-defaults) — one source of truth with the + // v2 `freeTextSearch()` builder. `resolveMatchOpts` merges each key over the + // per-call defaults and deep-clones, so a caller mutating their own opts + // object between `freeTextSearch(opts)` and `build()` cannot leak into the + // emitted config (clone-on-write). + this.matchOpts = resolveMatchOpts(opts) + return this + } + + /** Emit the encrypt-config column. Byte-identical to a v2 equality+order+match column. */ + override build(): ColumnSchema { + // Derive `cast_as` + the `unique`/`ore` blocks from the shared + // capability→index mapping (this domain's TEXT_SEARCH capabilities produce + // exactly `{ unique, ore, match }`), then override ONLY `match` with this + // builder's tuned opts. Hand-writing the unique/ore shape here would let it + // silently drift from `indexesForCapabilities` — the exact divergence class + // behind the text_ord `hm`-index bug. Deep-clone the match block so the + // returned config never aliases this builder's internal `matchOpts`. + const base = super.build() + return { + ...base, + indexes: { + ...base.indexes, + match: cloneMatchOpts(this.matchOpts), + }, + } + } +} + +// --------------------------------------------------------------------------- +// Concrete domain columns +// +// Every concrete class is an empty subclass parameterised by its literal domain +// definition (see EncryptedV3Column). The `types` namespace (see ./types) +// constructs these with the SAME literal constant so the instance's private +// `definition` field carries full literal type data — that is what keeps +// distinct domains nominally incompatible. +// --------------------------------------------------------------------------- + +// integer +export class EncryptedIntegerColumn extends EncryptedV3Column<typeof INTEGER> {} +export class EncryptedIntegerEqColumn extends EncryptedV3Column< + typeof INTEGER_EQ +> {} +export class EncryptedIntegerOrdOreColumn extends EncryptedV3Column< + typeof INTEGER_ORD_ORE +> {} +export class EncryptedIntegerOrdColumn extends EncryptedV3Column< + typeof INTEGER_ORD +> {} + +// smallint +export class EncryptedSmallintColumn extends EncryptedV3Column< + typeof SMALLINT +> {} +export class EncryptedSmallintEqColumn extends EncryptedV3Column< + typeof SMALLINT_EQ +> {} +export class EncryptedSmallintOrdOreColumn extends EncryptedV3Column< + typeof SMALLINT_ORD_ORE +> {} +export class EncryptedSmallintOrdColumn extends EncryptedV3Column< + typeof SMALLINT_ORD +> {} + +// bigint (int8) — native round-trips landed in protect-ffi 0.28; see the note +// by the BIGINT domain definitions above. +export class EncryptedBigintColumn extends EncryptedV3Column<typeof BIGINT> {} +export class EncryptedBigintEqColumn extends EncryptedV3Column< + typeof BIGINT_EQ +> {} +export class EncryptedBigintOrdOreColumn extends EncryptedV3Column< + typeof BIGINT_ORD_ORE +> {} +export class EncryptedBigintOrdColumn extends EncryptedV3Column< + typeof BIGINT_ORD +> {} + +// date +export class EncryptedDateColumn extends EncryptedV3Column<typeof DATE> {} +export class EncryptedDateEqColumn extends EncryptedV3Column<typeof DATE_EQ> {} +export class EncryptedDateOrdOreColumn extends EncryptedV3Column< + typeof DATE_ORD_ORE +> {} +export class EncryptedDateOrdColumn extends EncryptedV3Column< + typeof DATE_ORD +> {} + +// timestamp +export class EncryptedTimestampColumn extends EncryptedV3Column< + typeof TIMESTAMP +> {} +export class EncryptedTimestampEqColumn extends EncryptedV3Column< + typeof TIMESTAMP_EQ +> {} +export class EncryptedTimestampOrdOreColumn extends EncryptedV3Column< + typeof TIMESTAMP_ORD_ORE +> {} +export class EncryptedTimestampOrdColumn extends EncryptedV3Column< + typeof TIMESTAMP_ORD +> {} + +// numeric +export class EncryptedNumericColumn extends EncryptedV3Column<typeof NUMERIC> {} +export class EncryptedNumericEqColumn extends EncryptedV3Column< + typeof NUMERIC_EQ +> {} +export class EncryptedNumericOrdOreColumn extends EncryptedV3Column< + typeof NUMERIC_ORD_ORE +> {} +export class EncryptedNumericOrdColumn extends EncryptedV3Column< + typeof NUMERIC_ORD +> {} + +// text (text_search is defined above with its match-tuning override) +export class EncryptedTextColumn extends EncryptedV3Column<typeof TEXT> {} +export class EncryptedTextEqColumn extends EncryptedV3Column<typeof TEXT_EQ> {} +export class EncryptedTextMatchColumn extends EncryptedV3Column< + typeof TEXT_MATCH +> {} +export class EncryptedTextOrdOreColumn extends EncryptedV3Column< + typeof TEXT_ORD_ORE +> {} +export class EncryptedTextOrdColumn extends EncryptedV3Column< + typeof TEXT_ORD +> {} + +// boolean +export class EncryptedBooleanColumn extends EncryptedV3Column<typeof BOOLEAN> {} + +// real +export class EncryptedRealColumn extends EncryptedV3Column<typeof REAL> {} +export class EncryptedRealEqColumn extends EncryptedV3Column<typeof REAL_EQ> {} +export class EncryptedRealOrdOreColumn extends EncryptedV3Column< + typeof REAL_ORD_ORE +> {} +export class EncryptedRealOrdColumn extends EncryptedV3Column< + typeof REAL_ORD +> {} + +// double +export class EncryptedDoubleColumn extends EncryptedV3Column<typeof DOUBLE> {} +export class EncryptedDoubleEqColumn extends EncryptedV3Column< + typeof DOUBLE_EQ +> {} +export class EncryptedDoubleOrdOreColumn extends EncryptedV3Column< + typeof DOUBLE_ORD_ORE +> {} +export class EncryptedDoubleOrdColumn extends EncryptedV3Column< + typeof DOUBLE_ORD +> {} + +/** + * Union of every v3 concrete column type. Used as the value type for v3 table + * columns so a table may mix any generated domains. + */ +export type AnyEncryptedV3Column = + | EncryptedIntegerColumn + | EncryptedIntegerEqColumn + | EncryptedIntegerOrdOreColumn + | EncryptedIntegerOrdColumn + | EncryptedSmallintColumn + | EncryptedSmallintEqColumn + | EncryptedSmallintOrdOreColumn + | EncryptedSmallintOrdColumn + | EncryptedBigintColumn + | EncryptedBigintEqColumn + | EncryptedBigintOrdOreColumn + | EncryptedBigintOrdColumn + | EncryptedDateColumn + | EncryptedDateEqColumn + | EncryptedDateOrdOreColumn + | EncryptedDateOrdColumn + | EncryptedTimestampColumn + | EncryptedTimestampEqColumn + | EncryptedTimestampOrdOreColumn + | EncryptedTimestampOrdColumn + | EncryptedNumericColumn + | EncryptedNumericEqColumn + | EncryptedNumericOrdOreColumn + | EncryptedNumericOrdColumn + | EncryptedTextColumn + | EncryptedTextEqColumn + | EncryptedTextMatchColumn + | EncryptedTextOrdOreColumn + | EncryptedTextOrdColumn + | EncryptedTextSearchColumn + | EncryptedBooleanColumn + | EncryptedRealColumn + | EncryptedRealEqColumn + | EncryptedRealOrdOreColumn + | EncryptedRealOrdColumn + | EncryptedDoubleColumn + | EncryptedDoubleEqColumn + | EncryptedDoubleOrdOreColumn + | EncryptedDoubleOrdColumn + +/** + * Shape of v3 table columns: every value is a v3 concrete column builder. + * (Nested fields are deferred to later increments.) + */ +export type EncryptedV3TableColumn = { + [key: string]: AnyEncryptedV3Column +} + +/** Map a domain's {@link PlaintextKind} to its TypeScript plaintext type. */ +type PlaintextFromKind<K extends PlaintextKind> = K extends 'string' + ? string + : K extends 'number' + ? number + : K extends 'bigint' + ? bigint + : K extends 'boolean' + ? boolean + : K extends DateLikeCast + ? Date + : never + +/** + * The plaintext type for a single v3 column, read from the literal domain + * definition carried on the base class's private field. This is stable across + * empty subclasses that share the same base generic — a subclass-name + * conditional would collapse because those subclasses are structurally + * assignable to one another. + */ +export type PlaintextForColumn<C> = + C extends EncryptedV3Column<infer D> ? PlaintextFromKind<D['castAs']> : never + +/** + * The user-facing `queryType` names a v3 column supports, derived 1:1 from its + * capability flags. Resolves to `never` for a storage-only column (all flags + * `false`) and for any non-v3 value. The names mirror the {@link QueryCapabilities} + * keys and the first three {@link import('@/types').QueryTypeName} members. + */ +export type QueryTypesForColumn<C> = + C extends EncryptedV3Column<infer D> + ? + | (D['capabilities']['equality'] extends true ? 'equality' : never) + | (D['capabilities']['orderAndRange'] extends true + ? 'orderAndRange' + : never) + | (D['capabilities']['freeTextSearch'] extends true + ? 'freeTextSearch' + : never) + : never + +/** + * The concrete EQL v3 type string for a single column, read from the literal + * domain definition carried on the base class's private field (mirrors + * {@link PlaintextForColumn}). Distributes over a union of columns, so + * `EqlTypeForColumn<AnyEncryptedV3Column>` yields the union of every domain's + * `eqlType` — the canonical, source-of-truth key set for a type-driven test + * matrix keyed by domain. + */ +export type EqlTypeForColumn<C> = + C extends EncryptedV3Column<infer D> ? D['eqlType'] : never diff --git a/packages/stack/src/eql/v3/drizzle/codec.ts b/packages/stack/src/eql/v3/drizzle/codec.ts new file mode 100644 index 00000000..86d7e55a --- /dev/null +++ b/packages/stack/src/eql/v3/drizzle/codec.ts @@ -0,0 +1,23 @@ +/** + * v3 columns are `CREATE DOMAIN ... AS jsonb`, so they serialise as plain jsonb, + * distinct from v2's composite-literal parser. + */ + +export function v3ToDriver<TData>(value: TData): string | null { + if (value === null || value === undefined) { + return null + } + return JSON.stringify(value) +} + +export function v3FromDriver<TData>( + value: string | object | null | undefined, +): TData { + if (value === null || value === undefined) { + return value as TData + } + if (typeof value === 'object') { + return value as TData + } + return JSON.parse(value) as TData +} diff --git a/packages/stack/src/eql/v3/drizzle/column.ts b/packages/stack/src/eql/v3/drizzle/column.ts new file mode 100644 index 00000000..6727e447 --- /dev/null +++ b/packages/stack/src/eql/v3/drizzle/column.ts @@ -0,0 +1,122 @@ +import { customType } from 'drizzle-orm/pg-core' +import { + type AnyEncryptedV3Column, + type PlaintextForColumn, + types as v3Types, +} from '@/eql/v3' +import { v3FromDriver, v3ToDriver } from './codec.js' + +/** Every concrete `eql_v3.<domain>` string, derived from the eql/v3 factories. */ +export const EQL_V3_DOMAINS: ReadonlySet<string> = new Set( + Object.values(v3Types).map((factory) => factory('__probe__').getEqlType()), +) + +const buildersByDomain: ReadonlyMap< + string, + (name: string) => AnyEncryptedV3Column +> = new Map( + Object.values(v3Types).map((factory) => [ + factory('__probe__').getEqlType(), + factory, + ]), +) + +/** + * Drizzle copies `config.customTypeParams` from the builder into the processed + * PgColumn. Stashing the v3 builder there keeps recovery tied to the concrete + * column instance instead of a module-global name lookup. + */ +const EQL_V3_COLUMN_PARAM = Symbol.for('cipherstash:eqlv3Column') +const EQL_V3_COLUMN_LEGACY_PARAM = '_eqlv3Column' + +type EqlV3ColumnCarrier = Record<symbol, unknown> & { + [EQL_V3_COLUMN_LEGACY_PARAM]?: AnyEncryptedV3Column +} + +function readBuilder( + carrier: EqlV3ColumnCarrier | undefined, +): AnyEncryptedV3Column | undefined { + return ( + (carrier?.[EQL_V3_COLUMN_PARAM] as AnyEncryptedV3Column | undefined) ?? + carrier?.[EQL_V3_COLUMN_LEGACY_PARAM] + ) +} + +function writeBuilder( + carrier: EqlV3ColumnCarrier | undefined, + builder: AnyEncryptedV3Column, +): void { + if (!carrier) return + carrier[EQL_V3_COLUMN_PARAM] = builder + carrier[EQL_V3_COLUMN_LEGACY_PARAM] = builder +} + +function getCarrier(column: unknown): EqlV3ColumnCarrier | undefined { + if (!column || typeof column !== 'object') return undefined + + const direct = column as EqlV3ColumnCarrier + if (readBuilder(direct)) return direct + + const maybeWithConfig = column as { + config?: { customTypeParams?: EqlV3ColumnCarrier } + } + return maybeWithConfig.config?.customTypeParams +} + +function getSqlType(column: unknown): string | undefined { + if (!column || typeof column !== 'object') return undefined + const columnAny = column as { + getSQLType?: () => unknown + dataType?: unknown + sqlName?: unknown + } + const sqlType = + typeof columnAny.getSQLType === 'function' + ? columnAny.getSQLType() + : undefined + if (typeof sqlType === 'string') return sqlType + const dt = columnAny.dataType + const domain = typeof dt === 'function' ? dt() : (columnAny.sqlName ?? dt) + return typeof domain === 'string' ? domain : undefined +} + +export function makeEqlV3Column<C extends AnyEncryptedV3Column>(builder: C) { + type TData = PlaintextForColumn<C> + const domain = builder.getEqlType() + const name = builder.getName() + + const column = customType<{ data: TData; driverData: string | null }>({ + dataType() { + return domain + }, + toDriver(value: TData): string | null { + return v3ToDriver(value) + }, + fromDriver(value: string | object | null | undefined): TData { + return v3FromDriver<TData>(value) + }, + })(name) + + writeBuilder(getCarrier(column), builder) + writeBuilder(column as unknown as EqlV3ColumnCarrier, builder) + return column +} + +export function getEqlV3Column( + columnName: string, + column: unknown, +): AnyEncryptedV3Column | undefined { + const stashed = readBuilder(getCarrier(column)) + if (stashed) return stashed + + const sqlType = getSqlType(column) + const builderFactory = sqlType ? buildersByDomain.get(sqlType) : undefined + return builderFactory?.(columnName) +} + +export function isEqlV3Column(column: unknown): boolean { + if (!column || typeof column !== 'object') return false + if (readBuilder(getCarrier(column))) return true + const sqlType = getSqlType(column) + return typeof sqlType === 'string' && EQL_V3_DOMAINS.has(sqlType) +} diff --git a/packages/stack/src/eql/v3/drizzle/index.ts b/packages/stack/src/eql/v3/drizzle/index.ts new file mode 100644 index 00000000..0eaf9830 --- /dev/null +++ b/packages/stack/src/eql/v3/drizzle/index.ts @@ -0,0 +1,8 @@ +export { v3FromDriver, v3ToDriver } from './codec.js' +export { getEqlV3Column, isEqlV3Column, makeEqlV3Column } from './column.js' +export { + createEncryptionOperatorsV3, + EncryptionOperatorError, +} from './operators.js' +export { extractEncryptionSchemaV3 } from './schema-extraction.js' +export { types } from './types.js' diff --git a/packages/stack/src/eql/v3/drizzle/operators.ts b/packages/stack/src/eql/v3/drizzle/operators.ts new file mode 100644 index 00000000..7ed4ca78 --- /dev/null +++ b/packages/stack/src/eql/v3/drizzle/operators.ts @@ -0,0 +1,345 @@ +import { + and, + asc, + Column, + desc, + exists, + is, + isNotNull, + isNull, + not, + notExists, + or, + type SQL, + type SQLWrapper, + sql, +} from 'drizzle-orm' +import type { PgTable } from 'drizzle-orm/pg-core' +import type { EncryptionClient } from '@/encryption' +import type { AuditConfig } from '@/encryption/operations/base-operation' +import type { AnyEncryptedV3Column, AnyV3Table } from '@/eql/v3' +import type { LockContext } from '@/identity' +import type { ColumnSchema } from '@/schema' +import { getEqlV3Column } from './column.js' +import { extractEncryptionSchemaV3 } from './schema-extraction.js' +import { type ComparisonOp, type EqualityOp, v3Dialect } from './sql-dialect.js' + +const MAX_IN_ARRAY_CONCURRENCY = 4 + +export class EncryptionOperatorError extends Error { + constructor( + message: string, + public readonly context?: { + columnName?: string + tableName?: string + operator?: string + }, + ) { + super(message) + this.name = 'EncryptionOperatorError' + } +} + +interface ColumnContext { + builder: AnyEncryptedV3Column + table: AnyV3Table + indexes: ColumnSchema['indexes'] + columnName: string + tableName: string +} + +export type EncryptionOperatorCallOpts = { + lockContext?: LockContext + audit?: AuditConfig +} + +type ChainableOperation = { + withLockContext(lockContext: LockContext): ChainableOperation + audit(config: AuditConfig): ChainableOperation + then: PromiseLike<{ + data?: unknown + failure?: { message: string } + }>['then'] +} + +async function mapWithConcurrency<T, R>( + values: T[], + limit: number, + mapper: (value: T) => Promise<R>, +): Promise<R[]> { + const results = new Array<R>(values.length) + let next = 0 + + async function worker(): Promise<void> { + while (true) { + const index = next + next += 1 + if (index >= values.length) return + results[index] = await mapper(values[index]) + } + } + + await Promise.all( + Array.from({ length: Math.min(limit, values.length) }, () => worker()), + ) + return results +} + +export function createEncryptionOperatorsV3( + client: EncryptionClient, + defaults: EncryptionOperatorCallOpts = {}, +) { + const tableCache = new WeakMap<PgTable, AnyV3Table>() + + function drizzleTableOf(column: SQLWrapper): PgTable | undefined { + return is(column, Column) + ? (column.table as PgTable | undefined) + : undefined + } + + function resolveContext(column: SQLWrapper, operator: string): ColumnContext { + const columnName = is(column, Column) ? column.name : 'unknown' + const builder = getEqlV3Column(columnName, column) + if (!builder) { + throw new EncryptionOperatorError( + `Operator "${operator}" requires an encrypted v3 column, but "${columnName}" is not one.`, + { columnName, operator }, + ) + } + + const drizzleTable = drizzleTableOf(column) + const drizzleTableSymbols = drizzleTable as + | Record<symbol, string | undefined> + | undefined + const tableName = + drizzleTableSymbols?.[Symbol.for('drizzle:Name')] ?? 'unknown' + + let table = drizzleTable ? tableCache.get(drizzleTable) : undefined + if (!table && drizzleTable) { + table = extractEncryptionSchemaV3(drizzleTable) + tableCache.set(drizzleTable, table) + } + if (!table) { + throw new EncryptionOperatorError( + `Unable to resolve the encrypted table for column "${columnName}".`, + { columnName, operator }, + ) + } + + return { + builder, + table, + indexes: builder.build().indexes, + columnName, + tableName, + } + } + + function requireIndex( + ctx: ColumnContext, + index: 'unique' | 'ore' | 'match', + operator: string, + capability: string, + ): void { + if (!ctx.indexes[index]) { + throw new EncryptionOperatorError( + `Operator "${operator}" requires ${capability} on column "${ctx.columnName}" (eql_v3 domain ${ctx.builder.getEqlType()} does not support it).`, + { columnName: ctx.columnName, tableName: ctx.tableName, operator }, + ) + } + } + + function applyOperationOptions( + op: ChainableOperation, + opts?: EncryptionOperatorCallOpts, + ): ChainableOperation { + const lockContext = opts?.lockContext ?? defaults.lockContext + const audit = opts?.audit ?? defaults.audit + const withLock = lockContext ? op.withLockContext(lockContext) : op + if (audit) withLock.audit(audit) + return withLock + } + + async function encryptOperand( + ctx: ColumnContext, + value: unknown, + operator: string, + opts?: EncryptionOperatorCallOpts, + ): Promise<SQL> { + if (value == null) { + throw new EncryptionOperatorError( + `Operator "${operator}" cannot encrypt a null operand for column "${ctx.columnName}". Use isNull() or isNotNull() for NULL checks.`, + { + columnName: ctx.columnName, + tableName: ctx.tableName, + operator, + }, + ) + } + + const result = await applyOperationOptions( + client.encrypt(value as never, { + table: ctx.table, + column: ctx.builder as never, + }) as unknown as ChainableOperation, + opts, + ) + if (result.failure) { + throw new EncryptionOperatorError( + `Failed to encrypt query operand for "${ctx.columnName}": ${result.failure.message}`, + { columnName: ctx.columnName, tableName: ctx.tableName, operator }, + ) + } + return sql`${JSON.stringify(result.data)}` + } + + const colSql = (column: SQLWrapper): SQL => sql`${column}` + + async function equality( + op: EqualityOp, + left: SQLWrapper, + right: unknown, + opts?: EncryptionOperatorCallOpts, + ): Promise<SQL> { + const ctx = resolveContext(left, op) + if (!ctx.indexes.unique && !ctx.indexes.ore) { + throw new EncryptionOperatorError( + `Operator "${op}" requires equality on column "${ctx.columnName}".`, + { columnName: ctx.columnName, tableName: ctx.tableName, operator: op }, + ) + } + const enc = await encryptOperand(ctx, right, op, opts) + return v3Dialect.equality(op, colSql(left), enc) + } + + async function comparison( + op: ComparisonOp, + left: SQLWrapper, + right: unknown, + opts?: EncryptionOperatorCallOpts, + ): Promise<SQL> { + const ctx = resolveContext(left, op) + requireIndex(ctx, 'ore', op, 'order/range') + const enc = await encryptOperand(ctx, right, op, opts) + return v3Dialect.comparison(op, colSql(left), enc) + } + + async function range( + left: SQLWrapper, + min: unknown, + max: unknown, + negate: boolean, + operator: string, + opts?: EncryptionOperatorCallOpts, + ): Promise<SQL> { + const ctx = resolveContext(left, operator) + requireIndex(ctx, 'ore', operator, 'order/range') + const encMin = await encryptOperand(ctx, min, operator, opts) + const encMax = await encryptOperand(ctx, max, operator, opts) + const condition = v3Dialect.range(colSql(left), encMin, encMax) + return negate ? sql`NOT (${condition})` : condition + } + + async function contains( + left: SQLWrapper, + right: unknown, + operator: string, + opts?: EncryptionOperatorCallOpts, + ): Promise<SQL> { + const ctx = resolveContext(left, operator) + requireIndex(ctx, 'match', operator, 'free-text search') + const enc = await encryptOperand(ctx, right, operator, opts) + return v3Dialect.contains(colSql(left), enc) + } + + async function inArrayOp( + left: SQLWrapper, + values: unknown[], + negate: boolean, + operator: string, + opts?: EncryptionOperatorCallOpts, + ): Promise<SQL> { + if (values.length === 0) { + const ctx = resolveContext(left, operator) + throw new EncryptionOperatorError( + `Operator "${operator}" requires a non-empty list of values for column "${ctx.columnName}".`, + { columnName: ctx.columnName, tableName: ctx.tableName, operator }, + ) + } + const conditions = await mapWithConcurrency( + values, + MAX_IN_ARRAY_CONCURRENCY, + (v) => equality(negate ? 'ne' : 'eq', left, v, opts), + ) + const combined = negate ? and(...conditions) : or(...conditions) + return combined ?? (negate ? sql`true` : sql`false`) + } + + function orderTerm(column: SQLWrapper, operator: string): SQL { + const ctx = resolveContext(column, operator) + requireIndex(ctx, 'ore', operator, 'order/range') + return v3Dialect.orderBy(colSql(column)) + } + + async function combine( + joiner: typeof and, + empty: SQL, + conditions: (SQL | SQLWrapper | Promise<SQL> | undefined)[], + ): Promise<SQL> { + const present = conditions.filter( + (c): c is SQL | SQLWrapper | Promise<SQL> => c !== undefined, + ) + const resolved = await Promise.all(present) + return joiner(...resolved) ?? empty + } + + return { + eq: (l: SQLWrapper, r: unknown, opts?: EncryptionOperatorCallOpts) => + equality('eq', l, r, opts), + ne: (l: SQLWrapper, r: unknown, opts?: EncryptionOperatorCallOpts) => + equality('ne', l, r, opts), + gt: (l: SQLWrapper, r: unknown, opts?: EncryptionOperatorCallOpts) => + comparison('gt', l, r, opts), + gte: (l: SQLWrapper, r: unknown, opts?: EncryptionOperatorCallOpts) => + comparison('gte', l, r, opts), + lt: (l: SQLWrapper, r: unknown, opts?: EncryptionOperatorCallOpts) => + comparison('lt', l, r, opts), + lte: (l: SQLWrapper, r: unknown, opts?: EncryptionOperatorCallOpts) => + comparison('lte', l, r, opts), + between: ( + l: SQLWrapper, + min: unknown, + max: unknown, + opts?: EncryptionOperatorCallOpts, + ) => range(l, min, max, false, 'between', opts), + notBetween: ( + l: SQLWrapper, + min: unknown, + max: unknown, + opts?: EncryptionOperatorCallOpts, + ) => range(l, min, max, true, 'notBetween', opts), + contains: (l: SQLWrapper, r: unknown, opts?: EncryptionOperatorCallOpts) => + contains(l, r, 'contains', opts), + inArray: ( + l: SQLWrapper, + values: unknown[], + opts?: EncryptionOperatorCallOpts, + ) => inArrayOp(l, values, false, 'inArray', opts), + notInArray: ( + l: SQLWrapper, + values: unknown[], + opts?: EncryptionOperatorCallOpts, + ) => inArrayOp(l, values, true, 'notInArray', opts), + asc: (c: SQLWrapper) => asc(orderTerm(c, 'asc')), + desc: (c: SQLWrapper) => desc(orderTerm(c, 'desc')), + and: (...conds: (SQL | SQLWrapper | Promise<SQL> | undefined)[]) => + combine(and, sql`true`, conds), + or: (...conds: (SQL | SQLWrapper | Promise<SQL> | undefined)[]) => + combine(or, sql`false`, conds), + isNull, + isNotNull, + not, + exists, + notExists, + } +} diff --git a/packages/stack/src/eql/v3/drizzle/schema-extraction.ts b/packages/stack/src/eql/v3/drizzle/schema-extraction.ts new file mode 100644 index 00000000..d7df04d6 --- /dev/null +++ b/packages/stack/src/eql/v3/drizzle/schema-extraction.ts @@ -0,0 +1,38 @@ +import type { PgTable } from 'drizzle-orm/pg-core' +import { + type AnyEncryptedV3Column, + type AnyV3Table, + encryptedTable, +} from '@/eql/v3' +import { getEqlV3Column } from './column.js' + +export function extractEncryptionSchemaV3(table: PgTable): AnyV3Table { + // biome-ignore lint/suspicious/noExplicitAny: drizzle stores table metadata on symbols + const tableName = (table as any)[Symbol.for('drizzle:Name')] as + | string + | undefined + if (!tableName) { + throw new Error( + 'Unable to read table name from Drizzle table. Use a table created with pgTable().', + ) + } + + const columns: Record<string, AnyEncryptedV3Column> = {} + for (const [property, column] of Object.entries(table)) { + if (typeof column !== 'object' || column === null) continue + const columnName = + 'name' in column && typeof column.name === 'string' + ? column.name + : property + const builder = getEqlV3Column(columnName, column) + if (builder) columns[property] = builder + } + + if (Object.keys(columns).length === 0) { + throw new Error( + `No encrypted v3 columns found in table "${tableName}". Declare columns with the v3 drizzle \`types\` namespace.`, + ) + } + + return encryptedTable(tableName, columns) +} diff --git a/packages/stack/src/eql/v3/drizzle/sql-dialect.ts b/packages/stack/src/eql/v3/drizzle/sql-dialect.ts new file mode 100644 index 00000000..8080c231 --- /dev/null +++ b/packages/stack/src/eql/v3/drizzle/sql-dialect.ts @@ -0,0 +1,27 @@ +import { type SQL, sql } from 'drizzle-orm' + +export type EqualityOp = 'eq' | 'ne' +export type ComparisonOp = 'gt' | 'gte' | 'lt' | 'lte' + +export const v3Dialect = { + equality(op: EqualityOp, left: SQL, enc: SQL): SQL { + const fn = op === 'eq' ? sql.raw('eq') : sql.raw('neq') + return sql`eql_v3.${fn}(${left}, ${enc}::jsonb)` + }, + + comparison(op: ComparisonOp, left: SQL, enc: SQL): SQL { + return sql`eql_v3.${sql.raw(op)}(${left}, ${enc}::jsonb)` + }, + + range(left: SQL, min: SQL, max: SQL): SQL { + return sql`eql_v3.gte(${left}, ${min}::jsonb) AND eql_v3.lte(${left}, ${max}::jsonb)` + }, + + contains(left: SQL, enc: SQL): SQL { + return sql`eql_v3.contains(${left}, ${enc}::jsonb)` + }, + + orderBy(left: SQL): SQL { + return sql`eql_v3.ord_term(${left})` + }, +} diff --git a/packages/stack/src/eql/v3/drizzle/types.ts b/packages/stack/src/eql/v3/drizzle/types.ts new file mode 100644 index 00000000..b52fe83f --- /dev/null +++ b/packages/stack/src/eql/v3/drizzle/types.ts @@ -0,0 +1,19 @@ +import { types as v3Types } from '@/eql/v3' +import { makeEqlV3Column } from './column.js' + +type V3Types = typeof v3Types + +/** + * Drizzle-native mirror of `@/eql/v3`'s `types` namespace. Each PascalCase + * factory returns a Drizzle column wrapping the matching concrete v3 builder. + */ +export const types = Object.fromEntries( + Object.entries(v3Types).map(([name, factory]) => [ + name, + (columnName: string) => makeEqlV3Column(factory(columnName)), + ]), +) as { + [K in keyof V3Types]: ( + name: string, + ) => ReturnType<typeof makeEqlV3Column<ReturnType<V3Types[K]>>> +} diff --git a/packages/stack/src/eql/v3/index.ts b/packages/stack/src/eql/v3/index.ts new file mode 100644 index 00000000..069dc7ad --- /dev/null +++ b/packages/stack/src/eql/v3/index.ts @@ -0,0 +1,74 @@ +// Public barrel for the EQL v3 authoring DSL (`@cipherstash/stack/eql/v3`). +// +// Curated on purpose: it re-exports the `types` namespace, the concrete column +// classes (load-bearing for the `AnyEncryptedV3Column` union and nominal +// typing), the table API, and the inference type aliases. It deliberately does +// NOT re-export the per-domain literal consts (`INTEGER`, `TEXT_EQ`, …) — those are +// internal building blocks for `types` — and there are no standalone +// `encrypted<Domain>Column` factories any more: `types.*` is the single +// authoring API. + +export type { + AnyEncryptedV3Column, + EncryptedV3TableColumn, + EqlTypeForColumn, + PlaintextForColumn, + QueryCapabilities, + QueryTypesForColumn, +} from './columns' + +export { + EncryptedBigintColumn, + EncryptedBigintEqColumn, + EncryptedBigintOrdColumn, + EncryptedBigintOrdOreColumn, + EncryptedBooleanColumn, + EncryptedDateColumn, + EncryptedDateEqColumn, + EncryptedDateOrdColumn, + EncryptedDateOrdOreColumn, + EncryptedDoubleColumn, + EncryptedDoubleEqColumn, + EncryptedDoubleOrdColumn, + EncryptedDoubleOrdOreColumn, + EncryptedIntegerColumn, + EncryptedIntegerEqColumn, + EncryptedIntegerOrdColumn, + EncryptedIntegerOrdOreColumn, + EncryptedNumericColumn, + EncryptedNumericEqColumn, + EncryptedNumericOrdColumn, + EncryptedNumericOrdOreColumn, + EncryptedRealColumn, + EncryptedRealEqColumn, + EncryptedRealOrdColumn, + EncryptedRealOrdOreColumn, + EncryptedSmallintColumn, + EncryptedSmallintEqColumn, + EncryptedSmallintOrdColumn, + EncryptedSmallintOrdOreColumn, + EncryptedTextColumn, + EncryptedTextEqColumn, + EncryptedTextMatchColumn, + EncryptedTextOrdColumn, + EncryptedTextOrdOreColumn, + EncryptedTextSearchColumn, + EncryptedTimestampColumn, + EncryptedTimestampEqColumn, + EncryptedTimestampOrdColumn, + EncryptedTimestampOrdOreColumn, + TEXT_SEARCH_EQL_TYPE, +} from './columns' +export type { + AnyV3Table, + ColumnsOf, + InferEncrypted, + InferPlaintext, + QueryableColumnsOf, + V3DecryptedModel, + V3EncryptedModel, + V3ModelInput, +} from './table' + +export { buildEncryptConfig, EncryptedTable, encryptedTable } from './table' +export { types } from './types' diff --git a/packages/stack/src/eql/v3/table.ts b/packages/stack/src/eql/v3/table.ts new file mode 100644 index 00000000..8ea14497 --- /dev/null +++ b/packages/stack/src/eql/v3/table.ts @@ -0,0 +1,224 @@ +import type { ColumnSchema, EncryptConfig } from '@/schema' +import type { Encrypted } from '@/types' +import type { + EncryptedV3TableColumn, + PlaintextForColumn, + QueryTypesForColumn, +} from './columns' + +interface TableDefinition { + tableName: string + columns: Record<string, ColumnSchema> +} + +/** + * A v3 encrypted table. Mirrors the v2 `EncryptedTable` but only accepts v3 + * column builders. Emits the same `{ tableName, columns }` definition shape. + */ +export class EncryptedTable<T extends EncryptedV3TableColumn> { + /** @internal Type-level brand so TypeScript can infer `T` from `EncryptedTable<T>`. */ + declare readonly _columnType: T + + constructor( + public readonly tableName: string, + public readonly columnBuilders: T, + ) {} + + build(): TableDefinition { + const builtColumns: Record<string, ColumnSchema> = {} + for (const builder of Object.values(this.columnBuilders)) { + // Key by the column's DB name (`getName()`), NOT the JS property name. + // `encrypt`/`decrypt` look columns up in the config by `column.getName()`, + // so a camelCase JS key mapping to a snake_case DB column (e.g. + // `createdOn: types.Date('created_on')`) must register under + // `created_on` or the FFI reports "column not found in Encrypt config". + const name = builder.getName() + // Two JS properties resolving to the same DB name would silently overwrite + // here (later wins), dropping the first column's config. Fail loudly — + // matching the duplicate-tableName guard in buildEncryptConfig and the + // reserved-key guard in encryptedTable. + if (Object.hasOwn(builtColumns, name)) { + throw new Error( + `[eql/v3]: duplicate column name "${name}" in table "${this.tableName}" — two columns resolve to the same DB name`, + ) + } + builtColumns[name] = builder.build() + } + return { + tableName: this.tableName, + columns: builtColumns, + } + } + + /** + * Map each column's JS property name to its DB column name (`getName()`). + * The model path matches user models by property name but must address the + * encrypt config and FFI by DB name — `build()` keys columns by DB name, so + * the two only agree when property == name. This recovers the mapping that + * `build()` discards. + */ + buildColumnKeyMap(): Record<string, string> { + const map: Record<string, string> = {} + for (const [property, builder] of Object.entries(this.columnBuilders)) { + map[property] = builder.getName() + } + return map + } +} + +/** + * Own instance members of {@link EncryptedTable} that a column name must not + * shadow. Because {@link encryptedTable} copies column builders onto the + * instance for accessor access (`users.email`), a column named e.g. `build` + * would otherwise overwrite the method that {@link buildEncryptConfig} relies + * on. `_columnType` is a type-only `declare` (no runtime property) so it is + * listed explicitly here rather than caught by the `in` check below. + */ +const RESERVED_TABLE_KEYS = new Set([ + 'tableName', + 'columnBuilders', + '_columnType', + 'build', + 'buildColumnKeyMap', +]) + +/** + * Whether a column name would collide with a reserved property on the table + * object — either an own member ({@link RESERVED_TABLE_KEYS}) or any inherited + * `Object.prototype` member (`constructor`, `toString`, `valueOf`, + * `hasOwnProperty`, …). The `in` check covers the prototype chain so assigning + * the column as an own property can never shadow a prototype method/accessor. + */ +function isReservedTableKey(tableBuilder: object, colName: string): boolean { + return RESERVED_TABLE_KEYS.has(colName) || colName in tableBuilder +} + +/** + * Define a v3 encrypted table. Intentionally shadows the v2 `encryptedTable` + * name but lives on the `/eql/v3` subpath — the importer picks the model by + * import path. The returned object is also a column accessor (`users.email`). + */ +export function encryptedTable<T extends EncryptedV3TableColumn>( + tableName: string, + columns: T, +): EncryptedTable<T> & T { + const tableBuilder = new EncryptedTable( + tableName, + columns, + ) as EncryptedTable<T> & T + + for (const [colName, colBuilder] of Object.entries(columns)) { + if (isReservedTableKey(tableBuilder, colName)) { + throw new Error( + `Column name "${colName}" collides with a reserved EncryptedTable property`, + ) + } + ;(tableBuilder as EncryptedV3TableColumn)[colName] = colBuilder + } + + return tableBuilder +} + +/** + * Build an `EncryptConfig` (`v: 1`) from one or more v3 tables. Emits the same + * shape as v2's `buildEncryptConfig`. + */ +export function buildEncryptConfig( + ...tables: Array<EncryptedTable<EncryptedV3TableColumn>> +): EncryptConfig { + const config: EncryptConfig = { + v: 1, + tables: {}, + } + + for (const tb of tables) { + const tableDef = tb.build() + // Config tables are keyed by name, so a duplicate would silently overwrite + // the earlier table. Fail loudly instead. (v3-only additive guard; v2's + // buildEncryptConfig keeps its existing silent-overwrite behavior.) + if (Object.hasOwn(config.tables, tableDef.tableName)) { + throw new Error( + `[eql/v3]: duplicate table name "${tableDef.tableName}" passed to buildEncryptConfig — each table must have a unique name`, + ) + } + config.tables[tableDef.tableName] = tableDef.columns + } + + return config +} + +/** + * Infer the plaintext (decrypted) shape from a v3 table schema. Each column maps + * to the TypeScript type of its domain's `castAs` kind. + */ +export type InferPlaintext<T extends EncryptedTable<EncryptedV3TableColumn>> = + T extends EncryptedTable<infer C> + ? { [K in keyof C]: PlaintextForColumn<C[K]> } + : never + +/** + * Infer the encrypted shape from a v3 table schema. See {@link InferPlaintext} + * for why no key-remap filter is needed in the flat single-type model. + */ +export type InferEncrypted<T extends EncryptedTable<EncryptedV3TableColumn>> = + T extends EncryptedTable<infer C> ? { [K in keyof C]: Encrypted } : never + +// --------------------------------------------------------------------------- +// Typed-client surface helpers (@cipherstash/stack/v3) +// --------------------------------------------------------------------------- + +/** Any v3 table, regardless of its column map. */ +export type AnyV3Table = EncryptedTable<EncryptedV3TableColumn> + +/** Union of the concrete column builders declared on a v3 table. */ +export type ColumnsOf<T extends AnyV3Table> = + T extends EncryptedTable<infer C> ? C[keyof C] : never + +/** + * Union of the *queryable* column builders on a v3 table. Storage-only columns + * (whose {@link QueryTypesForColumn} is `never`) are filtered out, so they can't + * be passed to a query method. + */ +export type QueryableColumnsOf<T extends AnyV3Table> = + T extends EncryptedTable<infer C> + ? { + [K in keyof C]: [QueryTypesForColumn<C[K]>] extends [never] + ? never + : C[K] + }[keyof C] + : never + +/** + * The accepted input model for {@link import('@/encryption/v3').TypedEncryptionClient.encryptModel}. + * `T` is inferred from the argument: keys that name a schema column are pinned to + * the column's plaintext type (nullable if the field is nullable), so a wrong-typed + * field fails assignability; all other keys pass through unchanged. + */ +export type V3ModelInput<Table extends AnyV3Table, T> = { + [K in keyof T]: K extends keyof InferPlaintext<Table> + ? null extends T[K] + ? InferPlaintext<Table>[K] | null + : InferPlaintext<Table>[K] + : T[K] +} + +/** The encrypted result model: schema columns become `Encrypted`, others pass through. */ +export type V3EncryptedModel<Table extends AnyV3Table, T> = { + [K in keyof T]: K extends keyof InferPlaintext<Table> + ? null extends T[K] + ? Encrypted | null + : Encrypted + : T[K] +} + +/** + * The decrypted result model: schema columns become their plaintext type, others + * pass through. Structurally identical to {@link V3ModelInput} — decrypt yields + * the same plaintext shape encrypt accepts — so it is aliased rather than + * re-declared to keep the input and output shapes from silently drifting when + * one copy is edited. The distinct name is kept for call-site readability. + */ +export type V3DecryptedModel<Table extends AnyV3Table, T> = V3ModelInput< + Table, + T +> diff --git a/packages/stack/src/eql/v3/types.ts b/packages/stack/src/eql/v3/types.ts new file mode 100644 index 00000000..92f9ba15 --- /dev/null +++ b/packages/stack/src/eql/v3/types.ts @@ -0,0 +1,185 @@ +import { + BIGINT, + BIGINT_EQ, + BIGINT_ORD, + BIGINT_ORD_ORE, + BOOLEAN, + DATE, + DATE_EQ, + DATE_ORD, + DATE_ORD_ORE, + DOUBLE, + DOUBLE_EQ, + DOUBLE_ORD, + DOUBLE_ORD_ORE, + EncryptedBigintColumn, + EncryptedBigintEqColumn, + EncryptedBigintOrdColumn, + EncryptedBigintOrdOreColumn, + EncryptedBooleanColumn, + EncryptedDateColumn, + EncryptedDateEqColumn, + EncryptedDateOrdColumn, + EncryptedDateOrdOreColumn, + EncryptedDoubleColumn, + EncryptedDoubleEqColumn, + EncryptedDoubleOrdColumn, + EncryptedDoubleOrdOreColumn, + EncryptedIntegerColumn, + EncryptedIntegerEqColumn, + EncryptedIntegerOrdColumn, + EncryptedIntegerOrdOreColumn, + EncryptedNumericColumn, + EncryptedNumericEqColumn, + EncryptedNumericOrdColumn, + EncryptedNumericOrdOreColumn, + EncryptedRealColumn, + EncryptedRealEqColumn, + EncryptedRealOrdColumn, + EncryptedRealOrdOreColumn, + EncryptedSmallintColumn, + EncryptedSmallintEqColumn, + EncryptedSmallintOrdColumn, + EncryptedSmallintOrdOreColumn, + EncryptedTextColumn, + EncryptedTextEqColumn, + EncryptedTextMatchColumn, + EncryptedTextOrdColumn, + EncryptedTextOrdOreColumn, + EncryptedTextSearchColumn, + EncryptedTimestampColumn, + EncryptedTimestampEqColumn, + EncryptedTimestampOrdColumn, + EncryptedTimestampOrdOreColumn, + INTEGER, + INTEGER_EQ, + INTEGER_ORD, + INTEGER_ORD_ORE, + NUMERIC, + NUMERIC_EQ, + NUMERIC_ORD, + NUMERIC_ORD_ORE, + REAL, + REAL_EQ, + REAL_ORD, + REAL_ORD_ORE, + SMALLINT, + SMALLINT_EQ, + SMALLINT_ORD, + SMALLINT_ORD_ORE, + TEXT, + TEXT_EQ, + TEXT_MATCH, + TEXT_ORD, + TEXT_ORD_ORE, + TIMESTAMP, + TIMESTAMP_EQ, + TIMESTAMP_ORD, + TIMESTAMP_ORD_ORE, +} from './columns' + +/** + * The v3 column-type namespace. Each member is a public, semantic factory name + * for a concrete EQL v3 column. Most members mirror the underlying domain name; + * JS-friendly scalar names map to Postgres concrete domains, e.g. + * `types.IntegerOrd` builds an `eql_v3.integer_ord` column and `types.Boolean` + * builds an `eql_v3.bool` column. + * + * If these factory names stop matching the emitted capability/domain surface, + * the stack package is out of sync with the underlying EQL build. That is a + * version mismatch, not a harmless naming drift. + * + * Each factory returns the CONCRETE column class instance (never the widened + * `AnyEncryptedV3Column`) so per-column plaintext / query-capability inference + * stays precise. + * + * ```ts + * import { encryptedTable, types } from '@cipherstash/stack/eql/v3' + * + * const events = encryptedTable('events', { + * actor: types.TextEq('actor'), // equality + * weight: types.IntegerOrd('weight'), // order + range + * createdAt: types.Timestamp('created_at'), // storage only + * }) + * ``` + * + * `types.TextSearch` keeps the chainable `.freeTextSearch(opts)` tuner (the + * only capability-bearing chain — every other domain is fully described by its + * type). + */ +export const types = { + // integer + Integer: (name: string) => new EncryptedIntegerColumn(name, INTEGER), + IntegerEq: (name: string) => new EncryptedIntegerEqColumn(name, INTEGER_EQ), + IntegerOrdOre: (name: string) => + new EncryptedIntegerOrdOreColumn(name, INTEGER_ORD_ORE), + IntegerOrd: (name: string) => + new EncryptedIntegerOrdColumn(name, INTEGER_ORD), + + // smallint + Smallint: (name: string) => new EncryptedSmallintColumn(name, SMALLINT), + SmallintEq: (name: string) => + new EncryptedSmallintEqColumn(name, SMALLINT_EQ), + SmallintOrdOre: (name: string) => + new EncryptedSmallintOrdOreColumn(name, SMALLINT_ORD_ORE), + SmallintOrd: (name: string) => + new EncryptedSmallintOrdColumn(name, SMALLINT_ORD), + + // bigint (int8) — plaintext is a JS `bigint` (i64-bounded at the protect-ffi + // boundary); native round-tripping landed in protect-ffi 0.28 + Bigint: (name: string) => new EncryptedBigintColumn(name, BIGINT), + BigintEq: (name: string) => new EncryptedBigintEqColumn(name, BIGINT_EQ), + BigintOrdOre: (name: string) => + new EncryptedBigintOrdOreColumn(name, BIGINT_ORD_ORE), + BigintOrd: (name: string) => new EncryptedBigintOrdColumn(name, BIGINT_ORD), + + // date + Date: (name: string) => new EncryptedDateColumn(name, DATE), + DateEq: (name: string) => new EncryptedDateEqColumn(name, DATE_EQ), + DateOrdOre: (name: string) => + new EncryptedDateOrdOreColumn(name, DATE_ORD_ORE), + DateOrd: (name: string) => new EncryptedDateOrdColumn(name, DATE_ORD), + + // timestamp + Timestamp: (name: string) => new EncryptedTimestampColumn(name, TIMESTAMP), + TimestampEq: (name: string) => + new EncryptedTimestampEqColumn(name, TIMESTAMP_EQ), + TimestampOrdOre: (name: string) => + new EncryptedTimestampOrdOreColumn(name, TIMESTAMP_ORD_ORE), + TimestampOrd: (name: string) => + new EncryptedTimestampOrdColumn(name, TIMESTAMP_ORD), + + // numeric + Numeric: (name: string) => new EncryptedNumericColumn(name, NUMERIC), + NumericEq: (name: string) => new EncryptedNumericEqColumn(name, NUMERIC_EQ), + NumericOrdOre: (name: string) => + new EncryptedNumericOrdOreColumn(name, NUMERIC_ORD_ORE), + NumericOrd: (name: string) => + new EncryptedNumericOrdColumn(name, NUMERIC_ORD), + + // text + Text: (name: string) => new EncryptedTextColumn(name, TEXT), + TextEq: (name: string) => new EncryptedTextEqColumn(name, TEXT_EQ), + TextMatch: (name: string) => new EncryptedTextMatchColumn(name, TEXT_MATCH), + TextOrdOre: (name: string) => + new EncryptedTextOrdOreColumn(name, TEXT_ORD_ORE), + TextOrd: (name: string) => new EncryptedTextOrdColumn(name, TEXT_ORD), + TextSearch: (name: string) => new EncryptedTextSearchColumn(name), + + // boolean + Boolean: (name: string) => new EncryptedBooleanColumn(name, BOOLEAN), + + // real + Real: (name: string) => new EncryptedRealColumn(name, REAL), + RealEq: (name: string) => new EncryptedRealEqColumn(name, REAL_EQ), + RealOrdOre: (name: string) => + new EncryptedRealOrdOreColumn(name, REAL_ORD_ORE), + RealOrd: (name: string) => new EncryptedRealOrdColumn(name, REAL_ORD), + + // double + Double: (name: string) => new EncryptedDoubleColumn(name, DOUBLE), + DoubleEq: (name: string) => new EncryptedDoubleEqColumn(name, DOUBLE_EQ), + DoubleOrdOre: (name: string) => + new EncryptedDoubleOrdOreColumn(name, DOUBLE_ORD_ORE), + DoubleOrd: (name: string) => new EncryptedDoubleOrdColumn(name, DOUBLE_ORD), +} as const diff --git a/packages/stack/src/identity/index.ts b/packages/stack/src/identity/index.ts index a1197321..f9d0e4fb 100644 --- a/packages/stack/src/identity/index.ts +++ b/packages/stack/src/identity/index.ts @@ -39,7 +39,12 @@ export type LockContextInput = LockContext | Context * that protect-ffi expects. Synchronous — no token round-trip. */ export function resolveLockContext(input: LockContextInput): Context { - return input instanceof LockContext ? input.identityContext : input + // Use a structural check as well as `instanceof` so a `LockContext` + // constructed in another realm (or from a duplicate module instance) is still + // resolved rather than slipping through as a raw `Context`. + return input instanceof LockContext || 'identityContext' in input + ? (input as LockContext).identityContext + : input } /** @@ -188,7 +193,10 @@ export class LockContext { return withResult( () => ({ context: this.context, - ctsToken: this.ctsToken, + // Only include `ctsToken` when one was actually set, so the + // returned shape matches the optional `ctsToken?` type rather + // than carrying an explicit `undefined`. + ...(this.ctsToken ? { ctsToken: this.ctsToken } : {}), }), (error) => ({ type: EncryptionErrorTypes.CtsTokenError, diff --git a/packages/stack/src/schema/index.ts b/packages/stack/src/schema/index.ts index 48181f12..a289ed6d 100644 --- a/packages/stack/src/schema/index.ts +++ b/packages/stack/src/schema/index.ts @@ -1,5 +1,6 @@ import { z } from 'zod' -import type { Encrypted } from '@/types' +import type { BuildableTable, Encrypted } from '@/types' +import { resolveMatchOpts } from './match-defaults' // ------------------------ // Zod schemas @@ -37,15 +38,29 @@ export const eqlCastAsEnum = z 'double', 'boolean', 'date', + 'timestamp', 'jsonb', ]) .default('text') /** * SDK-facing data types — developer-friendly aliases accepted by `dataType()`. + * + * `timestamp` is distinct from `date`: `date` is calendar-date only (time-of-day + * truncated to midnight), while `timestamp` preserves the full date+time. v3 + * `timestamp` domains set `cast_as: 'timestamp'` so the FFI keeps the instant. */ export const castAsEnum = z - .enum(['bigint', 'boolean', 'date', 'number', 'string', 'json', 'text']) + .enum([ + 'bigint', + 'boolean', + 'date', + 'timestamp', + 'number', + 'string', + 'json', + 'text', + ]) .default('text') /** @@ -68,6 +83,8 @@ export function toEqlCastAs(value: CastAs): EqlCastAs { return 'boolean' case 'date': return 'date' + case 'timestamp': + return 'timestamp' case 'json': return 'jsonb' } @@ -210,7 +227,7 @@ export class EncryptedField { * a different type so the encryption layer knows how to encode the plaintext * before encrypting. * - * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'text'`, `'bigint'`, or `'json'`. + * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'timestamp'`, `'text'`, `'bigint'`, or `'json'`. Use `'timestamp'` (not `'date'`) to preserve time-of-day — `'date'` truncates to midnight. * @returns This `EncryptedField` instance for method chaining. * * @example @@ -259,7 +276,7 @@ export class EncryptedColumn { * a different type so the encryption layer knows how to encode the plaintext * before encrypting. * - * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`. + * @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'timestamp'`, `'text'`, `'bigint'`, or `'json'`. Use `'timestamp'` (not `'date'`) to preserve time-of-day — `'date'` truncates to midnight. * @returns This `EncryptedColumn` instance for method chaining. * * @example @@ -351,18 +368,11 @@ export class EncryptedColumn { * ``` */ freeTextSearch(opts?: MatchIndexOpts) { - // Provide defaults - this.indexesValue.match = { - tokenizer: opts?.tokenizer ?? { kind: 'ngram', token_length: 3 }, - token_filters: opts?.token_filters ?? [ - { - kind: 'downcase', - }, - ], - k: opts?.k ?? 6, - m: opts?.m ?? 2048, - include_original: opts?.include_original ?? true, - } + // Shared merge+clone (schema/match-defaults) — one source of truth with the + // EQL v3 domain builders. `resolveMatchOpts` deep-clones, so a caller + // mutating their own `opts` (or its nested tokenizer/token_filters) after + // this call cannot leak into the stored schema. + this.indexesValue.match = resolveMatchOpts(opts) return this } @@ -678,7 +688,7 @@ export function encryptedField(valueName: string) { * ``` */ export function buildEncryptConfig( - ...protectTables: Array<EncryptedTable<EncryptedTableColumn>> + ...protectTables: Array<BuildableTable> ): EncryptConfig { const config: EncryptConfig = { v: 1, diff --git a/packages/stack/src/schema/match-defaults.ts b/packages/stack/src/schema/match-defaults.ts new file mode 100644 index 00000000..e7518590 --- /dev/null +++ b/packages/stack/src/schema/match-defaults.ts @@ -0,0 +1,76 @@ +import type { MatchIndexOpts } from './index' + +/** + * Fully-resolved match-index options: every field present and non-`undefined`. + * + * `MatchIndexOpts` (the user-facing tuning input) has all fields optional — + * each is `.default(...).optional()` in the zod schema, so its inferred type is + * `T | undefined`. This type pins the BUILT/resolved shape explicitly via + * `NonNullable<...>`, which states the non-null intent directly and is robust + * regardless of `Required<>`'s subtle, `exactOptionalPropertyTypes`-dependent + * stripping semantics. + */ +export type BuiltMatchIndexOpts = { + tokenizer: NonNullable<MatchIndexOpts['tokenizer']> + token_filters: NonNullable<MatchIndexOpts['token_filters']> + k: NonNullable<MatchIndexOpts['k']> + m: NonNullable<MatchIndexOpts['m']> + include_original: NonNullable<MatchIndexOpts['include_original']> +} + +/** + * Default match-index parameters — the single source of truth shared by the + * v2 `freeTextSearch()` builder and the v3 domain builders (note + * `include_original: true`, which is the v2 builder default rather than the + * zod-schema default of `false`). + * + * This is a FACTORY (not a shared `const`) so every caller gets fresh, unaliased + * nested objects (`tokenizer`, `token_filters` and the `{ kind: 'downcase' }` + * inside it). A shared const would be shallow-copied by `{ ...DEFAULT }`, leaving + * those nested objects aliased across every column — a caller mutating one built + * config could then corrupt the defaults used by later columns. + */ +export function defaultMatchOpts(): BuiltMatchIndexOpts { + return { + tokenizer: { kind: 'ngram', token_length: 3 }, + token_filters: [{ kind: 'downcase' }], + k: 6, + m: 2048, + include_original: true, + } +} + +/** + * Deep-clone a built match block (`tokenizer` and `token_filters` are its only + * nested values) so no emitted config or stored builder state ever aliases + * another's nested objects — a caller mutating one cannot corrupt the other. + */ +export function cloneMatchOpts(opts: BuiltMatchIndexOpts): BuiltMatchIndexOpts { + return { + ...opts, + tokenizer: { ...opts.tokenizer }, + token_filters: opts.token_filters.map((f) => ({ ...f })), + } +} + +/** + * Resolve user-supplied `freeTextSearch(opts)` input into a fully-built match + * block: each provided key replaces its default, omitted keys keep the default + * (`opts?.x ?? default.x`). The single source of truth for that five-field merge + * shared by the v2 `freeTextSearch()` builder and the v3 domain builders. + * + * The result is deep-cloned ({@link cloneMatchOpts}) so a caller mutating their + * own `opts` object (or its nested `tokenizer`/`token_filters`) after this call + * can never leak into the stored builder state or the emitted config — clone-on- + * write for both builders, not just v3. + */ +export function resolveMatchOpts(opts?: MatchIndexOpts): BuiltMatchIndexOpts { + const defaults = defaultMatchOpts() + return cloneMatchOpts({ + tokenizer: opts?.tokenizer ?? defaults.tokenizer, + token_filters: opts?.token_filters ?? defaults.token_filters, + k: opts?.k ?? defaults.k, + m: opts?.m ?? defaults.m, + include_original: opts?.include_original ?? defaults.include_original, + }) +} diff --git a/packages/stack/src/types-public.ts b/packages/stack/src/types-public.ts index 929f0433..2553d3d3 100644 --- a/packages/stack/src/types-public.ts +++ b/packages/stack/src/types-public.ts @@ -14,6 +14,11 @@ // Query types (public only) export type { AuthStrategy, + BuildableColumn, + BuildableQueryColumn, + BuildableTable, + BuildableTableColumns, + BuildableV3QueryableColumn, BulkDecryptedData, BulkDecryptPayload, BulkEncryptedData, @@ -25,6 +30,7 @@ export type { DecryptionResult, Encrypted, EncryptedFields, + EncryptedFromBuildableTable, EncryptedFromSchema, EncryptedQuery, EncryptedQueryResult, diff --git a/packages/stack/src/types.ts b/packages/stack/src/types.ts index a284596b..be03ed12 100644 --- a/packages/stack/src/types.ts +++ b/packages/stack/src/types.ts @@ -1,15 +1,17 @@ import type { AuthStrategy, Encrypted as CipherStashEncrypted, + EncryptedPayload as CipherStashEncryptedPayload, EncryptedQuery as CipherStashEncryptedQuery, + EncryptedV3Query as CipherStashEncryptedV3Query, JsPlaintext, newClient, QueryOpName, } from '@cipherstash/protect-ffi' import type { + ColumnSchema, EncryptedColumn, EncryptedField, - EncryptedTable, EncryptedTableColumn, // Imported type-only for the TSDoc {@link} references in the comments below. encryptedColumn, @@ -49,18 +51,36 @@ export type Client = Awaited<ReturnType<typeof newClient>> | undefined export type EncryptedValue = Brand<CipherStashEncrypted, 'encrypted'> /** Structural type representing encrypted data stored in the database. Always - * carries a ciphertext. See also `EncryptedValue` for branded nominal typing, + * carries a ciphertext. Covers both wire formats: the EQL v2.3 payloads and + * the EQL v3 payloads. See also `EncryptedValue` for branded nominal typing, * and {@link EncryptedQuery} for the search-term shape returned by * `encryptQuery`. */ -export type Encrypted = CipherStashEncrypted +export type Encrypted = CipherStashEncryptedPayload /** Structural type representing an encrypted query term (search needle) * returned by `encryptQuery` / `encryptQueryBulk` for scalar * (`unique` / `match` / `ore`) lookups and `ste_vec_selector` JSON path - * queries. Carries no ciphertext — matched against stored values, never - * decrypted. JSON containment queries (`ste_vec_term`) return a + * queries, plus — under `eqlVersion: 3` — the `eql_v3.jsonb_query` + * containment needle. Carries no ciphertext — matched against stored values, + * never decrypted. v2 JSON containment queries (`ste_vec_term`) return a * storage-shaped {@link Encrypted} payload instead. */ -export type EncryptedQuery = CipherStashEncryptedQuery +export type EncryptedQuery = + | CipherStashEncryptedQuery + | CipherStashEncryptedV3Query + +/** + * Plaintext values the SDK accepts for encryption. + * + * Widens the FFI's `JsPlaintext` (`string | number | boolean | + * Record<string, unknown> | JsPlaintext[]`) with `Date`. `Date` is a supported + * cast target that is omitted from the FFI's `JsPlaintext` INPUT union, but it + * serializes at the boundary via `toJSON` (ISO string), so it is accepted on + * the way in. + * + * When the upstream FFI `JsPlaintext` includes `Date`, this extra arm can + * collapse back into `JsPlaintext`. + */ +export type Plaintext = JsPlaintext | Date // --------------------------------------------------------------------------- // Client configuration @@ -131,11 +151,95 @@ export type ClientConfig = { type AtLeastOneCsTable<T> = [T, ...T[]] +/** Structural contract for a column builder the client can consume for STORAGE + * (`encrypt`). Satisfied by v2 `EncryptedColumn` / `EncryptedField` AND v3 + * `EncryptedTextSearchColumn` — fields ARE encryptable, so this stays wide. */ +export interface BuildableColumn { + getName(): string + build(): ColumnSchema +} + +/** Structural contract for a column the client can consume for QUERIES + * (`encryptQuery` / search terms). Narrower than `BuildableColumn`: it must + * EXCLUDE non-queryable `EncryptedField` (a field has no indexes). A v2 + * `EncryptedColumn` qualifies via the nominal arm; a v3 queryable concrete + * type qualifies via the `getEqlType()` structural arm; `EncryptedField` (no + * `getEqlType`, not an `EncryptedColumn`) is rejected. */ +export interface BuildableV3QueryableColumn extends BuildableColumn { + getEqlType(): string + getQueryCapabilities(): { + equality: boolean + orderAndRange: boolean + freeTextSearch: boolean + } + isQueryable(): true +} + +export type BuildableQueryColumn = EncryptedColumn | BuildableV3QueryableColumn + +/** Structural contract for a table builder the client can consume. Satisfied by + * v2 and v3 `EncryptedTable` alike. */ +export interface BuildableTable { + tableName: string + build(): { tableName: string; columns: Record<string, ColumnSchema> } + /** + * Optional map from a model field's JS property name to its encrypt-config + * column name (the DB name). Present when the two can differ — v3 tables key + * their config by DB name (`column.getName()`) while models are written with + * JS property keys, so the model path must match by property but address the + * FFI/config by DB name. + * + * Absent on v2 tables, whose `build()` already keys columns by the JS property + * name; the model path then matches and addresses by that same key. + */ + buildColumnKeyMap?(): Record<string, string> +} + export type EncryptionClientConfig = { - schemas: AtLeastOneCsTable<EncryptedTable<EncryptedTableColumn>> + schemas: AtLeastOneCsTable<BuildableTable> config?: ClientConfig } +/** + * The literal column map of a buildable table, read from its type-level + * `_columnType` brand. Both v2 and v3 `EncryptedTable` carry this brand, so this + * recovers the literal column keys structurally. + * + * This deliberately uses the `_columnType` brand rather than `build().columns`: + * `BuildableTable.build()` is typed to return `Record<string, ColumnSchema>`, + * which erases the literal keys and would mark EVERY model field as encrypted. + * + * The fallbacks resolve to `Record<never, never>` (a no-key type), NOT `never`: + * a value typed as the bare structural `BuildableTable` carries no `_columnType` + * brand, and `keyof never` is `string | number | symbol` — which would wrongly + * mark EVERY model field as encrypted. `keyof Record<never, never>` is `never`, + * so `EncryptedFromBuildableTable` degrades gracefully to the model unchanged. + */ +export type BuildableTableColumns<T extends BuildableTable> = T extends { + readonly _columnType: infer C +} + ? C extends Record<string, unknown> + ? C + : Record<never, never> + : Record<never, never> + +/** + * Maps a plaintext model type to its encrypted form using a buildable table. + * + * Fields whose keys match a column defined in `Table` (via its `_columnType` + * brand) become `Encrypted` (`Encrypted | null` when the source field is + * nullable); all other fields retain their original types from `T`. Works for + * both v2 and v3 tables. See {@link EncryptedFromSchema} for the v2-specific + * variant retained for backward compatibility. + */ +export type EncryptedFromBuildableTable<T, Table extends BuildableTable> = { + [K in keyof T]: [K] extends [keyof BuildableTableColumns<Table>] + ? null extends T[K] + ? Encrypted | null + : Encrypted + : T[K] +} + // --------------------------------------------------------------------------- // Encrypt / decrypt operation options and results // --------------------------------------------------------------------------- @@ -147,8 +251,8 @@ export type EncryptionClientConfig = { */ export type EncryptOptions = { /** The column or nested field to encrypt into. From {@link EncryptedColumn} or {@link EncryptedField}. */ - column: EncryptedColumn | EncryptedField - table: EncryptedTable<EncryptedTableColumn> + column: BuildableColumn // storage: fields are encryptable, so stays wide + table: BuildableTable } /** Format for encrypted query/search term return values */ @@ -158,9 +262,9 @@ export type EncryptedReturnType = | 'escaped-composite-literal' export type SearchTerm = { - value: JsPlaintext - column: EncryptedColumn - table: EncryptedTable<EncryptedTableColumn> + value: Plaintext + column: BuildableQueryColumn // query: excludes non-queryable EncryptedField + table: BuildableTable returnType?: EncryptedReturnType } @@ -241,7 +345,7 @@ export type EncryptedFromSchema<T, S extends EncryptedTableColumn> = { // position-stable output. export type BulkEncryptPayload = Array<{ id?: string - plaintext: JsPlaintext | null + plaintext: Plaintext | null }> export type BulkEncryptedData = Array<{ id?: string; data: Encrypted | null }> @@ -310,8 +414,8 @@ export const queryTypeToQueryOp: Partial<Record<QueryTypeName, QueryOpName>> = { /** @internal */ export type QueryTermBase = { - column: EncryptedColumn - table: EncryptedTable<EncryptedTableColumn> + column: BuildableQueryColumn // query: excludes non-queryable EncryptedField + table: BuildableTable queryType?: QueryTypeName returnType?: EncryptedReturnType } @@ -319,5 +423,5 @@ export type QueryTermBase = { export type EncryptQueryOptions = QueryTermBase export type ScalarQueryTerm = QueryTermBase & { - value: JsPlaintext + value: Plaintext } diff --git a/packages/stack/src/wasm-inline.ts b/packages/stack/src/wasm-inline.ts index ce47233e..9fc36a4b 100644 --- a/packages/stack/src/wasm-inline.ts +++ b/packages/stack/src/wasm-inline.ts @@ -71,8 +71,6 @@ import { buildEncryptConfig, type CastAs, type EncryptConfig, - EncryptedColumn, - EncryptedField, type EncryptedTable, type EncryptedTableColumn, encryptConfigSchema, @@ -355,12 +353,26 @@ export function normalizeCastAs(config: EncryptConfig): unknown { return { ...config, tables } } -function getColumnName(col: EncryptOptions['column']): string { - if (col instanceof EncryptedColumn || col instanceof EncryptedField) { +/** + * Resolve a column's name structurally. Accepts any column builder exposing + * `getName()` — v2 `EncryptedColumn` / `EncryptedField` AND v3 column builders + * (e.g. `EncryptedTextSearchColumn`) alike — matching the structural + * `BuildableColumn` contract that `EncryptOptions.column` was widened to. + * + * An `instanceof EncryptedColumn || EncryptedField` gate would type-check after + * the widening but throw at runtime for a v3 column, breaking the type promise; + * resolving the name structurally keeps the wasm-inline encrypt entry honest. + * The `typeof` check still fails loudly for plain JS callers passing a value + * that is not a column builder. + * + * @internal exported for unit-test coverage. + */ +export function getColumnName(col: EncryptOptions['column']): string { + if (typeof col?.getName === 'function') { return col.getName() } throw new Error( - '[encryption]: opts.column must be an EncryptedColumn or EncryptedField', + '[encryption]: opts.column must be a column builder exposing getName()', ) } @@ -387,12 +399,16 @@ export function resolveStrategy(cfg: WasmClientConfig): WasmAuthStrategy { if (cfg.strategy) return cfg.strategy // No strategy → the access-key arm, where `workspaceCrn` and `accessKey` // are both required (and so present at runtime); the union widens their - // static types to `string | undefined`, hence the casts. + // static types to `string | undefined`, hence the casts. Guard at runtime + // so plain JS / Deno callers that bypass the compile-time union fail loudly + // instead of forwarding `undefined` into `AccessKeyStrategy.create`. + if (!cfg.workspaceCrn || !cfg.accessKey) { + throw new Error( + '[encryption]: `config.workspaceCrn` and `config.accessKey` are required when `config.strategy` is not provided.', + ) + } // `AccessKeyStrategy.create` takes the full workspace CRN — the region is // derived from it inside `@cipherstash/auth`, so the CRN stays the single // source of truth with no manual region split. - return AccessKeyStrategy.create( - cfg.workspaceCrn as string, - cfg.accessKey as string, - ) + return AccessKeyStrategy.create(cfg.workspaceCrn, cfg.accessKey) } diff --git a/packages/stack/tsconfig.typecheck.json b/packages/stack/tsconfig.typecheck.json new file mode 100644 index 00000000..9d06679f --- /dev/null +++ b/packages/stack/tsconfig.typecheck.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["__tests__/**/*.test-d.ts"] +} diff --git a/packages/stack/tsup.config.ts b/packages/stack/tsup.config.ts index 98cd6b51..0a342ae0 100644 --- a/packages/stack/tsup.config.ts +++ b/packages/stack/tsup.config.ts @@ -15,10 +15,13 @@ export default defineConfig([ 'src/identity/index.ts', 'src/secrets/index.ts', 'src/schema/index.ts', + 'src/eql/v3/index.ts', + 'src/eql/v3/drizzle/index.ts', 'src/drizzle/index.ts', 'src/dynamodb/index.ts', 'src/supabase/index.ts', 'src/encryption/index.ts', + 'src/encryption/v3.ts', 'src/errors/index.ts', ], format: ['cjs', 'esm'], diff --git a/packages/stack/vitest.config.ts b/packages/stack/vitest.config.ts index 64a1542f..c4b1da04 100644 --- a/packages/stack/vitest.config.ts +++ b/packages/stack/vitest.config.ts @@ -5,6 +5,28 @@ export default defineConfig({ resolve: { alias: { '@/': resolve(__dirname, './src') + '/', + // The installed `@cipherstash/{protect-ffi,auth}` only export `.`; their + // `/wasm-inline` subpaths (imported by `src/wasm-inline.ts`) are not + // resolvable by Vitest. Alias them to local stubs so unit tests that only + // exercise pure helpers can load the module. Tests needing real WASM + // behaviour mock these specifiers explicitly. + '@cipherstash/protect-ffi/wasm-inline': resolve( + __dirname, + './__tests__/helpers/stub-protect-ffi-wasm-inline.ts', + ), + '@cipherstash/auth/wasm-inline': resolve( + __dirname, + './__tests__/helpers/stub-auth-wasm-inline.ts', + ), + }, + }, + test: { + typecheck: { + // Scoped tsconfig keeps the 124 pre-existing wasm-inline typecheck errors + // out of scope (tracked as a follow-up). Run via the `test:types` script + // with `--typecheck.only` so the runtime suites do NOT also execute. + tsconfig: './tsconfig.typecheck.json', + include: ['__tests__/**/*.test-d.ts'], }, }, }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3297d549..0d237f5d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -558,8 +558,8 @@ importers: specifier: catalog:repo version: 0.40.0(@cipherstash/auth-darwin-arm64@0.40.0)(@cipherstash/auth-darwin-x64@0.40.0)(@cipherstash/auth-linux-arm64-gnu@0.40.0)(@cipherstash/auth-linux-x64-gnu@0.40.0)(@cipherstash/auth-linux-x64-musl@0.40.0)(@cipherstash/auth-win32-x64-msvc@0.40.0) '@cipherstash/protect-ffi': - specifier: 0.26.0 - version: 0.26.0 + specifier: 0.28.0 + version: 0.28.0 evlog: specifier: 1.11.0 version: 1.11.0(next@15.5.10(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3) @@ -588,6 +588,9 @@ importers: execa: specifier: ^9.5.2 version: 9.6.1 + fta-cli: + specifier: 3.0.0 + version: 3.0.0 json-schema-to-typescript: specifier: ^15.0.2 version: 15.0.4 @@ -941,8 +944,8 @@ packages: cpu: [arm64] os: [darwin] - '@cipherstash/protect-ffi-darwin-arm64@0.26.0': - resolution: {integrity: sha512-v2ZFgDlqHVdWEtnqxGYHGQ7gbkLVWzbB9CSEo0V3TGFhKjfh3tRsQFfZle+Fns9/1hHN0c/Q8jEvqmeRBt+TAA==} + '@cipherstash/protect-ffi-darwin-arm64@0.28.0': + resolution: {integrity: sha512-QRwiovEdgjstbaCONZGYXA82NG4Gwz9mJOZeAzthUmNIQfnVErO9UQAfJ+I1T/YG1Ww2FCWcHltXMl/qjyeK4A==} cpu: [arm64] os: [darwin] @@ -951,8 +954,8 @@ packages: cpu: [x64] os: [darwin] - '@cipherstash/protect-ffi-darwin-x64@0.26.0': - resolution: {integrity: sha512-z9pvB0v8k3S1RRzqkwMUCCNQjjJr2iY8KV3ItZOb7ykvNLd55x3gFlZKFe+zLhBesCIZASSHBFp9yIcO0GGyBA==} + '@cipherstash/protect-ffi-darwin-x64@0.28.0': + resolution: {integrity: sha512-H8qB2z3drJSc2bR5ITsJSFrOoNKvORbauTdHmaS1e5OleXsLl/F+56Zvghz8NWs+bXs/2aVzHxpYte8FgV8AAQ==} cpu: [x64] os: [darwin] @@ -961,8 +964,8 @@ packages: cpu: [arm64] os: [linux] - '@cipherstash/protect-ffi-linux-arm64-gnu@0.26.0': - resolution: {integrity: sha512-IA8r5IwzCpoFUE2cB5VCCCioA8RfOIMql87SUB2DLAFShOeIACvaSwNBktwTCzLgMe5283BXqqyPNn2HzEGYGA==} + '@cipherstash/protect-ffi-linux-arm64-gnu@0.28.0': + resolution: {integrity: sha512-h7vZxB/wako6j1jspkGl41gptTN1dBTWYqAR6jhVnvKJK0TBlyUKuSJwO1NeqyNfFQ/b1KmqJ11JGvY95uRZOA==} cpu: [arm64] os: [linux] @@ -971,8 +974,8 @@ packages: cpu: [x64] os: [linux] - '@cipherstash/protect-ffi-linux-x64-gnu@0.26.0': - resolution: {integrity: sha512-QZVoThJ5kjrf5icg3OJ9ctcnN0CqF6fatVTcuUOLg4nz8xb+m5dIv4WhgvCT7HnipGmALGwKWdpNlnaMrUu0cg==} + '@cipherstash/protect-ffi-linux-x64-gnu@0.28.0': + resolution: {integrity: sha512-PgHn0Og0PiCwFdV4yKhipGKfqkCXP6Xchyy6ykTaISabmSlkkbRNkyNF1/tZEQYF65sm5gmqSpwSYzKODaAsbg==} cpu: [x64] os: [linux] @@ -981,8 +984,8 @@ packages: cpu: [x64] os: [linux] - '@cipherstash/protect-ffi-linux-x64-musl@0.26.0': - resolution: {integrity: sha512-ji6uo8F8vKNI5lmkfEy7RX22jm79Yjg/csyVXAQcTRdwVNZdVGe01vm3f4BIXrFrGDUmHvVJWUHqChqU6z8QiA==} + '@cipherstash/protect-ffi-linux-x64-musl@0.28.0': + resolution: {integrity: sha512-fMu3k1Y3wYMcGbGpVtrlCMNRLd1//5c9ZHcyWFjKFqimOCbBO5akgCQij4zcvj4kYDHtveu9dOdOKVhaG8k6hQ==} cpu: [x64] os: [linux] @@ -991,16 +994,16 @@ packages: cpu: [x64] os: [win32] - '@cipherstash/protect-ffi-win32-x64-msvc@0.26.0': - resolution: {integrity: sha512-1XsLN+pcGjs1O7YCGBawbaVYnJ6N2r8jIcyL0LxQOgE40P4H+CcAwwxcZT4H243g18FJGIYGIW7MVN42csPOWw==} + '@cipherstash/protect-ffi-win32-x64-msvc@0.28.0': + resolution: {integrity: sha512-tF0y7TcyBtgN/jHodYMnrJ4etLkEI/klzDivW8Q8eIuIdoJ3q5muZKFIhNX0MbDDdh2O4GsRdNhXRubs7BiFpA==} cpu: [x64] os: [win32] '@cipherstash/protect-ffi@0.23.0': resolution: {integrity: sha512-Ca8MKLrrumC561VoPDOhuUZcF8C8YenqO1Ig9hSJSRUB+jFeIJXeyn7glExsvKYWtxOx/pRub9FV8A0RyuPHMg==} - '@cipherstash/protect-ffi@0.26.0': - resolution: {integrity: sha512-UqhzMh/x/qBKhYVRiBi6V5MpHH+WiUaWQ0Wm/Q80aCrMoBNolhLWxPhiXM6zBE3tMTmH7Ge0wYIWOxFMfygMEA==} + '@cipherstash/protect-ffi@0.28.0': + resolution: {integrity: sha512-R2L/8HwMREkVKlR5KCcuELIWz4QNButSBQzY+nRDHl1PUXjRqWG1h265FkKVtTXKNKUup7rB4mswu+M+t9KF3A==} '@clack/core@1.3.0': resolution: {integrity: sha512-xJPHpAmEQUBrXSLx0gF+q5K/IyihXpsHZcha+jB+tyahsKRK3Dxo4D0coZDewHo12NhiuzC3dTtMPbm53GEAAA==} @@ -3013,6 +3016,10 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + fta-cli@3.0.0: + resolution: {integrity: sha512-SBmoqIwbN7PLDmwmrPgjr6Z6/S9jPhNz5TCPmEVFkIaeloc/T2WXLeeXqhG1+C0UQxpOfGrC7CUb4friqbc2kQ==} + hasBin: true + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} @@ -4436,37 +4443,37 @@ snapshots: '@cipherstash/protect-ffi-darwin-arm64@0.23.0': optional: true - '@cipherstash/protect-ffi-darwin-arm64@0.26.0': + '@cipherstash/protect-ffi-darwin-arm64@0.28.0': optional: true '@cipherstash/protect-ffi-darwin-x64@0.23.0': optional: true - '@cipherstash/protect-ffi-darwin-x64@0.26.0': + '@cipherstash/protect-ffi-darwin-x64@0.28.0': optional: true '@cipherstash/protect-ffi-linux-arm64-gnu@0.23.0': optional: true - '@cipherstash/protect-ffi-linux-arm64-gnu@0.26.0': + '@cipherstash/protect-ffi-linux-arm64-gnu@0.28.0': optional: true '@cipherstash/protect-ffi-linux-x64-gnu@0.23.0': optional: true - '@cipherstash/protect-ffi-linux-x64-gnu@0.26.0': + '@cipherstash/protect-ffi-linux-x64-gnu@0.28.0': optional: true '@cipherstash/protect-ffi-linux-x64-musl@0.23.0': optional: true - '@cipherstash/protect-ffi-linux-x64-musl@0.26.0': + '@cipherstash/protect-ffi-linux-x64-musl@0.28.0': optional: true '@cipherstash/protect-ffi-win32-x64-msvc@0.23.0': optional: true - '@cipherstash/protect-ffi-win32-x64-msvc@0.26.0': + '@cipherstash/protect-ffi-win32-x64-msvc@0.28.0': optional: true '@cipherstash/protect-ffi@0.23.0': @@ -4480,16 +4487,16 @@ snapshots: '@cipherstash/protect-ffi-linux-x64-musl': 0.23.0 '@cipherstash/protect-ffi-win32-x64-msvc': 0.23.0 - '@cipherstash/protect-ffi@0.26.0': + '@cipherstash/protect-ffi@0.28.0': dependencies: '@neon-rs/load': 0.1.82 optionalDependencies: - '@cipherstash/protect-ffi-darwin-arm64': 0.26.0 - '@cipherstash/protect-ffi-darwin-x64': 0.26.0 - '@cipherstash/protect-ffi-linux-arm64-gnu': 0.26.0 - '@cipherstash/protect-ffi-linux-x64-gnu': 0.26.0 - '@cipherstash/protect-ffi-linux-x64-musl': 0.26.0 - '@cipherstash/protect-ffi-win32-x64-msvc': 0.26.0 + '@cipherstash/protect-ffi-darwin-arm64': 0.28.0 + '@cipherstash/protect-ffi-darwin-x64': 0.28.0 + '@cipherstash/protect-ffi-linux-arm64-gnu': 0.28.0 + '@cipherstash/protect-ffi-linux-x64-gnu': 0.28.0 + '@cipherstash/protect-ffi-linux-x64-musl': 0.28.0 + '@cipherstash/protect-ffi-win32-x64-msvc': 0.28.0 '@clack/core@1.3.0': dependencies: @@ -6223,6 +6230,8 @@ snapshots: fsevents@2.3.3: optional: true + fta-cli@3.0.0: {} + function-bind@1.1.2: {} gel@2.2.0: