diff --git a/.github/workflows/bench-eql.yml b/.github/workflows/bench-eql.yml index cee01ca3..782ed3c3 100644 --- a/.github/workflows/bench-eql.yml +++ b/.github/workflows/bench-eql.yml @@ -15,6 +15,9 @@ on: - "src/**/*.sql" - "tests/sqlx/**/*" - "tasks/**/*" + - "crates/**" + - "Cargo.toml" + - "Cargo.lock" schedule: # 02:00 UTC daily @@ -50,7 +53,7 @@ jobs: - uses: Swatinem/rust-cache@v2 with: - workspaces: tests/sqlx + workspaces: . shared-key: sqlx-tests - name: Setup database diff --git a/.github/workflows/macro-expand-eql.yml b/.github/workflows/macro-expand-eql.yml new file mode 100644 index 00000000..f6411657 --- /dev/null +++ b/.github/workflows/macro-expand-eql.yml @@ -0,0 +1,82 @@ +name: "Macro expand EQL" + +# Regenerates the int4 matrix `cargo expand` snapshot and fails if it has +# drifted from the committed copy. This is a body-level fidelity backstop for +# the `ordered_numeric_matrix!` / `scalar_domain_matrix!` macros — the +# name-inventory snapshot (test-eql.yml `matrix-coverage` job) catches +# add/remove of whole arms; this catches changes *inside* the generated bodies. +# +# Non-blocking by design: it is NOT a required PR check. `cargo expand` needs a +# nightly toolchain, so it is isolated off the PR path. +# - nightly schedule (the backstop that flags a forgotten local regen) +# - manual workflow_dispatch +# +# GAP (intended): there is no `pull_request` trigger, so a change that only +# touches macro *bodies* (no arm add/remove) can merge without ever running +# here and will first surface as a red nightly run afterwards. Accept this — the +# expand lane needs nightly and stays off the PR critical path by design. +# +# The pinned nightly date lives in ONE place: the `cargo +nightly-...` invocation +# in the `test:matrix:expand` mise task. The install step below DERIVES the date +# from mise.toml (grep), so there is nothing to keep in lockstep — bump it once in +# mise.toml. The snapshot then only moves when the macro moves, not when nightly +# reformats its expansion. +on: + schedule: + # 03:00 UTC daily + - cron: "0 3 * * *" + + workflow_dispatch: + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" + MISE_VERBOSE: "1" + +defaults: + run: + shell: bash -l {0} + +permissions: + contents: read + +jobs: + macro-expand: + name: "Macro expand drift (nightly)" + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4 + with: + version: 2026.4.0 + install: true + cache: true + + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + workspaces: tests/sqlx + shared-key: sqlx-tests + + # Derive the pinned nightly date from mise.toml (single source of truth — + # the `cargo +nightly-...` invocation in the `test:matrix:expand` task) so + # there is nothing to bump in lockstep here. cargo-expand is likewise pinned + # once in mise.toml's [tools] (`cargo:cargo-expand`) and installed by the + # mise-action step above, so its version is single-sourced too — no + # hardcoded version lives in this workflow. It drives the rustfmt pass, so + # an unpinned version could drift the snapshot even with a frozen macro + + # nightly. The snapshot then only moves when the macro moves. + - name: Install pinned nightly toolchain + run: | + NIGHTLY=$(grep -oE 'nightly-[0-9]{4}-[0-9]{2}-[0-9]{2}' mise.toml | head -1) + test -n "$NIGHTLY" || { echo "could not find pinned nightly in mise.toml"; exit 1; } + rustup toolchain install "$NIGHTLY" --profile minimal --component rustfmt + + - name: Regenerate and verify the matrix expansion snapshot + run: | + mise run test:matrix:expand + git diff --exit-code -- tests/sqlx/snapshots/int4_expanded.rs \ + || { echo "Expansion snapshot stale — run 'mise run test:matrix:expand' (needs the pinned nightly) and commit."; exit 1; } diff --git a/.github/workflows/test-eql.yml b/.github/workflows/test-eql.yml index 73e5ab37..776d701a 100644 --- a/.github/workflows/test-eql.yml +++ b/.github/workflows/test-eql.yml @@ -9,6 +9,9 @@ on: - "sql/**/*.sql" - "tests/**/*" - "tasks/**/*" + - "crates/**" + - "Cargo.toml" + - "Cargo.lock" pull_request: # run on all pull requests @@ -18,6 +21,9 @@ on: - "sql/**/*.sql" - "tests/**/*" - "tasks/**/*" + - "crates/**" + - "Cargo.toml" + - "Cargo.lock" workflow_dispatch: @@ -29,33 +35,167 @@ defaults: run: shell: bash -l {0} +permissions: + contents: read + jobs: schema: name: "JSON Schema validation" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false - - uses: jdx/mise-action@v4 + - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4 with: version: 2026.4.0 install: true cache: true - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: - workspaces: tests/sqlx + workspaces: . shared-key: sqlx-tests - name: Validate v2.2 / v2.3 payload schemas run: | mise run test:schema + rust-crates: + name: "Rust workspace crates" + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4 + with: + version: 2026.4.0 + install: true + cache: true + + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + workspaces: . + shared-key: sqlx-tests + + # fmt + clippy + test for the std-only catalog/generator crates. No + # Postgres: these never touch a database, so they run standalone and fast. + - name: Compile, lint and test the Rust workspace crates + run: | + export active_rust_toolchain=$(rustup show active-toolchain | cut -d' ' -f1) + rustup component add --toolchain ${active_rust_toolchain} rustfmt clippy + mise run test:crates + + codegen: + name: "Encrypted-domain codegen" + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4 + with: + version: 2026.4.0 + install: true + cache: true + + # Shared with the sibling Rust jobs so the eql-codegen build artifacts the + # parity gate needs are reused rather than rebuilt from scratch. + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + workspaces: . + shared-key: sqlx-tests + + # Crate compile/lint/test (cargo test -p eql-scalars -p eql-codegen) runs + # in the dedicated `test:crates` job; this job covers the codegen-specific + # gate only — golden parity. The plaintext fixture lists are no longer a + # generated file: they live in the catalog (`eql_scalars::INT4_VALUES` / + # `INT2_VALUES`) and are pinned by `eql-scalars`'s own unit tests, so there + # is nothing to regenerate-and-diff here. + + # Parity gate: assert the Rust eql-codegen output is line-normalized-equal + # to the int4 golden reference. Python is no longer an oracle (retired in + # P2). No Postgres needed — the generator runs offline. + - name: Verify generator parity (golden) + run: | + mise run codegen:parity + + self-contained-v3: + name: "eql_v3 self-containment" + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4 + with: + version: 2026.4.0 + install: true + cache: true + + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + workspaces: . + shared-key: sqlx-tests + + # Build to materialise release/cipherstash-encrypt-v3.sql and + # src/deps-ordered-v3.txt, then assert no eql_v2 symbol/file leakage. + - name: Build EQL + run: mise run --force build + + - name: Assert eql_v3 is self-contained + run: mise run test:self_contained_v3 + + matrix-coverage: + name: "Matrix coverage inventory" + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4 + with: + version: 2026.4.0 + install: true + cache: true + + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + workspaces: . + shared-key: sqlx-tests + + # Verify the matrix test-name set against the SINGLE canonical snapshot + # (snapshots/matrix_tests.txt) with the SAME pinned feature set the local + # task uses (`--no-default-features`, scale excluded), and cross-check the + # binary's discovered type set against `eql-codegen list-types`. A coverage + # change shows up as a diff in the snapshot; a catalog type missing its + # matrix wiring fails the cross-check. No Postgres needed: `--list` only + # enumerates, the suite uses runtime queries. + - name: Verify the matrix test-name inventory + run: | + mise run test:matrix:inventory + # Diff the whole snapshots/ directory so the single canonical file + # isn't hardcoded here; the mise task discovers the type set from the + # binary and reconciles it against `eql-codegen list-types`. + git add -N tests/sqlx/snapshots + git diff --exit-code -- tests/sqlx/snapshots \ + || { echo "Coverage inventory stale — run 'mise run test:matrix:inventory' and commit."; exit 1; } + test: name: "Test & Validate EQL (Postgres ${{ matrix.postgres-version }})" runs-on: ubuntu-latest-m - needs: schema + needs: [schema, codegen] strategy: fail-fast: false @@ -64,19 +204,30 @@ jobs: env: POSTGRES_VERSION: ${{ matrix.postgres-version }} + # CS_* are required for `mise run test:sqlx` to regenerate the + # cipherstash-client-encrypted fixtures before the suite runs. + # This repository does not accept fork PRs, so the secrets-on- + # `pull_request` constraint that breaks the fork CI flow does not + # apply here — leave the env block unconditional. + CS_CLIENT_ACCESS_KEY: ${{ secrets.CS_CLIENT_ACCESS_KEY }} + CS_WORKSPACE_CRN: ${{ secrets.CS_WORKSPACE_CRN }} + CS_CLIENT_ID: ${{ secrets.CS_CLIENT_ID }} + CS_CLIENT_KEY: ${{ secrets.CS_CLIENT_KEY }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false - - uses: jdx/mise-action@v4 + - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4 with: version: 2026.4.0 install: true # [default: true] run `mise install` cache: true # [default: true] cache mise using GitHub's cache - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: - workspaces: tests/sqlx + workspaces: . shared-key: sqlx-tests - name: Setup database (Postgres ${{ matrix.postgres-version }}) @@ -93,6 +244,11 @@ jobs: rustup component add --toolchain ${active_rust_toolchain} rustfmt clippy mise run --output prefix test --postgres ${POSTGRES_VERSION} + - name: Clean-DB v3 install smoke (Postgres ${{ matrix.postgres-version }}) + run: | + mise run build + mise run test:clean_install_v3 + splinter: name: "Supabase splinter" runs-on: ubuntu-latest-m @@ -101,9 +257,11 @@ jobs: POSTGRES_VERSION: "17" steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false - - uses: jdx/mise-action@v4 + - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4 with: version: 2026.4.0 install: true @@ -126,4 +284,3 @@ jobs: mise run --output prefix test:splinter --postgres ${POSTGRES_VERSION} - diff --git a/.gitignore b/.gitignore index d9a13a2e..83ee4c42 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,9 @@ deps-ordered.txt deps-supabase.txt deps-ordered-supabase.txt +src/deps-v3.txt +src/deps-ordered-v3.txt + # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore src/version.sql @@ -123,6 +126,10 @@ web_modules/ .env.local .envrc +# Local mise overrides (CipherStash credentials, etc.) +mise.local.toml +.mise.local.toml + # parcel-bundler cache (https://parceljs.org/) .parcel-cache @@ -215,6 +222,18 @@ eql--*.sql # Generated SQLx migration (built from src/, never commit) tests/sqlx/migrations/001_install_eql.sql +# Generated SQLx fixtures (regenerated via `mise run fixture:generate`, +# never commit — stale fixtures hide bugs) +tests/sqlx/fixtures/eql_v2* + +# Generated encrypted-domain SQL — regenerated by `tasks/build.sh` from the +# eql-scalars::CATALOG via `cargo run -p eql-codegen` on every build. The +# hand-written src/v3/scalars/functions.sql (no type subdir) stays committed. +src/v3/scalars/*/*_types.sql +src/v3/scalars/*/*_functions.sql +src/v3/scalars/*/*_operators.sql +src/v3/scalars/*/*_aggregates.sql + # Large generated test data files tests/ste_vec_vast.sql tests/ste_vec_*M.sql* @@ -225,7 +244,11 @@ tests/sqlx/target/ # Work files (agent-generated, not for version control) .work/ .serena/ +docs/superpowers/ # Build variants - protect variant deps src/deps-protect.txt src/deps-ordered-protect.txt + +# Cargo workspace root build artifacts +/target/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e8c9568..0c128bdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,19 @@ Each entry that ships in a published release links to the PR that introduced it. ## [Unreleased] +### Added + +- **`eql_v3` encrypted-domain schema, with the `int4` family as its first member.** Encrypted-domain type families now live in a new, additional `eql_v3` schema (the existing `eql_v2` schema is unchanged — it keeps the core types/operators and stays the documented public API). Four jsonb-backed domains for encrypted `int4` columns: `eql_v3.int4` (storage-only), `eql_v3.int4_eq` (`=` / `<>` via HMAC), and `eql_v3.int4_ord` / `eql_v3.int4_ord_ore` (also `<` `<=` `>` `>=` via ORE block terms). Supported comparisons resolve to inlinable wrappers; the native `jsonb` operator surface reachable through domain fallback is blocked (raises rather than silently mis-resolving). Each domain's `CHECK` requires the EQL envelope (`v`, `i`), the ciphertext (`c`), and the variant's index term(s), and pins the payload version (`VALUE->>'v' = '2'`, matching `eql_v2._encrypted_check_v`) — so a missing key or wrong-version payload is rejected on insert or cast rather than surfacing later at query time. Index via a functional index on the `eql_v3.eq_term` / `eql_v3.ord_term` extractors, not an operator class on the domain. The extractors return the searchable-encrypted-metadata index-term types `eql_v3.hmac_256` / `eql_v3.ore_block_u64_8_256`, which `eql_v3` owns directly (see the self-contained `eql_v3` schema entry below). Why: a type-safe, per-capability encrypted integer column instead of the untyped `eql_v2_encrypted`, namespaced under its own schema. This is the reference scalar implementation for the generated domain family. ([#239](https://github.com/cipherstash/encrypt-query-language/pull/239), supersedes [#225](https://github.com/cipherstash/encrypt-query-language/pull/225)) +- **`eql_v3.int2` encrypted-domain type family.** Four jsonb-backed domains for encrypted `int2` columns — `eql_v3.int2` (storage-only), `eql_v3.int2_eq` (`=` / `<>` via HMAC), and `eql_v3.int2_ord` / `eql_v3.int2_ord_ore` (also `<` `<=` `>` `>=` via ORE block terms, with `MIN` / `MAX` aggregates) — generated from the `int2` row in `eql-scalars::CATALOG` by the same materializer as the `eql_v3.int4` reference. Index via a functional index on the `eql_v3.eq_term` / `eql_v3.ord_term` extractors, not an operator class on the domain. Why: a type-safe, per-capability encrypted `smallint` column, proving the scalar generator generalizes beyond the `int4` reference. ([#243](https://github.com/cipherstash/encrypt-query-language/pull/243)) +- **`eql_v3.int8` encrypted-domain type family.** Four jsonb-backed domains for encrypted `int8` columns — `eql_v3.int8` (storage-only), `eql_v3.int8_eq` (`=` / `<>` via HMAC), and `eql_v3.int8_ord` / `eql_v3.int8_ord_ore` (also `<` `<=` `>` `>=` via ORE block terms, with `MIN` / `MAX` aggregates) — generated from the `int8` row in `eql-scalars::CATALOG` by the same materializer as the `eql_v3.int4` reference. Index via a functional index on the `eql_v3.eq_term` / `eql_v3.ord_term` extractors, not an operator class on the domain. Why: a type-safe, per-capability encrypted `bigint` column, extending the scalar generator across the full 64-bit integer width. ([#253](https://github.com/cipherstash/encrypt-query-language/pull/253)) +- **`eql_v3.date` encrypted-domain type family.** Four jsonb-backed domains for encrypted `date` columns — `eql_v3.date` (storage-only), `eql_v3.date_eq` (`=` / `<>` via HMAC), and `eql_v3.date_ord` / `eql_v3.date_ord_ore` (also `<` `<=` `>` `>=` via ORE block terms, with `MIN` / `MAX` aggregates) — generated from the `date` row in `eql-scalars::CATALOG` by the same materializer as the `eql_v3.int4` reference. Plaintexts encrypt under the `date` cast and compare via the same ORE block terms as the integer scalars (ORE is plaintext-agnostic — dates order like integers). Index via a functional index on the `eql_v3.eq_term` / `eql_v3.ord_term` extractors, not an operator class on the domain. Why: the first **non-integer ordered** scalar encrypted-domain type — a type-safe, per-capability encrypted `date` column — proving the generator and SQLx test matrix generalize beyond fixed-width integers. ([#256](https://github.com/cipherstash/encrypt-query-language/pull/256)) +- **Per-domain `MIN` / `MAX` aggregates for the encrypted-domain family.** `eql_v3.min(eql_v3._ord)` / `eql_v3.max(eql_v3._ord)` (and the `_ord_ore` twin) are generated for every ord-capable scalar variant, giving type-safe extrema on domain-typed columns — comparison routes through the variant's `<` / `>` operator (ORE block term, no decryption). The aggregates are declared `PARALLEL = SAFE` with a combine function (the state function itself — min/max are associative), so PostgreSQL can use partial/parallel aggregation on large `GROUP BY` workloads. Why: the new domain types previously had no equivalent of the composite-type aggregates. The existing `eql_v2.min(eql_v2_encrypted)` / `eql_v2.max(eql_v2_encrypted)` aggregates are **retained** and continue to work on `eql_v2_encrypted` columns; the per-domain aggregates are additive and coexist with them. ([#239](https://github.com/cipherstash/encrypt-query-language/pull/239)) +- **Self-contained `eql_v3` schema + standalone `release/cipherstash-encrypt-v3.sql` installer.** The `eql_v3` encrypted-domain surface no longer depends on `eql_v2` at runtime: it now owns its own copies of the searchable-encrypted-metadata (SEM) index-term types — `eql_v3.hmac_256` and `eql_v3.ore_block_u64_8_256` (with its btree operator class) — so the `eql_v3.eq_term` / `eql_v3.ord_term` extractors return `eql_v3` types and no `eql_v2.` appears anywhere in the v3 SQL. The whole v3 surface relocated under a single `src/v3/` tree (`src/v3/sem/` for the hand-written SEM types, `src/v3/scalars/` for the generated domain families). A new build variant ships the `eql_v3` schema on its own as `release/cipherstash-encrypt-v3.sql`, installable into a database with no `eql_v2` present; a CI gate greps that artifact and its dependency closure to keep it `eql_v2`-free. Why: a clean foundation for the per-scalar encrypted-domain model to stand alone, ahead of it replacing the `eql_v2_encrypted` composite column type. This is additive — a new schema and a new artifact — and leaves `eql_v2` byte-for-byte unchanged. ([#255](https://github.com/cipherstash/encrypt-query-language/pull/255)) + +### Changed + +- **Scalar encrypted-domain types are now defined in a Rust catalog, not TOML manifests; the Python codegen toolchain is removed.** Adding a scalar encrypted-domain type (`int4`, `int8`, …) is now one row in `eql-scalars::CATALOG` (`crates/eql-scalars/src/lib.rs`) instead of authoring `tasks/codegen/types/.toml`. `mise run build` regenerates the gitignored SQL surface via `cargo run -p eql-codegen` (Rust, std-only) rather than the Python generator. The catalog row's `Fixture` list is the single source of truth for that type's plaintext fixtures: the SQLx test matrix reads it directly as a compile-time-materialised const (`eql_scalars::INT4_VALUES` / `INT2_VALUES`, `ScalarType::FIXTURE_VALUES`), so there is no longer a generated, committed `tests/sqlx/src/fixtures/_values.rs` — a Rust source of truth no longer round-trips through generated Rust. The shipped SQL is unchanged — `release/*.sql` is byte-identical across the cutover — so there is no change for callers installing EQL; this only affects contributors who extend the scalar domain families. The `python` mise tool, the `pytest`-based `test:codegen` (now `cargo test -p eql-scalars -p eql-codegen`), the per-type `mise run codegen:domain` tasks, and the per-type `tests/sqlx/snapshots/_matrix_tests.txt` baselines (collapsed into one catalog-reconciled `tests/sqlx/snapshots/matrix_tests.txt`) are gone. Why: a single compiler-validated source of truth shared by the generator and the SQLx test harness, and one fewer toolchain in the build/test path — building and testing EQL no longer needs Python (Python remains only for the separate docs-markdown tooling). ([#252](https://github.com/cipherstash/encrypt-query-language/pull/252)) + ## [2.3.1] — 2026-05-21 ### Fixed diff --git a/CLAUDE.md b/CLAUDE.md index 65ed6d58..9c9a08ca 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -29,6 +29,7 @@ This project uses `mise` for task management. Common commands: - Run SQLx tests directly: `mise run test:sqlx` - Run SQLx tests in watch mode: `mise run test:sqlx:watch` - Tests are located in `tests/sqlx/` using Rust and SQLx framework +- Verify the scalar matrix coverage snapshot: `mise run test:matrix:inventory` (no database required). ONE committed `tests/sqlx/snapshots/matrix_tests.txt` baseline pins the token-normalized set of `scalars::::*` test names so a silently dropped/renamed/`#[cfg]`-gated test fails CI's `matrix-coverage` job. The task discovers the present scalar types from the test binary's `--list` and cross-checks them against `cargo run -p eql-codegen -- list-types`, so a catalog type missing its matrix wiring also fails. When you change which matrix tests the macro emits, regenerate and commit the single snapshot in the same change. See `tests/sqlx/snapshots/README.md`. ### Build System - Dependencies are resolved using `-- REQUIRE:` comments in SQL files @@ -36,6 +37,7 @@ This project uses `mise` for task management. Common commands: - `cipherstash-encrypt.sql` - Main installer - `cipherstash-encrypt-supabase.sql` - Supabase-compatible (excludes operator classes) - `cipherstash-encrypt-protect.sql` - ProtectJS variant (excludes config management) + - `cipherstash-encrypt-v3.sql` - Standalone, self-contained `eql_v3` surface only (globbed from `src/v3` alone; no `eql_v2`, installable into a DB with no `eql_v2` present) - Corresponding uninstallers for each variant #### Build Variants @@ -44,13 +46,14 @@ This project uses `mise` for task management. Common commands: | Main | Nothing | Full EQL with all features | | Supabase | Operator classes | Supabase compatibility | | Protect | `src/config/*`, `src/encryptindex/*` | ProtectJS (no database-side config) | +| v3-only | Everything outside `src/v3` (and `pin_search_path.sql`) | Self-contained `eql_v3` surface, `eql_v2`-free (gated by `mise run test:self_contained_v3`) | ## Project Architecture This is the **Encrypt Query Language (EQL)** - a PostgreSQL extension for searchable encryption. Key architectural components: ### Core Structure -- **Schema**: All EQL functions/types are in `eql_v2` PostgreSQL schema +- **Schema**: Core EQL functions/types are in the `eql_v2` PostgreSQL schema. The encrypted-domain type families (`int4` and future scalar domains) live in a separate `eql_v3` schema (see below). The `eql_v3` surface is **self-contained**: it owns its own copies of the searchable-encrypted-metadata (SEM) index-term types (`eql_v3.hmac_256`, `eql_v3.ore_block_u64_8_256`, hand-written under `src/v3/sem/`) and has no runtime dependency on `eql_v2`. `eql_v2` is unchanged and remains the documented public API. - **Main Type**: `eql_v2_encrypted` - composite type for encrypted columns (stored as JSONB) - **Configuration**: `eql_v2_configuration` table tracks encryption configs - **Index Types**: Various encrypted index types (blake3, hmac_256, bloom_filter, ore variants) @@ -61,6 +64,7 @@ This is the **Encrypt Query Language (EQL)** - a PostgreSQL extension for search - `src/operators/` - SQL operators for encrypted data comparisons - `src/config/` - Configuration management functions - `src/blake3/`, `src/hmac_256/`, `src/bloom_filter/`, `src/ore_*` - Index implementations +- `src/v3/` - Self-contained `eql_v3` surface: `src/v3/schema.sql`, forked `src/v3/crypto.sql` / `src/v3/common.sql`, hand-written SEM index-term types under `src/v3/sem/` (`hmac_256`, `ore_block_u64_8_256`), and the generated scalar encrypted-domain families under `src/v3/scalars//` (plus the shared blocker `src/v3/scalars/functions.sql`) - `tasks/` - mise task scripts - `tests/sqlx/` - Rust/SQLx test framework (PostgreSQL 14-17 support) - `release/` - Generated SQL installation files @@ -72,6 +76,25 @@ This is the **Encrypt Query Language (EQL)** - a PostgreSQL extension for search - **Operators**: Support comparisons between encrypted and plain JSONB data - **CipherStash Proxy**: Required for encryption/decryption operations +### Encrypted-Domain Types + +`src/v3/scalars/` holds the generated **encrypted-domain type families** — jsonb-backed PostgreSQL domains in the **`eql_v3` schema**, one domain per operator/index capability (`eql_v3.` storage-only, `eql_v3._eq`, `eql_v3._ord`). The schema qualifier replaces the old version-prefixed name, so the domains are `eql_v3.int4`, `eql_v3.int4_eq`, `eql_v3.int4_ord`, `eql_v3.int4_ord_ore` — created in `eql_v3`, not `public`. Their extractors/wrappers/aggregates (`eql_v3.eq_term`, `eql_v3.ord_term`, `eql_v3.eq`/`lt`/…, `eql_v3.min`/`max`) also live in `eql_v3`, and the SEM index-term types they return and construct (`eql_v3.hmac_256`, `eql_v3.ore_block_u64_8_256`) are **also `eql_v3`** — hand-written under `src/v3/sem/` so the whole v3 surface is self-contained (no `eql_v2.` appears anywhere in v3 SQL; CI gates this via `mise run test:self_contained_v3` and the standalone `release/cipherstash-encrypt-v3.sql` installer). `eql_v3.int4` (PR #239, supersedes #225) is the reference scalar implementation; future scalar types such as `int8`, `bool`, `date`, `float`, `numeric`, `timestamp`, `text`, and `jsonb` follow this materializer pattern. `text`, `numeric`, and `jsonb` are planned but have no generated SQL surface yet — `jsonb` in particular needs a separate SQL design beyond the ordered-scalar materializer. The `eql-scalars` fixture catalog (`crates/eql-scalars`) already models their fixture values ahead of the SQL surface. + +Adding a scalar encrypted-domain type is one row in the Rust catalog `eql-scalars::CATALOG` (`crates/eql-scalars/src/lib.rs`): a `ScalarSpec` giving the type `token` (e.g. `int8`), its `ScalarKind` (the `kind` field), the `DomainSpec`s mapping each generated domain suffix to its fixed index `Term`s (`_eq => [Hm]`, `_ord`/`_ord_ore => [Ore]`), and the `Fixture` value list. Term capabilities are fixed in the `Term` enum's `impl` methods (with unit tests): `Hm` provides equality, and `Ore` provides equality plus ordering. There is no TOML manifest and no Python — the catalog is the source of truth, validated by the compiler (an undefined term or unknown scalar is a compile error) plus catalog `#[test]`s. `mise run build` runs `cargo run -p eql-codegen`, which regenerates the scalar SQL surface into `src/v3/scalars//` from `CATALOG` at the start of every build; that surface includes supported comparison wrappers plus blockers for native `jsonb` operators that would otherwise be reachable through domain fallback. `cargo run -p eql-codegen` regenerates every type at once (the same call `mise run build` uses; there is no per-type codegen task). The generated `*_types.sql` / `*_functions.sql` / `*_operators.sql` / `*_aggregates.sql` files are gitignored and never committed. The per-type plaintext fixture lists the SQLx matrix consumes are **not** a generated file — they are materialised from each `CATALOG` row at compile time as `eql_scalars::INT4_VALUES` / `INT2_VALUES` (the `int_values!` macro) and read directly by `ScalarType::FIXTURE_VALUES`; a Rust source of truth no longer round-trips through a committed generated `.rs`. Generated SQL carries a `-- AUTOMATICALLY GENERATED FILE` header (the project-wide marker `docs:validate` greps on); change the catalog and rebuild, never hand-edit. Hand-written SQL beyond the fixed surface goes in `src/v3/scalars//_extensions.sql` with no auto-generated header and explicit `-- REQUIRE:` edges — that file IS committed. `text` and `jsonb` are out of scope for this scalar materializer. + +**Adding a new encrypted-domain type: follow `docs/reference/adding-a-scalar-encrypted-domain-type.md`.** The mechanics are fixed for ordered scalar domains; the catalog row only declares the token, kind, domain suffixes, and terms. New term behavior belongs in the `Term` enum's `impl` methods in `crates/eql-scalars/src` with tests, not in free-form catalog data. + +Regeneration is deterministic: an identical `CATALOG` produces byte-identical SQL. If `mise run build` produces unexpected output, the change is in `crates/eql-scalars/src` (the catalog/terms) or `crates/eql-codegen/src` (the renderers) — not in random run-to-run variation. + +Footguns the spec exists to prevent: + +- **Blockers must never be `STRICT`.** A `STRICT` blocker lets PostgreSQL skip the body and return `NULL` on a `NULL` argument, silently bypassing the "operator not supported" exception. +- **No domain-over-domain** (`CREATE DOMAIN a AS b`). Operators resolve against the ultimate base type (`jsonb`), so a derived domain does not inherit the base domain's operator surface — blockers stop engaging. +- **No operator class on a domain.** Index through a functional index on the extractor (`eq_term` / `ord_term`), whose return type already carries a default opclass. +- **Inlinable functions** (extractors, comparison wrappers) need `LANGUAGE sql`, a single-statement `SELECT`, `IMMUTABLE`, and **no `SET` clause** — a pinned `search_path` disables inlining. No per-type allowlist edit: the `pin_search_path.sql` structural rule recognises encrypted-domain functions intrinsically and `tasks/test/splinter.sh` covers the converged extractor/wrapper names. +- **Blockers must be `LANGUAGE plpgsql`, not `LANGUAGE sql`.** The inverse of the rule above. A blocker exists to always raise, but a `LANGUAGE sql` body is inlinable and the planner can elide the call when the result is provably unused (dead `CASE` branch, folded predicate). `LANGUAGE plpgsql` is opaque to the planner, so the call — and its `RAISE` — survives. The blocker renderers in `crates/eql-codegen/src` enforce this; don't "simplify" the rendered blockers to `LANGUAGE sql` even though the body is a single expression. +- **Build with `mise run clean && mise run build`** — a bare build can leave stale `release/*.sql`. + ### Testing Infrastructure - Tests are written in Rust using SQLx, located in `tests/sqlx/` - Tests run against PostgreSQL 14, 15, 16, 17 using Docker containers @@ -199,6 +222,7 @@ Prefer `LANGUAGE SQL` over `LANGUAGE plpgsql` unless you need procedural feature - Exception handling (`BEGIN...EXCEPTION...END`) - Complex control flow (loops, early returns) - Dynamic SQL (`EXECUTE`) +- Functions that must remain opaque to the planner — typically blockers whose only job is to `RAISE`. `LANGUAGE sql` would be inlined and may be elided when the result is provably unused; `LANGUAGE plpgsql` is never inlined, so the body always runs. See the encrypted-domain footgun list above and the blocker renderers in `crates/eql-codegen/src`. ## Release & changelog discipline @@ -222,7 +246,7 @@ What does *not* need an entry: Pick the right section (`Added` / `Changed` / `Deprecated` / `Removed` / `Fixed` / `Security`). Lead with the user-visible fact, then a short "Why." explanation, then a PR link in parentheses. Match the tone and density of existing entries — a single dense paragraph per entry, not a bullet list. -Example shape (real entry from `2.3.0`): +Example entry (real entry from `2.3.0`): > **`=`, `<>`, `~~` (`LIKE`), `~~*` (`ILIKE`) on `eql_v2_encrypted` are now inlinable SQL functions.** The planner can structurally match these operators against the documented functional indexes (`eql_v2.hmac_256(col)` for equality, `eql_v2.bloom_filter(col)` for `LIKE`/`ILIKE`), so bare-form queries (`WHERE col = $1`) engage the index without per-query rewriting. Previously these operators wrapped multi-branch PL/pgSQL bodies that the planner could not inline, forcing seq scans on Supabase / managed Postgres installations that lack operator-class indexes. ([#193](...), [#196](...)) @@ -239,7 +263,7 @@ The entry under `Changed` / `Deprecated` should cross-link to the `U-NNN`. See ` ### Versioning -The `eql_v2` PostgreSQL schema name is part of the public API and is **independent of the EQL release version**. Major-version bumps to EQL do not rename the schema. When deciding on a version bump: +The `eql_v2` PostgreSQL schema name is part of the public API and is **independent of the EQL release version**. Major-version bumps to EQL do not rename the schema. The `eql_v3` schema is **not** a rename of `eql_v2`: it is a separate, additional schema introduced to namespace the encrypted-domain type families. Both schemas coexist; `eql_v2` keeps the core types/operators and is unchanged. Adding a new schema for a new surface is additive, not a public-API break. When deciding on a version bump: - **Patch (`2.3.x`)** — bug fixes, no behaviour changes - **Minor (`2.x.0`)** — additive changes, behaviour changes that don't break the public API (signatures, schema name, payload format, operator names) diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..bfecae6b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,5445 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common 0.1.6", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures 0.2.17", + "zeroize", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", + "zeroize", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "polyval", + "subtle", + "zeroize", +] + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.16", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "serde", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "aquamarine" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f50776554130342de4836ba542aa85a4ddb361690d7e8df13774d7284c3d5c2" +dependencies = [ + "include_dir", + "itertools 0.10.5", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +dependencies = [ + "serde", + "zeroize", +] + +[[package]] +name = "async-compression" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac" +dependencies = [ + "compression-codecs", + "compression-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "async-mutex" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73112ce9e1059d8604242af62c7ec8e5975ac58ac251686c8403b45e8a6fe778" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "aws-lc-rs" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" +dependencies = [ + "aws-lc-sys", + "untrusted 0.7.1", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + +[[package]] +name = "backtrace-ext" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" +dependencies = [ + "backtrace", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base32" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + +[[package]] +name = "base85" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36915bbaca237c626689b5bd14d02f2ba7a5a359d30a2a08be697392e3718079" +dependencies = [ + "thiserror 1.0.69", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +dependencies = [ + "serde_core", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake3" +version = "1.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "cpufeatures 0.3.0", + "zeroize", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "block-modes" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e2211b0817f061502a8dd9f11a37e879e79763e3c698d2418cf824d8cb2f21e" + +[[package]] +name = "borrow-or-share" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc0b364ead1874514c8c2855ab558056ebfeb775653e7ae45ff72f28f8f3166c" + +[[package]] +name = "borsh" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "brotli" +version = "8.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bytecount" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +dependencies = [ + "serde", +] + +[[package]] +name = "cached" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9718806c4a2fe9e8a56fd736f97b340dd10ed1be8ed733ed50449f351dc33cae" +dependencies = [ + "ahash 0.8.12", + "cached_proc_macro", + "cached_proc_macro_types", + "hashbrown 0.14.5", + "once_cell", + "thiserror 1.0.69", + "web-time", +] + +[[package]] +name = "cached_proc_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f42a145ed2d10dce2191e1dcf30cfccfea9026660e143662ba5eec4017d5daa" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "cached_proc_macro_types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" + +[[package]] +name = "cc" +version = "1.2.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common 0.1.6", + "inout", +] + +[[package]] +name = "cipherstash-client" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0257cff25a25a706af6e190e5209865aae4ddf0b36f81febee7de014b22bcc40" +dependencies = [ + "aes-gcm-siv", + "anyhow", + "async-mutex", + "async-trait", + "base16ct", + "base64", + "base85", + "blake3", + "chrono", + "cipherstash-config", + "cipherstash-core", + "cllw-ore", + "cts-common", + "derive_more 1.0.0", + "dirs", + "futures", + "hex", + "hmac", + "itertools 0.12.1", + "lazy_static", + "log", + "miette", + "opaque-debug", + "orderable-bytes", + "ore-rs", + "percent-encoding", + "rand 0.8.6", + "recipher", + "reqwest", + "rmp-serde", + "rust-stemmers", + "rust_decimal", + "serde", + "serde_bytes", + "serde_cbor", + "serde_json", + "serdect", + "sha2", + "stack-auth", + "stack-profile", + "static_assertions", + "thiserror 1.0.69", + "tokio", + "toml", + "tracing", + "url", + "uuid", + "vitaminc", + "vitaminc-protected", + "winnow 0.6.26", + "zeroize", + "zerokms-protocol", +] + +[[package]] +name = "cipherstash-config" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d376d237e368e77de53b07bb7309812f45809299063c80b6cc3132f7d8494aed" +dependencies = [ + "bitflags", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "cipherstash-core" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca84ffd8a7b2f0c8c6b04eba600738fea115f5a4ed825035a2f13aa1524085a7" +dependencies = [ + "getrandom 0.2.16", + "hmac", + "lazy_static", + "num-bigint", + "rand 0.8.6", + "regex", + "sha2", + "thiserror 1.0.69", +] + +[[package]] +name = "cllw-ore" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f73a23cbc15404d9b314c03b16a888f798dbc681bceeb2e18674f602f9da02d" +dependencies = [ + "blake3", + "chrono", + "hex", + "orderable-bytes", + "rust_decimal", + "subtle", + "thiserror 1.0.69", + "unicode-normalization", +] + +[[package]] +name = "cmac" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8543454e3c3f5126effff9cd44d562af4e31fb8ce1cc0d3dcd8f084515dbc1aa" +dependencies = [ + "cipher", + "dbl", + "digest 0.10.7", +] + +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "compression-codecs" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf" +dependencies = [ + "brotli", + "compression-core", + "flate2", + "memchr", +] + +[[package]] +name = "compression-core" +version = "0.4.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-hex" +version = "1.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e2a781ebdf4467d1428dc4593067825fb646f6871475098d8577421af73558" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "proptest", + "serde_core", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "cts-common" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae6508011dee61bc36e16615e43cb26a8014c49ebb832e713602f3b0dc15af29" +dependencies = [ + "arrayvec", + "base32", + "cached", + "chrono", + "derive_more 2.1.1", + "either", + "getrandom 0.4.2", + "miette", + "nom", + "regex", + "serde", + "serde_json", + "thiserror 1.0.69", + "tracing", + "url", + "utoipa", + "uuid", + "vitaminc", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.108", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "data-encoding" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" + +[[package]] +name = "dbl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd2735a791158376708f9347fe8faba9667589d82427ef3aed6794a8981de3d9" +dependencies = [ + "generic-array", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl 2.1.1", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", + "unicode-xid", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.108", + "unicode-xid", +] + +[[package]] +name = "deunicode" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common 0.1.6", + "subtle", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.0", + "crypto-common 0.2.2", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "dummy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac124e13ae9aa56acc4241f8c8207501d93afdd8d8e62f0c1f2e12f6508c65" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] + +[[package]] +name = "email_address" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" +dependencies = [ + "serde", +] + +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "eql-codegen" +version = "0.1.0" +dependencies = [ + "eql-scalars", + "minijinja", + "serde", +] + +[[package]] +name = "eql-scalars" +version = "0.1.0" + +[[package]] +name = "eql-tests-macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "eql_tests" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "cipherstash-client", + "eql-scalars", + "eql-tests-macros", + "hex", + "jsonschema", + "paste", + "serde", + "serde_json", + "sqlx", + "tokio", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "fake" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d391ba4af7f1d93f01fcf7b2f29e2bc9348e109dfdbf4dcbdc51dfa38dab0b6" +dependencies = [ + "deunicode", + "dummy", + "rand 0.8.6", + "uuid", +] + +[[package]] +name = "fancy-regex" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277" +dependencies = [ + "bit-set", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fluent-uri" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc74ac4d8359ae70623506d512209619e5cf8f347124910440dbc221714b328e" +dependencies = [ + "borrow-or-share", + "ref-cast", + "serde", +] + +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fraction" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e076045bb43dac435333ed5f04caf35c7463631d0dae2deb2638d94dd0a5b872" +dependencies = [ + "lazy_static", + "num", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30" +dependencies = [ + "rustix 0.38.44", + "windows-targets 0.52.6", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasip2", + "wasip3", + "wasm-bindgen", +] + +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.8", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash 0.8.12", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.5", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + +[[package]] +name = "hickory-proto" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand 0.9.4", + "ring", + "thiserror 2.0.18", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "moka", + "once_cell", + "parking_lot", + "rand 0.9.4", + "resolv-conf", + "smallvec", + "thiserror 2.0.18", + "tokio", + "tracing", +] + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hybrid-array" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +dependencies = [ + "typenum", +] + +[[package]] +name = "hyper" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "include_dir" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "indexmap" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +dependencies = [ + "equivalent", + "hashbrown 0.16.0", + "serde", + "serde_core", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + +[[package]] +name = "ipconfig" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" +dependencies = [ + "socket2", + "widestring", + "windows-registry", + "windows-result", + "windows-sys 0.61.2", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.108", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.108", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "jsonschema" +version = "0.46.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc59d2432e047d6090ba1d83c782d0128bd6203857978218f5614dbd3287281f" +dependencies = [ + "ahash 0.8.12", + "bytecount", + "data-encoding", + "email_address", + "fancy-regex", + "fraction", + "getrandom 0.3.4", + "idna", + "itoa", + "num-cmp", + "num-traits", + "percent-encoding", + "referencing", + "regex", + "regex-syntax", + "serde", + "serde_json", + "unicode-general-category", + "uuid-simd", +] + +[[package]] +name = "jsonwebtoken" +version = "9.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +dependencies = [ + "base64", + "js-sys", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags", + "libc", + "redox_syscall", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest 0.10.7", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "memo-map" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d1115007560874e373613744c6fba374c17688327a71c1476d1a5954cc857b" + +[[package]] +name = "micromap" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a86d3146ed3995b5913c414f6664344b9617457320782e64f0bb44afd49d74" + +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "backtrace", + "backtrace-ext", + "cfg-if", + "miette-derive", + "owo-colors", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap", + "unicode-width 0.1.14", +] + +[[package]] +name = "miette-derive" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "minijinja" +version = "2.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2929e494b2280e1e18959bb2e121da03347ae896896fdfaceaab43c88a02803f" +dependencies = [ + "memo-map", + "serde", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "moka" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "equivalent", + "parking_lot", + "portable-atomic", + "smallvec", + "tagptr", + "uuid", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.6", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-cmp" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa" + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +dependencies = [ + "critical-section", + "portable-atomic", +] + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "open" +version = "5.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fbaa89d2ddc8473c78a3adf69eea8cffa28c483b8e02a971ef31527cd0fc92c" +dependencies = [ + "is-wsl", + "libc", + "pathdiff", +] + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "orderable-bytes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adba0469737879cabc3bdcaa6a7beb4ff7f5bb4aa5d624816c8bb9d425a7d5df" +dependencies = [ + "chrono", + "rust_decimal", +] + +[[package]] +name = "ore-rs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77fb65718f1aba7bb7f568db90a2b17a48871d83cd9d1101d19fce449dd8dea" +dependencies = [ + "aes", + "block-modes", + "byteorder", + "chrono", + "hex", + "lazy_static", + "num", + "orderable-bytes", + "rand 0.8.6", + "rand_chacha 0.3.1", + "rust_decimal", + "subtle-ng", + "thiserror 1.0.69", + "zeroize", +] + +[[package]] +name = "outref" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" + +[[package]] +name = "owo-colors" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + +[[package]] +name = "pem" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64", + "serde_core", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "potential_utf" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.108", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.6+spec-1.1.0", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "proc-macro2" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e0f6df8eaa422d97d72edcd152e1451618fed47fabbdbd5a8864167b1d4aff7" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" +dependencies = [ + "bitflags", + "num-traits", + "rand 0.9.4", + "rand_chacha 0.9.0", + "rand_xorshift", + "regex-syntax", + "unarray", +] + +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.4", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.5", +] + +[[package]] +name = "recipher" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9398dce78ddfce08f93e9d9a3ac64d9b0a4fed478c0a82003c6e4c90dc245125" +dependencies = [ + "aes", + "cmac", + "getrandom 0.2.16", + "hex", + "hex-literal", + "opaque-debug", + "rand 0.8.6", + "rand_chacha 0.3.1", + "serde", + "serde_cbor", + "sha2", + "thiserror 1.0.69", + "zeroize", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "referencing" +version = "0.46.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb674900ca31acd75c4aaf63f48e43e719631c0539ea5a9e64163d1296bcb730" +dependencies = [ + "ahash 0.8.12", + "fluent-uri", + "getrandom 0.3.4", + "hashbrown 0.16.0", + "itoa", + "micromap", + "parking_lot", + "percent-encoding", + "serde_json", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "reqwest" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" +dependencies = [ + "base64", + "bytes", + "futures-core", + "futures-util", + "hickory-resolver", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + +[[package]] +name = "resolv-conf" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "rkyv" +version = "0.7.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rmp" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "rmp-serde" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155" +dependencies = [ + "rmp", + "serde", +] + +[[package]] +name = "rsa" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" +dependencies = [ + "const-oid", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rust-stemmers" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e46a2036019fdb888131db7a4c847a1063a7493f971ed94ea82c67eada63ca54" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "rust_decimal" +version = "1.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c5108e3d4d903e21aac27f12ba5377b6b34f9f44b325e4894c7924169d06995" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand 0.8.6", + "rkyv", + "serde", + "serde_json", + "wasm-bindgen", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" +dependencies = [ + "aws-lc-rs", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted 0.9.0", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serdect" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f42f67da2385b51a5f9652db9c93d78aeaf7610bf5ec366080b6de810604af53" +dependencies = [ + "base16ct", + "serde", + "zeroize", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "simple_asn1" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror 2.0.18", + "time", +] + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlx" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" +dependencies = [ + "base64", + "bytes", + "chrono", + "crc", + "crossbeam-queue", + "either", + "event-listener 5.4.1", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.15.5", + "hashlink", + "indexmap", + "log", + "memchr", + "once_cell", + "percent-encoding", + "serde", + "serde_json", + "sha2", + "smallvec", + "thiserror 2.0.18", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 2.0.108", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" +dependencies = [ + "dotenvy", + "either", + "heck", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 2.0.108", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" +dependencies = [ + "atoi", + "base64", + "bitflags", + "byteorder", + "bytes", + "chrono", + "crc", + "digest 0.10.7", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand 0.8.6", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.18", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" +dependencies = [ + "atoi", + "base64", + "bitflags", + "byteorder", + "chrono", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.6", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.18", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" +dependencies = [ + "atoi", + "chrono", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "serde_urlencoded", + "sqlx-core", + "thiserror 2.0.18", + "tracing", + "url", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "stack-auth" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c823cc3d88e15478d51694ef56037400bd4ae3e1a9e046071e01d251168cc466" +dependencies = [ + "aquamarine", + "base64", + "cts-common", + "jsonwebtoken", + "miette", + "open", + "reqwest", + "serde", + "serde_json", + "stack-profile", + "thiserror 1.0.69", + "tokio", + "tracing", + "url", + "uuid", + "vitaminc", + "vitaminc-protected", + "web-time", + "zeroize", + "zerokms-protocol", +] + +[[package]] +name = "stack-profile" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1be30119d59260f3e932f78fbbfbe3674c151d39e7fcca24d0439e7e31ba8" +dependencies = [ + "dirs", + "gethostname", + "serde", + "serde_json", + "thiserror 1.0.69", + "uuid", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + +[[package]] +name = "supports-color" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" +dependencies = [ + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91" + +[[package]] +name = "supports-unicode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "terminal_size" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" +dependencies = [ + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "textwrap" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" +dependencies = [ + "unicode-linebreak", + "unicode-width 0.2.2", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.15", +] + +[[package]] +name = "toml_edit" +version = "0.25.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0db3bae107c9522f86d361697dee1d7386a2ddcf659d5aea5159819a21a3c4a7" +dependencies = [ + "indexmap", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.3", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.3", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "async-compression", + "bitflags", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "pin-project-lite", + "tokio", + "tokio-util", + "tower", + "tower-layer", + "tower-service", + "url", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-general-category" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b993bddc193ae5bd0d623b49ec06ac3e9312875fdae725a975c51db1cc1677f" + +[[package]] +name = "unicode-ident" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common 0.1.6", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utoipa" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bde15df68e80b16c7d16b9616e80770ad158988daa56a27dccd1e55558b0160" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba0b99ee52df3028635d93840c797102da61f8a7bb3cf751032455895b52ef8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", + "url", + "uuid", +] + +[[package]] +name = "uuid" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +dependencies = [ + "atomic", + "getrandom 0.4.2", + "js-sys", + "md-5", + "serde_core", + "sha1_smol", + "wasm-bindgen", +] + +[[package]] +name = "uuid-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b082222b4f6619906941c17eb2297fff4c2fb96cb60164170522942a200bd8" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "validator" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43fb22e1a008ece370ce08a3e9e4447a910e92621bb49b85d6e48a45397e7cfa" +dependencies = [ + "idna", + "once_cell", + "regex", + "serde", + "serde_derive", + "serde_json", + "url", + "validator_derive", +] + +[[package]] +name = "validator_derive" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7df16e474ef958526d1205f6dda359fdfab79d9aa6d54bafcb92dcd07673dca" +dependencies = [ + "darling", + "once_cell", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vitaminc" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec9807fc6a29a9ab4a9cd24f103573661d7e04d48651ce8c752d32e73a686446" +dependencies = [ + "vitaminc-aead", + "vitaminc-encrypt", + "vitaminc-protected", + "vitaminc-random", + "vitaminc-traits", +] + +[[package]] +name = "vitaminc-aead" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3933759550ab4841536e8d019fc73cd77ec2e43dcdaefa3218936534eefabb8d" +dependencies = [ + "bytes", + "serde", + "vitaminc-protected", + "vitaminc-random", + "zeroize", +] + +[[package]] +name = "vitaminc-encrypt" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdbcfd5e9054ce2a3f0cfac67c3e3164d65f38f3a6d593bc4d5d943e53aaf44" +dependencies = [ + "aes-gcm", + "aws-lc-rs", + "vitaminc-aead", + "vitaminc-protected", + "vitaminc-random", + "zeroize", +] + +[[package]] +name = "vitaminc-protected" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c639c70c23871680d0cedabb2fb8cfd0ff91eb98d90dd27e9bdebf6eac1fd18" +dependencies = [ + "bitvec", + "digest 0.11.3", + "serde", + "serde_bytes", + "subtle", + "vitaminc-protected-derive", + "zeroize", +] + +[[package]] +name = "vitaminc-protected-derive" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "659afc33e7252768204f44bd9f377a120a35dc586aa3538b66a3f4cc54a88653" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "vitaminc-random" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac67bf5f90acc53c87deb5f612ad1beefd0e0e7f5452ab3443d9fa4b0e23f9c5" +dependencies = [ + "getrandom 0.4.2", + "rand 0.10.1", + "thiserror 2.0.18", + "vitaminc-protected", + "vitaminc-random-derives", + "zeroize", +] + +[[package]] +name = "vitaminc-random-derives" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efeeb4347ca86ff167228cfbd655c7a6e8a5bd6f032330ac881d6c4c0441768b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "vitaminc-traits" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6ef24c094d225d00753134f082eba59ea2ba8d5d0b5ba761c038ca9375b3" +dependencies = [ + "anyhow", + "bytes", + "rmp-serde", + "serde", + "thiserror 2.0.18", + "vitaminc-protected", + "vitaminc-random", + "zeroize", +] + +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "serde", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.108", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "web-sys" +version = "0.3.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-root-certs" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "whoami" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" +dependencies = [ + "libredox", + "wasite", +] + +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.6.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn 2.0.108", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.108", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "zerokms-protocol" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04a9411f442b247e7d00c6a07cfbc6d56c12d485cfaf4f7effa001bfb1615296" +dependencies = [ + "base64", + "cipherstash-config", + "const-hex", + "cts-common", + "fake", + "getrandom 0.2.16", + "opaque-debug", + "rand 0.8.6", + "serde", + "static_assertions", + "thiserror 1.0.69", + "utoipa", + "uuid", + "validator", + "zeroize", +] + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..6e0b6760 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,25 @@ +# Cargo workspace root. +# +# Members: +# crates/eql-scalars — the scalar/term catalog (std-only, no deps). Source of +# truth for the Rust generator (Plan 2) and the SQLx test +# harness (Plan 3). +# crates/eql-codegen — the SQL generator binary (stub here; Plan 2 fills it in). +# crates/eql-tests-macros — proc-macros expanding the single scalar-harness +# list into the per-type SQLx-matrix wiring. +# tests/sqlx — the existing `eql_tests` SQLx integration crate. +# +# resolver = "2" keeps the heavy test-crate feature set (sqlx/tokio/cipherstash- +# client) from unifying into the lean catalog/generator crates. +# +# default-members = ["tests/sqlx"] keeps a bare `cargo test` / `cargo build` at the +# root building only the test crate, exactly as the pre-workspace layout did. +[workspace] +resolver = "2" +members = [ + "crates/eql-scalars", + "crates/eql-codegen", + "crates/eql-tests-macros", + "tests/sqlx", +] +default-members = ["tests/sqlx"] diff --git a/crates/eql-codegen/Cargo.toml b/crates/eql-codegen/Cargo.toml new file mode 100644 index 00000000..25165397 --- /dev/null +++ b/crates/eql-codegen/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "eql-codegen" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +eql-scalars = { path = "../eql-scalars" } +minijinja = "2" +serde = { version = "1", features = ["derive"] } + +[[bin]] +name = "eql-codegen" +path = "src/main.rs" + +[lib] +name = "eql_codegen" +path = "src/lib.rs" diff --git a/crates/eql-codegen/src/consts.rs b/crates/eql-codegen/src/consts.rs new file mode 100644 index 00000000..0f7a1ef7 --- /dev/null +++ b/crates/eql-codegen/src/consts.rs @@ -0,0 +1,45 @@ +//! AUTO-GENERATED headers, schema constants, and SQL-string escaping. + +/// SQL generated-file marker. The SQL templates emit this as their first line; +/// the writer uses it only to recognise files it owns (overwrite/clean safety). +pub(crate) const AUTO_GENERATED_HEADER: &str = "-- AUTOMATICALLY GENERATED FILE.\n"; + +/// The single schema housing the self-contained `eql_v3` surface: the +/// encrypted-domain families AND the SEM index-term types/constructors they +/// call. v3 has zero dependency on `eql_v2`, so domains and core index-term +/// types share one schema by construction — there is no second schema to point +/// the core types at. +pub(crate) const SCHEMA: &str = "eql_v3"; + +/// Always-present payload keys checked for presence in every domain CHECK, in +/// order: envelope version (`v`), ident (`i`), ciphertext (`c`). Term-specific +/// keys are appended after these by `context::domain_block`. +pub(crate) const ENVELOPE_KEYS: &[&str] = &["v", "i", "c"]; + +/// Escape a string for use inside a single-quoted SQL literal by doubling +/// embedded single quotes. Port of templates.py `_sql_str`. +pub(crate) fn sql_str(s: &str) -> String { + s.replace('\'', "''") +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sql_marker_is_grep_compatible_single_line() { + // The `^-- AUTOMATICALLY GENERATED FILE` marker is what + // tasks/docs/validate/{coverage,required-tags}.sh grep on to skip + // generated SQL — keep this assertion and that grep in lockstep. + assert_eq!(AUTO_GENERATED_HEADER, "-- AUTOMATICALLY GENERATED FILE.\n"); + assert!(AUTO_GENERATED_HEADER.contains("AUTOMATICALLY GENERATED FILE")); + } + + #[test] + fn sql_str_doubles_single_quotes() { + assert_eq!(sql_str("o'brien"), "o''brien"); + assert_eq!(sql_str("a'b'c"), "a''b''c"); + assert_eq!(sql_str("int4_eq"), "int4_eq"); + assert_eq!(sql_str("<="), "<="); + } +} diff --git a/crates/eql-codegen/src/context.rs b/crates/eql-codegen/src/context.rs new file mode 100644 index 00000000..78b50883 --- /dev/null +++ b/crates/eql-codegen/src/context.rs @@ -0,0 +1,328 @@ +//! minijinja environment + serde context structs + relocated logic helpers. + +use crate::consts::*; +use crate::operator_surface::Operator; +use eql_scalars::{DomainSpec, Term}; + +/// Build the minijinja environment with the embedded templates: one whole-file +/// template per output file (`types`/`functions`/`operators`/`aggregates`) plus +/// the per-kind function-body partials that `functions.sql` dynamically +/// `{% include %}`s. Templates are compiled in via `include_str!` — no runtime +/// file IO. +pub fn environment() -> minijinja::Environment<'static> { + let mut env = minijinja::Environment::new(); + // Preserve each template file's trailing newline so generated SQL files end + // with one (minijinja strips it by default). + env.set_keep_trailing_newline(true); + env.add_template("types.sql", include_str!("../templates/types.sql.j2")) + .expect("types.sql template"); + env.add_template( + "functions.sql", + include_str!("../templates/functions.sql.j2"), + ) + .expect("functions.sql template"); + // Per-kind function bodies, dynamically `{% include %}`d by the parent + // `functions.sql` template based on each entry's `kind` tag + // (Extractor/Wrapper/Unsupported -> extractor/wrapper/unsupported). + env.add_template( + "functions/extractor.sql.j2", + include_str!("../templates/functions/extractor.sql.j2"), + ) + .expect("functions/extractor.sql.j2 template"); + env.add_template( + "functions/wrapper.sql.j2", + include_str!("../templates/functions/wrapper.sql.j2"), + ) + .expect("functions/wrapper.sql.j2 template"); + env.add_template( + "functions/unsupported.sql.j2", + include_str!("../templates/functions/unsupported.sql.j2"), + ) + .expect("functions/unsupported.sql.j2 template"); + env.add_template( + "operators.sql", + include_str!("../templates/operators.sql.j2"), + ) + .expect("operators.sql template"); + env.add_template( + "aggregates.sql", + include_str!("../templates/aggregates.sql.j2"), + ) + .expect("aggregates.sql template"); + env.add_global("schema", SCHEMA); + env +} + +/// One idempotent CREATE DOMAIN block, with SQL-required values precomputed. +#[derive(serde::Serialize)] +pub struct DomainBlock { + pub typname: String, // sql_str-escaped bare name, e.g. int4_ord_ore + pub name: String, // raw bare name (unescaped), e.g. int4_ord_ore + pub keys: Vec, // ordered, sql_str-escaped key tokens (envelope + ciphertext + term keys) +} + +#[derive(serde::Serialize)] +pub struct TypesContext { + pub token: String, + pub domains: Vec, +} + +/// Build the per-domain block data (port of `render_domain_block`'s value logic, +/// minus comment prose and the CHECK skeleton — those are template-resident). +pub fn domain_block(token: &str, domain: &DomainSpec) -> DomainBlock { + let name = full_domain_name(token, domain.suffix); + + let mut keys: Vec = ENVELOPE_KEYS.iter().map(|k| sql_str(k)).collect(); + for k in Term::term_json_keys(domain.terms) { + keys.push(sql_str(k)); + } + + DomainBlock { + // typname is sql_str-escaped defensively: the escaping boundary stays + // Rust-side even though real catalog names carry no quotes. + typname: sql_str(&name), + name, + keys, + } +} + +/// One SQL parameter (name + SQL type), shared by wrapper and +/// unsupported-operator signatures and their `@param` docs tags. +#[derive(serde::Serialize)] +pub struct SqlParam { + pub name: &'static str, // "a", "b", or "selector" + pub ty: String, +} + +/// One generated function entry. The serde tag drives the template's three-way +/// switch; the unsupported-operator arm is never merged with the others (footgun +/// separation — its body must always raise). +#[derive(serde::Serialize)] +#[serde(tag = "kind")] +pub enum FnEntry { + Extractor { + ret: String, // e.g. eql_v2.hmac_256 (selection STAYS in Rust) + extractor: String, // e.g. eq_term + ctor: String, // e.g. hmac_256 (called as {{ schema }}.{{ ctor }}) + }, + Wrapper { + op: String, // SQL operator used in the body, e.g. = + function_name: String, // e.g. eq + args: [SqlParam; 2], + call_a: String, // e.g. eql_v3.eq_term(a) (embeds extract_arg cast logic) + call_b: String, // e.g. eql_v3.eq_term(b::eql_v3.int4_eq) + }, + Unsupported { + operator_lit: String, // sql_str(op), escaped content for the RAISE literal + function_name: String, // e.g. lt / "->" / "#>" + args: [SqlParam; 2], + returns: String, // boolean / text / jsonb / domain (selection STAYS in Rust) + }, +} + +#[derive(serde::Serialize)] +pub struct FunctionsContext { + pub requires: Vec, // dependency paths only; template emits "-- REQUIRE:" + pub token: String, + pub name: String, // full domain name (token+suffix) + pub dom: String, // schema-qualified domain, e.g. eql_v3.int4_eq + pub domain_lit: String, // sql_str(dom), defensively escaped for the RAISE literal + pub entries: Vec, +} + +/// Build the inlinable index-extractor entry for a domain term. +/// +/// The `RETURNS` type name equals the constructor name (`hmac_256`, +/// `ore_block_u64_8_256`); qualify it with `SCHEMA` — the same schema as the +/// body's constructor call — so the declared return type and the call stay in +/// lockstep. `Term::returns()` is intentionally not used. +pub fn extractor_entry(term: Term) -> FnEntry { + FnEntry::Extractor { + ret: format!("{SCHEMA}.{}", term.ctor()), + extractor: term.extractor().to_string(), + ctor: term.ctor().to_string(), + } +} + +/// Build an inlinable comparison-wrapper entry for a supported operator. +/// `dom` is the schema-qualified domain name. +pub fn wrapper_entry(dom: &str, op: &str, arg_a: &str, arg_b: &str, extractor: &str) -> FnEntry { + use crate::operator_surface::operator_function_name; + FnEntry::Wrapper { + op: op.to_string(), + function_name: operator_function_name(op).to_string(), + args: [ + SqlParam { + name: "a", + ty: arg_a.to_string(), + }, + SqlParam { + name: "b", + ty: arg_b.to_string(), + }, + ], + call_a: extract_arg(arg_a, extractor, dom, "a"), + call_b: extract_arg(arg_b, extractor, dom, "b"), + } +} + +/// Build an unsupported-operator entry. Every such entry shares one uniform +/// `RAISE EXCEPTION` body; only signature facts vary. +pub fn unsupported_entry(op: &str, args: [SqlParam; 2], returns: &str) -> FnEntry { + use crate::operator_surface::operator_function_name; + FnEntry::Unsupported { + // operator_lit is sql_str-escaped defensively for the single-quoted RAISE literal. + operator_lit: sql_str(op), + function_name: operator_function_name(op).to_string(), + args, + returns: returns.to_string(), + } +} + +/// One CREATE OPERATOR declaration, with the optional metadata line precomputed. +#[derive(serde::Serialize)] +pub struct OpEntry { + pub symbol: String, + pub function_name: String, // unqualified; schema literal lives in the template + pub leftarg: String, + pub rightarg: String, + pub metadata: Option, // e.g. "COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel" +} + +#[derive(serde::Serialize)] +pub struct OperatorsContext { + pub requires: Vec, + pub token: String, + pub name: String, + pub dom: String, + pub operators: Vec, +} + +/// Build one CREATE OPERATOR entry. Planner metadata is emitted only when the +/// current domain supports the operator and the operator carries metadata (the +/// `@>`/`<@` empty-metadata case collapses to `None`). +pub fn operator_entry(op: &Operator, leftarg: &str, rightarg: &str, supported: bool) -> OpEntry { + let metadata = if supported { + op.metadata.render() + } else { + None + }; + OpEntry { + symbol: op.symbol.to_string(), + function_name: op.function_name.to_string(), + leftarg: leftarg.to_string(), + rightarg: rightarg.to_string(), + metadata, + } +} + +#[derive(serde::Serialize)] +pub struct AggregatesContext { + pub requires: Vec, // dependency paths only; template emits "-- REQUIRE:" + pub token: String, + pub name: String, + pub dom: String, // schema-qualified domain, hoisted + pub aggregates: &'static [AggregateOp], // == AGGREGATE_OPS +} + +/// The schema-qualified SQL domain type name, e.g. `eql_v3.int4_eq`. +/// Port of `domain_name`. +pub fn domain_name(name: &str) -> String { + format!("{SCHEMA}.{name}") +} + +/// The full domain name from a token + suffix (suffix "" => bare token). +pub fn full_domain_name(token: &str, suffix: &str) -> String { + format!("{token}{suffix}") +} + +/// The extractor-call SQL for one operand, casting jsonb to the domain first. +/// Port of `_extract_arg`. `dom` is the schema-qualified domain name. +pub fn extract_arg(arg_type: &str, extractor: &str, dom: &str, arg: &str) -> String { + if arg_type == "jsonb" { + format!("{SCHEMA}.{extractor}({arg}::{dom})") + } else { + format!("{SCHEMA}.{extractor}({arg})") + } +} + +/// One aggregate operator definition (min or max). Only SQL-required facts: the +/// state-function name is the mechanical suffix `{{ a.name }}_sfunc` in the +/// template, and English comment phrases are template-resident. +#[derive(serde::Serialize)] +pub struct AggregateOp { + pub name: &'static str, // min / max + pub comparator: &'static str, // < / > +} + +/// The two aggregate ops in (min, max) order. Port of `AGGREGATE_OPS`. +pub const AGGREGATE_OPS: &[AggregateOp] = &[ + AggregateOp { + name: "min", + comparator: "<", + }, + AggregateOp { + name: "max", + comparator: ">", + }, +]; + +/// True if the domain carries a comparator term (supports `<`). +/// Port of `is_ord_capable`. +pub fn is_ord_capable(terms: &[Term]) -> bool { + Term::role_for_terms(terms) == "ord" +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn domain_name_qualifies_with_schema() { + assert_eq!(domain_name("int4_eq"), "eql_v3.int4_eq"); + } + + #[test] + fn is_ord_capable_matches_role() { + assert!(is_ord_capable(&[Term::Ore])); + assert!(!is_ord_capable(&[Term::Hm])); + assert!(!is_ord_capable(&[])); + } + + #[test] + fn environment_has_whole_file_and_partial_templates() { + let env = environment(); + for name in [ + // One whole-file template per generated SQL file. + "types.sql", + "functions.sql", + "operators.sql", + "aggregates.sql", + // Per-kind partials included by functions.sql. + "functions/extractor.sql.j2", + "functions/wrapper.sql.j2", + "functions/unsupported.sql.j2", + ] { + assert!(env.get_template(name).is_ok(), "missing template {name}"); + } + } + + #[test] + fn operator_entry_emits_metadata_only_when_supported() { + use crate::operator_surface::operator; + // Supported comparison operator carries its planner metadata. + let eq = operator_entry(&operator("="), "eql_v3.int4_eq", "eql_v3.int4_eq", true); + assert_eq!(eq.symbol, "="); + assert_eq!(eq.function_name, "eq"); + assert_eq!( + eq.metadata.as_deref(), + Some("COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel") + ); + // The same operator, unsupported on this domain → no metadata line. + let eq_unsupported = operator_entry(&operator("="), "eql_v3.int4", "eql_v3.int4", false); + assert_eq!(eq_unsupported.metadata, None); + // Supported but metadata-less operator (`@>`) → still no metadata line. + let contains = operator_entry(&operator("@>"), "eql_v3.int4_eq", "eql_v3.int4_eq", true); + assert_eq!(contains.metadata, None); + } +} diff --git a/crates/eql-codegen/src/generate.rs b/crates/eql-codegen/src/generate.rs new file mode 100644 index 00000000..622ca634 --- /dev/null +++ b/crates/eql-codegen/src/generate.rs @@ -0,0 +1,716 @@ +//! File renderers and orchestrator (port of generate.py). + +use std::path::{Path, PathBuf}; + +use eql_scalars::{DomainSpec, ScalarSpec, Term}; + +use crate::context::{domain_name, is_ord_capable}; +use crate::operator_surface::OPERATORS; + +/// REQUIRE edge for the v3 schema file — pulled in by every generated file. +const V3_SCHEMA: &str = "src/v3/schema.sql"; +/// REQUIRE edge for the hand-written shared blocker helper. +const V3_SCALARS_BLOCKER: &str = "src/v3/scalars/functions.sql"; +/// Root of the generated per-token scalar surface. The single place the tree +/// layout is spelled out — keeps `types_path`/`scalar_path` and the REQUIRE +/// vecs from drifting if the surface ever relocates again. +const V3_SCALARS_DIR: &str = "src/v3/scalars"; + +/// REQUIRE path for a generated file `file` under a token's scalar dir. +fn scalar_path(token: &str, file: &str) -> String { + format!("{V3_SCALARS_DIR}/{token}/{file}") +} + +/// The full domain name (token + suffix). suffix "" => bare token. +fn full_name(token: &str, suffix: &str) -> String { + format!("{token}{suffix}") +} + +/// The second-parameter name for an operator's generated signature. The `->` and +/// `->>` path operators take a path *selector* as their right operand; every +/// other operator uses the generic `b`. This is a naming convention only — it +/// has no bearing on whether the operator is supported. +fn arg_b_name(symbol: &str) -> &'static str { + match symbol { + "->" | "->>" => "selector", + _ => "b", + } +} + +/// REQUIRE path for a type's _types.sql. Port of `_types_path`. +fn types_path(token: &str) -> String { + scalar_path(token, &format!("{token}_types.sql")) +} + +/// Body for _types.sql: every domain in one idempotent DO block. +/// Port of `render_types_file`. +pub fn render_types_file(spec: &ScalarSpec) -> String { + use crate::context::{domain_block, environment, TypesContext}; + let ctx = TypesContext { + token: spec.token.to_string(), + domains: spec + .domains + .iter() + .map(|d| domain_block(spec.token, d)) + .collect(), + }; + environment() + .get_template("types.sql") + .unwrap() + .render(&ctx) + .expect("render types.sql") +} + +/// REQUIRE edges for a domain's _functions.sql. Port of `_functions_requires`. +fn functions_requires(token: &str, terms: &[Term]) -> Vec { + let mut reqs = vec![ + V3_SCHEMA.to_string(), + types_path(token), + V3_SCALARS_BLOCKER.to_string(), + ]; + for extra in Term::term_requires(terms) { + if !reqs.iter().any(|r| r == extra) { + reqs.push(extra.to_string()); + } + } + reqs +} + +/// Distinct extractor-bearing terms (first occurrence per extractor). +/// Port of `_extractor_terms`. +fn extractor_terms(terms: &[Term]) -> Vec { + let mut seen: Vec<&str> = Vec::new(); + let mut out: Vec = Vec::new(); + for &t in terms { + if !seen.contains(&t.extractor()) { + seen.push(t.extractor()); + out.push(t); + } + } + out +} + +/// Body for a domain's _functions.sql. Port of `render_functions_file`. +pub fn render_functions_file(token: &str, domain: &DomainSpec) -> String { + use crate::consts::sql_str; + use crate::context::{ + environment, extractor_entry, unsupported_entry, wrapper_entry, FunctionsContext, SqlParam, + }; + let name = full_name(token, domain.suffix); + let dom = domain_name(&name); + let domain_lit = sql_str(&dom); + let supported = Term::operators_for_terms(domain.terms); + let is_supported = |op: &str| supported.contains(&op); + + let mut entries = Vec::new(); + for term in extractor_terms(domain.terms) { + entries.push(extractor_entry(term)); + } + for op in OPERATORS { + let extractor = Term::extractor_for_operator(domain.terms, op.symbol); + for sig in op.signatures { + let rendered = sig.render(&dom); + if is_supported(op.symbol) { + if let Some(ex) = extractor { + entries.push(wrapper_entry( + &dom, + op.symbol, + &rendered.left, + &rendered.right, + ex, + )); + continue; + } + } + let args = [ + SqlParam { + name: "a", + ty: rendered.left, + }, + SqlParam { + name: arg_b_name(op.symbol), + ty: rendered.right, + }, + ]; + entries.push(unsupported_entry(op.symbol, args, &rendered.returns)); + } + } + + let ctx = FunctionsContext { + requires: functions_requires(token, domain.terms), + token: token.to_string(), + name, + dom, + domain_lit, + entries, + }; + environment() + .get_template("functions.sql") + .unwrap() + .render(&ctx) + .expect("render functions.sql") +} + +/// Body for a domain's _operators.sql. Port of `render_operators_file`. +pub fn render_operators_file(token: &str, domain: &DomainSpec) -> String { + use crate::context::{environment, operator_entry, OperatorsContext}; + let name = full_name(token, domain.suffix); + let dom = domain_name(&name); + let supported = Term::operators_for_terms(domain.terms); + let is_supported = |op: &str| supported.contains(&op); + + let mut operators = Vec::new(); + for op in OPERATORS { + for sig in op.signatures { + // CREATE OPERATOR only needs the operand types; `rendered.returns` is + // intentionally discarded here (it matters only for the function body). + let rendered = sig.render(&dom); + operators.push(operator_entry( + op, + &rendered.left, + &rendered.right, + is_supported(op.symbol), + )); + } + } + + let ctx = OperatorsContext { + requires: vec![ + V3_SCHEMA.to_string(), + types_path(token), + scalar_path(token, &format!("{name}_functions.sql")), + ], + token: token.to_string(), + name, + dom, + operators, + }; + environment() + .get_template("operators.sql") + .unwrap() + .render(&ctx) + .expect("render operators.sql") +} + +/// Body for a domain's _aggregates.sql, or None if not ord-capable. +/// Port of `render_aggregates_file`. +pub fn render_aggregates_file(token: &str, domain: &DomainSpec) -> Option { + use crate::context::{environment, AggregatesContext, AGGREGATE_OPS}; + if !is_ord_capable(domain.terms) { + return None; + } + let name = full_name(token, domain.suffix); + let dom = domain_name(&name); + let ctx = AggregatesContext { + requires: vec![ + V3_SCHEMA.to_string(), + types_path(token), + scalar_path(token, &format!("{name}_functions.sql")), + scalar_path(token, &format!("{name}_operators.sql")), + ], + token: token.to_string(), + name, + dom, // hoisted: one copy, template reads {{ dom }} + aggregates: AGGREGATE_OPS, // iterate the const directly (no per-entry wrapper) + }; + Some( + environment() + .get_template("aggregates.sql") + .unwrap() + .render(&ctx) + .expect("render aggregates.sql"), + ) +} + +use crate::writer::{ + clean_generated_files, ensure_generated_paths_writable, write_generated_file, WriteError, +}; + +/// Regenerate every generated file for one type into `out_dir`. +/// Port of `generate_type`. Returns the written paths. +pub fn generate_type(spec: &ScalarSpec, out_dir: &Path) -> Result, WriteError> { + let token = spec.token; + let mut targets = vec![out_dir.join(format!("{token}_types.sql"))]; + for d in spec.domains { + let name = full_name(token, d.suffix); + targets.push(out_dir.join(format!("{name}_functions.sql"))); + targets.push(out_dir.join(format!("{name}_operators.sql"))); + if is_ord_capable(d.terms) { + targets.push(out_dir.join(format!("{name}_aggregates.sql"))); + } + } + ensure_generated_paths_writable(&targets)?; + clean_generated_files(out_dir)?; + + let mut written: Vec = Vec::new(); + + let types_path = out_dir.join(format!("{token}_types.sql")); + write_generated_file(&types_path, &render_types_file(spec))?; + written.push(types_path); + + for d in spec.domains { + let name = full_name(token, d.suffix); + let fn_path = out_dir.join(format!("{name}_functions.sql")); + write_generated_file(&fn_path, &render_functions_file(token, d))?; + written.push(fn_path); + + let op_path = out_dir.join(format!("{name}_operators.sql")); + write_generated_file(&op_path, &render_operators_file(token, d))?; + written.push(op_path); + + if let Some(agg) = render_aggregates_file(token, d) { + let agg_path = out_dir.join(format!("{name}_aggregates.sql")); + write_generated_file(&agg_path, &agg)?; + written.push(agg_path); + } + } + Ok(written) +} + +/// Generate every catalog type's gitignored SQL surface under `out_root`. The +/// single entry point: replaces Python's per-type and --all forms. The +/// plaintext fixture lists are not generated — they live in the catalog +/// (`eql_scalars::INT4_VALUES` / `INT2_VALUES`), read directly by the SQLx tests. +pub fn generate_all(out_root: &Path) -> Result { + for spec in eql_scalars::CATALOG { + let token = spec.token; + let out_dir = out_root.join(V3_SCALARS_DIR).join(token); + let written = generate_type(spec, &out_dir)?; + + for p in &written { + let rel = p.strip_prefix(out_root).unwrap_or(p); + println!("generated {}", rel.display()); + } + println!("generated {} files for {token}", written.len()); + } + let tokens: Vec<&str> = eql_scalars::CATALOG.iter().map(|s| s.token).collect(); + println!( + "codegen: ok ({} types: {})", + tokens.len(), + tokens.join(", ") + ); + Ok(0) +} + +#[cfg(test)] +mod tests { + use super::*; + use eql_scalars::CATALOG; + + fn spec(token: &str) -> &'static ScalarSpec { + CATALOG + .iter() + .find(|s| s.token == token) + .expect("catalog token") + } + + fn domain<'a>(spec: &'a ScalarSpec, suffix: &str) -> &'a DomainSpec { + spec.domains + .iter() + .find(|d| d.suffix == suffix) + .expect("domain suffix") + } + + use std::fs; + + fn repo_root() -> PathBuf { + // crates/eql-codegen/ -> repo root is two parents up from CARGO_MANIFEST_DIR. + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .parent() + .unwrap() + .to_path_buf() + } + + fn strip_reference_marker(text: &str) -> String { + let mut lines: Vec<&str> = text.lines().collect(); + // .lines() drops the trailing newline; re-add per line and handle the + // first marker line(s). + while !lines.is_empty() + && (lines[0].starts_with("-- REFERENCE:") || lines[0].starts_with("// REFERENCE:")) + { + lines.remove(0); + } + let mut out = lines.join("\n"); + if text.ends_with('\n') { + out.push('\n'); + } + out + } + + fn rendered_for(token: &str, name: &str, spec: &ScalarSpec) -> String { + if name == format!("{token}_types.sql") { + return render_types_file(spec); + } + for d in spec.domains { + let full = full_name(token, d.suffix); + if name == format!("{full}_functions.sql") { + return render_functions_file(token, d); + } + if name == format!("{full}_operators.sql") { + return render_operators_file(token, d); + } + if name == format!("{full}_aggregates.sql") { + return render_aggregates_file(token, d) + .expect("reference exists but generator skipped (not ord-capable)"); + } + } + panic!("unrecognised reference filename: {name}"); + } + + #[test] + fn arg_b_name_is_selector_only_for_path_operators() { + assert_eq!(arg_b_name("->"), "selector"); + assert_eq!(arg_b_name("->>"), "selector"); + assert_eq!(arg_b_name("="), "b"); + assert_eq!(arg_b_name("||"), "b"); + assert_eq!(arg_b_name("@>"), "b"); + } + + #[test] + fn functions_render_supported_wrappers_and_unsupported_entries_from_catalog() { + let s = spec("int4"); + let d = domain(s, "_eq"); + let sql = render_functions_file("int4", d); + assert!(sql.contains("CREATE FUNCTION eql_v3.eq(")); + assert!(sql.contains("AS $$ SELECT")); + assert!(sql.contains("CREATE FUNCTION eql_v3.lt(")); + assert!(sql.contains("RAISE EXCEPTION 'operator % is not supported for %', '<'")); + assert!(sql.contains("CREATE FUNCTION eql_v3.\"->\"(")); + assert!(sql.contains("RAISE EXCEPTION 'operator % is not supported for %', '->'")); + } + + #[test] + fn types_file_matches_golden() { + let root = repo_root(); + let path = root.join("tests/codegen/reference/int4/int4_types.sql"); + let expected = strip_reference_marker(&fs::read_to_string(&path).unwrap()); + let actual = render_types_file(spec("int4")); + assert_eq!(actual, expected); + } + + #[test] + fn functions_files_match_golden() { + let root = repo_root(); + let s = spec("int4"); + for d in s.domains { + let full = full_name("int4", d.suffix); + let path = root.join(format!("tests/codegen/reference/int4/{full}_functions.sql")); + let expected = strip_reference_marker(&fs::read_to_string(&path).unwrap()); + let actual = render_functions_file("int4", d); + assert_eq!(actual, expected, "{full}_functions.sql diverged"); + } + } + + #[test] + fn operators_files_match_golden() { + let root = repo_root(); + let s = spec("int4"); + for d in s.domains { + let full = full_name("int4", d.suffix); + let path = root.join(format!("tests/codegen/reference/int4/{full}_operators.sql")); + let expected = strip_reference_marker(&fs::read_to_string(&path).unwrap()); + let actual = render_operators_file("int4", d); + assert_eq!(actual, expected, "{full}_operators.sql"); + } + } + + #[test] + fn aggregates_files_match_golden() { + let root = repo_root(); + let s = spec("int4"); + for d in s.domains { + if let Some(actual) = render_aggregates_file("int4", d) { + let full = full_name("int4", d.suffix); + let path = root.join(format!( + "tests/codegen/reference/int4/{full}_aggregates.sql" + )); + let expected = strip_reference_marker(&fs::read_to_string(&path).unwrap()); + assert_eq!(actual, expected, "{full}_aggregates.sql"); + } + } + } + + #[test] + fn generator_matches_int4_reference_golden() { + let root = repo_root(); + let ref_dir = root.join("tests/codegen/reference/int4"); + let s = spec("int4"); + let mut checked = 0; + for entry in fs::read_dir(&ref_dir).expect("reference dir") { + let path = entry.unwrap().path(); + if path.extension().and_then(|e| e.to_str()) != Some("sql") { + continue; + } + let name = path.file_name().unwrap().to_str().unwrap().to_string(); + let expected = strip_reference_marker(&fs::read_to_string(&path).unwrap()); + let actual = rendered_for("int4", &name, s); + assert_eq!( + actual, expected, + "{name}: generator diverged from golden reference" + ); + checked += 1; + } + assert!( + checked >= 11, + "expected >=11 reference SQL files, checked {checked}" + ); + } + + #[test] + fn generate_type_writes_expected_files() { + let d = crate::writer::test_support::tempdir(); + let s = spec("int4"); + let out = d.path().join("int4"); + let written = generate_type(s, &out).unwrap(); + let names: Vec = written + .iter() + .map(|p| p.file_name().unwrap().to_str().unwrap().to_string()) + .collect(); + assert!(names.contains(&"int4_types.sql".to_string())); + for dom in ["int4", "int4_eq", "int4_ord_ore", "int4_ord"] { + assert!(names.contains(&format!("{dom}_functions.sql"))); + assert!(names.contains(&format!("{dom}_operators.sql"))); + } + assert!(!names.contains(&"int4_aggregates.sql".to_string())); + assert!(!names.contains(&"int4_eq_aggregates.sql".to_string())); + assert!(names.contains(&"int4_ord_ore_aggregates.sql".to_string())); + assert!(names.contains(&"int4_ord_aggregates.sql".to_string())); + assert_eq!(written.len(), 11); + for p in &written { + assert!(fs::read_to_string(p) + .unwrap() + .starts_with(crate::consts::AUTO_GENERATED_HEADER)); + } + } + + #[test] + fn types_file_has_all_four_domains() { + let sql = render_types_file(spec("int4")); + assert!(sql.contains("-- REQUIRE: src/v3/schema.sql")); + for dom in ["int4", "int4_eq", "int4_ord_ore", "int4_ord"] { + assert!( + sql.contains(&format!("CREATE DOMAIN eql_v3.{dom} AS jsonb")), + "missing {dom}" + ); + } + } + + #[test] + fn storage_functions_file_is_all_blockers() { + let s = spec("int4"); + let sql = render_functions_file(s.token, domain(s, "")); + assert_eq!(sql.matches("CREATE FUNCTION").count(), 44); + assert!(!sql.contains("SET search_path")); + assert_eq!(sql.matches("LANGUAGE plpgsql").count(), 44); + assert_eq!( + sql.matches("LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE") + .count(), + 0 + ); + } + + #[test] + fn eq_functions_file_counts() { + let s = spec("int4"); + let sql = render_functions_file(s.token, domain(s, "_eq")); + assert_eq!(sql.matches("CREATE FUNCTION").count(), 45); + assert!(sql.contains("CREATE FUNCTION eql_v3.eq_term(a eql_v3.int4_eq)")); + assert!(sql.contains("RETURNS eql_v3.hmac_256")); + assert_eq!( + sql.matches("LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE") + .count(), + 7 + ); + assert_eq!(sql.matches("LANGUAGE plpgsql").count(), 38); + assert!(!sql.contains("SET search_path")); + } + + #[test] + fn ore_functions_file_counts() { + let s = spec("int4"); + let sql = render_functions_file(s.token, domain(s, "_ord")); + assert_eq!(sql.matches("CREATE FUNCTION").count(), 45); + assert!(sql.contains("CREATE FUNCTION eql_v3.ord_term(a eql_v3.int4_ord)")); + assert!(sql.contains("RETURNS eql_v3.ore_block_u64_8_256")); + assert_eq!( + sql.matches("LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE") + .count(), + 19 + ); + assert_eq!(sql.matches("LANGUAGE plpgsql").count(), 26); + } + + #[test] + fn operators_file_has_forty_four() { + let s = spec("int4"); + let sql = render_operators_file(s.token, domain(s, "_eq")); + assert_eq!(sql.matches("CREATE OPERATOR").count(), 44); + } + + #[test] + fn aggregates_file_only_for_ord_variants() { + let s = spec("int4"); + assert!(render_aggregates_file(s.token, domain(s, "")).is_none()); + assert!(render_aggregates_file(s.token, domain(s, "_eq")).is_none()); + assert!(render_aggregates_file(s.token, domain(s, "_ord")).is_some()); + assert!(render_aggregates_file(s.token, domain(s, "_ord_ore")).is_some()); + } + + #[test] + fn aggregates_file_carries_min_and_max_and_requires() { + let s = spec("int4"); + let sql = render_aggregates_file(s.token, domain(s, "_ord")).unwrap(); + assert_eq!(sql.matches("CREATE FUNCTION").count(), 2); + assert_eq!(sql.matches("CREATE AGGREGATE").count(), 2); + assert!(sql.contains("eql_v3.min_sfunc")); + assert!(sql.contains("eql_v3.max_sfunc")); + assert!(sql.contains("-- REQUIRE: src/v3/scalars/int4/int4_ord_operators.sql")); + assert!(sql.contains("-- REQUIRE: src/v3/scalars/int4/int4_ord_functions.sql")); + assert!(sql.contains("-- REQUIRE: src/v3/scalars/int4/int4_types.sql")); + } + + #[test] + fn ordered_files_byte_identical_modulo_typename() { + let s = spec("int4"); + let ord = domain(s, "_ord"); + let ore = domain(s, "_ord_ore"); + let norm = |sql: String| sql.replace("int4_ord_ore", "T").replace("int4_ord", "T"); + assert_eq!( + norm(render_functions_file(s.token, ord)), + norm(render_functions_file(s.token, ore)) + ); + assert_eq!( + norm(render_operators_file(s.token, ord)), + norm(render_operators_file(s.token, ore)) + ); + assert_eq!( + norm(render_aggregates_file(s.token, ord).unwrap()), + norm(render_aggregates_file(s.token, ore).unwrap()) + ); + } + + // --- Coarsened footgun invariant guards (whole-file scans) --- + + #[test] + fn blockers_are_never_strict_and_always_plpgsql() { + let s = spec("int4"); + // Storage domain functions file is all blockers. + let sql = render_functions_file("int4", domain(s, "")); + // Every CREATE FUNCTION here is a blocker: none may be STRICT, all plpgsql. + assert!(!sql.contains("STRICT"), "blocker marked STRICT"); + assert_eq!( + sql.matches("CREATE FUNCTION").count(), + sql.matches("LANGUAGE plpgsql").count(), + "every blocker must be LANGUAGE plpgsql" + ); + } + + #[test] + fn inlinable_functions_have_no_set_search_path() { + let s = spec("int4"); + // Extractors and wrappers (eq/ord functions files) are inlinable SQL. + for suffix in ["_eq", "_ord"] { + let sql = render_functions_file("int4", domain(s, suffix)); + // Inlinable rows are the LANGUAGE sql ones; none may pin search_path. + for block in sql.split("CREATE FUNCTION").skip(1) { + if block.contains("LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE") { + assert!( + !block.contains("SET search_path"), + "inlinable SQL function pins search_path" + ); + } + } + } + } + + #[test] + fn aggregate_state_functions_are_plpgsql_not_inlinable() { + let s = spec("int4"); + let sql = render_aggregates_file("int4", domain(s, "_ord")).unwrap(); + assert_eq!(sql.matches("CREATE FUNCTION").count(), 2); + assert_eq!( + sql.matches("LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE") + .count(), + 2 + ); + assert_eq!( + sql.matches("LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE") + .count(), + 0 + ); + } + + #[test] + fn generated_function_like_docs_keep_required_tags() { + let s = spec("int4"); + for d in s.domains { + let sql = render_functions_file("int4", d); + let functions = sql.matches("CREATE FUNCTION").count(); + assert_eq!(sql.matches("--! @return").count(), functions); + assert!( + sql.matches("--! @param").count() >= functions, + "each generated function must keep at least one @param tag" + ); + assert!( + sql.matches("--! @brief").count() >= functions, + "each generated function must keep @brief" + ); + } + + let sql = render_aggregates_file("int4", domain(s, "_ord")).unwrap(); + let function_like = + sql.matches("CREATE FUNCTION").count() + sql.matches("CREATE AGGREGATE").count(); + assert_eq!(sql.matches("--! @return").count(), function_like); + assert!(sql.matches("--! @param").count() >= function_like); + assert!(sql.matches("--! @brief").count() >= function_like); + } + + // --- Escaping guards over the context builders (synthetic inputs) --- + + #[test] + fn unsupported_entry_preserves_operator_literal_and_domain_lit_is_escaped() { + use crate::consts::sql_str; + use crate::context::{unsupported_entry, FnEntry, SqlParam}; + let dom = "eql_v3.o'dom"; + let domain_lit = sql_str(dom); + let entry = unsupported_entry( + "<", + [ + SqlParam { + name: "a", + ty: dom.into(), + }, + SqlParam { + name: "b", + ty: dom.into(), + }, + ], + "boolean", + ); + match entry { + FnEntry::Unsupported { operator_lit, .. } => { + assert_eq!(domain_lit, "eql_v3.o''dom"); // quote doubled by sql_str + assert_eq!(operator_lit, "<"); + } + _ => panic!("expected unsupported-operator entry"), + } + } + + #[test] + fn domain_block_escapes_quote_bearing_name() { + use crate::context::domain_block; + use eql_scalars::DomainSpec; + let block = domain_block( + "int4", + &DomainSpec { + suffix: "_q", + terms: &[], + }, + ); + assert_eq!(block.typname, "int4_q"); // no quote present → unchanged + // keys are sql_str-escaped key tokens; none should carry a bare unescaped quote. + assert!(block.keys.iter().all(|k| !k.contains("o'"))); + } +} diff --git a/crates/eql-codegen/src/lib.rs b/crates/eql-codegen/src/lib.rs new file mode 100644 index 00000000..aada6bb7 --- /dev/null +++ b/crates/eql-codegen/src/lib.rs @@ -0,0 +1,12 @@ +//! Scalar encrypted-domain SQL generator. Renders the `eql-scalars` catalog to +//! the gitignored SQL surface, validated byte-for-byte against the +//! `tests/codegen/reference/int4` golden (modulo the one `-- REFERENCE:` +//! provenance line each reference file carries). The plaintext fixture lists +//! the SQLx matrix consumes live in the catalog itself +//! (`eql_scalars::INT4_VALUES` / `INT2_VALUES`), not in a generated file. + +pub mod consts; +pub mod context; +pub mod generate; +pub mod operator_surface; +pub mod writer; diff --git a/crates/eql-codegen/src/main.rs b/crates/eql-codegen/src/main.rs new file mode 100644 index 00000000..c51bf4c2 --- /dev/null +++ b/crates/eql-codegen/src/main.rs @@ -0,0 +1,44 @@ +use std::path::PathBuf; +use std::process::ExitCode; + +use eql_codegen::generate::generate_all; + +fn repo_root() -> PathBuf { + // The binary runs from the repo root via `cargo run`; CARGO_MANIFEST_DIR + // points at crates/eql-codegen, so the repo root is two parents up. + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .parent() + .unwrap() + .to_path_buf() +} + +fn main() -> ExitCode { + let args: Vec = std::env::args().collect(); + + // `list-types`: print catalog tokens, one per line. Consumed by Plan 3's + // fixtures-all and matrix-inventory enumeration. + if args.len() == 2 && args[1] == "list-types" { + for spec in eql_scalars::CATALOG { + println!("{}", spec.token); + } + return ExitCode::SUCCESS; + } + + if args.len() == 1 { + // No args: generate every type's gitignored SQL surface. + match generate_all(&repo_root()) { + Ok(0) => return ExitCode::SUCCESS, + Ok(_) => return ExitCode::FAILURE, // any non-zero codegen result is a failure + Err(e) => { + eprintln!("error: {e}"); + return ExitCode::FAILURE; + } + } + } + + eprintln!("Usage: eql-codegen (generate all types)"); + eprintln!(" eql-codegen list-types (print catalog tokens)"); + ExitCode::from(2) +} diff --git a/crates/eql-codegen/src/operator_surface.rs b/crates/eql-codegen/src/operator_surface.rs new file mode 100644 index 00000000..38f1ec19 --- /dev/null +++ b/crates/eql-codegen/src/operator_surface.rs @@ -0,0 +1,536 @@ +//! The generated operator surface (port of operator_surface.py). + +/// One operator in the generated surface. +#[derive(Clone, Copy)] +pub struct Operator { + pub symbol: &'static str, + pub function_name: &'static str, + pub signatures: &'static [OperatorSignature], + pub metadata: OperatorMetadata, +} + +/// Optional `CREATE OPERATOR` planner metadata. Pure data — whether it is +/// emitted is a per-domain decision (supported operators only), not a property +/// of the operator's category. +#[derive(Clone, Copy)] +pub struct OperatorMetadata { + pub restrict: Option<&'static str>, + pub join: Option<&'static str>, + pub commutator: Option<&'static str>, + pub negator: Option<&'static str>, +} + +impl OperatorMetadata { + /// Metadata with no planner hints — the common case for operators that carry + /// no commutator/negator/selectivity estimators. + pub const fn none() -> Self { + Self { + restrict: None, + join: None, + commutator: None, + negator: None, + } + } + + /// Render the `CREATE OPERATOR` metadata clause, or `None` when no hint is + /// present (the `@>`/`<@` symmetric-but-empty case collapses to `None`). + pub fn render(self) -> Option { + let mut extras = Vec::new(); + if let Some(c) = self.commutator { + extras.push(format!("COMMUTATOR = {c}")); + } + if let Some(n) = self.negator { + extras.push(format!("NEGATOR = {n}")); + } + if let Some(r) = self.restrict { + extras.push(format!("RESTRICT = {r}")); + } + if let Some(j) = self.join { + extras.push(format!("JOIN = {j}")); + } + (!extras.is_empty()).then(|| extras.join(", ")) + } +} + +/// A type position in a PostgreSQL operator overload. `Domain` renders to the +/// concrete encrypted domain being generated; every other slot renders to a +/// fixed PostgreSQL type name. +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum TypeSlot { + Domain, + Jsonb, + Text, + Integer, + TextArray, + Jsonpath, + Boolean, +} + +impl TypeSlot { + fn render(self, dom: &str) -> String { + match self { + TypeSlot::Domain => dom.to_string(), + TypeSlot::Jsonb => "jsonb".to_string(), + TypeSlot::Text => "text".to_string(), + TypeSlot::Integer => "integer".to_string(), + TypeSlot::TextArray => "text[]".to_string(), + TypeSlot::Jsonpath => "jsonpath".to_string(), + TypeSlot::Boolean => "boolean".to_string(), + } + } +} + +/// One PostgreSQL-shaped operator overload: left/right argument slots and the +/// return slot. +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct OperatorSignature { + pub left: TypeSlot, + pub right: TypeSlot, + pub returns: TypeSlot, +} + +/// An `OperatorSignature` with every slot resolved to a concrete SQL type name. +pub struct RenderedSignature { + pub left: String, + pub right: String, + pub returns: String, +} + +impl OperatorSignature { + pub fn render(self, dom: &str) -> RenderedSignature { + RenderedSignature { + left: self.left.render(dom), + right: self.right.render(dom), + returns: self.returns.render(dom), + } + } +} + +/// Terse constructor for the static signature tables below. +const fn sig(left: TypeSlot, right: TypeSlot, returns: TypeSlot) -> OperatorSignature { + OperatorSignature { + left, + right, + returns, + } +} + +/// Symmetric boolean overloads (`domain`/`jsonb` convenience pairs), shared by +/// `=`, `<>`, `<`, `<=`, `>`, `>=`, `@>`, `<@`. +const BOOL_SYMMETRIC_SIGNATURES: &[OperatorSignature] = &[ + sig(TypeSlot::Domain, TypeSlot::Domain, TypeSlot::Boolean), + sig(TypeSlot::Domain, TypeSlot::Jsonb, TypeSlot::Boolean), + sig(TypeSlot::Jsonb, TypeSlot::Domain, TypeSlot::Boolean), +]; + +/// `->` path-selector overloads (returns the domain). +const ARROW_SIGNATURES: &[OperatorSignature] = &[ + sig(TypeSlot::Domain, TypeSlot::Text, TypeSlot::Domain), + sig(TypeSlot::Domain, TypeSlot::Integer, TypeSlot::Domain), + sig(TypeSlot::Jsonb, TypeSlot::Domain, TypeSlot::Domain), +]; + +/// `->>` path-selector overloads (returns text). +const ARROW_TEXT_SIGNATURES: &[OperatorSignature] = &[ + sig(TypeSlot::Domain, TypeSlot::Text, TypeSlot::Text), + sig(TypeSlot::Domain, TypeSlot::Integer, TypeSlot::Text), + sig(TypeSlot::Jsonb, TypeSlot::Domain, TypeSlot::Text), +]; + +/// `?` key-existence overload. +const HAS_KEY_SIGNATURES: &[OperatorSignature] = + &[sig(TypeSlot::Domain, TypeSlot::Text, TypeSlot::Boolean)]; + +/// `?|` / `?&` any/all-keys overloads. +const HAS_ANY_KEYS_SIGNATURES: &[OperatorSignature] = &[sig( + TypeSlot::Domain, + TypeSlot::TextArray, + TypeSlot::Boolean, +)]; + +/// `@?` / `@@` jsonpath-predicate overloads. +const JSONPATH_SIGNATURES: &[OperatorSignature] = + &[sig(TypeSlot::Domain, TypeSlot::Jsonpath, TypeSlot::Boolean)]; + +/// `#>` path-extract overload (returns jsonb). +const PATH_EXTRACT_JSONB_SIGNATURES: &[OperatorSignature] = + &[sig(TypeSlot::Domain, TypeSlot::TextArray, TypeSlot::Jsonb)]; + +/// `#>>` path-extract overload (returns text). +const PATH_EXTRACT_TEXT_SIGNATURES: &[OperatorSignature] = + &[sig(TypeSlot::Domain, TypeSlot::TextArray, TypeSlot::Text)]; + +/// `-` delete-key overloads. +const DELETE_SIGNATURES: &[OperatorSignature] = &[ + sig(TypeSlot::Domain, TypeSlot::Text, TypeSlot::Jsonb), + sig(TypeSlot::Domain, TypeSlot::Integer, TypeSlot::Jsonb), + sig(TypeSlot::Domain, TypeSlot::TextArray, TypeSlot::Jsonb), +]; + +/// `#-` delete-path overload. +const DELETE_PATH_SIGNATURES: &[OperatorSignature] = + &[sig(TypeSlot::Domain, TypeSlot::TextArray, TypeSlot::Jsonb)]; + +/// `||` concatenation overloads (`domain`/`jsonb` convenience pairs). +const CONCAT_SIGNATURES: &[OperatorSignature] = &[ + sig(TypeSlot::Domain, TypeSlot::Domain, TypeSlot::Jsonb), + sig(TypeSlot::Domain, TypeSlot::Jsonb, TypeSlot::Jsonb), + sig(TypeSlot::Jsonb, TypeSlot::Domain, TypeSlot::Jsonb), +]; + +/// Look up the operator metadata for a symbol. Panics on an unknown symbol — +/// the generator only ever passes catalog symbols, matching Python's KeyError. +pub fn operator(symbol: &str) -> Operator { + OPERATORS + .iter() + .copied() + .find(|o| o.symbol == symbol) + .unwrap_or_else(|| panic!("unknown operator symbol: {symbol}")) +} + +/// The generated SQL function name for an operator symbol (e.g. `eq`, `"->"`). +pub fn operator_function_name(symbol: &str) -> &'static str { + operator(symbol).function_name +} + +/// Comparison-operator metadata (commutator/negator/selectivity estimators). +const fn cmp_metadata( + restrict: &'static str, + join: &'static str, + commutator: &'static str, + negator: &'static str, +) -> OperatorMetadata { + OperatorMetadata { + restrict: Some(restrict), + join: Some(join), + commutator: Some(commutator), + negator: Some(negator), + } +} + +/// The 20-operator catalog. Order is: comparison operators, then path-selector +/// operators, then the remaining native jsonb operators. +pub const OPERATORS: &[Operator] = &[ + Operator { + symbol: "=", + function_name: "eq", + signatures: BOOL_SYMMETRIC_SIGNATURES, + metadata: cmp_metadata("eqsel", "eqjoinsel", "=", "<>"), + }, + Operator { + symbol: "<>", + function_name: "neq", + signatures: BOOL_SYMMETRIC_SIGNATURES, + metadata: cmp_metadata("neqsel", "neqjoinsel", "<>", "="), + }, + Operator { + symbol: "<", + function_name: "lt", + signatures: BOOL_SYMMETRIC_SIGNATURES, + metadata: cmp_metadata("scalarltsel", "scalarltjoinsel", ">", ">="), + }, + Operator { + symbol: "<=", + function_name: "lte", + signatures: BOOL_SYMMETRIC_SIGNATURES, + metadata: cmp_metadata("scalarlesel", "scalarlejoinsel", ">=", ">"), + }, + Operator { + symbol: ">", + function_name: "gt", + signatures: BOOL_SYMMETRIC_SIGNATURES, + metadata: cmp_metadata("scalargtsel", "scalargtjoinsel", "<", "<="), + }, + Operator { + symbol: ">=", + function_name: "gte", + signatures: BOOL_SYMMETRIC_SIGNATURES, + metadata: cmp_metadata("scalargesel", "scalargejoinsel", "<=", "<"), + }, + Operator { + symbol: "@>", + function_name: "contains", + signatures: BOOL_SYMMETRIC_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "<@", + function_name: "contained_by", + signatures: BOOL_SYMMETRIC_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "->", + function_name: "\"->\"", + signatures: ARROW_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "->>", + function_name: "\"->>\"", + signatures: ARROW_TEXT_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "?", + function_name: "\"?\"", + signatures: HAS_KEY_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "?|", + function_name: "\"?|\"", + signatures: HAS_ANY_KEYS_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "?&", + function_name: "\"?&\"", + signatures: HAS_ANY_KEYS_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "@?", + function_name: "\"@?\"", + signatures: JSONPATH_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "@@", + function_name: "\"@@\"", + signatures: JSONPATH_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "#>", + function_name: "\"#>\"", + signatures: PATH_EXTRACT_JSONB_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "#>>", + function_name: "\"#>>\"", + signatures: PATH_EXTRACT_TEXT_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "-", + function_name: "\"-\"", + signatures: DELETE_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "#-", + function_name: "\"#-\"", + signatures: DELETE_PATH_SIGNATURES, + metadata: OperatorMetadata::none(), + }, + Operator { + symbol: "||", + function_name: "\"||\"", + signatures: CONCAT_SIGNATURES, + metadata: OperatorMetadata::none(), + }, +]; + +#[cfg(test)] +mod tests { + use super::*; + + fn rendered_signatures(op: &str) -> Vec<(String, String, String)> { + operator(op) + .signatures + .iter() + .map(|sig| sig.render("eql_v3.int4_ord")) + .map(|sig| (sig.left, sig.right, sig.returns)) + .collect() + } + + #[test] + fn signature_slots_render_for_domain() { + let sig = OperatorSignature { + left: TypeSlot::Domain, + right: TypeSlot::Text, + returns: TypeSlot::Boolean, + }; + let rendered = sig.render("eql_v3.int4_eq"); + assert_eq!(rendered.left, "eql_v3.int4_eq"); + assert_eq!(rendered.right, "text"); + assert_eq!(rendered.returns, "boolean"); + } + + #[test] + fn operator_catalog_carries_postgres_signatures() { + let arrow = operator("->"); + let rendered: Vec<_> = arrow + .signatures + .iter() + .map(|sig| sig.render("eql_v3.int4")) + .map(|sig| (sig.left, sig.right, sig.returns)) + .collect(); + assert_eq!( + rendered, + vec![ + ( + "eql_v3.int4".to_string(), + "text".to_string(), + "eql_v3.int4".to_string() + ), + ( + "eql_v3.int4".to_string(), + "integer".to_string(), + "eql_v3.int4".to_string() + ), + ( + "jsonb".to_string(), + "eql_v3.int4".to_string(), + "eql_v3.int4".to_string() + ), + ] + ); + } + + #[test] + fn equality_signatures_match_existing_symmetric_shapes() { + assert_eq!( + rendered_signatures("="), + vec![ + ( + "eql_v3.int4_ord".into(), + "eql_v3.int4_ord".into(), + "boolean".into() + ), + ("eql_v3.int4_ord".into(), "jsonb".into(), "boolean".into()), + ("jsonb".into(), "eql_v3.int4_ord".into(), "boolean".into()), + ] + ); + } + + #[test] + fn native_jsonb_signatures_match_existing_operator_shapes() { + assert_eq!( + rendered_signatures("||"), + vec![ + ( + "eql_v3.int4_ord".into(), + "eql_v3.int4_ord".into(), + "jsonb".into() + ), + ("eql_v3.int4_ord".into(), "jsonb".into(), "jsonb".into()), + ("jsonb".into(), "eql_v3.int4_ord".into(), "jsonb".into()), + ] + ); + assert_eq!( + rendered_signatures("?|"), + vec![("eql_v3.int4_ord".into(), "text[]".into(), "boolean".into())] + ); + } + + #[test] + fn jsonpath_and_text_array_signatures_render() { + // `@?` carries the jsonpath slot and `#>`/`#>>` carry the text[] slot — + // the slot kinds not asserted by the symmetric/arrow signature tests. + assert_eq!( + rendered_signatures("@?"), + vec![( + "eql_v3.int4_ord".into(), + "jsonpath".into(), + "boolean".into() + )] + ); + assert_eq!( + rendered_signatures("#>"), + vec![("eql_v3.int4_ord".into(), "text[]".into(), "jsonb".into())] + ); + assert_eq!( + rendered_signatures("#>>"), + vec![("eql_v3.int4_ord".into(), "text[]".into(), "text".into())] + ); + } + + #[test] + fn twenty_operators_total() { + assert_eq!(OPERATORS.len(), 20); + } + + #[test] + fn every_operator_has_signatures() { + assert!( + OPERATORS.iter().all(|o| !o.signatures.is_empty()), + "every catalog operator must declare at least one signature" + ); + } + + #[test] + fn no_like_operators() { + assert!(OPERATORS + .iter() + .all(|o| o.symbol != "~~" && o.symbol != "~~*")); + } + + #[test] + fn function_names() { + assert_eq!(operator_function_name("="), "eq"); + assert_eq!(operator_function_name("<>"), "neq"); + assert_eq!(operator_function_name("<"), "lt"); + assert_eq!(operator_function_name("<="), "lte"); + assert_eq!(operator_function_name(">"), "gt"); + assert_eq!(operator_function_name(">="), "gte"); + assert_eq!(operator_function_name("@>"), "contains"); + assert_eq!(operator_function_name("<@"), "contained_by"); + assert_eq!(operator_function_name("->"), "\"->\""); + assert_eq!(operator_function_name("->>"), "\"->>\""); + assert_eq!(operator_function_name("?"), "\"?\""); + assert_eq!(operator_function_name("?|"), "\"?|\""); + assert_eq!(operator_function_name("?&"), "\"?&\""); + assert_eq!(operator_function_name("@?"), "\"@?\""); + assert_eq!(operator_function_name("@@"), "\"@@\""); + assert_eq!(operator_function_name("#>"), "\"#>\""); + assert_eq!(operator_function_name("#>>"), "\"#>>\""); + assert_eq!(operator_function_name("-"), "\"-\""); + assert_eq!(operator_function_name("#-"), "\"#-\""); + assert_eq!(operator_function_name("||"), "\"||\""); + } + + #[test] + fn selectivity_estimators() { + assert_eq!(operator("=").metadata.restrict, Some("eqsel")); + assert_eq!(operator("=").metadata.join, Some("eqjoinsel")); + assert_eq!(operator("<>").metadata.restrict, Some("neqsel")); + assert_eq!(operator("<").metadata.restrict, Some("scalarltsel")); + assert_eq!(operator("<=").metadata.restrict, Some("scalarlesel")); + assert_eq!(operator(">").metadata.restrict, Some("scalargtsel")); + assert_eq!(operator(">=").metadata.restrict, Some("scalargesel")); + } + + #[test] + fn negators_and_commutators() { + assert_eq!(operator("=").metadata.negator, Some("<>")); + assert_eq!(operator("<>").metadata.negator, Some("=")); + assert_eq!(operator("<").metadata.commutator, Some(">")); + assert_eq!(operator("<").metadata.negator, Some(">=")); + assert_eq!(operator(">=").metadata.commutator, Some("<=")); + } + + #[test] + fn metadata_renders_only_when_present() { + assert_eq!( + operator("=").metadata.render().unwrap(), + "COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel" + ); + assert_eq!(operator("->").metadata.render(), None); + assert_eq!(operator("@>").metadata.render(), None); + } + + #[test] + fn catalog_symbols_match_expected_order() { + let keys: Vec<&str> = OPERATORS.iter().map(|o| o.symbol).collect(); + assert_eq!( + keys, + vec![ + "=", "<>", "<", "<=", ">", ">=", "@>", "<@", "->", "->>", "?", "?|", "?&", "@?", + "@@", "#>", "#>>", "-", "#-", "||" + ] + ); + } +} diff --git a/crates/eql-codegen/src/writer.rs b/crates/eql-codegen/src/writer.rs new file mode 100644 index 00000000..4d310fc8 --- /dev/null +++ b/crates/eql-codegen/src/writer.rs @@ -0,0 +1,268 @@ +//! Ownership-guarded file writer (port of writer.py). + +use std::fs; +use std::io; +use std::path::{Path, PathBuf}; + +use crate::consts::AUTO_GENERATED_HEADER; + +/// First line of the SQL header — the ownership marker. +fn sql_marker() -> &'static str { + AUTO_GENERATED_HEADER.lines().next().unwrap() +} + +/// Raised when the generator would clobber a hand-written file. +#[derive(Debug)] +pub enum WriteError { + Ownership(String), + Io(io::Error), +} + +impl From for WriteError { + fn from(e: io::Error) -> Self { + WriteError::Io(e) + } +} + +impl std::fmt::Display for WriteError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + WriteError::Ownership(m) => write!(f, "{m}"), + WriteError::Io(e) => write!(f, "io error: {e}"), + } + } +} + +fn first_line(path: &Path) -> io::Result { + let content = fs::read_to_string(path)?; + Ok(content + .lines() + .next() + .unwrap_or("") + .trim_end_matches(['\r', '\n']) + .to_string()) +} + +/// True if the file carries the SQL AUTO-GENERATED marker. Port of `is_generated`. +pub fn is_generated(path: &Path) -> bool { + path.is_file() && first_line(path).map(|l| l == sql_marker()).unwrap_or(false) +} + +/// Delete every generated .sql file in `directory`, returning removed paths. +/// Port of `clean_generated_files`. +pub fn clean_generated_files(directory: &Path) -> io::Result> { + if !directory.is_dir() { + return Ok(Vec::new()); + } + let mut paths: Vec = fs::read_dir(directory)? + .filter_map(|e| e.ok().map(|e| e.path())) + .filter(|p| p.extension().and_then(|x| x.to_str()) == Some("sql")) + .collect(); + paths.sort(); + let mut removed = Vec::new(); + for p in paths { + if is_generated(&p) { + fs::remove_file(&p)?; + removed.push(p); + } + } + Ok(removed) +} + +/// Refuse a generation run if any target is hand-written. Port of +/// `ensure_generated_paths_writable`. +pub fn ensure_generated_paths_writable(paths: &[PathBuf]) -> Result<(), WriteError> { + for path in paths { + if path.exists() && !is_generated(path) { + return Err(WriteError::Ownership(format!( + "refusing to overwrite hand-written file: {} (no AUTO-GENERATED header). \ + Remove it by hand if it is a one-time generator-adoption target.", + path.display() + ))); + } + } + Ok(()) +} + +/// Write the rendered SQL `body` to `path`, after refusing to clobber a +/// hand-written file. The SQL templates emit the `-- AUTOMATICALLY GENERATED +/// FILE.` marker as their own first line, so the writer writes `body` verbatim +/// — it does not prepend a header. +pub fn write_generated_file(path: &Path, body: &str) -> Result<(), WriteError> { + ensure_generated_paths_writable(std::slice::from_ref(&path.to_path_buf()))?; + // The template is trusted to carry the ownership marker as its first line, + // but a renderer bug (or a hand-edited template) could drop it — which would + // then defeat `is_generated`/`clean_generated_files`, leaving an unowned file + // the next run refuses to overwrite. Validate the marker before writing. + let first = body + .lines() + .next() + .unwrap_or("") + .trim_end_matches(['\r', '\n']); + if first != sql_marker() { + return Err(WriteError::Ownership(format!( + "refusing to write generated file without the AUTO-GENERATED marker as its \ + first line: {} (expected first line {:?}, got {:?}). The SQL template must \ + emit the marker.", + path.display(), + sql_marker(), + first + ))); + } + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; + } + fs::write(path, body)?; + Ok(()) +} + +#[cfg(test)] +pub(crate) mod test_support { + use std::fs; + use std::path::{Path, PathBuf}; + + pub struct TempDir(PathBuf); + impl TempDir { + pub fn path(&self) -> &Path { + &self.0 + } + } + impl Drop for TempDir { + fn drop(&mut self) { + let _ = fs::remove_dir_all(&self.0); + } + } + pub fn tempdir() -> TempDir { + let mut p = std::env::temp_dir(); + let nanos = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_nanos(); + p.push(format!( + "eql-codegen-test-{nanos}-{:?}", + std::thread::current().id() + )); + fs::create_dir_all(&p).unwrap(); + TempDir(p) + } +} + +#[cfg(test)] +mod tests { + use super::test_support::tempdir as tmp; + use super::*; + + #[test] + fn is_generated_true_for_header() { + let d = tmp(); + let p = d.path().join("x.sql"); + fs::write(&p, format!("{AUTO_GENERATED_HEADER}SELECT 1;\n")).unwrap(); + assert!(is_generated(&p)); + } + + #[test] + fn is_generated_false_for_handwritten() { + let d = tmp(); + let p = d.path().join("x.sql"); + fs::write(&p, "-- REQUIRE: src/schema.sql\nSELECT 1;\n").unwrap(); + assert!(!is_generated(&p)); + } + + #[test] + fn is_generated_true_for_crlf_header() { + let d = tmp(); + let p = d.path().join("x.sql"); + let marker = sql_marker(); + fs::write(&p, format!("{marker}\r\nSELECT 1;\n")).unwrap(); + assert!(is_generated(&p)); + } + + #[test] + fn write_generated_file_writes_rendered_body_verbatim() { + let d = tmp(); + let p = d.path().join("int4_types.sql"); + // The template render carries the marker on line 1; the writer writes it + // through unchanged. + let body = format!("{AUTO_GENERATED_HEADER}DO $$ BEGIN END $$;\n"); + write_generated_file(&p, &body).unwrap(); + let text = fs::read_to_string(&p).unwrap(); + assert_eq!(text, body); + assert!(is_generated(&p)); + } + + #[test] + fn write_rejects_body_without_marker() { + let d = tmp(); + let p = d.path().join("int4_types.sql"); + // A body whose first line is NOT the AUTO-GENERATED marker must be + // rejected — the template is required to emit it. + let body = "-- REQUIRE: src/v3/schema.sql\nDO $$ BEGIN END $$;\n"; + let err = write_generated_file(&p, body).unwrap_err(); + assert!(matches!(err, WriteError::Ownership(_))); + assert!(err.to_string().contains("AUTO-GENERATED marker")); + assert!( + !p.exists(), + "no file should be written when the marker is missing" + ); + } + + #[test] + fn write_refuses_to_overwrite_handwritten() { + let d = tmp(); + let p = d.path().join("int4_types.sql"); + fs::write(&p, "-- REQUIRE: src/schema.sql\n-- hand-written\n").unwrap(); + let err = write_generated_file(&p, "DO $$ BEGIN END $$;\n").unwrap_err(); + assert!(matches!(err, WriteError::Ownership(_))); + assert!(err.to_string().contains("hand-written")); + } + + #[test] + fn preflight_refuses_handwritten_target() { + let d = tmp(); + let generated = d.path().join("int4_types.sql"); + let hand = d.path().join("int4_eq_functions.sql"); + fs::write( + &generated, + format!("{AUTO_GENERATED_HEADER}-- old generated\n"), + ) + .unwrap(); + fs::write(&hand, "-- REQUIRE: src/schema.sql\n-- hand-written\n").unwrap(); + let err = ensure_generated_paths_writable(&[generated.clone(), hand.clone()]).unwrap_err(); + assert!(err.to_string().contains("int4_eq_functions.sql")); + assert!(generated.exists()); + assert!(hand.exists()); + } + + #[test] + fn write_overwrites_existing_generated_file() { + let d = tmp(); + let p = d.path().join("int4_types.sql"); + fs::write(&p, format!("{AUTO_GENERATED_HEADER}-- old content\n")).unwrap(); + write_generated_file(&p, &format!("{AUTO_GENERATED_HEADER}-- new content\n")).unwrap(); + let text = fs::read_to_string(&p).unwrap(); + assert!(text.contains("-- new content")); + assert!(!text.contains("-- old content")); + } + + #[test] + fn clean_removes_only_generated_files() { + let d = tmp(); + let gen1 = d.path().join("int4_eq_functions.sql"); + let gen2 = d.path().join("int4_old_domain_functions.sql"); + let hand = d.path().join("int4_jsonb_extra.sql"); + fs::write(&gen1, format!("{AUTO_GENERATED_HEADER}SELECT 1;\n")).unwrap(); + fs::write(&gen2, format!("{AUTO_GENERATED_HEADER}SELECT 2;\n")).unwrap(); + fs::write(&hand, "-- REQUIRE: src/schema.sql\n-- hand-written\n").unwrap(); + let removed = clean_generated_files(d.path()).unwrap(); + assert!(!gen1.exists()); + assert!(!gen2.exists()); + assert!(hand.exists()); + assert_eq!(removed.len(), 2); + } + + #[test] + fn clean_on_empty_directory() { + let d = tmp(); + assert!(clean_generated_files(d.path()).unwrap().is_empty()); + } +} diff --git a/crates/eql-codegen/templates/aggregates.sql.j2 b/crates/eql-codegen/templates/aggregates.sql.j2 new file mode 100644 index 00000000..d85ab283 --- /dev/null +++ b/crates/eql-codegen/templates/aggregates.sql.j2 @@ -0,0 +1,34 @@ +-- AUTOMATICALLY GENERATED FILE. +{% for r in requires -%} +-- REQUIRE: {{ r }} +{% endfor %} +--! @file encrypted_domain/{{ token }}/{{ name }}_aggregates.sql +--! @brief Aggregates for {{ dom }}. +{% for a in aggregates %} +--! @brief State function for {{ a.name }} on {{ dom }}. +--! @param state {{ dom }} +--! @param value {{ dom }} +--! @return {{ dom }} +CREATE FUNCTION {{ schema }}.{{ a.name }}_sfunc(state {{ dom }}, value {{ dom }}) +RETURNS {{ dom }} +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value {{ a.comparator }} state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief {{ a.name }} aggregate for {{ dom }}. +--! @param input {{ dom }} +--! @return {{ dom }} +CREATE AGGREGATE {{ schema }}.{{ a.name }}({{ dom }}) ( + sfunc = {{ schema }}.{{ a.name }}_sfunc, + stype = {{ dom }}, + combinefunc = {{ schema }}.{{ a.name }}_sfunc, + parallel = safe +); +{% endfor -%} diff --git a/crates/eql-codegen/templates/functions.sql.j2 b/crates/eql-codegen/templates/functions.sql.j2 new file mode 100644 index 00000000..ba4f3a02 --- /dev/null +++ b/crates/eql-codegen/templates/functions.sql.j2 @@ -0,0 +1,9 @@ +-- AUTOMATICALLY GENERATED FILE. +{% for r in requires -%} +-- REQUIRE: {{ r }} +{% endfor %} +--! @file encrypted_domain/{{ token }}/{{ name }}_functions.sql +--! @brief Functions for {{ dom }}. +{% for e in entries %} +{% include "functions/" ~ e.kind|lower ~ ".sql.j2" -%} +{% endfor -%} diff --git a/crates/eql-codegen/templates/functions/extractor.sql.j2 b/crates/eql-codegen/templates/functions/extractor.sql.j2 new file mode 100644 index 00000000..9044f890 --- /dev/null +++ b/crates/eql-codegen/templates/functions/extractor.sql.j2 @@ -0,0 +1,7 @@ +--! @brief Index extractor for {{ dom }}. +--! @param a {{ dom }} +--! @return {{ e.ret }} +CREATE FUNCTION {{ schema }}.{{ e.extractor }}(a {{ dom }}) +RETURNS {{ e.ret }} +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT {{ schema }}.{{ e.ctor }}(a::jsonb) $$; diff --git a/crates/eql-codegen/templates/functions/unsupported.sql.j2 b/crates/eql-codegen/templates/functions/unsupported.sql.j2 new file mode 100644 index 00000000..5ec85aed --- /dev/null +++ b/crates/eql-codegen/templates/functions/unsupported.sql.j2 @@ -0,0 +1,8 @@ +--! @brief Unsupported operator blocker for {{ dom }}. +--! @param {{ e.args[0].name }} {{ e.args[0].ty }} +--! @param {{ e.args[1].name }} {{ e.args[1].ty }} +--! @return {{ e.returns }} +CREATE FUNCTION {{ schema }}.{{ e.function_name }}({{ e.args[0].name }} {{ e.args[0].ty }}, {{ e.args[1].name }} {{ e.args[1].ty }}) +RETURNS {{ e.returns }} IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '{{ e.operator_lit }}', '{{ domain_lit }}'; END; $$ +LANGUAGE plpgsql; diff --git a/crates/eql-codegen/templates/functions/wrapper.sql.j2 b/crates/eql-codegen/templates/functions/wrapper.sql.j2 new file mode 100644 index 00000000..1e0b43ac --- /dev/null +++ b/crates/eql-codegen/templates/functions/wrapper.sql.j2 @@ -0,0 +1,7 @@ +--! @brief Operator wrapper for {{ dom }}. +--! @param {{ e.args[0].name }} {{ e.args[0].ty }} +--! @param {{ e.args[1].name }} {{ e.args[1].ty }} +--! @return boolean +CREATE FUNCTION {{ schema }}.{{ e.function_name }}({{ e.args[0].name }} {{ e.args[0].ty }}, {{ e.args[1].name }} {{ e.args[1].ty }}) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT {{ e.call_a }} {{ e.op }} {{ e.call_b }} $$; diff --git a/crates/eql-codegen/templates/operators.sql.j2 b/crates/eql-codegen/templates/operators.sql.j2 new file mode 100644 index 00000000..bb33ff52 --- /dev/null +++ b/crates/eql-codegen/templates/operators.sql.j2 @@ -0,0 +1,13 @@ +-- AUTOMATICALLY GENERATED FILE. +{% for r in requires -%} +-- REQUIRE: {{ r }} +{% endfor %} +--! @file encrypted_domain/{{ token }}/{{ name }}_operators.sql +--! @brief Operators for {{ dom }}. +{% for o in operators %} +CREATE OPERATOR {{ o.symbol }} ( + FUNCTION = {{ schema }}.{{ o.function_name }}, + LEFTARG = {{ o.leftarg }}, RIGHTARG = {{ o.rightarg }}{% if o.metadata %}, + {{ o.metadata }}{% endif %} +); +{% endfor -%} diff --git a/crates/eql-codegen/templates/types.sql.j2 b/crates/eql-codegen/templates/types.sql.j2 new file mode 100644 index 00000000..f46f6616 --- /dev/null +++ b/crates/eql-codegen/templates/types.sql.j2 @@ -0,0 +1,26 @@ +-- AUTOMATICALLY GENERATED FILE. +-- REQUIRE: src/v3/schema.sql + +--! @file v3/scalars/{{ token }}/{{ token }}_types.sql +--! @brief Encrypted-domain types for {{ token }}. + +DO $$ +BEGIN +{%- for d in domains %} + --! @brief Encrypted domain {{ schema }}.{{ d.name }}. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = '{{ d.typname }}' AND typnamespace = '{{ schema }}'::regnamespace + ) THEN + CREATE DOMAIN {{ schema }}.{{ d.name }} AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + {%- for k in d.keys %} + AND VALUE ? '{{ k }}' + {%- endfor %} + AND VALUE->>'v' = '2' + ); + END IF; +{% endfor -%} +END +$$; diff --git a/crates/eql-codegen/tests/parity.rs b/crates/eql-codegen/tests/parity.rs new file mode 100644 index 00000000..a0f1e3b1 --- /dev/null +++ b/crates/eql-codegen/tests/parity.rs @@ -0,0 +1,113 @@ +//! THE PARITY GATE. Runs the Rust generator (into a temp dir) and asserts the +//! int4 SQL surface is byte-for-byte equal to the `tests/codegen/reference/int4` +//! golden (modulo the one leading `-- REFERENCE:` provenance line). The golden +//! reference — not the retired Python generator — is the sole oracle. The +//! plaintext fixture lists are not generated; they live in the catalog +//! (`eql_scalars::INT4_VALUES` / `INT2_VALUES`) and are pinned by +//! `eql-scalars`'s own `values_tests`. + +use std::fs; +use std::path::PathBuf; + +fn repo_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .parent() + .unwrap() + .to_path_buf() +} + +fn tempdir(tag: &str) -> PathBuf { + let mut p = std::env::temp_dir(); + let nanos = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_nanos(); + p.push(format!("eql-parity-{tag}-{nanos}")); + fs::create_dir_all(&p).unwrap(); + p +} + +#[test] +fn rust_generator_matches_int4_golden_files() { + let root = repo_root(); + let out = tempdir("rust-golden"); + eql_codegen::generate::generate_all(&out).expect("rust generate_all"); + + let ref_dir = root.join("tests/codegen/reference/int4"); + let gen_dir = out.join("src/v3/scalars/int4"); + + // Assert the generated .sql file SET matches the reference set first — the + // per-file byte comparison below only iterates reference files, so a missing + // generated file (or an extra one the reference never pins) would otherwise + // pass silently. + let sql_names = |dir: &std::path::Path| -> Vec { + let mut names: Vec = fs::read_dir(dir) + .unwrap() + .filter_map(|e| e.ok().map(|e| e.path())) + .filter(|p| p.extension().and_then(|x| x.to_str()) == Some("sql")) + .map(|p| p.file_name().unwrap().to_str().unwrap().to_string()) + .collect(); + names.sort(); + names + }; + let ref_names = sql_names(&ref_dir); + let gen_names = sql_names(&gen_dir); + assert_eq!( + gen_names, ref_names, + "generated int4 .sql file set differs from golden reference set \ + (reference: {ref_names:?}, generated: {gen_names:?})" + ); + + for entry in fs::read_dir(&ref_dir).unwrap() { + let path = entry.unwrap().path(); + if path.extension().and_then(|e| e.to_str()) != Some("sql") { + continue; + } + let name = path.file_name().unwrap().to_str().unwrap(); + let reference = fs::read_to_string(&path).unwrap(); + // Strip the leading `-- REFERENCE:` provenance line(s), preserving the + // remaining bytes verbatim (`split_inclusive` keeps the `\n` + // terminators). What remains is the generated body, which already starts + // with the template-owned `-- AUTOMATICALLY GENERATED FILE.` marker — the + // same first line the materialised file carries — so the comparison is + // byte-for-byte with no header re-added. + let expected: String = reference + .split_inclusive('\n') + .skip_while(|l| l.starts_with("-- REFERENCE:") || l.starts_with("// REFERENCE:")) + .collect(); + let actual = fs::read_to_string(gen_dir.join(name)).unwrap(); + assert_eq!( + actual, expected, + "{name}: materialised output differs from golden" + ); + } +} + +/// Both Rust strippers (the in-crate `strip_reference_marker` and this file's +/// golden test) skip a variable number of leading `-- REFERENCE:` lines, while +/// the shell gate skips exactly one with `tail -n +2`. They agree only while +/// every reference file carries exactly one marker line — make that explicit. +#[test] +fn every_reference_file_has_exactly_one_marker_line() { + let root = repo_root(); + let dir = root.join("tests/codegen/reference/int4"); + for entry in fs::read_dir(&dir).unwrap() { + let path = entry.unwrap().path(); + let ext = path.extension().and_then(|e| e.to_str()); + if ext != Some("sql") && ext != Some("rs") { + continue; + } + let text = fs::read_to_string(&path).unwrap(); + let markers = text + .lines() + .take_while(|l| l.starts_with("-- REFERENCE:") || l.starts_with("// REFERENCE:")) + .count(); + assert_eq!( + markers, 1, + "{}: expected exactly 1 leading REFERENCE marker line (shell `tail -n +2` assumes one); found {markers}", + path.display() + ); + } +} diff --git a/crates/eql-scalars/Cargo.toml b/crates/eql-scalars/Cargo.toml new file mode 100644 index 00000000..093b1a12 --- /dev/null +++ b/crates/eql-scalars/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "eql-scalars" +version = "0.1.0" +edition = "2021" +description = "Scalar/term catalog for EQL encrypted-domain codegen (std-only, no deps)." + +# INTENTIONALLY no dependencies. This crate must stay std-only so the future +# generator (eql-codegen) compiles in ~1-2s and never drags serde/toml onto the +# SQL build's critical path. Do not add deps here. +[dependencies] diff --git a/crates/eql-scalars/src/lib.rs b/crates/eql-scalars/src/lib.rs new file mode 100644 index 00000000..b5a362c7 --- /dev/null +++ b/crates/eql-scalars/src/lib.rs @@ -0,0 +1,1189 @@ +//! Scalar/term catalog for EQL encrypted-domain codegen — the Rust source of +//! truth replacing `tasks/codegen/{scalars,terms,spec}.py` and the +//! `types/*.toml` manifests. Std-only, no dependencies. +//! +//! `Fixture` is value-kind tagged (one non-generic enum, variant = value kind), +//! so a single `CATALOG` spans every scalar kind. Integer literals are +//! range-checked at their definition site by `fixtures!` (`N(-40000)` for `i16` +//! does not compile). +//! +//! Capability axes are independent: equality covers every kind; order covers +//! every kind except `jsonb` (ORE compares ciphertext, so it is +//! plaintext-agnostic — `text`/`date` order like integers); only the integer +//! kinds have an i128 range with `Min`/`Max`/`Zero` sentinels. `numeric_value` +//! cannot yet express the order of a non-integer fixture set. +//! +//! Public names are consumed verbatim by the later codegen plans — do not rename. + +/// The fixed-width integer kinds — exactly those scalar kinds with an `i128` +/// range and `MIN`/`MAX`/`Zero` sentinels. These accessors are **total**: every +/// variant answers every method. Non-integer kinds (`Numeric`/`Text`/`Jsonb`/ +/// `Date`) are simply not representable here, so there is no partial function to +/// panic — `ScalarKind::Date` cannot call `min_symbol()` because `Date` is not a +/// `BoundedIntKind`. Reach this type from a `ScalarKind` via +/// [`ScalarKind::as_bounded_int`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum BoundedIntKind { + I16, + I32, + I64, +} + +impl BoundedIntKind { + /// The Rust type name as it appears in generated source (e.g. `"i32"`). + pub const fn rust_type(self) -> &'static str { + match self { + BoundedIntKind::I16 => "i16", + BoundedIntKind::I32 => "i32", + BoundedIntKind::I64 => "i64", + } + } + + /// The `MIN` named-constant symbol (e.g. `"i32::MIN"`). + pub const fn min_symbol(self) -> &'static str { + match self { + BoundedIntKind::I16 => "i16::MIN", + BoundedIntKind::I32 => "i32::MIN", + BoundedIntKind::I64 => "i64::MIN", + } + } + + /// The `MAX` named-constant symbol (e.g. `"i32::MAX"`). + pub const fn max_symbol(self) -> &'static str { + match self { + BoundedIntKind::I16 => "i16::MAX", + BoundedIntKind::I32 => "i32::MAX", + BoundedIntKind::I64 => "i64::MAX", + } + } + + /// The zero literal symbol (always `"0"`). + pub const fn zero_symbol(self) -> &'static str { + "0" + } + + /// Inclusive lower bound of the representable range, widened to `i128`. + pub const fn min_value(self) -> i128 { + match self { + BoundedIntKind::I16 => i16::MIN as i128, + BoundedIntKind::I32 => i32::MIN as i128, + BoundedIntKind::I64 => i64::MIN as i128, + } + } + + /// Inclusive upper bound of the representable range, widened to `i128`. + pub const fn max_value(self) -> i128 { + match self { + BoundedIntKind::I16 => i16::MAX as i128, + BoundedIntKind::I32 => i32::MAX as i128, + BoundedIntKind::I64 => i64::MAX as i128, + } + } +} + +/// The native scalar a domain type maps onto. Integer kinds carry i128 bounds; +/// the others (`Numeric`/`Text`/`Jsonb`) have string fixtures and no numeric +/// range — though `Numeric`/`Text` are still ORE-orderable, only `Jsonb` is not. +/// Capability layer only: `CATALOG` declares which kinds actually exist. +/// +/// The bounded-numeric accessors live on the total [`BoundedIntKind`], reached +/// via [`ScalarKind::as_bounded_int`]; non-integer kinds have no such accessor, +/// so misuse is a compile error rather than a runtime panic. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ScalarKind { + I16, + I32, + I64, + Numeric, + Text, + Jsonb, + /// Calendar date (`chrono::NaiveDate`). Ordered like the integer kinds via + /// ORE, but string-backed (ISO-8601) at the catalog layer and with no i128 + /// range — so it is *not* `is_int()` and `as_bounded_int()` returns `None` + /// for it, like the other non-integer kinds. The bounded-numeric accessors + /// live on `BoundedIntKind`, which `Date` cannot be, so they are + /// unreachable for it by construction rather than by a runtime panic. + Date, +} + +impl ScalarKind { + /// The fixed-width integer kinds — those with `i128` bounds and + /// `Min`/`Max`/`Zero` sentinels — projected onto [`BoundedIntKind`], or + /// `None` for the non-integer kinds. The single boundary where "this kind has + /// bounds" is decided; the bounded accessors live on `BoundedIntKind` and are + /// total there. NOT an orderability test: `Numeric`/`Text`/`Date` are + /// ORE-orderable yet not integers. + pub const fn as_bounded_int(self) -> Option { + match self { + ScalarKind::I16 => Some(BoundedIntKind::I16), + ScalarKind::I32 => Some(BoundedIntKind::I32), + ScalarKind::I64 => Some(BoundedIntKind::I64), + ScalarKind::Numeric | ScalarKind::Text | ScalarKind::Jsonb | ScalarKind::Date => None, + } + } + + /// True for the fixed-width integer kinds. Gates the bounded-numeric + /// invariants. Equivalent to `self.as_bounded_int().is_some()`. + pub const fn is_int(self) -> bool { + self.as_bounded_int().is_some() + } + + /// The Rust type name as it appears in generated source (e.g. `"i32"`). + pub const fn rust_type(self) -> &'static str { + match self { + ScalarKind::I16 => "i16", + ScalarKind::I32 => "i32", + ScalarKind::I64 => "i64", + ScalarKind::Numeric => "numeric", + ScalarKind::Text => "text", + ScalarKind::Jsonb => "jsonb", + ScalarKind::Date => "chrono::NaiveDate", + } + } +} + +/// A fixed index term known to the scalar materializer. +/// +/// Mirrors `terms.py`'s `TERM_CATALOG`. `Hm` provides equality; `Ore` provides +/// equality plus ordering. The `json_key`/`extractor`/`returns`/`ctor` values +/// are the cross-schema SQL contract and are copied verbatim from `terms.py` — +/// changing one is a generated-SQL behaviour change, not a refactor. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Term { + Hm, + Ore, +} + +impl Term { + /// JSON payload key carrying this term (`"hm"` / `"ob"`). + pub const fn json_key(self) -> &'static str { + match self { + Term::Hm => "hm", + Term::Ore => "ob", + } + } + + /// The generated extractor function name (`"eq_term"` / `"ord_term"`). + pub const fn extractor(self) -> &'static str { + match self { + Term::Hm => "eq_term", + Term::Ore => "ord_term", + } + } + + /// Constructor name for the index-term type (unqualified). + pub const fn ctor(self) -> &'static str { + match self { + Term::Hm => "hmac_256", + Term::Ore => "ore_block_u64_8_256", + } + } + + /// Generated-file role label for a domain whose first term is this one. + pub const fn role(self) -> &'static str { + match self { + Term::Hm => "eq", + Term::Ore => "ord", + } + } + + /// SQL operators this term supports, in catalog order. + pub const fn operators(self) -> &'static [&'static str] { + match self { + Term::Hm => &["=", "<>"], + Term::Ore => &["=", "<>", "<", "<=", ">", ">="], + } + } + + /// SQL `-- REQUIRE:` edges this term pulls in, in catalog order. + pub const fn requires(self) -> &'static [&'static str] { + match self { + Term::Hm => &["src/v3/sem/hmac_256/functions.sql"], + Term::Ore => &[ + "src/v3/sem/ore_block_u64_8_256/functions.sql", + "src/v3/sem/ore_block_u64_8_256/operators.sql", + ], + } + } +} + +impl Term { + /// Stable dedupe — first occurrence wins. The Rust analogue of + /// `terms.py`'s `dict.fromkeys` ordering contract. + fn dedupe_preserving_order<'a>(items: impl IntoIterator) -> Vec<&'a str> { + let mut out: Vec<&'a str> = Vec::new(); + for item in items { + if !out.contains(&item) { + out.push(item); + } + } + out + } + + /// Supported operators for the union of a domain's terms (catalog order, + /// deduped). Mirrors `terms.py::operators_for_terms`. + pub fn operators_for_terms(terms: &[Term]) -> Vec<&'static str> { + Self::dedupe_preserving_order(terms.iter().flat_map(|t| t.operators().iter().copied())) + } + + /// JSON payload keys required by these terms (deduped, in order). + /// Mirrors `terms.py::term_json_keys`. + pub fn term_json_keys(terms: &[Term]) -> Vec<&'static str> { + Self::dedupe_preserving_order(terms.iter().map(|t| t.json_key())) + } + + /// SQL `-- REQUIRE:` edges needed by these terms (deduped, in order). + /// Mirrors `terms.py::term_requires`. + pub fn term_requires(terms: &[Term]) -> Vec<&'static str> { + Self::dedupe_preserving_order(terms.iter().flat_map(|t| t.requires().iter().copied())) + } + + /// The extractor that supports `op` for a domain carrying `terms`, or + /// `None`. First supporting term wins. Mirrors + /// `terms.py::extractor_for_operator`. + pub fn extractor_for_operator(terms: &[Term], op: &str) -> Option<&'static str> { + terms + .iter() + .find(|t| t.operators().contains(&op)) + .map(|t| t.extractor()) + } + + /// Generated-file role label for a domain with these terms. No terms => + /// `"storage"`; otherwise the first term's role. Mirrors + /// `terms.py::role_for_terms`. + pub fn role_for_terms(terms: &[Term]) -> &'static str { + match terms.first() { + None => "storage", + Some(t) => t.role(), + } + } +} + +/// A single fixture plaintext value, value-kind tagged: `Min`/`Max`/`Zero` are +/// the integer matrix pivots (resolved per-kind); `Int` is an integer literal; +/// `Numeric`/`Text`/`Jsonb` carry rendered string literals. +/// +/// `fixtures!` range-checks `Int` literals at compile time, but a hand-built +/// `Fixture::Int(n)` is not — hence the runtime invariant tests. `Int(MIN)` and +/// `Min` resolve equal but render differently (`"-32768"` vs `"i16::MIN"`). +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Fixture { + Min, + Max, + Zero, + Int(i128), + Numeric(&'static str), + Text(&'static str), + Jsonb(&'static str), + /// An ISO-8601 date string (`"1970-01-01"`). The catalog stays zero-dep, so + /// the string is parsed into a `chrono::NaiveDate` in the SQLx harness, not + /// here. Distinct by literal, like the other string-backed fixtures. + Date(&'static str), +} + +impl Fixture { + /// The integer value for this fixture (`Min`/`Max` -> kind bounds, `Zero` -> + /// 0, `Int(n)` -> n), or `None` for the string-backed kinds. Does not + /// range-check; `every_fixture_value_is_within_kind_bounds` guards the bounds. + /// + /// `const fn` so the `int_values!` materialiser can resolve a whole fixture + /// list into a typed `&'static` array at compile time. + pub const fn numeric_value(self, kind: ScalarKind) -> Option { + match self { + // `?` is not allowed in `const fn`, so match `as_bounded_int()` + // explicitly. A pivot on a non-integer kind resolves to `None`; the + // `pivot_sentinels_only_appear_with_integer_kinds` catalog test + // guarantees that combination never reaches a real `CATALOG` row. + Fixture::Min => match kind.as_bounded_int() { + Some(k) => Some(k.min_value()), + None => None, + }, + Fixture::Max => match kind.as_bounded_int() { + Some(k) => Some(k.max_value()), + None => None, + }, + Fixture::Zero => Some(0), + Fixture::Int(n) => Some(n), + Fixture::Numeric(_) | Fixture::Text(_) | Fixture::Jsonb(_) | Fixture::Date(_) => None, + } + } + + /// Render as a Rust source literal: sentinels -> named constant, `Int` -> the + /// number, string kinds -> a `Debug`-quoted (Rust-escaped, not SQL) literal. + pub fn render_literal(self, kind: ScalarKind) -> String { + const PIVOT_MSG: &str = "Min/Max/Zero fixtures require an integer kind"; + match self { + Fixture::Min => kind + .as_bounded_int() + .expect(PIVOT_MSG) + .min_symbol() + .to_string(), + Fixture::Max => kind + .as_bounded_int() + .expect(PIVOT_MSG) + .max_symbol() + .to_string(), + Fixture::Zero => kind + .as_bounded_int() + .expect(PIVOT_MSG) + .zero_symbol() + .to_string(), + Fixture::Int(n) => n.to_string(), + Fixture::Numeric(s) | Fixture::Text(s) | Fixture::Jsonb(s) | Fixture::Date(s) => { + format!("{s:?}") + } + } + } +} + +/// One generated public domain: a suffix appended to the type token and the +/// fixed index terms it carries. Suffix `""` is the storage-only domain. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DomainSpec { + pub suffix: &'static str, + pub terms: &'static [Term], +} + +/// A scalar encrypted-domain type: its SQL token, native Rust type, generated +/// domains, and fixture plaintext list. The Rust analogue of one `*.toml`. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct ScalarSpec { + pub token: &'static str, + pub kind: ScalarKind, + pub domains: &'static [DomainSpec], + pub fixtures: &'static [Fixture], +} + +impl ScalarSpec { + /// The fully-qualified domain name: `token` + `suffix`. Makes the old + /// "domain name must start with the token" validation structural. + pub fn domain_name(&self, domain: &DomainSpec) -> String { + format!("{}{}", self.token, domain.suffix) + } +} + +/// Domains shared by every ordered-integer scalar, in manifest file order: +/// storage (no terms), `_eq` (hm), `_ord_ore` (ore), `_ord` (ore). +const ORDERED_INT_DOMAINS: &[DomainSpec] = &[ + DomainSpec { + suffix: "", + terms: &[], + }, + DomainSpec { + suffix: "_eq", + terms: &[Term::Hm], + }, + DomainSpec { + suffix: "_ord_ore", + terms: &[Term::Ore], + }, + DomainSpec { + suffix: "_ord", + terms: &[Term::Ore], + }, +]; + +/// Builds a `&[Fixture]`. The `int ;` arm (a tt-muncher over `Min`/`Max`/ +/// `Zero` and `N()`) range-checks each literal against `` at compile +/// time via `const _RANGE_CHECK`, so out-of-range literals do not compile; +/// `text;`/`numeric;`/`jsonb;` wrap string literals. The reject case has no +/// in-crate test (macro isn't exported, no `trybuild` under zero-deps) — verify +/// by hand with a bad `N(..)`. +macro_rules! fixtures { + (int $t:ty; $($body:tt)*) => { fixtures!(@int $t; [] $($body)*) }; + (@int $t:ty; [$($acc:expr),*]) => { &[$($acc),*] }; + (@int $t:ty; [$($acc:expr),*] , $($r:tt)*) => { fixtures!(@int $t; [$($acc),*] $($r)*) }; + (@int $t:ty; [$($acc:expr),*] Min $($r:tt)*) => { fixtures!(@int $t; [$($acc,)* Fixture::Min ] $($r)*) }; + (@int $t:ty; [$($acc:expr),*] Max $($r:tt)*) => { fixtures!(@int $t; [$($acc,)* Fixture::Max ] $($r)*) }; + (@int $t:ty; [$($acc:expr),*] Zero $($r:tt)*) => { fixtures!(@int $t; [$($acc,)* Fixture::Zero] $($r)*) }; + (@int $t:ty; [$($acc:expr),*] N($v:literal) $($r:tt)*) => { + fixtures!(@int $t; [$($acc,)* Fixture::Int({ const _RANGE_CHECK: $t = $v; $v as i128 })] $($r)*) + }; + (text; $($s:literal),* $(,)?) => { &[$(Fixture::Text($s)),*] }; + (numeric; $($s:literal),* $(,)?) => { &[$(Fixture::Numeric($s)),*] }; + (jsonb; $($s:literal),* $(,)?) => { &[$(Fixture::Jsonb($s)),*] }; + (date; $($s:literal),* $(,)?) => { &[$(Fixture::Date($s)),*] }; +} + +/// int4 fixture plaintexts — verbatim from `tasks/codegen/types/int4.toml`. +/// `N(..)` literals are range-checked against `i32` at compile time. +const INT4_FIXTURES: &[Fixture] = fixtures!(int i32; + Min, N(-100), N(-1), Zero, N(1), N(2), N(5), N(10), N(17), N(25), + N(42), N(50), N(100), N(250), N(1000), N(9999), Max); + +/// int2 fixture plaintexts — verbatim from `tasks/codegen/types/int2.toml`. +/// `N(..)` literals are range-checked against `i16` at compile time. +const INT2_FIXTURES: &[Fixture] = fixtures!(int i16; + Min, N(-30000), N(-100), N(-1), Zero, N(1), N(2), N(5), N(10), N(17), + N(25), N(42), N(50), N(100), N(250), N(1000), N(9999), N(30000), Max); + +/// int8 fixture plaintexts — the int4 set plus two values beyond the i32 range +/// (`±5_000_000_000`) so the matrix exercises the full 64-bit width. `N(..)` +/// literals are range-checked against `i64` at compile time. +const INT8_FIXTURES: &[Fixture] = fixtures!(int i64; + Min, N(-5000000000), N(-100), N(-1), Zero, N(1), N(2), N(5), N(10), N(17), + N(25), N(42), N(50), N(100), N(250), N(1000), N(9999), N(5000000000), Max); + +/// date fixture plaintexts — ISO-8601 (`YYYY-MM-DD`) strings, parsed into +/// `chrono::NaiveDate` in the SQLx harness (the catalog stays zero-dep). The +/// three temporal pivots MUST be present verbatim: `"1900-01-01"` (min_pivot), +/// `"1970-01-01"` (zero = `NaiveDate::default()`), and `"2099-12-31"` +/// (max_pivot) — the matrix fetches each one's ciphertext via +/// `fetch_fixture_payload`, which fails loudly if a row is absent. The interior +/// dates span varied years/months so range operators yield distinguishable +/// counts. All distinct. +const DATE_FIXTURES: &[Fixture] = fixtures!(date; + "1900-01-01", "1950-07-15", "1969-12-31", "1970-01-01", "1970-01-02", + "1980-02-29", "1991-11-09", "1999-12-31", "2000-01-01", "2004-02-29", + "2012-06-30", "2016-03-15", "2020-10-21", "2024-02-29", "2038-01-19", + "2099-12-31"); + +const INT4: ScalarSpec = ScalarSpec { + token: "int4", + kind: ScalarKind::I32, + domains: ORDERED_INT_DOMAINS, + fixtures: INT4_FIXTURES, +}; + +const INT2: ScalarSpec = ScalarSpec { + token: "int2", + kind: ScalarKind::I16, + domains: ORDERED_INT_DOMAINS, + fixtures: INT2_FIXTURES, +}; + +const INT8: ScalarSpec = ScalarSpec { + token: "int8", + kind: ScalarKind::I64, + domains: ORDERED_INT_DOMAINS, + fixtures: INT8_FIXTURES, +}; + +/// `date` — an ordered, non-integer scalar. Reuses `ORDERED_INT_DOMAINS` (the +/// four-domain ordered shape is identical to the integer scalars); only the +/// kind and fixtures differ. +/// +/// Public (unlike the integer specs) because the SQLx harness reads +/// `DATE.fixtures` directly to parse the ISO strings into `chrono::NaiveDate` +/// at runtime — there is no `DATE_VALUES` const (chrono is not `const`-friendly +/// and `eql-scalars` stays zero-dep, so no typed slice is materialised here). +pub const DATE: ScalarSpec = ScalarSpec { + token: "date", + kind: ScalarKind::Date, + domains: ORDERED_INT_DOMAINS, + fixtures: DATE_FIXTURES, +}; + +/// The scalar catalog — the single source of truth. Order is significant (it +/// drives generation order). New types are appended as their SQL surface lands. +pub const CATALOG: &[ScalarSpec] = &[INT4, INT2, INT8, DATE]; + +/// Materialise an integer scalar's fixtures into a typed `&'static` slice at +/// compile time. This is the **single-sourced** plaintext list the SQLx test +/// matrix reads via `ScalarType::fixture_values()` and the fixture generator +/// encrypts — derived from the same `CATALOG` row that drives SQL generation, +/// so the oracle cannot drift from the fixture. (It replaces the old generated, +/// committed `tests/sqlx/src/fixtures/_values.rs` — a Rust source of truth no +/// longer needs to round-trip through generated Rust.) +/// +/// Integer kinds only: a non-numeric fixture (`Text`/`Numeric`/`Jsonb`) is a +/// const-eval error, mirroring `numeric_value`'s `None`. +macro_rules! int_values { + ($name:ident, $ty:ty, $spec:expr) => { + #[doc = concat!("Distinct plaintext fixture values for `", stringify!($spec), "`, ")] + #[doc = "materialised from its `CATALOG` row (see `int_values!`)."] + pub const $name: &[$ty] = { + const SPEC: ScalarSpec = $spec; + const N: usize = SPEC.fixtures.len(); + const ARR: [$ty; N] = { + let mut out = [0 as $ty; N]; + let mut i = 0; + while i < N { + out[i] = match SPEC.fixtures[i].numeric_value(SPEC.kind) { + Some(v) => { + // Const-eval bounds check: a fixture value that does + // not fit the narrowed target type would otherwise be + // silently truncated/wrapped by `as`. Make it a + // compile-time error instead. + if v < <$ty>::MIN as i128 || v > <$ty>::MAX as i128 { + panic!(concat!( + "integer scalar fixture value out of range for `", + stringify!($ty), + "`" + )); + } + v as $ty + } + None => panic!("integer scalar fixture must resolve to a number"), + }; + i += 1; + } + out + }; + &ARR + }; + }; +} + +int_values!(INT4_VALUES, i32, INT4); +int_values!(INT2_VALUES, i16, INT2); +int_values!(INT8_VALUES, i64, INT8); + +#[cfg(test)] +mod rust_tests { + use super::*; + + #[test] + fn bounded_int_kind_accessors_are_total() { + assert_eq!(BoundedIntKind::I16.rust_type(), "i16"); + assert_eq!(BoundedIntKind::I16.min_symbol(), "i16::MIN"); + assert_eq!(BoundedIntKind::I16.max_symbol(), "i16::MAX"); + assert_eq!(BoundedIntKind::I16.zero_symbol(), "0"); + assert_eq!(BoundedIntKind::I16.min_value(), -32_768_i128); + assert_eq!(BoundedIntKind::I16.max_value(), 32_767_i128); + + assert_eq!(BoundedIntKind::I32.min_symbol(), "i32::MIN"); + assert_eq!(BoundedIntKind::I32.min_value(), -2_147_483_648_i128); + assert_eq!(BoundedIntKind::I32.max_value(), 2_147_483_647_i128); + + assert_eq!(BoundedIntKind::I64.max_symbol(), "i64::MAX"); + assert_eq!( + BoundedIntKind::I64.min_value(), + -9_223_372_036_854_775_808_i128 + ); + assert_eq!( + BoundedIntKind::I64.max_value(), + 9_223_372_036_854_775_807_i128 + ); + } + + #[test] + fn as_bounded_int_maps_integer_kinds_only() { + assert_eq!(ScalarKind::I16.as_bounded_int(), Some(BoundedIntKind::I16)); + assert_eq!(ScalarKind::I32.as_bounded_int(), Some(BoundedIntKind::I32)); + assert_eq!(ScalarKind::I64.as_bounded_int(), Some(BoundedIntKind::I64)); + assert_eq!(ScalarKind::Numeric.as_bounded_int(), None); + assert_eq!(ScalarKind::Text.as_bounded_int(), None); + assert_eq!(ScalarKind::Jsonb.as_bounded_int(), None); + assert_eq!(ScalarKind::Date.as_bounded_int(), None); + } + + #[test] + fn i32_facts_match_int4() { + assert_eq!(ScalarKind::I32.rust_type(), "i32"); + let k = ScalarKind::I32 + .as_bounded_int() + .expect("I32 is an integer kind"); + assert_eq!(k.min_symbol(), "i32::MIN"); + assert_eq!(k.max_symbol(), "i32::MAX"); + assert_eq!(k.zero_symbol(), "0"); + assert_eq!(k.min_value(), -2_147_483_648_i128); + assert_eq!(k.max_value(), 2_147_483_647_i128); + } + + #[test] + fn i16_facts_match_int2() { + assert_eq!(ScalarKind::I16.rust_type(), "i16"); + let k = ScalarKind::I16 + .as_bounded_int() + .expect("I16 is an integer kind"); + assert_eq!(k.min_symbol(), "i16::MIN"); + assert_eq!(k.max_symbol(), "i16::MAX"); + assert_eq!(k.zero_symbol(), "0"); + assert_eq!(k.min_value(), -32_768_i128); + assert_eq!(k.max_value(), 32_767_i128); + } + + #[test] + fn is_int_classifies_kinds() { + assert!(ScalarKind::I16.is_int()); + assert!(ScalarKind::I32.is_int()); + assert!(ScalarKind::I64.is_int()); + assert!(!ScalarKind::Numeric.is_int()); + assert!(!ScalarKind::Text.is_int()); + assert!(!ScalarKind::Jsonb.is_int()); + assert!(!ScalarKind::Date.is_int()); + } + + #[test] + fn i64_facts() { + // Capability-layer fact: i64 is the Rust kind a future int8 maps onto. + // Present here so adding int8 later is a pure `CATALOG` append. + assert_eq!(ScalarKind::I64.rust_type(), "i64"); + let k = ScalarKind::I64 + .as_bounded_int() + .expect("I64 is an integer kind"); + assert_eq!(k.min_symbol(), "i64::MIN"); + assert_eq!(k.max_symbol(), "i64::MAX"); + assert_eq!(k.zero_symbol(), "0"); + assert_eq!(k.min_value(), -9_223_372_036_854_775_808_i128); + assert_eq!(k.max_value(), 9_223_372_036_854_775_807_i128); + } + + #[test] + fn date_maps_to_naive_date() { + // Ordered, non-integer kind: it carries a rust type but no i128 range, + // so it is not `is_int()` and `as_bounded_int()` returns `None` — the + // bounded accessors are simply not reachable for it. + assert_eq!(ScalarKind::Date.rust_type(), "chrono::NaiveDate"); + assert!(!ScalarKind::Date.is_int()); + assert_eq!(ScalarKind::Date.as_bounded_int(), None); + } + + /// The structural guarantee that replaces the old runtime panics: a + /// `Min`/`Max`/`Zero` pivot sentinel may only appear in a `CATALOG` row whose + /// kind is an integer kind. `render_literal` would `expect`-panic and + /// `numeric_value` would resolve to `None` for a pivot on a non-integer kind; + /// this test makes such a row a test failure at the source of truth. + #[test] + fn pivot_sentinels_only_appear_with_integer_kinds() { + for spec in CATALOG { + for fixture in spec.fixtures { + if matches!(fixture, Fixture::Min | Fixture::Max | Fixture::Zero) { + assert!( + spec.kind.is_int(), + "pivot sentinel {fixture:?} on non-integer kind {:?} (token `{}`)", + spec.kind, + spec.token, + ); + } + } + } + } +} + +#[cfg(test)] +mod term_tests { + use super::*; + + #[test] + fn hm_term_provides_equality() { + let hm = Term::Hm; + assert_eq!(hm.json_key(), "hm"); + assert_eq!(hm.extractor(), "eq_term"); + assert_eq!(hm.ctor(), "hmac_256"); + assert_eq!(hm.role(), "eq"); + assert_eq!(hm.operators(), &["=", "<>"]); + assert_eq!(hm.requires(), &["src/v3/sem/hmac_256/functions.sql"]); + } + + #[test] + fn ore_term_preserves_int4_sql_contract() { + let ore = Term::Ore; + assert_eq!(ore.json_key(), "ob"); + assert_eq!(ore.extractor(), "ord_term"); + assert_eq!(ore.ctor(), "ore_block_u64_8_256"); + assert_eq!(ore.role(), "ord"); + assert_eq!(ore.operators(), &["=", "<>", "<", "<=", ">", ">="]); + assert_eq!( + ore.requires(), + &[ + "src/v3/sem/ore_block_u64_8_256/functions.sql", + "src/v3/sem/ore_block_u64_8_256/operators.sql", + ] + ); + } +} + +#[cfg(test)] +mod term_helper_tests { + use super::*; + + #[test] + fn operators_are_union_in_catalog_order() { + // ore then hm: ore's six ops first, hm adds nothing new. + assert_eq!( + Term::operators_for_terms(&[Term::Ore, Term::Hm]), + vec!["=", "<>", "<", "<=", ">", ">="] + ); + } + + #[test] + fn operators_for_terms_handles_empty() { + assert!(Term::operators_for_terms(&[]).is_empty()); + } + + #[test] + fn json_keys_come_from_catalog() { + assert_eq!( + Term::term_json_keys(&[Term::Hm, Term::Ore]), + vec!["hm", "ob"] + ); + assert!(Term::term_json_keys(&[]).is_empty()); + } + + #[test] + fn requires_are_deduplicated_in_order() { + assert_eq!( + Term::term_requires(&[Term::Ore, Term::Ore, Term::Hm]), + vec![ + "src/v3/sem/ore_block_u64_8_256/functions.sql", + "src/v3/sem/ore_block_u64_8_256/operators.sql", + "src/v3/sem/hmac_256/functions.sql", + ] + ); + assert!(Term::term_requires(&[]).is_empty()); + } + + #[test] + fn role_for_terms_handles_storage_eq_ord() { + assert_eq!(Term::role_for_terms(&[]), "storage"); + assert_eq!(Term::role_for_terms(&[Term::Hm]), "eq"); + assert_eq!(Term::role_for_terms(&[Term::Ore]), "ord"); + } + + #[test] + fn extractor_for_operator_picks_first_supporting_term() { + assert_eq!( + Term::extractor_for_operator(&[Term::Hm], "="), + Some("eq_term") + ); + assert_eq!( + Term::extractor_for_operator(&[Term::Ore], "<"), + Some("ord_term") + ); + assert_eq!( + Term::extractor_for_operator(&[Term::Hm, Term::Ore], "="), + Some("eq_term") + ); + assert_eq!( + Term::extractor_for_operator(&[Term::Hm, Term::Ore], "<"), + Some("ord_term") + ); + } + + #[test] + fn extractor_for_operator_none_when_unsupported() { + assert_eq!(Term::extractor_for_operator(&[Term::Hm], "<"), None); + assert_eq!(Term::extractor_for_operator(&[], "="), None); + } +} + +#[cfg(test)] +mod fixture_tests { + use super::*; + + #[test] + fn numeric_value_resolves_sentinels_and_literals_for_i32() { + assert_eq!( + Fixture::Min.numeric_value(ScalarKind::I32), + Some(-2_147_483_648) + ); + assert_eq!( + Fixture::Max.numeric_value(ScalarKind::I32), + Some(2_147_483_647) + ); + assert_eq!(Fixture::Zero.numeric_value(ScalarKind::I32), Some(0)); + assert_eq!(Fixture::Int(42).numeric_value(ScalarKind::I32), Some(42)); + assert_eq!(Fixture::Int(-1).numeric_value(ScalarKind::I32), Some(-1)); + } + + #[test] + fn numeric_value_resolves_sentinels_per_kind() { + // Sentinels resolve to the kind's bounds; zero is always 0. + assert_eq!(Fixture::Min.numeric_value(ScalarKind::I16), Some(-32_768)); + assert_eq!(Fixture::Max.numeric_value(ScalarKind::I16), Some(32_767)); + assert_eq!( + Fixture::Min.numeric_value(ScalarKind::I64), + Some(-9_223_372_036_854_775_808) + ); + assert_eq!( + Fixture::Max.numeric_value(ScalarKind::I64), + Some(9_223_372_036_854_775_807) + ); + assert_eq!(Fixture::Zero.numeric_value(ScalarKind::I64), Some(0)); + // `Int` resolves verbatim; no runtime range-check here. + assert_eq!( + Fixture::Int(5_000_000_000).numeric_value(ScalarKind::I64), + Some(5_000_000_000) + ); + } + + #[test] + fn numeric_value_is_none_for_string_variants() { + assert_eq!(Fixture::Text("alice").numeric_value(ScalarKind::Text), None); + assert_eq!( + Fixture::Numeric("3.14").numeric_value(ScalarKind::Numeric), + None + ); + assert_eq!( + Fixture::Jsonb(r#"{"a":1}"#).numeric_value(ScalarKind::Jsonb), + None + ); + assert_eq!( + Fixture::Date("1970-01-01").numeric_value(ScalarKind::Date), + None + ); + } + + #[test] + fn render_literal_maps_sentinels() { + assert_eq!(Fixture::Min.render_literal(ScalarKind::I32), "i32::MIN"); + assert_eq!(Fixture::Max.render_literal(ScalarKind::I32), "i32::MAX"); + assert_eq!(Fixture::Zero.render_literal(ScalarKind::I32), "0"); + assert_eq!(Fixture::Min.render_literal(ScalarKind::I16), "i16::MIN"); + assert_eq!(Fixture::Max.render_literal(ScalarKind::I64), "i64::MAX"); + } + + #[test] + fn render_literal_passes_through_numeric() { + assert_eq!(Fixture::Int(-100).render_literal(ScalarKind::I32), "-100"); + assert_eq!(Fixture::Int(9999).render_literal(ScalarKind::I32), "9999"); + assert_eq!( + Fixture::Int(5_000_000_000).render_literal(ScalarKind::I64), + "5000000000" + ); + } + + #[test] + fn render_literal_quotes_string_variants() { + // String-backed kinds render a valid quoted Rust literal. + assert_eq!( + Fixture::Text("alice").render_literal(ScalarKind::Text), + "\"alice\"" + ); + assert_eq!( + Fixture::Numeric("3.14").render_literal(ScalarKind::Numeric), + "\"3.14\"" + ); + assert_eq!( + Fixture::Jsonb(r#"{"a":1}"#).render_literal(ScalarKind::Jsonb), + r#""{\"a\":1}""# + ); + assert_eq!( + Fixture::Date("1970-01-01").render_literal(ScalarKind::Date), + "\"1970-01-01\"" + ); + } + + #[test] + fn fixtures_macro_builds_each_kind() { + // The int arm range-checks at compile time; sentinels + literals mix. + const INTS: &[Fixture] = fixtures!(int i16; Min, N(-1), Zero, N(30000), Max); + assert_eq!( + INTS, + &[ + Fixture::Min, + Fixture::Int(-1), + Fixture::Zero, + Fixture::Int(30000), + Fixture::Max + ] + ); + // The string arms wrap into the matching variant. + const TEXTS: &[Fixture] = fixtures!(text; "alice", "bob"); + assert_eq!(TEXTS, &[Fixture::Text("alice"), Fixture::Text("bob")]); + const NUMS: &[Fixture] = fixtures!(numeric; "0.1", "-2.5"); + assert_eq!(NUMS, &[Fixture::Numeric("0.1"), Fixture::Numeric("-2.5")]); + const JSONS: &[Fixture] = fixtures!(jsonb; r#"{"a":1}"#); + assert_eq!(JSONS, &[Fixture::Jsonb(r#"{"a":1}"#)]); + const DATES: &[Fixture] = fixtures!(date; "1970-01-01", "2099-12-31"); + assert_eq!( + DATES, + &[Fixture::Date("1970-01-01"), Fixture::Date("2099-12-31")] + ); + } + + #[test] + fn fixtures_macro_handles_degenerate_inputs() { + // Empty list — every arm accepts zero elements. + const NO_INT: &[Fixture] = fixtures!(int i32;); + const NO_TEXT: &[Fixture] = fixtures!(text;); + assert_eq!(NO_INT, &[] as &[Fixture]); + assert_eq!(NO_TEXT, &[] as &[Fixture]); + // Trailing comma — int muncher (leading-comma rule) and string arm `$(,)?`. + const TRAILING_INT: &[Fixture] = fixtures!(int i32; Min, N(1),); + const TRAILING_TEXT: &[Fixture] = fixtures!(text; "a",); + assert_eq!(TRAILING_INT, &[Fixture::Min, Fixture::Int(1)]); + assert_eq!(TRAILING_TEXT, &[Fixture::Text("a")]); + // Sentinels-only, no `N(..)`. + const SENTINELS: &[Fixture] = fixtures!(int i32; Min, Zero, Max); + assert_eq!(SENTINELS, &[Fixture::Min, Fixture::Zero, Fixture::Max]); + } +} + +#[cfg(test)] +mod catalog_tests { + use super::*; + + fn scalar(token: &str) -> &'static ScalarSpec { + CATALOG + .iter() + .find(|s| s.token == token) + .unwrap_or_else(|| panic!("{token} missing from CATALOG")) + } + + #[test] + fn catalog_has_int4_int2_int8_date_in_order() { + let tokens: Vec<&str> = CATALOG.iter().map(|s| s.token).collect(); + assert_eq!(tokens, vec!["int4", "int2", "int8", "date"]); + } + + /// The three temporal matrix pivots must be present verbatim in DATE's + /// fixture strings — `fetch_fixture_payload` fetches each one's ciphertext, + /// failing loudly if absent. The integer `fixtures_include_min_max_and_zero` + /// invariant filters `is_int()` and skips date, so this is its temporal + /// analogue. + #[test] + fn temporal_fixtures_include_pivot_plaintexts() { + let date = scalar("date"); + let strings: Vec<&str> = date + .fixtures + .iter() + .filter_map(|f| match f { + Fixture::Date(s) => Some(*s), + _ => None, + }) + .collect(); + for pivot in ["1900-01-01", "1970-01-01", "2099-12-31"] { + assert!( + strings.contains(&pivot), + "date fixtures missing temporal pivot {pivot}" + ); + } + } + + #[test] + fn all_types_share_the_same_domain_shape() { + // Every scalar declares the same four domains with the same terms; + // only the token differs (the matrix-snapshot collapse depends on this). + // Generic over CATALOG, so it covers every type — including new ones — + // and subsumes the old per-type `_maps_to_*_with_four_domains` / + // `_domain_terms_match_manifest` tests (which only restated the + // catalog literal for one token). + for s in CATALOG { + let shape: Vec<(&str, &[Term])> = + s.domains.iter().map(|d| (d.suffix, d.terms)).collect(); + assert_eq!( + shape, + vec![ + ("", &[] as &[Term]), + ("_eq", &[Term::Hm][..]), + ("_ord_ore", &[Term::Ore][..]), + ("_ord", &[Term::Ore][..]), + ], + "{} has unexpected domain shape", + s.token + ); + } + } + + #[test] + fn every_int_kind_matches_its_rust_type() { + // The kind↔rust-type pairing for every integer scalar, generic over + // CATALOG. Replaces the per-type `_maps_to_iNN` / `_rust_type` + // restatements. + for s in CATALOG.iter().filter(|s| s.kind.is_int()) { + let expected = match s.token { + "int2" => ScalarKind::I16, + "int4" => ScalarKind::I32, + "int8" => ScalarKind::I64, + other => panic!("unmapped integer scalar token {other}"), + }; + assert_eq!(s.kind, expected, "{} maps to the wrong kind", s.token); + } + } + + #[test] + fn domain_name_concatenates_token_and_suffix() { + let s = scalar("int4"); + assert_eq!(s.domain_name(&s.domains[0]), "int4"); // storage + assert_eq!(s.domain_name(&s.domains[1]), "int4_eq"); + assert_eq!(s.domain_name(&s.domains[3]), "int4_ord"); + } +} + +#[cfg(test)] +mod values_tests { + use super::*; + + /// Every materialised `_VALUES` array equals its catalog row's fixtures, + /// resolved per kind, in order. Computed from the fixtures — no hardcoded + /// expected array — so it cannot drift and adding a type needs only one + /// `check(&INTx, INTx_VALUES)` line, not a duplicated golden list. Subsumes + /// the old per-type `_values_materialise_to_typed_array` goldens and + /// `materialised_values_track_their_fixture_lists`. + fn check>(spec: &ScalarSpec, values: &[T]) { + assert_eq!( + values.len(), + spec.fixtures.len(), + "{}: value count != fixture count", + spec.token + ); + for (i, (v, f)) in values.iter().zip(spec.fixtures).enumerate() { + assert_eq!( + (*v).into(), + f.numeric_value(spec.kind) + .expect("integer scalar fixture resolves to a number"), + "{}: value[{i}] does not match resolved fixture {f:?}", + spec.token + ); + } + } + + #[test] + fn materialised_values_match_resolved_fixtures() { + check(&INT4, INT4_VALUES); + check(&INT2, INT2_VALUES); + check(&INT8, INT8_VALUES); + } +} + +#[cfg(test)] +mod invariant_tests { + use super::*; + use std::collections::HashMap; + + #[test] + fn every_domain_name_starts_with_its_token() { + for s in CATALOG { + for d in s.domains { + let name = s.domain_name(d); + assert!( + name == s.token || name.starts_with(&format!("{}_", s.token)), + "{name} does not start with token {}", + s.token + ); + } + } + } + + #[test] + fn every_type_has_at_least_one_domain() { + for s in CATALOG { + assert!(!s.domains.is_empty(), "{} has no domains", s.token); + } + } + + /// Cross-kind distinctness key: integer fixtures dedupe by their resolved + /// number, string-backed fixtures by their literal. Generalises the Python + /// distinct-plaintext contract to every scalar kind. + #[derive(Debug, PartialEq, Eq, Hash)] + enum DistinctKey { + Num(i128), + Str(&'static str), + } + + fn distinct_key(f: Fixture, kind: ScalarKind) -> DistinctKey { + match f { + Fixture::Numeric(s) | Fixture::Text(s) | Fixture::Jsonb(s) | Fixture::Date(s) => { + DistinctKey::Str(s) + } + _ => DistinctKey::Num( + f.numeric_value(kind) + .expect("sentinel/Int fixtures resolve to a number"), + ), + } + } + + #[test] + fn fixtures_include_min_max_and_zero() { + // The MIN/MAX/ZERO pivots are an integer-kind invariant; non-integer + // kinds (text/numeric/jsonb) have no such pivots. + for s in CATALOG.iter().filter(|s| s.kind.is_int()) { + let bk = s + .kind + .as_bounded_int() + .expect("loop is filtered to integer kinds"); + let resolved: Vec = s + .fixtures + .iter() + .filter_map(|f| f.numeric_value(s.kind)) + .collect(); + assert!( + resolved.contains(&bk.min_value()), + "{} fixtures missing MIN", + s.token + ); + assert!( + resolved.contains(&bk.max_value()), + "{} fixtures missing MAX", + s.token + ); + assert!(resolved.contains(&0), "{} fixtures missing zero", s.token); + } + } + + #[test] + fn fixture_values_are_distinct_by_resolved_number() { + for s in CATALOG { + let mut seen: HashMap = HashMap::new(); + for f in s.fixtures { + if let Some(prev) = seen.insert(distinct_key(*f, s.kind), *f) { + panic!("{}: {f:?} duplicates {prev:?}", s.token); + } + } + } + } + + #[test] + fn distinct_key_separates_string_fixtures() { + // CATALOG is int-only, so the `Str` path is otherwise unexercised. + assert_eq!( + distinct_key(Fixture::Text("a"), ScalarKind::Text), + distinct_key(Fixture::Text("a"), ScalarKind::Text) + ); + assert_ne!( + distinct_key(Fixture::Text("a"), ScalarKind::Text), + distinct_key(Fixture::Text("b"), ScalarKind::Text) + ); + assert_eq!( + distinct_key(Fixture::Numeric("x"), ScalarKind::Numeric), + distinct_key(Fixture::Jsonb("x"), ScalarKind::Jsonb) + ); + // Str and Num keys never collide. + assert_ne!( + distinct_key(Fixture::Text("0"), ScalarKind::Text), + distinct_key(Fixture::Zero, ScalarKind::I32) + ); + } + + #[test] + fn every_fixture_value_is_within_kind_bounds() { + // Asserts the resolved sentinels stay within bounds (integer kinds only). + for s in CATALOG.iter().filter(|s| s.kind.is_int()) { + let bk = s + .kind + .as_bounded_int() + .expect("loop is filtered to integer kinds"); + let (lo, hi) = (bk.min_value(), bk.max_value()); + for f in s.fixtures { + let Some(n) = f.numeric_value(s.kind) else { + continue; + }; + assert!( + n >= lo && n <= hi, + "{}: fixture {f:?} resolves to {n}, out of range [{lo}, {hi}]", + s.token + ); + } + } + } + + #[test] + fn helper_outputs_match_for_known_domains() { + // Cross-check the Term helpers against a known domain shape on int4. + let s = CATALOG.iter().find(|s| s.token == "int4").unwrap(); + // storage domain: no terms. + assert_eq!(Term::role_for_terms(s.domains[0].terms), "storage"); + assert!(Term::operators_for_terms(s.domains[0].terms).is_empty()); + // _eq domain: hm => equality only. + assert_eq!(Term::role_for_terms(s.domains[1].terms), "eq"); + assert_eq!( + Term::operators_for_terms(s.domains[1].terms), + vec!["=", "<>"] + ); + assert_eq!(Term::term_json_keys(s.domains[1].terms), vec!["hm"]); + // _ord domain: ore => full ordering. + assert_eq!(Term::role_for_terms(s.domains[3].terms), "ord"); + assert_eq!( + Term::operators_for_terms(s.domains[3].terms), + vec!["=", "<>", "<", "<=", ">", ">="] + ); + assert_eq!(Term::term_json_keys(s.domains[3].terms), vec!["ob"]); + assert_eq!( + Term::extractor_for_operator(s.domains[3].terms, "<"), + Some("ord_term") + ); + } +} diff --git a/crates/eql-tests-macros/Cargo.toml b/crates/eql-tests-macros/Cargo.toml new file mode 100644 index 00000000..8c352a9a --- /dev/null +++ b/crates/eql-tests-macros/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "eql-tests-macros" +version = "0.1.0" +edition = "2021" +description = "Proc-macros that expand a single scalar-harness list into the per-type SQLx-matrix wiring (ScalarType impls, fixture modules, matrix suites, fixture dispatch)." + +[lib] +proc-macro = true + +[dependencies] +syn = { version = "2", features = ["full"] } +quote = "1" +proc-macro2 = "1" diff --git a/crates/eql-tests-macros/src/lib.rs b/crates/eql-tests-macros/src/lib.rs new file mode 100644 index 00000000..e252bca0 --- /dev/null +++ b/crates/eql-tests-macros/src/lib.rs @@ -0,0 +1,506 @@ +//! Proc-macros that expand one declarative scalar-type list into the per-type +//! SQLx-matrix wiring that used to be hand-maintained across four locations. +//! +//! The list lives once in the `scalar_types!` `macro_rules!` in +//! `tests/sqlx/src/scalar_types.rs`: +//! +//! ```ignore +//! eql_tests::scalar_types! { +//! int4 => i32, +//! int2 => i16, +//! } +//! ``` +//! +//! The harness pieces live in three separate compilation contexts — the +//! `eql-tests` lib, the `encrypted_domain` integration-test binary, and the +//! `generate_all_fixtures` integration-test binary — so no single invocation +//! can emit them all. `scalar_types!` forwards the same list to whichever +//! proc-macro below fits the call site; each parses the list and emits only the +//! items belonging there. The list is the single source of truth; the four +//! emitters are pure functions of it. +//! +//! Each entry is `token => rust_type`: `token` is the Postgres type token +//! (`int4`, also the fixture/domain suffix), `rust_type` is the Rust plaintext +//! type (`i32`). The catalog value const is the upper-cased token plus +//! `_VALUES` (`int4` -> `eql_scalars::INT4_VALUES`). +//! +//! Each emitter is split into a thin `#[proc_macro]` shim and a pure `*_tokens` +//! core so the core is unit-testable without a consumer crate. + +use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; +use quote::{format_ident, quote}; +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::{bracketed, Ident, Token, Type}; + +/// One `token => rust_type` entry, with an optional trailing `[temporal]` flag. +struct ScalarEntry { + /// Postgres type token (`int4`); also the fixture/domain suffix and the + /// matrix `suite` ident. + token: Ident, + /// Rust plaintext type (`i32`). + rust_type: Type, + /// Whether this entry is a **temporal** (chrono-backed) scalar rather than a + /// fixed-width integer. Declared explicitly via a trailing `[temporal]` + /// marker in the dispatch list (`date => chrono::NaiveDate [temporal]`) + /// rather than sniffed from the Rust type path — so a temporal type that + /// isn't chrono-spelled, or a non-temporal type whose path happens to + /// contain `DateTime`, cannot be misclassified. + temporal: bool, +} + +/// The recognised optional entry markers, written in `[brackets]` after the +/// rust type (`date => chrono::NaiveDate [temporal]`). `temporal` is the only +/// one today; a new marker is added here so the accepted set stays a single +/// source of truth — `parse_optional_marker` validates against this slice and +/// the rejection message lists it verbatim. +const SUPPORTED_MARKERS: &[&str] = &["temporal"]; + +/// Parse the optional trailing `[marker]` on a scalar entry, returning whether +/// the `temporal` marker was present. +/// +/// Absent brackets → `false` (an ordinary integer scalar). When brackets are +/// present they must hold exactly one recognised identifier: an unknown marker +/// (`[temporial]`), empty brackets (`[]`), or trailing junk (`[temporal foo]`) +/// are all hard parse errors. The whole point of the explicit marker is that a +/// typo fails loudly rather than silently defaulting an entry to integer, so +/// the parse is strict on every malformed shape, not just unknown names. +fn parse_optional_marker(input: ParseStream) -> syn::Result { + if !input.peek(syn::token::Bracket) { + return Ok(false); + } + let content; + bracketed!(content in input); + + let marker: Ident = content.parse()?; + // Reject anything after the single marker ident (`[temporal foo]`, + // `[temporal, bar]`) — otherwise `bracketed!` would silently drop it. + if !content.is_empty() { + let rest: TokenStream2 = content.parse()?; + return Err(syn::Error::new_spanned( + rest, + "expected a single marker identifier, e.g. `[temporal]`", + )); + } + + let name = marker.to_string(); + if !SUPPORTED_MARKERS.contains(&name.as_str()) { + let supported = SUPPORTED_MARKERS + .iter() + .map(|m| format!("`{m}`")) + .collect::>() + .join(", "); + return Err(syn::Error::new( + marker.span(), + format!("unknown scalar marker `{name}`; supported markers: {supported}"), + )); + } + + // Only `temporal` flips the temporal flag; a future non-temporal marker + // would pass validation above but leave this `false`. + Ok(name == "temporal") +} + +impl Parse for ScalarEntry { + fn parse(input: ParseStream) -> syn::Result { + let token: Ident = input.parse()?; + input.parse::]>()?; + let rust_type: Type = input.parse()?; + let temporal = parse_optional_marker(input)?; + Ok(ScalarEntry { + token, + rust_type, + temporal, + }) + } +} + +impl ScalarEntry { + /// Whether this entry is a **temporal** (chrono-backed) scalar rather than a + /// fixed-width integer, as declared by the `[temporal]` marker. It drives + /// two divergences: + /// + /// 1. The `impl ScalarType` for a temporal scalar is **hand-written** in + /// `scalar_domains.rs` (chrono values can't be a `const` slice and the + /// pivots are explicit sentinels), so `emit_scalar_type_impls` skips it. + /// 2. The integer-only fixture asserts (`::MIN`, `contains(&0)`, + /// `any(|v| v < 0)`) don't typecheck for a date, so `scalar_fixture!` + /// stamps a temporal (pivot-presence) variant instead. + fn is_temporal(&self) -> bool { + self.temporal + } +} + +/// The comma-separated list (optional trailing comma). +struct ScalarList { + entries: Vec, +} + +impl Parse for ScalarList { + fn parse(input: ParseStream) -> syn::Result { + let punctuated = Punctuated::::parse_terminated(input)?; + Ok(ScalarList { + entries: punctuated.into_iter().collect(), + }) + } +} + +/// `int4` -> `INT4_VALUES`, the catalog value const in `eql_scalars`. +fn values_const_ident(token: &Ident) -> Ident { + format_ident!("{}_VALUES", token.to_string().to_uppercase()) +} + +// --------------------------------------------------------------------------- +// Core token generators (pure, unit-testable). +// --------------------------------------------------------------------------- + +/// Emit one `impl ScalarType for ` per entry. See +/// [`emit_scalar_type_impls`]. +fn scalar_type_impls_tokens(list: &ScalarList) -> TokenStream2 { + // Temporal scalars hand-write their `impl ScalarType` (see `is_temporal`); + // only integer scalars get a macro-generated impl. + let impls = list.entries.iter().filter(|e| !e.is_temporal()).map(|e| { + let token_str = e.token.to_string(); + let rust_type = &e.rust_type; + let values = values_const_ident(&e.token); + quote! { + impl ScalarType for #rust_type { + const PG_TYPE: &'static str = #token_str; + + /// The catalog `eql_scalars::*_VALUES` list — the same values + /// the fixture generator encrypts, so the oracle can't drift + /// from the fixture. + fn fixture_values() -> &'static [#rust_type] { + ::eql_scalars::#values + } + + /// Integer scalars pivot on their inherent `MIN`/`MAX` consts; + /// the fixture lists include both (`fixtures!(int …; Min, …, Max)`). + fn min_pivot() -> #rust_type { + <#rust_type>::MIN + } + + fn max_pivot() -> #rust_type { + <#rust_type>::MAX + } + } + } + }); + quote! { #(#impls)* } +} + +/// Emit one `pub mod eql_v2_ { ... }` per entry. See +/// [`emit_scalar_fixture_modules`]. +fn scalar_fixture_modules_tokens(list: &ScalarList) -> TokenStream2 { + let mods = list.entries.iter().map(|e| { + let token_str = e.token.to_string(); + let rust_type = &e.rust_type; + let mod_ident = format_ident!("eql_v2_{}", e.token); + let fixture_name = format!("eql_v2_{}", token_str); + if e.is_temporal() { + // Temporal scalars have no `eql_scalars::_VALUES` const (chrono + // is not `const`-friendly). The values come from the harness + // accessor (`_values()`), and the fixture stamps the + // `temporal` kind so the integer-only signed-extreme asserts are + // replaced by a pivot-presence assert. The accessor name mirrors + // the token (`date` -> `date_values`). + let values_fn = format_ident!("{}_values", e.token); + quote! { + #[doc = concat!("`eql_v2_", #token_str, "` temporal scalar fixture — generated by `scalar_types!`.")] + pub mod #mod_ident { + use crate::scalar_domains::#values_fn as values; + crate::scalar_fixture!(temporal, #fixture_name, #rust_type, values()); + } + } + } else { + let values = values_const_ident(&e.token); + quote! { + #[doc = concat!("`eql_v2_", #token_str, "` scalar fixture — generated by `scalar_types!`.")] + pub mod #mod_ident { + use ::eql_scalars::#values as VALUES; + // `scalar_fixture!` is `#[macro_export]`ed by `eql-tests`; + // these modules expand into that lib, so `crate::` resolves it. + crate::scalar_fixture!(int, #fixture_name, #rust_type, VALUES); + } + } + } + }); + quote! { #(#mods)* } +} + +/// Emit the `generate_for_token` dispatch fn. See [`emit_fixture_dispatch`]. +fn fixture_dispatch_tokens(list: &ScalarList) -> TokenStream2 { + let arms = list.entries.iter().map(|e| { + let token_str = e.token.to_string(); + let mod_ident = format_ident!("eql_v2_{}", e.token); + quote! { + #token_str => ::eql_tests::fixtures::#mod_ident::spec().run().await, + } + }); + quote! { + /// Map a catalog token to its fixture generator and run it. A token in + /// the catalog but absent from the harness list hits the catch-all and + /// fails loudly, so a new scalar type can't silently skip generation. + async fn generate_for_token(token: &str) -> anyhow::Result<()> { + match token { + #(#arms)* + other => anyhow::bail!( + "no fixture generator wired for catalog token '{other}'. \ + Add it to the scalar_types! list (tests/sqlx/src/scalar_types.rs). \ + See the encrypted-domain spec §3." + ), + } + } + } +} + +/// Emit one `pub mod { ordered_numeric_matrix! { ... } }` per entry. +/// See [`emit_scalar_matrix_suites`]. +fn scalar_matrix_suites_tokens(list: &ScalarList) -> TokenStream2 { + let mods = list.entries.iter().map(|e| { + let token = &e.token; + let token_str = e.token.to_string(); + let rust_type = &e.rust_type; + let eql_type = format!("eql_v2_{}", token_str); + quote! { + #[doc = concat!("`eql_v2_", #token_str, "` matrix suite — generated by `scalar_types!`.")] + pub mod #token { + ::eql_tests::ordered_numeric_matrix! { + suite = #token, + scalar = #rust_type, + eql_type = #eql_type, + } + } + } + }); + quote! { #(#mods)* } +} + +// --------------------------------------------------------------------------- +// Proc-macro shims. +// --------------------------------------------------------------------------- + +/// Emit one `impl ScalarType for ` per entry. +/// +/// Invoked via `scalar_types!` in `tests/sqlx/src/scalar_domains.rs`, so the +/// impls land in the `eql-tests` lib next to the trait. `PG_TYPE` is the token +/// string; `FIXTURE_VALUES` is the catalog const `eql_scalars::_VALUES`. +#[proc_macro] +pub fn emit_scalar_type_impls(input: TokenStream) -> TokenStream { + let list = syn::parse_macro_input!(input as ScalarList); + scalar_type_impls_tokens(&list).into() +} + +/// Emit one `pub mod eql_v2_ { ... }` per entry. +/// +/// Invoked via `scalar_types!` in `tests/sqlx/src/fixtures/mod.rs`, so the +/// modules land at `crate::fixtures::eql_v2_` — the path the matrix and +/// fixture dispatch reference. Each body is a `use` of the catalog value const +/// plus a `scalar_fixture!` invocation. +#[proc_macro] +pub fn emit_scalar_fixture_modules(input: TokenStream) -> TokenStream { + let list = syn::parse_macro_input!(input as ScalarList); + scalar_fixture_modules_tokens(&list).into() +} + +/// Emit the `generate_for_token` dispatch fn. +/// +/// Invoked via `scalar_types!` in `tests/generate_all_fixtures.rs`. Emits an +/// `async fn generate_for_token(token: &str)` with one match arm per entry plus +/// a loud catch-all, so a catalog token missing from the harness list fails the +/// generator loudly. (The matrix-inventory cross-check enforces the same at +/// test time.) +#[proc_macro] +pub fn emit_fixture_dispatch(input: TokenStream) -> TokenStream { + let list = syn::parse_macro_input!(input as ScalarList); + fixture_dispatch_tokens(&list).into() +} + +/// Emit one `pub mod { ordered_numeric_matrix! { ... } }` per entry. +/// +/// Invoked via `scalar_types!` in +/// `tests/sqlx/tests/encrypted_domain/scalars/mod.rs`, so the matrix suites land +/// in the `encrypted_domain` integration-test binary where `#[sqlx::test]` +/// suites belong. Separate from the lib-side macros because that binary is a +/// different crate target. The emitted test names (`scalars::::matrix_*`) +/// match the old per-type files, so the `matrix_tests.txt` snapshot still holds. +#[proc_macro] +pub fn emit_scalar_matrix_suites(input: TokenStream) -> TokenStream { + let list = syn::parse_macro_input!(input as ScalarList); + scalar_matrix_suites_tokens(&list).into() +} + +#[cfg(test)] +mod tests { + use super::*; + + fn sample() -> ScalarList { + syn::parse_str::("int4 => i32, int8 => i64,").unwrap() + } + + /// Normalize to the `to_string()` form so whitespace differences don't make + /// assertions brittle. + fn norm(ts: &TokenStream2) -> String { + ts.to_string() + } + + #[test] + fn values_const_name_is_uppercased_with_suffix() { + let token: Ident = syn::parse_str("int8").unwrap(); + assert_eq!(values_const_ident(&token).to_string(), "INT8_VALUES"); + } + + #[test] + fn scalar_type_impls_emit_pg_type_and_fixture_values() { + let out = norm(&scalar_type_impls_tokens(&sample())); + // One impl per entry, with the right PG_TYPE string and catalog const. + assert!(out.contains("impl ScalarType for i32")); + assert!(out.contains("impl ScalarType for i64")); + assert!(out.contains(r#"const PG_TYPE : & 'static str = "int4""#)); + assert!(out.contains(r#"const PG_TYPE : & 'static str = "int8""#)); + assert!(out.contains(":: eql_scalars :: INT4_VALUES")); + assert!(out.contains(":: eql_scalars :: INT8_VALUES")); + // const→fn: fixture values is a method now, plus the integer pivots. + assert!(out.contains("fn fixture_values")); + // Assert the emitted pivot bodies, not bare `MIN`/`MAX` substrings: + // the latter also appear in the doc comment, so a loose check would + // pass even if the bodies stopped returning the inherent bounds. + assert!(out.contains("fn min_pivot () -> i32 { < i32 > :: MIN }")); + assert!(out.contains("fn max_pivot () -> i32 { < i32 > :: MAX }")); + assert!(out.contains("fn min_pivot () -> i64 { < i64 > :: MIN }")); + assert!(out.contains("fn max_pivot () -> i64 { < i64 > :: MAX }")); + } + + #[test] + fn fixture_modules_emit_named_mods_with_scalar_fixture() { + let out = norm(&scalar_fixture_modules_tokens(&sample())); + assert!(out.contains("pub mod eql_v2_int4")); + assert!(out.contains("pub mod eql_v2_int8")); + assert!(out.contains("crate :: scalar_fixture !")); + assert!(out.contains(r#""eql_v2_int4""#)); + assert!(out.contains(":: eql_scalars :: INT4_VALUES as VALUES")); + // Integer entries stamp the `int` kind discriminator. + assert!(out.contains("int ,")); + } + + #[test] + fn temporal_entry_skips_impl_and_stamps_temporal_fixture() { + let list = + syn::parse_str::("int4 => i32, date => chrono::NaiveDate [temporal],") + .unwrap(); + // Impl emitter skips the temporal entry (hand-written impl). + let impls = norm(&scalar_type_impls_tokens(&list)); + assert!(impls.contains("impl ScalarType for i32")); + assert!(!impls.contains("NaiveDate")); + // Fixture-module emitter stamps the temporal kind + harness accessor. + let mods = norm(&scalar_fixture_modules_tokens(&list)); + assert!(mods.contains("pub mod eql_v2_date")); + assert!(mods.contains("temporal ,")); + assert!(mods.contains("date_values")); + // Matrix + dispatch emitters include the temporal entry like any other. + let suites = norm(&scalar_matrix_suites_tokens(&list)); + assert!(suites.contains("pub mod date")); + assert!(suites.contains("scalar = chrono :: NaiveDate")); + let dispatch = norm(&fixture_dispatch_tokens(&list)); + assert!(dispatch.contains(r#""date" =>"#)); + } + + /// Parse a single entry, asserting it parses, and return whether it is + /// temporal. Keeps the per-shape assertions below to one line each. + fn parse_entry_is_temporal(src: &str) -> bool { + syn::parse_str::(src) + .unwrap_or_else(|e| panic!("`{src}` should parse: {e}")) + .is_temporal() + } + + /// Parse a single entry expecting a parse error, returning the message. + fn parse_entry_err(src: &str) -> String { + match syn::parse_str::(src) { + Ok(_) => panic!("`{src}` should have failed to parse"), + Err(e) => e.to_string(), + } + } + + #[test] + fn no_marker_is_integer() { + // No brackets → integer, even when the type path mentions chrono: + // temporal-ness is declared, never inferred from the rust type. + assert!(!parse_entry_is_temporal("int4 => i32")); + assert!(!parse_entry_is_temporal("date => chrono::NaiveDate")); + } + + #[test] + fn temporal_marker_sets_the_flag() { + assert!(parse_entry_is_temporal( + "date => chrono::NaiveDate [temporal]" + )); + // Marker binds to its own entry, not the next one, across a list. + let list = + syn::parse_str::("date => chrono::NaiveDate [temporal], int4 => i32,") + .unwrap(); + assert!(list.entries[0].is_temporal()); + assert!(!list.entries[1].is_temporal()); + } + + #[test] + fn unknown_marker_errors_and_lists_the_supported_set() { + let msg = parse_entry_err("date => chrono::NaiveDate [temporial]"); + // Names the offending marker and the supported set, so the message is + // actionable rather than just "parse error". + assert!(msg.contains("unknown scalar marker"), "got: {msg}"); + assert!( + msg.contains("temporial"), + "should name the bad marker: {msg}" + ); + assert!( + msg.contains("`temporal`"), + "should list supported markers: {msg}" + ); + } + + #[test] + fn empty_marker_brackets_error() { + // `[]` has no marker ident to parse — a malformed entry, not a no-op. + let msg = parse_entry_err("date => chrono::NaiveDate []"); + assert!(!msg.is_empty()); + } + + #[test] + fn trailing_junk_in_marker_brackets_errors() { + // Regression guard: `[temporal foo]` / `[temporal, bar]` must NOT be + // silently accepted as `temporal` with the extra tokens dropped. + let msg = parse_entry_err("date => chrono::NaiveDate [temporal foo]"); + assert!(msg.contains("single marker identifier"), "got: {msg}"); + let msg = parse_entry_err("date => chrono::NaiveDate [temporal, bar]"); + assert!(msg.contains("single marker identifier"), "got: {msg}"); + } + + #[test] + fn fixture_dispatch_emits_one_arm_per_token_and_a_catch_all() { + let out = norm(&fixture_dispatch_tokens(&sample())); + assert!(out.contains("async fn generate_for_token")); + assert!(out.contains(r#""int4" =>"#)); + assert!(out.contains(r#""int8" =>"#)); + assert!(out.contains(":: eql_tests :: fixtures :: eql_v2_int4 :: spec")); + // Loud catch-all preserved. + assert!(out.contains("other =>")); + assert!(out.contains("no fixture generator wired")); + } + + #[test] + fn matrix_suites_emit_mods_with_unchanged_suite_and_eql_type() { + let out = norm(&scalar_matrix_suites_tokens(&sample())); + assert!(out.contains("pub mod int4")); + assert!(out.contains("pub mod int8")); + assert!(out.contains(":: eql_tests :: ordered_numeric_matrix !")); + // suite/scalar/eql_type must match the old per-type files so test names + // (and the snapshot) are unchanged. + assert!(out.contains("suite = int4")); + assert!(out.contains("scalar = i32")); + assert!(out.contains(r#"eql_type = "eql_v2_int4""#)); + assert!(out.contains("suite = int8")); + assert!(out.contains("scalar = i64")); + assert!(out.contains(r#"eql_type = "eql_v2_int8""#)); + } +} diff --git a/docs/development/documentation-inventory.md b/docs/development/documentation-inventory.md index bdbe8fd8..e9e89eed 100644 --- a/docs/development/documentation-inventory.md +++ b/docs/development/documentation-inventory.md @@ -77,13 +77,6 @@ Generated: Mon 27 Oct 2025 11:39:50 AEDT ## src/crypto.sql -## src/encrypted/aggregates.sql - -- CREATE FUNCTION eql_v2.min(a eql_v2_encrypted, b eql_v2_encrypted) -- CREATE AGGREGATE eql_v2.min(eql_v2_encrypted) -- CREATE FUNCTION eql_v2.max(a eql_v2_encrypted, b eql_v2_encrypted) -- CREATE AGGREGATE eql_v2.max(eql_v2_encrypted) - ## src/encrypted/casts.sql - CREATE FUNCTION eql_v2.to_encrypted(data jsonb) diff --git a/docs/reference/adding-a-scalar-encrypted-domain-type.md b/docs/reference/adding-a-scalar-encrypted-domain-type.md new file mode 100644 index 00000000..2f95c20c --- /dev/null +++ b/docs/reference/adding-a-scalar-encrypted-domain-type.md @@ -0,0 +1,665 @@ +# Adding a Scalar Encrypted-Domain Type + +The one reference for adding a scalar encrypted-domain type (`int4`, `int2`, +and future ordered numeric scalars). The **top half** (§§1–4) is the path you +follow to add a type; the **reference half** (§§5–7) is the detail behind it — +the generated surface, its invariants, and how the generator itself works. +Read top-down to ship a type; drop into the reference half when something +breaks or you need the *why*. + +A scalar encrypted-domain type is a family of concrete `jsonb` domains in the +**`eql_v3`** schema (`eql_v3.`, `eql_v3._eq`, +`eql_v3._ord`, …), dropped by `DROP SCHEMA eql_v3 CASCADE` and surviving +an `eql_v2` uninstall. Their extractors, comparison wrappers, and MIN/MAX +aggregates also live in `eql_v3`; the searchable-encrypted-metadata (SEM) +index-term types they return (`eql_v3.hmac_256`, +`eql_v3.ore_block_u64_8_256`) are **also `eql_v3`** — hand-written under +`src/v3/sem/`. The whole v3 surface is self-contained: it owns every type it +needs and has no runtime dependency on `eql_v2` (CI gates this — see §6). + +The whole SQL surface is **generated** from a single Rust source of truth: the +`CATALOG` const in [`crates/eql-scalars/src/lib.rs`](../../crates/eql-scalars/src/lib.rs), +rendered by the [`eql-codegen`](../../crates/eql-codegen/) crate. There is no +TOML manifest and no Python — adding a type is adding one `ScalarSpec` row, +validated by the compiler plus catalog `#[test]`s. The reference type is +`eql_v3.int4`. **`text` and `jsonb` are out of scope** for this materializer +(see §7). + +--- + +## 1. TL;DR — the one path + +To add a scalar type `` (e.g. `int8`), with Rust type `` (e.g. `i64`): + +1. **Add a `ScalarSpec` row to `eql_scalars::CATALOG`** — `token`, `kind`, + `domains`, `fixtures` (§2). If the type needs a new scalar width, add a + `ScalarKind` variant first; if it needs new term behaviour, that goes in the + `Term` enum's `impl`, never in catalog data. +2. **Materialise the value list** — `int_values!(_VALUES, , );` + next to `CATALOG`, pinned by a `values_tests` assertion (§2). This is the + single source the SQLx matrix reads; there is no generated `_values.rs`. +3. **Wire the SQLx matrix oracle** — copy the seven small registrations from the + `int4` reference (§3). +4. **Regenerate** — `cargo run -p eql-codegen` (or just `mise run build`, which + runs the generator first). One run regenerates *every* catalog type; there is + no per-type codegen task. The generated `*_{types,functions,operators,aggregates}.sql` + are gitignored and never committed. +5. **Snapshot the matrix inventory** — `mise run test:matrix:inventory` (§3). +6. **Verify** — `mise run test:codegen`, the relevant SQLx suites, and the + PostgreSQL matrix (§4). + +Things you do **not** do: + +- **Don't commit generated SQL.** `*_types.sql` / `*_functions.sql` / + `*_operators.sql` / `*_aggregates.sql` are gitignored; the catalog plus the + renderers are the source of truth. Change the catalog and rebuild — never + hand-edit generated SQL. +- **Don't add a `tests/codegen/reference//` baseline.** `int4` is the sole + golden master (§4). +- **Don't edit `mise.toml`, the CI workflow, `pin_search_path.sql`, or + `splinter.sh`** for an ordinary type — they recognise the generated surface + intrinsically (§5, §6). The exception is a brand-new *term* whose extractor + has a new name (§5). + +Hand-written SQL beyond the fixed surface goes in +`src/v3/scalars//_extensions.sql` with explicit `-- REQUIRE:` edges +— and **that file IS committed** (§5). + +--- + +## 2. The catalog row (`ScalarSpec`) + +A scalar type is one `ScalarSpec` row in +[`crates/eql-scalars/src/lib.rs`](../../crates/eql-scalars/src/lib.rs): + +```rust +ScalarSpec { + token: "int4", + kind: ScalarKind::I32, + domains: &[ + DomainSpec { suffix: "", terms: &[] }, + DomainSpec { suffix: "_eq", terms: &[Term::Hm] }, + DomainSpec { suffix: "_ord_ore", terms: &[Term::Ore] }, + DomainSpec { suffix: "_ord", terms: &[Term::Ore] }, + ], + fixtures: INT4_FIXTURES, +} +``` + +The fields, all enforced by the type system and the catalog `#[test]`s rather +than a runtime validator: + +- **`token`** — the type token (`int4`); supplies `` everywhere. Each + domain's full name is `token` + `suffix` (`ScalarSpec::domain_name`), pinned by + `every_domain_name_starts_with_its_token`. +- **`kind`** — a `ScalarKind` (`I16` / `I32` / `I64` / `Numeric` / `Text` / + `Jsonb` / `Date`), carrying the Rust type name. Only the integer kinds have an + i128 range with `Min`/`Max`/`Zero` sentinels: those bounded accessors + (`min_symbol`/`max_symbol`/`zero_symbol`/`min_value`/`max_value`) live on the + total `BoundedIntKind` sub-enum, reached via `ScalarKind::as_bounded_int() -> + Option`. Non-integer kinds (`Numeric`/`Text`/`Jsonb`/`Date`) + return `None` and simply have no bounded accessor — misuse is a compile error, + not a runtime panic. **If `` needs a new fixed-width integer, add a + `BoundedIntKind` variant** (rust-type name, `MIN`/`MAX`/zero symbols, bounds) + plus its `ScalarKind` variant and `as_bounded_int` arm, with unit tests over + the `impl` methods. +- **`domains`** — a non-empty `&[DomainSpec]` (pinned by + `every_type_has_at_least_one_domain`), each a `suffix` + the fixed `&[Term]` it + carries. The storage domain is `suffix: ""` with no terms; `_eq => [Term::Hm]`; + `_ord` and `_ord_ore => [Term::Ore]`. A `DomainSpec` declares nothing else — no + extractor names, no operator lists, no REQUIRE edges. Every behavioural fact + comes from the `Term` enum. +- **`fixtures`** — the type's plaintext fixture list (see below). + +**Terms** are fixed by the `Term` enum (`crates/eql-scalars/src/lib.rs`). The +`json_key` / `extractor` / `returns` / `ctor` values are the cross-schema SQL +contract — changing one is a generated-SQL behaviour change, not a refactor: + +| Term | JSON key | Extractor | Returns | Operators | +| ----- | -------- | ----------- | -------------------------------- | -------------------------- | +| `Hm` | `hm` | `eq_term` | `eql_v3.hmac_256` | `=` `<>` | +| `Ore` | `ob` | `ord_term` | `eql_v3.ore_block_u64_8_256` | `=` `<>` `<` `<=` `>` `>=` | + +A type that needs a non-ORE equality term on an ordered domain needs a **new +`Term`**, not a catalog flag. Adding a term is a code change to the `Term` +enum's `impl` methods (`json_key`, `extractor`, `returns`, `ctor`, `role`, +`operators`, `requires`) with matching `#[test]`s (`term_tests` / +`term_helper_tests`) — never a free-form catalog field. + +**Twins.** `int4_ord` and `int4_ord_ore` both carry `&[Term::Ore]`. The +generator emits them as independent domains with byte-identical SQL modulo type +name (`ordered_files_byte_identical_modulo_typename`). Twins let callers choose +a name that documents intent ("ordered, regardless of mechanism" vs "ordered via +ORE block") without committing to one term family in a future migration. + +**Order is significant.** The generator iterates `CATALOG` in order (driving +generation order), and iterates each spec's `domains` slice in order — that +order shows up in the generated `_types.sql` `DO` block. Order the slice +the way you want the output to read. + +### Fixtures — single-sourcing the value list + +The `fixtures` field is an ordered `&[Fixture]` — the single source of truth +for the type's plaintext list, consumed by both the SQLx fixture generator and +the matrix oracle. A `Fixture` is value-kind tagged: `Min` / `Max` / `Zero` (the +integer matrix pivots, resolved per-kind), `Int(i128)` (an integer literal), and +`Numeric` / `Text` / `Jsonb` string variants. The `fixtures!` macro +range-checks each `Int` literal against the kind at compile time (`N(-40000)` +for an `i16` kind does not compile): + +```rust +const INT4_FIXTURES: &[Fixture] = fixtures!(int i32; + Min, N(-100), N(-1), Zero, N(1), N(2), N(5), N(10), N(17), N(25), + N(42), N(50), N(100), N(250), N(1000), N(9999), Max); +``` + +Catalog `#[test]`s enforce a **distinct-plaintext contract** plus the +matrix-pivot requirement: + +- `fixture_values_are_distinct_by_resolved_number` rejects duplicates against + the *resolved* value, so both copy-paste dups and sentinel/literal aliases + (`Min` alongside the same number) fail; +- `fixtures_include_min_max_and_zero` requires `Min`, `Max`, and zero for + integer kinds — the matrix uses those three as comparison pivots and fetches + each one's ciphertext from the fixture via `fetch_fixture_payload`, which fails + loudly if the row is absent; +- `every_fixture_value_is_within_kind_bounds` keeps every resolved value in + range. + +These are the compile/test-time analogue of the old `load_spec` validation. +Beyond the pivots, choose values so range operators produce distinguishable +result counts, include useful boundaries, and cover omitted-term negative cases. + +The plaintext list is **not** rendered to a generated file. The `int_values!` +macro (next to `CATALOG`) materialises a `Fixture` list into a typed `pub const +_VALUES: &[]` at compile time (`INT4_VALUES`, `INT2_VALUES`): + +```rust +int_values!(INT4_VALUES, i32, INT4); +``` + +Both consumers reference that single symbol — the fixture generator +(`fixtures::eql_v2_::spec`) and the matrix oracle's `fixture_values()` — so +the oracle cannot drift from the values the generator encrypts. There is no +committed `_values.rs`: a Rust source of truth does not round-trip through +generated Rust. Pin the exact materialised list with a `values_tests` assertion. + +### Temporal kinds — string-backed fixtures and the pivot trait + +A **temporal** scalar (the `date` reference; `timestamptz` follows the same +shape) is *ordered but non-integer*, so it diverges from the integer path in +three places — all in the catalog/harness, never the SQL codegen (domains stay +jsonb-backed and token-driven): + +- **String-backed fixtures.** `eql-scalars` stays zero-dependency, so the + catalog stores ISO strings (`Fixture::Date("1970-01-01")`), not `chrono` + values. There is **no** `int_values!` / `_VALUES` const for a temporal kind + (chrono constructors are not `const`). The SQLx harness parses the catalog + strings into a `LazyLock>` and exposes them via a + `date_values()` accessor; `ScalarType::fixture_values()` returns a borrow of + that. The fixtures must include the three pivot plaintexts verbatim — for + `date`: `"1900-01-01"` (min), `"1970-01-01"` (zero = `NaiveDate::default()`), + `"2099-12-31"` (max) — guarded by `temporal_fixtures_include_pivot_plaintexts`. +- **The pivot trait, not `Self::MIN`/`MAX`.** `ScalarType::fixture_values()` is a + method (not a `const`), and the comparison pivots come from + `ScalarType::min_pivot()` / `max_pivot()` (zero stays `Default::default()`). + Integer impls return `Self::MIN`/`Self::MAX` (emitted by the proc-macro); + temporal impls return explicit sentinel dates and are **hand-written** in + `scalar_domains.rs` (the macro emits only integer impls). `to_sql_literal` is + overridden to single-quote the value (`'1970-01-01'`), since a bare `Display` + date is not a valid SQL literal. +- **The sqlx `chrono` feature.** The test crate enables sqlx's `chrono` feature + (and depends on `chrono` directly) so `Encode`/`Decode`/`Type` resolve for + `NaiveDate`. The integer-only fixture asserts (`::MIN`, `contains(&0)`, + `v < 0`) are stamped only for `int` entries; temporal entries stamp a + pivot-presence assert instead (the `kind` discriminator on `scalar_fixture!`). + +--- + +## 3. Wire the SQLx matrix oracle + +The generated SQL is enough to *install* the domains, but the +`ordered_numeric_matrix!` suite only runs once the Rust harness knows about the +scalar. `` is the scalar's Rust type (`i32` for `int4`, `i16` for `int2`). +There are now **two** registrations: + +| File | Add | +|------|-----| +| `tests/sqlx/src/scalar_types.rs` | One ` => ` line in the `scalar_types!` list (e.g. `int8 => i64,`). This single line drives the `impl ScalarType`, the `eql_v2_` fixture module, the `ordered_numeric_matrix!` suite, and the `generate_for_token` arm — all generated by the `eql-tests-macros` proc-macros. | +| `tests/sqlx/src/fixtures/eql_plaintext.rs` | A sealed `EqlPlaintext` impl for ``: `impl Sealed for {}` and `impl EqlPlaintext for ` carrying just `const KIND: ScalarKind` plus the value-typed `to_plaintext` → the right `Plaintext` variant. `CAST` and `PLAINTEXT_SQL_TYPE` are **derived** from `KIND` via the `cast_for_kind` / `plaintext_sql_type_for_kind` `const fn` defaults, so a brand-new integer kind needs an arm in those two helpers — not a per-type const. Keep the three `#[test]`s (cast / sql-type / to_plaintext) mirroring the existing ones. | + +The single ` => ` line in `scalar_types.rs` is the harness source of +truth. The four code-generators (`emit_scalar_type_impls`, +`emit_scalar_fixture_modules`, `emit_scalar_matrix_suites`, +`emit_fixture_dispatch`) are pure functions of that list, invoked at each call +site via `scalar_types!()`; there are four because proc-macros emit into +the crate/module where they're invoked and the pieces span the `eql-tests` lib, +the `encrypted_domain` test binary, and the `generate_all_fixtures` test binary. +See the `scalar_types.rs` module docs and `crates/eql-tests-macros/src/lib.rs`. + +Forget the harness line and the matrix simply does not run for the type — the +matrix inventory cross-check (below) surfaces it, because the catalog has the +type but the binary has no `scalars::::` tests. A catalog token absent from +the `scalar_types!` list also fails the `generate_for_token` catch-all loudly +at fixture-generation time. + +The coverage these registrations unlock comes from the `ordered_numeric_matrix!` +convention wrapper in `tests/sqlx/src/matrix.rs`: one `impl ScalarType` plus a +single invocation taking `suite`, `scalar`, and `eql_type`. The matrix derives +its comparison pivots — the scalar's `MIN`, `MAX`, and zero +(`Default::default()`) — from the type rather than a hand-written list, so the +invocation carries no pivot argument. Equality-only scalars use the sibling +`eq_only_scalar_matrix!`. The `matrix.rs` module header is the canonical, +current list of the categories the matrix emits (sanity, correctness, +cross-shape, supported-NULL, blocker raises, index engagement, ORDER BY, ORDER +BY USING) — read it rather than duplicating a count here. For ordered `int4`, +keep the assertion that distinct plaintext values produce distinct ORE blocks; +do not add assertions for term behaviour the catalog does not promise. + +### Matrix coverage inventory snapshot + +The *set of test names* the matrix emits is guarded by **one** committed, +token-normalized snapshot at `tests/sqlx/snapshots/matrix_tests.txt` — the +sorted inventory of every `scalars::::*` test name with the type token +replaced by the literal ``. (The per-type `_matrix_tests.txt` files are +gone: they were byte-identical modulo the token, so one canonical set plus a +per-type normalize-and-compare carries the same signal at a fraction of the +committed surface.) This is the guard that catches a silently dropped, renamed, +or `#[cfg]`-gated matrix test — a behaviour the SQLx assertions cannot see (a +deleted test just stops running). The snapshot is a committed test baseline, +**not** gitignored generated SQL. + +`mise run test:matrix:inventory` discovers the present scalar types from the +`encrypted_domain` binary's `--list`, normalizes each type's token to ``, +asserts every type's set equals the canonical snapshot, and cross-checks the +discovered type set against `cargo run -p eql-codegen -- list-types` (the +catalog is the single source). You do **not** edit a per-type snapshot or touch +`mise.toml` / the CI workflow — you only regenerate the one `matrix_tests.txt` +when the macro's emitted name set itself changes. A catalog type missing its +matrix wiring fails the cross-check. The CI `matrix-coverage` job gates it. +**`tests/sqlx/snapshots/README.md` is the source of truth** for the mechanics +(pinned feature set, the catalog cross-check, the CI diff, and when to +regenerate). + +--- + +## 4. Regenerate, snapshot & verify + +Regeneration is deterministic: identical catalog + renderers produce +byte-identical SQL. If `mise run build` produces unexpected output, the change +is in `crates/eql-scalars/src` (catalog/terms) or `crates/eql-codegen/src` +(renderers) — not run-to-run variation. + +Run, in order: + +- `cargo run -p eql-codegen` (optional; refreshes all generated SQL from the + catalog before a full build) +- `mise run test:codegen` (`cargo test -p eql-scalars -p eql-codegen`) +- `mise run test:matrix:inventory` (matrix inventory + catalog cross-check; no + database) +- `mise run clean && mise run build` (regenerates every type's SQL from the + catalog first, then builds the release artefacts — a bare build can leave + stale `release/*.sql`) +- the relevant SQLx suites +- `mise run test` across supported PostgreSQL versions +- `mise run --output prefix test:splinter --postgres 17` after a PostgreSQL 17 + install has built EQL + +The CI codegen job is a prerequisite of the PostgreSQL test matrix, so +generated-SQL drift is caught before database tests run. + +**Why no per-type golden baseline.** Do **not** add a +`tests/codegen/reference//` baseline. `int4` is the sole golden master for +the type-generic generator: the templates are pure token substitution, so a +per-type baseline can only fail where `int4`'s already would. Drift protection +for a new type comes from the `int4` reference (shared templates + `Term` enum), +the catalog `values_tests` pinning the materialised `_VALUES`, the +catalog/generator `#[test]`s, and the `ordered_numeric_matrix!` SQLx suite +(behaviour, not bytes). + +--- + +## 5. The generated surface — what correct output looks like + +This is the contract the generated SQL satisfies. You normally never read it to +*add* a type — read it when a test fails or you're extending the surface. + +### Domains and CHECK constraints + +The generator emits `src/v3/scalars//_types.sql` (gitignored; +materialised on every build) with one idempotent `DO $$ ... $$` block. Every +domain is a concrete domain over `jsonb` in the `eql_v3` schema — **never** +`CREATE DOMAIN a AS b` over another generated domain (PostgreSQL resolves +operators against the underlying base type, bypassing the fixed surface). Each +domain's `CHECK` requires: + +- fixed envelope keys `v` and `i`; +- ciphertext key `c`; +- catalog JSON keys for the listed terms; +- the envelope version value `VALUE->>'v' = '2'`, matching the repo-wide + `eql_v2._encrypted_check_v` rule (`src/encrypted/constraints.sql`). + +So a domain with `&[Term::Ore]` requires `v`, `i`, `c`, and `ob` present, with +`v` pinned to `2`. Beyond key presence and the version value, a malformed term +can still fail later inside its extractor. + +### Extractors, wrappers, and blockers + +Extractor names and return types come from the `Term` enum. Generated extractors +and supported comparison wrappers are inline-friendly SQL functions: + +```sql +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT ... $$; +``` + +They must **not** carry a pinned `search_path` — a `SET` clause disables +inlining and reverts index-backed queries to seq scans. The build tooling +recognises these functions structurally, so the generator emits no +`eql-inline-critical` markers. (Aggregate state functions are the one deliberate +exception — see below.) + +Unsupported operators route to **blockers**, which are `LANGUAGE plpgsql`, +`IMMUTABLE`, `PARALLEL SAFE`, and intentionally **not `STRICT`**: + +- **`plpgsql`, not `sql`.** A `LANGUAGE sql` body is inlinable, and the planner + could elide the call when the result is provably unused (dead `CASE` branch, + folded predicate), letting a blocked operator appear to succeed. `plpgsql` is + opaque to the planner, so the call — and its `RAISE` — always survives. +- **Not `STRICT`.** A `STRICT` blocker lets PostgreSQL skip the body and return + `NULL` on a `NULL` argument, silently bypassing the unsupported-operator + exception. + +### Operators + +Every generated domain declares supported scalar comparison operators plus +blockers for the native `jsonb` operator surface PostgreSQL could otherwise +reach through domain-to-base-type fallback. The surface is a fixed 20 operators +(`crates/eql-codegen/src/operator_surface.rs`, `OPERATORS`), each with its +PostgreSQL-shaped signatures, summing to **44 `CREATE OPERATOR` statements per +domain**: + +| Operators | Forms | +|---|---| +| `=` `<>` `<` `<=` `>` `>=` `@>` `<@` | `(domain, domain)` · `(domain, jsonb)` · `(jsonb, domain)` | +| `->` `->>` | `(domain, text)` · `(domain, integer)` · `(jsonb, domain)` | +| `?` | `(domain, text)` | +| `?\|` `?&` | `(domain, text[])` | +| `@?` `@@` | `(domain, jsonpath)` | +| `#>` `#>>` `#-` | `(domain, text[])` | +| `-` | `(domain, text)` · `(domain, integer)` · `(domain, text[])` | +| `\|\|` | `(domain, domain)` · `(domain, jsonb)` · `(jsonb, domain)` | + +Whether an operator routes to a wrapper or a blocker is a per-domain decision +driven by the domain's terms (`Term::operators_for_terms`), not a property of +the operator. Supported operators are emitted with full planner metadata +(`COMMUTATOR`, `NEGATOR`, `RESTRICT`, `JOIN` selectivity estimators) backing +onto inlinable wrappers; everything else carries minimal metadata backing onto +blockers. Path operators always back onto blockers — neither current term +enables them — and the native `jsonb` operators are blocker-only. + +The wrapper/blocker split per domain (the 44-operator total never moves): + +| Domain terms | Extractors | Wrappers | Blockers | Functions | Operators | +| ---------------- | ---------: | -------: | -------: | --------: | --------: | +| none | 0 | 0 | 44 | 44 | 44 | +| `&[Term::Hm]` | 1 (`eq_term`) | 6 | 38 | 45 | 44 | +| `&[Term::Ore]` | 1 (`ord_term`) | 18 | 26 | 45 | 44 | + +Six wrappers for `Hm` = `=` and `<>` × three shapes; eighteen for `Ore` = six +operators × three shapes. + +**Untyped-literal resolver edge.** PostgreSQL's operator resolver still prefers +the built-in `jsonb` operator for untyped string literals in forms such as +`payload::eql_v3.int4 ? 'c'`. Use typed parameters or explicit casts +(`? 'c'::text`, bound text parameters) to route those forms to the generated +blocker. A live-DB structural guard +(`tests/sqlx/tests/encrypted_domain/family/jsonb_operator_surface.rs`) queries +`pg_operator` for every operator with a `jsonb` argument and asserts the set is +a subset of the enumerated surface, so a future PostgreSQL version that adds a +`jsonb` operator nobody enumerated fails the test rather than silently routing an +encrypted column to native plaintext-`jsonb` semantics. + +### Aggregates + +Each ordered (ord-capable) domain additionally gets a generated +`_aggregates.sql`: two state functions (`eql_v3.min_sfunc`, +`eql_v3.max_sfunc`) and two aggregates (`eql_v3.min()`, +`eql_v3.max()`). Comparison routes through the domain's `<` / `>` +operator (the ORE block term — no decryption). The state functions are `LANGUAGE +plpgsql IMMUTABLE STRICT PARALLEL SAFE` **with** a pinned `SET search_path` — +the one place the "no pinned `search_path`" rule does not apply, because +aggregate transition functions are never index expressions. `STRICT` makes +PostgreSQL seed the running state with the first non-NULL value and skip NULLs, +so an all-NULL group returns NULL. Each `CREATE AGGREGATE` declares +`combinefunc = ` and `parallel = safe`: min/max are associative, so the +state function doubles as the combine function, enabling partial and parallel +aggregation on large `GROUP BY` ORE workloads with no decryption. Storage-only +and equality-only domains have no comparator and emit no aggregate file. + +### Indexing + +Do not create operator classes on generated domains. Index through the +extractor, whose return type already carries a default opclass: + +```sql +CREATE INDEX ... ON table_name USING btree (eql_v3.ord_term(col)); +CREATE INDEX ... ON table_name USING hash (eql_v3.eq_term(col)); +``` + +`ore` depends on `src/v3/sem/ore_block_u64_8_256/functions.sql` and +`src/v3/sem/ore_block_u64_8_256/operators.sql`; `hm` depends on +`src/v3/sem/hmac_256/functions.sql`. + +### Extension files + +Optional hand-written SQL beyond the fixed surface belongs in +`src/v3/scalars//_extensions.sql`. The generator never creates, +lists, headers, or cleans it; it must declare its own `-- REQUIRE:` edges +(usually to `_types.sql` and whichever generated function or operator file it +extends). Use it for cross-domain casts, helper functions, or type-specific +constraints. Unlike the generated siblings, **`_extensions.sql` IS +committed.** (Neither `int4` nor `int2` ships one today.) + +`tasks/pin_search_path.sql` describes the fallback marker for inline-critical +extension functions that take no domain argument and so escape the structural +skip: + +```sql +COMMENT ON FUNCTION eql_v2.my_helper(...) IS 'eql-inline-critical: ...'; +``` + +The generator never emits this marker; every function it produces takes a domain +argument and is covered by the structural skip intrinsically. + +### Invariants the generator enforces + +The generator's job is partly to write SQL and partly to make incorrect SQL +unreachable. Invariants encoded in the renderers / templates and guarded by +`#[test]`s in `crates/eql-codegen/src/generate.rs`: + +- **Blockers are never `STRICT` and always `plpgsql`** — the + unsupported-operator template emits each blocker as `IMMUTABLE PARALLEL SAFE` / + `LANGUAGE plpgsql` without `STRICT` + (`blockers_are_never_strict_and_always_plpgsql`). +- **Wrappers and extractors are inlinable SQL** — `LANGUAGE sql IMMUTABLE STRICT + PARALLEL SAFE`, single-statement `SELECT`, no `SET search_path` + (`inlinable_functions_have_no_set_search_path`). +- **Aggregate state functions are the deliberate exception** — `plpgsql` *with* + a pinned `SET search_path` (`aggregate_state_functions_are_plpgsql_not_inlinable`). +- **SQL-literal injection is structurally prevented** — every interpolated + single-quoted literal passes through `sql_str` + (`crates/eql-codegen/src/consts.rs`), which doubles embedded single quotes. +- **No domain-over-domain** — every domain is `CREATE DOMAIN eql_v3. AS + jsonb` (`types_file_has_all_four_domains`). +- **No operator class on a domain** — the generator emits operators, not + operator classes. +- **Ownership boundary** — `is_generated` recognises owned files by their header + marker; `ensure_generated_paths_writable` refuses to overwrite anything else, + and `clean_generated_files` deletes only marked files + (`crates/eql-codegen/src/writer.rs`). A hand-written file at a generated path + is a hard error, not a silent clobber. + +### Lint and test integration + +Two pieces of build tooling recognise the generated output without per-type +edits: + +- **`tasks/pin_search_path.sql`** — structural skip identifies encrypted-domain + functions by language (`sql`), volatility (`IMMUTABLE`), and a jsonb-backed + `DOMAIN` argument in the `eql_v3` schema. New scalar types need no edit. +- **`tasks/test/splinter.sh`** — name-based allowlist. The converged wrapper / + extractor names (`eq`, `neq`, `lt`, `lte`, `gt`, `gte`, `eq_term`, `ord_term`) + plus the generated `min` / `max` aggregates are already covered by + `eql_v3`-schema entries. A new scalar type inherits coverage; **only a new + term whose extractor has a new name requires a splinter entry.** + +--- + +## 6. Generator internals — the machine + +You need this section only when **modifying the generator itself**, not when +adding a type. + +### Why a generator + +A single scalar type emits several hundred SQL declarations across eleven files: +four domains, three extractors, dozens of wrappers and blockers, 176 `CREATE +OPERATOR` statements (44 per domain), and MIN/MAX aggregates per ordered domain. +The shape is mechanical and the invariants are unforgiving — a `STRICT` blocker +silently bypasses its exception; a pinned `search_path` reverts queries to seq +scans. The generator exists so each new type adds one `CATALOG` row rather than +ninety hand-written declarations that must agree with each other and with +`pin_search_path.sql`, `tasks/test/splinter.sh`, and +`src/v3/scalars/functions.sql`. + +### Pipeline + +`eql-codegen` is a small Rust crate with a binary entry point. The generator +runs as `cargo run -p eql-codegen` (no subcommand), which calls +`generate::generate_all` (`crates/eql-codegen/src/generate.rs`) over every row of +`eql_scalars::CATALOG`, writing each type's SQL into +`src/v3/scalars//`. A second subcommand, `cargo run -p eql-codegen +-- list-types`, prints the catalog tokens one per line (consumed by the fixture +and matrix-inventory enumeration). `main` (`crates/eql-codegen/src/main.rs`) +recognises exactly these two forms; any other argument is a usage error. + +The generator targets the `eql_v3` schema throughout: `CORE_SCHEMA = "eql_v3"` +(`crates/eql-codegen/src/consts.rs`) qualifies both the domain families and the +SEM index-term types the extractors return (`eql_v3.hmac_256`, +`eql_v3.ore_block_u64_8_256`), so no generated SQL references `eql_v2`. + +`tasks/build.sh` runs `cargo run -p eql-codegen` at the start of every `mise run +build`, so the generated SQL is never checked in. (The build first sweeps every +generated `*_{types,functions,operators,aggregates}.sql` under +`src/v3/scalars` so a type removed from `CATALOG` cannot leave orphans the +`src/**/*.sql` build glob would pick up; hand-written `*_extensions.sql` is +preserved by the name patterns.) + +Stages, in order (`generate_all` → `generate_type`): + +1. **Read the catalog.** `eql_scalars::CATALOG` is the in-binary source of truth + — a `&[ScalarSpec]`. There is no parse/validate stage at generation time: the + catalog is validated at compile time (an undefined `Term` or unknown + `ScalarKind` does not compile) and by the catalog `#[test]`s, so the data is + already well-formed by the time `generate_all` runs. +2. **Resolve terms.** For each `DomainSpec`, the `Term` enum's `impl` methods + supply the extractor name, return type, JSON envelope key, supported + operators, and the SQL `-- REQUIRE:` edges those terms imply + (`Term::operators_for_terms`, `term_json_keys`, `term_requires`, + `extractor_for_operator`, `role_for_terms`). +3. **Render.** `render_types_file`, `render_functions_file`, + `render_operators_file`, and `render_aggregates_file` (the last only for + ordered domains) build the context structs in + `crates/eql-codegen/src/context.rs` and render them through embedded + **minijinja** templates (`crates/eql-codegen/templates/*.j2`, compiled in via + `include_str!` — no runtime file IO). The structural shape of each declaration + is split between the context builders (Rust) and the templates (Jinja). +4. **Write.** `clean_generated_files` first deletes every generated `.sql` in the + target directory (recognised by the header marker) so an abandoned domain + disappears on the next regeneration; `ensure_generated_paths_writable` then + refuses to proceed if any target path is a hand-written file lacking the + marker; `write_generated_file` writes each rendered body verbatim + (`crates/eql-codegen/src/writer.rs`). The template emits the `-- AUTOMATICALLY + GENERATED FILE.` marker as its own first line, so the writer does not prepend + a header — it only uses the marker to recognise files it owns. + +There is no caching layer and no incremental mode. Each run regenerates every +output for every catalog type from scratch. + +### Generated outputs + +For a type with `D` domains of which `A` are ordered, the generator writes `1 + +2D + A` SQL files into `src/v3/scalars//`. For `int4` (`D = 4`, `A = +2`): eleven SQL files. The outputs are gitignored +(`.gitignore` excludes `src/v3/scalars/*/*_{types,functions,operators,aggregates}.sql`) +and regenerated at the start of every build. + +| File | Content | +| --------------------------------- | ---------------------------------------------------------------------------------------- | +| `_types.sql` | Single idempotent `DO` block creating every domain; each `CHECK` pins the payload version (`VALUE->>'v' = '2'`) and required envelope/ciphertext/term keys; one `--! @brief` per domain | +| `_functions.sql` | One extractor per unique term, then 44 wrappers-or-blockers covering the surface | +| `_operators.sql` | 44 `CREATE OPERATOR` statements with planner metadata on supported ops | +| `_aggregates.sql` | MIN/MAX state functions + `CREATE AGGREGATE`; emitted only for ordered domains | + +Every file opens with the `-- AUTOMATICALLY GENERATED FILE.` marker (the +project-wide marker `docs:validate` greps on to skip generated SQL — +`crates/eql-codegen/src/consts.rs`), declares its `-- REQUIRE:` edges in +dependency order (types files require `src/v3/schema.sql`; function files require +`src/v3/schema.sql`, the types file, and +`src/v3/scalars/functions.sql` plus each term's `requires` set; operator +files require `src/v3/schema.sql`, the types file, and their domain's function +file; aggregate files require `src/v3/schema.sql`, the types file, and their +domain's function and operator files), and carries Doxygen `--! @file` / +`--! @brief` headers. + +### Generator tests and the parity gate + +The generator's tests are Rust, run by `mise run test:codegen` (`cargo test -p +eql-scalars -p eql-codegen`) — no database. `mise run test:crates` adds `cargo +clippy ... -D warnings`. + +- **`eql-scalars` unit tests** — `rust_tests`, `term_tests`, + `term_helper_tests`, `fixture_tests`, `catalog_tests`, `invariant_tests`, + `values_tests` over `CATALOG`, the `Term` / `ScalarKind` / `Fixture` impls, and + the materialised `_VALUES` consts. +- **`eql-codegen` unit tests** — file counts, language/volatility invariants, + escaping guards, and twin byte-identity + (`crates/eql-codegen/src/generate.rs` `#[cfg(test)]`). +- **The parity gate** — `mise run codegen:parity` (`tasks/codegen-parity.sh`). + It runs the generator into the real tree, then (1) compares the int4 generated + SQL **file set** against the golden under `tests/codegen/reference/int4/*.sql`, + excluding committed hand-written files (`comm -23` of `ls` against `git + ls-files`), so an extra or dropped generated file fails; and (2) diffs each + golden file **byte-for-byte** against its generated counterpart, after dropping + the golden's single leading `-- REFERENCE:` provenance line (`tail -n +2`). The + same byte-for-byte assertion runs in-crate as + `crates/eql-codegen/tests/parity.rs` + (`rust_generator_matches_int4_golden_files`). The golden reference — not any + Python oracle — is the sole contract that survives generator refactors. + +CI runs these in three jobs in `.github/workflows/test-eql.yml`: `rust-crates` +(`Rust workspace crates`, runs `mise run test:crates`), `codegen` +(`Encrypted-domain codegen`, runs `mise run codegen:parity`), and +`matrix-coverage` (`Matrix coverage inventory`, runs `mise run +test:matrix:inventory`). The codegen job is a prerequisite of the PostgreSQL +test matrix. + +Adding a new **term** is a bigger move than adding a type: edit the `Term` enum's +`impl` methods, add `#[test]`s, audit `splinter.sh` for a name collision if the +extractor name is new, and — because it changes the int4 surface — update the +golden reference under `tests/codegen/reference/int4/`. + +--- + +## 7. Out of scope — `text` and `jsonb` + +`text` and `jsonb` are **not** materialised through this generator. The +`ScalarKind` enum carries `Text` / `Numeric` / `Jsonb` variants and the +`Fixture` enum carries their string-backed shapes at the capability layer, but +`CATALOG` declares only the ordered scalars today — the fixed-width integers +(`int2` / `int4` / `int8`) and the temporal `date` — so no `text` / `jsonb` SQL +surface is generated. Text and JSONB encrypted behaviour lives on the composite +`eql_v2_encrypted` type and its hand-written operator surface in `src/encrypted/` +and `src/operators/`, not the scalar materializer. `jsonb` in particular needs a +separate SQL design beyond this ordered-scalar materializer. diff --git a/docs/reference/eql-functions.md b/docs/reference/eql-functions.md index 940cb1ae..b610349c 100644 --- a/docs/reference/eql-functions.md +++ b/docs/reference/eql-functions.md @@ -422,6 +422,37 @@ eql_v2.ste_vec(val eql_v2_encrypted) RETURNS eql_v2_encrypted[] eql_v2.ste_vec(val jsonb) RETURNS eql_v2_encrypted[] ``` +### `eql_v3.eq_term()` / `eql_v3.ord_term()` (encrypted-domain) + +Extract the equality (`hm`) or ordering (`ob`) index term from a scalar +encrypted-domain value. Generated per eq/ord-capable variant of every +scalar type — see [Adding a Scalar Encrypted-Domain Type](./adding-a-scalar-encrypted-domain-type.md). +The argument type selects the overload, and both are inlinable so a +functional index built on the extractor engages. The extractors live in +the `eql_v3` schema; their return types are the self-contained `eql_v3` +SEM index-term types. + +```sql +-- int4 — generated for every scalar type's eq / ord variants. +eql_v3.eq_term(a eql_v3.int4_eq) RETURNS eql_v3.hmac_256 +eql_v3.ord_term(a eql_v3.int4_ord) RETURNS eql_v3.ore_block_u64_8_256 +eql_v3.ord_term(a eql_v3.int4_ord_ore) RETURNS eql_v3.ore_block_u64_8_256 +``` + +**Example:** +```sql +-- Functional indexes on the extracted terms (see Database Indexes). +-- A column carries a single domain type, so `eq_term` and `ord_term` +-- apply to different columns (an `_eq` column vs an `_ord`/`_ord_ore` one). +CREATE INDEX ON users USING hash (eql_v3.eq_term(salary_eq)); +CREATE INDEX ON users USING btree (eql_v3.ord_term(salary_ord)); +``` + +> The full per-domain operator/wrapper/blocker surface (and the +> `eql_v3.` / `_eq` / `_ord` / `_ord_ore` domain types themselves) is +> documented in [SQL support](./sql-support.md#encrypted-domain-scalar-types-eql_v3t) +> and the [scalar encrypted-domain type reference](./adding-a-scalar-encrypted-domain-type.md). + --- ## JSONB Path Functions @@ -540,10 +571,11 @@ eql_v2.meta_data(val jsonb) RETURNS jsonb ### `eql_v2.selector()` -Extract selector hash from encrypted value. +Extract selector hash from an encrypted payload (`jsonb`) or a ste_vec entry. ```sql -eql_v2.selector(val eql_v2_encrypted) RETURNS text +eql_v2.selector(val jsonb) RETURNS text +eql_v2.selector(entry eql_v2.ste_vec_entry) RETURNS text ``` ### `eql_v2.is_ste_vec_array()` @@ -624,34 +656,51 @@ FROM products GROUP BY eql_v2.jsonb_path_query_first(encrypted_json, 'color_selector'); ``` -### `eql_v2.min()` +### `eql_v2.min()` / `eql_v2.max()` (composite type) -Returns the minimum encrypted value in a set (requires `ore` index for ordering). +Returns the minimum or maximum encrypted value in a set on an `eql_v2_encrypted` column (requires `ore` index terms for ordering). ```sql eql_v2.min(eql_v2_encrypted) RETURNS eql_v2_encrypted +eql_v2.max(eql_v2_encrypted) RETURNS eql_v2_encrypted ``` +Comparison routes through the `<` / `>` operator on `eql_v2_encrypted`, which uses the ORE block term — no decryption. + **Example:** ```sql SELECT eql_v2.min(encrypted_date) FROM events; -SELECT eql_v2.min(encrypted_price) FROM products WHERE category = 'electronics'; +SELECT eql_v2.max(encrypted_price) FROM products WHERE category = 'electronics'; ``` -### `eql_v2.max()` +### `eql_v3.min()` / `eql_v3.max()` (per-domain) -Returns the maximum encrypted value in a set (requires `ore` index for ordering). +Returns the minimum or maximum encrypted value in a set on an ordered encrypted-domain column. Defined per ord-capable variant of every scalar type (`eql_v3._ord`, `eql_v3._ord_ore`); the input type selects the aggregate via PostgreSQL's overload resolution. These are type-safe alternatives to the composite-type aggregates above and coexist with them. ```sql -eql_v2.max(eql_v2_encrypted) RETURNS eql_v2_encrypted +-- int4 — generated for every ordered variant of every scalar type. +eql_v3.min(eql_v3.int4_ord) RETURNS eql_v3.int4_ord +eql_v3.max(eql_v3.int4_ord) RETURNS eql_v3.int4_ord +eql_v3.min(eql_v3.int4_ord_ore) RETURNS eql_v3.int4_ord_ore +eql_v3.max(eql_v3.int4_ord_ore) RETURNS eql_v3.int4_ord_ore ``` +Comparison routes through the variant's `<` / `>` operator, which uses the ORE block term — no decryption. The state function is `STRICT`, so `NULL` inputs are skipped and an all-`NULL` input set returns `NULL`. + **Example:** ```sql -SELECT eql_v2.max(encrypted_date) FROM events; -SELECT eql_v2.max(encrypted_price) FROM products WHERE category = 'electronics'; +-- ord-capable column (e.g. price_encrypted typed as eql_v3.int4_ord) +SELECT eql_v3.min(price_encrypted) FROM products; +SELECT eql_v3.max(price_encrypted) FROM products WHERE category = 'electronics'; + +-- Equivalent on a generic jsonb column (cast to the right domain) +SELECT eql_v3.min(price_jsonb::eql_v3.int4_ord) FROM products; ``` +`SUM` / `AVG` and other numeric aggregates are not supported on encrypted columns — decrypt at the application boundary. `MIN` / `MAX` only require comparator-revealing terms; arithmetic aggregates would require homomorphic encryption. + +**See also:** [`docs/reference/sql-support.md`](./sql-support.md) for the per-variant capability table. + --- ## Utility Functions diff --git a/docs/reference/sql-support.md b/docs/reference/sql-support.md index e1bf18e4..82770ad9 100644 --- a/docs/reference/sql-support.md +++ b/docs/reference/sql-support.md @@ -59,6 +59,25 @@ Use the equivalent [`jsonb_path_query`](#jsonb-functions-and-selectors-enabled-b --- +## Encrypted-domain scalar types (`eql_v3.`) + +Scalar encrypted-domain types (e.g. `eql_v3.int4`; see [Adding a Scalar Encrypted-Domain Type](./adding-a-scalar-encrypted-domain-type.md)) are a different access model from the matrix above. Instead of configuring a search index on an `eql_v2_encrypted` column, you type the column as a specific domain *variant* whose operator surface is fixed at generation time. The index terms travel in the payload; there is no `add_search_config` step. The domains and their operator surface live in the `eql_v3` schema (dropped by `DROP SCHEMA eql_v3 CASCADE`, and they survive an `eql_v2` uninstall); their extracted index-term types are the self-contained `eql_v3` SEM types (`eql_v3.hmac_256`, `eql_v3.ore_block_u64_8_256`). + +Each scalar type `` generates one storage-only variant plus eq/ord query variants: + +| Domain variant | Term carried | `=` `<>` | `<` `<=` `>` `>=` | `MIN` / `MAX` | `LIKE`/`ILIKE`, JSONB / ste_vec ops | +| ------------------------------- | ------------------- | :------: | :---------------: | :-----------: | :---------------------------------: | +| `eql_v3.` | none (storage only) | ❌ | ❌ | ❌ | ❌ | +| `eql_v3._eq` | `hm` (hmac_256) | ✅ | ❌ | ❌ | ❌ | +| `eql_v3._ord` / `_ord_ore` | `ob` (ore_block) | ✅ | ✅ | ✅ | ❌ | + +- The bare `eql_v3.` variant carries no index term and **blocks every comparison operator** — it is storage / decryption only. Type the column as `_eq` or `_ord` (or cast at the call site) when you need to query. +- Unsupported operators are not silent no-ops: they route to blocker functions that `RAISE` an "operator not supported" exception (a `NULL` operand still raises — the blockers are deliberately not `STRICT`). +- `LIKE` / `ILIKE` and the native JSONB operators (`@>`, `<@`, `->`, `->>`, `?`, `?|`, `?&`, `@?`, `@@`, `#>`, `#>>`, `-`, `#-`, `||`) are blocked on **every** scalar domain variant — they are meaningless on a scalar payload. +- `MIN` / `MAX` are exposed only on the ordered variants as `eql_v3.min(eql_v3._ord)` / `eql_v3.max(...)` — see [EQL Functions Reference](./eql-functions.md#eql_v3min--eql_v3max-per-domain). + +--- + ## SQL syntax / feature support This matrix covers higher-level SQL constructs rather than individual operators. As above, ✅ requires the listed index to be configured on the column; ❌ means the construct cannot be used against that column (without first decrypting via CipherStash Proxy or Protect.js). @@ -76,7 +95,7 @@ This matrix covers higher-level SQL constructs rather than individual operators. | `GROUP BY col` | requires `unique` on the whole column; `ore` / `ope` not yet supported (see note below). Extracted JSON paths have separate caveats — see [ste_vec section](#index-terms-by-json-node-type). | ✅ | ❌ | ❌ | ❌ | ❌ | | `DISTINCT` / `DISTINCT ON (col)` | `unique`, `ore`, or `ope` | ✅ | ✅ | ✅ | ❌ | ❌ | | `HAVING` | same index requirements as the predicates used in `HAVING` (see operator matrix) | varies | varies | varies | varies | varies | -| `MIN(col)` / `MAX(col)` | | ❌ | ✅ | ✅ | ❌ | ❌ | +| `MIN(col)` / `MAX(col)` | `eql_v2.min(eql_v2_encrypted)` / `max` work on any `eql_v2_encrypted` column with `ore` terms. The encrypted-domain family additionally exposes type-safe `eql_v3.min(eql_v3._ord)` / `max` (and the `_ord_ore` twin); `Storage` and `Eq` variants have no comparator and do not declare these aggregates. | ❌ | ✅ | ✅ | ❌ | ❌ | | `COUNT(col)` / `COUNT(DISTINCT col)` | `ore` / `ope` or `unique` for `DISTINCT`; none for plain `COUNT(col)` | ✅ | ✅ | ✅ | ✅ | ✅ | | `JOIN … ON lhs.col = rhs.col` | same index and keyset on both sides | ✅ | ✅ | ✅ | ❌ | ❌ | | `JOIN … ON lhs.col < rhs.col` etc. | same index and keyset on both sides | ❌ | ✅ | ✅ | ❌ | ❌ | @@ -89,7 +108,8 @@ Notes: - **Cross-column / cross-table comparisons** (joins, `IN (subquery)`, `UNION` dedup, etc.) require both sides to have been encrypted with the *same* keyset and the matching search index. Encrypted values from different `ste_vec` prefixes are deliberately incomparable. - **`GROUP BY`** on encrypted columns relies on an operator class which currently only supports encrypted values with a `unique` index term. This is a surprising limitation because it would be natural to expect `ore` / `ope` index terms to also work. This limitation will be lifted in the future. See [Database Indexes](./database-indexes.md#group-by) for performance considerations. - **`ORDER BY`** without an `ore` or `ope` index will still *run* (the EQL `compare` function has a deterministic literal fallback to avoid btree errors), but the resulting order is not meaningful. Configure `ore` (or `ope`) whenever ordering matters. -- **Aggregates beyond `MIN`/`MAX`** (e.g. `SUM`, `AVG`) are not supported on encrypted values — decrypt and perform those aggregate operations on the client-side instead. +- **`MIN(col)` / `MAX(col)`** is available two ways. The composite-type aggregates `eql_v2.min(eql_v2_encrypted)` / `eql_v2.max(eql_v2_encrypted)` work on any `eql_v2_encrypted` column carrying `ore` terms. The encrypted-domain family additionally exposes type-safe per-variant aggregates — see `eql_v3.min(eql_v3._ord)` / `eql_v3.max(eql_v3._ord)` (and the `_ord_ore` twin) in [EQL Functions Reference](./eql-functions.md#eql_v3min--eql_v3max-per-domain). For a domain-typed column, type it as the appropriate `_ord` variant or cast at the call site (`eql_v3.min(col::eql_v3.int4_ord)`). +- **Aggregates beyond `MIN`/`MAX`** (e.g. `SUM`, `AVG`) are not supported on encrypted values — they would require homomorphic encryption. Decrypt at the application boundary and perform those aggregates client-side. - **Parameter binding**: CipherStash Proxy rewrites bound parameters in `WHERE`, `JOIN`, and `RETURNING` clauses with `::JSONB::eql_v2_encrypted` casts so that the encrypted operator and any B-tree / GIN indexes are selected. Writing those casts yourself is only required when bypassing the proxy. --- diff --git a/mise.toml b/mise.toml index fbf499b4..8baafecb 100644 --- a/mise.toml +++ b/mise.toml @@ -11,10 +11,20 @@ "rust" = { version = "latest", components = "rustc,rust-std,cargo,rustfmt,rust-docs,clippy" } "cargo:cargo-binstall" = "latest" "cargo:sqlx-cli" = "latest" +# Single source of truth for the cargo-expand version used by `test:matrix:expand`. +# Pinned in lockstep with the nightly date in that task: cargo-expand drives the +# rustfmt pass, so an unpinned version can drift the matrix snapshot even with a +# frozen macro + nightly. mise installs this for both local runs and CI (the +# macro-expand-eql.yml workflow's mise-action step), so there is no separate +# hardcoded version to keep in lockstep. +"cargo:cargo-expand" = "1.0.122" +# Still required by the documentation tooling (`tasks/docs/generate/*.py`, run +# by `docs:generate:markdown` in the release workflow). The encrypted-domain +# codegen toolchain is now Rust (eql-scalars/eql-codegen) and needs no Python. "python" = "3.13" [task_config] -includes = ["tasks", "tasks/postgres.toml"] +includes = ["tasks", "tasks/postgres.toml", "tasks/fixtures.toml"] [env] POSTGRES_DB = "cipherstash" @@ -32,8 +42,13 @@ run = """ rm -f release/cipherstash-encrypt.sql """ -[tasks."test:sqlx"] -description = "Run SQLx tests with hybrid migration approach" +[tasks."test:sqlx:prep"] +description = "Prepare the SQLx test DB: cp built EQL into migrations, migrate, regenerate fixtures" +# `build` produces release/cipherstash-encrypt.sql, which is then cp'd into +# tests/sqlx/migrations/001_install_eql.sql below. Without this dep, a stale +# release artifact silently ships an old EQL extension into the test DB and +# regression-guard migrations (e.g. 003_install_ste_vec_data.sql) fail. +depends = ["build"] dir = "{{config_root}}" run = """ # Copy built SQL to SQLx migrations (EQL install is generated, not static) @@ -45,12 +60,36 @@ echo "Running SQLx migrations..." cd tests/sqlx sqlx migrate run +# Regenerate fixtures every run — they are not committed (see .gitignore). +# fixture:generate:all iterates eql-scalars::CATALOG and generates every +# scalar fixture in one process, so new scalar types are picked up +# automatically (add the catalog row + the fixture wiring) without editing +# this task. +# Generator encrypts via cipherstash-client directly, which needs BOTH a +# ZeroKMS auth credential (CS_CLIENT_ACCESS_KEY + CS_WORKSPACE_CRN, via +# AutoStrategy) AND a client key (CS_CLIENT_ID + CS_CLIENT_KEY, via +# EnvKeyProvider) in the shell environment. Auth and key material are +# separate roles — the two pairs are not alternatives. +echo "Regenerating SQLx fixtures..." +cd "{{config_root}}" +mise run fixture:generate:all +""" + +[tasks."test:sqlx"] +description = "Run SQLx tests with hybrid migration approach" +# Prep (build + cp + migrate + fixtures) is shared with test:sqlx:watch. +depends = ["test:sqlx:prep"] +dir = "{{config_root}}/tests/sqlx" +run = """ echo "Running Rust tests..." cargo test """ [tasks."test:sqlx:watch"] description = "Run SQLx tests in watch mode (rebuild EQL on changes)" +# Same prep as test:sqlx so watch mode starts from a migrated DB + fresh +# fixtures, not a stale checkout. +depends = ["test:sqlx:prep"] dir = "{{config_root}}/tests/sqlx" run = """ cargo watch -x test @@ -62,3 +101,158 @@ dir = "{{config_root}}/tests/sqlx" run = """ cargo test --test payload_schema_tests """ + +[tasks."codegen:parity"] +description = "Parity gate: Rust eql-codegen output matches the int4 golden (byte-for-byte)" +dir = "{{config_root}}" +run = "bash tasks/codegen-parity.sh" + +[tasks."test:codegen"] +description = "Run the encrypted-domain catalog + generator tests (no database required)" +dir = "{{config_root}}" +run = """ +cargo test -p eql-scalars -p eql-codegen +""" + +[tasks."test:crates"] +description = "Compile, lint and test the std-only Rust workspace crates (no database)" +dir = "{{config_root}}" +run = """ +#!/usr/bin/env bash +# eql-scalars / eql-codegen / eql-tests-macros are the lean workspace members. +# Scope explicitly to them (NOT --workspace): a workspace-wide test would drag +# in tests/sqlx, whose suite needs Postgres + CS_* secrets and is already +# covered by the `test` job. eql-tests-macros only pulls syn/quote/proc-macro2, +# so it stays in the lean set. clippy is likewise scoped — a workspace clippy +# recompiles the heavy sqlx/tokio/cipherstash-client tree for no added coverage +# of these crates. +# bash is pinned via the `#!/usr/bin/env bash` shebang above (mise honors a +# `#!` first line), so `set -o pipefail` is available regardless of the runner's +# /bin/sh (dash on the CI images). +set -euo pipefail +cargo fmt --check +cargo clippy -p eql-scalars -p eql-codegen -p eql-tests-macros --all-targets -- -D warnings +cargo test -p eql-scalars -p eql-codegen -p eql-tests-macros +""" + +[tasks."test:matrix:inventory"] +description = "Verify the matrix test-name set against the single canonical snapshot, catalog-cross-checked (no database required)" +dir = "{{config_root}}/tests/sqlx" +run = """ +#!/usr/bin/env bash +# ONE canonical, token-normalized snapshot (snapshots/matrix_tests.txt) pins the +# set of macro-emitted matrix test names. The two per-type snapshots are gone: +# they were byte-identical modulo the type token, so one canonical set plus a +# per-type normalize+compare carries the same signal at 1/N the committed surface. +# +# Steps: +# 1. List the encrypted_domain binary ONCE (deterministic; reused below). +# 2. Discover the set of scalar types present FROM THE BINARY'S OWN OUTPUT +# (scalars:::: prefixes) — never a directory glob. +# 3. For each discovered type, normalize its token to and assert its set +# equals the canonical snapshot. Assert at least one type is present. +# 4. Completeness cross-check: assert the discovered type set equals +# `eql-codegen list-types`. A catalog type added without its matrix wiring +# (no scalars:::: tests in the binary) fails here. +# +# `--no-default-features` excludes the `scale` arm (a known, documented blind +# spot, covered by the scale gate + family::mutations negative controls). +# `LC_ALL=C sort` makes ordering byte-stable across locales. No database needed. +set -euo pipefail + +test -f snapshots/matrix_tests.txt || { echo "snapshots/matrix_tests.txt missing — regenerate (see snapshots/README.md)." >&2; exit 1; } + +listing=$(cargo test --no-default-features --test encrypted_domain -- --list | sed -n 's/: test$//p') + +# Types present in the binary, from scalars:::: prefixes. +discovered=$(printf '%s\\n' "$listing" \ + | sed -n 's/^scalars::\\([a-z0-9_]*\\)::.*/\\1/p' \ + | LC_ALL=C sort -u) +[ -n "$discovered" ] || { echo "No scalars:::: tests found in the encrypted_domain binary." >&2; exit 1; } + +# Per-type normalize + compare against the canonical snapshot. +checked=0 +while IFS= read -r t; do + [ -n "$t" ] || continue + printf '%s\\n' "$listing" | grep "^scalars::${t}::" \ + | sed -e "s/^scalars::${t}::/scalars::::/" -e "s/_${t}_/__/g" | LC_ALL=C sort > "/tmp/matrix-norm-${t}.txt" + if ! cmp -s "/tmp/matrix-norm-${t}.txt" snapshots/matrix_tests.txt; then + echo "Matrix test-name set for '${t}' differs from snapshots/matrix_tests.txt:" >&2 + diff snapshots/matrix_tests.txt "/tmp/matrix-norm-${t}.txt" >&2 || true + exit 1 + fi + checked=$((checked + 1)) +done <<< "$discovered" +[ "$checked" -gt 0 ] || { echo "No scalar type matched the canonical snapshot." >&2; exit 1; } + +# Completeness cross-check against the catalog (the single source of truth). +catalog=$(cd "{{config_root}}" && cargo run -p eql-codegen -- list-types | LC_ALL=C sort -u) +if [ "$discovered" != "$catalog" ]; then + echo "Catalog types and matrix-wired types disagree." >&2 + echo " catalog (eql-codegen list-types): $(echo "$catalog" | tr '\\n' ' ')" >&2 + echo " matrix-wired (binary --list): $(echo "$discovered" | tr '\\n' ' ')" >&2 + echo "A catalog type missing its matrix wiring (or a wired type not in the catalog) trips this." >&2 + exit 1 +fi + +echo "Matrix inventory OK: ${checked} type(s) match the canonical snapshot; catalog reconciled." +""" + +[tasks."test:matrix:expand"] +description = "Regenerate the int4 matrix cargo-expand snapshot (requires the pinned nightly + cargo-expand)" +dir = "{{config_root}}/tests/sqlx" +run = """ +#!/usr/bin/env bash +# Body-level fidelity backstop for the macro: the expanded source of the int4 +# matrix arms. The `cargo +nightly-...` invocation below is the SINGLE source of +# the pinned nightly date — .github/workflows/macro-expand-eql.yml greps it from +# here rather than hardcoding, so there is nothing to keep in lockstep. The date +# is pinned to a known-good value so the snapshot only moves when *the macro* +# moves, not when nightly reformats — bump it deliberately, here, in one place. +# +# `#[sqlx::test]` embeds one `sqlx::migrate::Migration` per file in migrations/ +# plus the fixture (via include_str) into EVERY generated test — ~477 MB of +# repeated data dwarfing the macro bodies, and non-deterministic across +# environments (the generated 001_install_eql.sql is absent in a bare checkout). +# Normalise both to fixed empties so the snapshot depends only on matrix.rs + +# the sqlx/test harness: swap migrations/ for a single empty placeholder and +# empty the int4 fixture, expand, then restore (trap fires on any exit). This is +# expand-only surgery on gitignored/generated inputs; nothing here is committed. +# +# Non-blocking lane (no Postgres, never compiled): the `.rs` name lives under +# snapshots/, not tests/, so Cargo never treats it as a test target. +set -euo pipefail +# Force the mise-pinned cargo-expand (mise.toml [tools]) to win over any stray +# global `cargo install cargo-expand` in ~/.cargo/bin, which otherwise sits +# ahead of mise's install dir on PATH and silently drifts the snapshot. The +# version is single-sourced in [tools]; this only fixes PATH precedence. +PATH="$(mise where cargo:cargo-expand)/bin:$PATH" +export PATH +mkdir -p snapshots fixtures +BK=$(mktemp -d) +cp -a migrations "$BK/migrations" +# The int4 fixture is gitignored (regenerated) and absent in a bare checkout — +# back it up only if present, and on restore drop the empty stand-in if so. +HAD_FIXTURE=0 +if [ -f fixtures/eql_v2_int4.sql ]; then cp -a fixtures/eql_v2_int4.sql "$BK/eql_v2_int4.sql"; HAD_FIXTURE=1; fi +restore() { + rm -rf migrations && cp -a "$BK/migrations" migrations + if [ "$HAD_FIXTURE" = 1 ]; then cp -af "$BK/eql_v2_int4.sql" fixtures/eql_v2_int4.sql; else rm -f fixtures/eql_v2_int4.sql; fi + rm -rf "$BK" +} +trap restore EXIT +# Wipe + recreate so the expand input is ALWAYS exactly one empty migration + +# one empty fixture, regardless of what the checkout had — this is what makes +# the snapshot deterministic across local and CI. +rm -rf migrations && mkdir migrations +: > migrations/0001_placeholder.sql +: > fixtures/eql_v2_int4.sql +# Expand into a temp file and mv into place only on success — a redirect straight +# onto the snapshot would zero it before cargo runs, so a transient expand +# failure would leave a 0-byte snapshot locally. (Under `set -euo pipefail` a +# cargo failure aborts the script and the trap restores migrations/fixtures; the +# temp file is then orphaned in $TMPDIR, which is acceptable.) +OUT=$(mktemp) +cargo +nightly-2026-05-01 expand --test encrypted_domain scalars::int4 > "$OUT" +mv "$OUT" snapshots/int4_expanded.rs +""" diff --git a/src/lint/lints.sql b/src/lint/lints.sql index 12ffea00..08c4a7de 100644 --- a/src/lint/lints.sql +++ b/src/lint/lints.sql @@ -1,4 +1,5 @@ -- REQUIRE: src/schema.sql +-- REQUIRE: src/v3/schema.sql --! @brief EQL lint: detect non-inlinable operator implementation functions --! @@ -38,6 +39,26 @@ --! 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 encrypted domain (`eql_v3.*` or +--! `public.eql_v2_*`) 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 +--! encrypted domain (`eql_v3.*` or +--! `public.eql_v2_*`). Opclasses on domains +--! bypass operator resolution; use a +--! functional index on the extractor instead. --! --! @example --! ``` @@ -74,7 +95,8 @@ AS $$ SELECT 1 FROM pg_type t WHERE t.oid IN (op.oprleft, op.oprright) AND (t.typname LIKE 'eql_v2%' - OR t.typnamespace = 'eql_v2'::regnamespace) + OR t.typnamespace = 'eql_v2'::regnamespace + OR t.typnamespace = 'eql_v3'::regnamespace) ) ), @@ -85,6 +107,7 @@ AS $$ 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, @@ -94,6 +117,41 @@ AS $$ 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_v2` whose body contains + -- one of the two blocker markers emitted by the codegen + -- (`encrypted_domain_unsupported_bool` for boolean blockers; the literal + -- `is not supported for` for path-operator blockers) AND that take at + -- least one `public.eql_v2_*` domain over jsonb argument. The argument + -- filter excludes the shared `encrypted_domain_unsupported_bool(text, + -- text)` helper itself, which contains the marker in its body but is + -- not a blocker. + 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 IN ('eql_v2', 'eql_v3') + AND (p.prosrc LIKE '%encrypted_domain_unsupported_bool%' + 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' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) + ) ) -- ┌─────────────────────────────────────────────────────────────────┐ @@ -113,6 +171,10 @@ AS $$ 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 @@ -125,6 +187,10 @@ AS $$ 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 @@ -136,6 +202,10 @@ AS $$ '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 @@ -146,6 +216,10 @@ AS $$ '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 │ @@ -201,6 +275,92 @@ AS $$ 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' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) + AND bt.typtype = 'd' + AND ( + bn.nspname = 'eql_v3' + OR (bn.nspname = 'public' AND bt.typname LIKE 'eql_v2\_%') + ) + + -- ┌─────────────────────────────────────────────────────────────────┐ + -- │ Domain opclass: an operator class declared FOR TYPE on an │ + -- │ 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' + OR (tn.nspname = 'public' AND t.typname LIKE 'eql_v2\_%') + ) + ORDER BY 1, 2, 3; $$; diff --git a/src/ore_block_u64_8_256/operators.sql b/src/ore_block_u64_8_256/operators.sql index e9e34561..06a4fa65 100644 --- a/src/ore_block_u64_8_256/operators.sql +++ b/src/ore_block_u64_8_256/operators.sql @@ -123,10 +123,17 @@ $$; --! @brief = operator for ORE block types +--! +--! COMMUTATOR is the operator itself: equality is symmetric. The clause +--! is required for a MERGES (mergejoinable) operator — 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_v2_int4_ord_ore equality wrappers). CREATE OPERATOR = ( FUNCTION=eql_v2.ore_block_u64_8_256_eq, LEFTARG=eql_v2.ore_block_u64_8_256, RIGHTARG=eql_v2.ore_block_u64_8_256, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel, @@ -137,10 +144,14 @@ CREATE OPERATOR = ( --! @brief <> operator for ORE block types +--! +--! COMMUTATOR is the operator itself: inequality is symmetric. Required +--! alongside the MERGES flag — see the = operator above. CREATE OPERATOR <> ( FUNCTION=eql_v2.ore_block_u64_8_256_neq, LEFTARG=eql_v2.ore_block_u64_8_256, RIGHTARG=eql_v2.ore_block_u64_8_256, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = eqsel, JOIN = eqjoinsel, diff --git a/src/v3/common.sql b/src/v3/common.sql new file mode 100644 index 00000000..698989c7 --- /dev/null +++ b/src/v3/common.sql @@ -0,0 +1,49 @@ +-- REQUIRE: src/v3/schema.sql + +--! @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.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)'; diff --git a/src/v3/crypto.sql b/src/v3/crypto.sql new file mode 100644 index 00000000..bd99b162 --- /dev/null +++ b/src/v3/crypto.sql @@ -0,0 +1,53 @@ +-- REQUIRE: src/v3/schema.sql + +--! @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 $$; diff --git a/src/v3/scalars/functions.sql b/src/v3/scalars/functions.sql new file mode 100644 index 00000000..53273023 --- /dev/null +++ b/src/v3/scalars/functions.sql @@ -0,0 +1,26 @@ +-- REQUIRE: src/v3/schema.sql + +--! @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//. +--! 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.*) +--! @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; diff --git a/src/v3/schema.sql b/src/v3/schema.sql new file mode 100644 index 00000000..41be4d40 --- /dev/null +++ b/src/v3/schema.sql @@ -0,0 +1,23 @@ +--! @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.int4, 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_u64_8_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; diff --git a/src/v3/sem/hmac_256/functions.sql b/src/v3/sem/hmac_256/functions.sql new file mode 100644 index 00000000..9b2592cc --- /dev/null +++ b/src/v3/sem/hmac_256/functions.sql @@ -0,0 +1,42 @@ +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/sem/hmac_256/types.sql + +--! @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 + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + BEGIN + RETURN val ->> 'hm' IS NOT NULL; + END; +$$ LANGUAGE plpgsql; diff --git a/src/v3/sem/hmac_256/types.sql b/src/v3/sem/hmac_256/types.sql new file mode 100644 index 00000000..92987935 --- /dev/null +++ b/src/v3/sem/hmac_256/types.sql @@ -0,0 +1,12 @@ +-- REQUIRE: src/v3/schema.sql + +--! @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; diff --git a/src/v3/sem/ore_block_u64_8_256/functions.sql b/src/v3/sem/ore_block_u64_8_256/functions.sql new file mode 100644 index 00000000..ccc6a817 --- /dev/null +++ b/src/v3/sem/ore_block_u64_8_256/functions.sql @@ -0,0 +1,216 @@ +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/crypto.sql +-- REQUIRE: src/v3/common.sql +-- REQUIRE: src/v3/sem/ore_block_u64_8_256/types.sql + +--! @file v3/sem/ore_block_u64_8_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_u64_8_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 passes `val->'ob'`, always an +--! array or JSON null, 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_ore_block_u64_8_256(val jsonb) +RETURNS eql_v3.ore_block_u64_8_256 + IMMUTABLE +AS $$ + SELECT CASE WHEN jsonb_typeof(val) = 'array' + THEN ROW(( + SELECT array_agg(ROW(b)::eql_v3.ore_block_u64_8_256_term) + FROM unnest(eql_v3.jsonb_array_to_bytea_array(val)) AS b + ))::eql_v3.ore_block_u64_8_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.sql does +--! not recognise it; this marker is the documented manual opt-in. +COMMENT ON FUNCTION eql_v3.jsonb_array_to_ore_block_u64_8_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_u64_8_256 ORE block index term +--! @throws Exception if 'ob' field is missing +CREATE FUNCTION eql_v3.ore_block_u64_8_256(val jsonb) + RETURNS eql_v3.ore_block_u64_8_256 + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + BEGIN + IF val IS NULL THEN + RETURN NULL; + END IF; + + IF eql_v3.has_ore_block_u64_8_256(val) THEN + RETURN eql_v3.jsonb_array_to_ore_block_u64_8_256(val->'ob'); + END IF; + RAISE 'Expected an ore index (ob) value in json: %', val; + END; +$$ LANGUAGE plpgsql; + + +--! @brief Check if JSONB payload contains ORE block index term +--! @param val jsonb containing encrypted EQL payload +--! @return boolean True if 'ob' field is present and non-null +CREATE FUNCTION eql_v3.has_ore_block_u64_8_256(val jsonb) + RETURNS boolean + IMMUTABLE STRICT PARALLEL SAFE + SET search_path = pg_catalog, extensions, public +AS $$ + BEGIN + RETURN val ->> 'ob' IS NOT NULL; + END; +$$ LANGUAGE plpgsql; + + +--! @brief Compare two ORE block terms using cryptographic comparison +--! @internal +--! @param a eql_v3.ore_block_u64_8_256_term First ORE term +--! @param b eql_v3.ore_block_u64_8_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 +CREATE FUNCTION eql_v3.compare_ore_block_u64_8_256_term(a eql_v3.ore_block_u64_8_256_term, b eql_v3.ore_block_u64_8_256_term) + RETURNS integer + 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; + right_offset CONSTANT smallint := 136; -- 8 * 17 + + 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; + + FOR block IN 0..7 LOOP + IF + substr(a.bytes, 1 + block, 1) != substr(b.bytes, 1 + block, 1) + OR substr(a.bytes, 9 + left_block_size * block, left_block_size) != substr(b.bytes, 9 + 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 := substr(b.bytes, right_offset + 1, 16); + + target_block := substr(b.bytes, right_offset + 17 + (unequal_block * right_block_size), right_block_size); + + data_block := substr(a.bytes, 9 + (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_u64_8_256_term[] First array +--! @param b eql_v3.ore_block_u64_8_256_term[] Second array +--! @return integer -1/0/1, or NULL if either array is NULL +CREATE FUNCTION eql_v3.compare_ore_block_u64_8_256_terms(a eql_v3.ore_block_u64_8_256_term[], b eql_v3.ore_block_u64_8_256_term[]) +RETURNS integer + 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_u64_8_256_term(a[1], b[1]); + + IF cmp_result = 0 THEN + RETURN eql_v3.compare_ore_block_u64_8_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_u64_8_256 First ORE block +--! @param b eql_v3.ore_block_u64_8_256 Second ORE block +--! @return integer -1/0/1 +CREATE FUNCTION eql_v3.compare_ore_block_u64_8_256_terms(a eql_v3.ore_block_u64_8_256, b eql_v3.ore_block_u64_8_256) +RETURNS integer + SET search_path = pg_catalog, extensions, public +AS $$ + BEGIN + RETURN eql_v3.compare_ore_block_u64_8_256_terms(a.terms, b.terms); + END +$$ LANGUAGE plpgsql; diff --git a/src/v3/sem/ore_block_u64_8_256/operator_class.sql b/src/v3/sem/ore_block_u64_8_256/operator_class.sql new file mode 100644 index 00000000..b367c8f6 --- /dev/null +++ b/src/v3/sem/ore_block_u64_8_256/operator_class.sql @@ -0,0 +1,26 @@ +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/sem/ore_block_u64_8_256/types.sql +-- REQUIRE: src/v3/sem/ore_block_u64_8_256/functions.sql + +--! @file v3/sem/ore_block_u64_8_256/operator_class.sql +--! @brief B-tree operator family + default class on eql_v3.ore_block_u64_8_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_u64_8_256_operator_family USING btree; + +--! @brief B-tree operator class for ORE block encrypted values +--! +--! Supports operators: <, <=, =, >=, >. Uses comparison function +--! compare_ore_block_u64_8_256_terms. +CREATE OPERATOR CLASS eql_v3.ore_block_u64_8_256_operator_class DEFAULT FOR TYPE eql_v3.ore_block_u64_8_256 USING btree FAMILY eql_v3.ore_block_u64_8_256_operator_family AS + OPERATOR 1 <, + OPERATOR 2 <=, + OPERATOR 3 =, + OPERATOR 4 >=, + OPERATOR 5 >, + FUNCTION 1 eql_v3.compare_ore_block_u64_8_256_terms(a eql_v3.ore_block_u64_8_256, b eql_v3.ore_block_u64_8_256); diff --git a/src/v3/sem/ore_block_u64_8_256/operators.sql b/src/v3/sem/ore_block_u64_8_256/operators.sql new file mode 100644 index 00000000..beca9da8 --- /dev/null +++ b/src/v3/sem/ore_block_u64_8_256/operators.sql @@ -0,0 +1,181 @@ +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/sem/ore_block_u64_8_256/types.sql +-- REQUIRE: src/v3/sem/ore_block_u64_8_256/functions.sql + +--! @file v3/sem/ore_block_u64_8_256/operators.sql +--! @brief Comparison operators on eql_v3.ore_block_u64_8_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_u64_8_256 Left operand +--! @param b eql_v3.ore_block_u64_8_256 Right operand +--! @return boolean True if the ORE blocks are equal +--! +--! @see eql_v3.compare_ore_block_u64_8_256_terms +CREATE FUNCTION eql_v3.ore_block_u64_8_256_eq(a eql_v3.ore_block_u64_8_256, b eql_v3.ore_block_u64_8_256) +RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_block_u64_8_256_terms(a, b) = 0 +$$; + +--! @brief Not-equal backing function for ORE block types +--! @internal +--! +--! @param a eql_v3.ore_block_u64_8_256 Left operand +--! @param b eql_v3.ore_block_u64_8_256 Right operand +--! @return boolean True if the ORE blocks are not equal +--! +--! @see eql_v3.compare_ore_block_u64_8_256_terms +CREATE FUNCTION eql_v3.ore_block_u64_8_256_neq(a eql_v3.ore_block_u64_8_256, b eql_v3.ore_block_u64_8_256) +RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_block_u64_8_256_terms(a, b) <> 0 +$$; + +--! @brief Less-than backing function for ORE block types +--! @internal +--! +--! @param a eql_v3.ore_block_u64_8_256 Left operand +--! @param b eql_v3.ore_block_u64_8_256 Right operand +--! @return boolean True if the left operand is less than the right operand +--! +--! @see eql_v3.compare_ore_block_u64_8_256_terms +CREATE FUNCTION eql_v3.ore_block_u64_8_256_lt(a eql_v3.ore_block_u64_8_256, b eql_v3.ore_block_u64_8_256) +RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_block_u64_8_256_terms(a, b) = -1 +$$; + +--! @brief Less-than-or-equal backing function for ORE block types +--! @internal +--! +--! @param a eql_v3.ore_block_u64_8_256 Left operand +--! @param b eql_v3.ore_block_u64_8_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_u64_8_256_terms +CREATE FUNCTION eql_v3.ore_block_u64_8_256_lte(a eql_v3.ore_block_u64_8_256, b eql_v3.ore_block_u64_8_256) +RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_block_u64_8_256_terms(a, b) != 1 +$$; + +--! @brief Greater-than backing function for ORE block types +--! @internal +--! +--! @param a eql_v3.ore_block_u64_8_256 Left operand +--! @param b eql_v3.ore_block_u64_8_256 Right operand +--! @return boolean True if the left operand is greater than the right operand +--! +--! @see eql_v3.compare_ore_block_u64_8_256_terms +CREATE FUNCTION eql_v3.ore_block_u64_8_256_gt(a eql_v3.ore_block_u64_8_256, b eql_v3.ore_block_u64_8_256) +RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_block_u64_8_256_terms(a, b) = 1 +$$; + +--! @brief Greater-than-or-equal backing function for ORE block types +--! @internal +--! +--! @param a eql_v3.ore_block_u64_8_256 Left operand +--! @param b eql_v3.ore_block_u64_8_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_u64_8_256_terms +CREATE FUNCTION eql_v3.ore_block_u64_8_256_gte(a eql_v3.ore_block_u64_8_256, b eql_v3.ore_block_u64_8_256) +RETURNS boolean + LANGUAGE sql + IMMUTABLE STRICT PARALLEL SAFE +AS $$ + SELECT eql_v3.compare_ore_block_u64_8_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._ord_ore equality wrappers). +CREATE OPERATOR = ( + FUNCTION=eql_v3.ore_block_u64_8_256_eq, + LEFTARG=eql_v3.ore_block_u64_8_256, + RIGHTARG=eql_v3.ore_block_u64_8_256, + COMMUTATOR = =, + NEGATOR = <>, + RESTRICT = eqsel, + JOIN = eqjoinsel, + HASHES, + MERGES +); + +--! @brief <> operator for ORE block types +CREATE OPERATOR <> ( + FUNCTION=eql_v3.ore_block_u64_8_256_neq, + LEFTARG=eql_v3.ore_block_u64_8_256, + RIGHTARG=eql_v3.ore_block_u64_8_256, + COMMUTATOR = <>, + NEGATOR = =, + RESTRICT = eqsel, + JOIN = eqjoinsel, + HASHES, + MERGES +); + +--! @brief > operator for ORE block types +CREATE OPERATOR > ( + FUNCTION=eql_v3.ore_block_u64_8_256_gt, + LEFTARG=eql_v3.ore_block_u64_8_256, + RIGHTARG=eql_v3.ore_block_u64_8_256, + COMMUTATOR = <, + NEGATOR = <=, + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel +); + +--! @brief < operator for ORE block types +CREATE OPERATOR < ( + FUNCTION=eql_v3.ore_block_u64_8_256_lt, + LEFTARG=eql_v3.ore_block_u64_8_256, + RIGHTARG=eql_v3.ore_block_u64_8_256, + COMMUTATOR = >, + NEGATOR = >=, + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel +); + +--! @brief <= operator for ORE block types +CREATE OPERATOR <= ( + FUNCTION=eql_v3.ore_block_u64_8_256_lte, + LEFTARG=eql_v3.ore_block_u64_8_256, + RIGHTARG=eql_v3.ore_block_u64_8_256, + COMMUTATOR = >=, + NEGATOR = >, + RESTRICT = scalarlesel, + JOIN = scalarlejoinsel +); + +--! @brief >= operator for ORE block types +CREATE OPERATOR >= ( + FUNCTION=eql_v3.ore_block_u64_8_256_gte, + LEFTARG=eql_v3.ore_block_u64_8_256, + RIGHTARG=eql_v3.ore_block_u64_8_256, + COMMUTATOR = <=, + NEGATOR = <, + RESTRICT = scalargesel, + JOIN = scalargejoinsel +); diff --git a/src/v3/sem/ore_block_u64_8_256/types.sql b/src/v3/sem/ore_block_u64_8_256/types.sql new file mode 100644 index 00000000..f7e44dd0 --- /dev/null +++ b/src/v3/sem/ore_block_u64_8_256/types.sql @@ -0,0 +1,26 @@ +-- REQUIRE: src/v3/schema.sql + +--! @file v3/sem/ore_block_u64_8_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_u64_8_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_u64_8_256 AS ( + terms eql_v3.ore_block_u64_8_256_term[] +); diff --git a/tasks/build.sh b/tasks/build.sh index 0768dd34..98dee8db 100755 --- a/tasks/build.sh +++ b/tasks/build.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash #MISE description="Build SQL into single release file" #MISE alias="b" -#MISE sources=["src/**/*.sql", "tasks/pin_search_path.sql", "tasks/uninstall.sql", "tasks/uninstall-protect.sql"] +#MISE sources=["src/**/*.sql", "tasks/pin_search_path.sql", "tasks/uninstall.sql", "tasks/uninstall-protect.sql", "crates/eql-scalars/src/**/*.rs", "crates/eql-codegen/src/**/*.rs"] #MISE outputs=["release/cipherstash-encrypt.sql","release/cipherstash-encrypt-uninstall.sql","release/cipherstash-encrypt-protect.sql","release/cipherstash-encrypt-protect-uninstall.sql"] #USAGE flag "--version " help="Specify release version of EQL" default="DEV" @@ -9,6 +9,29 @@ set -euo pipefail +# Regenerate encrypted-domain SQL from the Rust catalog before building. +# Generated files (src/v3/scalars//_*.sql) are gitignored; the +# catalog at crates/eql-scalars/src (eql-scalars::CATALOG) is the source of +# truth, rendered by the eql-codegen binary. +# +# Nuke every generated file first so a type removed from the catalog can't +# leave orphans in src/ that the `src/**/*.sql` build glob would silently +# pick up. eql-codegen cleans within a directory it regenerates, but never +# runs for a type no longer in the catalog. Hand-written *_extensions.sql is +# preserved by the name patterns; -mindepth 2 keeps the type-agnostic +# src/v3/scalars/functions.sql safe. +find src/v3/scalars -mindepth 2 -type f \ + \( -name '*_types.sql' -o -name '*_functions.sql' -o -name '*_operators.sql' \ + -o -name '*_aggregates.sql' \) \ + -delete 2>/dev/null || true + +# Regenerate every type — the catalog (eql-scalars::CATALOG) is the single +# source of truth for the enumeration; eql-codegen renders all SQL in one +# deterministic run. The plaintext fixture lists are not generated — the SQLx +# tests read them straight from the catalog (eql_scalars::INT4_VALUES / …). The +# orphan sweep above still handles the catalog-removed case the generator cannot. +cargo run -p eql-codegen + # Fail loudly if any file referenced in a tsorted dep list doesn't exist. # Without this, `xargs cat` would print `cat: foo.sql: No such file or directory` # and continue — silently producing an incomplete release artefact. @@ -27,6 +50,29 @@ verify_deps_exist() { fi } +# Fail loudly if any v3 REQUIRE edge points OUTSIDE src/v3. The v3-only build +# must be self-contained (no eql_v2 coupling); a stray `-- REQUIRE: src/...` +# edge to a non-v3 file would silently pull eql_v2 SQL into the v3 artefact (or +# tsort would drop it), breaking self-containment. Each line in deps-v3.txt is +# " "; self-edges (file == dep) are skipped, every other dep target +# must start with src/v3/. +verify_v3_self_contained() { + local dep_file=$1 + local offending=0 + while IFS=' ' read -r src dep; do + [[ -z "$dep" ]] && continue + [[ "$src" == "$dep" ]] && continue + if [[ "$dep" != src/v3/* ]]; then + echo "ERROR: v3 REQUIRE edge points outside src/v3: $src -- REQUIRE: $dep" >&2 + offending=1 + fi + done < "$dep_file" + if [[ $offending -ne 0 ]]; then + echo "ERROR: v3-only build is not self-contained — a -- REQUIRE: target lives outside src/v3 (see above)." >&2 + exit 1 + fi +} + mkdir -p release rm -f release/cipherstash-encrypt-uninstall.sql @@ -38,6 +84,9 @@ rm -f release/cipherstash-encrypt-supabase.sql rm -f release/cipherstash-encrypt-protect.sql rm -f release/cipherstash-encrypt-protect-uninstall.sql +rm -f release/cipherstash-encrypt-v3.sql +rm -f release/cipherstash-encrypt-v3-uninstall.sql + rm -f dbdev/eql--0.0.0.sql rm -f src/version.sql @@ -47,6 +96,8 @@ rm -f src/deps-supabase.txt rm -f src/deps-ordered-supabase.txt rm -f src/deps-protect.txt rm -f src/deps-ordered-protect.txt +rm -f src/deps-v3.txt +rm -f src/deps-ordered-v3.txt RELEASE_VERSION=${usage_version:-DEV} @@ -142,6 +193,39 @@ cat tasks/pin_search_path.sql >> release/cipherstash-encrypt-protect.sql cat tasks/uninstall-protect.sql >> release/cipherstash-encrypt-protect-uninstall.sql +# v3-only build (design D9): the self-contained eql_v3 surface — schema, SEM +# types, scalar domains — globbed from src/v3 ONLY. This is the unit the +# self-containment gate greps; it is the only artifact that can be "free of +# eql_v2", because the combined variants glob all of src/. It deliberately does +# NOT append tasks/pin_search_path.sql (D11): that script is eql_v2-coupled +# (raises if public.eql_v2_encrypted / eql_v2.ste_vec_entry are absent and only +# ever pins eql_v2 functions), so appending it would both fail a clean v3 +# install and break the self-containment grep. +find src/v3 -type f -path "*.sql" ! -path "*_test.sql" | while IFS= read -r sql_file; do + echo "$sql_file" + + echo "$sql_file $sql_file" >> src/deps-v3.txt + + while IFS= read -r line; do + if [[ "$line" == *"-- REQUIRE:"* ]]; then + deps=${line#*-- REQUIRE: } + for dep in $deps; do + echo "$sql_file $dep" >> src/deps-v3.txt + done + fi + done < "$sql_file" +done + +verify_v3_self_contained src/deps-v3.txt + +cat src/deps-v3.txt | tsort | tac > src/deps-ordered-v3.txt +verify_deps_exist src/deps-ordered-v3.txt + +cat src/deps-ordered-v3.txt | xargs cat | grep -v REQUIRE >> release/cipherstash-encrypt-v3.sql + +cat tasks/uninstall-v3.sql >> release/cipherstash-encrypt-v3-uninstall.sql + + echo echo '###############################################' echo "# ✅Build succeeded" @@ -151,8 +235,10 @@ echo 'Installer:' echo ' release/cipherstash-encrypt.sql' echo ' release/cipherstash-encrypt-supabase.sql' echo ' release/cipherstash-encrypt-protect.sql' +echo ' release/cipherstash-encrypt-v3.sql' echo echo 'Uninstaller:' echo ' release/cipherstash-encrypt-uninstall.sql' echo ' release/cipherstash-encrypt-uninstall-supabase.sql' echo ' release/cipherstash-encrypt-protect-uninstall.sql' +echo ' release/cipherstash-encrypt-v3-uninstall.sql' diff --git a/tasks/codegen-parity.sh b/tasks/codegen-parity.sh new file mode 100755 index 00000000..0445802f --- /dev/null +++ b/tasks/codegen-parity.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +#MISE description="Parity gate: Rust eql-codegen output matches the int4 golden (byte-for-byte)" + +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$REPO_ROOT" + +echo "==> Generating with the Rust generator (writes the real repo tree)" +cargo run -q -p eql-codegen -- > /dev/null + +echo "==> Comparing int4 generated SQL file SET vs golden (catches extra/dropped files)" +# The content loop below is golden-driven: it verifies every golden file has a +# matching generated body, so a DROPPED file fails there. It cannot see an EXTRA +# generated file (a new template output, or the new half of a rename) — that name +# is never iterated. Assert the sets are equal first to close that blind spot. +# "Generated" excludes any committed, hand-written SQL (e.g. int4_extensions.sql), +# which lives in this dir but has no golden counterpart; git-tracked == hand-written. +# find (not `ls *.sql`) so an empty dir yields zero lines instead of aborting +# under `set -e`; `-maxdepth 1` + sed strips the leading `./` for bare names. +golden_set=$(cd tests/codegen/reference/int4 \ + && find . -maxdepth 1 -name '*.sql' | sed 's#.*/##' | LC_ALL=C sort) +gen_set=$(cd src/v3/scalars/int4 \ + && comm -23 <(find . -maxdepth 1 -name '*.sql' | sed 's#.*/##' | LC_ALL=C sort) \ + <(git ls-files . | sed 's#.*/##' | LC_ALL=C sort)) +if [ "$golden_set" != "$gen_set" ]; then + echo "int4 generated SQL file set differs from golden (< golden, > generated):" >&2 + diff <(echo "$golden_set") <(echo "$gen_set") >&2 || true + exit 1 +fi + +echo "==> Diffing Rust int4 SQL vs golden reference (byte-for-byte)" +for f in tests/codegen/reference/int4/*.sql; do + name="$(basename "$f")" + # Drop the 1-line `-- REFERENCE:` provenance line, then compare the remaining + # bytes EXACTLY. Both the reference body (from line 2) and the whole generated + # file start with the template-owned `-- AUTOMATICALLY GENERATED FILE.` marker, + # so no header strip is needed — any whitespace or blank-line drift fails here. + diff <(tail -n +2 "$f") "src/v3/scalars/int4/$name" +done + +echo "PARITY OK: Rust generator matches the int4 golden (byte-for-byte)." diff --git a/tasks/docs/generate.sh b/tasks/docs/generate.sh index ea5a5658..033bdc20 100755 --- a/tasks/docs/generate.sh +++ b/tasks/docs/generate.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash #MISE description="Generate API documentation (with Doxygen)" +# Build first so generated encrypted-domain SQL exists under src/. +#MISE depends=["build"] set -e diff --git a/tasks/docs/validate.sh b/tasks/docs/validate.sh index 39275596..14b659af 100755 --- a/tasks/docs/validate.sh +++ b/tasks/docs/validate.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash #MISE description="Validate SQL documentation" +# Build first so generated encrypted-domain SQL exists under src/. +#MISE depends=["build"] set -e diff --git a/tasks/docs/validate/coverage.sh b/tasks/docs/validate/coverage.sh index 623f8f2f..4657ec76 100755 --- a/tasks/docs/validate/coverage.sh +++ b/tasks/docs/validate/coverage.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash #MISE description="Checks documentation coverage for SQL files" +# Build first so generated encrypted-domain SQL exists under src/. +#MISE depends=["build"] set -e diff --git a/tasks/docs/validate/documented-sql.sh b/tasks/docs/validate/documented-sql.sh index b7fd166d..9ce3fb34 100755 --- a/tasks/docs/validate/documented-sql.sh +++ b/tasks/docs/validate/documented-sql.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash #MISE description="Validates SQL syntax for all documented files" +# Build first so generated encrypted-domain SQL exists under src/. +#MISE depends=["build"] set -e diff --git a/tasks/docs/validate/required-tags.sh b/tasks/docs/validate/required-tags.sh index 55e59557..602c37c1 100755 --- a/tasks/docs/validate/required-tags.sh +++ b/tasks/docs/validate/required-tags.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash #MISE description="Validates required Doxygen tags are present" +# Build first so generated encrypted-domain SQL exists under src/. +#MISE depends=["build"] set -e diff --git a/tasks/fixtures.toml b/tasks/fixtures.toml new file mode 100644 index 00000000..04b7d5b5 --- /dev/null +++ b/tasks/fixtures.toml @@ -0,0 +1,29 @@ +["fixture:generate:all"] +description = "Regenerate every scalar SQLx fixture in one process, driven by eql-scalars::CATALOG" +# Replaces the Python-era per-type `fixture:generate ` script and the +# TOML-glob `fixture:generate:all` loop (one `cargo test` per type). The +# generate_all_fixtures test iterates eql-scalars::CATALOG and runs every +# eql_v2_ fixture generator in a SINGLE process. The encrypted-fixture logic +# is unchanged; only enumeration + entry point changed. +# +# Writes tests/sqlx/fixtures/eql_v2_.sql (gitignored — regenerated on every +# `mise run test:sqlx`). +# +# Prerequisites: +# - mise run postgres:up (Postgres with EQL installed) +# - CS_* credentials in the shell environment. The generator needs BOTH +# pairs — they are not alternatives: +# CS_CLIENT_ACCESS_KEY + CS_WORKSPACE_CRN ZeroKMS auth (AutoStrategy) +# CS_CLIENT_ID + CS_CLIENT_KEY client key (EnvKeyProvider) +# +# Must run inside the crate — a workspace member still builds from its own dir. +dir = "{{config_root}}/tests/sqlx" +run = """ +#!/usr/bin/env bash +# bash is pinned via the `#!/usr/bin/env bash` shebang above (mise honors a `#!` +# first line), so `set -o pipefail` is available regardless of the runner's +# /bin/sh (dash on the CI images). +set -euo pipefail +cargo test --features fixture-gen --test generate_all_fixtures \ + generate_all -- --ignored --exact --nocapture +""" diff --git a/tasks/pin_search_path.sql b/tasks/pin_search_path.sql index 8369589e..75eed567 100644 --- a/tasks/pin_search_path.sql +++ b/tasks/pin_search_path.sql @@ -1,5 +1,5 @@ --! @file pin_search_path.sql ---! @brief Post-install: pin search_path on every eql_v2.* function +--! @brief Post-install: pin search_path on every eql_v2.* and eql_v3.* function --! --! This file is appended verbatim by `tasks/build.sh` to the end of every --! release variant (main, supabase, protect/stack), AFTER all `src/**/*.sql` @@ -99,7 +99,8 @@ BEGIN 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_v2' + WHERE ( + n.nspname = 'eql_v2' AND ( -- Same-type (encrypted, encrypted) operators that must inline. -- `like`/`ilike` are the SQL helpers that `~~`/`~~*` delegate to; @@ -215,13 +216,16 @@ BEGIN OR p.proargtypes[1] = (SELECT t.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 = 'int4'))) - -- XOR-aware equality term extractor on a ste_vec entry. Must - -- inline so `eql_v2.eq_term(col -> 'sel')` folds into the - -- calling query and matches a functional hash index built on - -- the same expression. - OR (p.pronargs = 1 - AND p.proname = 'eq_term' - AND p.proargtypes[0] = entry_oid) + -- Equality-term and order-term extractors — `eq_term` / `ord_term` + -- on a ste_vec entry and on the encrypted-domain family. Must + -- inline so `eql_v2.eq_term(col)` / `eql_v2.ord_term(col)` fold + -- into the calling query and match a functional index built on the + -- same expression. Name-only match (any arity-1 overload). The + -- encrypted-domain overloads are also covered by the identity + -- predicate's structural skip in the pin loop; these name-only + -- clauses are kept as belt-and-suspenders. + OR (p.pronargs = 1 AND p.proname = 'eq_term') + OR (p.pronargs = 1 AND p.proname = 'ord_term') -- Type-safe `@>` / `<@` overloads with typed needles -- (`stevec_query`, `ste_vec_entry`). Inline to the existing -- `ste_vec_contains` machinery — must stay unpinned to engage @@ -241,13 +245,34 @@ BEGIN OR p.proargtypes[0] = (SELECT t.oid FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE n.nspname = 'eql_v2' AND t.typname = 'stevec_query'))) - ); + ) + ) + OR ( + -- eql_v3 SEM index-term functions (self-contained fork). These mirror the + -- eql_v2 ore_block / hmac_256 inline-critical clauses above: the + -- comparison-wrapper inlining for the eql_v3 *_ord domains and eq_term only + -- reaches functional-index matching if these inner functions stay inlinable + -- (no SET, IMMUTABLE). The generated extractors/wrappers themselves are + -- spared by the jsonb-DOMAIN structural skip below; these SEM functions take + -- a composite (ore_block) or raw jsonb (hmac_256) arg, so they need an + -- explicit entry here. + n.nspname = 'eql_v3' + AND ( + (p.pronargs = 2 + AND p.proname IN ('ore_block_u64_8_256_eq', 'ore_block_u64_8_256_neq', + 'ore_block_u64_8_256_lt', 'ore_block_u64_8_256_lte', + 'ore_block_u64_8_256_gt', 'ore_block_u64_8_256_gte')) + OR (p.pronargs = 1 + AND p.proname = 'hmac_256' + 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_v2' + WHERE n.nspname IN ('eql_v2', 'eql_v3') -- Only normal functions ('f') and window functions ('w') accept -- ALTER FUNCTION ... SET. Aggregates ('a') would be rejected by -- ALTER ROUTINE/FUNCTION, and procedures ('p') would need ALTER @@ -259,6 +284,49 @@ BEGIN WHERE c LIKE 'search_path=%' ) AND NOT (p.oid = ANY (coalesce(inline_critical_oids, '{}'::oid[]))) + -- Encrypted-domain family — structural skip (hybrid primary mechanism). + -- A new encrypted-domain type needs NO edit here: its inline-critical + -- extractors and comparison wrappers are recognised by the identity + -- predicate — LANGUAGE sql, IMMUTABLE, and taking at least one argument + -- typed as a jsonb-backed DOMAIN of the encrypted-domain families. The + -- families live in the `eql_v3` schema (e.g. `eql_v3.int4_eq`); the + -- legacy `public.eql_v2_*` form is kept for any pre-v3 domain. The + -- predicate is proconfig-independent: the outer loop has already + -- excluded any function with a pinned `search_path`, so the only + -- functions reaching here are unpinned. This catches no core function: + -- `eql_v2_encrypted` is a composite type (not a domain), `ste_vec_entry` + -- is a domain in `eql_v2` (not `eql_v3`/`public`), and `hmac_256` is a + -- domain over `text` (not `jsonb`). The eql_v3 blockers are plpgsql, so + -- the LANGUAGE-sql guard leaves them to be pinned as intended. + AND NOT ( + p.prolang = (SELECT l.oid FROM pg_catalog.pg_language l + WHERE l.lanname = 'sql') + 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' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) + ) + ) + -- Encrypted-domain family — comment-marker fallback. Covers a + -- hand-written extension function that is inline-critical but takes no + -- domain argument (invisible to the identity predicate). The generator + -- does NOT emit this marker — every function it produces takes a domain + -- argument and is covered by the structural skip above. The marker is a + -- manual opt-in for hand-written extension functions only. + 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 -- oid::regprocedure renders as `schema.name(argtype, argtype)` and is a -- valid target for ALTER FUNCTION regardless of caller search_path. diff --git a/tasks/test.sh b/tasks/test.sh index 2e7988e9..74e044df 100755 --- a/tasks/test.sh +++ b/tasks/test.sh @@ -22,6 +22,11 @@ echo "" echo "Building EQL..." mise run --output prefix --force build +# The encrypted-domain codegen drift suite (`test:codegen`) is the deprecated +# Python generator's pytest and is intentionally not run here. The Rust +# generator is gated against the hand-written reference by the dedicated +# "Encrypted-domain codegen" CI job (`mise run codegen:parity`). + # Run lints on sqlx tests echo "" echo "==============================================" diff --git a/tasks/test/clean_install_v3.sh b/tasks/test/clean_install_v3.sh new file mode 100755 index 00000000..7c771da8 --- /dev/null +++ b/tasks/test/clean_install_v3.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +#MISE description="Install release/cipherstash-encrypt-v3.sql into a scratch DB with NO eql_v2 and smoke-test it (D11, D4)" +#USAGE flag "--port " help="Postgres port" default="7432" +#USAGE flag "--user " help="Postgres user" default="cipherstash" + +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +cd "$REPO_ROOT" + +PG_PORT="${usage_port:-7432}" +PG_USER="${usage_user:-cipherstash}" +export PGPASSWORD="${POSTGRES_PASSWORD:-password}" +SCRATCH_DB="cipherstash_v3_clean" + +ADMIN=(psql -U "$PG_USER" -h localhost -p "$PG_PORT" -d postgres -v ON_ERROR_STOP=1 -q) +RUN=(psql -U "$PG_USER" -h localhost -p "$PG_PORT" -d "$SCRATCH_DB" -v ON_ERROR_STOP=1 -q) + +test -f release/cipherstash-encrypt-v3.sql || { echo "Build first: release/cipherstash-encrypt-v3.sql missing" >&2; exit 2; } + +echo "==> (re)creating scratch database $SCRATCH_DB (no eql_v2 installed)" +"${ADMIN[@]}" -c "DROP DATABASE IF EXISTS ${SCRATCH_DB} WITH (FORCE);" +"${ADMIN[@]}" -c "CREATE DATABASE ${SCRATCH_DB};" + +cleanup() { "${ADMIN[@]}" -c "DROP DATABASE IF EXISTS ${SCRATCH_DB} WITH (FORCE);" >/dev/null 2>&1 || true; } +trap cleanup EXIT + +echo "==> installing the standalone eql_v3 surface" +"${RUN[@]}" -f release/cipherstash-encrypt-v3.sql + +echo "==> asserting NO eql_v2 schema exists (proves no v2 dependency)" +"${RUN[@]}" -c "DO \$\$ BEGIN IF EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = 'eql_v2') THEN RAISE EXCEPTION 'eql_v2 schema unexpectedly present'; END IF; END \$\$;" + +echo "==> smoke: domains, SEM types, extractors, opclass functional index (D4)" +"${RUN[@]}" <<'SQL' +-- Domains and SEM types exist in eql_v3. +SELECT 'eql_v3.int4_ord'::regtype; +SELECT 'eql_v3.hmac_256'::regtype; +SELECT 'eql_v3.ore_block_u64_8_256'::regtype; + +-- A real ordered-domain column + the documented functional index. This is the +-- D4 proof: it fails outright if the ported operator_class is absent. +CREATE TABLE v3_smoke (c eql_v3.int4_ord); +CREATE INDEX v3_smoke_ord ON v3_smoke (eql_v3.ord_term(c)); +DROP TABLE v3_smoke; +SQL + +echo "==> smoke: the shared blocker is reachable and raises" +"${RUN[@]}" <<'SQL' +DO $$ +DECLARE + raised boolean := false; +BEGIN + -- The blocker always RAISEs; catch it and assert we got the expected message. + BEGIN + PERFORM eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '<'); + EXCEPTION WHEN OTHERS THEN + raised := true; + IF SQLERRM <> 'operator < is not supported for eql_v3.int4' THEN + RAISE EXCEPTION 'blocker raised an unexpected message: %', SQLERRM; + END IF; + END; + + IF NOT raised THEN + RAISE EXCEPTION 'blocker eql_v3.encrypted_domain_unsupported_bool did not raise'; + END IF; +END $$; +SQL + +echo "clean v3 install OK (D11 + D4 proven)" diff --git a/tasks/test/self_contained_v3.sh b/tasks/test/self_contained_v3.sh new file mode 100755 index 00000000..72466624 --- /dev/null +++ b/tasks/test/self_contained_v3.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +#MISE description="Assert the eql_v3 surface is self-contained (no eql_v2 symbol/file leakage)" + +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +cd "$REPO_ROOT" + +fail=0 + +# Symbol level (design goal 1): no eql_v2. anywhere under src/v3 — the +# hand-written SEM + foundation files plus the gitignored generated scalar +# surface (present because build runs codegen). Run `mise run build` first. +# Match both schema-qualified refs (`eql_v2.`) and bare v2 entity names +# (`eql_v2_encrypted`, `eql_v2_configuration`, …). Prose like "the eql_v2 +# original is unchanged" in doc comments is intentionally still allowed. +echo "==> Symbol gate: no 'eql_v2.' / 'eql_v2_' under src/v3" +if grep -rnE 'eql_v2[._]' src/v3; then + echo "ERROR: eql_v2 symbol/entity reference found in src/v3 (must be self-contained)" >&2 + fail=1 +fi + +# File level (design goal 2): the v3-only dependency closure pulls in no file +# outside src/v3/. tsort output is one path per line. +if [[ ! -f src/deps-ordered-v3.txt ]]; then + echo "ERROR: src/deps-ordered-v3.txt missing — run 'mise run build' first" >&2 + exit 2 +fi +echo "==> File gate: every path in src/deps-ordered-v3.txt is under src/v3/" +if grep -v '^src/v3/' src/deps-ordered-v3.txt; then + echo "ERROR: v3 dep closure pulls in a path outside src/v3/ (eql_v2 file leak)" >&2 + fail=1 +fi + +# Belt-and-braces: the assembled artifact carries no eql_v2 symbol. +echo "==> Artifact gate: release/cipherstash-encrypt-v3.sql has no 'eql_v2.' / 'eql_v2_'" +if [[ ! -f release/cipherstash-encrypt-v3.sql ]]; then + echo "ERROR: release/cipherstash-encrypt-v3.sql missing — run 'mise run build' first" >&2 + exit 2 +fi +if grep -nE 'eql_v2[._]' release/cipherstash-encrypt-v3.sql; then + echo "ERROR: assembled v3 artifact contains an eql_v2 symbol/entity reference" >&2 + fail=1 +fi + +if [[ $fail -ne 0 ]]; then + echo "self-containment gate FAILED" >&2 + exit 1 +fi +echo "self-containment gate OK" diff --git a/tasks/test/splinter.sh b/tasks/test/splinter.sh index dae147d6..282b485b 100755 --- a/tasks/test/splinter.sh +++ b/tasks/test/splinter.sh @@ -9,6 +9,9 @@ set -euo pipefail +# Scope: only findings in EQL-owned schemas are gated. +EQL_OWNED_SCHEMAS="('eql_v2', 'eql_v3')" + # Pinned to splinter main as of 2026-04-27. Bump intentionally. SPLINTER_SHA="55db5b1f28e58d816f7d9136eed87eabcd95868d" SPLINTER_URL="https://raw.githubusercontent.com/supabase/splinter/${SPLINTER_SHA}/splinter.sql" @@ -81,7 +84,7 @@ function_search_path_mutable eql_v2 jsonb_contained_by function GIN-inlining: sa function_search_path_mutable eql_v2 ore_cllw function Consolidated ORE-CLLW extractor (U-006): inlinable SQL so the planner can fold `eql_v2.ore_cllw(col -> 'sel')` calls into the calling query. SET search_path would silently undo the inlining and prevent functional-index match through the extractor form. Two overloads: (jsonb), (eql_v2.ste_vec_entry). function_search_path_mutable eql_v2 has_ore_cllw function Consolidated ORE-CLLW presence check (U-006): inlinable SQL counterpart to `eql_v2.ore_cllw`. Same rationale as `ore_cllw` — must stay unpinned to inline into the calling query. Two overloads: (jsonb), (eql_v2.ste_vec_entry). function_search_path_mutable eql_v2 selector function STE-vec entry selector extractor (#219): typed (eql_v2.ste_vec_entry) overload, inlinable so the planner can fold `eql_v2.selector(col -> 'sel')` into the calling query. -function_search_path_mutable eql_v2 eq function Equality backing function for `eql_v2.ste_vec_entry × eql_v2.ste_vec_entry` (#219). Inlines to `hmac_256(a) = hmac_256(b)`; the `=` operator must reach the functional hash index on `eql_v2.hmac_256(col -> 'sel')` for bare-form field equality to engage Index Scan. +function_search_path_mutable eql_v2 eq function Equality backing function for `eql_v2.ste_vec_entry × eql_v2.ste_vec_entry` (#219). Inlines to `hmac_256(a) = hmac_256(b)`; the `=` operator must reach the functional hash index on `eql_v2.hmac_256(col -> 'sel')` for bare-form field equality to engage Index Scan. (The converged int4 wrappers moved to the eql_v3 schema — see the eql_v3 rows below.) function_search_path_mutable eql_v2 neq function Inequality backing function for `eql_v2.ste_vec_entry`. Same rationale as `eq`. function_search_path_mutable eql_v2 lt function Less-than backing function for `eql_v2.ste_vec_entry`. Inlines to `ore_cllw(a) < ore_cllw(b)`; must reach the functional btree opclass on `eql_v2.ore_cllw` for ordered field queries to engage Index Scan. function_search_path_mutable eql_v2 lte function Less-than-or-equal backing function for `eql_v2.ste_vec_entry`. Same rationale as `lt`. @@ -94,10 +97,35 @@ function_search_path_mutable eql_v2 ore_cllw_lte function Inner comparator for t function_search_path_mutable eql_v2 ore_cllw_gt function Inner comparator for the `eql_v2.ore_cllw` type's `>` operator (#221). Same rationale as `ore_cllw_eq`. function_search_path_mutable eql_v2 ore_cllw_gte function Inner comparator for the `eql_v2.ore_cllw` type's `>=` operator (#221). Same rationale as `ore_cllw_eq`. function_search_path_mutable eql_v2 -> function Typed sv-element selector lookup (U-007): inlinable SQL so the planner can fold `col -> ''` into the calling query, preserving functional-index match for the chained recipes `WHERE col -> 'sel' = $1::ste_vec_entry` (via eq_term) and `ORDER BY eql_v2.ore_cllw(col -> 'sel')`. Three overloads: (enc, text), (enc, enc), (enc, int). -function_search_path_mutable eql_v2 eq_term function XOR-aware equality term extractor on a ste_vec entry (U-007): coalesces hm and oc as bytea. Must inline so `eql_v2.eq_term(col -> 'sel')` folds into the calling query and matches a functional hash index built on the same expression — same precedent as ore_cllw / hmac_256 extractors on ste_vec_entry. +function_search_path_mutable eql_v2 eq_term function XOR-aware equality term extractor on a ste_vec entry (U-007): coalesces hm and oc as bytea. Must inline so `eql_v2.eq_term(col -> 'sel')` folds into the calling query and matches a functional hash index built on the same expression — same precedent as ore_cllw / hmac_256 extractors on ste_vec_entry. (The eql_v3.int4_eq eq_term extractor is a separate overload in the eql_v3 schema — see the eql_v3 rows below.) function_search_path_mutable eql_v2 min function Aggregate (splinter labels these type=function): ALTER AGGREGATE has no SET configuration_parameter syntax, and ALTER ROUTINE/FUNCTION reject aggregates. The aggregate's SFUNC has a pinned search_path. function_search_path_mutable eql_v2 max function Aggregate: same as min. function_search_path_mutable eql_v2 grouped_value function Aggregate: same as min. +# Encrypted-domain families live in the eql_v3 schema (the int4 family and +# future scalar domains). Their inlinable extractors and comparison wrappers +# must stay unpinned for functional-index matching, exactly as the eql_v2 +# encrypted-type operators above; splinter matches by (schema, name, type), so +# they need their own rows. The plpgsql blockers are pinned by +# tasks/pin_search_path.sql and do not surface here. +function_search_path_mutable eql_v3 eq_term function HMAC equality term extractor for the eql_v3 *_eq domains: returns eql_v3.hmac_256. Must inline so `eql_v3.eq_term(col)` folds into the calling query and matches the functional hash/btree index built on the same expression. SET search_path would disable SQL function inlining (see PostgreSQL inline_function). +function_search_path_mutable eql_v3 ord_term function ORE-block order term extractor for the eql_v3 ordered domains: returns eql_v3.ore_block_u64_8_256 (carrying the main DEFAULT btree opclass). Used inside the inlinable comparison wrappers and as the functional-index expression USING btree (eql_v3.ord_term(col)); must inline. Covers both ord_term overloads (eql_v3.int4_ord, eql_v3.int4_ord_ore). +function_search_path_mutable eql_v3 eq function Equality comparison wrapper on the eql_v3 domains. Inlines to `eq_term(a) = eq_term(b)`; must reach the functional index on eql_v3.eq_term(col) for bare-form equality to engage Index Scan. Covers the converged eq wrappers on the eql_v3 int4 variants. +function_search_path_mutable eql_v3 neq function Inequality comparison wrapper on the eql_v3 domains. Same rationale as eql_v3.eq. +function_search_path_mutable eql_v3 lt function Less-than comparison wrapper on the eql_v3 ordered domains. Inlines to `ord_term(a) < ord_term(b)`; must reach the functional btree index on eql_v3.ord_term(col) for range queries to engage Index Scan. +function_search_path_mutable eql_v3 lte function Less-than-or-equal comparison wrapper on the eql_v3 ordered domains. Same rationale as eql_v3.lt. +function_search_path_mutable eql_v3 gt function Greater-than comparison wrapper on the eql_v3 ordered domains. Same rationale as eql_v3.lt. +function_search_path_mutable eql_v3 gte function Greater-than-or-equal comparison wrapper on the eql_v3 ordered domains. Same rationale as eql_v3.lt. +function_search_path_mutable eql_v3 min function Per-domain MIN aggregate on the eql_v3 ordered domains (splinter labels aggregates type=function): ALTER AGGREGATE has no SET configuration_parameter syntax, and ALTER ROUTINE/FUNCTION reject aggregates. The aggregate's SFUNC carries a pinned search_path. +function_search_path_mutable eql_v3 max function Per-domain MAX aggregate on the eql_v3 ordered domains. Same as eql_v3.min. +function_search_path_mutable eql_v3 ore_block_u64_8_256_eq function Inner comparator for the eql_v3 ore_block_u64_8_256 type's `=` operator (self-contained SEM fork). The eql_v3 *_ord comparison wrappers inline to `ord_term(a) op ord_term(b)`; the planner only carries that through to the functional ORE index if this inner function is also inlinable (no SET, IMMUTABLE). Mirrors eql_v2.ore_block_u64_8_256_eq. +function_search_path_mutable eql_v3 ore_block_u64_8_256_neq function Inner comparator for the eql_v3 ore_block_u64_8_256 `<>` operator. Same rationale as eql_v3.ore_block_u64_8_256_eq. +function_search_path_mutable eql_v3 ore_block_u64_8_256_lt function Inner comparator for the eql_v3 ore_block_u64_8_256 `<` operator. Same rationale as eql_v3.ore_block_u64_8_256_eq. +function_search_path_mutable eql_v3 ore_block_u64_8_256_lte function Inner comparator for the eql_v3 ore_block_u64_8_256 `<=` operator. Same rationale as eql_v3.ore_block_u64_8_256_eq. +function_search_path_mutable eql_v3 ore_block_u64_8_256_gt function Inner comparator for the eql_v3 ore_block_u64_8_256 `>` operator. Same rationale as eql_v3.ore_block_u64_8_256_eq. +function_search_path_mutable eql_v3 ore_block_u64_8_256_gte function Inner comparator for the eql_v3 ore_block_u64_8_256 `>=` operator. Same rationale as eql_v3.ore_block_u64_8_256_eq. +function_search_path_mutable eql_v3 hmac_256 function HMAC equality extractor for the eql_v3 SEM fork: inlinable SQL (jsonb) constructor used inside eql_v3.eq_term. Must inline so the functional hash/btree index on eql_v3.eq_term(col) engages. Mirrors eql_v2.hmac_256. +function_search_path_mutable eql_v3 jsonb_array_to_bytea_array function Hand-written jsonb→bytea[] helper for the eql_v3 SEM fork: inlinable SQL (no SET, IMMUTABLE). Reached per-encrypted-value through eql_v3.ore_block_u64_8_256; must inline so the planner can fold it into the calling query. Pinned by neither the structural skip (it takes bare jsonb, not a jsonb-backed domain) nor an inline-critical OID clause — it carries the documented `eql-inline-critical` COMMENT marker that tasks/pin_search_path.sql honours. The eql_v2 copy stays plpgsql (pinned) by design. +function_search_path_mutable eql_v3 jsonb_array_to_ore_block_u64_8_256 function Hand-written jsonb→ore_block composite helper for the eql_v3 SEM fork: inlinable SQL (no SET, IMMUTABLE). Same rationale as eql_v3.jsonb_array_to_bytea_array — reached per-encrypted-value through eql_v3.ore_block_u64_8_256, carries the `eql-inline-critical` COMMENT marker. The eql_v2 copy stays plpgsql (pinned) by design. ALLOW # Wrap splinter (a single bare SELECT expression) into a subquery we can @@ -106,6 +134,7 @@ ALLOW splinter_body="$(tail -n +2 "$splinter_sql" | sed 's/;[[:space:]]*$//')" # Pull all findings with their metadata, then split into allowlisted vs not. +# Scoped to EQL-owned schemas — see EQL_OWNED_SCHEMAS at the top of this file. "${PSQL[@]}" -At -F $'\t' --quiet < "$all_findings_tsv" BEGIN; SET LOCAL search_path = ''; @@ -117,6 +146,7 @@ SELECT coalesce(metadata->>'name', ''), coalesce(metadata->>'type', '') FROM (${splinter_body}) splinter +WHERE coalesce(metadata->>'schema', '') IN ${EQL_OWNED_SCHEMAS} ORDER BY level, name, detail; COMMIT; SQL @@ -155,11 +185,14 @@ awk -F'\t' \ # Touch in case awk didn't write either file (no findings at all). touch "$findings_tsv" "$allowlisted_tsv" +# Summary scoped to the same schemas the gate considers, so the count line +# matches what was actually checked. "${PSQL[@]}" -At -F $'\t' --quiet < "$summary_by_rule" BEGIN; SET LOCAL search_path = ''; SELECT level, name, count(*) FROM (${splinter_body}) splinter +WHERE coalesce(metadata->>'schema', '') IN ${EQL_OWNED_SCHEMAS} GROUP BY level, name ORDER BY CASE level WHEN 'ERROR' THEN 0 WHEN 'WARN' THEN 1 WHEN 'INFO' THEN 2 ELSE 3 END, @@ -175,7 +208,7 @@ warns="$(awk -F'\t' '$2 == "WARN"' "$findings_tsv" | wc -l | tr -d ' ')" infos="$(awk -F'\t' '$2 == "INFO"' "$findings_tsv" | wc -l | tr -d ' ')" echo -echo "Splinter findings: raw=${raw_total} (allowlisted=${allowlisted_total}, unallowlisted=${total} — ERROR=${errors} WARN=${warns} INFO=${infos})" +echo "Splinter findings: raw=${raw_total} (allowlisted=${allowlisted_total}, unmatched=${total} — ERROR=${errors} WARN=${warns} INFO=${infos})" echo printf 'LEVEL\tRULE\tCOUNT (raw)\n' cat "$summary_by_rule" @@ -188,7 +221,7 @@ fi if [[ "$total" -gt 0 ]]; then echo - echo "Unallowlisted findings:" + echo "Findings not covered by the allowlist:" awk -F'\t' '{ printf " - [%s] %s — %s\n", $2, $1, $3 }' "$findings_tsv" fi @@ -198,11 +231,12 @@ if [[ -n "${GITHUB_STEP_SUMMARY:-}" ]]; then echo "## Supabase splinter (database linter)" echo echo "Pinned to [\`splinter@${SPLINTER_SHA:0:12}\`](https://github.com/supabase/splinter/tree/${SPLINTER_SHA})." + echo "Scope: schemas owned by EQL (${EQL_OWNED_SCHEMAS//[\'()]/}). Findings outside these schemas are not reported." echo - echo "**${raw_total} raw findings** (allowlisted: ${allowlisted_total}, unallowlisted: ${total} — ERROR: ${errors}, WARN: ${warns}, INFO: ${infos})" + echo "**${raw_total} raw findings** (allowlisted: ${allowlisted_total}, unmatched: ${total} — ERROR: ${errors}, WARN: ${warns}, INFO: ${infos})" echo if [[ "$total" -gt 0 ]]; then - echo "### Unallowlisted findings (action required)" + echo "### Unmatched findings (action required)" echo echo "| Level | Rule | Detail |" echo "| --- | --- | --- |" diff --git a/tasks/uninstall-protect.sql b/tasks/uninstall-protect.sql index 83fddc7d..eb48602e 100644 --- a/tasks/uninstall-protect.sql +++ b/tasks/uninstall-protect.sql @@ -1 +1,2 @@ DROP SCHEMA IF EXISTS eql_v2 CASCADE; +DROP SCHEMA IF EXISTS eql_v3 CASCADE; diff --git a/tasks/uninstall-v3.sql b/tasks/uninstall-v3.sql new file mode 100644 index 00000000..ce680dc9 --- /dev/null +++ b/tasks/uninstall-v3.sql @@ -0,0 +1,3 @@ +-- Uninstall the standalone eql_v3 surface. CASCADE removes the domains, SEM +-- types, operators, opclass, and any columns typed with the eql_v3 domains. +DROP SCHEMA IF EXISTS eql_v3 CASCADE; diff --git a/tasks/uninstall.sql b/tasks/uninstall.sql index d7777870..e087e2a8 100644 --- a/tasks/uninstall.sql +++ b/tasks/uninstall.sql @@ -10,3 +10,8 @@ END $$; DROP SCHEMA IF EXISTS eql_v2 CASCADE; + +-- Encrypted-domain families (eql_v3.int4 and future scalar domains) live in +-- their own schema; drop it too. CASCADE removes the domains and any columns +-- typed with them. +DROP SCHEMA IF EXISTS eql_v3 CASCADE; diff --git a/tests/codegen/reference/README.md b/tests/codegen/reference/README.md new file mode 100644 index 00000000..fb2de720 --- /dev/null +++ b/tests/codegen/reference/README.md @@ -0,0 +1,27 @@ +# Codegen reference + +The SQL files under `int4/` are the hand-maintained golden reference for the encrypted-domain scalar generator, the Rust crate `crates/eql-codegen` (embedded minijinja templates in `crates/eql-codegen/templates/*.j2`). `int4` is the **single golden master**: the generator is type-generic — its templates are pure token substitution driven by the `eql_scalars::CATALOG` rows (`crates/eql-scalars/src/lib.rs`) — so one anchored type detects all template/term drift for every current and future scalar. + +Each reference file's first line is a `-- REFERENCE:` provenance marker; everything after it is the generated body verbatim, starting with the template-owned `-- AUTOMATICALLY GENERATED FILE.` header. + +The parity gate runs the generator (`cargo run -p eql-codegen`, which writes the real `src/v3/scalars/int4/` tree) and asserts its output matches these files **byte-for-byte** after dropping that single provenance line. It runs three ways, all on the same reference: + +- `mise run codegen:parity` (`tasks/codegen-parity.sh`) — the CI shell gate. It first compares the generated `int4` SQL *file set* against the golden `*.sql` set (`comm -23` against `git ls-files` excludes the committed, hand-written `int4_extensions.sql`, which has no golden counterpart) to catch extra/dropped files, then `diff`s each golden file against its generated counterpart after `tail -n +2` drops the provenance line. Any whitespace or blank-line drift fails — there is no normalization. +- `crates/eql-codegen/tests/parity.rs` (`rust_generator_matches_int4_golden_files`) — runs `generate_all` into a temp dir and byte-compares the materialised `int4` SQL surface against the same golden. +- the in-crate golden tests in `crates/eql-codegen/src/generate.rs` — byte-compare each `render_*_file` output against the corresponding reference. + +The golden reference, not any retired generator, is the sole oracle. If the generator diverges, either it regressed (fix `crates/eql-codegen`) or the reference is being updated deliberately (commit the new `int4` reference in the same PR). + +See `docs/reference/adding-a-scalar-encrypted-domain-type.md` §6 for the full generator story (catalog source of truth, minijinja templates, term capabilities). + +## No committed fixture values + +Plaintext fixture lists are **not** generated and **not** committed as `_values.rs` files — there are none in the tree. They live in the catalog as `eql_scalars::INT4_VALUES` / `INT2_VALUES`, materialised at compile time by the `int_values!` macro in `crates/eql-scalars/src/lib.rs` from each `CATALOG` row, and pinned by `eql-scalars`'s own `values_tests`. The parity gate only globs `*.sql`; it does not check any `values.rs`. + +## New scalar types do not add a reference + +Adding a scalar type (`int2`, `int8`, …) does **not** add a `tests/codegen/reference//` directory. A per-type baseline would be redundant: the SQL is byte-identical to `int4` modulo the type token, so it can only fail when `int4`'s baseline already would. New types are guaranteed three other ways: + +- the `int4` reference here anchors the shared generator (templates + the `Term` enum's capability `impl`s in `crates/eql-scalars`); +- a catalog row plus the compiler and `eql-scalars`'s `#[test]`/`values_tests` over `CATALOG` validate the new type's spec and materialised value list; +- the SQLx `ordered_numeric_matrix!` suite exercises the generated SQL's *behaviour* against a real database — a far stronger guarantee than a byte comparison — and `mise run test:matrix:inventory` reconciles the matrix test-name set against the single canonical, token-normalized `tests/sqlx/snapshots/matrix_tests.txt` (cross-checked against `eql-codegen list-types`) with no database required. diff --git a/tests/codegen/reference/int4/int4_eq_functions.sql b/tests/codegen/reference/int4/int4_eq_functions.sql new file mode 100644 index 00000000..54a7c048 --- /dev/null +++ b/tests/codegen/reference/int4/int4_eq_functions.sql @@ -0,0 +1,407 @@ +-- REFERENCE: hand-maintained parity baseline for crates/eql-codegen - see ../README.md +-- AUTOMATICALLY GENERATED FILE. +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/scalars/int4/int4_types.sql +-- REQUIRE: src/v3/scalars/functions.sql +-- REQUIRE: src/v3/sem/hmac_256/functions.sql + +--! @file encrypted_domain/int4/int4_eq_functions.sql +--! @brief Functions for eql_v3.int4_eq. + +--! @brief Index extractor for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @return eql_v3.hmac_256 +CREATE FUNCTION eql_v3.eq_term(a eql_v3.int4_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.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int4_eq, b eql_v3.int4_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int4_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.int4_eq) $$; + +--! @brief Operator wrapper for eql_v3.int4_eq. +--! @param a jsonb +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.int4_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.int4_eq) = eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int4_eq, b eql_v3.int4_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a) <> eql_v3.eq_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int4_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.int4_eq) $$; + +--! @brief Operator wrapper for eql_v3.int4_eq. +--! @param a jsonb +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.int4_eq) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.eq_term(a::eql_v3.int4_eq) <> eql_v3.eq_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int4_eq, b eql_v3.int4_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int4_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a jsonb +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.int4_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int4_eq, b eql_v3.int4_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int4_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a jsonb +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.int4_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int4_eq, b eql_v3.int4_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int4_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a jsonb +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.int4_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int4_eq, b eql_v3.int4_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int4_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a jsonb +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.int4_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int4_eq, b eql_v3.int4_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int4_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a jsonb +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.int4_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4_eq, b eql_v3.int4_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4_eq, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a jsonb +--! @param b eql_v3.int4_eq +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.int4_eq) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param selector text +--! @return eql_v3.int4_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.int4_eq, selector text) +RETURNS eql_v3.int4_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param selector integer +--! @return eql_v3.int4_eq +CREATE FUNCTION eql_v3."->"(a eql_v3.int4_eq, selector integer) +RETURNS eql_v3.int4_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a jsonb +--! @param selector eql_v3.int4_eq +--! @return eql_v3.int4_eq +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int4_eq) +RETURNS eql_v3.int4_eq IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4_eq, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4_eq, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a jsonb +--! @param selector eql_v3.int4_eq +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.int4_eq) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.int4_eq, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.int4_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.int4_eq, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.int4_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.int4_eq, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.int4_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.int4_eq, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_eq, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_eq, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.int4_eq, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b eql_v3.int4_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int4_eq, b eql_v3.int4_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a eql_v3.int4_eq +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int4_eq, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_eq. +--! @param a jsonb +--! @param b eql_v3.int4_eq +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int4_eq) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_eq'; END; $$ +LANGUAGE plpgsql; diff --git a/tests/codegen/reference/int4/int4_eq_operators.sql b/tests/codegen/reference/int4/int4_eq_operators.sql new file mode 100644 index 00000000..9da0ce32 --- /dev/null +++ b/tests/codegen/reference/int4/int4_eq_operators.sql @@ -0,0 +1,234 @@ +-- REFERENCE: hand-maintained parity baseline for crates/eql-codegen - see ../README.md +-- AUTOMATICALLY GENERATED FILE. +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/scalars/int4/int4_types.sql +-- REQUIRE: src/v3/scalars/int4/int4_eq_functions.sql + +--! @file encrypted_domain/int4/int4_eq_operators.sql +--! @brief Operators for eql_v3.int4_eq. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4_eq, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4_eq, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_eq, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.int4_eq, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4_eq, RIGHTARG = eql_v3.int4_eq +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4_eq, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_eq +); diff --git a/tests/codegen/reference/int4/int4_functions.sql b/tests/codegen/reference/int4/int4_functions.sql new file mode 100644 index 00000000..dc142163 --- /dev/null +++ b/tests/codegen/reference/int4/int4_functions.sql @@ -0,0 +1,404 @@ +-- REFERENCE: hand-maintained parity baseline for crates/eql-codegen - see ../README.md +-- AUTOMATICALLY GENERATED FILE. +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/scalars/int4/int4_types.sql +-- REQUIRE: src/v3/scalars/functions.sql + +--! @file encrypted_domain/int4/int4_functions.sql +--! @brief Functions for eql_v3.int4. + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int4, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int4, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a jsonb +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '=', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int4, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int4, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a jsonb +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int4, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int4, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a jsonb +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int4, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int4, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a jsonb +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<=', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int4, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int4, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a jsonb +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int4, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int4, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a jsonb +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '>=', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int4, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int4, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a jsonb +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a jsonb +--! @param b eql_v3.int4 +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.int4) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param selector text +--! @return eql_v3.int4 +CREATE FUNCTION eql_v3."->"(a eql_v3.int4, selector text) +RETURNS eql_v3.int4 IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param selector integer +--! @return eql_v3.int4 +CREATE FUNCTION eql_v3."->"(a eql_v3.int4, selector integer) +RETURNS eql_v3.int4 IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a jsonb +--! @param selector eql_v3.int4 +--! @return eql_v3.int4 +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int4) +RETURNS eql_v3.int4 IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a jsonb +--! @param selector eql_v3.int4 +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.int4) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.int4, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.int4, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.int4, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.int4, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.int4, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.int4, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.int4, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int4, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int4, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int4, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.int4, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b eql_v3.int4 +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int4, b eql_v3.int4) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a eql_v3.int4 +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int4, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4. +--! @param a jsonb +--! @param b eql_v3.int4 +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int4) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4'; END; $$ +LANGUAGE plpgsql; diff --git a/tests/codegen/reference/int4/int4_operators.sql b/tests/codegen/reference/int4/int4_operators.sql new file mode 100644 index 00000000..fb6c03f9 --- /dev/null +++ b/tests/codegen/reference/int4/int4_operators.sql @@ -0,0 +1,228 @@ +-- REFERENCE: hand-maintained parity baseline for crates/eql-codegen - see ../README.md +-- AUTOMATICALLY GENERATED FILE. +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/scalars/int4/int4_types.sql +-- REQUIRE: src/v3/scalars/int4/int4_functions.sql + +--! @file encrypted_domain/int4/int4_operators.sql +--! @brief Operators for eql_v3.int4. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.int4, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.int4, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.int4, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.int4, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.int4, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.int4, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.int4, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.int4, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4, RIGHTARG = eql_v3.int4 +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4 +); diff --git a/tests/codegen/reference/int4/int4_ord_aggregates.sql b/tests/codegen/reference/int4/int4_ord_aggregates.sql new file mode 100644 index 00000000..95ce5d3b --- /dev/null +++ b/tests/codegen/reference/int4/int4_ord_aggregates.sql @@ -0,0 +1,63 @@ +-- REFERENCE: hand-maintained parity baseline for crates/eql-codegen - see ../README.md +-- AUTOMATICALLY GENERATED FILE. +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/scalars/int4/int4_types.sql +-- REQUIRE: src/v3/scalars/int4/int4_ord_functions.sql +-- REQUIRE: src/v3/scalars/int4/int4_ord_operators.sql + +--! @file encrypted_domain/int4/int4_ord_aggregates.sql +--! @brief Aggregates for eql_v3.int4_ord. + +--! @brief State function for min on eql_v3.int4_ord. +--! @param state eql_v3.int4_ord +--! @param value eql_v3.int4_ord +--! @return eql_v3.int4_ord +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.int4_ord, value eql_v3.int4_ord) +RETURNS eql_v3.int4_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.int4_ord. +--! @param input eql_v3.int4_ord +--! @return eql_v3.int4_ord +CREATE AGGREGATE eql_v3.min(eql_v3.int4_ord) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.int4_ord, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.int4_ord. +--! @param state eql_v3.int4_ord +--! @param value eql_v3.int4_ord +--! @return eql_v3.int4_ord +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.int4_ord, value eql_v3.int4_ord) +RETURNS eql_v3.int4_ord +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.int4_ord. +--! @param input eql_v3.int4_ord +--! @return eql_v3.int4_ord +CREATE AGGREGATE eql_v3.max(eql_v3.int4_ord) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.int4_ord, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); diff --git a/tests/codegen/reference/int4/int4_ord_functions.sql b/tests/codegen/reference/int4/int4_ord_functions.sql new file mode 100644 index 00000000..4b170fcb --- /dev/null +++ b/tests/codegen/reference/int4/int4_ord_functions.sql @@ -0,0 +1,396 @@ +-- REFERENCE: hand-maintained parity baseline for crates/eql-codegen - see ../README.md +-- AUTOMATICALLY GENERATED FILE. +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/scalars/int4/int4_types.sql +-- REQUIRE: src/v3/scalars/functions.sql +-- REQUIRE: src/v3/sem/ore_block_u64_8_256/functions.sql +-- REQUIRE: src/v3/sem/ore_block_u64_8_256/operators.sql + +--! @file encrypted_domain/int4/int4_ord_functions.sql +--! @brief Functions for eql_v3.int4_ord. + +--! @brief Index extractor for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @return eql_v3.ore_block_u64_8_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.int4_ord) +RETURNS eql_v3.ore_block_u64_8_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_u64_8_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int4_ord, b eql_v3.int4_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int4_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.int4_ord) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a jsonb +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.int4_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int4_ord, b eql_v3.int4_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int4_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.int4_ord) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a jsonb +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.int4_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int4_ord, b eql_v3.int4_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int4_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.int4_ord) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a jsonb +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.int4_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int4_ord, b eql_v3.int4_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int4_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.int4_ord) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a jsonb +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.int4_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int4_ord, b eql_v3.int4_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int4_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.int4_ord) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a jsonb +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.int4_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int4_ord, b eql_v3.int4_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int4_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.int4_ord) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord. +--! @param a jsonb +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.int4_ord) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int4_ord, b eql_v3.int4_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int4_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a jsonb +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.int4_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4_ord, b eql_v3.int4_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4_ord, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a jsonb +--! @param b eql_v3.int4_ord +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.int4_ord) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param selector text +--! @return eql_v3.int4_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.int4_ord, selector text) +RETURNS eql_v3.int4_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param selector integer +--! @return eql_v3.int4_ord +CREATE FUNCTION eql_v3."->"(a eql_v3.int4_ord, selector integer) +RETURNS eql_v3.int4_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a jsonb +--! @param selector eql_v3.int4_ord +--! @return eql_v3.int4_ord +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int4_ord) +RETURNS eql_v3.int4_ord IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4_ord, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4_ord, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a jsonb +--! @param selector eql_v3.int4_ord +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.int4_ord) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.int4_ord, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.int4_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.int4_ord, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.int4_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.int4_ord, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.int4_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.int4_ord, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_ord, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_ord, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.int4_ord, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b eql_v3.int4_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int4_ord, b eql_v3.int4_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a eql_v3.int4_ord +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int4_ord, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord. +--! @param a jsonb +--! @param b eql_v3.int4_ord +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int4_ord) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_ord'; END; $$ +LANGUAGE plpgsql; diff --git a/tests/codegen/reference/int4/int4_ord_operators.sql b/tests/codegen/reference/int4/int4_ord_operators.sql new file mode 100644 index 00000000..52a52a12 --- /dev/null +++ b/tests/codegen/reference/int4/int4_ord_operators.sql @@ -0,0 +1,246 @@ +-- REFERENCE: hand-maintained parity baseline for crates/eql-codegen - see ../README.md +-- AUTOMATICALLY GENERATED FILE. +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/scalars/int4/int4_types.sql +-- REQUIRE: src/v3/scalars/int4/int4_ord_functions.sql + +--! @file encrypted_domain/int4/int4_ord_operators.sql +--! @brief Operators for eql_v3.int4_ord. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4_ord, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4_ord, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_ord, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.int4_ord, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4_ord, RIGHTARG = eql_v3.int4_ord +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4_ord, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord +); diff --git a/tests/codegen/reference/int4/int4_ord_ore_aggregates.sql b/tests/codegen/reference/int4/int4_ord_ore_aggregates.sql new file mode 100644 index 00000000..369a1938 --- /dev/null +++ b/tests/codegen/reference/int4/int4_ord_ore_aggregates.sql @@ -0,0 +1,63 @@ +-- REFERENCE: hand-maintained parity baseline for crates/eql-codegen - see ../README.md +-- AUTOMATICALLY GENERATED FILE. +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/scalars/int4/int4_types.sql +-- REQUIRE: src/v3/scalars/int4/int4_ord_ore_functions.sql +-- REQUIRE: src/v3/scalars/int4/int4_ord_ore_operators.sql + +--! @file encrypted_domain/int4/int4_ord_ore_aggregates.sql +--! @brief Aggregates for eql_v3.int4_ord_ore. + +--! @brief State function for min on eql_v3.int4_ord_ore. +--! @param state eql_v3.int4_ord_ore +--! @param value eql_v3.int4_ord_ore +--! @return eql_v3.int4_ord_ore +CREATE FUNCTION eql_v3.min_sfunc(state eql_v3.int4_ord_ore, value eql_v3.int4_ord_ore) +RETURNS eql_v3.int4_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value < state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief min aggregate for eql_v3.int4_ord_ore. +--! @param input eql_v3.int4_ord_ore +--! @return eql_v3.int4_ord_ore +CREATE AGGREGATE eql_v3.min(eql_v3.int4_ord_ore) ( + sfunc = eql_v3.min_sfunc, + stype = eql_v3.int4_ord_ore, + combinefunc = eql_v3.min_sfunc, + parallel = safe +); + +--! @brief State function for max on eql_v3.int4_ord_ore. +--! @param state eql_v3.int4_ord_ore +--! @param value eql_v3.int4_ord_ore +--! @return eql_v3.int4_ord_ore +CREATE FUNCTION eql_v3.max_sfunc(state eql_v3.int4_ord_ore, value eql_v3.int4_ord_ore) +RETURNS eql_v3.int4_ord_ore +LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE +SET search_path = pg_catalog, extensions, public +AS $$ +BEGIN + IF value > state THEN + RETURN value; + END IF; + RETURN state; +END; +$$; + +--! @brief max aggregate for eql_v3.int4_ord_ore. +--! @param input eql_v3.int4_ord_ore +--! @return eql_v3.int4_ord_ore +CREATE AGGREGATE eql_v3.max(eql_v3.int4_ord_ore) ( + sfunc = eql_v3.max_sfunc, + stype = eql_v3.int4_ord_ore, + combinefunc = eql_v3.max_sfunc, + parallel = safe +); diff --git a/tests/codegen/reference/int4/int4_ord_ore_functions.sql b/tests/codegen/reference/int4/int4_ord_ore_functions.sql new file mode 100644 index 00000000..e93c8491 --- /dev/null +++ b/tests/codegen/reference/int4/int4_ord_ore_functions.sql @@ -0,0 +1,396 @@ +-- REFERENCE: hand-maintained parity baseline for crates/eql-codegen - see ../README.md +-- AUTOMATICALLY GENERATED FILE. +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/scalars/int4/int4_types.sql +-- REQUIRE: src/v3/scalars/functions.sql +-- REQUIRE: src/v3/sem/ore_block_u64_8_256/functions.sql +-- REQUIRE: src/v3/sem/ore_block_u64_8_256/operators.sql + +--! @file encrypted_domain/int4/int4_ord_ore_functions.sql +--! @brief Functions for eql_v3.int4_ord_ore. + +--! @brief Index extractor for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @return eql_v3.ore_block_u64_8_256 +CREATE FUNCTION eql_v3.ord_term(a eql_v3.int4_ord_ore) +RETURNS eql_v3.ore_block_u64_8_256 +LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ore_block_u64_8_256(a::jsonb) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.eq(a eql_v3.int4_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.int4_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.eq(a jsonb, b eql_v3.int4_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord_ore) = eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.neq(a eql_v3.int4_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.int4_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.neq(a jsonb, b eql_v3.int4_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord_ore) <> eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lt(a eql_v3.int4_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.int4_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lt(a jsonb, b eql_v3.int4_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord_ore) < eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.lte(a eql_v3.int4_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.int4_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.lte(a jsonb, b eql_v3.int4_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord_ore) <= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gt(a eql_v3.int4_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.int4_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gt(a jsonb, b eql_v3.int4_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord_ore) > eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a) >= eql_v3.ord_term(b) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.gte(a eql_v3.int4_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.int4_ord_ore) $$; + +--! @brief Operator wrapper for eql_v3.int4_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.gte(a jsonb, b eql_v3.int4_ord_ore) +RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE +AS $$ SELECT eql_v3.ord_term(a::eql_v3.int4_ord_ore) >= eql_v3.ord_term(b) $$; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contains(a eql_v3.int4_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contains(a jsonb, b eql_v3.int4_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@>', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b jsonb +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a eql_v3.int4_ord_ore, b jsonb) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int4_ord_ore +--! @return boolean +CREATE FUNCTION eql_v3.contained_by(a jsonb, b eql_v3.int4_ord_ore) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '<@', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param selector text +--! @return eql_v3.int4_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.int4_ord_ore, selector text) +RETURNS eql_v3.int4_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param selector integer +--! @return eql_v3.int4_ord_ore +CREATE FUNCTION eql_v3."->"(a eql_v3.int4_ord_ore, selector integer) +RETURNS eql_v3.int4_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.int4_ord_ore +--! @return eql_v3.int4_ord_ore +CREATE FUNCTION eql_v3."->"(a jsonb, selector eql_v3.int4_ord_ore) +RETURNS eql_v3.int4_ord_ore IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param selector text +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4_ord_ore, selector text) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param selector integer +--! @return text +CREATE FUNCTION eql_v3."->>"(a eql_v3.int4_ord_ore, selector integer) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a jsonb +--! @param selector eql_v3.int4_ord_ore +--! @return text +CREATE FUNCTION eql_v3."->>"(a jsonb, selector eql_v3.int4_ord_ore) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '->>', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b text +--! @return boolean +CREATE FUNCTION eql_v3."?"(a eql_v3.int4_ord_ore, b text) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?|"(a eql_v3.int4_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?|', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b text[] +--! @return boolean +CREATE FUNCTION eql_v3."?&"(a eql_v3.int4_ord_ore, b text[]) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '?&', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@?"(a eql_v3.int4_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@?', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b jsonpath +--! @return boolean +CREATE FUNCTION eql_v3."@@"(a eql_v3.int4_ord_ore, b jsonpath) +RETURNS boolean IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '@@', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#>"(a eql_v3.int4_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b text[] +--! @return text +CREATE FUNCTION eql_v3."#>>"(a eql_v3.int4_ord_ore, b text[]) +RETURNS text IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#>>', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b text +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_ord_ore, b text) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b integer +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_ord_ore, b integer) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."-"(a eql_v3.int4_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '-', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b text[] +--! @return jsonb +CREATE FUNCTION eql_v3."#-"(a eql_v3.int4_ord_ore, b text[]) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '#-', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b eql_v3.int4_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int4_ord_ore, b eql_v3.int4_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a eql_v3.int4_ord_ore +--! @param b jsonb +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a eql_v3.int4_ord_ore, b jsonb) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; + +--! @brief Unsupported operator blocker for eql_v3.int4_ord_ore. +--! @param a jsonb +--! @param b eql_v3.int4_ord_ore +--! @return jsonb +CREATE FUNCTION eql_v3."||"(a jsonb, b eql_v3.int4_ord_ore) +RETURNS jsonb IMMUTABLE PARALLEL SAFE +AS $$ BEGIN RAISE EXCEPTION 'operator % is not supported for %', '||', 'eql_v3.int4_ord_ore'; END; $$ +LANGUAGE plpgsql; diff --git a/tests/codegen/reference/int4/int4_ord_ore_operators.sql b/tests/codegen/reference/int4/int4_ord_ore_operators.sql new file mode 100644 index 00000000..73e57f63 --- /dev/null +++ b/tests/codegen/reference/int4/int4_ord_ore_operators.sql @@ -0,0 +1,246 @@ +-- REFERENCE: hand-maintained parity baseline for crates/eql-codegen - see ../README.md +-- AUTOMATICALLY GENERATED FILE. +-- REQUIRE: src/v3/schema.sql +-- REQUIRE: src/v3/scalars/int4/int4_types.sql +-- REQUIRE: src/v3/scalars/int4/int4_ord_ore_functions.sql + +--! @file encrypted_domain/int4/int4_ord_ore_operators.sql +--! @brief Operators for eql_v3.int4_ord_ore. + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR = ( + FUNCTION = eql_v3.eq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore, + COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR <> ( + FUNCTION = eql_v3.neq, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore, + COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR < ( + FUNCTION = eql_v3.lt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore, + COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR <= ( + FUNCTION = eql_v3.lte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore, + COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarlesel, JOIN = scalarlejoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + FUNCTION = eql_v3.gt, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore, + COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR >= ( + FUNCTION = eql_v3.gte, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore, + COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargesel, JOIN = scalargejoinsel +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR @> ( + FUNCTION = eql_v3.contains, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR <@ ( + FUNCTION = eql_v3.contained_by, + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR -> ( + FUNCTION = eql_v3."->", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR ->> ( + FUNCTION = eql_v3."->>", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore +); + +CREATE OPERATOR ? ( + FUNCTION = eql_v3."?", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR ?| ( + FUNCTION = eql_v3."?|", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR ?& ( + FUNCTION = eql_v3."?&", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR @? ( + FUNCTION = eql_v3."@?", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR @@ ( + FUNCTION = eql_v3."@@", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonpath +); + +CREATE OPERATOR #> ( + FUNCTION = eql_v3."#>", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #>> ( + FUNCTION = eql_v3."#>>", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = integer +); + +CREATE OPERATOR - ( + FUNCTION = eql_v3."-", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR #- ( + FUNCTION = eql_v3."#-", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = text[] +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = eql_v3.int4_ord_ore +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = eql_v3.int4_ord_ore, RIGHTARG = jsonb +); + +CREATE OPERATOR || ( + FUNCTION = eql_v3."||", + LEFTARG = jsonb, RIGHTARG = eql_v3.int4_ord_ore +); diff --git a/tests/codegen/reference/int4/int4_types.sql b/tests/codegen/reference/int4/int4_types.sql new file mode 100644 index 00000000..01082ea2 --- /dev/null +++ b/tests/codegen/reference/int4/int4_types.sql @@ -0,0 +1,73 @@ +-- REFERENCE: hand-maintained parity baseline for crates/eql-codegen - see ../README.md +-- AUTOMATICALLY GENERATED FILE. +-- REQUIRE: src/v3/schema.sql + +--! @file v3/scalars/int4/int4_types.sql +--! @brief Encrypted-domain types for int4. + +DO $$ +BEGIN + --! @brief Encrypted domain eql_v3.int4. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'int4' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.int4 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.int4_eq. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'int4_eq' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.int4_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.int4_ord_ore. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'int4_ord_ore' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.int4_ord_ore AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND VALUE->>'v' = '2' + ); + END IF; + + --! @brief Encrypted domain eql_v3.int4_ord. + IF NOT EXISTS ( + SELECT 1 FROM pg_type + WHERE typname = 'int4_ord' AND typnamespace = 'eql_v3'::regnamespace + ) THEN + CREATE DOMAIN eql_v3.int4_ord AS jsonb + CHECK ( + jsonb_typeof(VALUE) = 'object' + AND VALUE ? 'v' + AND VALUE ? 'i' + AND VALUE ? 'c' + AND VALUE ? 'ob' + AND VALUE->>'v' = '2' + ); + END IF; +END +$$; diff --git a/tests/sqlx/Cargo.lock b/tests/sqlx/Cargo.lock deleted file mode 100644 index db86aeba..00000000 --- a/tests/sqlx/Cargo.lock +++ /dev/null @@ -1,2171 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "getrandom 0.3.4", - "once_cell", - "serde", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[package]] -name = "anyhow" -version = "1.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" - -[[package]] -name = "atoi" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" -dependencies = [ - "num-traits", -] - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" - -[[package]] -name = "bit-set" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" - -[[package]] -name = "bitflags" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" -dependencies = [ - "serde_core", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "borrow-or-share" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0b364ead1874514c8c2855ab558056ebfeb775653e7ae45ff72f28f8f3166c" - -[[package]] -name = "bumpalo" -version = "3.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" - -[[package]] -name = "bytecount" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - -[[package]] -name = "crossbeam-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "data-encoding" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" - -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -dependencies = [ - "serde", -] - -[[package]] -name = "email_address" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" -dependencies = [ - "serde", -] - -[[package]] -name = "eql_tests" -version = "0.1.0" -dependencies = [ - "anyhow", - "hex", - "jsonschema", - "serde", - "serde_json", - "sqlx", - "tokio", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "etcetera" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" -dependencies = [ - "cfg-if", - "home", - "windows-sys 0.48.0", -] - -[[package]] -name = "event-listener" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "fancy-regex" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277" -dependencies = [ - "bit-set", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "fluent-uri" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc74ac4d8359ae70623506d512209619e5cf8f347124910440dbc221714b328e" -dependencies = [ - "borrow-or-share", - "ref-cast", - "serde", -] - -[[package]] -name = "flume" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" -dependencies = [ - "futures-core", - "futures-sink", - "spin", -] - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "foldhash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" - -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fraction" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076045bb43dac435333ed5f04caf35c7463631d0dae2deb2638d94dd0a5b872" -dependencies = [ - "lazy_static", - "num", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-intrusive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" -dependencies = [ - "futures-core", - "lock_api", - "parking_lot", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-core", - "futures-io", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi", - "wasip2", - "wasm-bindgen", -] - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.1.5", -] - -[[package]] -name = "hashbrown" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.2.0", -] - -[[package]] -name = "hashlink" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" -dependencies = [ - "hashbrown 0.15.5", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "icu_collections" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" - -[[package]] -name = "icu_properties" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "potential_utf", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" - -[[package]] -name = "icu_provider" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" -dependencies = [ - "displaydoc", - "icu_locale_core", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "indexmap" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" -dependencies = [ - "equivalent", - "hashbrown 0.16.0", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "js-sys" -version = "0.3.98" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "jsonschema" -version = "0.46.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc59d2432e047d6090ba1d83c782d0128bd6203857978218f5614dbd3287281f" -dependencies = [ - "ahash", - "bytecount", - "data-encoding", - "email_address", - "fancy-regex", - "fraction", - "getrandom 0.3.4", - "idna", - "itoa", - "num-cmp", - "num-traits", - "percent-encoding", - "referencing", - "regex", - "regex-syntax", - "serde", - "serde_json", - "unicode-general-category", - "uuid-simd", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin", -] - -[[package]] -name = "libc" -version = "0.2.177" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" - -[[package]] -name = "libm" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" - -[[package]] -name = "libredox" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" -dependencies = [ - "bitflags", - "libc", - "redox_syscall", -] - -[[package]] -name = "libsqlite3-sys" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" -dependencies = [ - "pkg-config", - "vcpkg", -] - -[[package]] -name = "litemap" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest", -] - -[[package]] -name = "memchr" -version = "2.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" - -[[package]] -name = "micromap" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a86d3146ed3995b5913c414f6664344b9617457320782e64f0bb44afd49d74" - -[[package]] -name = "mio" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint-dig" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" -dependencies = [ - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-cmp" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa" - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "outref" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" - -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "potential_utf" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" -dependencies = [ - "zerovec", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "proc-macro2" -version = "1.0.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e0f6df8eaa422d97d72edcd152e1451618fed47fabbdbd5a8864167b1d4aff7" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "rand" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.16", -] - -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags", -] - -[[package]] -name = "ref-cast" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" -dependencies = [ - "ref-cast-impl", -] - -[[package]] -name = "ref-cast-impl" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "referencing" -version = "0.46.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb674900ca31acd75c4aaf63f48e43e719631c0539ea5a9e64163d1296bcb730" -dependencies = [ - "ahash", - "fluent-uri", - "getrandom 0.3.4", - "hashbrown 0.16.0", - "itoa", - "micromap", - "parking_lot", - "percent-encoding", - "serde_json", -] - -[[package]] -name = "regex" -version = "1.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" - -[[package]] -name = "rsa" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" -dependencies = [ - "const-oid", - "digest", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core", - "signature", - "spki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.145" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", - "serde_core", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest", - "rand_core", -] - -[[package]] -name = "slab" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -dependencies = [ - "serde", -] - -[[package]] -name = "socket2" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "sqlx" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" -dependencies = [ - "sqlx-core", - "sqlx-macros", - "sqlx-mysql", - "sqlx-postgres", - "sqlx-sqlite", -] - -[[package]] -name = "sqlx-core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" -dependencies = [ - "base64", - "bytes", - "crc", - "crossbeam-queue", - "either", - "event-listener", - "futures-core", - "futures-intrusive", - "futures-io", - "futures-util", - "hashbrown 0.15.5", - "hashlink", - "indexmap", - "log", - "memchr", - "once_cell", - "percent-encoding", - "serde", - "serde_json", - "sha2", - "smallvec", - "thiserror", - "tokio", - "tokio-stream", - "tracing", - "url", -] - -[[package]] -name = "sqlx-macros" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" -dependencies = [ - "proc-macro2", - "quote", - "sqlx-core", - "sqlx-macros-core", - "syn", -] - -[[package]] -name = "sqlx-macros-core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" -dependencies = [ - "dotenvy", - "either", - "heck", - "hex", - "once_cell", - "proc-macro2", - "quote", - "serde", - "serde_json", - "sha2", - "sqlx-core", - "sqlx-mysql", - "sqlx-postgres", - "sqlx-sqlite", - "syn", - "tokio", - "url", -] - -[[package]] -name = "sqlx-mysql" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" -dependencies = [ - "atoi", - "base64", - "bitflags", - "byteorder", - "bytes", - "crc", - "digest", - "dotenvy", - "either", - "futures-channel", - "futures-core", - "futures-io", - "futures-util", - "generic-array", - "hex", - "hkdf", - "hmac", - "itoa", - "log", - "md-5", - "memchr", - "once_cell", - "percent-encoding", - "rand", - "rsa", - "serde", - "sha1", - "sha2", - "smallvec", - "sqlx-core", - "stringprep", - "thiserror", - "tracing", - "whoami", -] - -[[package]] -name = "sqlx-postgres" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" -dependencies = [ - "atoi", - "base64", - "bitflags", - "byteorder", - "crc", - "dotenvy", - "etcetera", - "futures-channel", - "futures-core", - "futures-util", - "hex", - "hkdf", - "hmac", - "home", - "itoa", - "log", - "md-5", - "memchr", - "once_cell", - "rand", - "serde", - "serde_json", - "sha2", - "smallvec", - "sqlx-core", - "stringprep", - "thiserror", - "tracing", - "whoami", -] - -[[package]] -name = "sqlx-sqlite" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" -dependencies = [ - "atoi", - "flume", - "futures-channel", - "futures-core", - "futures-executor", - "futures-intrusive", - "futures-util", - "libsqlite3-sys", - "log", - "percent-encoding", - "serde", - "serde_urlencoded", - "sqlx-core", - "thiserror", - "tracing", - "url", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "stringprep" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" -dependencies = [ - "unicode-bidi", - "unicode-normalization", - "unicode-properties", -] - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "2.0.108" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thiserror" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tinystr" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tinyvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" -dependencies = [ - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.61.2", -] - -[[package]] -name = "tokio-macros" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-stream" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" -dependencies = [ - "once_cell", -] - -[[package]] -name = "typenum" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" - -[[package]] -name = "unicode-bidi" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" - -[[package]] -name = "unicode-general-category" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b993bddc193ae5bd0d623b49ec06ac3e9312875fdae725a975c51db1cc1677f" - -[[package]] -name = "unicode-ident" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-properties" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" - -[[package]] -name = "url" -version = "2.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "uuid-simd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b082222b4f6619906941c17eb2297fff4c2fb96cb60164170522942a200bd8" -dependencies = [ - "outref", - "vsimd", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "vsimd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" - -[[package]] -name = "wasm-bindgen" -version = "0.2.121" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.121" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.121" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.121" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "whoami" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" -dependencies = [ - "libredox", - "wasite", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - -[[package]] -name = "writeable" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" - -[[package]] -name = "yoke" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.8.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" - -[[package]] -name = "zerotrie" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/tests/sqlx/Cargo.toml b/tests/sqlx/Cargo.toml index 875383cf..e67941c1 100644 --- a/tests/sqlx/Cargo.toml +++ b/tests/sqlx/Cargo.toml @@ -4,13 +4,21 @@ version = "0.1.0" edition = "2021" [dependencies] -sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "macros"] } +sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "macros", "chrono"] } tokio = { version = "1", features = ["full"] } serde = { version = "1", features = ["derive"] } serde_json = "1" anyhow = "1" hex = "0.4" jsonschema = { version = "0.46.4", default-features = false } +cipherstash-client = { version = "0.35", features = ["tokio"] } +# chrono is already in the tree transitively (cipherstash-client / ore-rs); pin +# it as a direct dependency so the harness can name `chrono::NaiveDate` for the +# `date` scalar (Encode/Decode/Type come from the sqlx `chrono` feature above). +chrono = { version = "0.4", default-features = false } +paste = "1" +eql-scalars = { path = "../../crates/eql-scalars" } +eql-tests-macros = { path = "../../crates/eql-tests-macros" } [dev-dependencies] # None needed - tests live in this crate @@ -22,3 +30,19 @@ default = [] # it on push to main and on a nightly schedule. Run locally with: # mise run test:bench bench = [] +# Opt-in to the matrix's per-(variant, index) scale tests. Each builds +# ~5000 rows of filler plus a single selective pivot and asserts the +# planner *prefers* the functional index with `enable_seqscan` left on. +# The default index tests force seqscan off and only prove the index is +# *usable*. Off by default to keep `mise run test` fast; CI runs with +# `--features scale`. +scale = [] +# Opt-in to compiling the fixture generators. Without this feature the +# `#[cfg(feature = "fixture-gen")]` generator tests do not exist, so +# `cargo test` and CI never see them. Generators need a live Postgres and, +# in the process env, BOTH a ZeroKMS auth credential (`CS_CLIENT_ACCESS_KEY` +# + `CS_WORKSPACE_CRN`, via AutoStrategy) AND a client key (`CS_CLIENT_ID` + +# `CS_CLIENT_KEY`, via EnvKeyProvider) — the two pairs are not alternatives. +# Regenerate all fixtures with: +# mise run fixture:generate:all +fixture-gen = [] diff --git a/tests/sqlx/README.md b/tests/sqlx/README.md index ec4e92eb..978ad1f1 100644 --- a/tests/sqlx/README.md +++ b/tests/sqlx/README.md @@ -48,6 +48,24 @@ cargo test equality cargo test -- --nocapture ``` +### Generator credentials + +`mise run test:sqlx` regenerates the `eql_v2_int4` fixture before running the +suite via `mise run fixture:generate eql_v2_int4`. The generator encrypts +plaintexts in-process using `cipherstash-client` (no Proxy / no Docker +sidecar), so the following CipherStash workspace credentials must be +present in the shell environment when you run it locally or in CI: + +- `CS_CLIENT_ACCESS_KEY` + `CS_WORKSPACE_CRN` — preferred, single-token + bearer credential, picked up by `AutoStrategy::detect()`. +- `CS_CLIENT_ID` + `CS_CLIENT_KEY` — the client-key pair used by + `EnvKeyProvider` to derive the per-call data keys. + +If either set is missing the first call into the generator fails fast +during ZeroKMS handshake with a clear `anyhow` chain naming the missing +variable. Other SQLx tests do not need the `CS_*` variables — only the +fixture-regeneration step does. + ## Test Data ### Fixtures @@ -70,7 +88,7 @@ cargo test -- --nocapture **encryptindex_tables.sql**: Tables for encryption workflow tests - Table: `users` with plaintext columns for encryption testing -**like_data.sql**: Test data for LIKE operator tests +**match_data.sql**: Test data for LIKE operator tests - 3 encrypted records with bloom filter indexes diff --git a/tests/sqlx/fixtures/FIXTURE_SCHEMA.md b/tests/sqlx/fixtures/FIXTURE_SCHEMA.md index 8814dff0..c8122b06 100644 --- a/tests/sqlx/fixtures/FIXTURE_SCHEMA.md +++ b/tests/sqlx/fixtures/FIXTURE_SCHEMA.md @@ -7,13 +7,20 @@ This document defines the structure and dependencies of test fixtures used in th ``` EQL Extension (via migrations) ├── encrypted_json.sql - ├── array_data.sql + │ └── array_data.sql (extends `encrypted` table from encrypted_json) + ├── match_data.sql + ├── config_tables.sql + ├── constraint_tables.sql + ├── encryptindex_tables.sql + ├── drop_operator_classes.sql (Supabase-simulation; drops opclasses + ORE operators) ├── order_by_null_data.sql (depends on ore migration) ├── ore table (migration 002 — not a fixture) └── bench_data.sql + bench_setup.sql (depend on migration 007) + +eql_v2_int4.sql (no EQL dependency — generated, plain jsonb, not committed) ``` -All fixtures depend on the EQL extension being installed via SQLx migrations. +All fixtures except the generated `eql_v2_int4.sql` depend on the EQL extension being installed via SQLx migrations. --- @@ -182,6 +189,62 @@ CREATE TABLE bench ( --- +## eql_v2_int4.sql + +**Purpose:** 17 encrypted integers for verifying encrypted-integer fixture +structure. The set MUST include the signed extremes (`i32::MIN`/`i32::MAX`) and +zero — they are the matrix comparison pivots, which is why the count grew from +14 to 17. Unlike its neighbours, this is a **generated** fixture — produced by +`mise run fixture:generate:all` (the Rust fixture framework in +`tests/sqlx/src/fixtures/`) and **not committed** (see `.gitignore`). It is +plain SQL with **no EQL dependency**: `payload` is `jsonb`, so the script +applies standalone. + +**Regenerated every test run.** `mise run test:sqlx` invokes the generator +before `cargo test`, so a stale committed fixture cannot mask a payload-shape +regression. The generator encrypts in-process via `cipherstash-client`; it +needs a live Postgres plus **both** CipherStash credential pairs in the shell +environment (they are not alternatives): `CS_CLIENT_ACCESS_KEY` + +`CS_WORKSPACE_CRN` for ZeroKMS auth (AutoStrategy) **and** `CS_CLIENT_ID` + +`CS_CLIENT_KEY` for the client key (EnvKeyProvider). Do not hand-edit the +generated file; it is overwritten in place on every run. + +**Schema:** Table lives in the dedicated `fixtures` SQL schema (kept out of the +`public` type/domain namespace so a downstream `public.eql_v2_int4` domain can +coexist): +```sql +CREATE SCHEMA IF NOT EXISTS fixtures; +CREATE TABLE fixtures.eql_v2_int4 ( + id BIGINT PRIMARY KEY, + plaintext integer NOT NULL, + payload jsonb NOT NULL +); +``` + +**Data:** +- 17 rows, ids 1-17; `id = N` is the Nth generated value. +- `plaintext` values: `i32::MIN, -100, -1, 0, 1, 2, 5, 10, 17, 25, 42, 50, 100, 250, 1000, 9999, i32::MAX` + — the signed extremes and zero (matrix comparison pivots) plus + small/medium/large magnitudes. +- `plaintext` is the **in-table oracle**: consuming tests filter + `WHERE plaintext = N` directly, so no Rust value constant is shared. +- Each `payload` is a cipherstash-client-encrypted JSONB object carrying + `c` (ciphertext), `hm` (HMAC equality term), `ob` (ORE block ordering + term), an inert `i` metadata object, and the EQL v2 root discriminator + (`k = "ct"`, `v = 2`). + +**Used By:** +- `__scalar_matrix_fixture_shape!` arm in `tests/sqlx/src/matrix.rs` (structural verification, generated per type) +- (#225) the `eql_v2_int4` domain operator tests, via per-query `payload` casts + +**Opt-in:** Not a migration — a SQLx fixture script. Each consuming test opts +in explicitly: +```rust +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +``` + +--- + ## Validation Tests Each fixture should have a validation test to ensure correct structure: diff --git a/tests/sqlx/fixtures/drop_operator_classes.sql b/tests/sqlx/fixtures/drop_operator_classes.sql index 2c5632bb..094073aa 100644 --- a/tests/sqlx/fixtures/drop_operator_classes.sql +++ b/tests/sqlx/fixtures/drop_operator_classes.sql @@ -16,6 +16,13 @@ DROP OPERATOR FAMILY IF EXISTS eql_v2.encrypted_hash_operator_family USING hash DROP OPERATOR CLASS IF EXISTS eql_v2.ore_block_u64_8_256_operator_class USING btree CASCADE; DROP OPERATOR FAMILY IF EXISTS eql_v2.ore_block_u64_8_256_operator_family USING btree CASCADE; +-- Drop the self-contained eql_v3 ORE btree operator class too — its file carries +-- the `*operator_class.sql` suffix, so the Supabase build's `**/*operator_class.sql` +-- glob excludes it as well. Without this the unqualified-name opclass check below +-- still finds the eql_v3 copy. +DROP OPERATOR CLASS IF EXISTS eql_v3.ore_block_u64_8_256_operator_class USING btree CASCADE; +DROP OPERATOR FAMILY IF EXISTS eql_v3.ore_block_u64_8_256_operator_family USING btree CASCADE; + -- Drop ore_block_u64_8_256 operators (also excluded from Supabase build) DROP OPERATOR IF EXISTS = (eql_v2.ore_block_u64_8_256, eql_v2.ore_block_u64_8_256) CASCADE; DROP OPERATOR IF EXISTS <> (eql_v2.ore_block_u64_8_256, eql_v2.ore_block_u64_8_256) CASCADE; diff --git a/tests/sqlx/fixtures/like_data.sql b/tests/sqlx/fixtures/match_data.sql similarity index 97% rename from tests/sqlx/fixtures/like_data.sql rename to tests/sqlx/fixtures/match_data.sql index 8f5b2adc..bd7a49c5 100644 --- a/tests/sqlx/fixtures/like_data.sql +++ b/tests/sqlx/fixtures/match_data.sql @@ -1,4 +1,4 @@ --- Fixture: like_data.sql +-- Fixture: match_data.sql -- -- Creates test data for LIKE operator tests (~~ and ~~* operators) -- Tests encrypted-to-encrypted matching using bloom filter indexes diff --git a/tests/sqlx/snapshots/README.md b/tests/sqlx/snapshots/README.md new file mode 100644 index 00000000..ed363608 --- /dev/null +++ b/tests/sqlx/snapshots/README.md @@ -0,0 +1,80 @@ +# Matrix coverage inventory snapshot + +This directory holds ONE committed snapshot, `matrix_tests.txt` — the canonical, +token-normalized list of every `scalars::::*` test name in the +`encrypted_domain` SQLx binary, with each type token replaced by the literal +``. It is a **committed test baseline**, not gitignored generated SQL — keep +it in version control. + +The per-type `_matrix_tests.txt` files are gone. They were byte-identical +modulo the type token (the matrix tests are macro-generated from one +`ordered_numeric_matrix!` invocation per type with no per-type variation), so a +single canonical set plus a per-type normalize-and-compare carries the same +signal at a fraction of the committed surface. + +## What it guards + +The SQLx assertions verify that the tests which run produce the right results. +They cannot see a test that *stops running* — a matrix test that is deleted, +renamed, or hidden behind a `#[cfg]` gate simply vanishes silently, quietly +shrinking coverage. This snapshot closes that gap: it pins the *set of test +names* so any such change shows up as an added/removed line in the PR diff. + +## How it is generated / checked + +Run: + +```bash +mise run test:matrix:inventory +``` + +The task (`mise.toml`, `[tasks."test:matrix:inventory"]`): + +1. Lists the `encrypted_domain` binary ONCE with + `cargo test --no-default-features --test encrypted_domain -- --list`. +2. Discovers the set of scalar types present **from the binary's own output** + (the `scalars::::` prefixes) — never a directory glob. +3. Normalizes each type's token to `` and asserts that type's set equals the + canonical `matrix_tests.txt`. Asserts at least one type is present. +4. **Completeness cross-check:** asserts the discovered type set equals + `cargo run -p eql-codegen -- list-types` (the catalog is the single source). + A catalog type added without its matrix wiring — no `scalars::::` tests in + the binary — fails here. + +`LC_ALL=C sort` makes ordering byte-stable across locales. No database is +required — `--list` only enumerates; the suite uses runtime queries. + +It pins `--no-default-features` so the inventory is deterministic regardless of +the caller's local flags. That deliberately excludes the `scale` feature arm +(`#[cfg(feature = "scale")]`) — a known blind spot of this inventory, covered +instead by the scale gate plus the `family::mutations` negative controls. + +## CI enforcement + +The `matrix-coverage` job in `.github/workflows/test-eql.yml` runs the same +task, then `git add -N tests/sqlx/snapshots` and +`git diff --exit-code -- tests/sqlx/snapshots`. The `git add -N` makes a +brand-new, never-committed snapshot trip the diff too. A divergence (or a failed +catalog cross-check) fails the job. + +## When you must update this + +- **Adding a new scalar type** → add the catalog row in + `eql-scalars::CATALOG`, wire the SQLx matrix oracle (see + `docs/reference/adding-a-scalar-encrypted-domain-type.md` §3), then run + `mise run test:matrix:inventory`. If the new type's + normalized name set matches the canonical snapshot (it will, for a standard + `ordered_numeric_matrix!` type), no snapshot edit is needed — the cross-check + just confirms the type is wired. +- **Removing a scalar type** → remove the catalog row and its matrix wiring; the + cross-check then sees the type gone from both sides. +- **Changing which matrix tests the macro emits** → regenerate and commit + `matrix_tests.txt` in the same change: + ```bash + cd tests/sqlx + cargo test --no-default-features --test encrypted_domain -- --list \ + | sed -n 's/: test$//p' | grep '^scalars::int4::' \ + | sed -e 's/^scalars::int4::/scalars::::/' -e 's/_int4_/__/g' | LC_ALL=C sort > snapshots/matrix_tests.txt + ``` + +See `docs/reference/adding-a-scalar-encrypted-domain-type.md` §3 (matrix oracle + inventory snapshot). diff --git a/tests/sqlx/snapshots/int4_expanded.rs b/tests/sqlx/snapshots/int4_expanded.rs new file mode 100644 index 00000000..f2997d2a --- /dev/null +++ b/tests/sqlx/snapshots/int4_expanded.rs @@ -0,0 +1,28917 @@ +///`eql_v2_int4` matrix suite — generated by `scalar_types!`. +pub mod int4 { + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_sanity"] + #[doc(hidden)] + pub const matrix_int4_storage_sanity: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_storage_sanity"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 454usize, + start_col: 26usize, + end_line: 454usize, + end_col: 60usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_sanity()), + ), + }; + fn matrix_int4_storage_sanity() -> anyhow::Result<()> { + async fn matrix_int4_storage_sanity(_pool: sqlx::PgPool) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + if !!spec.sql_domain.is_empty() { + ::core::panicking::panic( + "assertion failed: !spec.sql_domain.is_empty()", + ) + } + if !::fixture_table_name() + .starts_with("fixtures.") + { + ::core::panicking::panic( + "assertion failed: ::fixture_table_name().starts_with(\"fixtures.\")", + ) + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_sanity", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_sanity; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_sanity"] + #[doc(hidden)] + pub const matrix_int4_eq_sanity: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_eq_sanity"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 454usize, + start_col: 26usize, + end_line: 454usize, + end_col: 60usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_sanity()), + ), + }; + fn matrix_int4_eq_sanity() -> anyhow::Result<()> { + async fn matrix_int4_eq_sanity(_pool: sqlx::PgPool) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + if !!spec.sql_domain.is_empty() { + ::core::panicking::panic( + "assertion failed: !spec.sql_domain.is_empty()", + ) + } + if !::fixture_table_name() + .starts_with("fixtures.") + { + ::core::panicking::panic( + "assertion failed: ::fixture_table_name().starts_with(\"fixtures.\")", + ) + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_sanity", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_sanity; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_sanity"] + #[doc(hidden)] + pub const matrix_int4_ord_sanity: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_ord_sanity"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 454usize, + start_col: 26usize, + end_line: 454usize, + end_col: 60usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_sanity()), + ), + }; + fn matrix_int4_ord_sanity() -> anyhow::Result<()> { + async fn matrix_int4_ord_sanity(_pool: sqlx::PgPool) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + if !!spec.sql_domain.is_empty() { + ::core::panicking::panic( + "assertion failed: !spec.sql_domain.is_empty()", + ) + } + if !::fixture_table_name() + .starts_with("fixtures.") + { + ::core::panicking::panic( + "assertion failed: ::fixture_table_name().starts_with(\"fixtures.\")", + ) + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_sanity", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_sanity; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_sanity"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_sanity: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_ord_ore_sanity"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 454usize, + start_col: 26usize, + end_line: 454usize, + end_col: 60usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_sanity()), + ), + }; + fn matrix_int4_ord_ore_sanity() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_sanity(_pool: sqlx::PgPool) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + if !!spec.sql_domain.is_empty() { + ::core::panicking::panic( + "assertion failed: !spec.sql_domain.is_empty()", + ) + } + if !::fixture_table_name() + .starts_with("fixtures.") + { + ::core::panicking::panic( + "assertion failed: ::fixture_table_name().starts_with(\"fixtures.\")", + ) + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_sanity", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_sanity; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_eq_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_eq_eq_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_eq_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_eq_pivot_min_correctness()), + ), + }; + fn matrix_int4_eq_eq_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_eq_eq_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_eq_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_eq_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_eq_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_eq_eq_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_eq_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_eq_pivot_max_correctness()), + ), + }; + fn matrix_int4_eq_eq_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_eq_eq_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_eq_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_eq_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_eq_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_eq_eq_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_eq_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_eq_pivot_zero_correctness()), + ), + }; + fn matrix_int4_eq_eq_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_eq_eq_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_eq_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_eq_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_neq_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_eq_neq_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_neq_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_neq_pivot_min_correctness()), + ), + }; + fn matrix_int4_eq_neq_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_eq_neq_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<>", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<>", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<>", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_neq_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_neq_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_neq_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_eq_neq_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_neq_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_neq_pivot_max_correctness()), + ), + }; + fn matrix_int4_eq_neq_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_eq_neq_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<>", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<>", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<>", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_neq_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_neq_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_neq_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_eq_neq_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_neq_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_neq_pivot_zero_correctness()), + ), + }; + fn matrix_int4_eq_neq_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_eq_neq_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<>", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<>", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<>", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_neq_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_neq_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_eq_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_eq_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_eq_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_eq_pivot_min_correctness()), + ), + }; + fn matrix_int4_ord_eq_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_eq_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_eq_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_eq_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_eq_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_eq_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_eq_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_eq_pivot_max_correctness()), + ), + }; + fn matrix_int4_ord_eq_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_eq_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_eq_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_eq_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_eq_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_eq_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_eq_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_eq_pivot_zero_correctness()), + ), + }; + fn matrix_int4_ord_eq_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_eq_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_eq_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_eq_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_neq_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_neq_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_neq_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_neq_pivot_min_correctness()), + ), + }; + fn matrix_int4_ord_neq_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_neq_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<>", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<>", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<>", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_neq_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_neq_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_neq_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_neq_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_neq_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_neq_pivot_max_correctness()), + ), + }; + fn matrix_int4_ord_neq_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_neq_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<>", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<>", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<>", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_neq_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_neq_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_neq_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_neq_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_neq_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_neq_pivot_zero_correctness()), + ), + }; + fn matrix_int4_ord_neq_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_neq_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<>", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<>", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<>", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_neq_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_neq_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_eq_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_eq_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_eq_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_eq_pivot_min_correctness()), + ), + }; + fn matrix_int4_ord_ore_eq_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_eq_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_eq_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_eq_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_eq_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_eq_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_eq_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_eq_pivot_max_correctness()), + ), + }; + fn matrix_int4_ord_ore_eq_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_eq_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_eq_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_eq_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_eq_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_eq_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_eq_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_eq_pivot_zero_correctness()), + ), + }; + fn matrix_int4_ord_ore_eq_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_eq_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_eq_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_eq_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_neq_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_neq_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_neq_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_neq_pivot_min_correctness()), + ), + }; + fn matrix_int4_ord_ore_neq_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_neq_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<>", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<>", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<>", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_neq_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_neq_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_neq_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_neq_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_neq_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_neq_pivot_max_correctness()), + ), + }; + fn matrix_int4_ord_ore_neq_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_neq_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<>", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<>", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<>", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_neq_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_neq_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_neq_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_neq_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_neq_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_neq_pivot_zero_correctness()), + ), + }; + fn matrix_int4_ord_ore_neq_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_neq_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<>", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<>", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<>", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_neq_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_neq_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lt_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_lt_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lt_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lt_pivot_min_correctness()), + ), + }; + fn matrix_int4_ord_lt_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_lt_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lt_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_lt_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lt_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_lt_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lt_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lt_pivot_max_correctness()), + ), + }; + fn matrix_int4_ord_lt_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_lt_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lt_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_lt_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lt_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_lt_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lt_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lt_pivot_zero_correctness()), + ), + }; + fn matrix_int4_ord_lt_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_lt_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lt_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_lt_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lte_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_lte_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lte_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lte_pivot_min_correctness()), + ), + }; + fn matrix_int4_ord_lte_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_lte_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lte_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_lte_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lte_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_lte_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lte_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lte_pivot_max_correctness()), + ), + }; + fn matrix_int4_ord_lte_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_lte_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lte_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_lte_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lte_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_lte_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lte_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lte_pivot_zero_correctness()), + ), + }; + fn matrix_int4_ord_lte_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_lte_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lte_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_lte_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gt_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_gt_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gt_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gt_pivot_min_correctness()), + ), + }; + fn matrix_int4_ord_gt_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_gt_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + ">", + lit, + ), + ) + }); + let expected = ::expected_forward( + ">", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, ">", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gt_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_gt_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gt_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_gt_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gt_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gt_pivot_max_correctness()), + ), + }; + fn matrix_int4_ord_gt_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_gt_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + ">", + lit, + ), + ) + }); + let expected = ::expected_forward( + ">", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, ">", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gt_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_gt_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gt_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_gt_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gt_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gt_pivot_zero_correctness()), + ), + }; + fn matrix_int4_ord_gt_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_gt_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + ">", + lit, + ), + ) + }); + let expected = ::expected_forward( + ">", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, ">", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gt_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_gt_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gte_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_gte_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gte_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gte_pivot_min_correctness()), + ), + }; + fn matrix_int4_ord_gte_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_gte_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + ">=", + lit, + ), + ) + }); + let expected = ::expected_forward( + ">=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, ">=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gte_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_gte_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gte_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_gte_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gte_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gte_pivot_max_correctness()), + ), + }; + fn matrix_int4_ord_gte_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_gte_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + ">=", + lit, + ), + ) + }); + let expected = ::expected_forward( + ">=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, ">=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gte_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_gte_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gte_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_gte_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gte_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gte_pivot_zero_correctness()), + ), + }; + fn matrix_int4_ord_gte_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_gte_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + ">=", + lit, + ), + ) + }); + let expected = ::expected_forward( + ">=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, ">=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gte_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_gte_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lt_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lt_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lt_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lt_pivot_min_correctness()), + ), + }; + fn matrix_int4_ord_ore_lt_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lt_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lt_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_lt_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lt_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lt_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lt_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lt_pivot_max_correctness()), + ), + }; + fn matrix_int4_ord_ore_lt_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lt_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lt_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_lt_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lt_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lt_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lt_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lt_pivot_zero_correctness()), + ), + }; + fn matrix_int4_ord_ore_lt_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lt_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lt_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_lt_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lte_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lte_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lte_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lte_pivot_min_correctness()), + ), + }; + fn matrix_int4_ord_ore_lte_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lte_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lte_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_lte_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lte_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lte_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lte_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lte_pivot_max_correctness()), + ), + }; + fn matrix_int4_ord_ore_lte_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lte_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lte_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_lte_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lte_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lte_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lte_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lte_pivot_zero_correctness()), + ), + }; + fn matrix_int4_ord_ore_lte_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lte_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + "<=", + lit, + ), + ) + }); + let expected = ::expected_forward( + "<=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, "<=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lte_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_lte_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gt_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gt_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gt_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gt_pivot_min_correctness()), + ), + }; + fn matrix_int4_ord_ore_gt_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gt_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + ">", + lit, + ), + ) + }); + let expected = ::expected_forward( + ">", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, ">", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gt_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_gt_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gt_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gt_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gt_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gt_pivot_max_correctness()), + ), + }; + fn matrix_int4_ord_ore_gt_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gt_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + ">", + lit, + ), + ) + }); + let expected = ::expected_forward( + ">", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, ">", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gt_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_gt_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gt_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gt_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gt_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gt_pivot_zero_correctness()), + ), + }; + fn matrix_int4_ord_ore_gt_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gt_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + ">", + lit, + ), + ) + }); + let expected = ::expected_forward( + ">", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, ">", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gt_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_gt_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gte_pivot_min_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gte_pivot_min_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gte_pivot_min_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gte_pivot_min_correctness()), + ), + }; + fn matrix_int4_ord_ore_gte_pivot_min_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gte_pivot_min_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + ">=", + lit, + ), + ) + }); + let expected = ::expected_forward( + ">=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, ">=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gte_pivot_min_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_gte_pivot_min_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gte_pivot_max_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gte_pivot_max_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gte_pivot_max_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gte_pivot_max_correctness()), + ), + }; + fn matrix_int4_ord_ore_gte_pivot_max_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gte_pivot_max_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + ">=", + lit, + ), + ) + }); + let expected = ::expected_forward( + ">=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, ">=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gte_pivot_max_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_gte_pivot_max_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gte_pivot_zero_correctness"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gte_pivot_zero_correctness: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gte_pivot_zero_correctness", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 590usize, + start_col: 22usize, + end_line: 590usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gte_pivot_zero_correctness()), + ), + }; + fn matrix_int4_ord_ore_gte_pivot_zero_correctness() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gte_pivot_zero_correctness( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let predicate = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{0} {1} {2}::jsonb::{0}", + &spec.sql_domain, + ">=", + lit, + ), + ) + }); + let expected = ::expected_forward( + ">=", + pivot, + ); + ::eql_tests::scalar_domains::assert_scalar_plaintexts::< + i32, + >(&pool, &spec.sql_domain, ">=", &predicate, &expected) + .await + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gte_pivot_zero_correctness", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_gte_pivot_zero_correctness; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_eq_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_eq_eq_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_eq_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_eq_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_eq_eq_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_eq_eq_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_eq_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_eq_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_eq_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_eq_eq_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_eq_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_eq_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_eq_eq_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_eq_eq_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_eq_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_eq_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_eq_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_eq_eq_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_eq_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_eq_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_eq_eq_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_eq_eq_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_eq_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_eq_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_neq_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_eq_neq_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_neq_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_neq_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_eq_neq_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_eq_neq_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<>", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<>"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<>", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<>", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<>", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<>", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_neq_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_neq_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_neq_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_eq_neq_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_neq_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_neq_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_eq_neq_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_eq_neq_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<>", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<>"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<>", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<>", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<>", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<>", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_neq_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_neq_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_neq_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_eq_neq_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_neq_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_neq_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_eq_neq_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_eq_neq_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<>", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<>"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<>", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<>", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<>", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<>", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_neq_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_neq_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_eq_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_eq_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_eq_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_eq_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_ord_eq_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_eq_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_eq_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_eq_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_eq_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_eq_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_eq_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_eq_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_ord_eq_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_eq_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_eq_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_eq_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_eq_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_eq_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_eq_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_eq_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_ord_eq_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_eq_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_eq_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_eq_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_neq_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_neq_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_neq_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_neq_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_ord_neq_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_neq_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<>", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<>"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<>", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<>", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<>", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<>", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_neq_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_neq_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_neq_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_neq_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_neq_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_neq_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_ord_neq_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_neq_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<>", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<>"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<>", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<>", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<>", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<>", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_neq_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_neq_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_neq_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_neq_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_neq_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_neq_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_ord_neq_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_neq_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<>", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<>"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<>", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<>", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<>", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<>", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_neq_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_neq_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_eq_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_eq_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_eq_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_eq_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_eq_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_eq_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_eq_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_eq_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_eq_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_eq_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_eq_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_eq_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_eq_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_eq_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_eq_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_eq_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_eq_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_eq_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_eq_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_eq_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_eq_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_eq_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_eq_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_eq_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_neq_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_neq_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_neq_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_neq_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_neq_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_neq_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<>", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<>"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<>", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<>", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<>", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<>", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_neq_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_neq_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_neq_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_neq_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_neq_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_neq_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_neq_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_neq_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<>", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<>"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<>", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<>", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<>", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<>", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_neq_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_neq_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_neq_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_neq_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_neq_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_neq_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_neq_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_neq_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<>", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<>"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<>", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<>", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<>", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<>", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_neq_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_neq_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lt_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_lt_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lt_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lt_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_ord_lt_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_lt_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lt_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_lt_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lt_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_lt_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lt_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lt_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_ord_lt_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_lt_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lt_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_lt_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lt_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_lt_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lt_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lt_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_ord_lt_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_lt_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lt_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_lt_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lte_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_lte_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lte_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lte_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_ord_lte_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_lte_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lte_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_lte_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lte_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_lte_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lte_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lte_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_ord_lte_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_lte_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lte_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_lte_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lte_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_lte_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lte_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lte_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_ord_lte_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_lte_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lte_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_lte_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gt_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_gt_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gt_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gt_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_ord_gt_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_gt_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + ">", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op(">"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + ">", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", ">", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", ">", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + ">", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gt_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_gt_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gt_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_gt_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gt_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gt_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_ord_gt_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_gt_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + ">", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op(">"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + ">", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", ">", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", ">", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + ">", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gt_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_gt_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gt_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_gt_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gt_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gt_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_ord_gt_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_gt_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + ">", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op(">"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + ">", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", ">", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", ">", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + ">", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gt_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_gt_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gte_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_gte_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gte_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gte_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_ord_gte_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_gte_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + ">=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op(">="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + ">=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", ">=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", ">=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + ">=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gte_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_gte_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gte_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_gte_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gte_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gte_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_ord_gte_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_gte_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + ">=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op(">="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + ">=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", ">=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", ">=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + ">=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gte_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_gte_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gte_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_gte_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gte_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gte_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_ord_gte_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_gte_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + ">=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op(">="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + ">=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", ">=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", ">=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + ">=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gte_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_gte_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lt_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lt_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lt_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lt_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_lt_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lt_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lt_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_lt_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lt_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lt_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lt_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lt_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_lt_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lt_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lt_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_lt_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lt_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lt_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lt_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lt_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_lt_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lt_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lt_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_lt_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lte_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lte_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lte_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lte_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_lte_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lte_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lte_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_lte_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lte_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lte_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lte_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lte_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_lte_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lte_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lte_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_lte_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lte_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lte_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lte_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lte_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_lte_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lte_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + "<=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op("<="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + "<=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", "<=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", "<=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + "<=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lte_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_lte_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gt_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gt_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gt_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gt_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_gt_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gt_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + ">", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op(">"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + ">", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", ">", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", ">", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + ">", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gt_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_gt_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gt_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gt_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gt_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gt_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_gt_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gt_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + ">", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op(">"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + ">", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", ">", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", ">", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + ">", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gt_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_gt_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gt_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gt_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gt_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gt_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_gt_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gt_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + ">", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op(">"), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + ">", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", ">", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", ">", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + ">", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gt_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_gt_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gte_pivot_min_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gte_pivot_min_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gte_pivot_min_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gte_pivot_min_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_gte_pivot_min_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gte_pivot_min_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::min_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + ">=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op(">="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + ">=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", ">=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", ">=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + ">=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gte_pivot_min_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_gte_pivot_min_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gte_pivot_max_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gte_pivot_max_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gte_pivot_max_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gte_pivot_max_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_gte_pivot_max_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gte_pivot_max_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::max_pivot(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + ">=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op(">="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + ">=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", ">=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", ">=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + ">=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gte_pivot_max_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_gte_pivot_max_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gte_pivot_zero_cross_shape"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gte_pivot_zero_cross_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gte_pivot_zero_cross_shape", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 631usize, + start_col: 22usize, + end_line: 631usize, + end_col: 96usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gte_pivot_zero_cross_shape()), + ), + }; + fn matrix_int4_ord_ore_gte_pivot_zero_cross_shape() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gte_pivot_zero_cross_shape( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let pivot: i32 = ::default(); + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let forward_count = ::expected_forward( + ">=", + pivot, + ) + .len() as i64; + let commuted_count = ::expected_forward( + ::eql_tests::scalar_domains::commute_op(">="), + pivot, + ) + .len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ( + "d_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "payload::{1} {0} {2}::jsonb::{1}", + ">=", + d, + lit, + ), + ) + }), + forward_count, + ), + ( + "d_j", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("payload::{1} {0} {2}::jsonb", ">=", d, lit), + ) + }), + forward_count, + ), + ( + "j_d", + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1}::jsonb {0} payload::{2}", ">=", lit, d), + ) + }), + commuted_count, + ), + ]; + let table = ::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }); + let count: i64 = sqlx::query_scalar(&count_sql) + .fetch_one(&pool) + .await?; + match (&count, &expected_count) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} op={1} pivot={2:?} shape={3} SQL={4} expected {5} rows, got {6}", + d, + ">=", + pivot, + shape_label, + count_sql, + expected_count, + count, + ), + ), + ); + } + } + }; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gte_pivot_zero_cross_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_gte_pivot_zero_cross_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_eq_supported_null"] + #[doc(hidden)] + pub const matrix_int4_eq_eq_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_eq_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_eq_supported_null()), + ), + }; + fn matrix_int4_eq_eq_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_eq_eq_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + "=", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_eq_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_eq_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_neq_supported_null"] + #[doc(hidden)] + pub const matrix_int4_eq_neq_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_neq_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_neq_supported_null()), + ), + }; + fn matrix_int4_eq_neq_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_eq_neq_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + "<>", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_neq_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_neq_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_eq_supported_null"] + #[doc(hidden)] + pub const matrix_int4_ord_eq_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_eq_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_eq_supported_null()), + ), + }; + fn matrix_int4_ord_eq_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_eq_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + "=", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_eq_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_eq_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_neq_supported_null"] + #[doc(hidden)] + pub const matrix_int4_ord_neq_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_neq_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_neq_supported_null()), + ), + }; + fn matrix_int4_ord_neq_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_neq_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + "<>", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_neq_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_neq_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_eq_supported_null"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_eq_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_eq_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_eq_supported_null()), + ), + }; + fn matrix_int4_ord_ore_eq_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_eq_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + "=", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_eq_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_eq_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_neq_supported_null"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_neq_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_neq_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_neq_supported_null()), + ), + }; + fn matrix_int4_ord_ore_neq_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_neq_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + "<>", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_neq_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_neq_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lt_supported_null"] + #[doc(hidden)] + pub const matrix_int4_ord_lt_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lt_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lt_supported_null()), + ), + }; + fn matrix_int4_ord_lt_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_lt_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + "<", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lt_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_lt_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_lte_supported_null"] + #[doc(hidden)] + pub const matrix_int4_ord_lte_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_lte_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_lte_supported_null()), + ), + }; + fn matrix_int4_ord_lte_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_lte_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + "<=", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_lte_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_lte_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gt_supported_null"] + #[doc(hidden)] + pub const matrix_int4_ord_gt_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gt_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gt_supported_null()), + ), + }; + fn matrix_int4_ord_gt_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_gt_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + ">", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gt_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_gt_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_gte_supported_null"] + #[doc(hidden)] + pub const matrix_int4_ord_gte_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_gte_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_gte_supported_null()), + ), + }; + fn matrix_int4_ord_gte_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_gte_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + ">=", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_gte_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_gte_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lt_supported_null"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lt_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lt_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lt_supported_null()), + ), + }; + fn matrix_int4_ord_ore_lt_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lt_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + "<", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lt_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_lt_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_lte_supported_null"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_lte_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_lte_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_lte_supported_null()), + ), + }; + fn matrix_int4_ord_ore_lte_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_lte_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + "<=", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_lte_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_lte_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gt_supported_null"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gt_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gt_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gt_supported_null()), + ), + }; + fn matrix_int4_ord_ore_gt_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gt_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + ">", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gt_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_gt_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_gte_supported_null"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_gte_supported_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_gte_supported_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 683usize, + start_col: 22usize, + end_line: 683usize, + end_col: 79usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_gte_supported_null()), + ), + }; + fn matrix_int4_ord_ore_gte_supported_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_gte_supported_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + &spec.sql_domain, + ">=", + ), + ) + }); + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[Some(payload), None], + ) + .await?; + ::eql_tests::scalar_domains::assert_null( + &pool, + &sql, + &[None, Some(payload)], + ) + .await?; + ::eql_tests::scalar_domains::assert_null(&pool, &sql, &[None, None]) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_gte_supported_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_gte_supported_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_eq_blocker"] + #[doc(hidden)] + pub const matrix_int4_storage_eq_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_storage_eq_blocker"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_eq_blocker()), + ), + }; + fn matrix_int4_storage_eq_blocker() -> anyhow::Result<()> { + async fn matrix_int4_storage_eq_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "=", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "=", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "=", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_eq_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_eq_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_neq_blocker"] + #[doc(hidden)] + pub const matrix_int4_storage_neq_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_storage_neq_blocker"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_neq_blocker()), + ), + }; + fn matrix_int4_storage_neq_blocker() -> anyhow::Result<()> { + async fn matrix_int4_storage_neq_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "<>", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "<>", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "<>", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_neq_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_neq_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_lt_blocker"] + #[doc(hidden)] + pub const matrix_int4_storage_lt_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_storage_lt_blocker"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_lt_blocker()), + ), + }; + fn matrix_int4_storage_lt_blocker() -> anyhow::Result<()> { + async fn matrix_int4_storage_lt_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "<", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "<", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "<", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_lt_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_lt_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_lte_blocker"] + #[doc(hidden)] + pub const matrix_int4_storage_lte_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_storage_lte_blocker"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_lte_blocker()), + ), + }; + fn matrix_int4_storage_lte_blocker() -> anyhow::Result<()> { + async fn matrix_int4_storage_lte_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "<=", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "<=", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "<=", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_lte_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_lte_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_gt_blocker"] + #[doc(hidden)] + pub const matrix_int4_storage_gt_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_storage_gt_blocker"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_gt_blocker()), + ), + }; + fn matrix_int4_storage_gt_blocker() -> anyhow::Result<()> { + async fn matrix_int4_storage_gt_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + ">", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", ">", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", ">", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_gt_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_gt_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_gte_blocker"] + #[doc(hidden)] + pub const matrix_int4_storage_gte_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_storage_gte_blocker"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_gte_blocker()), + ), + }; + fn matrix_int4_storage_gte_blocker() -> anyhow::Result<()> { + async fn matrix_int4_storage_gte_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + ">=", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", ">=", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", ">=", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_gte_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_gte_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_contains_blocker"] + #[doc(hidden)] + pub const matrix_int4_storage_contains_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_storage_contains_blocker", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_contains_blocker()), + ), + }; + fn matrix_int4_storage_contains_blocker() -> anyhow::Result<()> { + async fn matrix_int4_storage_contains_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "@>", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "@>", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "@>", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_contains_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_contains_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_contained_by_blocker"] + #[doc(hidden)] + pub const matrix_int4_storage_contained_by_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_storage_contained_by_blocker", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_contained_by_blocker()), + ), + }; + fn matrix_int4_storage_contained_by_blocker() -> anyhow::Result<()> { + async fn matrix_int4_storage_contained_by_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "<@", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "<@", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "<@", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_contained_by_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_contained_by_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_lt_blocker"] + #[doc(hidden)] + pub const matrix_int4_eq_lt_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_eq_lt_blocker"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_lt_blocker()), + ), + }; + fn matrix_int4_eq_lt_blocker() -> anyhow::Result<()> { + async fn matrix_int4_eq_lt_blocker(pool: sqlx::PgPool) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "<", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "<", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "<", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_lt_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_lt_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_lte_blocker"] + #[doc(hidden)] + pub const matrix_int4_eq_lte_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_eq_lte_blocker"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_lte_blocker()), + ), + }; + fn matrix_int4_eq_lte_blocker() -> anyhow::Result<()> { + async fn matrix_int4_eq_lte_blocker(pool: sqlx::PgPool) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "<=", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "<=", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "<=", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_lte_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_lte_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_gt_blocker"] + #[doc(hidden)] + pub const matrix_int4_eq_gt_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_eq_gt_blocker"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_gt_blocker()), + ), + }; + fn matrix_int4_eq_gt_blocker() -> anyhow::Result<()> { + async fn matrix_int4_eq_gt_blocker(pool: sqlx::PgPool) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + ">", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", ">", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", ">", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_gt_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_gt_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_gte_blocker"] + #[doc(hidden)] + pub const matrix_int4_eq_gte_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_eq_gte_blocker"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_gte_blocker()), + ), + }; + fn matrix_int4_eq_gte_blocker() -> anyhow::Result<()> { + async fn matrix_int4_eq_gte_blocker(pool: sqlx::PgPool) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + ">=", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", ">=", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", ">=", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_gte_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_gte_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_contains_blocker"] + #[doc(hidden)] + pub const matrix_int4_eq_contains_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_eq_contains_blocker"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_contains_blocker()), + ), + }; + fn matrix_int4_eq_contains_blocker() -> anyhow::Result<()> { + async fn matrix_int4_eq_contains_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "@>", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "@>", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "@>", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_contains_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_contains_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_contained_by_blocker"] + #[doc(hidden)] + pub const matrix_int4_eq_contained_by_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_contained_by_blocker", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_contained_by_blocker()), + ), + }; + fn matrix_int4_eq_contained_by_blocker() -> anyhow::Result<()> { + async fn matrix_int4_eq_contained_by_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "<@", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "<@", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "<@", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_contained_by_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_contained_by_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_contains_blocker"] + #[doc(hidden)] + pub const matrix_int4_ord_contains_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_contains_blocker", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_contains_blocker()), + ), + }; + fn matrix_int4_ord_contains_blocker() -> anyhow::Result<()> { + async fn matrix_int4_ord_contains_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "@>", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "@>", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "@>", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_contains_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_contains_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_contained_by_blocker"] + #[doc(hidden)] + pub const matrix_int4_ord_contained_by_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_contained_by_blocker", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_contained_by_blocker()), + ), + }; + fn matrix_int4_ord_contained_by_blocker() -> anyhow::Result<()> { + async fn matrix_int4_ord_contained_by_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "<@", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "<@", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "<@", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_contained_by_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_contained_by_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_contains_blocker"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_contains_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_contains_blocker", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_contains_blocker()), + ), + }; + fn matrix_int4_ord_ore_contains_blocker() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_contains_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "@>", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "@>", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "@>", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_contains_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_contains_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_contained_by_blocker"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_contained_by_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_contained_by_blocker", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 747usize, + start_col: 22usize, + end_line: 747usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_contained_by_blocker()), + ), + }; + fn matrix_int4_ord_ore_contained_by_blocker() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_contained_by_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let msg = ::eql_tests::scalar_domains::blocker_msg( + &spec.sql_domain, + "<@", + ); + let d = &spec.sql_domain; + let shapes: [(String, String); 3] = [ + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ( + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$1::jsonb::{0}", d)) + }), + "$2::jsonb".into(), + ), + ( + "$1::jsonb".into(), + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("$2::jsonb::{0}", d)) + }), + ), + ]; + for (lhs, rhs) in shapes { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT {1} {0} {2}", "<@", lhs, rhs), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + &msg, + ) + .await?; + } + let null_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{1} {0} $2::jsonb::{1}", "<@", d), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, Some(payload)], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[Some(payload), None], + &msg, + ) + .await?; + ::eql_tests::scalar_domains::assert_raises( + &pool, + &null_sql, + &[None, None], + &msg, + ) + .await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_contained_by_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_contained_by_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_payload_check"] + #[doc(hidden)] + pub const matrix_int4_storage_payload_check: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_storage_payload_check", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 814usize, + start_col: 22usize, + end_line: 814usize, + end_col: 67usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_payload_check()), + ), + }; + fn matrix_int4_storage_payload_check() -> anyhow::Result<()> { + async fn matrix_int4_storage_payload_check( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let d = &spec.sql_domain; + let baseline = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + for key in spec.variant.payload_required_keys() { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT (\'{0}\'::jsonb - \'{1}\')::{2}", + baseline, + key, + d, + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_one(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "{0} must reject payload missing `{1}`: {2}", + d, + key, + sql, + ), + ) + }), + ) + .to_string(); + if ::anyhow::__private::not( + err.contains("violates check constraint"), + ) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "expected check-constraint violation for missing `{0}` on {1}, got: {2}", + key, + d, + err, + ), + ); + error + }); + } + } + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT \'[\"v\",\"i\",\"c\"]\'::jsonb::{0}", d), + ) + }); + let err = sqlx::query(&sql) + .fetch_one(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{0} must reject non-object payload", d), + ) + }), + ) + .to_string(); + if ::anyhow::__private::not(err.contains("violates check constraint")) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "expected check-constraint violation for non-object on {0}, got: {1}", + d, + err, + ), + ); + error + }); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_payload_check", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_payload_check; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_payload_check"] + #[doc(hidden)] + pub const matrix_int4_eq_payload_check: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_eq_payload_check"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 814usize, + start_col: 22usize, + end_line: 814usize, + end_col: 67usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_payload_check()), + ), + }; + fn matrix_int4_eq_payload_check() -> anyhow::Result<()> { + async fn matrix_int4_eq_payload_check(pool: sqlx::PgPool) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let d = &spec.sql_domain; + let baseline = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + for key in spec.variant.payload_required_keys() { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT (\'{0}\'::jsonb - \'{1}\')::{2}", + baseline, + key, + d, + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_one(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "{0} must reject payload missing `{1}`: {2}", + d, + key, + sql, + ), + ) + }), + ) + .to_string(); + if ::anyhow::__private::not( + err.contains("violates check constraint"), + ) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "expected check-constraint violation for missing `{0}` on {1}, got: {2}", + key, + d, + err, + ), + ); + error + }); + } + } + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT \'[\"v\",\"i\",\"c\"]\'::jsonb::{0}", d), + ) + }); + let err = sqlx::query(&sql) + .fetch_one(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{0} must reject non-object payload", d), + ) + }), + ) + .to_string(); + if ::anyhow::__private::not(err.contains("violates check constraint")) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "expected check-constraint violation for non-object on {0}, got: {1}", + d, + err, + ), + ); + error + }); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_payload_check", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_payload_check; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_payload_check"] + #[doc(hidden)] + pub const matrix_int4_ord_payload_check: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_ord_payload_check"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 814usize, + start_col: 22usize, + end_line: 814usize, + end_col: 67usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_payload_check()), + ), + }; + fn matrix_int4_ord_payload_check() -> anyhow::Result<()> { + async fn matrix_int4_ord_payload_check( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let baseline = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + for key in spec.variant.payload_required_keys() { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT (\'{0}\'::jsonb - \'{1}\')::{2}", + baseline, + key, + d, + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_one(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "{0} must reject payload missing `{1}`: {2}", + d, + key, + sql, + ), + ) + }), + ) + .to_string(); + if ::anyhow::__private::not( + err.contains("violates check constraint"), + ) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "expected check-constraint violation for missing `{0}` on {1}, got: {2}", + key, + d, + err, + ), + ); + error + }); + } + } + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT \'[\"v\",\"i\",\"c\"]\'::jsonb::{0}", d), + ) + }); + let err = sqlx::query(&sql) + .fetch_one(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{0} must reject non-object payload", d), + ) + }), + ) + .to_string(); + if ::anyhow::__private::not(err.contains("violates check constraint")) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "expected check-constraint violation for non-object on {0}, got: {1}", + d, + err, + ), + ); + error + }); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_payload_check", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_payload_check; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_payload_check"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_payload_check: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_payload_check", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 814usize, + start_col: 22usize, + end_line: 814usize, + end_col: 67usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_payload_check()), + ), + }; + fn matrix_int4_ord_ore_payload_check() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_payload_check( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let baseline = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + for key in spec.variant.payload_required_keys() { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT (\'{0}\'::jsonb - \'{1}\')::{2}", + baseline, + key, + d, + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_one(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "{0} must reject payload missing `{1}`: {2}", + d, + key, + sql, + ), + ) + }), + ) + .to_string(); + if ::anyhow::__private::not( + err.contains("violates check constraint"), + ) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "expected check-constraint violation for missing `{0}` on {1}, got: {2}", + key, + d, + err, + ), + ); + error + }); + } + } + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT \'[\"v\",\"i\",\"c\"]\'::jsonb::{0}", d), + ) + }); + let err = sqlx::query(&sql) + .fetch_one(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{0} must reject non-object payload", d), + ) + }), + ) + .to_string(); + if ::anyhow::__private::not(err.contains("violates check constraint")) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "expected check-constraint violation for non-object on {0}, got: {1}", + d, + err, + ), + ); + error + }); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_payload_check", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_payload_check; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_path_op_blockers"] + #[doc(hidden)] + pub const matrix_int4_storage_path_op_blockers: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_storage_path_op_blockers", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 887usize, + start_col: 22usize, + end_line: 887usize, + end_col: 70usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_path_op_blockers()), + ), + }; + fn matrix_int4_storage_path_op_blockers() -> anyhow::Result<()> { + async fn matrix_int4_storage_path_op_blockers( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + for op in ["->", "->>"] { + let msg = ::eql_tests::scalar_domains::blocker_msg(d, op); + for sql in [ + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} \'field\'::text", + d, + op, + ), + ) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{0} {1} 0::integer", d, op), + ) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb {0} $1::jsonb::{1}", op, d), + ) + }), + ] { + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload)], + &msg, + ) + .await?; + } + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_path_op_blockers", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_path_op_blockers; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_path_op_blockers"] + #[doc(hidden)] + pub const matrix_int4_eq_path_op_blockers: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_eq_path_op_blockers"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 887usize, + start_col: 22usize, + end_line: 887usize, + end_col: 70usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_path_op_blockers()), + ), + }; + fn matrix_int4_eq_path_op_blockers() -> anyhow::Result<()> { + async fn matrix_int4_eq_path_op_blockers( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + for op in ["->", "->>"] { + let msg = ::eql_tests::scalar_domains::blocker_msg(d, op); + for sql in [ + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} \'field\'::text", + d, + op, + ), + ) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{0} {1} 0::integer", d, op), + ) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb {0} $1::jsonb::{1}", op, d), + ) + }), + ] { + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload)], + &msg, + ) + .await?; + } + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_path_op_blockers", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_path_op_blockers; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_path_op_blockers"] + #[doc(hidden)] + pub const matrix_int4_ord_path_op_blockers: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_path_op_blockers", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 887usize, + start_col: 22usize, + end_line: 887usize, + end_col: 70usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_path_op_blockers()), + ), + }; + fn matrix_int4_ord_path_op_blockers() -> anyhow::Result<()> { + async fn matrix_int4_ord_path_op_blockers( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + for op in ["->", "->>"] { + let msg = ::eql_tests::scalar_domains::blocker_msg(d, op); + for sql in [ + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} \'field\'::text", + d, + op, + ), + ) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{0} {1} 0::integer", d, op), + ) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb {0} $1::jsonb::{1}", op, d), + ) + }), + ] { + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload)], + &msg, + ) + .await?; + } + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_path_op_blockers", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_path_op_blockers; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_path_op_blockers"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_path_op_blockers: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_path_op_blockers", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 887usize, + start_col: 22usize, + end_line: 887usize, + end_col: 70usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_path_op_blockers()), + ), + }; + fn matrix_int4_ord_ore_path_op_blockers() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_path_op_blockers( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + for op in ["->", "->>"] { + let msg = ::eql_tests::scalar_domains::blocker_msg(d, op); + for sql in [ + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} \'field\'::text", + d, + op, + ), + ) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb::{0} {1} 0::integer", d, op), + ) + }), + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT $1::jsonb {0} $1::jsonb::{1}", op, d), + ) + }), + ] { + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload)], + &msg, + ) + .await?; + } + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_path_op_blockers", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_path_op_blockers; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_native_absent_ops"] + #[doc(hidden)] + pub const matrix_int4_storage_native_absent_ops: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_storage_native_absent_ops", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 944usize, + start_col: 22usize, + end_line: 944usize, + end_col: 71usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_native_absent_ops()), + ), + }; + fn matrix_int4_storage_native_absent_ops() -> anyhow::Result<()> { + async fn matrix_int4_storage_native_absent_ops( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + for op in ["~~", "~~*"] { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + d, + op, + ), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + "operator does not exist", + ) + .await?; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_native_absent_ops", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_native_absent_ops; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_native_absent_ops"] + #[doc(hidden)] + pub const matrix_int4_eq_native_absent_ops: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_native_absent_ops", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 944usize, + start_col: 22usize, + end_line: 944usize, + end_col: 71usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_native_absent_ops()), + ), + }; + fn matrix_int4_eq_native_absent_ops() -> anyhow::Result<()> { + async fn matrix_int4_eq_native_absent_ops( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + for op in ["~~", "~~*"] { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + d, + op, + ), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + "operator does not exist", + ) + .await?; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_native_absent_ops", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_native_absent_ops; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_native_absent_ops"] + #[doc(hidden)] + pub const matrix_int4_ord_native_absent_ops: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_native_absent_ops", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 944usize, + start_col: 22usize, + end_line: 944usize, + end_col: 71usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_native_absent_ops()), + ), + }; + fn matrix_int4_ord_native_absent_ops() -> anyhow::Result<()> { + async fn matrix_int4_ord_native_absent_ops( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + for op in ["~~", "~~*"] { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + d, + op, + ), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + "operator does not exist", + ) + .await?; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_native_absent_ops", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_native_absent_ops; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_native_absent_ops"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_native_absent_ops: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_native_absent_ops", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 944usize, + start_col: 22usize, + end_line: 944usize, + end_col: 71usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_native_absent_ops()), + ), + }; + fn matrix_int4_ord_ore_native_absent_ops() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_native_absent_ops( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + for op in ["~~", "~~*"] { + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT $1::jsonb::{0} {1} $2::jsonb::{0}", + d, + op, + ), + ) + }); + ::eql_tests::scalar_domains::assert_raises( + &pool, + &sql, + &[Some(payload), Some(payload)], + "operator does not exist", + ) + .await?; + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_native_absent_ops", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_native_absent_ops; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_typed_column_blocker"] + #[doc(hidden)] + pub const matrix_int4_storage_typed_column_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_storage_typed_column_blocker", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 997usize, + start_col: 22usize, + end_line: 997usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_typed_column_blocker()), + ), + }; + fn matrix_int4_storage_typed_column_blocker() -> anyhow::Result<()> { + async fn matrix_int4_storage_typed_column_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let mut tx = pool.begin().await?; + let create_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE typed_col (id integer GENERATED ALWAYS AS IDENTITY,value {0}) ON COMMIT DROP", + d, + ), + ) + }); + sqlx::query(&create_sql).execute(&mut *tx).await?; + let insert_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO typed_col(value) VALUES ($1::jsonb::{0})", + d, + ), + ) + }); + sqlx::query(&insert_sql).bind(payload).execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "=", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "=", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "="); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "<>", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "<>", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "<>"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "<", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "<", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "<"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "<=", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "<=", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "<="); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + ">", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", ">", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, ">"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + ">=", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", ">=", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, ">="); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "@>", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "@>", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "@>"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "<@", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "<@", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "<@"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_typed_column_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_typed_column_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_typed_column_blocker"] + #[doc(hidden)] + pub const matrix_int4_eq_typed_column_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_typed_column_blocker", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 997usize, + start_col: 22usize, + end_line: 997usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_typed_column_blocker()), + ), + }; + fn matrix_int4_eq_typed_column_blocker() -> anyhow::Result<()> { + async fn matrix_int4_eq_typed_column_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let mut tx = pool.begin().await?; + let create_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE typed_col (id integer GENERATED ALWAYS AS IDENTITY,value {0}) ON COMMIT DROP", + d, + ), + ) + }); + sqlx::query(&create_sql).execute(&mut *tx).await?; + let insert_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO typed_col(value) VALUES ($1::jsonb::{0})", + d, + ), + ) + }); + sqlx::query(&insert_sql).bind(payload).execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "<", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "<", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "<"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "<=", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "<=", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "<="); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + ">", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", ">", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, ">"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + ">=", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", ">=", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, ">="); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "@>", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "@>", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "@>"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "<@", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "<@", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "<@"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_typed_column_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_typed_column_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_typed_column_blocker"] + #[doc(hidden)] + pub const matrix_int4_ord_typed_column_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_typed_column_blocker", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 997usize, + start_col: 22usize, + end_line: 997usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_typed_column_blocker()), + ), + }; + fn matrix_int4_ord_typed_column_blocker() -> anyhow::Result<()> { + async fn matrix_int4_ord_typed_column_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let mut tx = pool.begin().await?; + let create_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE typed_col (id integer GENERATED ALWAYS AS IDENTITY,value {0}) ON COMMIT DROP", + d, + ), + ) + }); + sqlx::query(&create_sql).execute(&mut *tx).await?; + let insert_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO typed_col(value) VALUES ($1::jsonb::{0})", + d, + ), + ) + }); + sqlx::query(&insert_sql).bind(payload).execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "@>", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "@>", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "@>"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "<@", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "<@", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "<@"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_typed_column_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_typed_column_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_typed_column_blocker"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_typed_column_blocker: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_typed_column_blocker", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 997usize, + start_col: 22usize, + end_line: 997usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_typed_column_blocker()), + ), + }; + fn matrix_int4_ord_ore_typed_column_blocker() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_typed_column_blocker( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let mut tx = pool.begin().await?; + let create_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE typed_col (id integer GENERATED ALWAYS AS IDENTITY,value {0}) ON COMMIT DROP", + d, + ), + ) + }); + sqlx::query(&create_sql).execute(&mut *tx).await?; + let insert_sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO typed_col(value) VALUES ($1::jsonb::{0})", + d, + ), + ) + }); + sqlx::query(&insert_sql).bind(payload).execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "@>", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "@>", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "@>"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM typed_col WHERE value {0} value", + "<@", + ), + ) + }); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("{1} column {0} must raise", "<@", d), + ) + }), + ) + .to_string(); + let expected = ::eql_tests::scalar_domains::blocker_msg(d, "<@"); + if ::anyhow::__private::not(err.contains(&expected)) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "unexpected error for {0}: got {1}, want {2}", + sql, + err, + expected, + ), + ); + error + }); + } + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_typed_column_blocker", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_typed_column_blocker; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_planner_metadata_eq"] + #[doc(hidden)] + pub const matrix_int4_eq_planner_metadata_eq: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_planner_metadata_eq", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1078usize, + start_col: 22usize, + end_line: 1078usize, + end_col: 78usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_planner_metadata_eq()), + ), + }; + fn matrix_int4_eq_planner_metadata_eq() -> anyhow::Result<()> { + async fn matrix_int4_eq_planner_metadata_eq( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let d = &spec.sql_domain; + let ops: &[&str] = &["=", "<>"]; + let op_list = ops + .iter() + .map(|o| ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("\'{0}\'", o)) + })) + .collect::>() + .join(", "); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "\n SELECT o.oprname,\n lt.typname AS lhs,\n rt.typname AS rhs,\n o.oprcom <> 0 AS has_commutator,\n o.oprnegate <> 0 AS has_negator,\n o.oprrest::oid <> 0 AS has_restrict,\n o.oprjoin::oid <> 0 AS has_join\n FROM pg_catalog.pg_operator o\n JOIN pg_catalog.pg_type lt ON lt.oid = o.oprleft\n JOIN pg_catalog.pg_type rt ON rt.oid = o.oprright\n WHERE o.oprname IN ({0})\n AND (\'{1}\'::regtype = o.oprleft OR \'{1}\'::regtype = o.oprright)\n ", + op_list, + d, + ), + ) + }); + let rows: Vec<(String, String, String, bool, bool, bool, bool)> = sqlx::query_as( + &sql, + ) + .fetch_all(&pool) + .await?; + let expected = ops.len() * 3; + if ::anyhow::__private::not(rows.len() == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "expected {2} rows ({0} ops x 3 arg shapes) on {3}, got {1}", + ops.len(), + rows.len(), + expected, + d, + ), + ) + }), + ), + ); + } + for (op, lhs, rhs, has_com, has_neg, has_rest, has_join) in &rows { + if ::anyhow::__private::not(*has_com) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare COMMUTATOR", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_neg) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare NEGATOR", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_rest) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare RESTRICT", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_join) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare JOIN", + op, + lhs, + rhs, + ), + ); + error + }); + } + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_planner_metadata_eq", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_planner_metadata_eq; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_planner_metadata_eq"] + #[doc(hidden)] + pub const matrix_int4_ord_planner_metadata_eq: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_planner_metadata_eq", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1078usize, + start_col: 22usize, + end_line: 1078usize, + end_col: 78usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_planner_metadata_eq()), + ), + }; + fn matrix_int4_ord_planner_metadata_eq() -> anyhow::Result<()> { + async fn matrix_int4_ord_planner_metadata_eq( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let ops: &[&str] = &["=", "<>"]; + let op_list = ops + .iter() + .map(|o| ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("\'{0}\'", o)) + })) + .collect::>() + .join(", "); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "\n SELECT o.oprname,\n lt.typname AS lhs,\n rt.typname AS rhs,\n o.oprcom <> 0 AS has_commutator,\n o.oprnegate <> 0 AS has_negator,\n o.oprrest::oid <> 0 AS has_restrict,\n o.oprjoin::oid <> 0 AS has_join\n FROM pg_catalog.pg_operator o\n JOIN pg_catalog.pg_type lt ON lt.oid = o.oprleft\n JOIN pg_catalog.pg_type rt ON rt.oid = o.oprright\n WHERE o.oprname IN ({0})\n AND (\'{1}\'::regtype = o.oprleft OR \'{1}\'::regtype = o.oprright)\n ", + op_list, + d, + ), + ) + }); + let rows: Vec<(String, String, String, bool, bool, bool, bool)> = sqlx::query_as( + &sql, + ) + .fetch_all(&pool) + .await?; + let expected = ops.len() * 3; + if ::anyhow::__private::not(rows.len() == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "expected {2} rows ({0} ops x 3 arg shapes) on {3}, got {1}", + ops.len(), + rows.len(), + expected, + d, + ), + ) + }), + ), + ); + } + for (op, lhs, rhs, has_com, has_neg, has_rest, has_join) in &rows { + if ::anyhow::__private::not(*has_com) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare COMMUTATOR", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_neg) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare NEGATOR", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_rest) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare RESTRICT", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_join) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare JOIN", + op, + lhs, + rhs, + ), + ); + error + }); + } + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_planner_metadata_eq", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_planner_metadata_eq; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_planner_metadata_eq"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_planner_metadata_eq: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_planner_metadata_eq", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1078usize, + start_col: 22usize, + end_line: 1078usize, + end_col: 78usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_planner_metadata_eq()), + ), + }; + fn matrix_int4_ord_ore_planner_metadata_eq() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_planner_metadata_eq( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let ops: &[&str] = &["=", "<>"]; + let op_list = ops + .iter() + .map(|o| ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("\'{0}\'", o)) + })) + .collect::>() + .join(", "); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "\n SELECT o.oprname,\n lt.typname AS lhs,\n rt.typname AS rhs,\n o.oprcom <> 0 AS has_commutator,\n o.oprnegate <> 0 AS has_negator,\n o.oprrest::oid <> 0 AS has_restrict,\n o.oprjoin::oid <> 0 AS has_join\n FROM pg_catalog.pg_operator o\n JOIN pg_catalog.pg_type lt ON lt.oid = o.oprleft\n JOIN pg_catalog.pg_type rt ON rt.oid = o.oprright\n WHERE o.oprname IN ({0})\n AND (\'{1}\'::regtype = o.oprleft OR \'{1}\'::regtype = o.oprright)\n ", + op_list, + d, + ), + ) + }); + let rows: Vec<(String, String, String, bool, bool, bool, bool)> = sqlx::query_as( + &sql, + ) + .fetch_all(&pool) + .await?; + let expected = ops.len() * 3; + if ::anyhow::__private::not(rows.len() == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "expected {2} rows ({0} ops x 3 arg shapes) on {3}, got {1}", + ops.len(), + rows.len(), + expected, + d, + ), + ) + }), + ), + ); + } + for (op, lhs, rhs, has_com, has_neg, has_rest, has_join) in &rows { + if ::anyhow::__private::not(*has_com) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare COMMUTATOR", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_neg) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare NEGATOR", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_rest) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare RESTRICT", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_join) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare JOIN", + op, + lhs, + rhs, + ), + ); + error + }); + } + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_planner_metadata_eq", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_planner_metadata_eq; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_planner_metadata_ord"] + #[doc(hidden)] + pub const matrix_int4_ord_planner_metadata_ord: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_planner_metadata_ord", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1078usize, + start_col: 22usize, + end_line: 1078usize, + end_col: 78usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_planner_metadata_ord()), + ), + }; + fn matrix_int4_ord_planner_metadata_ord() -> anyhow::Result<()> { + async fn matrix_int4_ord_planner_metadata_ord( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let ops: &[&str] = &["<", "<=", ">", ">="]; + let op_list = ops + .iter() + .map(|o| ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("\'{0}\'", o)) + })) + .collect::>() + .join(", "); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "\n SELECT o.oprname,\n lt.typname AS lhs,\n rt.typname AS rhs,\n o.oprcom <> 0 AS has_commutator,\n o.oprnegate <> 0 AS has_negator,\n o.oprrest::oid <> 0 AS has_restrict,\n o.oprjoin::oid <> 0 AS has_join\n FROM pg_catalog.pg_operator o\n JOIN pg_catalog.pg_type lt ON lt.oid = o.oprleft\n JOIN pg_catalog.pg_type rt ON rt.oid = o.oprright\n WHERE o.oprname IN ({0})\n AND (\'{1}\'::regtype = o.oprleft OR \'{1}\'::regtype = o.oprright)\n ", + op_list, + d, + ), + ) + }); + let rows: Vec<(String, String, String, bool, bool, bool, bool)> = sqlx::query_as( + &sql, + ) + .fetch_all(&pool) + .await?; + let expected = ops.len() * 3; + if ::anyhow::__private::not(rows.len() == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "expected {2} rows ({0} ops x 3 arg shapes) on {3}, got {1}", + ops.len(), + rows.len(), + expected, + d, + ), + ) + }), + ), + ); + } + for (op, lhs, rhs, has_com, has_neg, has_rest, has_join) in &rows { + if ::anyhow::__private::not(*has_com) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare COMMUTATOR", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_neg) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare NEGATOR", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_rest) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare RESTRICT", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_join) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare JOIN", + op, + lhs, + rhs, + ), + ); + error + }); + } + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_planner_metadata_ord", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_planner_metadata_ord; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_planner_metadata_ord"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_planner_metadata_ord: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_planner_metadata_ord", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1078usize, + start_col: 22usize, + end_line: 1078usize, + end_col: 78usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_planner_metadata_ord()), + ), + }; + fn matrix_int4_ord_ore_planner_metadata_ord() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_planner_metadata_ord( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let ops: &[&str] = &["<", "<=", ">", ">="]; + let op_list = ops + .iter() + .map(|o| ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("\'{0}\'", o)) + })) + .collect::>() + .join(", "); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "\n SELECT o.oprname,\n lt.typname AS lhs,\n rt.typname AS rhs,\n o.oprcom <> 0 AS has_commutator,\n o.oprnegate <> 0 AS has_negator,\n o.oprrest::oid <> 0 AS has_restrict,\n o.oprjoin::oid <> 0 AS has_join\n FROM pg_catalog.pg_operator o\n JOIN pg_catalog.pg_type lt ON lt.oid = o.oprleft\n JOIN pg_catalog.pg_type rt ON rt.oid = o.oprright\n WHERE o.oprname IN ({0})\n AND (\'{1}\'::regtype = o.oprleft OR \'{1}\'::regtype = o.oprright)\n ", + op_list, + d, + ), + ) + }); + let rows: Vec<(String, String, String, bool, bool, bool, bool)> = sqlx::query_as( + &sql, + ) + .fetch_all(&pool) + .await?; + let expected = ops.len() * 3; + if ::anyhow::__private::not(rows.len() == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "expected {2} rows ({0} ops x 3 arg shapes) on {3}, got {1}", + ops.len(), + rows.len(), + expected, + d, + ), + ) + }), + ), + ); + } + for (op, lhs, rhs, has_com, has_neg, has_rest, has_join) in &rows { + if ::anyhow::__private::not(*has_com) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare COMMUTATOR", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_neg) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare NEGATOR", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_rest) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare RESTRICT", + op, + lhs, + rhs, + ), + ); + error + }); + } + if ::anyhow::__private::not(*has_join) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "operator {0}({1},{2}) must declare JOIN", + op, + lhs, + rhs, + ), + ); + error + }); + } + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_planner_metadata_ord", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_planner_metadata_ord; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_index_engages_btree"] + #[doc(hidden)] + pub const matrix_int4_eq_index_engages_btree: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_index_engages_btree", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1644usize, + start_col: 22usize, + end_line: 1644usize, + end_col: 75usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_index_engages_btree()), + ), + }; + fn matrix_int4_eq_index_engages_btree() -> anyhow::Result<()> { + async fn matrix_int4_eq_index_engages_btree( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let table = "matrix_int4_eq_idx_btree"; + let index = "matrix_int4_eq_idx_btree_idx"; + let fixture_table = ::fixture_table_name(); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {2} (plaintext {0}, value {1}) ON COMMIT DROP", + ::PG_TYPE, + &spec.sql_domain, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {2}(plaintext, value) SELECT plaintext, payload::{0} FROM {1}", + &spec.sql_domain, + fixture_table, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE INDEX {2} ON {3} USING {0} ({1}(value))", + "btree", + "eql_v3.eq_term", + index, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("ANALYZE {0}", table)) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query("SET LOCAL enable_seqscan = off").execute(&mut *tx).await?; + let pivot: i32 = ::fixture_values()[0]; + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let rhs_casts = [ + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("::{0}", &spec.sql_domain)) + }), + String::new(), + ]; + for rhs_cast in &rhs_casts { + let query = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {2} WHERE value {0} {3}::jsonb{1}", + "=", + rhs_cast, + table, + lit, + ), + ) + }); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} rhs_cast={2:?} must use index={3}", + &spec.sql_domain, + "=", + rhs_cast, + index, + ), + ) + }), + ) + .await?; + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_index_engages_btree", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_index_engages_btree; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_index_engages_hash"] + #[doc(hidden)] + pub const matrix_int4_eq_index_engages_hash: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_index_engages_hash", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1644usize, + start_col: 22usize, + end_line: 1644usize, + end_col: 75usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_index_engages_hash()), + ), + }; + fn matrix_int4_eq_index_engages_hash() -> anyhow::Result<()> { + async fn matrix_int4_eq_index_engages_hash( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let table = "matrix_int4_eq_idx_hash"; + let index = "matrix_int4_eq_idx_hash_idx"; + let fixture_table = ::fixture_table_name(); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {2} (plaintext {0}, value {1}) ON COMMIT DROP", + ::PG_TYPE, + &spec.sql_domain, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {2}(plaintext, value) SELECT plaintext, payload::{0} FROM {1}", + &spec.sql_domain, + fixture_table, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE INDEX {2} ON {3} USING {0} ({1}(value))", + "hash", + "eql_v3.eq_term", + index, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("ANALYZE {0}", table)) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query("SET LOCAL enable_seqscan = off").execute(&mut *tx).await?; + let pivot: i32 = ::fixture_values()[0]; + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let rhs_casts = [ + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("::{0}", &spec.sql_domain)) + }), + String::new(), + ]; + for rhs_cast in &rhs_casts { + let query = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {2} WHERE value {0} {3}::jsonb{1}", + "=", + rhs_cast, + table, + lit, + ), + ) + }); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} rhs_cast={2:?} must use index={3}", + &spec.sql_domain, + "=", + rhs_cast, + index, + ), + ) + }), + ) + .await?; + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_index_engages_hash", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_index_engages_hash; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_index_engages_btree"] + #[doc(hidden)] + pub const matrix_int4_ord_index_engages_btree: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_index_engages_btree", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1644usize, + start_col: 22usize, + end_line: 1644usize, + end_col: 75usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_index_engages_btree()), + ), + }; + fn matrix_int4_ord_index_engages_btree() -> anyhow::Result<()> { + async fn matrix_int4_ord_index_engages_btree( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let table = "matrix_int4_ord_idx_btree"; + let index = "matrix_int4_ord_idx_btree_idx"; + let fixture_table = ::fixture_table_name(); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {2} (plaintext {0}, value {1}) ON COMMIT DROP", + ::PG_TYPE, + &spec.sql_domain, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {2}(plaintext, value) SELECT plaintext, payload::{0} FROM {1}", + &spec.sql_domain, + fixture_table, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE INDEX {2} ON {3} USING {0} ({1}(value))", + "btree", + "eql_v3.ord_term", + index, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("ANALYZE {0}", table)) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query("SET LOCAL enable_seqscan = off").execute(&mut *tx).await?; + let pivot: i32 = ::fixture_values()[0]; + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let rhs_casts = [ + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("::{0}", &spec.sql_domain)) + }), + String::new(), + ]; + for rhs_cast in &rhs_casts { + let query = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {2} WHERE value {0} {3}::jsonb{1}", + "=", + rhs_cast, + table, + lit, + ), + ) + }); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} rhs_cast={2:?} must use index={3}", + &spec.sql_domain, + "=", + rhs_cast, + index, + ), + ) + }), + ) + .await?; + } + for rhs_cast in &rhs_casts { + let query = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {2} WHERE value {0} {3}::jsonb{1}", + "<", + rhs_cast, + table, + lit, + ), + ) + }); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} rhs_cast={2:?} must use index={3}", + &spec.sql_domain, + "<", + rhs_cast, + index, + ), + ) + }), + ) + .await?; + } + for rhs_cast in &rhs_casts { + let query = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {2} WHERE value {0} {3}::jsonb{1}", + "<=", + rhs_cast, + table, + lit, + ), + ) + }); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} rhs_cast={2:?} must use index={3}", + &spec.sql_domain, + "<=", + rhs_cast, + index, + ), + ) + }), + ) + .await?; + } + for rhs_cast in &rhs_casts { + let query = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {2} WHERE value {0} {3}::jsonb{1}", + ">", + rhs_cast, + table, + lit, + ), + ) + }); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} rhs_cast={2:?} must use index={3}", + &spec.sql_domain, + ">", + rhs_cast, + index, + ), + ) + }), + ) + .await?; + } + for rhs_cast in &rhs_casts { + let query = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {2} WHERE value {0} {3}::jsonb{1}", + ">=", + rhs_cast, + table, + lit, + ), + ) + }); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} rhs_cast={2:?} must use index={3}", + &spec.sql_domain, + ">=", + rhs_cast, + index, + ), + ) + }), + ) + .await?; + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_index_engages_btree", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_index_engages_btree; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_index_engages_btree"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_index_engages_btree: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_index_engages_btree", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1644usize, + start_col: 22usize, + end_line: 1644usize, + end_col: 75usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_index_engages_btree()), + ), + }; + fn matrix_int4_ord_ore_index_engages_btree() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_index_engages_btree( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let table = "matrix_int4_ord_ore_idx_btree"; + let index = "matrix_int4_ord_ore_idx_btree_idx"; + let fixture_table = ::fixture_table_name(); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {2} (plaintext {0}, value {1}) ON COMMIT DROP", + ::PG_TYPE, + &spec.sql_domain, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {2}(plaintext, value) SELECT plaintext, payload::{0} FROM {1}", + &spec.sql_domain, + fixture_table, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE INDEX {2} ON {3} USING {0} ({1}(value))", + "btree", + "eql_v3.ord_term", + index, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("ANALYZE {0}", table)) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query("SET LOCAL enable_seqscan = off").execute(&mut *tx).await?; + let pivot: i32 = ::fixture_values()[0]; + let payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let lit = ::eql_tests::scalar_domains::sql_string_literal(&payload); + let rhs_casts = [ + ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("::{0}", &spec.sql_domain)) + }), + String::new(), + ]; + for rhs_cast in &rhs_casts { + let query = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {2} WHERE value {0} {3}::jsonb{1}", + "=", + rhs_cast, + table, + lit, + ), + ) + }); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} rhs_cast={2:?} must use index={3}", + &spec.sql_domain, + "=", + rhs_cast, + index, + ), + ) + }), + ) + .await?; + } + for rhs_cast in &rhs_casts { + let query = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {2} WHERE value {0} {3}::jsonb{1}", + "<", + rhs_cast, + table, + lit, + ), + ) + }); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} rhs_cast={2:?} must use index={3}", + &spec.sql_domain, + "<", + rhs_cast, + index, + ), + ) + }), + ) + .await?; + } + for rhs_cast in &rhs_casts { + let query = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {2} WHERE value {0} {3}::jsonb{1}", + "<=", + rhs_cast, + table, + lit, + ), + ) + }); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} rhs_cast={2:?} must use index={3}", + &spec.sql_domain, + "<=", + rhs_cast, + index, + ), + ) + }), + ) + .await?; + } + for rhs_cast in &rhs_casts { + let query = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {2} WHERE value {0} {3}::jsonb{1}", + ">", + rhs_cast, + table, + lit, + ), + ) + }); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} rhs_cast={2:?} must use index={3}", + &spec.sql_domain, + ">", + rhs_cast, + index, + ), + ) + }), + ) + .await?; + } + for rhs_cast in &rhs_casts { + let query = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {2} WHERE value {0} {3}::jsonb{1}", + ">=", + rhs_cast, + table, + lit, + ), + ) + }); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} rhs_cast={2:?} must use index={3}", + &spec.sql_domain, + ">=", + rhs_cast, + index, + ), + ) + }), + ) + .await?; + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_index_engages_btree", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_index_engages_btree; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_scale_preference_default_btree"] + #[doc(hidden)] + pub const matrix_int4_ord_scale_preference_default_btree: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_scale_preference_default_btree", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1266usize, + start_col: 22usize, + end_line: 1266usize, + end_col: 86usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_scale_preference_default_btree()), + ), + }; + fn matrix_int4_ord_scale_preference_default_btree() -> anyhow::Result<()> { + async fn matrix_int4_ord_scale_preference_default_btree( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let table = "matrix_int4_ord_scaledef_btree"; + let index = "matrix_int4_ord_scaledef_btree_idx"; + let values: &[i32] = ::fixture_values(); + if ::anyhow::__private::not(values.len() >= 2) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "scale test requires >= 2 fixture rows for distinct filler/pivot", + ), + ); + error + }); + } + let filler = values[0]; + let pivot = values[values.len() / 2]; + let filler_payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, filler) + .await?; + let pivot_payload = ::eql_tests::scalar_domains::fetch_fixture_payload::< + i32, + >(&pool, pivot) + .await?; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {0} (value {1}) ON COMMIT DROP", + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {0}(value) SELECT $1::jsonb::{1} FROM generate_series(1, 5000)", + table, + d, + ), + ) + }), + ) + .bind(&filler_payload) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {0}(value) VALUES ($1::jsonb::{1})", + table, + d, + ), + ) + }), + ) + .bind(&pivot_payload) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE INDEX {2} ON {3} USING {0} ({1}(value))", + "btree", + "eql_v3.ord_term", + index, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("ANALYZE {0}", table)) + }), + ) + .execute(&mut *tx) + .await?; + let lit = pivot_payload.replace('\'', "''"); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {0} WHERE value = \'{1}\'::jsonb::{2}", + table, + lit, + d, + ), + ) + }), + index, + "with seqscan ON the planner must PREFER the ord_term functional index for a selective =", + ) + .await?; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_scale_preference_default_btree", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_scale_preference_default_btree; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_fixture_shape"] + #[doc(hidden)] + pub const matrix_int4_fixture_shape: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_fixture_shape"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1344usize, + start_col: 22usize, + end_line: 1344usize, + end_col: 55usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_fixture_shape()), + ), + }; + fn matrix_int4_fixture_shape() -> anyhow::Result<()> { + async fn matrix_int4_fixture_shape(pool: sqlx::PgPool) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let table = ::fixture_table_name(); + let expected: &[i32] = ::fixture_values(); + let n = expected.len() as i64; + let count: i64 = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT COUNT(*) FROM {0}", table), + ) + }), + ) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(count == n) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "row count must match FIXTURE_VALUES.len(): want {0}, got {1}", + n, + count, + ), + ); + error + }); + } + let ids: Vec = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT id FROM {0} ORDER BY id", table), + ) + }), + ) + .fetch_all(&pool) + .await?; + if ::anyhow::__private::not(ids == (1..=n).collect::>()) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!("ids must be sequential from 1: got {0:?}", ids), + ); + error + }); + } + let plaintexts: Vec = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT plaintext FROM {0} ORDER BY id", table), + ) + }), + ) + .fetch_all(&pool) + .await?; + if ::anyhow::__private::not(plaintexts == expected) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "plaintext column must match FIXTURE_VALUES in order", + ), + ); + error + }); + } + for (label, predicate) in [ + ( + "hm string", + "payload->'hm' IS NULL OR jsonb_typeof(payload->'hm') <> 'string'", + ), + ( + "ob array", + "payload->'ob' IS NULL OR jsonb_typeof(payload->'ob') <> 'array'", + ), + ( + "c string", + "payload->'c' IS NULL OR jsonb_typeof(payload->'c') <> 'string'", + ), + ] { + let missing: i64 = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT COUNT(*) FROM {0} WHERE {1}", + table, + predicate, + ), + ) + }), + ) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(missing == 0) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "every payload must carry a `{0}` term; missing = {1}", + label, + missing, + ), + ); + error + }); + } + } + let distinct_hm: i64 = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT COUNT(DISTINCT payload->>\'hm\') FROM {0}", + table, + ), + ) + }), + ) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(distinct_hm == n) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "{0} distinct values -> {0} distinct hm terms; got {1}", + n, + distinct_hm, + ), + ); + error + }); + } + let mismatched_version: i64 = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT COUNT(*) FROM {0} WHERE payload->\'v\' IS NULL OR payload->>\'v\' <> \'2\'", + table, + ), + ) + }), + ) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(mismatched_version == 0) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!("every payload must declare v = \'2\'"), + ); + error + }); + } + if !expected.is_empty() { + let probe = expected[expected.len() / 2]; + let probe_lit = ::to_sql_literal(probe); + let expected_id = (expected.len() / 2 + 1) as i64; + let ids: Vec = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT id FROM {1} WHERE plaintext = {0} ORDER BY id", + probe_lit, + table, + ), + ) + }), + ) + .fetch_all(&pool) + .await?; + if ::anyhow::__private::not( + ids + == ::alloc::boxed::box_assume_init_into_vec_unsafe( + ::alloc::intrinsics::write_box_via_move( + ::alloc::boxed::Box::new_uninit(), + [expected_id], + ), + ), + ) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "expected exactly one row with plaintext = {0:?} at id {1}, got {2:?}", + probe, + expected_id, + ids, + ), + ); + error + }); + } + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_fixture_shape", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_fixture_shape; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ord_routes_through_ob"] + #[doc(hidden)] + pub const matrix_int4_ord_ord_routes_through_ob: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ord_routes_through_ob", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1447usize, + start_col: 22usize, + end_line: 1447usize, + end_col: 75usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ord_routes_through_ob()), + ), + }; + fn matrix_int4_ord_ord_routes_through_ob() -> anyhow::Result<()> { + async fn matrix_int4_ord_ord_routes_through_ob( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let table = "matrix_int4_ord_no_hm"; + let index = "matrix_int4_ord_no_hm_idx"; + let fixture_table = ::fixture_table_name(); + let pivot: i32 = ::fixture_values()[0]; + let pivot_lit = ::to_sql_literal( + pivot, + ); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {1} (plaintext {0}, value {2}) ON COMMIT DROP", + ::PG_TYPE, + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT plaintext, (payload - \'hm\')::{2} FROM {0}", + fixture_table, + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let with_hm: i64 = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE jsonb_exists(value::jsonb, \'hm\')", + table, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(with_hm == 0) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!("test rows must not carry hm"), + ); + error + }); + } + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE INDEX {0} ON {1} USING btree (eql_v3.ord_term(value))", + index, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("ANALYZE {0}", table)) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query("SET LOCAL enable_seqscan = off").execute(&mut *tx).await?; + let pivot_payload: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT (payload - \'hm\')::text FROM {0} WHERE plaintext = {1}", + fixture_table, + pivot_lit, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let eq_count: i64 = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE value = $1::jsonb::{1}", + table, + d, + ), + ) + }), + ) + .bind(&pivot_payload) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(eq_count == 1) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "= must match exactly the pivot row via ob with no hm present (want 1, got {0})", + eq_count, + ), + ); + error + }); + } + let expected_neq = ::fixture_values() + .len() as i64 - eq_count; + let neq_count: i64 = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE value <> $1::jsonb::{1}", + table, + d, + ), + ) + }), + ) + .bind(&pivot_payload) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(neq_count == expected_neq) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "<> must match every non-pivot fixture row (want {0}, got {1})", + expected_neq, + neq_count, + ), + ); + error + }); + } + let lit = pivot_payload.replace('\'', "''"); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {0} WHERE value = \'{1}\'::jsonb::{2}", + table, + lit, + d, + ), + ) + }), + index, + "= must engage the eql_v3.ord_term functional btree with no hm", + ) + .await?; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ord_routes_through_ob", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ord_routes_through_ob; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_ord_routes_through_ob"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_ord_routes_through_ob: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_ord_routes_through_ob", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1447usize, + start_col: 22usize, + end_line: 1447usize, + end_col: 75usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_ord_routes_through_ob()), + ), + }; + fn matrix_int4_ord_ore_ord_routes_through_ob() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_ord_routes_through_ob( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let table = "matrix_int4_ord_ore_no_hm"; + let index = "matrix_int4_ord_ore_no_hm_idx"; + let fixture_table = ::fixture_table_name(); + let pivot: i32 = ::fixture_values()[0]; + let pivot_lit = ::to_sql_literal( + pivot, + ); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {1} (plaintext {0}, value {2}) ON COMMIT DROP", + ::PG_TYPE, + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT plaintext, (payload - \'hm\')::{2} FROM {0}", + fixture_table, + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let with_hm: i64 = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE jsonb_exists(value::jsonb, \'hm\')", + table, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(with_hm == 0) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!("test rows must not carry hm"), + ); + error + }); + } + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE INDEX {0} ON {1} USING btree (eql_v3.ord_term(value))", + index, + table, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("ANALYZE {0}", table)) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query("SET LOCAL enable_seqscan = off").execute(&mut *tx).await?; + let pivot_payload: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT (payload - \'hm\')::text FROM {0} WHERE plaintext = {1}", + fixture_table, + pivot_lit, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let eq_count: i64 = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE value = $1::jsonb::{1}", + table, + d, + ), + ) + }), + ) + .bind(&pivot_payload) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(eq_count == 1) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "= must match exactly the pivot row via ob with no hm present (want 1, got {0})", + eq_count, + ), + ); + error + }); + } + let expected_neq = ::fixture_values() + .len() as i64 - eq_count; + let neq_count: i64 = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} WHERE value <> $1::jsonb::{1}", + table, + d, + ), + ) + }), + ) + .bind(&pivot_payload) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(neq_count == expected_neq) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "<> must match every non-pivot fixture row (want {0}, got {1})", + expected_neq, + neq_count, + ), + ); + error + }); + } + let lit = pivot_payload.replace('\'', "''"); + ::eql_tests::matrix::assert_index_scan_uses( + &mut *tx, + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT * FROM {0} WHERE value = \'{1}\'::jsonb::{2}", + table, + lit, + d, + ), + ) + }), + index, + "= must engage the eql_v3.ord_term functional btree with no hm", + ) + .await?; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_ord_routes_through_ob", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_ord_routes_through_ob; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_ore_injectivity"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_ore_injectivity: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_ore_injectivity", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1581usize, + start_col: 22usize, + end_line: 1581usize, + end_col: 69usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_ore_injectivity()), + ), + }; + fn matrix_int4_ord_ore_ore_injectivity() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_ore_injectivity( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let fixture_table = ::fixture_table_name(); + let collisions: i64 = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT count(*) FROM {0} a JOIN {0} b ON a.id < b.id WHERE a.payload::{1} = b.payload::{1}", + fixture_table, + d, + ), + ) + }), + ) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(collisions == 0) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "no two distinct plaintexts may share an ORE term on {0}", + d, + ), + ); + error + }); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_ore_injectivity", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_ore_injectivity; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_aggregate_min"] + #[doc(hidden)] + pub const matrix_int4_ord_aggregate_min: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_ord_aggregate_min"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2099usize, + start_col: 22usize, + end_line: 2099usize, + end_col: 73usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_aggregate_min()), + ), + }; + fn matrix_int4_ord_aggregate_min() -> anyhow::Result<()> { + async fn matrix_int4_ord_aggregate_min( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let extremum: i32 = ::fixture_values() + .iter() + .copied() + .min() + .expect("FIXTURE_VALUES must be non-empty"); + let extremum_lit = ::to_sql_literal(extremum); + let expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + extremum_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&pool) + .await?; + let actual: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(payload::{1})::text FROM {2}", + "min", + d, + fixture, + ), + ) + }), + ) + .fetch_one(&pool) + .await?; + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "eql_v3.{0}({1}) must return the payload of plaintext={2:?} (the fixture {3})", + "min", + d, + extremum, + "min", + ), + ), + ); + } + } + }; + let ord_terms_match: bool = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.ord_term(eql_v3.{0}(payload::{1})) = eql_v3.ord_term($1::jsonb::{1}) FROM {2}", + "min", + d, + fixture, + ), + ) + }), + ) + .bind(&expected) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(ord_terms_match) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "eql_v3.ord_term(eql_v3.{0}({1})) must equal eql_v3.ord_term() for plaintext={2:?}", + "min", + d, + extremum, + ), + ) + }), + ), + ); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_aggregate_min", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_aggregate_min; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_aggregate_min_empty"] + #[doc(hidden)] + pub const matrix_int4_ord_aggregate_min_empty: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_aggregate_min_empty", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2157usize, + start_col: 22usize, + end_line: 2157usize, + end_col: 80usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_aggregate_min_empty()), + ), + }; + fn matrix_int4_ord_aggregate_min_empty() -> anyhow::Result<()> { + async fn matrix_int4_ord_aggregate_min_empty( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE empty_agg (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let result: Option = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(value)::text FROM empty_agg", + "min", + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(result.is_none()) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "empty rowset to eql_v3.{0} on {1} must return NULL, got {2:?}", + "min", + d, + result, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_aggregate_min_empty", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_aggregate_min_empty; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_aggregate_min_all_null"] + #[doc(hidden)] + pub const matrix_int4_ord_aggregate_min_all_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_aggregate_min_all_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2182usize, + start_col: 22usize, + end_line: 2182usize, + end_col: 83usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_aggregate_min_all_null()), + ), + }; + fn matrix_int4_ord_aggregate_min_all_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_aggregate_min_all_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(NULL::{1})::text FROM generate_series(1, 3)", + "min", + d, + ), + ) + }); + let result: Option = sqlx::query_scalar(&sql) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(result.is_none()) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "all-NULL input to eql_v3.{0} on {1} must return NULL, got {2:?}; SQL={3}", + "min", + d, + result, + sql, + ), + ) + }), + ), + ); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_aggregate_min_all_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_aggregate_min_all_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_aggregate_min_mixed_null"] + #[doc(hidden)] + pub const matrix_int4_ord_aggregate_min_mixed_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_aggregate_min_mixed_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2208usize, + start_col: 22usize, + end_line: 2208usize, + end_col: 85usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_aggregate_min_mixed_null()), + ), + }; + fn matrix_int4_ord_aggregate_min_mixed_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_aggregate_min_mixed_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let values: &[i32] = ::fixture_values(); + if ::anyhow::__private::not(values.len() >= 2) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "mixed-NULL test needs >= 2 fixture values; got {0}", + values.len(), + ), + ) + }), + ), + ); + } + let mut sorted: Vec = values.to_vec(); + sorted.sort(); + let low: i32 = *sorted.first().expect("non-empty after len check"); + let high: i32 = *sorted.last().expect("non-empty after len check"); + let expected_plaintext: i32 = low.min(high); + let low_lit = ::to_sql_literal(low); + let high_lit = ::to_sql_literal(high); + let expected_lit = ::to_sql_literal( + expected_plaintext, + ); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE mixed_null (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO mixed_null(value) SELECT NULL::{2} UNION ALL SELECT payload::{2} FROM {3} WHERE plaintext = {0} UNION ALL SELECT NULL::{2} UNION ALL SELECT payload::{2} FROM {3} WHERE plaintext = {1} UNION ALL SELECT NULL::{2}", + low_lit, + high_lit, + d, + fixture, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + expected_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let actual: Option = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(value)::text FROM mixed_null", + "min", + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not( + actual.as_deref() == Some(expected.as_str()), + ) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "eql_v3.{0} on mixed NULL/non-NULL must return the {1} non-NULL value (plaintext={2:?}); want {3:?}, got {4:?}", + "min", + "min", + expected_plaintext, + expected, + actual, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_aggregate_min_mixed_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_aggregate_min_mixed_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_aggregate_max"] + #[doc(hidden)] + pub const matrix_int4_ord_aggregate_max: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_ord_aggregate_max"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2099usize, + start_col: 22usize, + end_line: 2099usize, + end_col: 73usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_aggregate_max()), + ), + }; + fn matrix_int4_ord_aggregate_max() -> anyhow::Result<()> { + async fn matrix_int4_ord_aggregate_max( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let extremum: i32 = ::fixture_values() + .iter() + .copied() + .max() + .expect("FIXTURE_VALUES must be non-empty"); + let extremum_lit = ::to_sql_literal(extremum); + let expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + extremum_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&pool) + .await?; + let actual: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(payload::{1})::text FROM {2}", + "max", + d, + fixture, + ), + ) + }), + ) + .fetch_one(&pool) + .await?; + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "eql_v3.{0}({1}) must return the payload of plaintext={2:?} (the fixture {3})", + "max", + d, + extremum, + "max", + ), + ), + ); + } + } + }; + let ord_terms_match: bool = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.ord_term(eql_v3.{0}(payload::{1})) = eql_v3.ord_term($1::jsonb::{1}) FROM {2}", + "max", + d, + fixture, + ), + ) + }), + ) + .bind(&expected) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(ord_terms_match) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "eql_v3.ord_term(eql_v3.{0}({1})) must equal eql_v3.ord_term() for plaintext={2:?}", + "max", + d, + extremum, + ), + ) + }), + ), + ); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_aggregate_max", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_aggregate_max; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_aggregate_max_empty"] + #[doc(hidden)] + pub const matrix_int4_ord_aggregate_max_empty: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_aggregate_max_empty", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2157usize, + start_col: 22usize, + end_line: 2157usize, + end_col: 80usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_aggregate_max_empty()), + ), + }; + fn matrix_int4_ord_aggregate_max_empty() -> anyhow::Result<()> { + async fn matrix_int4_ord_aggregate_max_empty( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE empty_agg (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let result: Option = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(value)::text FROM empty_agg", + "max", + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(result.is_none()) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "empty rowset to eql_v3.{0} on {1} must return NULL, got {2:?}", + "max", + d, + result, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_aggregate_max_empty", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_aggregate_max_empty; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_aggregate_max_all_null"] + #[doc(hidden)] + pub const matrix_int4_ord_aggregate_max_all_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_aggregate_max_all_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2182usize, + start_col: 22usize, + end_line: 2182usize, + end_col: 83usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_aggregate_max_all_null()), + ), + }; + fn matrix_int4_ord_aggregate_max_all_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_aggregate_max_all_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(NULL::{1})::text FROM generate_series(1, 3)", + "max", + d, + ), + ) + }); + let result: Option = sqlx::query_scalar(&sql) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(result.is_none()) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "all-NULL input to eql_v3.{0} on {1} must return NULL, got {2:?}; SQL={3}", + "max", + d, + result, + sql, + ), + ) + }), + ), + ); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_aggregate_max_all_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_aggregate_max_all_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_aggregate_max_mixed_null"] + #[doc(hidden)] + pub const matrix_int4_ord_aggregate_max_mixed_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_aggregate_max_mixed_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2208usize, + start_col: 22usize, + end_line: 2208usize, + end_col: 85usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_aggregate_max_mixed_null()), + ), + }; + fn matrix_int4_ord_aggregate_max_mixed_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_aggregate_max_mixed_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let values: &[i32] = ::fixture_values(); + if ::anyhow::__private::not(values.len() >= 2) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "mixed-NULL test needs >= 2 fixture values; got {0}", + values.len(), + ), + ) + }), + ), + ); + } + let mut sorted: Vec = values.to_vec(); + sorted.sort(); + let low: i32 = *sorted.first().expect("non-empty after len check"); + let high: i32 = *sorted.last().expect("non-empty after len check"); + let expected_plaintext: i32 = low.max(high); + let low_lit = ::to_sql_literal(low); + let high_lit = ::to_sql_literal(high); + let expected_lit = ::to_sql_literal( + expected_plaintext, + ); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE mixed_null (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO mixed_null(value) SELECT NULL::{2} UNION ALL SELECT payload::{2} FROM {3} WHERE plaintext = {0} UNION ALL SELECT NULL::{2} UNION ALL SELECT payload::{2} FROM {3} WHERE plaintext = {1} UNION ALL SELECT NULL::{2}", + low_lit, + high_lit, + d, + fixture, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + expected_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let actual: Option = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(value)::text FROM mixed_null", + "max", + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not( + actual.as_deref() == Some(expected.as_str()), + ) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "eql_v3.{0} on mixed NULL/non-NULL must return the {1} non-NULL value (plaintext={2:?}); want {3:?}, got {4:?}", + "max", + "max", + expected_plaintext, + expected, + actual, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_aggregate_max_mixed_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_aggregate_max_mixed_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_aggregate_min"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_aggregate_min: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_aggregate_min", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2099usize, + start_col: 22usize, + end_line: 2099usize, + end_col: 73usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_aggregate_min()), + ), + }; + fn matrix_int4_ord_ore_aggregate_min() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_aggregate_min( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let extremum: i32 = ::fixture_values() + .iter() + .copied() + .min() + .expect("FIXTURE_VALUES must be non-empty"); + let extremum_lit = ::to_sql_literal(extremum); + let expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + extremum_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&pool) + .await?; + let actual: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(payload::{1})::text FROM {2}", + "min", + d, + fixture, + ), + ) + }), + ) + .fetch_one(&pool) + .await?; + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "eql_v3.{0}({1}) must return the payload of plaintext={2:?} (the fixture {3})", + "min", + d, + extremum, + "min", + ), + ), + ); + } + } + }; + let ord_terms_match: bool = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.ord_term(eql_v3.{0}(payload::{1})) = eql_v3.ord_term($1::jsonb::{1}) FROM {2}", + "min", + d, + fixture, + ), + ) + }), + ) + .bind(&expected) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(ord_terms_match) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "eql_v3.ord_term(eql_v3.{0}({1})) must equal eql_v3.ord_term() for plaintext={2:?}", + "min", + d, + extremum, + ), + ) + }), + ), + ); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_aggregate_min", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_aggregate_min; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_aggregate_min_empty"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_aggregate_min_empty: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_aggregate_min_empty", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2157usize, + start_col: 22usize, + end_line: 2157usize, + end_col: 80usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_aggregate_min_empty()), + ), + }; + fn matrix_int4_ord_ore_aggregate_min_empty() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_aggregate_min_empty( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE empty_agg (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let result: Option = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(value)::text FROM empty_agg", + "min", + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(result.is_none()) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "empty rowset to eql_v3.{0} on {1} must return NULL, got {2:?}", + "min", + d, + result, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_aggregate_min_empty", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_aggregate_min_empty; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_aggregate_min_all_null"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_aggregate_min_all_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_aggregate_min_all_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2182usize, + start_col: 22usize, + end_line: 2182usize, + end_col: 83usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_aggregate_min_all_null()), + ), + }; + fn matrix_int4_ord_ore_aggregate_min_all_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_aggregate_min_all_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(NULL::{1})::text FROM generate_series(1, 3)", + "min", + d, + ), + ) + }); + let result: Option = sqlx::query_scalar(&sql) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(result.is_none()) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "all-NULL input to eql_v3.{0} on {1} must return NULL, got {2:?}; SQL={3}", + "min", + d, + result, + sql, + ), + ) + }), + ), + ); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_aggregate_min_all_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_aggregate_min_all_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_aggregate_min_mixed_null"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_aggregate_min_mixed_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_aggregate_min_mixed_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2208usize, + start_col: 22usize, + end_line: 2208usize, + end_col: 85usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_aggregate_min_mixed_null()), + ), + }; + fn matrix_int4_ord_ore_aggregate_min_mixed_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_aggregate_min_mixed_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let values: &[i32] = ::fixture_values(); + if ::anyhow::__private::not(values.len() >= 2) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "mixed-NULL test needs >= 2 fixture values; got {0}", + values.len(), + ), + ) + }), + ), + ); + } + let mut sorted: Vec = values.to_vec(); + sorted.sort(); + let low: i32 = *sorted.first().expect("non-empty after len check"); + let high: i32 = *sorted.last().expect("non-empty after len check"); + let expected_plaintext: i32 = low.min(high); + let low_lit = ::to_sql_literal(low); + let high_lit = ::to_sql_literal(high); + let expected_lit = ::to_sql_literal( + expected_plaintext, + ); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE mixed_null (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO mixed_null(value) SELECT NULL::{2} UNION ALL SELECT payload::{2} FROM {3} WHERE plaintext = {0} UNION ALL SELECT NULL::{2} UNION ALL SELECT payload::{2} FROM {3} WHERE plaintext = {1} UNION ALL SELECT NULL::{2}", + low_lit, + high_lit, + d, + fixture, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + expected_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let actual: Option = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(value)::text FROM mixed_null", + "min", + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not( + actual.as_deref() == Some(expected.as_str()), + ) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "eql_v3.{0} on mixed NULL/non-NULL must return the {1} non-NULL value (plaintext={2:?}); want {3:?}, got {4:?}", + "min", + "min", + expected_plaintext, + expected, + actual, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_aggregate_min_mixed_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_aggregate_min_mixed_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_aggregate_max"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_aggregate_max: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_aggregate_max", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2099usize, + start_col: 22usize, + end_line: 2099usize, + end_col: 73usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_aggregate_max()), + ), + }; + fn matrix_int4_ord_ore_aggregate_max() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_aggregate_max( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let extremum: i32 = ::fixture_values() + .iter() + .copied() + .max() + .expect("FIXTURE_VALUES must be non-empty"); + let extremum_lit = ::to_sql_literal(extremum); + let expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + extremum_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&pool) + .await?; + let actual: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(payload::{1})::text FROM {2}", + "max", + d, + fixture, + ), + ) + }), + ) + .fetch_one(&pool) + .await?; + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "eql_v3.{0}({1}) must return the payload of plaintext={2:?} (the fixture {3})", + "max", + d, + extremum, + "max", + ), + ), + ); + } + } + }; + let ord_terms_match: bool = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.ord_term(eql_v3.{0}(payload::{1})) = eql_v3.ord_term($1::jsonb::{1}) FROM {2}", + "max", + d, + fixture, + ), + ) + }), + ) + .bind(&expected) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(ord_terms_match) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "eql_v3.ord_term(eql_v3.{0}({1})) must equal eql_v3.ord_term() for plaintext={2:?}", + "max", + d, + extremum, + ), + ) + }), + ), + ); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_aggregate_max", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_aggregate_max; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_aggregate_max_empty"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_aggregate_max_empty: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_aggregate_max_empty", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2157usize, + start_col: 22usize, + end_line: 2157usize, + end_col: 80usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_aggregate_max_empty()), + ), + }; + fn matrix_int4_ord_ore_aggregate_max_empty() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_aggregate_max_empty( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE empty_agg (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let result: Option = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(value)::text FROM empty_agg", + "max", + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(result.is_none()) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "empty rowset to eql_v3.{0} on {1} must return NULL, got {2:?}", + "max", + d, + result, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_aggregate_max_empty", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_aggregate_max_empty; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_aggregate_max_all_null"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_aggregate_max_all_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_aggregate_max_all_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2182usize, + start_col: 22usize, + end_line: 2182usize, + end_col: 83usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_aggregate_max_all_null()), + ), + }; + fn matrix_int4_ord_ore_aggregate_max_all_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_aggregate_max_all_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(NULL::{1})::text FROM generate_series(1, 3)", + "max", + d, + ), + ) + }); + let result: Option = sqlx::query_scalar(&sql) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(result.is_none()) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "all-NULL input to eql_v3.{0} on {1} must return NULL, got {2:?}; SQL={3}", + "max", + d, + result, + sql, + ), + ) + }), + ), + ); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_aggregate_max_all_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_aggregate_max_all_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_aggregate_max_mixed_null"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_aggregate_max_mixed_null: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_aggregate_max_mixed_null", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2208usize, + start_col: 22usize, + end_line: 2208usize, + end_col: 85usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_aggregate_max_mixed_null()), + ), + }; + fn matrix_int4_ord_ore_aggregate_max_mixed_null() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_aggregate_max_mixed_null( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let values: &[i32] = ::fixture_values(); + if ::anyhow::__private::not(values.len() >= 2) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "mixed-NULL test needs >= 2 fixture values; got {0}", + values.len(), + ), + ) + }), + ), + ); + } + let mut sorted: Vec = values.to_vec(); + sorted.sort(); + let low: i32 = *sorted.first().expect("non-empty after len check"); + let high: i32 = *sorted.last().expect("non-empty after len check"); + let expected_plaintext: i32 = low.max(high); + let low_lit = ::to_sql_literal(low); + let high_lit = ::to_sql_literal(high); + let expected_lit = ::to_sql_literal( + expected_plaintext, + ); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE mixed_null (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO mixed_null(value) SELECT NULL::{2} UNION ALL SELECT payload::{2} FROM {3} WHERE plaintext = {0} UNION ALL SELECT NULL::{2} UNION ALL SELECT payload::{2} FROM {3} WHERE plaintext = {1} UNION ALL SELECT NULL::{2}", + low_lit, + high_lit, + d, + fixture, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + expected_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let actual: Option = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(value)::text FROM mixed_null", + "max", + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not( + actual.as_deref() == Some(expected.as_str()), + ) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "eql_v3.{0} on mixed NULL/non-NULL must return the {1} non-NULL value (plaintext={2:?}); want {3:?}, got {4:?}", + "max", + "max", + expected_plaintext, + expected, + actual, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_aggregate_max_mixed_null", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_aggregate_max_mixed_null; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_aggregate_group_by_min"] + #[doc(hidden)] + pub const matrix_int4_ord_aggregate_group_by_min: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_aggregate_group_by_min", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2387usize, + start_col: 22usize, + end_line: 2387usize, + end_col: 82usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_aggregate_group_by_min()), + ), + }; + fn matrix_int4_ord_aggregate_group_by_min() -> anyhow::Result<()> { + async fn matrix_int4_ord_aggregate_group_by_min( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let values: &[i32] = ::fixture_values(); + if ::anyhow::__private::not(values.len() >= 5) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "GROUP BY test needs >= 5 fixture values; got {0}", + values.len(), + ), + ) + }), + ), + ); + } + let group1: &[i32] = &values[..3]; + let group2: &[i32] = &values[3..5]; + let group1_extremum: i32 = group1 + .iter() + .copied() + .min() + .expect("group 1 is non-empty"); + let group2_extremum: i32 = group2 + .iter() + .copied() + .min() + .expect("group 2 is non-empty"); + let g1_lit = ::to_sql_literal(group1_extremum); + let g2_lit = ::to_sql_literal(group2_extremum); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE group_test (group_key int, value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + for v in group1 { + let lit = ::to_sql_literal(*v); + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO group_test(group_key, value) SELECT 1, payload::{0} FROM {1} WHERE plaintext = {2}", + d, + fixture, + lit, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + } + for v in group2 { + let lit = ::to_sql_literal(*v); + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO group_test(group_key, value) SELECT 2, payload::{0} FROM {1} WHERE plaintext = {2}", + d, + fixture, + lit, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + } + let g1_expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + g1_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let g2_expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + g2_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let rows: Vec<(i32, String)> = sqlx::query_as( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT group_key, eql_v3.{0}(value)::text FROM group_test GROUP BY group_key ORDER BY group_key", + "min", + ), + ) + }), + ) + .fetch_all(&mut *tx) + .await?; + if ::anyhow::__private::not(rows.len() == 2) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "GROUP BY must return 2 rows, got {0}", + rows.len(), + ), + ) + }), + ), + ); + } + if ::anyhow::__private::not(rows[0].0 == 1 && rows[0].1 == g1_expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "group 1 eql_v3.{0}({1}) must yield payload for plaintext={2:?}; want ({3}, {4:?}), got {5:?}", + "min", + d, + group1_extremum, + 1, + g1_expected, + rows[0], + ), + ) + }), + ), + ); + } + if ::anyhow::__private::not(rows[1].0 == 2 && rows[1].1 == g2_expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "group 2 eql_v3.{0}({1}) must yield payload for plaintext={2:?}; want ({3}, {4:?}), got {5:?}", + "min", + d, + group2_extremum, + 2, + g2_expected, + rows[1], + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_aggregate_group_by_min", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_aggregate_group_by_min; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_aggregate_group_by_max"] + #[doc(hidden)] + pub const matrix_int4_ord_aggregate_group_by_max: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_aggregate_group_by_max", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2387usize, + start_col: 22usize, + end_line: 2387usize, + end_col: 82usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_aggregate_group_by_max()), + ), + }; + fn matrix_int4_ord_aggregate_group_by_max() -> anyhow::Result<()> { + async fn matrix_int4_ord_aggregate_group_by_max( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let values: &[i32] = ::fixture_values(); + if ::anyhow::__private::not(values.len() >= 5) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "GROUP BY test needs >= 5 fixture values; got {0}", + values.len(), + ), + ) + }), + ), + ); + } + let group1: &[i32] = &values[..3]; + let group2: &[i32] = &values[3..5]; + let group1_extremum: i32 = group1 + .iter() + .copied() + .max() + .expect("group 1 is non-empty"); + let group2_extremum: i32 = group2 + .iter() + .copied() + .max() + .expect("group 2 is non-empty"); + let g1_lit = ::to_sql_literal(group1_extremum); + let g2_lit = ::to_sql_literal(group2_extremum); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE group_test (group_key int, value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + for v in group1 { + let lit = ::to_sql_literal(*v); + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO group_test(group_key, value) SELECT 1, payload::{0} FROM {1} WHERE plaintext = {2}", + d, + fixture, + lit, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + } + for v in group2 { + let lit = ::to_sql_literal(*v); + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO group_test(group_key, value) SELECT 2, payload::{0} FROM {1} WHERE plaintext = {2}", + d, + fixture, + lit, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + } + let g1_expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + g1_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let g2_expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + g2_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let rows: Vec<(i32, String)> = sqlx::query_as( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT group_key, eql_v3.{0}(value)::text FROM group_test GROUP BY group_key ORDER BY group_key", + "max", + ), + ) + }), + ) + .fetch_all(&mut *tx) + .await?; + if ::anyhow::__private::not(rows.len() == 2) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "GROUP BY must return 2 rows, got {0}", + rows.len(), + ), + ) + }), + ), + ); + } + if ::anyhow::__private::not(rows[0].0 == 1 && rows[0].1 == g1_expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "group 1 eql_v3.{0}({1}) must yield payload for plaintext={2:?}; want ({3}, {4:?}), got {5:?}", + "max", + d, + group1_extremum, + 1, + g1_expected, + rows[0], + ), + ) + }), + ), + ); + } + if ::anyhow::__private::not(rows[1].0 == 2 && rows[1].1 == g2_expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "group 2 eql_v3.{0}({1}) must yield payload for plaintext={2:?}; want ({3}, {4:?}), got {5:?}", + "max", + d, + group2_extremum, + 2, + g2_expected, + rows[1], + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_aggregate_group_by_max", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_aggregate_group_by_max; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_aggregate_group_by_min"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_aggregate_group_by_min: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_aggregate_group_by_min", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2387usize, + start_col: 22usize, + end_line: 2387usize, + end_col: 82usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_aggregate_group_by_min()), + ), + }; + fn matrix_int4_ord_ore_aggregate_group_by_min() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_aggregate_group_by_min( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let values: &[i32] = ::fixture_values(); + if ::anyhow::__private::not(values.len() >= 5) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "GROUP BY test needs >= 5 fixture values; got {0}", + values.len(), + ), + ) + }), + ), + ); + } + let group1: &[i32] = &values[..3]; + let group2: &[i32] = &values[3..5]; + let group1_extremum: i32 = group1 + .iter() + .copied() + .min() + .expect("group 1 is non-empty"); + let group2_extremum: i32 = group2 + .iter() + .copied() + .min() + .expect("group 2 is non-empty"); + let g1_lit = ::to_sql_literal(group1_extremum); + let g2_lit = ::to_sql_literal(group2_extremum); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE group_test (group_key int, value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + for v in group1 { + let lit = ::to_sql_literal(*v); + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO group_test(group_key, value) SELECT 1, payload::{0} FROM {1} WHERE plaintext = {2}", + d, + fixture, + lit, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + } + for v in group2 { + let lit = ::to_sql_literal(*v); + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO group_test(group_key, value) SELECT 2, payload::{0} FROM {1} WHERE plaintext = {2}", + d, + fixture, + lit, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + } + let g1_expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + g1_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let g2_expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + g2_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let rows: Vec<(i32, String)> = sqlx::query_as( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT group_key, eql_v3.{0}(value)::text FROM group_test GROUP BY group_key ORDER BY group_key", + "min", + ), + ) + }), + ) + .fetch_all(&mut *tx) + .await?; + if ::anyhow::__private::not(rows.len() == 2) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "GROUP BY must return 2 rows, got {0}", + rows.len(), + ), + ) + }), + ), + ); + } + if ::anyhow::__private::not(rows[0].0 == 1 && rows[0].1 == g1_expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "group 1 eql_v3.{0}({1}) must yield payload for plaintext={2:?}; want ({3}, {4:?}), got {5:?}", + "min", + d, + group1_extremum, + 1, + g1_expected, + rows[0], + ), + ) + }), + ), + ); + } + if ::anyhow::__private::not(rows[1].0 == 2 && rows[1].1 == g2_expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "group 2 eql_v3.{0}({1}) must yield payload for plaintext={2:?}; want ({3}, {4:?}), got {5:?}", + "min", + d, + group2_extremum, + 2, + g2_expected, + rows[1], + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_aggregate_group_by_min", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_aggregate_group_by_min; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_aggregate_group_by_max"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_aggregate_group_by_max: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_aggregate_group_by_max", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2387usize, + start_col: 22usize, + end_line: 2387usize, + end_col: 82usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_aggregate_group_by_max()), + ), + }; + fn matrix_int4_ord_ore_aggregate_group_by_max() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_aggregate_group_by_max( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let values: &[i32] = ::fixture_values(); + if ::anyhow::__private::not(values.len() >= 5) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "GROUP BY test needs >= 5 fixture values; got {0}", + values.len(), + ), + ) + }), + ), + ); + } + let group1: &[i32] = &values[..3]; + let group2: &[i32] = &values[3..5]; + let group1_extremum: i32 = group1 + .iter() + .copied() + .max() + .expect("group 1 is non-empty"); + let group2_extremum: i32 = group2 + .iter() + .copied() + .max() + .expect("group 2 is non-empty"); + let g1_lit = ::to_sql_literal(group1_extremum); + let g2_lit = ::to_sql_literal(group2_extremum); + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE group_test (group_key int, value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + for v in group1 { + let lit = ::to_sql_literal(*v); + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO group_test(group_key, value) SELECT 1, payload::{0} FROM {1} WHERE plaintext = {2}", + d, + fixture, + lit, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + } + for v in group2 { + let lit = ::to_sql_literal(*v); + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO group_test(group_key, value) SELECT 2, payload::{0} FROM {1} WHERE plaintext = {2}", + d, + fixture, + lit, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + } + let g1_expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + g1_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let g2_expected: String = sqlx::query_scalar( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT payload::text FROM {1} WHERE plaintext = {0}", + g2_lit, + fixture, + ), + ) + }), + ) + .fetch_one(&mut *tx) + .await?; + let rows: Vec<(i32, String)> = sqlx::query_as( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT group_key, eql_v3.{0}(value)::text FROM group_test GROUP BY group_key ORDER BY group_key", + "max", + ), + ) + }), + ) + .fetch_all(&mut *tx) + .await?; + if ::anyhow::__private::not(rows.len() == 2) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "GROUP BY must return 2 rows, got {0}", + rows.len(), + ), + ) + }), + ), + ); + } + if ::anyhow::__private::not(rows[0].0 == 1 && rows[0].1 == g1_expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "group 1 eql_v3.{0}({1}) must yield payload for plaintext={2:?}; want ({3}, {4:?}), got {5:?}", + "max", + d, + group1_extremum, + 1, + g1_expected, + rows[0], + ), + ) + }), + ), + ); + } + if ::anyhow::__private::not(rows[1].0 == 2 && rows[1].1 == g2_expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "group 2 eql_v3.{0}({1}) must yield payload for plaintext={2:?}; want ({3}, {4:?}), got {5:?}", + "max", + d, + group2_extremum, + 2, + g2_expected, + rows[1], + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_aggregate_group_by_max", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_aggregate_group_by_max; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_aggregate_parallel_safe"] + #[doc(hidden)] + pub const matrix_int4_ord_aggregate_parallel_safe: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_aggregate_parallel_safe", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2302usize, + start_col: 22usize, + end_line: 2302usize, + end_col: 77usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_aggregate_parallel_safe()), + ), + }; + fn matrix_int4_ord_aggregate_parallel_safe() -> anyhow::Result<()> { + async fn matrix_int4_ord_aggregate_parallel_safe( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + for agg in ["min", "max"] { + let (proparallel, has_combine): (String, bool) = sqlx::query_as( + "SELECT p.proparallel::text, a.aggcombinefn <> 0 \ + FROM pg_proc p \ + JOIN pg_aggregate a ON a.aggfnoid = p.oid \ + WHERE p.proname = $1 \ + AND p.pronamespace = 'eql_v3'::regnamespace \ + AND p.proargtypes[0]::regtype = $2::regtype", + ) + .bind(agg) + .bind(d) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(proparallel == "s") { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "eql_v3.{0}({1}) must be PARALLEL SAFE (proparallel=\'s\'), got {2:?}", + agg, + d, + proparallel, + ), + ); + error + }); + } + if ::anyhow::__private::not(has_combine) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "eql_v3.{0}({1}) must declare a combinefunc for partial aggregation", + agg, + d, + ), + ); + error + }); + } + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_aggregate_parallel_safe", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_aggregate_parallel_safe; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_aggregate_parallel_safe"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_aggregate_parallel_safe: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_aggregate_parallel_safe", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2302usize, + start_col: 22usize, + end_line: 2302usize, + end_col: 77usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_aggregate_parallel_safe()), + ), + }; + fn matrix_int4_ord_ore_aggregate_parallel_safe() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_aggregate_parallel_safe( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + for agg in ["min", "max"] { + let (proparallel, has_combine): (String, bool) = sqlx::query_as( + "SELECT p.proparallel::text, a.aggcombinefn <> 0 \ + FROM pg_proc p \ + JOIN pg_aggregate a ON a.aggfnoid = p.oid \ + WHERE p.proname = $1 \ + AND p.pronamespace = 'eql_v3'::regnamespace \ + AND p.proargtypes[0]::regtype = $2::regtype", + ) + .bind(agg) + .bind(d) + .fetch_one(&pool) + .await?; + if ::anyhow::__private::not(proparallel == "s") { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "eql_v3.{0}({1}) must be PARALLEL SAFE (proparallel=\'s\'), got {2:?}", + agg, + d, + proparallel, + ), + ); + error + }); + } + if ::anyhow::__private::not(has_combine) { + return ::anyhow::__private::Err({ + let error = ::anyhow::__private::format_err( + format_args!( + "eql_v3.{0}({1}) must declare a combinefunc for partial aggregation", + agg, + d, + ), + ); + error + }); + } + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_aggregate_parallel_safe", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_ord_ore_aggregate_parallel_safe; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_aggregate_typecheck_min"] + #[doc(hidden)] + pub const matrix_int4_storage_aggregate_typecheck_min: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_storage_aggregate_typecheck_min", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2543usize, + start_col: 22usize, + end_line: 2543usize, + end_col: 83usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_aggregate_typecheck_min()), + ), + }; + fn matrix_int4_storage_aggregate_typecheck_min() -> anyhow::Result<()> { + async fn matrix_int4_storage_aggregate_typecheck_min( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE typecheck_table (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO typecheck_table(value) VALUES ($1::jsonb::{0})", + d, + ), + ) + }), + ) + .bind(payload) + .execute(&mut *tx) + .await?; + sqlx::query("SAVEPOINT probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(value) FROM typecheck_table", + "min", + ), + ) + }); + let err = sqlx::query_scalar::<_, String>(&sql) + .fetch_one(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "eql_v3.{0} on non-ord variant {1} must raise but succeeded", + "min", + d, + ), + ) + }), + ); + let db_err = err + .as_database_error() + .expect("expected database error from typecheck probe"); + let code = db_err.code(); + if ::anyhow::__private::not( + code.as_deref() == Some("42883") || code.as_deref() == Some("42725"), + ) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "expected SQLSTATE 42883 (undefined_function) or 42725 (ambiguous_function) for eql_v3.{0}({1}), got {2:?} (message: {3})", + "min", + d, + code, + db_err.message(), + ), + ) + }), + ), + ); + } + sqlx::query("ROLLBACK TO SAVEPOINT probe").execute(&mut *tx).await?; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_aggregate_typecheck_min", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_aggregate_typecheck_min; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_aggregate_typecheck_max"] + #[doc(hidden)] + pub const matrix_int4_storage_aggregate_typecheck_max: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_storage_aggregate_typecheck_max", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2543usize, + start_col: 22usize, + end_line: 2543usize, + end_col: 83usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_aggregate_typecheck_max()), + ), + }; + fn matrix_int4_storage_aggregate_typecheck_max() -> anyhow::Result<()> { + async fn matrix_int4_storage_aggregate_typecheck_max( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE typecheck_table (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO typecheck_table(value) VALUES ($1::jsonb::{0})", + d, + ), + ) + }), + ) + .bind(payload) + .execute(&mut *tx) + .await?; + sqlx::query("SAVEPOINT probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(value) FROM typecheck_table", + "max", + ), + ) + }); + let err = sqlx::query_scalar::<_, String>(&sql) + .fetch_one(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "eql_v3.{0} on non-ord variant {1} must raise but succeeded", + "max", + d, + ), + ) + }), + ); + let db_err = err + .as_database_error() + .expect("expected database error from typecheck probe"); + let code = db_err.code(); + if ::anyhow::__private::not( + code.as_deref() == Some("42883") || code.as_deref() == Some("42725"), + ) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "expected SQLSTATE 42883 (undefined_function) or 42725 (ambiguous_function) for eql_v3.{0}({1}), got {2:?} (message: {3})", + "max", + d, + code, + db_err.message(), + ), + ) + }), + ), + ); + } + sqlx::query("ROLLBACK TO SAVEPOINT probe").execute(&mut *tx).await?; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_aggregate_typecheck_max", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_storage_aggregate_typecheck_max; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_aggregate_typecheck_min"] + #[doc(hidden)] + pub const matrix_int4_eq_aggregate_typecheck_min: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_aggregate_typecheck_min", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2543usize, + start_col: 22usize, + end_line: 2543usize, + end_col: 83usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_aggregate_typecheck_min()), + ), + }; + fn matrix_int4_eq_aggregate_typecheck_min() -> anyhow::Result<()> { + async fn matrix_int4_eq_aggregate_typecheck_min( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE typecheck_table (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO typecheck_table(value) VALUES ($1::jsonb::{0})", + d, + ), + ) + }), + ) + .bind(payload) + .execute(&mut *tx) + .await?; + sqlx::query("SAVEPOINT probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(value) FROM typecheck_table", + "min", + ), + ) + }); + let err = sqlx::query_scalar::<_, String>(&sql) + .fetch_one(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "eql_v3.{0} on non-ord variant {1} must raise but succeeded", + "min", + d, + ), + ) + }), + ); + let db_err = err + .as_database_error() + .expect("expected database error from typecheck probe"); + let code = db_err.code(); + if ::anyhow::__private::not( + code.as_deref() == Some("42883") || code.as_deref() == Some("42725"), + ) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "expected SQLSTATE 42883 (undefined_function) or 42725 (ambiguous_function) for eql_v3.{0}({1}), got {2:?} (message: {3})", + "min", + d, + code, + db_err.message(), + ), + ) + }), + ), + ); + } + sqlx::query("ROLLBACK TO SAVEPOINT probe").execute(&mut *tx).await?; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_aggregate_typecheck_min", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_aggregate_typecheck_min; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_aggregate_typecheck_max"] + #[doc(hidden)] + pub const matrix_int4_eq_aggregate_typecheck_max: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_aggregate_typecheck_max", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2543usize, + start_col: 22usize, + end_line: 2543usize, + end_col: 83usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_aggregate_typecheck_max()), + ), + }; + fn matrix_int4_eq_aggregate_typecheck_max() -> anyhow::Result<()> { + async fn matrix_int4_eq_aggregate_typecheck_max( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let d = &spec.sql_domain; + let payload = ::eql_tests::helpers::PLACEHOLDER_PAYLOAD; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE typecheck_table (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO typecheck_table(value) VALUES ($1::jsonb::{0})", + d, + ), + ) + }), + ) + .bind(payload) + .execute(&mut *tx) + .await?; + sqlx::query("SAVEPOINT probe").execute(&mut *tx).await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT eql_v3.{0}(value) FROM typecheck_table", + "max", + ), + ) + }); + let err = sqlx::query_scalar::<_, String>(&sql) + .fetch_one(&mut *tx) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "eql_v3.{0} on non-ord variant {1} must raise but succeeded", + "max", + d, + ), + ) + }), + ); + let db_err = err + .as_database_error() + .expect("expected database error from typecheck probe"); + let code = db_err.code(); + if ::anyhow::__private::not( + code.as_deref() == Some("42883") || code.as_deref() == Some("42725"), + ) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "expected SQLSTATE 42883 (undefined_function) or 42725 (ambiguous_function) for eql_v3.{0}({1}), got {2:?} (message: {3})", + "max", + d, + code, + db_err.message(), + ), + ) + }), + ), + ); + } + sqlx::query("ROLLBACK TO SAVEPOINT probe").execute(&mut *tx).await?; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_aggregate_typecheck_max", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures(&[]); + let f: fn(_) -> _ = matrix_int4_eq_aggregate_typecheck_max; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_count_typed_column"] + #[doc(hidden)] + pub const matrix_int4_storage_count_typed_column: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_storage_count_typed_column", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2644usize, + start_col: 22usize, + end_line: 2644usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_count_typed_column()), + ), + }; + fn matrix_int4_storage_count_typed_column() -> anyhow::Result<()> { + async fn matrix_int4_storage_count_typed_column( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let expected = ::fixture_values().len() as i64; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE typed_count (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO typed_count(value) SELECT payload::{0} FROM {1}", + d, + fixture, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let actual: i64 = sqlx::query_scalar( + "SELECT COUNT(value) FROM typed_count", + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(actual == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "COUNT(value) on typed {0} column: want {1}, got {2}", + d, + expected, + actual, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_count_typed_column", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_storage_count_typed_column; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_storage_count_path_cast"] + #[doc(hidden)] + pub const matrix_int4_storage_count_path_cast: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_storage_count_path_cast", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2677usize, + start_col: 22usize, + end_line: 2677usize, + end_col: 69usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_storage_count_path_cast()), + ), + }; + fn matrix_int4_storage_count_path_cast() -> anyhow::Result<()> { + async fn matrix_int4_storage_count_path_cast( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Storage); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let expected = ::fixture_values().len() as i64; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT COUNT(payload::{0}) FROM {1}", d, fixture), + ) + }); + let actual: i64 = sqlx::query_scalar(&sql).fetch_one(&pool).await?; + if ::anyhow::__private::not(actual == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "COUNT(payload::{0}) on {1}: want {2}, got {3}; SQL={4}", + d, + fixture, + expected, + actual, + sql, + ), + ) + }), + ), + ); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_storage_count_path_cast", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_storage_count_path_cast; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_count_typed_column"] + #[doc(hidden)] + pub const matrix_int4_eq_count_typed_column: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_count_typed_column", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2644usize, + start_col: 22usize, + end_line: 2644usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_count_typed_column()), + ), + }; + fn matrix_int4_eq_count_typed_column() -> anyhow::Result<()> { + async fn matrix_int4_eq_count_typed_column( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let expected = ::fixture_values().len() as i64; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE typed_count (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO typed_count(value) SELECT payload::{0} FROM {1}", + d, + fixture, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let actual: i64 = sqlx::query_scalar( + "SELECT COUNT(value) FROM typed_count", + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(actual == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "COUNT(value) on typed {0} column: want {1}, got {2}", + d, + expected, + actual, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_count_typed_column", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_count_typed_column; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_count_path_cast"] + #[doc(hidden)] + pub const matrix_int4_eq_count_path_cast: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_eq_count_path_cast"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2677usize, + start_col: 22usize, + end_line: 2677usize, + end_col: 69usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_count_path_cast()), + ), + }; + fn matrix_int4_eq_count_path_cast() -> anyhow::Result<()> { + async fn matrix_int4_eq_count_path_cast( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let expected = ::fixture_values().len() as i64; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT COUNT(payload::{0}) FROM {1}", d, fixture), + ) + }); + let actual: i64 = sqlx::query_scalar(&sql).fetch_one(&pool).await?; + if ::anyhow::__private::not(actual == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "COUNT(payload::{0}) on {1}: want {2}, got {3}; SQL={4}", + d, + fixture, + expected, + actual, + sql, + ), + ) + }), + ), + ); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_count_path_cast", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_count_path_cast; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_eq_count_distinct_extractor"] + #[doc(hidden)] + pub const matrix_int4_eq_count_distinct_extractor: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_eq_count_distinct_extractor", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2721usize, + start_col: 22usize, + end_line: 2721usize, + end_col: 78usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_eq_count_distinct_extractor()), + ), + }; + fn matrix_int4_eq_count_distinct_extractor() -> anyhow::Result<()> { + async fn matrix_int4_eq_count_distinct_extractor( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Eq); + let d = &spec.sql_domain; + let extractor_fn = spec + .extractor_fn() + .expect("non-Storage variant must expose an extractor"); + let extractor = ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("{0}(value)", extractor_fn)) + }); + let fixture = ::fixture_table_name(); + let expected = ::fixture_values().len() as i64; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE distinct_count (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO distinct_count(value) SELECT payload::{0} FROM {1}", + d, + fixture, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT COUNT(DISTINCT {0}) FROM distinct_count", + extractor, + ), + ) + }); + let actual: i64 = sqlx::query_scalar(&sql).fetch_one(&mut *tx).await?; + if ::anyhow::__private::not(actual == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "COUNT(DISTINCT {0}) on {1}: want {2} (one per FIXTURE_VALUES row), got {3}; SQL={4}", + extractor, + d, + expected, + actual, + sql, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_eq_count_distinct_extractor", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_eq_count_distinct_extractor; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_count_typed_column"] + #[doc(hidden)] + pub const matrix_int4_ord_count_typed_column: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_count_typed_column", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2644usize, + start_col: 22usize, + end_line: 2644usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_count_typed_column()), + ), + }; + fn matrix_int4_ord_count_typed_column() -> anyhow::Result<()> { + async fn matrix_int4_ord_count_typed_column( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let expected = ::fixture_values().len() as i64; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE typed_count (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO typed_count(value) SELECT payload::{0} FROM {1}", + d, + fixture, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let actual: i64 = sqlx::query_scalar( + "SELECT COUNT(value) FROM typed_count", + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(actual == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "COUNT(value) on typed {0} column: want {1}, got {2}", + d, + expected, + actual, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_count_typed_column", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_count_typed_column; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_count_path_cast"] + #[doc(hidden)] + pub const matrix_int4_ord_count_path_cast: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName("scalars::int4::matrix_int4_ord_count_path_cast"), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2677usize, + start_col: 22usize, + end_line: 2677usize, + end_col: 69usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_count_path_cast()), + ), + }; + fn matrix_int4_ord_count_path_cast() -> anyhow::Result<()> { + async fn matrix_int4_ord_count_path_cast( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let expected = ::fixture_values().len() as i64; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT COUNT(payload::{0}) FROM {1}", d, fixture), + ) + }); + let actual: i64 = sqlx::query_scalar(&sql).fetch_one(&pool).await?; + if ::anyhow::__private::not(actual == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "COUNT(payload::{0}) on {1}: want {2}, got {3}; SQL={4}", + d, + fixture, + expected, + actual, + sql, + ), + ) + }), + ), + ); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_count_path_cast", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_count_path_cast; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_count_distinct_extractor"] + #[doc(hidden)] + pub const matrix_int4_ord_count_distinct_extractor: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_count_distinct_extractor", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2721usize, + start_col: 22usize, + end_line: 2721usize, + end_col: 78usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_count_distinct_extractor()), + ), + }; + fn matrix_int4_ord_count_distinct_extractor() -> anyhow::Result<()> { + async fn matrix_int4_ord_count_distinct_extractor( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let extractor_fn = spec + .extractor_fn() + .expect("non-Storage variant must expose an extractor"); + let extractor = ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("{0}(value)", extractor_fn)) + }); + let fixture = ::fixture_table_name(); + let expected = ::fixture_values().len() as i64; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE distinct_count (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO distinct_count(value) SELECT payload::{0} FROM {1}", + d, + fixture, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT COUNT(DISTINCT {0}) FROM distinct_count", + extractor, + ), + ) + }); + let actual: i64 = sqlx::query_scalar(&sql).fetch_one(&mut *tx).await?; + if ::anyhow::__private::not(actual == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "COUNT(DISTINCT {0}) on {1}: want {2} (one per FIXTURE_VALUES row), got {3}; SQL={4}", + extractor, + d, + expected, + actual, + sql, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_count_distinct_extractor", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_count_distinct_extractor; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_count_typed_column"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_count_typed_column: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_count_typed_column", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2644usize, + start_col: 22usize, + end_line: 2644usize, + end_col: 72usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_count_typed_column()), + ), + }; + fn matrix_int4_ord_ore_count_typed_column() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_count_typed_column( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let expected = ::fixture_values().len() as i64; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE typed_count (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO typed_count(value) SELECT payload::{0} FROM {1}", + d, + fixture, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let actual: i64 = sqlx::query_scalar( + "SELECT COUNT(value) FROM typed_count", + ) + .fetch_one(&mut *tx) + .await?; + if ::anyhow::__private::not(actual == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "COUNT(value) on typed {0} column: want {1}, got {2}", + d, + expected, + actual, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_count_typed_column", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_count_typed_column; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_count_path_cast"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_count_path_cast: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_count_path_cast", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2677usize, + start_col: 22usize, + end_line: 2677usize, + end_col: 69usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_count_path_cast()), + ), + }; + fn matrix_int4_ord_ore_count_path_cast() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_count_path_cast( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let fixture = ::fixture_table_name(); + let expected = ::fixture_values().len() as i64; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!("SELECT COUNT(payload::{0}) FROM {1}", d, fixture), + ) + }); + let actual: i64 = sqlx::query_scalar(&sql).fetch_one(&pool).await?; + if ::anyhow::__private::not(actual == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "COUNT(payload::{0}) on {1}: want {2}, got {3}; SQL={4}", + d, + fixture, + expected, + actual, + sql, + ), + ) + }), + ), + ); + } + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_count_path_cast", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_count_path_cast; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_count_distinct_extractor"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_count_distinct_extractor: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_count_distinct_extractor", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2721usize, + start_col: 22usize, + end_line: 2721usize, + end_col: 78usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_count_distinct_extractor()), + ), + }; + fn matrix_int4_ord_ore_count_distinct_extractor() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_count_distinct_extractor( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let extractor_fn = spec + .extractor_fn() + .expect("non-Storage variant must expose an extractor"); + let extractor = ::alloc::__export::must_use({ + ::alloc::fmt::format(format_args!("{0}(value)", extractor_fn)) + }); + let fixture = ::fixture_table_name(); + let expected = ::fixture_values().len() as i64; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE distinct_count (value {0}) ON COMMIT DROP", + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO distinct_count(value) SELECT payload::{0} FROM {1}", + d, + fixture, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT COUNT(DISTINCT {0}) FROM distinct_count", + extractor, + ), + ) + }); + let actual: i64 = sqlx::query_scalar(&sql).fetch_one(&mut *tx).await?; + if ::anyhow::__private::not(actual == expected) { + return ::anyhow::__private::Err( + ::anyhow::Error::msg( + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "COUNT(DISTINCT {0}) on {1}: want {2} (one per FIXTURE_VALUES row), got {3}; SQL={4}", + extractor, + d, + expected, + actual, + sql, + ), + ) + }), + ), + ); + } + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_count_distinct_extractor", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_count_distinct_extractor; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_order_by_asc_no_where"] + #[doc(hidden)] + pub const matrix_int4_ord_order_by_asc_no_where: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_order_by_asc_no_where", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1782usize, + start_col: 22usize, + end_line: 1782usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_order_by_asc_no_where()), + ), + }; + fn matrix_int4_ord_order_by_asc_no_where() -> anyhow::Result<()> { + async fn matrix_int4_ord_order_by_asc_no_where( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let fixture_table = ::fixture_table_name(); + let zero: i32 = Default::default(); + let gt_zero = "all" == "gt_zero"; + let where_clause = if gt_zero { + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + " WHERE plaintext > {0}", + ::to_sql_literal(zero), + ), + ) + }) + } else { + String::new() + }; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0}{3} ORDER BY eql_v3.ord_term(payload::{1}) {2}", + fixture_table, + &spec.sql_domain, + "ASC", + where_clause, + ), + ) + }); + let actual: Vec = sqlx::query_scalar(&sql).fetch_all(&pool).await?; + let mut expected: Vec = ::fixture_values() + .to_vec(); + expected.sort(); + if gt_zero { + expected.retain(|v| *v > zero); + } + if "ASC" == "DESC" { + expected.reverse(); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + &spec.sql_domain, + "asc_no_where", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_order_by_asc_no_where", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_order_by_asc_no_where; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_order_by_desc_no_where"] + #[doc(hidden)] + pub const matrix_int4_ord_order_by_desc_no_where: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_order_by_desc_no_where", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1782usize, + start_col: 22usize, + end_line: 1782usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_order_by_desc_no_where()), + ), + }; + fn matrix_int4_ord_order_by_desc_no_where() -> anyhow::Result<()> { + async fn matrix_int4_ord_order_by_desc_no_where( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let fixture_table = ::fixture_table_name(); + let zero: i32 = Default::default(); + let gt_zero = "all" == "gt_zero"; + let where_clause = if gt_zero { + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + " WHERE plaintext > {0}", + ::to_sql_literal(zero), + ), + ) + }) + } else { + String::new() + }; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0}{3} ORDER BY eql_v3.ord_term(payload::{1}) {2}", + fixture_table, + &spec.sql_domain, + "DESC", + where_clause, + ), + ) + }); + let actual: Vec = sqlx::query_scalar(&sql).fetch_all(&pool).await?; + let mut expected: Vec = ::fixture_values() + .to_vec(); + expected.sort(); + if gt_zero { + expected.retain(|v| *v > zero); + } + if "DESC" == "DESC" { + expected.reverse(); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + &spec.sql_domain, + "desc_no_where", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_order_by_desc_no_where", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_order_by_desc_no_where; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_order_by_asc_with_where"] + #[doc(hidden)] + pub const matrix_int4_ord_order_by_asc_with_where: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_order_by_asc_with_where", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1782usize, + start_col: 22usize, + end_line: 1782usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_order_by_asc_with_where()), + ), + }; + fn matrix_int4_ord_order_by_asc_with_where() -> anyhow::Result<()> { + async fn matrix_int4_ord_order_by_asc_with_where( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let fixture_table = ::fixture_table_name(); + let zero: i32 = Default::default(); + let gt_zero = "gt_zero" == "gt_zero"; + let where_clause = if gt_zero { + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + " WHERE plaintext > {0}", + ::to_sql_literal(zero), + ), + ) + }) + } else { + String::new() + }; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0}{3} ORDER BY eql_v3.ord_term(payload::{1}) {2}", + fixture_table, + &spec.sql_domain, + "ASC", + where_clause, + ), + ) + }); + let actual: Vec = sqlx::query_scalar(&sql).fetch_all(&pool).await?; + let mut expected: Vec = ::fixture_values() + .to_vec(); + expected.sort(); + if gt_zero { + expected.retain(|v| *v > zero); + } + if "ASC" == "DESC" { + expected.reverse(); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + &spec.sql_domain, + "asc_with_where", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_order_by_asc_with_where", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_order_by_asc_with_where; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_order_by_desc_with_where"] + #[doc(hidden)] + pub const matrix_int4_ord_order_by_desc_with_where: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_order_by_desc_with_where", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1782usize, + start_col: 22usize, + end_line: 1782usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_order_by_desc_with_where()), + ), + }; + fn matrix_int4_ord_order_by_desc_with_where() -> anyhow::Result<()> { + async fn matrix_int4_ord_order_by_desc_with_where( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let fixture_table = ::fixture_table_name(); + let zero: i32 = Default::default(); + let gt_zero = "gt_zero" == "gt_zero"; + let where_clause = if gt_zero { + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + " WHERE plaintext > {0}", + ::to_sql_literal(zero), + ), + ) + }) + } else { + String::new() + }; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0}{3} ORDER BY eql_v3.ord_term(payload::{1}) {2}", + fixture_table, + &spec.sql_domain, + "DESC", + where_clause, + ), + ) + }); + let actual: Vec = sqlx::query_scalar(&sql).fetch_all(&pool).await?; + let mut expected: Vec = ::fixture_values() + .to_vec(); + expected.sort(); + if gt_zero { + expected.retain(|v| *v > zero); + } + if "DESC" == "DESC" { + expected.reverse(); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + &spec.sql_domain, + "desc_with_where", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_order_by_desc_with_where", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_order_by_desc_with_where; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_order_by_asc_no_where"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_order_by_asc_no_where: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_order_by_asc_no_where", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1782usize, + start_col: 22usize, + end_line: 1782usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_order_by_asc_no_where()), + ), + }; + fn matrix_int4_ord_ore_order_by_asc_no_where() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_order_by_asc_no_where( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let fixture_table = ::fixture_table_name(); + let zero: i32 = Default::default(); + let gt_zero = "all" == "gt_zero"; + let where_clause = if gt_zero { + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + " WHERE plaintext > {0}", + ::to_sql_literal(zero), + ), + ) + }) + } else { + String::new() + }; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0}{3} ORDER BY eql_v3.ord_term(payload::{1}) {2}", + fixture_table, + &spec.sql_domain, + "ASC", + where_clause, + ), + ) + }); + let actual: Vec = sqlx::query_scalar(&sql).fetch_all(&pool).await?; + let mut expected: Vec = ::fixture_values() + .to_vec(); + expected.sort(); + if gt_zero { + expected.retain(|v| *v > zero); + } + if "ASC" == "DESC" { + expected.reverse(); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + &spec.sql_domain, + "asc_no_where", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_order_by_asc_no_where", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_order_by_asc_no_where; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_order_by_desc_no_where"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_order_by_desc_no_where: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_order_by_desc_no_where", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1782usize, + start_col: 22usize, + end_line: 1782usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_order_by_desc_no_where()), + ), + }; + fn matrix_int4_ord_ore_order_by_desc_no_where() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_order_by_desc_no_where( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let fixture_table = ::fixture_table_name(); + let zero: i32 = Default::default(); + let gt_zero = "all" == "gt_zero"; + let where_clause = if gt_zero { + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + " WHERE plaintext > {0}", + ::to_sql_literal(zero), + ), + ) + }) + } else { + String::new() + }; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0}{3} ORDER BY eql_v3.ord_term(payload::{1}) {2}", + fixture_table, + &spec.sql_domain, + "DESC", + where_clause, + ), + ) + }); + let actual: Vec = sqlx::query_scalar(&sql).fetch_all(&pool).await?; + let mut expected: Vec = ::fixture_values() + .to_vec(); + expected.sort(); + if gt_zero { + expected.retain(|v| *v > zero); + } + if "DESC" == "DESC" { + expected.reverse(); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + &spec.sql_domain, + "desc_no_where", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_order_by_desc_no_where", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_order_by_desc_no_where; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_order_by_asc_with_where"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_order_by_asc_with_where: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_order_by_asc_with_where", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1782usize, + start_col: 22usize, + end_line: 1782usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_order_by_asc_with_where()), + ), + }; + fn matrix_int4_ord_ore_order_by_asc_with_where() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_order_by_asc_with_where( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let fixture_table = ::fixture_table_name(); + let zero: i32 = Default::default(); + let gt_zero = "gt_zero" == "gt_zero"; + let where_clause = if gt_zero { + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + " WHERE plaintext > {0}", + ::to_sql_literal(zero), + ), + ) + }) + } else { + String::new() + }; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0}{3} ORDER BY eql_v3.ord_term(payload::{1}) {2}", + fixture_table, + &spec.sql_domain, + "ASC", + where_clause, + ), + ) + }); + let actual: Vec = sqlx::query_scalar(&sql).fetch_all(&pool).await?; + let mut expected: Vec = ::fixture_values() + .to_vec(); + expected.sort(); + if gt_zero { + expected.retain(|v| *v > zero); + } + if "ASC" == "DESC" { + expected.reverse(); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + &spec.sql_domain, + "asc_with_where", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_order_by_asc_with_where", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_order_by_asc_with_where; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_order_by_desc_with_where"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_order_by_desc_with_where: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_order_by_desc_with_where", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1782usize, + start_col: 22usize, + end_line: 1782usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_order_by_desc_with_where()), + ), + }; + fn matrix_int4_ord_ore_order_by_desc_with_where() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_order_by_desc_with_where( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + use ::eql_tests::scalar_domains::ScalarType; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let fixture_table = ::fixture_table_name(); + let zero: i32 = Default::default(); + let gt_zero = "gt_zero" == "gt_zero"; + let where_clause = if gt_zero { + ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + " WHERE plaintext > {0}", + ::to_sql_literal(zero), + ), + ) + }) + } else { + String::new() + }; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0}{3} ORDER BY eql_v3.ord_term(payload::{1}) {2}", + fixture_table, + &spec.sql_domain, + "DESC", + where_clause, + ), + ) + }); + let actual: Vec = sqlx::query_scalar(&sql).fetch_all(&pool).await?; + let mut expected: Vec = ::fixture_values() + .to_vec(); + expected.sort(); + if gt_zero { + expected.retain(|v| *v > zero); + } + if "DESC" == "DESC" { + expected.reverse(); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + &spec.sql_domain, + "desc_with_where", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_order_by_desc_with_where", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_order_by_desc_with_where; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_order_by_asc_nulls_first"] + #[doc(hidden)] + pub const matrix_int4_ord_order_by_asc_nulls_first: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_order_by_asc_nulls_first", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1892usize, + start_col: 22usize, + end_line: 1892usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_order_by_asc_nulls_first()), + ), + }; + fn matrix_int4_ord_order_by_asc_nulls_first() -> anyhow::Result<()> { + async fn matrix_int4_ord_order_by_asc_nulls_first( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + const NULL_ROWS: usize = 3; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let table = "matrix_int4_ord_order_by_asc_nulls_first"; + let fixture_table = ::fixture_table_name(); + let pg = ::PG_TYPE; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {0} (plaintext {1}, value {2}) ON COMMIT DROP", + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT plaintext, payload::{2} FROM {0}", + fixture_table, + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT NULL::{2}, NULL::{3} FROM generate_series(1, {0})", + NULL_ROWS, + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {2} ORDER BY eql_v3.ord_term(value) {0} NULLS {1}", + "ASC", + "FIRST", + table, + ), + ) + }); + let actual: Vec> = sqlx::query_scalar(&sql) + .fetch_all(&mut *tx) + .await?; + let mut non_null: Vec = ::fixture_values() + .to_vec(); + non_null.sort(); + if "ASC" == "DESC" { + non_null.reverse(); + } + let sorted = non_null.into_iter().map(Some); + let mut expected: Vec> = Vec::new(); + if "FIRST" == "FIRST" { + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + expected.extend(sorted); + } else { + expected.extend(sorted); + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + d, + "asc_nulls_first", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_order_by_asc_nulls_first", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_order_by_asc_nulls_first; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_order_by_asc_nulls_last"] + #[doc(hidden)] + pub const matrix_int4_ord_order_by_asc_nulls_last: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_order_by_asc_nulls_last", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1892usize, + start_col: 22usize, + end_line: 1892usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_order_by_asc_nulls_last()), + ), + }; + fn matrix_int4_ord_order_by_asc_nulls_last() -> anyhow::Result<()> { + async fn matrix_int4_ord_order_by_asc_nulls_last( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + const NULL_ROWS: usize = 3; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let table = "matrix_int4_ord_order_by_asc_nulls_last"; + let fixture_table = ::fixture_table_name(); + let pg = ::PG_TYPE; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {0} (plaintext {1}, value {2}) ON COMMIT DROP", + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT plaintext, payload::{2} FROM {0}", + fixture_table, + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT NULL::{2}, NULL::{3} FROM generate_series(1, {0})", + NULL_ROWS, + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {2} ORDER BY eql_v3.ord_term(value) {0} NULLS {1}", + "ASC", + "LAST", + table, + ), + ) + }); + let actual: Vec> = sqlx::query_scalar(&sql) + .fetch_all(&mut *tx) + .await?; + let mut non_null: Vec = ::fixture_values() + .to_vec(); + non_null.sort(); + if "ASC" == "DESC" { + non_null.reverse(); + } + let sorted = non_null.into_iter().map(Some); + let mut expected: Vec> = Vec::new(); + if "LAST" == "FIRST" { + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + expected.extend(sorted); + } else { + expected.extend(sorted); + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + d, + "asc_nulls_last", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_order_by_asc_nulls_last", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_order_by_asc_nulls_last; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_order_by_desc_nulls_first"] + #[doc(hidden)] + pub const matrix_int4_ord_order_by_desc_nulls_first: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_order_by_desc_nulls_first", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1892usize, + start_col: 22usize, + end_line: 1892usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_order_by_desc_nulls_first()), + ), + }; + fn matrix_int4_ord_order_by_desc_nulls_first() -> anyhow::Result<()> { + async fn matrix_int4_ord_order_by_desc_nulls_first( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + const NULL_ROWS: usize = 3; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let table = "matrix_int4_ord_order_by_desc_nulls_first"; + let fixture_table = ::fixture_table_name(); + let pg = ::PG_TYPE; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {0} (plaintext {1}, value {2}) ON COMMIT DROP", + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT plaintext, payload::{2} FROM {0}", + fixture_table, + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT NULL::{2}, NULL::{3} FROM generate_series(1, {0})", + NULL_ROWS, + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {2} ORDER BY eql_v3.ord_term(value) {0} NULLS {1}", + "DESC", + "FIRST", + table, + ), + ) + }); + let actual: Vec> = sqlx::query_scalar(&sql) + .fetch_all(&mut *tx) + .await?; + let mut non_null: Vec = ::fixture_values() + .to_vec(); + non_null.sort(); + if "DESC" == "DESC" { + non_null.reverse(); + } + let sorted = non_null.into_iter().map(Some); + let mut expected: Vec> = Vec::new(); + if "FIRST" == "FIRST" { + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + expected.extend(sorted); + } else { + expected.extend(sorted); + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + d, + "desc_nulls_first", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_order_by_desc_nulls_first", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_order_by_desc_nulls_first; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_order_by_desc_nulls_last"] + #[doc(hidden)] + pub const matrix_int4_ord_order_by_desc_nulls_last: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_order_by_desc_nulls_last", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1892usize, + start_col: 22usize, + end_line: 1892usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_order_by_desc_nulls_last()), + ), + }; + fn matrix_int4_ord_order_by_desc_nulls_last() -> anyhow::Result<()> { + async fn matrix_int4_ord_order_by_desc_nulls_last( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + const NULL_ROWS: usize = 3; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let d = &spec.sql_domain; + let table = "matrix_int4_ord_order_by_desc_nulls_last"; + let fixture_table = ::fixture_table_name(); + let pg = ::PG_TYPE; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {0} (plaintext {1}, value {2}) ON COMMIT DROP", + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT plaintext, payload::{2} FROM {0}", + fixture_table, + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT NULL::{2}, NULL::{3} FROM generate_series(1, {0})", + NULL_ROWS, + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {2} ORDER BY eql_v3.ord_term(value) {0} NULLS {1}", + "DESC", + "LAST", + table, + ), + ) + }); + let actual: Vec> = sqlx::query_scalar(&sql) + .fetch_all(&mut *tx) + .await?; + let mut non_null: Vec = ::fixture_values() + .to_vec(); + non_null.sort(); + if "DESC" == "DESC" { + non_null.reverse(); + } + let sorted = non_null.into_iter().map(Some); + let mut expected: Vec> = Vec::new(); + if "LAST" == "FIRST" { + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + expected.extend(sorted); + } else { + expected.extend(sorted); + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + d, + "desc_nulls_last", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_order_by_desc_nulls_last", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_order_by_desc_nulls_last; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_order_by_asc_nulls_first"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_order_by_asc_nulls_first: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_order_by_asc_nulls_first", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1892usize, + start_col: 22usize, + end_line: 1892usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_order_by_asc_nulls_first()), + ), + }; + fn matrix_int4_ord_ore_order_by_asc_nulls_first() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_order_by_asc_nulls_first( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + const NULL_ROWS: usize = 3; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let table = "matrix_int4_ord_ore_order_by_asc_nulls_first"; + let fixture_table = ::fixture_table_name(); + let pg = ::PG_TYPE; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {0} (plaintext {1}, value {2}) ON COMMIT DROP", + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT plaintext, payload::{2} FROM {0}", + fixture_table, + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT NULL::{2}, NULL::{3} FROM generate_series(1, {0})", + NULL_ROWS, + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {2} ORDER BY eql_v3.ord_term(value) {0} NULLS {1}", + "ASC", + "FIRST", + table, + ), + ) + }); + let actual: Vec> = sqlx::query_scalar(&sql) + .fetch_all(&mut *tx) + .await?; + let mut non_null: Vec = ::fixture_values() + .to_vec(); + non_null.sort(); + if "ASC" == "DESC" { + non_null.reverse(); + } + let sorted = non_null.into_iter().map(Some); + let mut expected: Vec> = Vec::new(); + if "FIRST" == "FIRST" { + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + expected.extend(sorted); + } else { + expected.extend(sorted); + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + d, + "asc_nulls_first", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_order_by_asc_nulls_first", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_order_by_asc_nulls_first; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_order_by_asc_nulls_last"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_order_by_asc_nulls_last: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_order_by_asc_nulls_last", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1892usize, + start_col: 22usize, + end_line: 1892usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_order_by_asc_nulls_last()), + ), + }; + fn matrix_int4_ord_ore_order_by_asc_nulls_last() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_order_by_asc_nulls_last( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + const NULL_ROWS: usize = 3; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let table = "matrix_int4_ord_ore_order_by_asc_nulls_last"; + let fixture_table = ::fixture_table_name(); + let pg = ::PG_TYPE; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {0} (plaintext {1}, value {2}) ON COMMIT DROP", + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT plaintext, payload::{2} FROM {0}", + fixture_table, + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT NULL::{2}, NULL::{3} FROM generate_series(1, {0})", + NULL_ROWS, + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {2} ORDER BY eql_v3.ord_term(value) {0} NULLS {1}", + "ASC", + "LAST", + table, + ), + ) + }); + let actual: Vec> = sqlx::query_scalar(&sql) + .fetch_all(&mut *tx) + .await?; + let mut non_null: Vec = ::fixture_values() + .to_vec(); + non_null.sort(); + if "ASC" == "DESC" { + non_null.reverse(); + } + let sorted = non_null.into_iter().map(Some); + let mut expected: Vec> = Vec::new(); + if "LAST" == "FIRST" { + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + expected.extend(sorted); + } else { + expected.extend(sorted); + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + d, + "asc_nulls_last", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_order_by_asc_nulls_last", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_order_by_asc_nulls_last; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_order_by_desc_nulls_first"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_order_by_desc_nulls_first: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_order_by_desc_nulls_first", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1892usize, + start_col: 22usize, + end_line: 1892usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_order_by_desc_nulls_first()), + ), + }; + fn matrix_int4_ord_ore_order_by_desc_nulls_first() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_order_by_desc_nulls_first( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + const NULL_ROWS: usize = 3; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let table = "matrix_int4_ord_ore_order_by_desc_nulls_first"; + let fixture_table = ::fixture_table_name(); + let pg = ::PG_TYPE; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {0} (plaintext {1}, value {2}) ON COMMIT DROP", + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT plaintext, payload::{2} FROM {0}", + fixture_table, + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT NULL::{2}, NULL::{3} FROM generate_series(1, {0})", + NULL_ROWS, + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {2} ORDER BY eql_v3.ord_term(value) {0} NULLS {1}", + "DESC", + "FIRST", + table, + ), + ) + }); + let actual: Vec> = sqlx::query_scalar(&sql) + .fetch_all(&mut *tx) + .await?; + let mut non_null: Vec = ::fixture_values() + .to_vec(); + non_null.sort(); + if "DESC" == "DESC" { + non_null.reverse(); + } + let sorted = non_null.into_iter().map(Some); + let mut expected: Vec> = Vec::new(); + if "FIRST" == "FIRST" { + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + expected.extend(sorted); + } else { + expected.extend(sorted); + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + d, + "desc_nulls_first", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_order_by_desc_nulls_first", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_order_by_desc_nulls_first; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_order_by_desc_nulls_last"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_order_by_desc_nulls_last: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_order_by_desc_nulls_last", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 1892usize, + start_col: 22usize, + end_line: 1892usize, + end_col: 74usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_order_by_desc_nulls_last()), + ), + }; + fn matrix_int4_ord_ore_order_by_desc_nulls_last() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_order_by_desc_nulls_last( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + const NULL_ROWS: usize = 3; + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let d = &spec.sql_domain; + let table = "matrix_int4_ord_ore_order_by_desc_nulls_last"; + let fixture_table = ::fixture_table_name(); + let pg = ::PG_TYPE; + let mut tx = pool.begin().await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "CREATE TEMP TABLE {0} (plaintext {1}, value {2}) ON COMMIT DROP", + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT plaintext, payload::{2} FROM {0}", + fixture_table, + table, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + sqlx::query( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "INSERT INTO {1}(plaintext, value) SELECT NULL::{2}, NULL::{3} FROM generate_series(1, {0})", + NULL_ROWS, + table, + pg, + d, + ), + ) + }), + ) + .execute(&mut *tx) + .await?; + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {2} ORDER BY eql_v3.ord_term(value) {0} NULLS {1}", + "DESC", + "LAST", + table, + ), + ) + }); + let actual: Vec> = sqlx::query_scalar(&sql) + .fetch_all(&mut *tx) + .await?; + let mut non_null: Vec = ::fixture_values() + .to_vec(); + non_null.sort(); + if "DESC" == "DESC" { + non_null.reverse(); + } + let sorted = non_null.into_iter().map(Some); + let mut expected: Vec> = Vec::new(); + if "LAST" == "FIRST" { + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + expected.extend(sorted); + } else { + expected.extend(sorted); + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + } + match (&actual, &expected) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::Some( + format_args!( + "domain={0} mode={1} SQL={2} expected {3:?}, got {4:?}", + d, + "desc_nulls_last", + sql, + expected, + actual, + ), + ), + ); + } + } + }; + tx.commit().await?; + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_order_by_desc_nulls_last", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_order_by_desc_nulls_last; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_order_by_using_lt_rejects"] + #[doc(hidden)] + pub const matrix_int4_ord_order_by_using_lt_rejects: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_order_by_using_lt_rejects", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2009usize, + start_col: 22usize, + end_line: 2009usize, + end_col: 87usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_order_by_using_lt_rejects()), + ), + }; + fn matrix_int4_ord_order_by_using_lt_rejects() -> anyhow::Result<()> { + async fn matrix_int4_ord_order_by_using_lt_rejects( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let fixture_table = ::fixture_table_name(); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0} ORDER BY payload::{1} USING {2}", + fixture_table, + &spec.sql_domain, + "<", + ), + ) + }); + let err = sqlx::query_scalar::<_, i32>(&sql) + .fetch_all(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} SQL={2} must reject ORDER BY USING (no opclass on domain by design) but succeeded", + &spec.sql_domain, + "<", + sql, + ), + ) + }), + ); + ::eql_tests::assert_db_error(&err, "42809", None); + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_order_by_using_lt_rejects", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_order_by_using_lt_rejects; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_order_by_using_lte_rejects"] + #[doc(hidden)] + pub const matrix_int4_ord_order_by_using_lte_rejects: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_order_by_using_lte_rejects", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2009usize, + start_col: 22usize, + end_line: 2009usize, + end_col: 87usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_order_by_using_lte_rejects()), + ), + }; + fn matrix_int4_ord_order_by_using_lte_rejects() -> anyhow::Result<()> { + async fn matrix_int4_ord_order_by_using_lte_rejects( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let fixture_table = ::fixture_table_name(); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0} ORDER BY payload::{1} USING {2}", + fixture_table, + &spec.sql_domain, + "<=", + ), + ) + }); + let err = sqlx::query_scalar::<_, i32>(&sql) + .fetch_all(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} SQL={2} must reject ORDER BY USING (no opclass on domain by design) but succeeded", + &spec.sql_domain, + "<=", + sql, + ), + ) + }), + ); + ::eql_tests::assert_db_error(&err, "42809", None); + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_order_by_using_lte_rejects", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_order_by_using_lte_rejects; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_order_by_using_gt_rejects"] + #[doc(hidden)] + pub const matrix_int4_ord_order_by_using_gt_rejects: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_order_by_using_gt_rejects", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2009usize, + start_col: 22usize, + end_line: 2009usize, + end_col: 87usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_order_by_using_gt_rejects()), + ), + }; + fn matrix_int4_ord_order_by_using_gt_rejects() -> anyhow::Result<()> { + async fn matrix_int4_ord_order_by_using_gt_rejects( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let fixture_table = ::fixture_table_name(); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0} ORDER BY payload::{1} USING {2}", + fixture_table, + &spec.sql_domain, + ">", + ), + ) + }); + let err = sqlx::query_scalar::<_, i32>(&sql) + .fetch_all(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} SQL={2} must reject ORDER BY USING (no opclass on domain by design) but succeeded", + &spec.sql_domain, + ">", + sql, + ), + ) + }), + ); + ::eql_tests::assert_db_error(&err, "42809", None); + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_order_by_using_gt_rejects", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_order_by_using_gt_rejects; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_order_by_using_gte_rejects"] + #[doc(hidden)] + pub const matrix_int4_ord_order_by_using_gte_rejects: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_order_by_using_gte_rejects", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2009usize, + start_col: 22usize, + end_line: 2009usize, + end_col: 87usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_order_by_using_gte_rejects()), + ), + }; + fn matrix_int4_ord_order_by_using_gte_rejects() -> anyhow::Result<()> { + async fn matrix_int4_ord_order_by_using_gte_rejects( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::Ord); + let fixture_table = ::fixture_table_name(); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0} ORDER BY payload::{1} USING {2}", + fixture_table, + &spec.sql_domain, + ">=", + ), + ) + }); + let err = sqlx::query_scalar::<_, i32>(&sql) + .fetch_all(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} SQL={2} must reject ORDER BY USING (no opclass on domain by design) but succeeded", + &spec.sql_domain, + ">=", + sql, + ), + ) + }), + ); + ::eql_tests::assert_db_error(&err, "42809", None); + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_order_by_using_gte_rejects", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_order_by_using_gte_rejects; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_order_by_using_lt_rejects"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_order_by_using_lt_rejects: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_order_by_using_lt_rejects", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2009usize, + start_col: 22usize, + end_line: 2009usize, + end_col: 87usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_order_by_using_lt_rejects()), + ), + }; + fn matrix_int4_ord_ore_order_by_using_lt_rejects() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_order_by_using_lt_rejects( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let fixture_table = ::fixture_table_name(); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0} ORDER BY payload::{1} USING {2}", + fixture_table, + &spec.sql_domain, + "<", + ), + ) + }); + let err = sqlx::query_scalar::<_, i32>(&sql) + .fetch_all(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} SQL={2} must reject ORDER BY USING (no opclass on domain by design) but succeeded", + &spec.sql_domain, + "<", + sql, + ), + ) + }), + ); + ::eql_tests::assert_db_error(&err, "42809", None); + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_order_by_using_lt_rejects", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_order_by_using_lt_rejects; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_order_by_using_lte_rejects"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_order_by_using_lte_rejects: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_order_by_using_lte_rejects", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2009usize, + start_col: 22usize, + end_line: 2009usize, + end_col: 87usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_order_by_using_lte_rejects()), + ), + }; + fn matrix_int4_ord_ore_order_by_using_lte_rejects() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_order_by_using_lte_rejects( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let fixture_table = ::fixture_table_name(); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0} ORDER BY payload::{1} USING {2}", + fixture_table, + &spec.sql_domain, + "<=", + ), + ) + }); + let err = sqlx::query_scalar::<_, i32>(&sql) + .fetch_all(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} SQL={2} must reject ORDER BY USING (no opclass on domain by design) but succeeded", + &spec.sql_domain, + "<=", + sql, + ), + ) + }), + ); + ::eql_tests::assert_db_error(&err, "42809", None); + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_order_by_using_lte_rejects", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_order_by_using_lte_rejects; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_order_by_using_gt_rejects"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_order_by_using_gt_rejects: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_order_by_using_gt_rejects", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2009usize, + start_col: 22usize, + end_line: 2009usize, + end_col: 87usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_order_by_using_gt_rejects()), + ), + }; + fn matrix_int4_ord_ore_order_by_using_gt_rejects() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_order_by_using_gt_rejects( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let fixture_table = ::fixture_table_name(); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0} ORDER BY payload::{1} USING {2}", + fixture_table, + &spec.sql_domain, + ">", + ), + ) + }); + let err = sqlx::query_scalar::<_, i32>(&sql) + .fetch_all(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} SQL={2} must reject ORDER BY USING (no opclass on domain by design) but succeeded", + &spec.sql_domain, + ">", + sql, + ), + ) + }), + ); + ::eql_tests::assert_db_error(&err, "42809", None); + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_order_by_using_gt_rejects", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_order_by_using_gt_rejects; + ::sqlx::testing::TestFn::run_test(f, args) + } + extern crate test; + #[rustc_test_marker = "scalars::int4::matrix_int4_ord_ore_order_by_using_gte_rejects"] + #[doc(hidden)] + pub const matrix_int4_ord_ore_order_by_using_gte_rejects: test::TestDescAndFn = test::TestDescAndFn { + desc: test::TestDesc { + name: test::StaticTestName( + "scalars::int4::matrix_int4_ord_ore_order_by_using_gte_rejects", + ), + ignore: false, + ignore_message: ::core::option::Option::None, + source_file: "tests/sqlx/src/matrix.rs", + start_line: 2009usize, + start_col: 22usize, + end_line: 2009usize, + end_col: 87usize, + compile_fail: false, + no_run: false, + should_panic: test::ShouldPanic::No, + test_type: test::TestType::IntegrationTest, + }, + testfn: test::StaticTestFn( + #[coverage(off)] + || test::assert_test_result(matrix_int4_ord_ore_order_by_using_gte_rejects()), + ), + }; + fn matrix_int4_ord_ore_order_by_using_gte_rejects() -> anyhow::Result<()> { + async fn matrix_int4_ord_ore_order_by_using_gte_rejects( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + { + let spec = ::eql_tests::scalar_domains::ScalarDomainSpec::new::< + i32, + >(::eql_tests::scalar_domains::Variant::OrdOre); + let fixture_table = ::fixture_table_name(); + let sql = ::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "SELECT plaintext FROM {0} ORDER BY payload::{1} USING {2}", + fixture_table, + &spec.sql_domain, + ">=", + ), + ) + }); + let err = sqlx::query_scalar::<_, i32>(&sql) + .fetch_all(&pool) + .await + .expect_err( + &::alloc::__export::must_use({ + ::alloc::fmt::format( + format_args!( + "domain={0} op={1} SQL={2} must reject ORDER BY USING (no opclass on domain by design) but succeeded", + &spec.sql_domain, + ">=", + sql, + ), + ) + }), + ); + ::eql_tests::assert_db_error(&err, "42809", None); + Ok(()) + } + } + let mut args = ::sqlx::testing::TestArgs::new( + "encrypted_domain::scalars::int4::matrix_int4_ord_ore_order_by_using_gte_rejects", + ); + args.migrator( + &::sqlx::migrate::Migrator { + migrations: ::std::borrow::Cow::Borrowed( + &[ + ::sqlx::migrate::Migration { + version: 1i64, + description: ::std::borrow::Cow::Borrowed("placeholder"), + migration_type: ::sqlx::migrate::MigrationType::Simple, + sql: ::std::borrow::Cow::Borrowed(""), + no_tx: false, + checksum: ::std::borrow::Cow::Borrowed( + &[ + 56u8, 176u8, 96u8, 167u8, 81u8, 172u8, 150u8, 56u8, 76u8, + 217u8, 50u8, 126u8, 177u8, 177u8, 227u8, 106u8, 33u8, 253u8, + 183u8, 17u8, 20u8, 190u8, 7u8, 67u8, 76u8, 12u8, 199u8, + 191u8, 99u8, 246u8, 225u8, 218u8, 39u8, 78u8, 222u8, 191u8, + 231u8, 111u8, 101u8, 251u8, 213u8, 26u8, 210u8, 241u8, 72u8, + 152u8, 185u8, 91u8, + ], + ), + }, + ], + ), + ..::sqlx::migrate::Migrator::DEFAULT + }, + ); + args.fixtures( + &[ + ::sqlx::testing::TestFixture { + path: "../../../fixtures/eql_v2_int4.sql", + contents: "", + }, + ], + ); + let f: fn(_) -> _ = matrix_int4_ord_ore_order_by_using_gte_rejects; + ::sqlx::testing::TestFn::run_test(f, args) + } +} diff --git a/tests/sqlx/snapshots/matrix_tests.txt b/tests/sqlx/snapshots/matrix_tests.txt new file mode 100644 index 00000000..2cdfc22b --- /dev/null +++ b/tests/sqlx/snapshots/matrix_tests.txt @@ -0,0 +1,211 @@ +scalars::::matrix__eq_aggregate_typecheck_max +scalars::::matrix__eq_aggregate_typecheck_min +scalars::::matrix__eq_contained_by_blocker +scalars::::matrix__eq_contains_blocker +scalars::::matrix__eq_count_distinct_extractor +scalars::::matrix__eq_count_path_cast +scalars::::matrix__eq_count_typed_column +scalars::::matrix__eq_eq_pivot_max_correctness +scalars::::matrix__eq_eq_pivot_max_cross_shape +scalars::::matrix__eq_eq_pivot_min_correctness +scalars::::matrix__eq_eq_pivot_min_cross_shape +scalars::::matrix__eq_eq_pivot_zero_correctness +scalars::::matrix__eq_eq_pivot_zero_cross_shape +scalars::::matrix__eq_eq_supported_null +scalars::::matrix__eq_gt_blocker +scalars::::matrix__eq_gte_blocker +scalars::::matrix__eq_index_engages_btree +scalars::::matrix__eq_index_engages_hash +scalars::::matrix__eq_lt_blocker +scalars::::matrix__eq_lte_blocker +scalars::::matrix__eq_native_absent_ops +scalars::::matrix__eq_neq_pivot_max_correctness +scalars::::matrix__eq_neq_pivot_max_cross_shape +scalars::::matrix__eq_neq_pivot_min_correctness +scalars::::matrix__eq_neq_pivot_min_cross_shape +scalars::::matrix__eq_neq_pivot_zero_correctness +scalars::::matrix__eq_neq_pivot_zero_cross_shape +scalars::::matrix__eq_neq_supported_null +scalars::::matrix__eq_path_op_blockers +scalars::::matrix__eq_payload_check +scalars::::matrix__eq_planner_metadata_eq +scalars::::matrix__eq_sanity +scalars::::matrix__eq_typed_column_blocker +scalars::::matrix__fixture_shape +scalars::::matrix__ord_aggregate_group_by_max +scalars::::matrix__ord_aggregate_group_by_min +scalars::::matrix__ord_aggregate_max +scalars::::matrix__ord_aggregate_max_all_null +scalars::::matrix__ord_aggregate_max_empty +scalars::::matrix__ord_aggregate_max_mixed_null +scalars::::matrix__ord_aggregate_min +scalars::::matrix__ord_aggregate_min_all_null +scalars::::matrix__ord_aggregate_min_empty +scalars::::matrix__ord_aggregate_min_mixed_null +scalars::::matrix__ord_aggregate_parallel_safe +scalars::::matrix__ord_contained_by_blocker +scalars::::matrix__ord_contains_blocker +scalars::::matrix__ord_count_distinct_extractor +scalars::::matrix__ord_count_path_cast +scalars::::matrix__ord_count_typed_column +scalars::::matrix__ord_eq_pivot_max_correctness +scalars::::matrix__ord_eq_pivot_max_cross_shape +scalars::::matrix__ord_eq_pivot_min_correctness +scalars::::matrix__ord_eq_pivot_min_cross_shape +scalars::::matrix__ord_eq_pivot_zero_correctness +scalars::::matrix__ord_eq_pivot_zero_cross_shape +scalars::::matrix__ord_eq_supported_null +scalars::::matrix__ord_gt_pivot_max_correctness +scalars::::matrix__ord_gt_pivot_max_cross_shape +scalars::::matrix__ord_gt_pivot_min_correctness +scalars::::matrix__ord_gt_pivot_min_cross_shape +scalars::::matrix__ord_gt_pivot_zero_correctness +scalars::::matrix__ord_gt_pivot_zero_cross_shape +scalars::::matrix__ord_gt_supported_null +scalars::::matrix__ord_gte_pivot_max_correctness +scalars::::matrix__ord_gte_pivot_max_cross_shape +scalars::::matrix__ord_gte_pivot_min_correctness +scalars::::matrix__ord_gte_pivot_min_cross_shape +scalars::::matrix__ord_gte_pivot_zero_correctness +scalars::::matrix__ord_gte_pivot_zero_cross_shape +scalars::::matrix__ord_gte_supported_null +scalars::::matrix__ord_index_engages_btree +scalars::::matrix__ord_lt_pivot_max_correctness +scalars::::matrix__ord_lt_pivot_max_cross_shape +scalars::::matrix__ord_lt_pivot_min_correctness +scalars::::matrix__ord_lt_pivot_min_cross_shape +scalars::::matrix__ord_lt_pivot_zero_correctness +scalars::::matrix__ord_lt_pivot_zero_cross_shape +scalars::::matrix__ord_lt_supported_null +scalars::::matrix__ord_lte_pivot_max_correctness +scalars::::matrix__ord_lte_pivot_max_cross_shape +scalars::::matrix__ord_lte_pivot_min_correctness +scalars::::matrix__ord_lte_pivot_min_cross_shape +scalars::::matrix__ord_lte_pivot_zero_correctness +scalars::::matrix__ord_lte_pivot_zero_cross_shape +scalars::::matrix__ord_lte_supported_null +scalars::::matrix__ord_native_absent_ops +scalars::::matrix__ord_neq_pivot_max_correctness +scalars::::matrix__ord_neq_pivot_max_cross_shape +scalars::::matrix__ord_neq_pivot_min_correctness +scalars::::matrix__ord_neq_pivot_min_cross_shape +scalars::::matrix__ord_neq_pivot_zero_correctness +scalars::::matrix__ord_neq_pivot_zero_cross_shape +scalars::::matrix__ord_neq_supported_null +scalars::::matrix__ord_ord_routes_through_ob +scalars::::matrix__ord_order_by_asc_no_where +scalars::::matrix__ord_order_by_asc_nulls_first +scalars::::matrix__ord_order_by_asc_nulls_last +scalars::::matrix__ord_order_by_asc_with_where +scalars::::matrix__ord_order_by_desc_no_where +scalars::::matrix__ord_order_by_desc_nulls_first +scalars::::matrix__ord_order_by_desc_nulls_last +scalars::::matrix__ord_order_by_desc_with_where +scalars::::matrix__ord_order_by_using_gt_rejects +scalars::::matrix__ord_order_by_using_gte_rejects +scalars::::matrix__ord_order_by_using_lt_rejects +scalars::::matrix__ord_order_by_using_lte_rejects +scalars::::matrix__ord_ore_aggregate_group_by_max +scalars::::matrix__ord_ore_aggregate_group_by_min +scalars::::matrix__ord_ore_aggregate_max +scalars::::matrix__ord_ore_aggregate_max_all_null +scalars::::matrix__ord_ore_aggregate_max_empty +scalars::::matrix__ord_ore_aggregate_max_mixed_null +scalars::::matrix__ord_ore_aggregate_min +scalars::::matrix__ord_ore_aggregate_min_all_null +scalars::::matrix__ord_ore_aggregate_min_empty +scalars::::matrix__ord_ore_aggregate_min_mixed_null +scalars::::matrix__ord_ore_aggregate_parallel_safe +scalars::::matrix__ord_ore_contained_by_blocker +scalars::::matrix__ord_ore_contains_blocker +scalars::::matrix__ord_ore_count_distinct_extractor +scalars::::matrix__ord_ore_count_path_cast +scalars::::matrix__ord_ore_count_typed_column +scalars::::matrix__ord_ore_eq_pivot_max_correctness +scalars::::matrix__ord_ore_eq_pivot_max_cross_shape +scalars::::matrix__ord_ore_eq_pivot_min_correctness +scalars::::matrix__ord_ore_eq_pivot_min_cross_shape +scalars::::matrix__ord_ore_eq_pivot_zero_correctness +scalars::::matrix__ord_ore_eq_pivot_zero_cross_shape +scalars::::matrix__ord_ore_eq_supported_null +scalars::::matrix__ord_ore_gt_pivot_max_correctness +scalars::::matrix__ord_ore_gt_pivot_max_cross_shape +scalars::::matrix__ord_ore_gt_pivot_min_correctness +scalars::::matrix__ord_ore_gt_pivot_min_cross_shape +scalars::::matrix__ord_ore_gt_pivot_zero_correctness +scalars::::matrix__ord_ore_gt_pivot_zero_cross_shape +scalars::::matrix__ord_ore_gt_supported_null +scalars::::matrix__ord_ore_gte_pivot_max_correctness +scalars::::matrix__ord_ore_gte_pivot_max_cross_shape +scalars::::matrix__ord_ore_gte_pivot_min_correctness +scalars::::matrix__ord_ore_gte_pivot_min_cross_shape +scalars::::matrix__ord_ore_gte_pivot_zero_correctness +scalars::::matrix__ord_ore_gte_pivot_zero_cross_shape +scalars::::matrix__ord_ore_gte_supported_null +scalars::::matrix__ord_ore_index_engages_btree +scalars::::matrix__ord_ore_lt_pivot_max_correctness +scalars::::matrix__ord_ore_lt_pivot_max_cross_shape +scalars::::matrix__ord_ore_lt_pivot_min_correctness +scalars::::matrix__ord_ore_lt_pivot_min_cross_shape +scalars::::matrix__ord_ore_lt_pivot_zero_correctness +scalars::::matrix__ord_ore_lt_pivot_zero_cross_shape +scalars::::matrix__ord_ore_lt_supported_null +scalars::::matrix__ord_ore_lte_pivot_max_correctness +scalars::::matrix__ord_ore_lte_pivot_max_cross_shape +scalars::::matrix__ord_ore_lte_pivot_min_correctness +scalars::::matrix__ord_ore_lte_pivot_min_cross_shape +scalars::::matrix__ord_ore_lte_pivot_zero_correctness +scalars::::matrix__ord_ore_lte_pivot_zero_cross_shape +scalars::::matrix__ord_ore_lte_supported_null +scalars::::matrix__ord_ore_native_absent_ops +scalars::::matrix__ord_ore_neq_pivot_max_correctness +scalars::::matrix__ord_ore_neq_pivot_max_cross_shape +scalars::::matrix__ord_ore_neq_pivot_min_correctness +scalars::::matrix__ord_ore_neq_pivot_min_cross_shape +scalars::::matrix__ord_ore_neq_pivot_zero_correctness +scalars::::matrix__ord_ore_neq_pivot_zero_cross_shape +scalars::::matrix__ord_ore_neq_supported_null +scalars::::matrix__ord_ore_ord_routes_through_ob +scalars::::matrix__ord_ore_order_by_asc_no_where +scalars::::matrix__ord_ore_order_by_asc_nulls_first +scalars::::matrix__ord_ore_order_by_asc_nulls_last +scalars::::matrix__ord_ore_order_by_asc_with_where +scalars::::matrix__ord_ore_order_by_desc_no_where +scalars::::matrix__ord_ore_order_by_desc_nulls_first +scalars::::matrix__ord_ore_order_by_desc_nulls_last +scalars::::matrix__ord_ore_order_by_desc_with_where +scalars::::matrix__ord_ore_order_by_using_gt_rejects +scalars::::matrix__ord_ore_order_by_using_gte_rejects +scalars::::matrix__ord_ore_order_by_using_lt_rejects +scalars::::matrix__ord_ore_order_by_using_lte_rejects +scalars::::matrix__ord_ore_ore_injectivity +scalars::::matrix__ord_ore_path_op_blockers +scalars::::matrix__ord_ore_payload_check +scalars::::matrix__ord_ore_planner_metadata_eq +scalars::::matrix__ord_ore_planner_metadata_ord +scalars::::matrix__ord_ore_sanity +scalars::::matrix__ord_ore_typed_column_blocker +scalars::::matrix__ord_path_op_blockers +scalars::::matrix__ord_payload_check +scalars::::matrix__ord_planner_metadata_eq +scalars::::matrix__ord_planner_metadata_ord +scalars::::matrix__ord_sanity +scalars::::matrix__ord_scale_preference_default_btree +scalars::::matrix__ord_typed_column_blocker +scalars::::matrix__storage_aggregate_typecheck_max +scalars::::matrix__storage_aggregate_typecheck_min +scalars::::matrix__storage_contained_by_blocker +scalars::::matrix__storage_contains_blocker +scalars::::matrix__storage_count_path_cast +scalars::::matrix__storage_count_typed_column +scalars::::matrix__storage_eq_blocker +scalars::::matrix__storage_gt_blocker +scalars::::matrix__storage_gte_blocker +scalars::::matrix__storage_lt_blocker +scalars::::matrix__storage_lte_blocker +scalars::::matrix__storage_native_absent_ops +scalars::::matrix__storage_neq_blocker +scalars::::matrix__storage_path_op_blockers +scalars::::matrix__storage_payload_check +scalars::::matrix__storage_sanity +scalars::::matrix__storage_typed_column_blocker diff --git a/tests/sqlx/src/assertions.rs b/tests/sqlx/src/assertions.rs index 2fa7d4b6..538db6a1 100644 --- a/tests/sqlx/src/assertions.rs +++ b/tests/sqlx/src/assertions.rs @@ -148,3 +148,51 @@ impl<'a> QueryAssertion<'a> { ); } } + +/// Assert a `sqlx::Error` is a database error with the given SQLSTATE, +/// optionally with the given constraint name. Includes the actual error +/// in the panic message so a failing test prints *why* it failed, not +/// just *that* it failed — `assert!(result.is_err(), "…")` swallows the +/// underlying error so a constraint engagement against the wrong +/// constraint or SQLSTATE passes silently. +/// +/// # SQLSTATEs commonly seen on encrypted columns +/// - `23505` — unique_violation +/// - `23502` — not_null_violation +/// - `23514` — check_violation +/// - `23503` — foreign_key_violation +/// - `P0001` — raise_exception (PL/pgSQL `RAISE EXCEPTION`) +/// - `42704` — undefined_object (no operator class found, etc.) +/// +/// # Example +/// ```ignore +/// let result = sqlx::query(...).execute(&pool).await.unwrap_err(); +/// assert_db_error(&result, "23514", Some("encrypted_check_c_constrained")); +/// ``` +pub fn assert_db_error( + err: &sqlx::Error, + expected_sqlstate: &str, + expected_constraint: Option<&str>, +) { + let db_err = err + .as_database_error() + .unwrap_or_else(|| panic!("expected database error, got: {err:?}")); + + let code = db_err.code(); + assert_eq!( + code.as_deref(), + Some(expected_sqlstate), + "expected SQLSTATE {expected_sqlstate}, got {code:?} (message: {})", + db_err.message(), + ); + + if let Some(expected) = expected_constraint { + let constraint = db_err.constraint(); + assert_eq!( + constraint, + Some(expected), + "expected constraint name {expected:?}, got {constraint:?} (message: {})", + db_err.message(), + ); + } +} diff --git a/tests/sqlx/src/fixtures/cipherstash.rs b/tests/sqlx/src/fixtures/cipherstash.rs new file mode 100644 index 00000000..22e552fa --- /dev/null +++ b/tests/sqlx/src/fixtures/cipherstash.rs @@ -0,0 +1,392 @@ +//! Direct `cipherstash-client` integration — the encryption oracle for the +//! SQLx fixture generator. +//! +//! Earlier revisions of the generator started a CipherStash Proxy container, +//! wrote `add_search_config` rows so Proxy knew which columns to encrypt, +//! restarted the container so it reloaded that config, then INSERTed +//! plaintexts through a Proxy-mediated Postgres connection. That whole loop +//! existed only because the Proxy was the encryption oracle. +//! +//! `cipherstash-client` 0.35 exposes the same surface natively. This module +//! owns the bootstrap — `build_cipher()` builds a `ScopedCipher` — +//! and the batched helper `encrypt_store()` that wraps `eql::encrypt_eql` and +//! returns the resulting EQL ciphertexts as `serde_json::Value`s ready to bind +//! into a `jsonb` column. A fixture-generator process makes exactly one +//! `encrypt_store` call, so the cipher is built once per process by +//! construction — no static cache, no cross-runtime hazard. +//! +//! `column_config_for` is the bridge between the fixture spec's string-typed +//! index names (`"unique"`, `"ore"`, …) and the typed `IndexType` enum +//! cipherstash-config uses. Unknown names raise immediately so a typo at +//! spec construction fails fast. + +use std::borrow::Cow; +use std::sync::Arc; + +use anyhow::{anyhow, Context, Result}; +use cipherstash_client::encryption::ScopedCipher; +use cipherstash_client::eql::{ + encrypt_eql, EqlCiphertext, EqlEncryptOpts, EqlOperation, EqlOutput, Identifier, + PreparedPlaintext, +}; +use cipherstash_client::schema::column::{Index, IndexType}; +use cipherstash_client::schema::{ColumnConfig, ColumnType}; +use cipherstash_client::zerokms::{EnvKeyProvider, ZeroKMSBuilder}; +use cipherstash_client::AutoStrategy; + +use super::eql_plaintext::{Cast, EqlPlaintext}; +use super::index_kind::IndexKind; + +/// Build a fresh `ScopedCipher`. Performs `AutoStrategy::detect()`, the +/// ZeroKMS handshake, and the keyset load on every call — fine because +/// every fixture-generator process calls this exactly once via the +/// single batched `encrypt_store`. +async fn build_cipher() -> Result>> { + let zerokms = ZeroKMSBuilder::auto()? + .with_key_provider(EnvKeyProvider) + .build() + .await?; + + let cipher = ScopedCipher::init_default(Arc::new(zerokms)).await?; + + Ok(Arc::new(cipher)) +} + +/// Build a `ColumnConfig` from the fixture spec's index list + cast. +/// +/// `IndexKind` is a typed enum — every value is a real EQL index by +/// construction, so the mapping is total and `column_config_for` cannot +/// fail on an unknown index name. Extending fixture coverage to a new +/// index is one variant on `IndexKind` plus one arm here, both compile- +/// time checked. +/// The single encrypted-payload column name. Single-sourced here so the +/// `ColumnConfig` built for encryption and the `INSERT` target column in the +/// driver cannot drift apart. +pub const PAYLOAD_COLUMN: &str = "payload"; + +pub fn column_config_for(spec_indexes: &[IndexKind], cast: Cast) -> Result { + let column_type = cast_to_column_type(cast)?; + let mut config = ColumnConfig::build(PAYLOAD_COLUMN).casts_as(column_type); + + for ix in spec_indexes { + config = config.add_index(Index::new(index_type_for(*ix))); + } + + Ok(config) +} + +/// Map an `EqlPlaintext::Cast` onto cipherstash-config's `ColumnType`. The +/// `Cast` newtype's allowlist is structural, so the only failure mode is +/// "we extended `EqlPlaintext` with a new variant but forgot to extend +/// this mapping" — explicit error rather than a `_ => unreachable!()` +/// gives the maintainer a clear breadcrumb. +fn cast_to_column_type(cast: Cast) -> Result { + match cast.as_str() { + "int" => Ok(ColumnType::Int), + "small_int" => Ok(ColumnType::SmallInt), + "big_int" => Ok(ColumnType::BigInt), + "boolean" => Ok(ColumnType::Boolean), + "date" => Ok(ColumnType::Date), + "decimal" => Ok(ColumnType::Decimal), + "float" | "real" | "double" => Ok(ColumnType::Float), + "text" => Ok(ColumnType::Text), + "jsonb" | "json" => Ok(ColumnType::Json), + "timestamp" => Ok(ColumnType::Timestamp), + other => Err(anyhow!( + "no cipherstash-config ColumnType mapping for cast {other:?} — \ + extend cipherstash::cast_to_column_type when adding a new \ + EqlPlaintext variant" + )), + } +} + +/// Map an `IndexKind` variant onto cipherstash-config's `IndexType`. +/// Reuses the canonical constructors on `Index` (`Index::new_unique`, +/// etc.) so the defaults stay in sync with whatever cipherstash-config +/// considers the canonical shape for each index. Total — every variant +/// has an arm; adding a new variant is a compile error here, which is +/// the point. +fn index_type_for(kind: IndexKind) -> IndexType { + match kind { + IndexKind::Unique => Index::new_unique().index_type, + IndexKind::Ore => IndexType::Ore, + IndexKind::Match => Index::new_match().index_type, + } +} + +/// Encrypt a batch of plaintext values for storage and return one EQL +/// ciphertext per input as a `serde_json::Value` ready to bind into a +/// `jsonb` column. +/// +/// One `encrypt_eql` call regardless of `values.len()` — ZeroKMS does the +/// round trip once, not N times. The per-value field in each +/// `PreparedPlaintext` is `value.to_plaintext()`; the config, identifier, +/// and `EqlOperation::Store` are shared across the batch. +/// +/// Uses `EqlOperation::Store`, which yields a full storage payload +/// (`{"k": "ct", "v": 2, "i": …, "c": …, "hm": …, "ob": …}`) — the same +/// shape Proxy produced for the working table. `EqlEncryptOpts::default()` +/// uses the cipher's default keyset, no lock context, no service token, no +/// index filter — the same defaults Proxy uses for column-config-driven +/// inserts. +/// +/// An empty `values` slice short-circuits before `build_cipher()` so a +/// caller with nothing to encrypt does not pay the ZeroKMS bootstrap +/// cost. +pub async fn encrypt_store( + table: &str, + column: &str, + values: &[T], + config: &ColumnConfig, +) -> Result> { + if values.is_empty() { + return Ok(Vec::new()); + } + + let cipher = build_cipher().await?; + + // `Identifier::new` does two `String` allocations per call — cheap + // enough that constructing per-iteration is preferred over assuming + // the upstream type implements `Clone`. + let prepared: Vec = values + .iter() + .map(|value| { + PreparedPlaintext::new( + Cow::Borrowed(config), + Identifier::new(table, column), + value.to_plaintext(), + EqlOperation::Store, + ) + }) + .collect(); + + let opts = EqlEncryptOpts::default(); + let outputs = encrypt_eql(cipher, prepared, &opts) + .await + .with_context(|| { + format!( + "encrypting batch of {} values for {table}.{column}", + values.len() + ) + })?; + + if outputs.len() != values.len() { + return Err(anyhow!( + "encrypt_eql returned {} outputs for {} inputs", + outputs.len(), + values.len() + )); + } + + outputs + .into_iter() + .map(|output| { + let ciphertext: EqlCiphertext = match output { + EqlOutput::Store(ct) => ct, + EqlOutput::Query(_) => { + // EqlOperation::Store always yields EqlOutput::Store; + // treating the other arm as unreachable would hide a + // future API drift. + return Err(anyhow!( + "encrypt_eql returned a Query output for an EqlOperation::Store input" + )); + } + }; + serde_json::to_value(&ciphertext).context("serialising EqlCiphertext to JSON") + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn column_config_for_int_with_unique_and_ore_builds_a_two_index_config() { + let indexes = [IndexKind::Unique, IndexKind::Ore]; + let config = column_config_for(&indexes, Cast::INT).unwrap(); + + assert_eq!(config.name, "payload"); + assert!(matches!(config.cast_type, ColumnType::Int)); + assert_eq!(config.indexes.len(), 2); + assert!(config.indexes.iter().any(|i| i.is_unique())); + assert!(config.indexes.iter().any(|i| i.is_ore())); + } + + // Note: the "unknown index name rejected at runtime" test is gone — + // `IndexKind` is a closed enum, so a typo is a compile error. + + #[test] + fn index_type_for_maps_every_variant_to_its_canonical_index_type() { + // Each `IndexKind` variant round-trips into the `IndexType` + // cipherstash-config considers canonical for that name. Compared + // via the public `Index` surface (`is_unique`, `is_ore`, + // `is_match`) so the assertion does not depend on the shape of + // the non-exhaustive `IndexType` enum. + let unique = Index::new(index_type_for(IndexKind::Unique)); + assert!(unique.is_unique(), "Unique must map to the unique index"); + + let ore = Index::new(index_type_for(IndexKind::Ore)); + assert!(ore.is_ore(), "Ore must map to the ORE index"); + + let m = Index::new(index_type_for(IndexKind::Match)); + assert!(m.is_match(), "Match must map to the match (bloom) index"); + } + + #[tokio::test] + async fn encrypt_store_with_empty_values_returns_an_empty_vec_without_building_cipher() { + // Empty input short-circuits before `build_cipher()` so a caller + // with nothing to encrypt does not pay the ZeroKMS bootstrap cost. + // Running this test under `cargo test` (no `fixture-gen` feature, + // no CS_* env vars) proves the short-circuit: if `build_cipher()` + // were reached, the missing credentials would surface as an error. + let config = column_config_for(&[IndexKind::Unique], Cast::INT).unwrap(); + let out = encrypt_store::("t", "c", &[], &config).await.unwrap(); + assert!(out.is_empty(), "empty input must yield empty output"); + } + + #[test] + fn cast_to_column_type_covers_every_eql_plaintext_cast_constant() { + // Every Cast constant on EqlPlaintext must round-trip into a + // ColumnType — otherwise a freshly-added EqlPlaintext variant + // would crash the generator at run time instead of failing the + // build. Listed explicitly so a new `pub const` on Cast forces an + // update here. + for cast in [ + Cast::TEXT, + Cast::INT, + Cast::SMALL_INT, + Cast::BIG_INT, + Cast::REAL, + Cast::DOUBLE, + Cast::BOOLEAN, + Cast::DATE, + Cast::JSONB, + Cast::JSON, + Cast::FLOAT, + Cast::DECIMAL, + Cast::TIMESTAMP, + ] { + cast_to_column_type(cast).unwrap_or_else(|e| { + panic!("Cast::{} has no ColumnType mapping: {e}", cast.as_str()) + }); + } + } +} + +/// Live `encrypt_store` round-trips against a real ZeroKMS keyset. Gated +/// by `fixture-gen` so default `cargo test` runs do not require +/// `CS_CLIENT_ACCESS_KEY` / `CS_WORKSPACE_CRN`. Each test is +/// `#[ignore]` so it only runs under +/// `cargo test --features fixture-gen -- --ignored`, mirroring the +/// `generate` test in `eql_v2_int4.rs`. +/// +/// These complement the structural fixture-tests in +/// the `__scalar_matrix_fixture_shape!` arm in `tests/sqlx/src/matrix.rs`: those assert over the +/// regenerated SQL file end-to-end; these isolate the +/// `encrypt_store` call so an SDK API drift surfaces here before the +/// whole fixture pipeline fails. +#[cfg(all(test, feature = "fixture-gen"))] +mod live_tests { + use super::*; + use serde_json::Value; + + /// Config used by every live test — `Unique` drives the `hm` term, + /// `Ore` drives the `ob` term, so the returned payloads carry both. + fn int_config_with_hm_and_ob() -> ColumnConfig { + column_config_for(&[IndexKind::Unique, IndexKind::Ore], Cast::INT).unwrap() + } + + /// Assert the well-formed Store shape: the payload is a JSON object + /// with non-null `v`, `c`, `hm`, `ob`, and `i` fields. Mirrors the + /// per-key assertions in the generated `scalars::int4` matrix suite + /// (emitted from the `scalar_types!` list in `scalar_types.rs`). + fn assert_store_shape(payload: &Value) { + let obj = payload.as_object().expect("payload must be a JSON object"); + for key in ["v", "c", "hm", "ob", "i"] { + assert!( + obj.get(key).is_some_and(|v| !v.is_null()), + "payload must carry a non-null `{key}` field; got {payload}" + ); + } + // `v` is the EQL payload-format version. The cipherstash-client + // JSON encodes it as the integer 2; the existing fixture tests + // check `payload->>'v' = '2'` via Postgres's text-cast operator. + // Asserting the number here matches the source format directly. + assert_eq!( + obj.get("v").and_then(Value::as_i64), + Some(2), + "payload must declare v = 2; got {payload}" + ); + } + + #[tokio::test] + #[ignore = "live ZeroKMS — run via `cargo test --features fixture-gen -- --ignored`"] + async fn encrypt_store_single_value_returns_one_eql_payload() { + let config = int_config_with_hm_and_ob(); + let out = encrypt_store("live_one", "payload", &[42_i32], &config) + .await + .expect("encrypt_store should succeed against live ZeroKMS"); + assert_eq!(out.len(), 1, "single input should produce single output"); + assert_store_shape(&out[0]); + } + + #[tokio::test] + #[ignore = "live ZeroKMS — run via `cargo test --features fixture-gen -- --ignored`"] + async fn encrypt_store_batch_returns_one_payload_per_input_in_input_order() { + let config = int_config_with_hm_and_ob(); + let values = [-1_i32, 1, 42]; + let out = encrypt_store("live_batch", "payload", &values, &config) + .await + .expect("encrypt_store should succeed against live ZeroKMS"); + assert_eq!( + out.len(), + values.len(), + "batch length must equal input length" + ); + for (i, payload) in out.iter().enumerate() { + assert_store_shape(payload); + // Each payload's `i.t` should match the table identifier we + // supplied — that's the field consuming code uses to bind a + // payload to its source column. + let identifier_t = payload + .get("i") + .and_then(Value::as_object) + .and_then(|o| o.get("t")) + .and_then(Value::as_str); + assert_eq!( + identifier_t, + Some("live_batch"), + "payload[{i}].i.t must match the table argument; got {payload}" + ); + } + } + + #[tokio::test] + #[ignore = "live ZeroKMS — run via `cargo test --features fixture-gen -- --ignored`"] + async fn encrypt_store_batch_distinct_plaintexts_yield_distinct_hm() { + // HMAC is the equality term — three distinct plaintexts must + // yield three distinct `hm` strings. Mirrors + // `hmac_equality_terms_are_distinct_for_distinct_values` in the + // fixture-tests but at the unit-test layer. + let config = int_config_with_hm_and_ob(); + let out = encrypt_store("live_distinct", "payload", &[-1_i32, 1, 42], &config) + .await + .expect("encrypt_store should succeed against live ZeroKMS"); + + let hms: Vec<&str> = out + .iter() + .map(|p| { + p.get("hm") + .and_then(Value::as_str) + .expect("payload must carry a string `hm` term") + }) + .collect(); + let unique: std::collections::HashSet<&&str> = hms.iter().collect(); + assert_eq!( + unique.len(), + hms.len(), + "distinct plaintexts must yield distinct hm terms; got {hms:?}" + ); + } +} diff --git a/tests/sqlx/src/fixtures/driver.rs b/tests/sqlx/src/fixtures/driver.rs new file mode 100644 index 00000000..127e20a1 --- /dev/null +++ b/tests/sqlx/src/fixtures/driver.rs @@ -0,0 +1,415 @@ +//! `FixtureSpec::run()` — the generation driver. +//! +//! mise owns the containers; this owns the data. The driver opens a direct +//! Postgres connection and encrypts each plaintext value via +//! `cipherstash-client` (see the sibling `cipherstash` module) before +//! inserting the result into a transient working table. Errors are `anyhow` +//! with `.context(...)` — a generator is a developer tool; a clear crash +//! beats a partial fixture. +//! +//! The `public._fixture_` working table is transient plumbing: `.run()` +//! creates it, encrypts into it, renders the committed rows from it, then +//! drops it before returning. The drop runs unconditionally once the table +//! exists — on success *and* on any returned error: `run` captures the +//! post-schema result, drops the table, and only then propagates a failure. +//! So the table never outlives a *returned* run; only a hard crash (panic / +//! `kill`) can leak it, and the next run's start-of-schema +//! `DROP TABLE IF EXISTS` reclaims that case. + +use std::path::PathBuf; + +use anyhow::{Context, Result}; +use sqlx::postgres::PgConnectOptions; +use sqlx::{ConnectOptions, Connection, PgConnection, Row}; + +use super::cipherstash; +use super::eql_plaintext::EqlPlaintext; +use super::spec::FixtureSpec; + +/// Bag of Rust-type bounds required of a fixture's plaintext value `T`. +/// Collapses the long `where` clause on `impl FixtureSpec<'a, T>` to a single +/// alias; the blanket impl below makes it auto-applied to any `T` that +/// already satisfies the bounds. +pub trait FixtureValue: + EqlPlaintext + + Copy + + Send + + Sync + + for<'q> sqlx::Encode<'q, sqlx::Postgres> + + sqlx::Type +{ +} + +impl FixtureValue for T where + T: EqlPlaintext + + Copy + + Send + + Sync + + for<'q> sqlx::Encode<'q, sqlx::Postgres> + + sqlx::Type +{ +} + +/// Driver connection options, parsed once from the environment at the start +/// of `run`. Only the unmediated Postgres connection is needed: DDL, +/// inserts, and the render step all run against it. Encryption happens in +/// Rust (cipherstash-client), so there is no second connection. +struct DriverConfig { + direct: PgConnectOptions, +} + +impl DriverConfig { + /// Build connection options from env vars, defaulting to the + /// `mise.toml` `[env]` values. Port parses are strict — a malformed + /// `POSTGRES_PORT` surfaces as an `anyhow::Error` with the offending + /// value, matching the rest of the driver's error story. + fn from_env() -> Result { + let host = env_or("POSTGRES_HOST", "localhost"); + let user = env_or("POSTGRES_USER", "cipherstash"); + let password = env_or("POSTGRES_PASSWORD", "password"); + let database = env_or("POSTGRES_DB", "cipherstash"); + let port = parse_port_env("POSTGRES_PORT", 7432)?; + + let direct = PgConnectOptions::new() + .host(&host) + .port(port) + .username(&user) + .password(&password) + .database(&database); + + Ok(Self { direct }) + } +} + +fn env_or(key: &str, default: &str) -> String { + std::env::var(key).unwrap_or_else(|_| default.to_string()) +} + +fn parse_port_env(key: &str, default: u16) -> Result { + match std::env::var(key) { + Ok(value) => value + .parse::() + .with_context(|| format!("{key}={value:?} must be a valid u16")), + Err(_) => Ok(default), + } +} + +/// Absolute path to `tests/sqlx/fixtures/.sql`. Resolved from +/// `CARGO_MANIFEST_DIR` (the `tests/sqlx` crate root) so the path is correct +/// regardless of the process working directory. +fn fixture_script_path(filename: &str) -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("fixtures") + .join(filename) +} + +impl<'a, T> FixtureSpec<'a, T> +where + T: FixtureValue, +{ + /// Generate and write `tests/sqlx/fixtures/.sql`. + /// + /// The production entry point. Parses the env-driven `DriverConfig` + /// once, opens a single direct Postgres connection, runs the + /// schema/insert/render/drop pipeline inline against that connection + /// (no second connection needed — encryption happens in Rust via + /// cipherstash-client), then composes the rendered INSERT lines with + /// `fixture_script_preamble` and writes the committed script to disk. + /// + /// The pipeline mirrors the teardown contract in `run_with`: drop the + /// working table unconditionally once it has been created, and + /// propagate failures in causal order (insert error first). + pub async fn run(&self) -> Result<()> { + let config = DriverConfig::from_env()?; + + let mut direct = config + .direct + .clone() + .connect() + .await + .context("connecting to Postgres (direct)")?; + + self.check_complete().context("invalid FixtureSpec")?; + + sqlx::raw_sql(&self.working_schema_sql()) + .execute(&mut direct) + .await + .context("applying working-table schema")?; + + // Insert directly on the same connection used for schema/render/drop. + // The earlier two-connection design existed because `run_with` borrows + // `direct` mutably across the closure call; production has no such + // need — `insert_direct` is the only caller of cipherstash-client and + // can hold the same `&mut direct` for its duration. + let insert_result = self.insert_direct(&mut direct).await; + let render_result = if insert_result.is_ok() { + sqlx::query(&self.render_rows_sql()) + .fetch_all(&mut direct) + .await + .context("rendering fixture rows") + } else { + Ok(Vec::new()) + }; + + let working = self.working_table(); + let drop_result = sqlx::raw_sql(&format!("DROP TABLE IF EXISTS public.{working};")) + .execute(&mut direct) + .await; + + insert_result?; + let rows = render_result?; + drop_result.context("dropping the working table")?; + + let lines: Vec = rows + .iter() + .map(|r| r.try_get::(0).context("reading rendered INSERT")) + .collect::>()?; + + let _ = direct.close().await; + + let mut script = self.fixture_script_preamble(); + for line in &lines { + script.push_str(line); + script.push('\n'); + } + + let path = fixture_script_path(&self.script_filename()); + std::fs::write(&path, script) + .with_context(|| format!("writing fixture script {}", path.display()))?; + println!("wrote {} ({} rows)", path.display(), self.values().len()); + Ok(()) + } + + /// Encrypt every plaintext value via cipherstash-client in **one + /// batched call**, then INSERT each ciphertext into the working + /// table as plain JSONB. The committed `ColumnConfig` is built once + /// from the spec's indexes + cast — the fixture name is fed as the + /// table identifier so the resulting payload's `i.t` field matches + /// the working table, preserving the shape Proxy used to emit. + /// + /// Batching means one ZeroKMS round trip per fixture run regardless + /// of value count; the INSERT loop is per-row because the working + /// table is local Postgres and the per-row execute cost is in + /// microseconds. + async fn insert_direct(&self, direct: &mut PgConnection) -> Result<()> { + let config = cipherstash::column_config_for(self.indexes(), T::CAST) + .context("building ColumnConfig from FixtureSpec indexes")?; + + let working = self.working_table(); + let payloads = cipherstash::encrypt_store( + &working, + cipherstash::PAYLOAD_COLUMN, + self.values(), + &config, + ) + .await + .context("encrypting fixture values")?; + + let insert = format!( + "INSERT INTO public.{working} (id, plaintext, {col}) VALUES ($1, $2, $3)", + col = cipherstash::PAYLOAD_COLUMN + ); + for (i, (value, payload)) in self.values().iter().zip(payloads).enumerate() { + let id = (i as i64) + 1; + sqlx::query(&insert) + .bind(id) + .bind(*value) + .bind(sqlx::types::Json(payload)) + .execute(&mut *direct) + .await + .with_context(|| format!("inserting value #{id}"))?; + } + Ok(()) + } + + /// **Test seam** for the schema-apply / insert / render / teardown + /// pipeline. Production code uses `run()`, which inlines the same + /// pipeline on a single connection. This entry point exists so tests + /// can plug in arbitrary insert behavior (hand-crafted JSONB, + /// deliberate failures) without going through cipherstash-client. + /// Gated behind `#[cfg(test)]` so it is never linked into a + /// production build. + /// + /// Pipeline: + /// 1. Check the spec is complete. + /// 2. Apply `working_schema_sql` on `direct`. After this succeeds the + /// `public._fixture_` table exists and MUST be dropped before + /// return, whatever happens next. + /// 3. Run `insert_rows()`. Its result is captured (not + /// `?`-propagated) so the drop in step 5 always runs. + /// 4. If the inserter succeeded, render the committed rows via + /// `render_rows_sql` on `direct`. Skipped on inserter error. + /// 5. Drop the working table on `direct` unconditionally. + /// 6. Propagate failures in causal order: inserter error first + /// (root cause), then render, then drop. + /// + /// The closure has no `&mut PgConnection` parameter because the + /// caller (a test) closes over its own pool / connection — the + /// production path's single-connection invariant is enforced inside + /// `run`, not here. + /// + /// Private by design: this is a test seam, not a public API. + #[cfg(test)] + async fn run_with( + &self, + direct: &mut PgConnection, + insert_rows: F, + ) -> Result> + where + F: FnOnce() -> Fut + Send, + Fut: std::future::Future> + Send, + { + self.check_complete().context("invalid FixtureSpec")?; + + sqlx::raw_sql(&self.working_schema_sql()) + .execute(&mut *direct) + .await + .context("applying working-table schema")?; + + let insert_result = insert_rows().await; + let render_result = if insert_result.is_ok() { + sqlx::query(&self.render_rows_sql()) + .fetch_all(&mut *direct) + .await + .context("rendering fixture rows") + } else { + // Empty placeholder — never observed; `insert_result?` below short-circuits. + Ok(Vec::new()) + }; + + let working = self.working_table(); + let drop_result = sqlx::raw_sql(&format!("DROP TABLE IF EXISTS public.{working};")) + .execute(&mut *direct) + .await; + + insert_result?; + let rows = render_result?; + drop_result.context("dropping the working table")?; + + rows.iter() + .map(|r| r.try_get::(0).context("reading rendered INSERT")) + .collect() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sqlx::PgPool; + + /// A small int4 spec for driver tests. Three values keeps the test fast; + /// the driver's orchestration is independent of value count. + fn small_spec(name: &'static str) -> FixtureSpec<'static, i32> { + use super::super::index_kind::IndexKind; + const VALUES: &[i32] = &[-1, 1, 42]; + FixtureSpec::new(name) + .with_index(IndexKind::Unique) + .with_index(IndexKind::Ore) + .with_column_type("jsonb") + .with_values(VALUES) + } + + #[sqlx::test] + async fn run_with_renders_committed_rows_and_drops_working_table(pool: PgPool) -> Result<()> { + let spec = small_spec("driver_test_a"); + let working = spec.working_table(); + let working_for_closure = working.clone(); + let pool_for_closure = pool.clone(); + + let mut conn = pool.acquire().await?; + + // `run_with` is the test seam; it borrows `&mut conn` for the + // schema/render/drop steps, so a test that wants to insert via + // sqlx must close over its own connection — exactly the + // two-connection shape production (`run`) was rewritten to + // avoid. Tests pay this cost so production doesn't have to. + let lines = spec + .run_with(&mut conn, move || async move { + let mut c = pool_for_closure.acquire().await?; + let exists: Option = sqlx::query_scalar(&format!( + "SELECT to_regclass('public.{working_for_closure}')::text" + )) + .fetch_one(&mut *c) + .await?; + assert!( + exists.is_some(), + "working table should exist inside the closure" + ); + + for (i, value) in [-1i32, 1, 42].iter().enumerate() { + let id = (i as i64) + 1; + let insert = format!( + "INSERT INTO public.{working_for_closure} \ + (id, plaintext, payload) \ + VALUES ($1, $2, $3::jsonb)" + ); + sqlx::query(&insert) + .bind(id) + .bind(*value) + .bind( + r#"{"v":2,"c":"x","i":{"t":"_fixture_driver_test_a","c":"payload"},"hm":"x","ob":["1"]}"#, + ) + .execute(&mut *c) + .await?; + } + Ok(()) + }) + .await?; + + assert_eq!(lines.len(), 3, "one rendered INSERT per inserted row"); + for line in &lines { + assert!( + line.starts_with( + "INSERT INTO fixtures.driver_test_a (id, plaintext, payload) VALUES (" + ), + "rendered line should target the committed table: {line}" + ); + } + + let after: Option = + sqlx::query_scalar(&format!("SELECT to_regclass('public.{working}')::text")) + .fetch_one(&pool) + .await?; + assert!( + after.is_none(), + "working table should be dropped after run_with returns" + ); + + Ok(()) + } + + #[sqlx::test] + async fn run_with_drops_working_table_on_inserter_error(pool: PgPool) -> Result<()> { + let spec = small_spec("driver_test_b"); + let working = spec.working_table(); + + let mut conn = pool.acquire().await?; + + let result = spec + .run_with(&mut conn, || async { + anyhow::bail!("forced failure for test") + }) + .await; + + assert!( + result.is_err(), + "run_with should propagate the inserter error" + ); + let err_msg = format!("{:#}", result.unwrap_err()); + assert!( + err_msg.contains("forced failure for test"), + "error chain should contain the forced failure: {err_msg}" + ); + + let after: Option = + sqlx::query_scalar(&format!("SELECT to_regclass('public.{working}')::text")) + .fetch_one(&pool) + .await?; + assert!( + after.is_none(), + "working table should be dropped even on inserter error" + ); + + Ok(()) + } +} diff --git a/tests/sqlx/src/fixtures/eql_plaintext.rs b/tests/sqlx/src/fixtures/eql_plaintext.rs new file mode 100644 index 00000000..65c9f43e --- /dev/null +++ b/tests/sqlx/src/fixtures/eql_plaintext.rs @@ -0,0 +1,262 @@ +//! Maps a Rust plaintext type `T` to its EQL search-config cast and the SQL +//! type of the `plaintext` column. +//! +//! `Cast` and `PlaintextSqlType` are newtypes with private fields; the only +//! way to obtain one is via the predeclared constants on each type. That +//! makes the EQL allowlist structural — a `T::CAST` is, by construction, a +//! value EQL accepts. The trait is sealed so external crates cannot add +//! impls that bypass this guarantee. +//! +//! `to_plaintext` lifts the value into the cipherstash-client +//! `encryption::Plaintext` enum so the fixture generator can encrypt directly +//! via `eql::encrypt_eql` (no Proxy round trip). + +use std::fmt; + +use cipherstash_client::encryption::Plaintext; +use eql_scalars::ScalarKind; + +/// The `cast_as` argument for `eql_v2.add_search_config`. The field is +/// private so the allowlist is the set of `pub const`s below. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Cast(&'static str); + +impl Cast { + pub const TEXT: Cast = Cast("text"); + pub const INT: Cast = Cast("int"); + pub const SMALL_INT: Cast = Cast("small_int"); + pub const BIG_INT: Cast = Cast("big_int"); + pub const REAL: Cast = Cast("real"); + pub const DOUBLE: Cast = Cast("double"); + pub const BOOLEAN: Cast = Cast("boolean"); + pub const DATE: Cast = Cast("date"); + pub const JSONB: Cast = Cast("jsonb"); + pub const JSON: Cast = Cast("json"); + pub const FLOAT: Cast = Cast("float"); + pub const DECIMAL: Cast = Cast("decimal"); + pub const TIMESTAMP: Cast = Cast("timestamp"); + + pub fn as_str(&self) -> &'static str { + self.0 + } +} + +impl fmt::Display for Cast { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.0) + } +} + +/// The SQL type for the `plaintext` oracle column. As with `Cast`, the only +/// way to construct one is via the predeclared constants below. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct PlaintextSqlType(&'static str); + +impl PlaintextSqlType { + pub const INTEGER: PlaintextSqlType = PlaintextSqlType("integer"); + pub const SMALLINT: PlaintextSqlType = PlaintextSqlType("smallint"); + pub const BIGINT: PlaintextSqlType = PlaintextSqlType("bigint"); + pub const DATE: PlaintextSqlType = PlaintextSqlType("date"); + + pub fn as_str(&self) -> &'static str { + self.0 + } +} + +impl fmt::Display for PlaintextSqlType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.0) + } +} + +/// The EQL `cast_as` for a scalar kind, drawn from the `Cast` allowlist. +/// +/// Only the wired kinds (the integer kinds plus `Date`) have `EqlPlaintext` +/// impls, so only those resolve; the remaining kinds mirror the `eql_scalars` +/// accessor convention and `panic!`, since no impl can ever reach them. +const fn cast_for_kind(kind: ScalarKind) -> Cast { + match kind { + ScalarKind::I32 => Cast::INT, + ScalarKind::I16 => Cast::SMALL_INT, + ScalarKind::I64 => Cast::BIG_INT, + ScalarKind::Date => Cast::DATE, + ScalarKind::Numeric | ScalarKind::Text | ScalarKind::Jsonb => { + panic!("EqlPlaintext is only implemented for the wired scalar kinds") + } + } +} + +/// The `plaintext` oracle column SQL type for a scalar kind, drawn from the +/// `PlaintextSqlType` allowlist. As with `cast_for_kind`, only the wired kinds +/// (integers plus `Date`) resolve. +const fn plaintext_sql_type_for_kind(kind: ScalarKind) -> PlaintextSqlType { + match kind { + ScalarKind::I32 => PlaintextSqlType::INTEGER, + ScalarKind::I16 => PlaintextSqlType::SMALLINT, + ScalarKind::I64 => PlaintextSqlType::BIGINT, + ScalarKind::Date => PlaintextSqlType::DATE, + ScalarKind::Numeric | ScalarKind::Text | ScalarKind::Jsonb => { + panic!("EqlPlaintext is only implemented for the wired scalar kinds") + } + } +} + +mod sealed { + pub trait Sealed {} + impl Sealed for i32 {} + impl Sealed for i16 {} + impl Sealed for i64 {} + impl Sealed for chrono::NaiveDate {} +} + +/// A Rust type usable as a fixture `plaintext` value, carrying its EQL cast +/// and the SQL type of the `plaintext` column. Sealed; only this crate may +/// add impls. +/// +/// Each impl supplies a single `KIND`; the EQL cast and `plaintext` column +/// SQL type are derived from it via `cast_for_kind` / +/// `plaintext_sql_type_for_kind`, so they cannot drift from the kind. +pub trait EqlPlaintext: sealed::Sealed { + /// The scalar kind this plaintext type maps to. The single source of + /// truth from which `CAST` and `PLAINTEXT_SQL_TYPE` are derived. + const KIND: ScalarKind; + + const CAST: Cast = cast_for_kind(Self::KIND); + const PLAINTEXT_SQL_TYPE: PlaintextSqlType = plaintext_sql_type_for_kind(Self::KIND); + + /// Lift the Rust value into the cipherstash-client `Plaintext` enum the + /// EQL encryption pipeline consumes. The mapping is total — every + /// `EqlPlaintext` impl maps cleanly onto a `Plaintext::*(Some(_))` + /// variant. + /// + /// Takes `&self` so future non-`Copy` plaintexts (`String`, + /// `BigDecimal`, `Vec`) implement without unnecessary clones. + fn to_plaintext(&self) -> Plaintext; +} + +impl EqlPlaintext for i32 { + const KIND: ScalarKind = ScalarKind::I32; + + fn to_plaintext(&self) -> Plaintext { + Plaintext::Int(Some(*self)) + } +} + +impl EqlPlaintext for i16 { + const KIND: ScalarKind = ScalarKind::I16; + + fn to_plaintext(&self) -> Plaintext { + Plaintext::SmallInt(Some(*self)) + } +} + +impl EqlPlaintext for i64 { + const KIND: ScalarKind = ScalarKind::I64; + + fn to_plaintext(&self) -> Plaintext { + Plaintext::BigInt(Some(*self)) + } +} + +impl EqlPlaintext for chrono::NaiveDate { + const KIND: ScalarKind = ScalarKind::Date; + + fn to_plaintext(&self) -> Plaintext { + Plaintext::NaiveDate(Some(*self)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn i32_casts_to_int() { + assert_eq!(::CAST.as_str(), "int"); + } + + #[test] + fn i32_plaintext_sql_type_is_integer() { + assert_eq!( + ::PLAINTEXT_SQL_TYPE.as_str(), + "integer" + ); + } + + #[test] + fn i32_to_plaintext_wraps_in_int_variant() { + // The trait must lift the raw i32 into the EQL pipeline's Plaintext + // enum so the fixture driver can hand it to `eql::encrypt_eql`. + match 42_i32.to_plaintext() { + Plaintext::Int(Some(value)) => assert_eq!(value, 42), + other => panic!("expected Plaintext::Int(Some(42)), got {other:?}"), + } + } + + #[test] + fn i16_casts_to_small_int() { + assert_eq!(::CAST.as_str(), "small_int"); + } + + #[test] + fn i16_plaintext_sql_type_is_smallint() { + assert_eq!( + ::PLAINTEXT_SQL_TYPE.as_str(), + "smallint" + ); + } + + #[test] + fn i16_to_plaintext_wraps_in_small_int_variant() { + // i16 must lift into the SmallInt variant so the fixture driver + // encrypts it under the `small_int` cast, not `int`. + match 42_i16.to_plaintext() { + Plaintext::SmallInt(Some(value)) => assert_eq!(value, 42), + other => panic!("expected Plaintext::SmallInt(Some(42)), got {other:?}"), + } + } + + #[test] + fn i64_casts_to_big_int() { + assert_eq!(::CAST.as_str(), "big_int"); + } + + #[test] + fn i64_plaintext_sql_type_is_bigint() { + assert_eq!(::PLAINTEXT_SQL_TYPE.as_str(), "bigint"); + } + + #[test] + fn i64_to_plaintext_wraps_in_big_int_variant() { + // i64 must lift into the BigInt variant so the fixture driver + // encrypts it under the `big_int` cast, not `int`. + match 42_i64.to_plaintext() { + Plaintext::BigInt(Some(value)) => assert_eq!(value, 42), + other => panic!("expected Plaintext::BigInt(Some(42)), got {other:?}"), + } + } + + #[test] + fn naive_date_casts_to_date() { + assert_eq!(::CAST.as_str(), "date"); + } + + #[test] + fn naive_date_plaintext_sql_type_is_date() { + assert_eq!( + ::PLAINTEXT_SQL_TYPE.as_str(), + "date" + ); + } + + #[test] + fn naive_date_to_plaintext_wraps_in_naive_date_variant() { + // A NaiveDate must lift into the NaiveDate variant so the fixture + // driver encrypts it under the `date` cast. + let d = chrono::NaiveDate::from_ymd_opt(1970, 1, 1).unwrap(); + match d.to_plaintext() { + Plaintext::NaiveDate(Some(value)) => assert_eq!(value, d), + other => panic!("expected Plaintext::NaiveDate(Some(1970-01-01)), got {other:?}"), + } + } +} diff --git a/tests/sqlx/src/fixtures/index_kind.rs b/tests/sqlx/src/fixtures/index_kind.rs new file mode 100644 index 00000000..f1633a03 --- /dev/null +++ b/tests/sqlx/src/fixtures/index_kind.rs @@ -0,0 +1,59 @@ +//! `IndexKind` — the typed EQL search-index identifier. +//! +//! Replaces the `&str` / `FixtureIdentifier`-validated string at the +//! spec/driver boundary. `FixtureIdentifier` proves the value matches +//! `^[a-z][a-z0-9_]*$`; it does NOT prove the name is a real index type. +//! `IndexKind` proves both, at compile time. A typo at spec construction +//! (`.with_index(IndexKind::Uniqu)`) is a compile error rather than a +//! runtime "unknown EQL index identifier" panic deep in the driver. + +use std::fmt; + +/// One of the EQL search-index identifiers cipherstash-config recognises. +/// Construction is through the variants — by construction every value is +/// in the allowlist. The wire-form `&str` (used in cipherstash-config and +/// the SQL renderers) is available via `as_str` / `Display`. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum IndexKind { + /// `unique` — drives `=` / `<>` via HMAC. + Unique, + /// `ore` — drives `<` / `<=` / `>` / `>=` via ORE block terms. + Ore, + /// `match` — drives `LIKE` / `ILIKE` via the bloom filter. + Match, +} + +impl IndexKind { + pub fn as_str(self) -> &'static str { + match self { + IndexKind::Unique => "unique", + IndexKind::Ore => "ore", + IndexKind::Match => "match", + } + } +} + +impl fmt::Display for IndexKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn renders_as_the_eql_wire_form_string() { + assert_eq!(IndexKind::Unique.as_str(), "unique"); + assert_eq!(IndexKind::Ore.as_str(), "ore"); + assert_eq!(IndexKind::Match.as_str(), "match"); + } + + #[test] + fn display_matches_as_str() { + assert_eq!(format!("{}", IndexKind::Unique), "unique"); + assert_eq!(format!("{}", IndexKind::Ore), "ore"); + assert_eq!(format!("{}", IndexKind::Match), "match"); + } +} diff --git a/tests/sqlx/src/fixtures/mod.rs b/tests/sqlx/src/fixtures/mod.rs new file mode 100644 index 00000000..65cdacbc --- /dev/null +++ b/tests/sqlx/src/fixtures/mod.rs @@ -0,0 +1,33 @@ +//! Type-checked fixture generation framework. +//! +//! A fixture is one Rust file under `src/fixtures/` declaring a `FixtureSpec`. +//! `FixtureSpec::run()` generates the SQLx fixture script +//! `tests/sqlx/fixtures/.sql` (gitignored — regenerated on every +//! `mise run test:sqlx`). + +pub mod validation; + +pub mod eql_plaintext; + +pub use eql_plaintext::EqlPlaintext; + +pub mod index_kind; + +pub use index_kind::IndexKind; + +pub mod spec; + +pub use spec::FixtureSpec; + +#[macro_use] +pub mod scalar_fixture; + +pub mod cipherstash; + +pub mod driver; + +// The per-type scalar fixture modules (`eql_v2_int4`, `eql_v2_int2`, …) are +// generated from the harness list in `scalar_types.rs`. Each expands to +// `pub mod eql_v2_ { … scalar_fixture! … }`, reading its plaintext values +// directly from the catalog (`eql_scalars::_VALUES`). +crate::scalar_types!(fixture_modules); diff --git a/tests/sqlx/src/fixtures/scalar_fixture.rs b/tests/sqlx/src/fixtures/scalar_fixture.rs new file mode 100644 index 00000000..d6a955ab --- /dev/null +++ b/tests/sqlx/src/fixtures/scalar_fixture.rs @@ -0,0 +1,127 @@ +//! `scalar_fixture!` — collapse a scalar fixture wrapper to one invocation. +//! +//! Every `eql_v2_` scalar fixture file (`eql_v2_int2`, `eql_v2_int4`, …) is +//! the same three items differing only in the fixture name, the Rust plaintext +//! type, and the generated value list: the `spec()` builder, the `fixture-gen` +//! generator test, and a small property-test module. This macro stamps all +//! three out, so a new scalar fixture is one `use` of the value const plus one +//! `scalar_fixture!(…)`. +//! +//! The per-file `//!` module docs still belong in each fixture file — they +//! describe *that* type's value choices and are not boilerplate. + +/// Stamp out the `spec()` builder, the `fixture-gen` generator test, and the +/// property-test module for a scalar fixture. +/// +/// The leading **kind** discriminator (`int` / `temporal`) selects which +/// property asserts are stamped — the rest of the expansion is identical: +/// +/// - `int` — signed-extreme asserts (`<$ty>::MIN`/`MAX`, `contains(&0)`, +/// `any(|v| v < 0)`). These typecheck only for integer plaintexts. +/// - `temporal` — a pivot-presence assert (`min_pivot`/`max_pivot`/zero from the +/// `ScalarType` impl all appear in the values). `<$ty>::MIN` / `< 0` don't +/// exist for a `chrono::NaiveDate`, so the integer asserts can't be reused. +/// +/// - `$name` — the fixture name (`"eql_v2_int2"`), drives every derived path. +/// - `$ty` — the Rust plaintext type (`i16` / `chrono::NaiveDate`). +/// - `$values` — the value source: the catalog const (`eql_scalars::INT2_VALUES`) +/// for integers, or the harness accessor (`date_values()`) for temporal. +/// +/// Indexes are fixed to `Unique` (HMAC, drives `=` / `<>`) and `Ore` (ORE +/// block terms, drives `<` `<=` `>` `>=`) with a committed `jsonb` payload — +/// the shape shared by every ordered scalar domain. +#[macro_export] +macro_rules! scalar_fixture { + // Integer scalars: signed-extreme property asserts. + (int, $name:literal, $ty:ty, $values:expr $(,)?) => { + $crate::scalar_fixture!(@common $name, $ty, $values); + + #[cfg(test)] + mod tests { + use super::*; + + #[test] + fn spec_is_complete() { + assert!(spec().check_complete().is_ok()); + } + + #[test] + fn spec_includes_signed_extremes() { + // MIN / MAX exercise ORE block-encoding sign-bit edges that a + // smaller list would not cover. + let spec = spec(); + let values = spec.values(); + assert!( + values.contains(&<$ty>::MIN), + "spec must include {}::MIN", + stringify!($ty) + ); + assert!( + values.contains(&<$ty>::MAX), + "spec must include {}::MAX", + stringify!($ty) + ); + assert!(values.contains(&0), "spec must include 0"); + } + + #[test] + fn spec_includes_negative_values() { + assert!(spec().values().iter().any(|&v| v < 0)); + } + } + }; + + // Temporal scalars: pivot-presence property assert (no signed extremes). + (temporal, $name:literal, $ty:ty, $values:expr $(,)?) => { + $crate::scalar_fixture!(@common $name, $ty, $values); + + #[cfg(test)] + mod tests { + use super::*; + use $crate::scalar_domains::ScalarType; + + #[test] + fn spec_is_complete() { + assert!(spec().check_complete().is_ok()); + } + + #[test] + fn spec_includes_pivots() { + // The three matrix pivots (min/max/zero) must be present in the + // fixture — `fetch_fixture_payload` fetches each at test time. + let spec = spec(); + let values = spec.values(); + let min = <$ty as ScalarType>::min_pivot(); + let max = <$ty as ScalarType>::max_pivot(); + let zero: $ty = ::core::default::Default::default(); + assert!(values.contains(&min), "spec must include min_pivot {min:?}"); + assert!(values.contains(&max), "spec must include max_pivot {max:?}"); + assert!(values.contains(&zero), "spec must include zero pivot {zero:?}"); + } + } + }; + + // Shared expansion: the `spec()` builder + the gated generator test. + (@common $name:literal, $ty:ty, $values:expr) => { + /// The complete fixture definition. `IndexKind::Unique` drives `=` / + /// `<>` (HMAC); `IndexKind::Ore` drives `<` `<=` `>` `>=` (ORE block + /// terms). + pub fn spec() -> $crate::fixtures::FixtureSpec<'static, $ty> { + $crate::fixtures::FixtureSpec::new($name) + .with_index($crate::fixtures::IndexKind::Unique) + .with_index($crate::fixtures::IndexKind::Ore) + .with_column_type("jsonb") + .with_values($values) + } + + /// The generator. Gated by `fixture-gen` so `cargo test` never compiles + /// it; `#[ignore]` is a second guard. Run via + /// `mise run fixture:generate`. + #[cfg(feature = "fixture-gen")] + #[tokio::test] + #[ignore = "generator — run via `mise run fixture:generate`"] + async fn generate() -> anyhow::Result<()> { + spec().run().await + } + }; +} diff --git a/tests/sqlx/src/fixtures/spec.rs b/tests/sqlx/src/fixtures/spec.rs new file mode 100644 index 00000000..5f9b952d --- /dev/null +++ b/tests/sqlx/src/fixtures/spec.rs @@ -0,0 +1,363 @@ +//! `FixtureSpec` — the type-checked fixture plug-in contract. +//! +//! `T` is the Rust plaintext type, inferred from `.with_values()`. Everything +//! not derivable — the indexes, the committed `payload` column type, the +//! data — is explicit. The fixture name drives every path by convention: +//! - table `fixtures.` +//! - working table `public._fixture_` +//! - script `tests/sqlx/fixtures/.sql` +//! - SQLx ref `scripts("")` +//! +//! Token-safety is enforced **at construction**: `new`, `.with_index`, and +//! `.with_column_type` each validate via the newtype `TryFrom` and **panic** +//! on a violation, so the builder stays a fluent chain (no `Result`, no +//! `?`). Because the spec stores validated newtypes (`FixtureIdentifier`, +//! `ColumnType`) and uses them via `Display` in the SQL renderers, an +//! unvalidated `&str` cannot reach a generated SQL string. `T::CAST` / +//! `T::PLAINTEXT_SQL_TYPE` are typed const newtypes (`Cast`, +//! `PlaintextSqlType`) — their allowlists are structural, so no runtime +//! check is needed. `check_complete()` covers only the completeness checks +//! (non-empty indexes/values) that the builder cannot make until the chain +//! is finished. + +use super::eql_plaintext::EqlPlaintext; +use super::index_kind::IndexKind; +use super::validation::{ColumnType, FixtureIdentifier}; + +/// A fully specified fixture, ready to `.run()`. +pub struct FixtureSpec<'a, T> { + name: FixtureIdentifier, + indexes: Vec, + column_type: ColumnType, + values: &'a [T], +} + +impl<'a, T> FixtureSpec<'a, T> { + /// Start a spec. `name` must match `^[a-z][a-z0-9_]*$` — it becomes a SQL + /// identifier and a filename. Other fields take defaults until set: + /// `column_type` defaults to `"jsonb"`, `indexes`/`values` to empty. + /// + /// # Panics + /// Panics if `name` is not a valid identifier. + pub fn new(name: &str) -> Self { + let name = + FixtureIdentifier::try_from(name).unwrap_or_else(|e| panic!("fixture name: {e}")); + let column_type = ColumnType::try_from("jsonb") + .expect("default column type \"jsonb\" must be in the allowlist"); + Self { + name, + indexes: Vec::new(), + column_type, + values: &[], + } + } + + /// Add a search index. `IndexKind` is a closed enum — a typo at the + /// call site is a compile error rather than a runtime panic. + pub fn with_index(mut self, kind: IndexKind) -> Self { + self.indexes.push(kind); + self + } + + /// Set the committed `payload` column SQL type. Defaults to `"jsonb"`. + /// + /// # Panics + /// Panics if `column_type` is not in `validation::ALLOWED_COLUMN_TYPES`. + pub fn with_column_type(mut self, column_type: &str) -> Self { + self.column_type = + ColumnType::try_from(column_type).unwrap_or_else(|e| panic!("column type: {e}")); + self + } + + /// Set the plaintext value list. `T` is inferred and bound here, so this + /// is where `T::CAST` and `T::PLAINTEXT_SQL_TYPE` become known. Their + /// allowlists are structural (typed-const newtypes), so no runtime + /// validation is needed at this point. + pub fn with_values(mut self, values: &'a [T]) -> Self + where + T: EqlPlaintext, + { + self.values = values; + self + } + + // ----- accessors used by SQL rendering / the driver ----- + + pub fn name(&self) -> &str { + self.name.as_str() + } + + pub fn indexes(&self) -> &[IndexKind] { + &self.indexes + } + + pub fn column_type(&self) -> &ColumnType { + &self.column_type + } + + /// The plaintext value slice. + pub fn values(&self) -> &[T] { + self.values + } + + /// `fixtures.` — the committed fixture table. + pub fn fixture_table(&self) -> String { + format!("fixtures.{}", self.name) + } + + /// `_fixture_` — the transient working table (unqualified `public`). + pub fn working_table(&self) -> String { + format!("_fixture_{}", self.name) + } + + /// `.sql` — the generated script filename (relative to fixtures dir). + pub fn script_filename(&self) -> String { + format!("{}.sql", self.name) + } + + /// SQL for the transient working table on the generation database. + /// `id BIGINT PRIMARY KEY`, `plaintext` as the SQL type for `T`, and a + /// plain `payload jsonb` staging column. The fixture driver encrypts in + /// Rust via `cipherstash-client` and inserts the resulting JSONB directly + /// — the working table is a values buffer that exists only so the render + /// step can use Postgres `format('%L', …)` for SQL literal escaping. No + /// `eql_v2_configuration` writes, no EQL types — the working table has + /// no EQL dependency at all. + /// + /// The leading `DROP TABLE IF EXISTS` is belt-and-suspenders: a normal run + /// drops the working table itself at the end of `run()`, so this only + /// matters when a prior run crashed before its own teardown. + pub fn working_schema_sql(&self) -> String + where + T: EqlPlaintext, + { + let working = self.working_table(); + format!( + "DROP TABLE IF EXISTS public.{working};\n\ + CREATE TABLE public.{working} (\n \ + id BIGINT PRIMARY KEY,\n \ + plaintext {plaintext_type} NOT NULL,\n \ + payload jsonb NOT NULL\n);\n", + plaintext_type = T::PLAINTEXT_SQL_TYPE, + ) + } + + /// The committed fixture script's header + schema + DDL, up to (not + /// including) the rendered INSERT rows. The driver appends the INSERTs. + /// `payload` uses the committed `column_type` (`jsonb` for #224), not + /// `eql_v2_encrypted`; `plaintext` uses the SQL type for `T`. + pub fn fixture_script_preamble(&self) -> String + where + T: EqlPlaintext, + { + format!( + "-- AUTO-GENERATED by `mise run fixture:generate {name}`.\n\ + -- DO NOT EDIT BY HAND. Re-run the generator to refresh.\n\ + --\n\ + -- Encrypted via cipherstash-client (HMAC + ORE block terms).\n\ + -- A SQLx fixture script: opt in with\n\ + -- #[sqlx::test(fixtures(path = \"../fixtures\", scripts(\"{name}\")))]\n\ + \n\ + CREATE SCHEMA IF NOT EXISTS fixtures;\n\ + DROP TABLE IF EXISTS {table};\n\ + CREATE TABLE {table} (\n \ + id BIGINT PRIMARY KEY,\n \ + plaintext {plaintext_type} NOT NULL,\n \ + payload {column_type} NOT NULL\n);\n\n", + name = self.name, + table = self.fixture_table(), + plaintext_type = T::PLAINTEXT_SQL_TYPE, + column_type = self.column_type, + ) + } + + /// SQL run on the *direct* connection to render each working-table row as + /// a committed INSERT. `format('%L', ...)` does server-side literal + /// escaping; row values never pass through Rust string interpolation. + /// `payload::text` projects the already-encrypted JSONB straight through + /// — the working table stores the cipherstash-client-encrypted payload as + /// plain `jsonb`, so no composite unwrap is needed. + pub fn render_rows_sql(&self) -> String { + format!( + "SELECT format(\n \ + 'INSERT INTO {table} (id, plaintext, payload) VALUES (%L, %L, %L::{column_type});',\n \ + id, plaintext, payload::text\n) \ + FROM public.{working} ORDER BY id", + table = self.fixture_table(), + column_type = self.column_type, + working = self.working_table(), + ) + } + + /// Check the spec is *complete*: it has at least one index and at least + /// one value. These cannot be checked at construction — the builder does + /// not know when the chain is finished — so the driver calls this before + /// generating any SQL. Token safety is already guaranteed by the + /// `FixtureIdentifier`/`ColumnType` newtypes; this method covers only what + /// construction cannot. + pub fn check_complete(&self) -> anyhow::Result<()> { + if self.indexes.is_empty() { + anyhow::bail!("fixture {:?} declares no indexes", self.name.as_str()); + } + if self.values.is_empty() { + anyhow::bail!("fixture {:?} has no values", self.name.as_str()); + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn int4_spec() -> FixtureSpec<'static, i32> { + const VALUES: &[i32] = &[-1, 1, 42]; + FixtureSpec::new("eql_v2_int4") + .with_index(IndexKind::Unique) + .with_index(IndexKind::Ore) + .with_column_type("jsonb") + .with_values(VALUES) + } + + #[test] + fn derives_paths_from_the_name() { + let s = int4_spec(); + assert_eq!(s.fixture_table(), "fixtures.eql_v2_int4"); + assert_eq!(s.working_table(), "_fixture_eql_v2_int4"); + assert_eq!(s.script_filename(), "eql_v2_int4.sql"); + } + + #[test] + fn records_indexes_in_order() { + let s = int4_spec(); + assert_eq!(s.indexes(), &[IndexKind::Unique, IndexKind::Ore]); + } + + #[test] + fn column_type_defaults_to_jsonb() { + const V: &[i32] = &[1]; + let s = FixtureSpec::new("x") + .with_index(IndexKind::Unique) + .with_values(V); + assert_eq!(s.column_type().as_str(), "jsonb"); + } + + #[test] + fn valid_spec_passes_completeness_check() { + assert!(int4_spec().check_complete().is_ok()); + } + + #[test] + #[should_panic(expected = "is not a valid identifier")] + fn validation_rejects_a_bad_name() { + // A bad name panics at construction, before the chain continues. + let _ = FixtureSpec::<'static, i32>::new("Bad-Name"); + } + + #[test] + #[should_panic(expected = "is not in the allowlist")] + fn validation_rejects_a_non_allowlisted_column_type() { + // A non-allowlisted column type panics in `.with_column_type()`. + let _ = FixtureSpec::<'static, i32>::new("x").with_column_type("text"); + } + + // Note: `with_index` formerly panicked on a malformed identifier (a + // `FixtureIdentifier::try_from` failure). The typed `IndexKind` enum + // makes that case unrepresentable — a typo is now a compile error. + + #[test] + fn completeness_rejects_a_spec_with_no_indexes() { + const V: &[i32] = &[1]; + let s = FixtureSpec::new("x").with_values(V); + assert!(s.check_complete().is_err()); + } + + #[test] + fn completeness_rejects_a_spec_with_no_values() { + const V: &[i32] = &[]; + let s = FixtureSpec::new("x") + .with_index(IndexKind::Unique) + .with_values(V); + assert!(s.check_complete().is_err()); + } + + #[test] + fn working_schema_sql_drops_and_creates_the_working_table() { + let sql = int4_spec().working_schema_sql(); + assert!(sql.contains("DROP TABLE IF EXISTS public._fixture_eql_v2_int4;")); + assert!(sql.contains("CREATE TABLE public._fixture_eql_v2_int4 (")); + assert!(sql.contains("id BIGINT PRIMARY KEY")); + assert!(sql.contains("plaintext integer NOT NULL")); + // The working table's payload is plain jsonb — encryption happens in + // Rust via cipherstash-client, not via a Proxy round trip. + assert!(sql.contains("payload jsonb")); + assert!( + !sql.contains("eql_v2_encrypted"), + "working table should not depend on the eql_v2_encrypted type" + ); + } + + #[test] + fn working_schema_sql_does_not_touch_eql_configuration() { + // The cipherstash-client path does NOT write to eql_v2_configuration: + // ColumnConfig lives entirely in Rust, no add_search_config / + // remove_search_config calls are emitted, and the working table has + // no EQL dependency. + let sql = int4_spec().working_schema_sql(); + assert!(!sql.contains("add_search_config")); + assert!(!sql.contains("remove_search_config")); + assert!(!sql.contains("eql_v2_configuration")); + } + + #[test] + fn fixture_script_preamble_renders_the_committed_table() { + let preamble = int4_spec().fixture_script_preamble(); + // header + assert!(preamble.contains("AUTO-GENERATED")); + assert!(preamble.contains("DO NOT EDIT BY HAND")); + assert!(preamble.contains("mise run fixture:generate eql_v2_int4")); + assert!(preamble.contains("HMAC + ORE block terms")); + // schema + table in the fixtures schema, jsonb payload + assert!(preamble.contains("CREATE SCHEMA IF NOT EXISTS fixtures;")); + assert!(preamble.contains("DROP TABLE IF EXISTS fixtures.eql_v2_int4;")); + assert!(preamble.contains("CREATE TABLE fixtures.eql_v2_int4 (")); + assert!(preamble.contains("id BIGINT PRIMARY KEY")); + assert!(preamble.contains("plaintext integer NOT NULL")); + assert!(preamble.contains("payload jsonb NOT NULL")); + } + + #[test] + fn fixture_script_preamble_attributes_encryption_to_cipherstash_client() { + // The preamble must record the encryption path so a reader of the + // committed SQL can trace it back to the generator. + let preamble = int4_spec().fixture_script_preamble(); + assert!(preamble.contains("cipherstash-client")); + assert!( + !preamble.contains("CipherStash Proxy"), + "preamble must not credit the Proxy — encryption is direct now" + ); + } + + #[test] + fn fixture_script_preamble_uses_the_committed_column_type() { + // The committed table uses .with_column_type(), NOT eql_v2_encrypted. + let preamble = int4_spec().fixture_script_preamble(); + assert!(!preamble.contains("eql_v2_encrypted")); + } + + #[test] + fn render_rows_sql_projects_format_l_over_the_working_table() { + let sql = int4_spec().render_rows_sql(); + assert!(sql.contains("INSERT INTO fixtures.eql_v2_int4 (id, plaintext, payload) VALUES")); + assert!(sql.contains("%L, %L, %L::jsonb")); + assert!(sql.contains("FROM public._fixture_eql_v2_int4")); + // payload is already encrypted JSONB in the working table; no + // composite to unwrap. + assert!(sql.contains("payload::text")); + assert!( + !sql.contains("(payload).data"), + "render must not unwrap a composite — payload is plain jsonb" + ); + assert!(sql.contains("ORDER BY id")); + } +} diff --git a/tests/sqlx/src/fixtures/validation.rs b/tests/sqlx/src/fixtures/validation.rs new file mode 100644 index 00000000..61746e60 --- /dev/null +++ b/tests/sqlx/src/fixtures/validation.rs @@ -0,0 +1,154 @@ +//! Pure SQL-token validators. Validated tokens are wrapped in newtypes +//! (`FixtureIdentifier`, `ColumnType`) so a renderer that accepts the newtype +//! receives type-level proof of validation — an unvalidated `&str` cannot +//! reach the renderer's format strings. + +use std::fmt; + +/// Maximum unquoted identifier length PostgreSQL preserves; longer identifiers +/// are silently truncated (`NAMEDATALEN - 1`). +const MAX_IDENTIFIER_LEN: usize = 63; + +/// Lowercase snake-case identifier, must start with a letter and be at most +/// 63 bytes (PostgreSQL truncates beyond that): `^[a-z][a-z0-9_]{0,62}$`. +fn is_valid_identifier(s: &str) -> bool { + // All accepted chars are single-byte ASCII, so byte length == char count. + if s.len() > MAX_IDENTIFIER_LEN { + return false; + } + let mut chars = s.chars(); + match chars.next() { + Some(c) if c.is_ascii_lowercase() => {} + _ => return false, + } + chars.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_') +} + +/// Allowlist of committed `payload` column types. `{ jsonb }` for #224 — no +/// domain types exist yet. Extending to domain-typed fixtures means extending +/// this list with validated, optionally schema-qualified type tokens. +pub const ALLOWED_COLUMN_TYPES: &[&str] = &["jsonb"]; + +fn is_valid_column_type(s: &str) -> bool { + ALLOWED_COLUMN_TYPES.contains(&s) +} + +/// A validated SQL identifier. Construction proves the string matches +/// `^[a-z][a-z0-9_]*$`. Renderers interpolate via `Display`, so the bare +/// `&str` cannot reach generated SQL once it has been validated into this type. +#[derive(Debug, Clone)] +pub struct FixtureIdentifier(String); + +impl FixtureIdentifier { + pub fn as_str(&self) -> &str { + &self.0 + } +} + +impl TryFrom<&str> for FixtureIdentifier { + type Error = String; + fn try_from(s: &str) -> Result { + if is_valid_identifier(s) { + Ok(Self(s.to_string())) + } else { + Err(format!( + "{s:?} is not a valid identifier (^[a-z][a-z0-9_]*$)" + )) + } + } +} + +impl fmt::Display for FixtureIdentifier { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(&self.0) + } +} + +/// A validated committed-payload column type token. Construction proves the +/// string is in `ALLOWED_COLUMN_TYPES`. +#[derive(Debug, Clone)] +pub struct ColumnType(String); + +impl ColumnType { + pub fn as_str(&self) -> &str { + &self.0 + } +} + +impl TryFrom<&str> for ColumnType { + type Error = String; + fn try_from(s: &str) -> Result { + if is_valid_column_type(s) { + Ok(Self(s.to_string())) + } else { + Err(format!( + "{s:?} is not in the allowlist {ALLOWED_COLUMN_TYPES:?}" + )) + } + } +} + +impl fmt::Display for ColumnType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(&self.0) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn accepts_valid_identifiers() { + assert!(FixtureIdentifier::try_from("eql_v2_int4").is_ok()); + assert!(FixtureIdentifier::try_from("a").is_ok()); + assert!(FixtureIdentifier::try_from("x9_y").is_ok()); + } + + #[test] + fn rejects_invalid_identifiers() { + assert!(FixtureIdentifier::try_from("").is_err()); + assert!(FixtureIdentifier::try_from("9abc").is_err()); // leading digit + assert!(FixtureIdentifier::try_from("_abc").is_err()); // leading underscore + assert!(FixtureIdentifier::try_from("Abc").is_err()); // uppercase + assert!(FixtureIdentifier::try_from("a-b").is_err()); // hyphen + assert!(FixtureIdentifier::try_from("a b").is_err()); // space + assert!(FixtureIdentifier::try_from("a;DROP").is_err()); // injection attempt + } + + #[test] + fn accepts_63_char_identifier() { + // 63 bytes is the longest PostgreSQL preserves unquoted. + let id = format!("a{}", "b".repeat(62)); + assert_eq!(id.len(), 63); + assert!(FixtureIdentifier::try_from(id.as_str()).is_ok()); + } + + #[test] + fn rejects_64_char_identifier() { + // 64 bytes would be silently truncated by PostgreSQL. + let id = format!("a{}", "b".repeat(63)); + assert_eq!(id.len(), 64); + assert!(FixtureIdentifier::try_from(id.as_str()).is_err()); + } + + #[test] + fn identifier_renders_via_display() { + let id = FixtureIdentifier::try_from("eql_v2_int4").unwrap(); + assert_eq!(format!("{id}"), "eql_v2_int4"); + } + + #[test] + fn column_type_accepts_jsonb_only() { + assert!(ColumnType::try_from("jsonb").is_ok()); + assert!(ColumnType::try_from("text").is_err()); + assert!(ColumnType::try_from("eql_v2_int4").is_err()); + assert!(ColumnType::try_from("jsonb; DROP TABLE x").is_err()); + } + + #[test] + fn column_type_renders_via_display() { + let ct = ColumnType::try_from("jsonb").unwrap(); + assert_eq!(format!("{ct}"), "jsonb"); + } +} diff --git a/tests/sqlx/src/helpers.rs b/tests/sqlx/src/helpers.rs index 6bf5fc4c..2e111e55 100644 --- a/tests/sqlx/src/helpers.rs +++ b/tests/sqlx/src/helpers.rs @@ -6,6 +6,19 @@ use anyhow::{Context, Result}; use serde_json; use sqlx::{PgPool, Row}; +/// Sentinel payload that satisfies every encrypted-domain CHECK in the +/// `eql_v2_{,_eq,_ord,_ord_ore}` family. Carries the EQL envelope +/// (`v`, `i`, `c`) plus *both* term keys (`hm`, `ob`) so one bind value +/// works for any variant's cast. +/// +/// Used by blocker / null-result tests where the payload is bound but +/// never decrypted — the blocker raises (or the STRICT wrapper +/// short-circuits) before the term values matter. **Not a representative +/// payload.** Real encrypted payloads come from the fixture +/// (Proxy-encrypted). +pub const PLACEHOLDER_PAYLOAD: &str = + r#"{"v":2,"i":{"t":"t","c":"c"},"c":"sample","hm":"sample","ob":["00"]}"#; + /// Fetch ORE encrypted value from pre-seeded ore table /// /// The ore table is created by migration `002_install_ore_data.sql` diff --git a/tests/sqlx/src/lib.rs b/tests/sqlx/src/lib.rs index 911264c3..4386222b 100644 --- a/tests/sqlx/src/lib.rs +++ b/tests/sqlx/src/lib.rs @@ -5,11 +5,28 @@ use sqlx::PgPool; pub mod assertions; +pub mod fixtures; pub mod helpers; pub mod index_types; +pub mod matrix; +pub mod scalar_domains; +#[macro_use] +pub mod scalar_types; pub mod selectors; -pub use assertions::QueryAssertion; +// Re-export `paste` under a stable path so the `scalar_domain_matrix!` macro +// can refer to `$crate::paste::paste!` without requiring callers to depend on +// the `paste` crate directly. +#[doc(hidden)] +pub use paste; + +// Re-export the harness proc-macro crate under a stable path so the +// `scalar_types!` macro can refer to `$crate::eql_tests_macros::!` +// without each call site depending on the proc-macro crate directly. +#[doc(hidden)] +pub use eql_tests_macros; + +pub use assertions::{assert_db_error, QueryAssertion}; pub use helpers::{ analyze_table, assert_no_seq_scan, assert_sequential_ids, assert_uses_index, assert_uses_seq_scan, create_jsonb_gin_index, ensure_pg_stat_statements, explain_analyze_avg, @@ -18,8 +35,13 @@ pub use helpers::{ get_ore_text_encrypted_as_jsonb, get_ste_vec_encrypted, get_ste_vec_encrypted_pair, get_ste_vec_selector_term, get_ste_vec_sv_element, get_ste_vec_term_by_id, read_pg_stat_statements, reset_pg_stat_statements, ExplainStats, PgStatEntry, + PLACEHOLDER_PAYLOAD, }; pub use index_types as IndexTypes; +pub use scalar_domains::{ + assert_null, assert_raises, assert_scalar_plaintexts, blocker_msg, commute_op, + fetch_fixture_payload, sql_string_literal, ScalarDomainSpec, ScalarType, Variant, +}; pub use selectors::Selectors; /// Reset pg_stat_user_functions tracking before tests diff --git a/tests/sqlx/src/matrix.rs b/tests/sqlx/src/matrix.rs new file mode 100644 index 00000000..2fdb9e5b --- /dev/null +++ b/tests/sqlx/src/matrix.rs @@ -0,0 +1,2757 @@ +//! Type-generic test matrix for encrypted scalar domains. +//! +//! Two entry points: +//! +//! - **`ordered_numeric_matrix!`** — the recommended wrapper. For an +//! ordered numeric scalar (i32, i64, f64, date, numeric, timestamp, +//! ...) all four variants are present, the operator surface is +//! identical, and the only inputs that change per type are the scalar +//! itself, the suite token (used to derive domain + test names), the +//! EQL type name (the fixture `scripts(...)` ref), and the pivot +//! values. Invocation is ~5 lines. +//! +//! - **`scalar_domain_matrix!`** — the lower-level macro the wrapper +//! expands to. Use directly only for types with a non-standard surface +//! (e.g. equality-only scalars like bool). +//! +//! Each invocation emits one `#[sqlx::test]` per (category, domain, +//! operator, pivot) tuple. Categories: sanity, correctness, cross-shape, +//! supported-NULL, blocker raises, index engagement, ORDER BY, ORDER BY +//! USING. +//! +//! Per-domain capability and payload metadata live in `Variant` (see +//! `scalar_domains.rs`); the macro derives the runtime `ScalarDomainSpec` +//! from `<$scalar as ScalarType>::PG_TYPE` + `Variant::` so no +//! per-type constants are needed. + +// ============================================================================ +// EXPLAIN plan inspection — node-type-aware index-engagement assertion. +// +// The index-engagement arms (`*_index_engages_*`, `*_ord_routes_through_ob`) +// previously asserted `plan_text.contains(index_name)` on a *text* EXPLAIN. +// That substring match is too weak in two independent ways: +// +// 1. It cannot distinguish an actual index-scan node from an incidental +// textual mention of the index name (e.g. inside an `Index Cond`, a +// filter expression, or a "Recheck Cond" line) — any line carrying the +// string passes, even if the relation is still read in full. +// 2. It says nothing about *which kind* of node read the relation. A +// Bitmap-recheck that still touches every heap row, or a node that +// merely references the index, looks identical to a clean Index Scan. +// +// `assert_index_scan_uses` parses `EXPLAIN (FORMAT JSON)` and requires a +// genuine index-scan node (`Index Scan` / `Index Only Scan` / +// `Bitmap Index Scan`) whose `Index Name` is the expected index. This is a +// structurally meaningful assertion even with `enable_seqscan = off`. +// +// LOUD CAVEAT — VALIDITY, NOT PREFERENCE. Even after this upgrade, the +// index-engagement arms run against a ~17-row fixture with +// `SET LOCAL enable_seqscan = off`. With the only cheaper alternative +// (seqscan) forcibly disabled, the planner will pick essentially any usable +// index. So these arms prove the index is USABLE / VALID (the operator +// resolves through the functional index and produces a real index-scan node) +// — they do NOT prove the planner would PREFER the index under realistic +// costs. Cost-preference is proven exclusively by `__scalar_matrix_scale_case` +// (the `*_scale_preference_*` tests), which build ~5000 rows and leave +// `enable_seqscan` ON. Those are `#[cfg(feature = "scale")]` and are OFF in +// default PR CI. Do not read a green index-engagement arm as "the planner +// chooses this index" — it only means "the planner *can* use this index". +// ============================================================================ + +/// Assert that a JSON EXPLAIN plan contains a real index-scan node whose +/// `Index Name` matches `index_name`. +/// +/// Recursively walks the plan tree. A node qualifies only if its `Node Type` +/// is one of `Index Scan`, `Index Only Scan`, or `Bitmap Index Scan` AND its +/// `Index Name` equals `index_name`. This is strictly stronger than a +/// substring match on the text plan, which would also accept an index name +/// appearing in an `Index Cond` / `Recheck Cond` / filter expression without +/// any index-scan node actually reading the relation. +/// +/// `query` is the bare SQL (no `EXPLAIN` prefix); it is interpolated directly, +/// so it must be a trusted/hardcoded string. `tx` is any sqlx executor. +/// +/// Returns `Err` (with the full pretty-printed plan) if no qualifying node is +/// found, so it composes with the `?` operator inside the generated arms. +pub async fn assert_index_scan_uses<'e, E>( + executor: E, + query: &str, + index_name: &str, + context: &str, +) -> anyhow::Result<()> +where + E: sqlx::Executor<'e, Database = sqlx::Postgres>, +{ + let sql = format!("EXPLAIN (FORMAT JSON) {query}"); + let plan: serde_json::Value = sqlx::query_scalar(&sql) + .fetch_one(executor) + .await + .map_err(|e| anyhow::anyhow!("running `{sql}`: {e}"))?; + + let mut index_scan_nodes: Vec<(String, String)> = Vec::new(); + collect_index_scan_nodes(&plan, &mut index_scan_nodes); + + let matched = index_scan_nodes + .iter() + .any(|(_node_type, name)| name == index_name); + + anyhow::ensure!( + matched, + "{context}: expected an index-scan node (Index Scan / Index Only Scan / \ + Bitmap Index Scan) referencing index `{index_name}`, but found none. \ + Index-scan nodes present: {index_scan_nodes:?}. Full plan:\n{}", + serde_json::to_string_pretty(&plan).unwrap_or_else(|_| plan.to_string()), + ); + Ok(()) +} + +/// Recursively collect `(Node Type, Index Name)` pairs for every index-scan +/// node in a JSON EXPLAIN plan tree. Only the three index-scan node types are +/// collected; other nodes (Seq Scan, Aggregate, Sort, ...) are skipped but +/// their children are still walked. +fn collect_index_scan_nodes(value: &serde_json::Value, found: &mut Vec<(String, String)>) { + match value { + serde_json::Value::Object(map) => { + if let Some(node_type) = map.get("Node Type").and_then(|v| v.as_str()) { + if matches!( + node_type, + "Index Scan" | "Index Only Scan" | "Bitmap Index Scan" + ) { + let index_name = map + .get("Index Name") + .and_then(|v| v.as_str()) + .unwrap_or(""); + found.push((node_type.to_string(), index_name.to_string())); + } + } + for v in map.values() { + collect_index_scan_nodes(v, found); + } + } + serde_json::Value::Array(arr) => { + for item in arr { + collect_index_scan_nodes(item, found); + } + } + _ => {} + } +} + +/// Convention wrapper for ordered numeric scalars. Expands to a +/// `scalar_domain_matrix!` invocation with the standard 4 variants, 6 +/// supported comparison operators, 2 path operators, and the standard +/// blocker / index partitions. +/// +/// `eql_type` is the fixture/table name (e.g. `"eql_v2_int4"`), used as the +/// SQLx fixture `scripts(...)` ref — sqlx parses it as a token-level string +/// literal, so it must be a literal, not derived. It is NOT a domain type +/// name: the `eql_v3.*` domains exercised here are derived from the scalar +/// type (see `scalar_domains.rs`, `format!("eql_v3.{}…", T::PG_TYPE)`). +/// +/// Pivots — the comparison anchors swept by the correctness / cross-shape +/// arms — are derived from the scalar type: `min_pivot()`, `max_pivot()`, and +/// zero (`Default::default()`). Integer scalars resolve `min_pivot`/`max_pivot` +/// to `Self::MIN`/`Self::MAX`; temporal scalars use explicit sentinel dates. The +/// fixture must contain those three plaintext rows, since each pivot's +/// ciphertext is fetched at test time via `fetch_fixture_payload`. +#[macro_export] +macro_rules! ordered_numeric_matrix { + ( + suite = $suite:ident, + scalar = $scalar:ty, + eql_type = $eql_type:literal $(,)? + ) => { + $crate::scalar_domain_matrix! { + suite = $suite, + scalar = $scalar, + eql_type = $eql_type, + // Relative to the suite source file at + // tests/sqlx/tests/encrypted_domain/scalars/.rs; sqlx's + // include_str! resolves it against that file. Every scalar + // suite lives at this depth, so the path is fixed here rather + // than repeated per invocation. + fixture_path = "../../../fixtures", + all_domains = [(storage, Storage), (eq, Eq), (ord, Ord), (ord_ore, OrdOre)], + eq_domains = [(eq, Eq), (ord, Ord), (ord_ore, OrdOre)], + ord_domains = [(ord, Ord), (ord_ore, OrdOre)], + ord_ore_domains = [(ord_ore, OrdOre)], + pivots = [ + (min, <$scalar as $crate::scalar_domains::ScalarType>::min_pivot()), + (max, <$scalar as $crate::scalar_domains::ScalarType>::max_pivot()), + (zero, <$scalar as ::core::default::Default>::default()), + ], + eq_ops = [(eq, "="), (neq, "<>")], + ord_ops = [(lt, "<"), (lte, "<="), (gt, ">"), (gte, ">=")], + index_combos = [ + (eq, Eq, "eql_v3.eq_term", "btree", [(eq, "=")]), + (eq, Eq, "eql_v3.eq_term", "hash", [(eq, "=")]), + (ord, Ord, "eql_v3.ord_term", "btree", + [(eq, "="), (lt, "<"), (lte, "<="), (gt, ">"), (gte, ">=")]), + (ord_ore, OrdOre, "eql_v3.ord_term", "btree", + [(eq, "="), (lt, "<"), (lte, "<="), (gt, ">"), (gte, ">=")]), + ], + blocker_combos = [ + (storage, Storage, [ + (eq, "="), (neq, "<>"), + (lt, "<"), (lte, "<="), (gt, ">"), (gte, ">="), + (contains, "@>"), (contained_by, "<@"), + ]), + (eq, Eq, [ + (lt, "<"), (lte, "<="), (gt, ">"), (gte, ">="), + (contains, "@>"), (contained_by, "<@"), + ]), + (ord, Ord, [(contains, "@>"), (contained_by, "<@")]), + (ord_ore, OrdOre, [(contains, "@>"), (contained_by, "<@")]), + ], + // Always-on cost-preference proof (#239 thread 17): the recommended + // converged ordered domain, ord_term btree. One curated combo keeps + // PR CI cost bounded. + scale_default_combos = [ + (ord, Ord, "eql_v3.ord_term", "btree"), + ], + } + }; +} + +/// Convention wrapper for equality-only scalars (no ord variants). Bool +/// is the canonical consumer: `=` / `<>` are meaningful; the four ord +/// operators are deliberate blockers. +/// +/// Expands to `scalar_domain_matrix!` with `ord_domains = []`, +/// `ord_ore_domains = []`, no btree-ord index combo, and blocker_combos +/// covering the ord operators on every materialised variant. Order-by / +/// order-by-using arms emit zero tests because they iterate empty +/// ord_domains. +/// +/// **Status:** this umbrella has no in-tree consumer yet. It exists so +/// that adding `bool` (or any other equality-only scalar) is one +/// `impl ScalarType` + fixture + one-line macro invocation, with no +/// macro authoring required. Runtime validation lands with bool. +#[macro_export] +macro_rules! eq_only_scalar_matrix { + ( + suite = $suite:ident, + scalar = $scalar:ty, + eql_type = $eql_type:literal, + pivots = [$($pivot:tt),+ $(,)?] $(,)? + ) => { + $crate::scalar_domain_matrix! { + suite = $suite, + scalar = $scalar, + eql_type = $eql_type, + // Fixed path; see `ordered_numeric_matrix!` for the rationale. + fixture_path = "../../../fixtures", + all_domains = [(storage, Storage), (eq, Eq)], + eq_domains = [(eq, Eq)], + ord_domains = [], + ord_ore_domains = [], + pivots = [$($pivot),+], + eq_ops = [(eq, "="), (neq, "<>")], + ord_ops = [(lt, "<"), (lte, "<="), (gt, ">"), (gte, ">=")], + index_combos = [ + (eq, Eq, "eql_v3.eq_term", "btree", [(eq, "=")]), + (eq, Eq, "eql_v3.eq_term", "hash", [(eq, "=")]), + ], + blocker_combos = [ + (storage, Storage, [ + (eq, "="), (neq, "<>"), + (lt, "<"), (lte, "<="), (gt, ">"), (gte, ">="), + (contains, "@>"), (contained_by, "<@"), + ]), + (eq, Eq, [ + (lt, "<"), (lte, "<="), (gt, ">"), (gte, ">="), + (contains, "@>"), (contained_by, "<@"), + ]), + ], + // Equality-only scalars have no ordered functional index to prefer. + scale_default_combos = [], + } + }; +} + +/// Low-level entry point. Use `ordered_numeric_matrix!` instead unless +/// your type's surface deviates from the standard ordered-numeric shape. +#[macro_export] +macro_rules! scalar_domain_matrix { + ( + suite = $suite:ident, + scalar = $scalar:ty, + eql_type = $eql_type:literal, + fixture_path = $fixture_path:literal, + all_domains = [$(($all_name:ident, $all_variant:ident)),+ $(,)?], + eq_domains = [$($eq_dom:tt),+ $(,)?], + ord_domains = [$($ord_dom:tt),* $(,)?], + ord_ore_domains = [$($ord_ore_dom:tt),* $(,)?], + pivots = [$($pivot:tt),+ $(,)?], + eq_ops = [$($eq_op:tt),+ $(,)?], + ord_ops = [$($ord_op:tt),+ $(,)?], + index_combos = [$($index_combo:tt),+ $(,)?], + blocker_combos = [$($blocker_combo:tt),+ $(,)?], + // Curated combo(s) that get an ALWAYS-ON cost-preference test (#239 + // thread 17). May be empty (e.g. equality-only scalars have no ordered + // index to prefer). + scale_default_combos = [$($scale_default_combo:tt),* $(,)?] $(,)? + ) => { + $crate::__scalar_matrix_sanity! { + suite = $suite, scalar = $scalar, + domains = [$(($all_name, $all_variant)),+], + } + $crate::__scalar_matrix_dxop_outer! { + case = __scalar_matrix_correctness_case, + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($eq_dom),+], ops_list = [$($eq_op),+], + pivots_list = [$($pivot),+], + } + $crate::__scalar_matrix_dxop_outer! { + case = __scalar_matrix_correctness_case, + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($ord_dom),*], ops_list = [$($ord_op),+], + pivots_list = [$($pivot),+], + } + $crate::__scalar_matrix_dxop_outer! { + case = __scalar_matrix_cross_shape_case, + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($eq_dom),+], ops_list = [$($eq_op),+], + pivots_list = [$($pivot),+], + } + $crate::__scalar_matrix_dxop_outer! { + case = __scalar_matrix_cross_shape_case, + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($ord_dom),*], ops_list = [$($ord_op),+], + pivots_list = [$($pivot),+], + } + $crate::__scalar_matrix_dxo_outer! { + case = __scalar_matrix_supported_null_case, + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($eq_dom),+], ops_list = [$($eq_op),+], + } + $crate::__scalar_matrix_dxo_outer! { + case = __scalar_matrix_supported_null_case, + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($ord_dom),*], ops_list = [$($ord_op),+], + } + $crate::__scalar_matrix_blocker_outer! { + suite = $suite, scalar = $scalar, + combos = [$($blocker_combo),+], + } + $crate::__scalar_matrix_payload_check_outer! { + suite = $suite, scalar = $scalar, + domains = [$(($all_name, $all_variant)),+], + } + $crate::__scalar_matrix_path_op_outer! { + suite = $suite, scalar = $scalar, + domains = [$(($all_name, $all_variant)),+], + } + $crate::__scalar_matrix_native_absent_outer! { + suite = $suite, scalar = $scalar, + domains = [$(($all_name, $all_variant)),+], + } + $crate::__scalar_matrix_typed_column_outer! { + suite = $suite, scalar = $scalar, + combos = [$($blocker_combo),+], + } + $crate::__scalar_matrix_planner_metadata_outer! { + suite = $suite, scalar = $scalar, group = eq, + domains = [$($eq_dom),+], + ops_list = [$($eq_op),+], + } + $crate::__scalar_matrix_planner_metadata_outer! { + suite = $suite, scalar = $scalar, group = ord, + domains = [$($ord_dom),*], + ops_list = [$($ord_op),+], + } + $crate::__scalar_matrix_index_outer! { + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + combos = [$($index_combo),+], + } + $crate::__scalar_matrix_scale_outer! { + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + combos = [$($index_combo),+], + } + $crate::__scalar_matrix_scale_default_outer! { + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + combos = [$($scale_default_combo),*], + } + $crate::__scalar_matrix_fixture_shape! { + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + } + $crate::__scalar_matrix_ord_routes_outer! { + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($ord_dom),*], + } + $crate::__scalar_matrix_ore_injectivity_outer! { + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($ord_ore_dom),*], + } + $crate::__scalar_matrix_aggregate_outer! { + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($ord_dom),*], + } + $crate::__scalar_matrix_aggregate_group_by_outer! { + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($ord_dom),*], + } + $crate::__scalar_matrix_aggregate_parallel_outer! { + suite = $suite, scalar = $scalar, + domains = [$($ord_dom),*], + } + $crate::__scalar_matrix_aggregate_typecheck_outer! { + suite = $suite, scalar = $scalar, + domains = [$(($all_name, $all_variant)),+], + } + $crate::__scalar_matrix_count_outer! { + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$(($all_name, $all_variant)),+], + } + $crate::__scalar_matrix_order_by_outer! { + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($ord_dom),*], + } + $crate::__scalar_matrix_order_by_nulls_outer! { + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($ord_dom),*], + } + $crate::__scalar_matrix_order_by_using_outer! { + suite = $suite, scalar = $scalar, script = $eql_type, script_path = $fixture_path, + domains = [$($ord_dom),*], ops_list = [$($ord_op),+], + } + }; +} + +// ============================================================================ +// Helpers: spec construction inside generated test bodies. +// ============================================================================ + +/// Inside a generated test body, build the runtime `ScalarDomainSpec` +/// from `<$scalar>::PG_TYPE` + `Variant::$variant`. All categories use +/// this — keeps the per-case body short. +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_spec { + ($scalar:ty, $variant:ident) => { + $crate::scalar_domains::ScalarDomainSpec::new::<$scalar>( + $crate::scalar_domains::Variant::$variant, + ) + }; +} + +// ============================================================================ +// Sanity category — one test per domain. Cheap thread-through check that +// the macro expanded and the trait wires up. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_sanity { + ( + suite = $suite:ident, + scalar = $scalar:ty, + domains = [$(($name:ident, $variant:ident)),+ $(,)?] $(,)? + ) => { + $( + $crate::paste::paste! { + #[sqlx::test] + async fn [](_pool: sqlx::PgPool) + -> anyhow::Result<()> + { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + assert!(!spec.sql_domain.is_empty()); + assert!(<$scalar as $crate::scalar_domains::ScalarType>::fixture_table_name() + .starts_with("fixtures.")); + Ok(()) + } + } + )+ + }; +} + +// ============================================================================ +// Shared cartesian-product drivers. `macro_rules!` cannot cross-product +// independent lists in one repetition (`$($($(…)*)*)*` over flat depth-1 +// lists does not compile — every metavariable is bound at depth 1), so one +// recursion level fixes one dimension. These generic drivers do that fan-out +// once and dispatch to a per-category leaf macro named by `case`. The +// dimension lists are independent: this is a product, not a zip. +// ============================================================================ + +// domain × op × pivot. +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_dxop_outer { + ( + case = $case:ident, + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domains = [$($domain:tt),* $(,)?], + ops_list = $ops_list:tt, pivots_list = $pivots_list:tt $(,)? + ) => { + $( + $crate::__scalar_matrix_dxop_mid! { + case = $case, + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + domain = $domain, ops_list = $ops_list, pivots_list = $pivots_list, + } + )* + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_dxop_mid { + ( + case = $case:ident, + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domain = ($dom_name:ident, $variant:ident), + ops_list = [$($op:tt),+ $(,)?], pivots_list = $pivots_list:tt $(,)? + ) => { + $( + $crate::__scalar_matrix_dxop_inner! { + case = $case, + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + op = $op, pivots_list = $pivots_list, + } + )+ + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_dxop_inner { + ( + case = $case:ident, + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident, + op = ($op_name:ident, $op:literal), + pivots_list = [$($pivot:tt),+ $(,)?] $(,)? + ) => { + $( + $crate::$case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + op_name = $op_name, op = $op, pivot = $pivot, + } + )+ + }; +} + +// domain × op. +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_dxo_outer { + ( + case = $case:ident, + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domains = [$($domain:tt),* $(,)?], ops_list = $ops_list:tt $(,)? + ) => { + $( + $crate::__scalar_matrix_dxo_inner! { + case = $case, + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + domain = $domain, ops_list = $ops_list, + } + )* + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_dxo_inner { + ( + case = $case:ident, + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domain = ($dom_name:ident, $variant:ident), + ops_list = [$($op:tt),+ $(,)?] $(,)? + ) => { + $( + $crate::$case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, op = $op, + } + )+ + }; +} + +// ============================================================================ +// Correctness category — leaf for the domain × op × pivot driver: assert the +// row set from `WHERE col op pivot` matches `T::expected_forward(op, pivot)`. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_correctness_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident, + op_name = $op_name:ident, op = $op:literal, + pivot = ($pivot_name:ident, $pivot_val:expr) $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let pivot: $scalar = $pivot_val; + let payload = + $crate::scalar_domains::fetch_fixture_payload::<$scalar>(&pool, pivot).await?; + let lit = $crate::scalar_domains::sql_string_literal(&payload); + let predicate = format!( + "payload::{d} {op} {lit}::jsonb::{d}", + d = &spec.sql_domain, op = $op, + ); + let expected = + <$scalar as $crate::scalar_domains::ScalarType>::expected_forward($op, pivot); + $crate::scalar_domains::assert_scalar_plaintexts::<$scalar>( + &pool, &spec.sql_domain, $op, &predicate, &expected, + ) + .await + } + } + }; +} + +// ============================================================================ +// Cross-shape category — leaf for the domain × op × pivot driver: per +// (domain, op, pivot) sweep the three operator argument shapes (d,d), (d,j), +// (j,d) and assert each returns the right row count. The `j_d` shape uses the +// commuted operator's expected set. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_cross_shape_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident, + op_name = $op_name:ident, op = $op:literal, + pivot = ($pivot_name:ident, $pivot_val:expr) $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let pivot: $scalar = $pivot_val; + let payload = + $crate::scalar_domains::fetch_fixture_payload::<$scalar>(&pool, pivot).await?; + let lit = $crate::scalar_domains::sql_string_literal(&payload); + let forward_count = + <$scalar as $crate::scalar_domains::ScalarType>::expected_forward($op, pivot) + .len() as i64; + let commuted_count = <$scalar as $crate::scalar_domains::ScalarType>::expected_forward( + $crate::scalar_domains::commute_op($op), pivot, + ).len() as i64; + let d = &spec.sql_domain; + let shapes = [ + ("d_d", format!("payload::{d} {op} {lit}::jsonb::{d}", op = $op), forward_count), + ("d_j", format!("payload::{d} {op} {lit}::jsonb", op = $op), forward_count), + ("j_d", format!("{lit}::jsonb {op} payload::{d}", op = $op), commuted_count), + ]; + let table = <$scalar as $crate::scalar_domains::ScalarType>::fixture_table_name(); + for (shape_label, predicate, expected_count) in shapes { + let count_sql = format!("SELECT count(*) FROM {table} WHERE {predicate}"); + let count: i64 = sqlx::query_scalar(&count_sql).fetch_one(&pool).await?; + assert_eq!( + count, expected_count, + "domain={} op={} pivot={:?} shape={shape_label} SQL={count_sql} \ + expected {expected_count} rows, got {count}", + d, $op, pivot + ); + } + Ok(()) + } + } + }; +} + +// ============================================================================ +// Supported-NULL category — leaf for the domain × op driver: STRICT wrappers +// must propagate NULL on all three NULL positions (left, right, both). +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_supported_null_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident, + op = ($op_name:ident, $op:literal) $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let payload = $crate::helpers::PLACEHOLDER_PAYLOAD; + let sql = format!( + "SELECT $1::jsonb::{d} {op} $2::jsonb::{d}", + d = &spec.sql_domain, op = $op, + ); + $crate::scalar_domains::assert_null(&pool, &sql, &[Some(payload), None]).await?; + $crate::scalar_domains::assert_null(&pool, &sql, &[None, Some(payload)]).await?; + $crate::scalar_domains::assert_null(&pool, &sql, &[None, None]).await?; + Ok(()) + } + } + }; +} + +// ============================================================================ +// Blocker category — per blocked (domain, op), sweep 3 arg shapes (all +// must raise) and 3 NULL positions on the (d, d) shape (non-STRICT proof). +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_blocker_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, + combos = [$($combo:tt),+ $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_blocker_combo! { + suite = $suite, scalar = $scalar, combo = $combo, + } + )+ + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_blocker_combo { + ( + suite = $suite:ident, scalar = $scalar:ty, + combo = ($dom_name:ident, $variant:ident, [$($op:tt),+ $(,)?]) $(,)? + ) => { + $( + $crate::__scalar_matrix_blocker_case! { + suite = $suite, scalar = $scalar, + dom_name = $dom_name, variant = $variant, op = $op, + } + )+ + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_blocker_case { + ( + suite = $suite:ident, scalar = $scalar:ty, + dom_name = $dom_name:ident, variant = $variant:ident, + op = ($op_name:ident, $op:literal) $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let payload = $crate::helpers::PLACEHOLDER_PAYLOAD; + let msg = $crate::scalar_domains::blocker_msg(&spec.sql_domain, $op); + let d = &spec.sql_domain; + + // Sweep 3 arg shapes — every overload must engage. + let shapes: [(String, String); 3] = [ + (format!("$1::jsonb::{d}"), format!("$2::jsonb::{d}")), + (format!("$1::jsonb::{d}"), "$2::jsonb".into()), + ("$1::jsonb".into(), format!("$2::jsonb::{d}")), + ]; + for (lhs, rhs) in shapes { + let sql = format!("SELECT {lhs} {op} {rhs}", op = $op); + $crate::scalar_domains::assert_raises( + &pool, &sql, &[Some(payload), Some(payload)], &msg, + ).await?; + } + + // Sweep 3 NULL positions on the (d, d) shape — blockers + // are non-STRICT so they must engage on every NULL config. + let null_sql = format!( + "SELECT $1::jsonb::{d} {op} $2::jsonb::{d}", op = $op, + ); + $crate::scalar_domains::assert_raises(&pool, &null_sql, &[None, Some(payload)], &msg).await?; + $crate::scalar_domains::assert_raises(&pool, &null_sql, &[Some(payload), None], &msg).await?; + $crate::scalar_domains::assert_raises(&pool, &null_sql, &[None, None], &msg).await?; + Ok(()) + } + } + }; +} + +// ============================================================================ +// Payload-check category — per variant, the domain CHECK rejects payloads +// missing required keys (envelope `v`/`i`/`c` plus `Variant::required_term()`) +// and rejects non-object payloads. Required keys are derived from +// `Variant::payload_required_keys()` so future variants pick up coverage. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_payload_check_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, + domains = [$(($dom_name:ident, $variant:ident)),+ $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_payload_check_case! { + suite = $suite, scalar = $scalar, + dom_name = $dom_name, variant = $variant, + } + )+ + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_payload_check_case { + ( + suite = $suite:ident, scalar = $scalar:ty, + dom_name = $dom_name:ident, variant = $variant:ident $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let baseline = $crate::helpers::PLACEHOLDER_PAYLOAD; + + // Each required key must trigger CHECK rejection when stripped. + for key in spec.variant.payload_required_keys() { + let sql = format!( + "SELECT ('{baseline}'::jsonb - '{key}')::{d}", + ); + let err = sqlx::query(&sql) + .fetch_one(&pool) + .await + .expect_err(&format!( + "{d} must reject payload missing `{key}`: {sql}" + )) + .to_string(); + anyhow::ensure!( + err.contains("violates check constraint"), + "expected check-constraint violation for missing `{key}` on {d}, got: {err}", + ); + } + + // Non-object payloads are rejected for every variant. + let sql = format!(r#"SELECT '["v","i","c"]'::jsonb::{d}"#); + let err = sqlx::query(&sql) + .fetch_one(&pool) + .await + .expect_err(&format!("{d} must reject non-object payload")) + .to_string(); + anyhow::ensure!( + err.contains("violates check constraint"), + "expected check-constraint violation for non-object on {d}, got: {err}", + ); + Ok(()) + } + } + }; +} + +// ============================================================================ +// Path-operator category — `->` and `->>` must raise the blocker on every +// variant (encrypted domains don't expose JSON path access). Three arg +// shapes per op, matching the parameter blocker arm's coverage. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_path_op_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, + domains = [$(($dom_name:ident, $variant:ident)),+ $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_path_op_case! { + suite = $suite, scalar = $scalar, + dom_name = $dom_name, variant = $variant, + } + )+ + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_path_op_case { + ( + suite = $suite:ident, scalar = $scalar:ty, + dom_name = $dom_name:ident, variant = $variant:ident $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let payload = $crate::helpers::PLACEHOLDER_PAYLOAD; + + for op in ["->", "->>"] { + let msg = $crate::scalar_domains::blocker_msg(d, op); + for sql in [ + format!("SELECT $1::jsonb::{d} {op} 'field'::text"), + format!("SELECT $1::jsonb::{d} {op} 0::integer"), + format!("SELECT $1::jsonb {op} $1::jsonb::{d}"), + ] { + $crate::scalar_domains::assert_raises( + &pool, &sql, &[Some(payload)], &msg, + ).await?; + } + } + Ok(()) + } + } + }; +} + +// ============================================================================ +// Native-absent category — `~~` / `~~*` (LIKE / ILIKE) are deliberately +// not declared on encrypted-domain types (no pattern-match capability), +// so resolution falls back to PostgreSQL's "operator does not exist" +// rather than an EQL blocker. Pin that they stay absent on every variant. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_native_absent_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, + domains = [$(($dom_name:ident, $variant:ident)),+ $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_native_absent_case! { + suite = $suite, scalar = $scalar, + dom_name = $dom_name, variant = $variant, + } + )+ + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_native_absent_case { + ( + suite = $suite:ident, scalar = $scalar:ty, + dom_name = $dom_name:ident, variant = $variant:ident $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let payload = $crate::helpers::PLACEHOLDER_PAYLOAD; + + for op in ["~~", "~~*"] { + let sql = format!("SELECT $1::jsonb::{d} {op} $2::jsonb::{d}"); + $crate::scalar_domains::assert_raises( + &pool, &sql, + &[Some(payload), Some(payload)], + "operator does not exist", + ).await?; + } + Ok(()) + } + } + }; +} + +// ============================================================================ +// Typed-column blocker category — pins the bare `WHERE col op col` form a +// real caller writes. The parameter blocker arm uses $1/$2 binds; this +// form resolves the same overloads through a different planner path +// (column-typed operand vs. cast-expression operand). One test per +// (variant, blocker-ops list), savepoint-isolated to avoid abort. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_typed_column_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, + combos = [$($combo:tt),+ $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_typed_column_case! { + suite = $suite, scalar = $scalar, combo = $combo, + } + )+ + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_typed_column_case { + ( + suite = $suite:ident, scalar = $scalar:ty, + combo = ($dom_name:ident, $variant:ident, [$(($op_name:ident, $op:literal)),+ $(,)?]) $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let payload = $crate::helpers::PLACEHOLDER_PAYLOAD; + + let mut tx = pool.begin().await?; + let create_sql = format!( + "CREATE TEMP TABLE typed_col (\ + id integer GENERATED ALWAYS AS IDENTITY,\ + value {d}\ + ) ON COMMIT DROP" + ); + sqlx::query(&create_sql).execute(&mut *tx).await?; + let insert_sql = format!( + "INSERT INTO typed_col(value) VALUES ($1::jsonb::{d})" + ); + sqlx::query(&insert_sql).bind(payload).execute(&mut *tx).await?; + + $( + sqlx::query("SAVEPOINT op_probe").execute(&mut *tx).await?; + let sql = format!("SELECT * FROM typed_col WHERE value {op} value", op = $op); + let err = sqlx::query(&sql) + .fetch_all(&mut *tx) + .await + .expect_err(&format!("{d} column {op} must raise", op = $op)) + .to_string(); + let expected = $crate::scalar_domains::blocker_msg(d, $op); + anyhow::ensure!( + err.contains(&expected), + "unexpected error for {sql}: got {err}, want {expected}", + ); + sqlx::query("ROLLBACK TO SAVEPOINT op_probe").execute(&mut *tx).await?; + )+ + + tx.commit().await?; + Ok(()) + } + } + }; +} + +// ============================================================================ +// Planner-metadata category — for every (variant, supported-op) the +// declared operator must carry COMMUTATOR, NEGATOR, and the RESTRICT / +// JOIN selectivity estimators on all 3 arg-shapes. Without these the +// planner cannot normalise commuted/negated predicates or cost them. +// Called twice from `scalar_domain_matrix!`: once for (eq_domains, +// eq_ops), once for (ord_domains, ord_ops). Storage variants have no +// supported ops and so don't emit a test. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_planner_metadata_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, group = $group:ident, + domains = [$(($dom_name:ident, $variant:ident)),* $(,)?], + ops_list = $ops_list:tt $(,)? + ) => { + $( + $crate::__scalar_matrix_planner_metadata_case! { + suite = $suite, scalar = $scalar, group = $group, + dom_name = $dom_name, variant = $variant, + ops_list = $ops_list, + } + )* + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_planner_metadata_case { + ( + suite = $suite:ident, scalar = $scalar:ty, group = $group:ident, + dom_name = $dom_name:ident, variant = $variant:ident, + ops_list = [$(($op_name:ident, $op:literal)),+ $(,)?] $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let ops: &[&str] = &[$($op),+]; + let op_list = ops.iter() + .map(|o| format!("'{o}'")) + .collect::>() + .join(", "); + let sql = format!( + r#" + SELECT o.oprname, + lt.typname AS lhs, + rt.typname AS rhs, + o.oprcom <> 0 AS has_commutator, + o.oprnegate <> 0 AS has_negator, + o.oprrest::oid <> 0 AS has_restrict, + o.oprjoin::oid <> 0 AS has_join + FROM pg_catalog.pg_operator o + JOIN pg_catalog.pg_type lt ON lt.oid = o.oprleft + JOIN pg_catalog.pg_type rt ON rt.oid = o.oprright + WHERE o.oprname IN ({op_list}) + AND ('{d}'::regtype = o.oprleft OR '{d}'::regtype = o.oprright) + "# + ); + let rows: Vec<(String, String, String, bool, bool, bool, bool)> = + sqlx::query_as(&sql).fetch_all(&pool).await?; + + let expected = ops.len() * 3; + anyhow::ensure!( + rows.len() == expected, + "expected {expected} rows ({n_ops} ops x 3 arg shapes) on {d}, got {got}", + n_ops = ops.len(), + got = rows.len(), + ); + for (op, lhs, rhs, has_com, has_neg, has_rest, has_join) in &rows { + anyhow::ensure!(*has_com, + "operator {op}({lhs},{rhs}) must declare COMMUTATOR"); + anyhow::ensure!(*has_neg, + "operator {op}({lhs},{rhs}) must declare NEGATOR"); + anyhow::ensure!(*has_rest, + "operator {op}({lhs},{rhs}) must declare RESTRICT"); + anyhow::ensure!(*has_join, + "operator {op}({lhs},{rhs}) must declare JOIN"); + } + Ok(()) + } + } + }; +} + +// ============================================================================ +// Scale-preference category — feature-gated. Builds a temp table with +// ~5000 filler rows plus one selective pivot, creates the functional +// index, and asserts the planner *prefers* the index with +// `enable_seqscan` left on. The index_engages arm forces seqscan off and +// only proves the index is *usable*; this proves the planner picks it. +// Off by default (`#[cfg(feature = "scale")]`) so PR CI stays fast. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_scale_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + combos = [$($combo:tt),+ $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_scale_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, combo = $combo, + } + )+ + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_scale_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + combo = ( + $dom_name:ident, $variant:ident, + $extractor:literal, $using:literal, + [$(($op_name:ident, $op:literal)),+ $(,)?] $(,)? + ) $(,)? + ) => { + $crate::paste::paste! { + #[cfg(feature = "scale")] + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + use $crate::scalar_domains::ScalarType; + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let table = concat!( + "matrix_", stringify!($suite), "_", stringify!($dom_name), + "_scale_", $using, + ); + let index = concat!( + "matrix_", stringify!($suite), "_", stringify!($dom_name), + "_scale_", $using, "_idx", + ); + + let values: &[$scalar] = <$scalar as ScalarType>::fixture_values(); + anyhow::ensure!(values.len() >= 2, + "scale test requires >= 2 fixture rows for distinct filler/pivot"); + let filler = values[0]; + let pivot = values[values.len() / 2]; + let filler_payload = + $crate::scalar_domains::fetch_fixture_payload::<$scalar>(&pool, filler).await?; + let pivot_payload = + $crate::scalar_domains::fetch_fixture_payload::<$scalar>(&pool, pivot).await?; + + let mut tx = pool.begin().await?; + sqlx::query(&format!( + "CREATE TEMP TABLE {table} (value {d}) ON COMMIT DROP", + )).execute(&mut *tx).await?; + sqlx::query(&format!( + "INSERT INTO {table}(value) \ +SELECT $1::jsonb::{d} FROM generate_series(1, 5000)", + )).bind(&filler_payload).execute(&mut *tx).await?; + sqlx::query(&format!( + "INSERT INTO {table}(value) VALUES ($1::jsonb::{d})", + )).bind(&pivot_payload).execute(&mut *tx).await?; + sqlx::query(&format!( + "CREATE INDEX {index} ON {table} USING {using} ({extractor}(value))", using = $using, extractor = $extractor, + )).execute(&mut *tx).await?; + sqlx::query(&format!("ANALYZE {table}")) + .execute(&mut *tx).await?; + + let lit = pivot_payload.replace('\'', "''"); + $crate::matrix::assert_index_scan_uses( + &mut *tx, + &format!("SELECT * FROM {table} WHERE value = '{lit}'::jsonb::{d}"), + index, + &format!( + "with seqscan enabled the planner must prefer the {extractor} {using} index for a selective =", + extractor = $extractor, using = $using, + ), + ).await?; + + tx.commit().await?; + Ok(()) + } + } + }; +} + +// ============================================================================ +// Scale-preference DEFAULT category — the always-on counterpart of the +// feature-gated scale sweep above (#239 thread 17). For one curated combo +// (the recommended ordered domain, ord_term btree) it builds ~5000 filler +// rows + one selective pivot, ANALYZEs, and — leaving `enable_seqscan` ON — +// asserts the planner PREFERS the functional index under realistic costs. +// Unlike the index-engagement arms (validity only, seqscan forced off), this +// proves cost-preference; unlike the `*_scale_preference_*` sweep it runs in +// default PR CI. The assertion is node-type-aware via `assert_index_scan_uses` +// (a genuine Index/Index-Only/Bitmap-Index-Scan node referencing the index), +// so it cannot be satisfied by an incidental textual mention of the index. +// Curated to a single combo so PR CI cost stays bounded. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_scale_default_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + combos = [$($combo:tt),* $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_scale_default_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, combo = $combo, + } + )* + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_scale_default_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + combo = ($dom_name:ident, $variant:ident, $extractor:literal, $using:literal) $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + use $crate::scalar_domains::ScalarType; + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let table = concat!( + "matrix_", stringify!($suite), "_", stringify!($dom_name), + "_scaledef_", $using, + ); + let index = concat!( + "matrix_", stringify!($suite), "_", stringify!($dom_name), + "_scaledef_", $using, "_idx", + ); + + let values: &[$scalar] = <$scalar as ScalarType>::fixture_values(); + anyhow::ensure!(values.len() >= 2, + "scale test requires >= 2 fixture rows for distinct filler/pivot"); + let filler = values[0]; + let pivot = values[values.len() / 2]; + let filler_payload = + $crate::scalar_domains::fetch_fixture_payload::<$scalar>(&pool, filler).await?; + let pivot_payload = + $crate::scalar_domains::fetch_fixture_payload::<$scalar>(&pool, pivot).await?; + + let mut tx = pool.begin().await?; + sqlx::query(&format!( + "CREATE TEMP TABLE {table} (value {d}) ON COMMIT DROP", + )).execute(&mut *tx).await?; + sqlx::query(&format!( + "INSERT INTO {table}(value) \ +SELECT $1::jsonb::{d} FROM generate_series(1, 5000)", + )).bind(&filler_payload).execute(&mut *tx).await?; + sqlx::query(&format!( + "INSERT INTO {table}(value) VALUES ($1::jsonb::{d})", + )).bind(&pivot_payload).execute(&mut *tx).await?; + sqlx::query(&format!( + "CREATE INDEX {index} ON {table} USING {using} ({extractor}(value))", using = $using, extractor = $extractor, + )).execute(&mut *tx).await?; + sqlx::query(&format!("ANALYZE {table}")) + .execute(&mut *tx).await?; + // enable_seqscan left ON: this is a cost-preference proof, not a + // validity check. With ~5000 filler rows and a single selective + // pivot, a correctly-costed plan must choose the functional index. + + let lit = pivot_payload.replace('\'', "''"); + $crate::matrix::assert_index_scan_uses( + &mut *tx, + &format!("SELECT * FROM {table} WHERE value = '{lit}'::jsonb::{d}"), + index, + "with seqscan ON the planner must PREFER the ord_term functional index for a selective =", + ).await?; + + tx.commit().await?; + Ok(()) + } + } + }; +} + +// ============================================================================ +// Fixture-shape category — one test per type that pins the fixture's +// structural invariants: row count matches `T::fixture_values().len()`, +// ids are sequential from 1, plaintext column matches fixture_values() in +// order, every payload carries the variant terms (`hm`, `ob`, `c`), +// distinct plaintexts produce distinct hm terms, every payload declares +// `v=2`. A single test runs all assertions to keep pool-setup cost +// bounded. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_fixture_shape { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + use $crate::scalar_domains::ScalarType; + let table = <$scalar as ScalarType>::fixture_table_name(); + let expected: &[$scalar] = <$scalar as ScalarType>::fixture_values(); + let n = expected.len() as i64; + + let count: i64 = sqlx::query_scalar(&format!( + "SELECT COUNT(*) FROM {table}", + )).fetch_one(&pool).await?; + anyhow::ensure!(count == n, + "row count must match FIXTURE_VALUES.len(): want {n}, got {count}"); + + let ids: Vec = sqlx::query_scalar(&format!( + "SELECT id FROM {table} ORDER BY id", + )).fetch_all(&pool).await?; + anyhow::ensure!(ids == (1..=n).collect::>(), + "ids must be sequential from 1: got {ids:?}"); + + let plaintexts: Vec<$scalar> = sqlx::query_scalar(&format!( + "SELECT plaintext FROM {table} ORDER BY id", + )).fetch_all(&pool).await?; + anyhow::ensure!(plaintexts == expected, + "plaintext column must match FIXTURE_VALUES in order"); + + for (label, predicate) in [ + ("hm string", "payload->'hm' IS NULL OR jsonb_typeof(payload->'hm') <> 'string'"), + ("ob array", "payload->'ob' IS NULL OR jsonb_typeof(payload->'ob') <> 'array'"), + ("c string", "payload->'c' IS NULL OR jsonb_typeof(payload->'c') <> 'string'"), + ] { + let missing: i64 = sqlx::query_scalar(&format!( + "SELECT COUNT(*) FROM {table} WHERE {predicate}", + )).fetch_one(&pool).await?; + anyhow::ensure!(missing == 0, + "every payload must carry a `{label}` term; missing = {missing}"); + } + + let distinct_hm: i64 = sqlx::query_scalar(&format!( + "SELECT COUNT(DISTINCT payload->>'hm') FROM {table}", + )).fetch_one(&pool).await?; + anyhow::ensure!(distinct_hm == n, + "{n} distinct values -> {n} distinct hm terms; got {distinct_hm}"); + + let mismatched_version: i64 = sqlx::query_scalar(&format!( + "SELECT COUNT(*) FROM {table} \ + WHERE payload->'v' IS NULL OR payload->>'v' <> '2'", + )).fetch_one(&pool).await?; + anyhow::ensure!(mismatched_version == 0, + "every payload must declare v = '2'"); + + // Value-filtering oracle: take the midpoint of FIXTURE_VALUES, + // derive its expected id from position, assert exactly one row. + if !expected.is_empty() { + let probe = expected[expected.len() / 2]; + let probe_lit = <$scalar as ScalarType>::to_sql_literal(probe); + let expected_id = (expected.len() / 2 + 1) as i64; + let ids: Vec = sqlx::query_scalar(&format!( + "SELECT id FROM {table} WHERE plaintext = {lit} ORDER BY id", lit = probe_lit, + )).fetch_all(&pool).await?; + anyhow::ensure!(ids == vec![expected_id], + "expected exactly one row with plaintext = {probe:?} at id {expected_id}, got {ids:?}"); + } + + Ok(()) + } + } + }; +} + +// ============================================================================ +// Ord-routes-through-ob category — ordered variants carry `c + ob` and +// drop `hm`. Equality on an ord variant must therefore route through +// `eql_v3.ord_term` (the `ob` term), never HMAC. Strip `hm` from every +// fixture payload so an accidental regression to HMAC equality fails +// rather than passing on the hm-carrying fixture. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_ord_routes_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domains = [$(($dom_name:ident, $variant:ident)),* $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_ord_routes_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + } + )* + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_ord_routes_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let table = concat!( + "matrix_", stringify!($suite), "_", stringify!($dom_name), "_no_hm", + ); + let index = concat!( + "matrix_", stringify!($suite), "_", stringify!($dom_name), "_no_hm_idx", + ); + let fixture_table = + <$scalar as $crate::scalar_domains::ScalarType>::fixture_table_name(); + let pivot: $scalar = + <$scalar as $crate::scalar_domains::ScalarType>::fixture_values()[0]; + let pivot_lit = + <$scalar as $crate::scalar_domains::ScalarType>::to_sql_literal(pivot); + + let mut tx = pool.begin().await?; + sqlx::query(&format!( + "CREATE TEMP TABLE {table} (plaintext {pg}, value {d}) ON COMMIT DROP", + pg = <$scalar as $crate::scalar_domains::ScalarType>::PG_TYPE, + )).execute(&mut *tx).await?; + sqlx::query(&format!( + "INSERT INTO {table}(plaintext, value) \ + SELECT plaintext, (payload - 'hm')::{d} FROM {fixture}", fixture = fixture_table, + )).execute(&mut *tx).await?; + let with_hm: i64 = sqlx::query_scalar(&format!( + "SELECT count(*) FROM {table} WHERE jsonb_exists(value::jsonb, 'hm')", + )).fetch_one(&mut *tx).await?; + anyhow::ensure!(with_hm == 0, "test rows must not carry hm"); + + sqlx::query(&format!( + "CREATE INDEX {index} ON {table} USING btree (eql_v3.ord_term(value))", + )).execute(&mut *tx).await?; + sqlx::query(&format!("ANALYZE {table}")) + .execute(&mut *tx).await?; + sqlx::query("SET LOCAL enable_seqscan = off") + .execute(&mut *tx).await?; + + let pivot_payload: String = sqlx::query_scalar(&format!( + "SELECT (payload - 'hm')::text FROM {fixture} WHERE plaintext = {lit}", + fixture = fixture_table, lit = pivot_lit, + )).fetch_one(&mut *tx).await?; + + // The fixture plaintexts are distinct, so the pivot row is + // unique: `=` via ob must match EXACTLY one row, not "at + // least one". A weaker `>= 1` here is not independent of the + // `<>` check below — `expected_neq` is `len - eq_count`, so an + // `=` that over-matches inflates `eq_count` and deflates + // `expected_neq` in lockstep and both assertions still pass. + // Pinning `== 1` makes both this and the derived `<>` count + // load-bearing. + let eq_count: i64 = sqlx::query_scalar(&format!( + "SELECT count(*) FROM {table} WHERE value = $1::jsonb::{d}", + )).bind(&pivot_payload).fetch_one(&mut *tx).await?; + anyhow::ensure!(eq_count == 1, + "= must match exactly the pivot row via ob with no hm present (want 1, got {eq_count})"); + + // Derive from the pinned `eq_count == 1`: every other fixture + // row must be `<>`. Kept as `len - eq_count` (not a bare + // `len - 1`) so that if the `== 1` invariant above is ever + // relaxed the two assertions cannot silently compensate for + // each other — the derivation stays honest regardless. + let expected_neq = + <$scalar as $crate::scalar_domains::ScalarType>::fixture_values().len() as i64 + - eq_count; + let neq_count: i64 = sqlx::query_scalar(&format!( + "SELECT count(*) FROM {table} WHERE value <> $1::jsonb::{d}", + )).bind(&pivot_payload).fetch_one(&mut *tx).await?; + anyhow::ensure!(neq_count == expected_neq, + "<> must match every non-pivot fixture row (want {expected_neq}, got {neq_count})", + ); + + // VALIDITY, NOT PREFERENCE: this runs with + // `enable_seqscan = off` (set above) on the ~17-row fixture, + // so the planner picks the only usable alternative. A green + // assertion proves the `eql_v3.ord_term` functional btree is + // *usable* for `=` with no hm present, NOT that the planner + // would *prefer* it at realistic scale. Cost-preference lives + // in the `*_scale_preference_*` tests + // (`#[cfg(feature = "scale")]`, OFF in PR CI). See the module + // header on `assert_index_scan_uses` for the full caveat. + // + // Node-type-aware (not a name substring): we require a genuine + // Index/Index-Only/Bitmap-Index-Scan node referencing `index`, + // so an incidental textual mention of the index name in an + // Index Cond / filter can no longer satisfy the assertion. + let lit = pivot_payload.replace('\'', "''"); + $crate::matrix::assert_index_scan_uses( + &mut *tx, + &format!("SELECT * FROM {table} WHERE value = '{lit}'::jsonb::{d}"), + index, + "= must engage the eql_v3.ord_term functional btree with no hm", + ).await?; + + tx.commit().await?; + Ok(()) + } + } + }; +} + +// ============================================================================ +// ORE-injectivity category — for OrdOre variants, distinct plaintexts in +// the fixture must produce distinct ORE blocks. Pairwise self-join over +// the fixture: zero collisions. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_ore_injectivity_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domains = [$(($dom_name:ident, $variant:ident)),* $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_ore_injectivity_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + } + )* + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_ore_injectivity_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let fixture_table = + <$scalar as $crate::scalar_domains::ScalarType>::fixture_table_name(); + let collisions: i64 = sqlx::query_scalar(&format!( + "SELECT count(*) \ +FROM {fixture} a \ +JOIN {fixture} b ON a.id < b.id \ +WHERE a.payload::{d} = b.payload::{d}", + fixture = fixture_table, + )).fetch_one(&pool).await?; + anyhow::ensure!(collisions == 0, + "no two distinct plaintexts may share an ORE term on {d}"); + Ok(()) + } + } + }; +} + +// ============================================================================ +// Index-engagement category — per (domain, extractor, using, ops) build a +// typed temp table from the fixture, create the functional index, sweep +// ops × rhs-casts asserting EXPLAIN contains a genuine index-scan node +// referencing the index (via `assert_index_scan_uses`, not a name substring). +// +// VALIDITY ONLY: forces `enable_seqscan = off` on the ~17-row fixture, so a +// green arm proves the index is *usable*, NOT that the planner would *prefer* +// it. Cost-preference is the `*_scale_preference_*` tests +// (`#[cfg(feature = "scale")]`, OFF in PR CI). See the module-level comment on +// `assert_index_scan_uses` for the full caveat. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_index_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + combos = [$($combo:tt),+ $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_index_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, combo = $combo, + } + )+ + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_index_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + combo = ( + $dom_name:ident, $variant:ident, + $extractor:literal, $using:literal, + [$(($op_name:ident, $op:literal)),+ $(,)?] $(,)? + ) $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let table = concat!( + "matrix_", stringify!($suite), "_", stringify!($dom_name), + "_idx_", $using, + ); + let index = concat!( + "matrix_", stringify!($suite), "_", stringify!($dom_name), + "_idx_", $using, "_idx", + ); + let fixture_table = + <$scalar as $crate::scalar_domains::ScalarType>::fixture_table_name(); + let mut tx = pool.begin().await?; + + sqlx::query(&format!( + "CREATE TEMP TABLE {table} (plaintext {pg}, value {d}) ON COMMIT DROP", + pg = <$scalar as $crate::scalar_domains::ScalarType>::PG_TYPE, + d = &spec.sql_domain, + )).execute(&mut *tx).await?; + sqlx::query(&format!( + "INSERT INTO {table}(plaintext, value) \ + SELECT plaintext, payload::{d} FROM {fixture}", d = &spec.sql_domain, fixture = fixture_table, + )).execute(&mut *tx).await?; + sqlx::query(&format!( + "CREATE INDEX {index} ON {table} USING {using} ({extractor}(value))", using = $using, extractor = $extractor, + )).execute(&mut *tx).await?; + sqlx::query(&format!("ANALYZE {table}")) + .execute(&mut *tx).await?; + sqlx::query("SET LOCAL enable_seqscan = off").execute(&mut *tx).await?; + + let pivot: $scalar = <$scalar as $crate::scalar_domains::ScalarType>::fixture_values()[0]; + let payload = + $crate::scalar_domains::fetch_fixture_payload::<$scalar>(&pool, pivot).await?; + let lit = $crate::scalar_domains::sql_string_literal(&payload); + + // VALIDITY, NOT PREFERENCE: `enable_seqscan = off` is set + // above and the table holds only the ~17 fixture rows, so the + // planner has no cheaper option than the functional index. + // These arms therefore prove the index is *usable* for each + // (op, rhs-cast) shape — that the operator resolves through + // `{extractor}` and produces a real index-scan node — NOT that + // the planner would *prefer* the index under realistic costs. + // Cost-preference is proven ONLY by the `*_scale_preference_*` + // tests (`#[cfg(feature = "scale")]`), which are OFF in default + // PR CI. See the module header on `assert_index_scan_uses`. + // + // The assertion is node-type-aware (Index / Index Only / + // Bitmap Index Scan referencing `index`), not a bare substring + // match on the text plan, so an index name that merely appears + // in an Index Cond / Recheck Cond / filter cannot pass it. + let rhs_casts = [format!("::{d}", d = &spec.sql_domain), String::new()]; + $( + for rhs_cast in &rhs_casts { + let query = format!( + "SELECT * FROM {table} WHERE value {op} {lit}::jsonb{cast}", op = $op, cast = rhs_cast, + ); + $crate::matrix::assert_index_scan_uses( + &mut *tx, + &query, + index, + &format!( + "domain={} op={} rhs_cast={:?} must use index={}", + &spec.sql_domain, $op, rhs_cast, index, + ), + ).await?; + } + )+ + + tx.commit().await?; + Ok(()) + } + } + }; +} + +// ============================================================================ +// ORDER BY category — per ord domain × {ASC,DESC} × {no-WHERE, WHERE>0}. +// Fixture has no NULL plaintexts so NULLS FIRST/LAST is moot. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_order_by_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domains = [$($domain:tt),* $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_order_by_domain! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, domain = $domain, + } + )* + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_order_by_domain { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domain = ($dom_name:ident, $variant:ident) $(,)? + ) => { + $crate::__scalar_matrix_order_by_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + mode_name = asc_no_where, direction = "ASC", filter = all, + } + $crate::__scalar_matrix_order_by_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + mode_name = desc_no_where, direction = "DESC", filter = all, + } + $crate::__scalar_matrix_order_by_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + mode_name = asc_with_where, direction = "ASC", filter = gt_zero, + } + $crate::__scalar_matrix_order_by_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + mode_name = desc_with_where, direction = "DESC", filter = gt_zero, + } + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_order_by_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident, + mode_name = $mode_name:ident, direction = $direction:literal, + filter = $filter:ident $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + use $crate::scalar_domains::ScalarType; + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let fixture_table = <$scalar as ScalarType>::fixture_table_name(); + + let zero: $scalar = Default::default(); + let gt_zero = stringify!($filter) == "gt_zero"; + // Build the WHERE clause from the zero pivot's SQL literal so it + // is type-agnostic: `plaintext > 0` for integers, `plaintext > + // '1970-01-01'` for dates. A hardcoded `> 0` would not typecheck + // against a non-integer plaintext column. + let where_clause = if gt_zero { + format!(" WHERE plaintext > {}", <$scalar as ScalarType>::to_sql_literal(zero)) + } else { + String::new() + }; + let sql = format!( + "SELECT plaintext FROM {fixture}{where_clause} \ +ORDER BY eql_v3.ord_term(payload::{d}) {dir}", + fixture = fixture_table, + d = &spec.sql_domain, dir = $direction, + ); + let actual: Vec<$scalar> = sqlx::query_scalar(&sql).fetch_all(&pool).await?; + + let mut expected: Vec<$scalar> = + <$scalar as ScalarType>::fixture_values().to_vec(); + expected.sort(); + if gt_zero { + expected.retain(|v| *v > zero); + } + if $direction == "DESC" { expected.reverse(); } + + assert_eq!(actual, expected, + "domain={} mode={} SQL={} expected {:?}, got {:?}", + &spec.sql_domain, stringify!($mode_name), sql, expected, actual); + Ok(()) + } + } + }; +} + +// ============================================================================ +// ORDER BY NULLS FIRST/LAST category — per ord domain × {ASC,DESC} × +// {NULLS FIRST, NULLS LAST}. The plain ORDER BY arm above sorts the fixture, +// which has no NULL rows, so NULLS placement goes untested there. This arm +// builds an isolated temp table mixing NULL-valued rows with the fixture rows +// and pins that the NULL sort keys land at the requested end while the +// non-NULL rows stay in plaintext order. `eql_v3.ord_term` is STRICT, so a +// NULL domain value yields a NULL sort key; a regression making it non-STRICT +// would let NULL rows interleave — see the `family::mutations` negative +// control for that dimension. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_order_by_nulls_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domains = [$($domain:tt),* $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_order_by_nulls_domain! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, domain = $domain, + } + )* + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_order_by_nulls_domain { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domain = ($dom_name:ident, $variant:ident) $(,)? + ) => { + $crate::__scalar_matrix_order_by_nulls_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + mode_name = asc_nulls_first, direction = "ASC", nulls = "FIRST", + } + $crate::__scalar_matrix_order_by_nulls_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + mode_name = asc_nulls_last, direction = "ASC", nulls = "LAST", + } + $crate::__scalar_matrix_order_by_nulls_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + mode_name = desc_nulls_first, direction = "DESC", nulls = "FIRST", + } + $crate::__scalar_matrix_order_by_nulls_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + mode_name = desc_nulls_last, direction = "DESC", nulls = "LAST", + } + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_order_by_nulls_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident, + mode_name = $mode_name:ident, direction = $direction:literal, nulls = $nulls:literal $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + // Number of NULL-valued rows mixed in; >1 proves they cluster. + const NULL_ROWS: usize = 3; + + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let table = concat!( + "matrix_", stringify!($suite), "_", stringify!($dom_name), + "_order_by_", stringify!($mode_name), + ); + let fixture_table = + <$scalar as $crate::scalar_domains::ScalarType>::fixture_table_name(); + let pg = <$scalar as $crate::scalar_domains::ScalarType>::PG_TYPE; + + let mut tx = pool.begin().await?; + sqlx::query(&format!( + "CREATE TEMP TABLE {table} (plaintext {pg}, value {d}) ON COMMIT DROP", + )).execute(&mut *tx).await?; + // Non-NULL rows: every fixture row, carrying its plaintext. + sqlx::query(&format!( + "INSERT INTO {table}(plaintext, value) \ +SELECT plaintext, payload::{d} FROM {fixture}", fixture = fixture_table, + )).execute(&mut *tx).await?; + // NULL-valued rows: NULL plaintext too, so they surface as None + // and their position is what the assertion pins. + sqlx::query(&format!( + "INSERT INTO {table}(plaintext, value) \ +SELECT NULL::{pg}, NULL::{d} FROM generate_series(1, {n})", n = NULL_ROWS, + )).execute(&mut *tx).await?; + + let sql = format!( + "SELECT plaintext FROM {table} \ +ORDER BY eql_v3.ord_term(value) {dir} NULLS {nulls}", + dir = $direction, nulls = $nulls, + ); + let actual: Vec> = + sqlx::query_scalar(&sql).fetch_all(&mut *tx).await?; + + // Ground truth: non-NULL plaintexts sorted (reversed for DESC), + // with NULL_ROWS Nones at the requested end. + let mut non_null: Vec<$scalar> = + <$scalar as $crate::scalar_domains::ScalarType>::fixture_values().to_vec(); + non_null.sort(); + if $direction == "DESC" { non_null.reverse(); } + let sorted = non_null.into_iter().map(Some); + let mut expected: Vec> = Vec::new(); + if $nulls == "FIRST" { + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + expected.extend(sorted); + } else { + expected.extend(sorted); + expected.extend(std::iter::repeat(None).take(NULL_ROWS)); + } + + assert_eq!(actual, expected, + "domain={} mode={} SQL={} expected {:?}, got {:?}", + d, stringify!($mode_name), sql, expected, actual); + + tx.commit().await?; + Ok(()) + } + } + }; +} + +// ============================================================================ +// ORDER BY USING category — every op × ord domain must reject +// `ORDER BY col USING ` because the design forbids opclasses on +// these domains. If a refactor accidentally adds one, this fails. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_order_by_using_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domains = [$($domain:tt),* $(,)?], ops_list = $ops_list:tt $(,)? + ) => { + $( + $crate::__scalar_matrix_order_by_using_inner! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + domain = $domain, ops_list = $ops_list, + } + )* + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_order_by_using_inner { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domain = ($dom_name:ident, $variant:ident), + ops_list = [$(($op_name:ident, $op:literal)),+ $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_order_by_using_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + op_name = $op_name, op = $op, + } + )+ + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_order_by_using_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident, + op_name = $op_name:ident, op = $op:literal $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let fixture_table = + <$scalar as $crate::scalar_domains::ScalarType>::fixture_table_name(); + let sql = format!( + "SELECT plaintext FROM {fixture} ORDER BY payload::{d} USING {op}", + fixture = fixture_table, d = &spec.sql_domain, op = $op, + ); + let err = sqlx::query_scalar::<_, $scalar>(&sql) + .fetch_all(&pool) + .await + .expect_err(&format!( + "domain={} op={} SQL={} must reject ORDER BY USING (no opclass on \ +domain by design) but succeeded", + &spec.sql_domain, $op, sql, + )); + // SQLSTATE 42809 (wrong_object_type) — "operator X is not a + // valid ordering operator". The boolean operator exists on the + // domain but lacks a btree opclass entry, so ORDER BY USING + // refuses to use it. Pinning this catches the regression where + // a stray opclass would make ORDER BY USING start succeeding + // for the wrong reason — `is_err()` alone could not. + $crate::assert_db_error(&err, "42809", None); + Ok(()) + } + } + }; +} + +// ============================================================================ +// Aggregate category — per (ord domain, op ∈ {min, max}), three tests: +// extremum identity (payload of the min/max FIXTURE_VALUES row), all-NULL +// returns NULL, and mixed NULL/non-NULL returns the correct extremum from +// the non-NULL subset. Pins that `eql_v3.min` / `eql_v3.max` aggregates +// route through the domain's `<` / `>` and that the STRICT state function +// correctly seeds + skips NULLs. Emits zero tests when ord_domains is +// empty — eq-only umbrellas pick that up naturally. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_aggregate_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domains = [$($domain:tt),* $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_aggregate_mid! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + domain = $domain, + } + )* + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_aggregate_mid { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domain = ($dom_name:ident, $variant:ident) $(,)? + ) => { + $crate::__scalar_matrix_aggregate_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + op_name = min, agg_fn = "min", picker = min, + } + $crate::__scalar_matrix_aggregate_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + op_name = max, agg_fn = "max", picker = max, + } + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_aggregate_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident, + op_name = $op_name:ident, agg_fn = $agg_fn:literal, picker = $picker:ident $(,)? + ) => { + $crate::paste::paste! { + // Extremum identity: aggregate returns the exact payload of the + // smallest (or largest) fixture row. Domain-cast on both sides + // so the comparator routes through the variant's `<` / `>`. + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + use $crate::scalar_domains::ScalarType; + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let fixture = <$scalar as ScalarType>::fixture_table_name(); + let extremum: $scalar = <$scalar as ScalarType>::fixture_values() + .iter() + .copied() + .$picker() + .expect("FIXTURE_VALUES must be non-empty"); + let extremum_lit = <$scalar as ScalarType>::to_sql_literal(extremum); + + let expected: String = sqlx::query_scalar(&format!( + "SELECT payload::text FROM {fixture} WHERE plaintext = {lit}", lit = extremum_lit, + )).fetch_one(&pool).await?; + + let actual: String = sqlx::query_scalar(&format!( + "SELECT eql_v3.{agg}(payload::{d})::text FROM {fixture}", + agg = $agg_fn, + )).fetch_one(&pool).await?; + + assert_eq!( + actual, expected, + "eql_v3.{}({}) must return the payload of plaintext={:?} (the fixture {})", + $agg_fn, d, extremum, $agg_fn, + ); + + // Secondary diagnostic: when the primary identity holds, + // the ORE comparator must agree. The check is reached only + // on success of `assert_eq!`, so it's a self-consistency + // assertion on the comparator — catches the regression + // where payload text matches but `ord_term` resolves to a + // different value (e.g. due to payload-key reordering). + let ord_terms_match: bool = sqlx::query_scalar(&format!( + "SELECT eql_v3.ord_term(eql_v3.{agg}(payload::{d})) \ + = eql_v3.ord_term($1::jsonb::{d}) \ + FROM {fixture}", + agg = $agg_fn, + )) + .bind(&expected) + .fetch_one(&pool) + .await?; + anyhow::ensure!( + ord_terms_match, + "eql_v3.ord_term(eql_v3.{}({})) must equal eql_v3.ord_term() \ + for plaintext={:?}", + $agg_fn, d, extremum, + ); + Ok(()) + } + + // Empty rowset: aggregate over zero rows returns NULL, + // structurally distinct from the all-NULL case (no rows fed + // at all vs. rows fed but every value NULL). Both must + // return NULL but they exercise different sfunc paths. + #[sqlx::test] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let mut tx = pool.begin().await?; + sqlx::query(&format!( + "CREATE TEMP TABLE empty_agg (value {d}) ON COMMIT DROP", + )).execute(&mut *tx).await?; + let result: Option = sqlx::query_scalar(&format!( + "SELECT eql_v3.{agg}(value)::text FROM empty_agg", + agg = $agg_fn, + )).fetch_one(&mut *tx).await?; + anyhow::ensure!( + result.is_none(), + "empty rowset to eql_v3.{} on {} must return NULL, got {:?}", + $agg_fn, d, result, + ); + tx.commit().await?; + Ok(()) + } + + // All-NULL input: STRICT sfunc never seeds the state, final + // result is NULL. No fixture needed. + #[sqlx::test] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let sql = format!( + "SELECT eql_v3.{agg}(NULL::{d})::text FROM generate_series(1, 3)", + agg = $agg_fn, + ); + let result: Option = sqlx::query_scalar(&sql) + .fetch_one(&pool) + .await?; + anyhow::ensure!( + result.is_none(), + "all-NULL input to eql_v3.{} on {} must return NULL, got {:?}; SQL={}", + $agg_fn, d, result, sql, + ); + Ok(()) + } + + // Mixed NULL / non-NULL: feeds [NULL, mid, NULL, high, NULL] and + // asserts the aggregate returns the correct extremum of {mid, + // high}. A non-STRICT sfunc would crash on (state=NULL, value=mid) + // because `value < state` would be NULL; the STRICT contract + // skips NULL inputs and seeds with the first non-NULL value. + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + use $crate::scalar_domains::ScalarType; + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let fixture = <$scalar as ScalarType>::fixture_table_name(); + let values: &[$scalar] = <$scalar as ScalarType>::fixture_values(); + anyhow::ensure!( + values.len() >= 2, + "mixed-NULL test needs >= 2 fixture values; got {}", + values.len(), + ); + let mut sorted: Vec<$scalar> = values.to_vec(); + sorted.sort(); + // Span the fixture's extremes — for signed numeric scalars this + // exercises the ORE sign-bit edges in addition to pinning STRICT + // sfunc behaviour. + let low: $scalar = *sorted.first().expect("non-empty after len check"); + let high: $scalar = *sorted.last().expect("non-empty after len check"); + // .min() / .max() on two values resolves to the correct picker. + let expected_plaintext: $scalar = low.$picker(high); + let low_lit = <$scalar as ScalarType>::to_sql_literal(low); + let high_lit = <$scalar as ScalarType>::to_sql_literal(high); + let expected_lit = <$scalar as ScalarType>::to_sql_literal(expected_plaintext); + + let mut tx = pool.begin().await?; + sqlx::query(&format!( + "CREATE TEMP TABLE mixed_null (value {d}) ON COMMIT DROP", + )).execute(&mut *tx).await?; + sqlx::query(&format!( + "INSERT INTO mixed_null(value) \ + SELECT NULL::{d} \ + UNION ALL SELECT payload::{d} FROM {fixture} WHERE plaintext = {low} \ + UNION ALL SELECT NULL::{d} \ + UNION ALL SELECT payload::{d} FROM {fixture} WHERE plaintext = {high} \ + UNION ALL SELECT NULL::{d}", low = low_lit, high = high_lit, + )).execute(&mut *tx).await?; + + let expected: String = sqlx::query_scalar(&format!( + "SELECT payload::text FROM {fixture} WHERE plaintext = {lit}", lit = expected_lit, + )).fetch_one(&mut *tx).await?; + + let actual: Option = sqlx::query_scalar(&format!( + "SELECT eql_v3.{agg}(value)::text FROM mixed_null", + agg = $agg_fn, + )).fetch_one(&mut *tx).await?; + + anyhow::ensure!( + actual.as_deref() == Some(expected.as_str()), + "eql_v3.{} on mixed NULL/non-NULL must return the {} non-NULL value (plaintext={:?}); want {expected:?}, got {actual:?}", + $agg_fn, $agg_fn, expected_plaintext, + ); + + tx.commit().await?; + Ok(()) + } + } + }; +} + +// ============================================================================ +// Aggregate parallelism category — per ord domain, assert that the catalog +// declares MIN/MAX as PARALLEL SAFE with a combine function. Without those, +// PostgreSQL silently forecloses partial/parallel aggregation on exactly the +// large GROUP BY workloads these ORE aggregates exist to serve (#239 thread +// 22). A catalog-level structural guard (cheap, deterministic, no plan +// dependence) rather than a flaky "force a parallel plan" behavioural test. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_aggregate_parallel_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, + domains = [$($domain:tt),* $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_aggregate_parallel_case! { + suite = $suite, scalar = $scalar, domain = $domain, + } + )* + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_aggregate_parallel_case { + ( + suite = $suite:ident, scalar = $scalar:ty, + domain = ($dom_name:ident, $variant:ident) $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + for agg in ["min", "max"] { + let (proparallel, has_combine): (String, bool) = sqlx::query_as( + "SELECT p.proparallel::text, a.aggcombinefn <> 0 \ + FROM pg_proc p \ + JOIN pg_aggregate a ON a.aggfnoid = p.oid \ + WHERE p.proname = $1 \ + AND p.pronamespace = 'eql_v3'::regnamespace \ + AND p.proargtypes[0]::regtype = $2::regtype", + ) + .bind(agg) + .bind(d) + .fetch_one(&pool) + .await?; + anyhow::ensure!(proparallel == "s", + "eql_v3.{agg}({d}) must be PARALLEL SAFE (proparallel='s'), got {proparallel:?}"); + anyhow::ensure!(has_combine, + "eql_v3.{agg}({d}) must declare a combinefunc for partial aggregation"); + } + Ok(()) + } + } + }; +} + +// ============================================================================ +// Aggregate GROUP BY category — per (ord domain, op ∈ {min, max}), build a +// temp table partitioned into two groups, populate each with a known +// subset of fixture rows, GROUP BY the group key, and assert that +// `eql_v3.(value)` returns the correct extremum payload per group. +// Pins that the aggregate composes correctly under GROUP BY (state is +// reset between groups, the sfunc routes through the variant's +// comparator inside each partition). +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_aggregate_group_by_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domains = [$($domain:tt),* $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_aggregate_group_by_mid! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + domain = $domain, + } + )* + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_aggregate_group_by_mid { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domain = ($dom_name:ident, $variant:ident) $(,)? + ) => { + $crate::__scalar_matrix_aggregate_group_by_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + op_name = min, agg_fn = "min", picker = min, + } + $crate::__scalar_matrix_aggregate_group_by_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + op_name = max, agg_fn = "max", picker = max, + } + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_aggregate_group_by_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident, + op_name = $op_name:ident, agg_fn = $agg_fn:literal, picker = $picker:ident $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + use $crate::scalar_domains::ScalarType; + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let fixture = <$scalar as ScalarType>::fixture_table_name(); + let values: &[$scalar] = <$scalar as ScalarType>::fixture_values(); + anyhow::ensure!( + values.len() >= 5, + "GROUP BY test needs >= 5 fixture values; got {}", + values.len(), + ); + + // Partition FIXTURE_VALUES[..3] into group 1 and [3..5] + // into group 2. Per-group extremum is computed in Rust as + // the ground truth. + let group1: &[$scalar] = &values[..3]; + let group2: &[$scalar] = &values[3..5]; + let group1_extremum: $scalar = group1.iter().copied().$picker() + .expect("group 1 is non-empty"); + let group2_extremum: $scalar = group2.iter().copied().$picker() + .expect("group 2 is non-empty"); + let g1_lit = <$scalar as ScalarType>::to_sql_literal(group1_extremum); + let g2_lit = <$scalar as ScalarType>::to_sql_literal(group2_extremum); + + let mut tx = pool.begin().await?; + sqlx::query(&format!( + "CREATE TEMP TABLE group_test (group_key int, value {d}) \ +ON COMMIT DROP", + )).execute(&mut *tx).await?; + + // Insert group 1 rows. + for v in group1 { + let lit = <$scalar as ScalarType>::to_sql_literal(*v); + sqlx::query(&format!( + "INSERT INTO group_test(group_key, value) \ +SELECT 1, payload::{d} FROM {fixture} WHERE plaintext = {lit}", + )).execute(&mut *tx).await?; + } + // Insert group 2 rows. + for v in group2 { + let lit = <$scalar as ScalarType>::to_sql_literal(*v); + sqlx::query(&format!( + "INSERT INTO group_test(group_key, value) \ +SELECT 2, payload::{d} FROM {fixture} WHERE plaintext = {lit}", + )).execute(&mut *tx).await?; + } + + // Lookup the expected payload texts for each group's extremum. + let g1_expected: String = sqlx::query_scalar(&format!( + "SELECT payload::text FROM {fixture} WHERE plaintext = {lit}", lit = g1_lit, + )).fetch_one(&mut *tx).await?; + let g2_expected: String = sqlx::query_scalar(&format!( + "SELECT payload::text FROM {fixture} WHERE plaintext = {lit}", lit = g2_lit, + )).fetch_one(&mut *tx).await?; + + let rows: Vec<(i32, String)> = sqlx::query_as(&format!( + "SELECT group_key, eql_v3.{agg}(value)::text \ +FROM group_test GROUP BY group_key ORDER BY group_key", + agg = $agg_fn, + )).fetch_all(&mut *tx).await?; + + anyhow::ensure!( + rows.len() == 2, + "GROUP BY must return 2 rows, got {}", + rows.len(), + ); + anyhow::ensure!( + rows[0].0 == 1 && rows[0].1 == g1_expected, + "group 1 eql_v3.{}({}) must yield payload for plaintext={:?}; \ +want ({}, {:?}), got {:?}", + $agg_fn, d, group1_extremum, 1, g1_expected, rows[0], + ); + anyhow::ensure!( + rows[1].0 == 2 && rows[1].1 == g2_expected, + "group 2 eql_v3.{}({}) must yield payload for plaintext={:?}; \ +want ({}, {:?}), got {:?}", + $agg_fn, d, group2_extremum, 2, g2_expected, rows[1], + ); + + tx.commit().await?; + Ok(()) + } + } + }; +} + +// ============================================================================ +// Aggregate type-safety category — for variants that do NOT support ord +// (Storage, Eq), `eql_v3.min()` / `eql_v3.max(...)` must +// resolve to "function does not exist" (SQLSTATE 42883). Pins that +// codegen correctly omits MIN/MAX wrappers for these variants — a +// SQL-level regression test complementing the codegen unit test. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_aggregate_typecheck_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, + domains = [$(($dom_name:ident, $variant:ident)),+ $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_aggregate_typecheck_dispatch! { + suite = $suite, scalar = $scalar, + dom_name = $dom_name, variant = $variant, + } + )+ + }; +} + +// Dispatch on variant ident: ord-capable variants (Ord, OrdOre) emit no +// typecheck test — they DO declare min/max. Non-ord variants (Storage, +// Eq) emit one test per aggregate op asserting the call fails with +// SQLSTATE 42883. +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_aggregate_typecheck_dispatch { + // Ord, OrdOre: no typecheck test — these variants declare min/max. + ( + suite = $suite:ident, scalar = $scalar:ty, + dom_name = $dom_name:ident, variant = Ord $(,)? + ) => {}; + ( + suite = $suite:ident, scalar = $scalar:ty, + dom_name = $dom_name:ident, variant = OrdOre $(,)? + ) => {}; + // Storage, Eq: emit min + max typecheck tests. + ( + suite = $suite:ident, scalar = $scalar:ty, + dom_name = $dom_name:ident, variant = $variant:ident $(,)? + ) => { + $crate::__scalar_matrix_aggregate_typecheck_case! { + suite = $suite, scalar = $scalar, + dom_name = $dom_name, variant = $variant, + op_name = min, agg_fn = "min", + } + $crate::__scalar_matrix_aggregate_typecheck_case! { + suite = $suite, scalar = $scalar, + dom_name = $dom_name, variant = $variant, + op_name = max, agg_fn = "max", + } + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_aggregate_typecheck_case { + ( + suite = $suite:ident, scalar = $scalar:ty, + dom_name = $dom_name:ident, variant = $variant:ident, + op_name = $op_name:ident, agg_fn = $agg_fn:literal $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let payload = $crate::helpers::PLACEHOLDER_PAYLOAD; + + let mut tx = pool.begin().await?; + sqlx::query(&format!( + "CREATE TEMP TABLE typecheck_table (value {d}) ON COMMIT DROP", + )).execute(&mut *tx).await?; + sqlx::query(&format!( + "INSERT INTO typecheck_table(value) VALUES ($1::jsonb::{d})", + )).bind(payload).execute(&mut *tx).await?; + + // Savepoint-isolate the probe so the failed lookup + // doesn't abort the outer transaction and tx.commit() + // can succeed cleanly. + sqlx::query("SAVEPOINT probe").execute(&mut *tx).await?; + let sql = format!( + "SELECT eql_v3.{agg}(value) FROM typecheck_table", + agg = $agg_fn, + ); + let err = sqlx::query_scalar::<_, String>(&sql) + .fetch_one(&mut *tx) + .await + .expect_err(&format!( + "eql_v3.{} on non-ord variant {} must raise but succeeded", + $agg_fn, d, + )); + // 42883 = undefined_function (no overload defined at all); + // 42725 = ambiguous_function (multiple overloads resolve, + // none specific to this variant). Either confirms the + // variant carries no MIN/MAX of its own — the generic + // eql_v2_encrypted overload is reachable via cast but + // can't be resolved unambiguously from a domain-typed + // column. Both outcomes are acceptable "not supported". + let db_err = err.as_database_error() + .expect("expected database error from typecheck probe"); + let code = db_err.code(); + anyhow::ensure!( + code.as_deref() == Some("42883") || code.as_deref() == Some("42725"), + "expected SQLSTATE 42883 (undefined_function) or 42725 \ +(ambiguous_function) for eql_v3.{}({}), got {:?} (message: {})", + $agg_fn, d, code, db_err.message(), + ); + sqlx::query("ROLLBACK TO SAVEPOINT probe").execute(&mut *tx).await?; + + tx.commit().await?; + Ok(()) + } + } + }; +} + +// ============================================================================ +// COUNT category — pins three forms per variant: plain COUNT(value) on a +// typed column, COUNT(payload::variant) on the fixture, and +// COUNT(DISTINCT extractor(value)) using the variant's own extractor. The +// DISTINCT case dispatches per-variant: Storage has no extractor and so +// emits no DISTINCT test; Eq uses eq_term, Ord/OrdOre use ord_term. +// +// This is net new coverage relative to the legacy aggregate_tests.rs file, +// which only covered plain COUNT and only against the eql_v2_encrypted +// type. Pinning per-variant DISTINCT catches the breakage class where +// picking the wrong extractor would fail at runtime ("function +// eql_v3.eq_term(eql_v3.int4_ord) does not exist") — exactly the kind of +// thing the variant-aware matrix is meant to surface mechanically. +// ============================================================================ + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_count_outer { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + domains = [$(($dom_name:ident, $variant:ident)),+ $(,)?] $(,)? + ) => { + $( + $crate::__scalar_matrix_count_case! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + } + $crate::__scalar_matrix_count_distinct_dispatch! { + suite = $suite, scalar = $scalar, script = $script, script_path = $script_path, + dom_name = $dom_name, variant = $variant, + } + )+ + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_count_case { + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident $(,)? + ) => { + $crate::paste::paste! { + // COUNT(value) on a typed column — pins that PG's native COUNT + // works on a domain-typed column without an aggregate declaration. + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + use $crate::scalar_domains::ScalarType; + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let fixture = <$scalar as ScalarType>::fixture_table_name(); + let expected = <$scalar as ScalarType>::fixture_values().len() as i64; + + let mut tx = pool.begin().await?; + sqlx::query(&format!( + "CREATE TEMP TABLE typed_count (value {d}) ON COMMIT DROP", + )).execute(&mut *tx).await?; + sqlx::query(&format!( + "INSERT INTO typed_count(value) SELECT payload::{d} FROM {fixture}", + )).execute(&mut *tx).await?; + + let actual: i64 = sqlx::query_scalar( + "SELECT COUNT(value) FROM typed_count", + ).fetch_one(&mut *tx).await?; + anyhow::ensure!( + actual == expected, + "COUNT(value) on typed {} column: want {}, got {}", + d, expected, actual, + ); + + tx.commit().await?; + Ok(()) + } + + // COUNT(payload::variant) on the fixture — pins COUNT on a + // path-cast expression. No temp table; the cast happens inline. + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + use $crate::scalar_domains::ScalarType; + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let fixture = <$scalar as ScalarType>::fixture_table_name(); + let expected = <$scalar as ScalarType>::fixture_values().len() as i64; + + let sql = format!( + "SELECT COUNT(payload::{d}) FROM {fixture}", + ); + let actual: i64 = sqlx::query_scalar(&sql).fetch_one(&pool).await?; + anyhow::ensure!( + actual == expected, + "COUNT(payload::{}) on {}: want {}, got {}; SQL={}", + d, fixture, expected, actual, sql, + ); + Ok(()) + } + } + }; +} + +// Dispatch on variant ident: Storage has no discriminating extractor, so +// emits no DISTINCT test. The other three (Eq, Ord, OrdOre) each emit one +// test that reads the extractor function name from the runtime +// `ScalarDomainSpec::extractor_fn()` accessor (Eq -> `eql_v3.eq_term`, +// Ord/OrdOre -> `eql_v3.ord_term`) and appends `(value)` at the call site. +#[macro_export] +#[doc(hidden)] +macro_rules! __scalar_matrix_count_distinct_dispatch { + // Storage: no DISTINCT case — no extractor to deduplicate by. + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = Storage $(,)? + ) => {}; + // Eq, Ord, OrdOre — emit the DISTINCT test. + ( + suite = $suite:ident, scalar = $scalar:ty, script = $script:literal, script_path = $script_path:literal, + dom_name = $dom_name:ident, variant = $variant:ident $(,)? + ) => { + $crate::paste::paste! { + #[sqlx::test(fixtures(path = $script_path, scripts($script)))] + async fn []( + pool: sqlx::PgPool, + ) -> anyhow::Result<()> { + use $crate::scalar_domains::ScalarType; + let spec = $crate::__scalar_matrix_spec!($scalar, $variant); + let d = &spec.sql_domain; + let extractor_fn = spec.extractor_fn() + .expect("non-Storage variant must expose an extractor"); + let extractor = format!("{extractor_fn}(value)"); + let fixture = <$scalar as ScalarType>::fixture_table_name(); + let expected = <$scalar as ScalarType>::fixture_values().len() as i64; + + let mut tx = pool.begin().await?; + sqlx::query(&format!( + "CREATE TEMP TABLE distinct_count (value {d}) ON COMMIT DROP", + )).execute(&mut *tx).await?; + sqlx::query(&format!( + "INSERT INTO distinct_count(value) SELECT payload::{d} FROM {fixture}", + )).execute(&mut *tx).await?; + + let sql = format!( + "SELECT COUNT(DISTINCT {extr}) FROM distinct_count", + extr = extractor, + ); + let actual: i64 = sqlx::query_scalar(&sql).fetch_one(&mut *tx).await?; + anyhow::ensure!( + actual == expected, + "COUNT(DISTINCT {}) on {}: want {} (one per FIXTURE_VALUES row), got {}; SQL={}", + extractor, d, expected, actual, sql, + ); + + tx.commit().await?; + Ok(()) + } + } + }; +} diff --git a/tests/sqlx/src/scalar_domains.rs b/tests/sqlx/src/scalar_domains.rs new file mode 100644 index 00000000..69453f59 --- /dev/null +++ b/tests/sqlx/src/scalar_domains.rs @@ -0,0 +1,442 @@ +//! Type-generic substrate for the encrypted-scalar-domain test matrix. +//! +//! Adding a new encrypted scalar type (e.g. `i64` for int8, `f64` for +//! float8) is one ` => ` line in the `scalar_types!` list +//! (`scalar_types.rs`) plus an `EqlPlaintext` impl and a catalog row. +//! The `impl ScalarType` below is generated from that list. Everything +//! else — the four `eql_v2_{,_eq,_ord,_ord_ore}` domains, per-domain +//! payload shapes, supported operators, index extractor expressions, +//! ground-truth result sets — is derived from `T::PG_TYPE`, +//! `T::fixture_values()`, and the `Variant` enum. + +use anyhow::{bail, Context, Result}; +use sqlx::PgPool; +use std::fmt::{Debug, Display}; +use std::sync::LazyLock; + +/// One impl per scalar type. Two `const`s and the rest defaults. +pub trait ScalarType: + Copy + + Ord + + Default + + Debug + + Display + + Send + + Sync + + Unpin + + 'static + + for<'r> sqlx::Decode<'r, sqlx::Postgres> + + sqlx::Type +{ + /// Postgres native type token — also the suffix in the SQL domain + /// name and the fixture script name. Examples: `"int4"`, `"int8"`. + const PG_TYPE: &'static str; + + /// Distinct plaintext values present in the fixture, in a stable + /// order that MUST match fixture insertion order (the SQL script's + /// `id` sequence). Callers rely on this: the fixture-shape test + /// compares this slice element-wise against the `ORDER BY id` + /// plaintext column, and the scale/index arms index positionally + /// (`[0]`, `[len / 2]`) without sorting. A lazily-built `Vec` impl + /// must therefore be built deterministically in that same order. + /// + /// A method rather than a `const` because non-integer scalars (e.g. + /// `chrono::NaiveDate`, whose `from_ymd_opt` is not `const`) cannot be + /// materialised into a const slice; the harness builds those into a + /// `LazyLock>` and returns a borrow of it (see `date_values`). + /// Integer scalars return their `eql_scalars::_VALUES` const directly. + /// + /// For types driven by `ordered_numeric_matrix!`, the values MUST + /// include the three pivots (`min_pivot()`, `max_pivot()`, and zero + /// `Default::default()`): the matrix uses those as comparison pivots and + /// fetches each one's ciphertext via `fetch_fixture_payload`, which fails + /// loudly if the row is absent. + fn fixture_values() -> &'static [Self]; + + /// The low comparison pivot swept by the correctness / cross-shape arms. + /// Integer scalars return `Self::MIN`; temporal scalars return an explicit + /// sentinel (e.g. `1900-01-01`). A trait method rather than `Self::MIN` + /// because `chrono::DateTime` exposes `MAX_UTC`, not an inherent + /// `::MAX` const. The pivot must be present verbatim in `fixture_values()`. + fn min_pivot() -> Self; + + /// The high comparison pivot. Integer scalars return `Self::MAX`; temporal + /// scalars return an explicit sentinel (e.g. `2099-12-31`). Must be present + /// verbatim in `fixture_values()`. + fn max_pivot() -> Self; + + /// `fixtures.eql_v2_`. + fn fixture_table_name() -> String { + format!("fixtures.eql_v2_{}", Self::PG_TYPE) + } + + /// SQL-literal rendering via `Display`. Override for types whose + /// `Display` form isn't a valid SQL literal (e.g. strings, dates). + fn to_sql_literal(value: Self) -> String { + value.to_string() + } + + /// Ground-truth result set for `WHERE col op pivot`. Default works + /// for any `Ord` scalar; override only for non-orderable types. + fn expected_forward(op: &str, pivot: Self) -> Vec { + let predicate: fn(Self, Self) -> bool = match op { + "=" => |a, b| a == b, + "<>" => |a, b| a != b, + "<" => |a, b| a < b, + "<=" => |a, b| a <= b, + ">" => |a, b| a > b, + ">=" => |a, b| a >= b, + other => panic!("expected_forward: unsupported operator {other}"), + }; + let mut values: Vec = Self::fixture_values() + .iter() + .copied() + .filter(|v| predicate(*v, pivot)) + .collect(); + values.sort(); + values + } +} + +// The per-type `impl ScalarType` blocks for the **integer** scalars (each +// carrying its `PG_TYPE` token, `fixture_values() = eql_scalars::_VALUES`, +// and `min_pivot()`/`max_pivot()` = `Self::MIN`/`Self::MAX`) are generated from +// the single harness list in `scalar_types.rs`. To add an integer type, add a +// `token => rust_type` line there — not an impl here. +// +// Temporal scalars (`chrono::NaiveDate`, and `DateTime` in the stacked +// timestamptz PR) are hand-written below instead: their fixture values cannot be +// a `const` slice (chrono constructors are not `const`), and their pivots are +// explicit sentinels rather than `Self::MIN`/`Self::MAX`. The macro emits only +// integer impls. +crate::scalar_types!(scalar_type_impls); + +/// Typed `chrono::NaiveDate` fixture values, parsed once from `date`'s catalog +/// row. The catalog stores ISO strings (zero-dep); parsing into `NaiveDate` +/// lives here. `from_ymd_opt` is not `const`, so this cannot be a const slice — +/// hence the `LazyLock>` + `fixture_values()`-returns-a-borrow shape that +/// the const→fn trait change exists to allow. +static DATE_VALUES_CELL: LazyLock> = LazyLock::new(|| { + eql_scalars::DATE + .fixtures + .iter() + .map(|f| match f { + eql_scalars::Fixture::Date(s) => chrono::NaiveDate::parse_from_str(s, "%Y-%m-%d") + .unwrap_or_else(|e| panic!("invalid date fixture {s:?}: {e}")), + other => panic!("date catalog fixture must be Fixture::Date, got {other:?}"), + }) + .collect() +}); + +/// The parsed `chrono::NaiveDate` fixture values, in catalog order. Mirrors the +/// `eql_scalars::_VALUES` accessor pattern for the integer scalars; the +/// stacked timestamptz PR adds a sibling `timestamptz_values()`. Public so the +/// `eql_v2_date` fixture module (emitted by `scalar_types!(fixture_modules)`) +/// can hand the slice to `scalar_fixture!` — temporal scalars have no +/// `eql_scalars::_VALUES` const to point at. +pub fn date_values() -> &'static [chrono::NaiveDate] { + &DATE_VALUES_CELL +} + +impl ScalarType for chrono::NaiveDate { + const PG_TYPE: &'static str = "date"; + + fn fixture_values() -> &'static [Self] { + date_values() + } + + /// Temporal min pivot — `1900-01-01`, present verbatim in the catalog + /// fixtures (not `Self::MIN`, which would be far outside the fixture set). + fn min_pivot() -> Self { + chrono::NaiveDate::from_ymd_opt(1900, 1, 1).expect("1900-01-01 is a valid date") + } + + /// Temporal max pivot — `2099-12-31`, present verbatim in the catalog + /// fixtures. + fn max_pivot() -> Self { + chrono::NaiveDate::from_ymd_opt(2099, 12, 31).expect("2099-12-31 is a valid date") + } + + /// `Display` renders a `NaiveDate` as `2099-12-31` (unquoted), which is not + /// a valid SQL literal on its own — wrap it in single quotes. + fn to_sql_literal(value: Self) -> String { + format!("'{value}'") + } +} + +#[cfg(test)] +mod date_value_tests { + use super::*; + + /// The parsed `NaiveDate` values match the catalog fixture strings in + /// order and count — the harness oracle cannot drift from the catalog the + /// fixture generator encrypts. + #[test] + fn date_values_match_catalog_fixtures() { + let catalog: Vec<&str> = eql_scalars::DATE + .fixtures + .iter() + .map(|f| match f { + eql_scalars::Fixture::Date(s) => *s, + other => panic!("unexpected non-date fixture {other:?}"), + }) + .collect(); + let parsed = ::fixture_values(); + assert_eq!( + parsed.len(), + catalog.len(), + "parsed date count must match catalog fixture count" + ); + for (date, iso) in parsed.iter().zip(&catalog) { + assert_eq!(&date.format("%Y-%m-%d").to_string(), iso); + } + } + + /// The three temporal pivots resolve to fixture rows present verbatim. + #[test] + fn date_pivots_are_in_fixture_values() { + let values = ::fixture_values(); + let min = ::min_pivot(); + let max = ::max_pivot(); + let zero = chrono::NaiveDate::default(); + assert!(values.contains(&min), "min_pivot {min} must be a fixture"); + assert!(values.contains(&max), "max_pivot {max} must be a fixture"); + assert!( + values.contains(&zero), + "zero pivot {zero} must be a fixture" + ); + // Default is 1970-01-01, the documented zero pivot. + assert_eq!( + zero, + chrono::NaiveDate::from_ymd_opt(1970, 1, 1).unwrap(), + "NaiveDate::default() must be 1970-01-01" + ); + } +} + +/// Per-domain capability + payload shape. Storage carries no terms, `Eq` +/// adds `hm`, `Ord`/`OrdOre` add `ob`. `Ord` and `OrdOre` are deliberate +/// twins — same operator surface, different SQL domain names — for the +/// scheme-explicit vs converged-name migration story. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Variant { + Storage, + Eq, + Ord, + OrdOre, +} + +impl Variant { + /// Every variant the family currently materialises, in declaration + /// order. Tests iterate over this rather than hand-listing variants + /// so adding a future variant requires no test edit. + pub const ALL: &'static [Variant] = + &[Variant::Storage, Variant::Eq, Variant::Ord, Variant::OrdOre]; + + pub const fn suffix(self) -> &'static str { + match self { + Variant::Storage => "", + Variant::Eq => "_eq", + Variant::Ord => "_ord", + Variant::OrdOre => "_ord_ore", + } + } + + /// Term key the variant requires on its CHECK constraint. `Storage` + /// requires nothing beyond the envelope; `Eq` requires `hm`; + /// `Ord` / `OrdOre` require `ob`. Read by tests that need to know + /// "what term does this variant carry?" — not by payload builders; + /// see `PLACEHOLDER_PAYLOAD`. + pub const fn required_term(self) -> Option<&'static str> { + match self { + Variant::Storage => None, + Variant::Eq => Some("hm"), + Variant::Ord | Variant::OrdOre => Some("ob"), + } + } + + /// Top-level JSONB keys the variant's domain CHECK requires. + /// Storage requires the EQL envelope (`v`, `i`, `c`); ord-capable + /// variants additionally require their term key (`hm` / `ob`). The + /// matrix `payload_check` arm iterates this to assert each key's + /// absence is rejected at the cast. + pub fn payload_required_keys(self) -> impl Iterator { + ["v", "i", "c"].into_iter().chain(self.required_term()) + } + + pub const fn supports_eq(self) -> bool { + !matches!(self, Variant::Storage) + } + + pub const fn supports_ord(self) -> bool { + matches!(self, Variant::Ord | Variant::OrdOre) + } + + /// Function name of the discriminating extractor for this variant, + /// or `None` if the variant carries no extractor (`Storage`). Returns + /// just the function name — call sites append `(column)` themselves so + /// the accessor is decoupled from any specific column-naming + /// convention. `Eq` resolves to `eql_v3.eq_term`; `Ord` and `OrdOre` + /// both resolve to `eql_v3.ord_term`. + pub const fn extractor_fn(self) -> Option<&'static str> { + match self { + Variant::Storage => None, + Variant::Eq => Some("eql_v3.eq_term"), + Variant::Ord | Variant::OrdOre => Some("eql_v3.ord_term"), + } + } +} + +/// Runtime spec built from `(T, Variant)`. The matrix macro consumes +/// this; nothing here is `const` because `sql_domain` is derived via +/// `format!` from `T::PG_TYPE`. The domains live in the `eql_v3` schema, +/// so `sql_domain` is schema-qualified (e.g. `eql_v3.int4_eq`). +#[derive(Debug, Clone)] +pub struct ScalarDomainSpec { + pub sql_domain: String, + pub variant: Variant, +} + +impl ScalarDomainSpec { + pub fn new(variant: Variant) -> Self { + Self { + sql_domain: format!("eql_v3.{}{}", T::PG_TYPE, variant.suffix()), + variant, + } + } + + pub fn supports_eq(&self) -> bool { + self.variant.supports_eq() + } + + pub fn supports_ord(&self) -> bool { + self.variant.supports_ord() + } + + pub fn extractor_fn(&self) -> Option<&'static str> { + self.variant.extractor_fn() + } +} + +/// SQL string-literal escaping for direct interpolation. +pub fn sql_string_literal(value: &str) -> String { + format!("'{}'", value.replace('\'', "''")) +} + +/// `a op b` and `b op' a` return the same row set when `op'` is the +/// commutator of `op`. Used by the cross-shape arm when the column moves +/// to the right operand. +pub fn commute_op(op: &str) -> &'static str { + match op { + "=" => "=", + "<>" => "<>", + "<" => ">", + "<=" => ">=", + ">" => "<", + ">=" => "<=", + other => panic!("commute_op: unsupported operator {other}"), + } +} + +/// Fetch the payload row keyed by `plaintext` from `T`'s fixture table. +pub async fn fetch_fixture_payload(pool: &PgPool, plaintext: T) -> Result { + let sql = format!( + "SELECT payload::text FROM {table} WHERE plaintext = {lit}", + table = T::fixture_table_name(), + lit = T::to_sql_literal(plaintext), + ); + sqlx::query_scalar(&sql) + .fetch_one(pool) + .await + .with_context(|| { + format!( + "fetching {} payload for plaintext={:?}", + T::fixture_table_name(), + plaintext + ) + }) +} + +/// Sorted plaintexts matching `predicate` against `T`'s fixture table. +async fn scalar_plaintexts_matching( + pool: &PgPool, + predicate: &str, +) -> Result> { + let sql = format!( + "SELECT plaintext FROM {table} WHERE {predicate} ORDER BY plaintext", + table = T::fixture_table_name(), + ); + let mut rows: Vec = sqlx::query_scalar(&sql) + .fetch_all(pool) + .await + .with_context(|| format!("running scalar plaintext query: {sql}"))?; + rows.sort(); + Ok(rows) +} + +/// Run `predicate` against `T`'s fixture; assert plaintexts equal `expected`. +pub async fn assert_scalar_plaintexts( + pool: &PgPool, + domain: &str, + op: &str, + predicate: &str, + expected: &[T], +) -> Result<()> { + let actual = scalar_plaintexts_matching::(pool, predicate).await?; + let mut want = expected.to_vec(); + want.sort(); + assert_eq!( + actual, want, + "domain={domain} operator={op} predicate={predicate} must match expected plaintexts" + ); + Ok(()) +} + +/// Unified raise-assertion: query must error and the message must contain +/// `expected_msg`. Covers blocker raises (`expected_msg = "operator X is +/// not supported for {domain}"`) and native-operator absence +/// (`"operator does not exist"`). Bind slots are `Option<&str>`: `Some` +/// = bind the payload, `None` = bind NULL. +pub async fn assert_raises( + pool: &PgPool, + sql: &str, + binds: &[Option<&str>], + expected_msg: &str, +) -> Result<()> { + let mut q = sqlx::query(sql); + for b in binds { + q = q.bind(*b); + } + let result = q.fetch_one(pool).await; + let err = match result { + Ok(_) => bail!("SQL must raise: {sql}"), + Err(e) => e.to_string(), + }; + if !err.contains(expected_msg) { + bail!("SQL={sql} expected error containing {expected_msg:?}, got {err}"); + } + Ok(()) +} + +/// Unified NULL-result assertion: the query must succeed and return NULL. +/// Used for supported operators where STRICT semantics propagate NULL. +pub async fn assert_null(pool: &PgPool, sql: &str, binds: &[Option<&str>]) -> Result<()> { + let mut q = sqlx::query_scalar::<_, Option>(sql); + for b in binds { + q = q.bind(*b); + } + let result: Option = q + .fetch_one(pool) + .await + .with_context(|| format!("running null-result assertion: {sql}"))?; + if result.is_some() { + bail!("SQL={sql} with NULL operand must yield NULL, got {result:?}"); + } + Ok(()) +} + +/// Blocker error message — the contract every encrypted-domain blocker +/// must satisfy regardless of arg shape or NULL configuration. +pub fn blocker_msg(domain: &str, op: &str) -> String { + format!("operator {op} is not supported for {domain}") +} diff --git a/tests/sqlx/src/scalar_types.rs b/tests/sqlx/src/scalar_types.rs new file mode 100644 index 00000000..6747900a --- /dev/null +++ b/tests/sqlx/src/scalar_types.rs @@ -0,0 +1,58 @@ +//! The single declarative list of scalar types under matrix test — the harness +//! source of truth. +//! +//! To add a scalar encrypted-domain type to the SQLx matrix, add one +//! `token => rust_type` line below (plus the catalog row in `eql-scalars` and +//! the `EqlPlaintext` impl, owned separately — see +//! `docs/reference/adding-a-scalar-encrypted-domain-type.md` §3). A temporal +//! (chrono-backed) scalar adds a trailing `[temporal]` marker +//! (`date => chrono::NaiveDate [temporal]`): it hand-writes its `impl +//! ScalarType` in `scalar_domains.rs` and gets pivot-presence fixture asserts +//! instead of the integer signed-extreme ones. +//! +//! The harness pieces live in three separate compilation contexts (the +//! `eql-tests` lib, the `encrypted_domain` integration-test binary, and the +//! `generate_all_fixtures` integration-test binary), so no single proc-macro +//! invocation can reach all three. The list is held here once, inside the +//! `scalar_types!` `macro_rules!`; each call site invokes `scalar_types!()` +//! to forward it to the matching `eql_tests_macros` proc-macro: +//! +//! - `scalar_type_impls` — `scalar_domains.rs` (lib): the `impl ScalarType` block. +//! - `fixture_modules` — `fixtures/mod.rs` (lib): the `pub mod eql_v3_` modules. +//! - `matrix_suites` — `tests/encrypted_domain/scalars/mod.rs` (test binary): +//! the `ordered_numeric_matrix!` suites. +//! - `fixture_dispatch` — `tests/generate_all_fixtures.rs` (test binary): the +//! `generate_for_token` dispatch fn. +//! +//! The matrix-inventory cross-check (`mise run test:matrix:inventory`) compares +//! the type set the binary emits against `eql-codegen list-types`, so a catalog +//! type missing from this list fails loudly. + +/// Forward the canonical scalar-type list to the `eql_tests_macros` proc-macro +/// selected by `$mode` (see module docs for call sites). +/// +/// This is the only place the harness token set is declared. Keep it in sync +/// with `eql-scalars::CATALOG`; the matrix-inventory cross-check enforces it. +#[macro_export] +macro_rules! scalar_types { + (scalar_type_impls) => { + $crate::scalar_types!(@dispatch emit_scalar_type_impls); + }; + (fixture_modules) => { + $crate::scalar_types!(@dispatch emit_scalar_fixture_modules); + }; + (matrix_suites) => { + $crate::scalar_types!(@dispatch emit_scalar_matrix_suites); + }; + (fixture_dispatch) => { + $crate::scalar_types!(@dispatch emit_fixture_dispatch); + }; + (@dispatch $emitter:ident) => { + $crate::eql_tests_macros::$emitter! { + int4 => i32, + int2 => i16, + int8 => i64, + date => chrono::NaiveDate [temporal], + } + }; +} diff --git a/tests/sqlx/tests/aggregate_tests.rs b/tests/sqlx/tests/aggregate_tests.rs index 9306df26..f942a51e 100644 --- a/tests/sqlx/tests/aggregate_tests.rs +++ b/tests/sqlx/tests/aggregate_tests.rs @@ -1,14 +1,20 @@ //! Aggregate function tests //! -//! Tests COUNT, MAX, MIN with encrypted data including eql_v2.min() and eql_v2.max() +//! Covers native `COUNT` / `GROUP BY` on `eql_v2_encrypted` and the +//! `eql_v2.min(eql_v2_encrypted)` / `eql_v2.max(eql_v2_encrypted)` aggregates +//! on the composite type. Per-domain aggregates +//! (`eql_v2.min(eql_v2__ord)` etc.) are additionally covered by the +//! encrypted-domain test matrix (`tests/sqlx/src/matrix.rs`, instantiated per +//! scalar type from `tests/sqlx/tests/encrypted_domain/scalars/.rs`). use anyhow::Result; use sqlx::PgPool; #[sqlx::test] async fn count_aggregate_on_encrypted_column(pool: PgPool) -> Result<()> { - // Test: COUNT works on encrypted columns (counts non-NULL encrypted values) - + // COUNT on an `eql_v2_encrypted` column is PostgreSQL-native — no + // aggregate declaration is required. Pin that it still counts non-NULL + // encrypted rows on the legacy composite type. let count: i64 = sqlx::query_scalar("SELECT COUNT(e) FROM ore") .fetch_one(&pool) .await?; @@ -68,9 +74,9 @@ async fn min_aggregate_on_encrypted_column(pool: PgPool) -> Result<()> { #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] async fn group_by_with_encrypted_column(pool: PgPool) -> Result<()> { - // Test: GROUP BY works with encrypted data - // Fixture creates 3 distinct encrypted records, each unique - + // GROUP BY on `eql_v2_encrypted` works natively against the fixture's + // distinct payloads. Pin that grouping by an encrypted column returns + // the expected number of groups. let group_count: i64 = sqlx::query_scalar( "SELECT COUNT(*) FROM ( SELECT e, COUNT(*) FROM encrypted GROUP BY e diff --git a/tests/sqlx/tests/build_validation_tests.rs b/tests/sqlx/tests/build_validation_tests.rs index 264f770b..691a5d4a 100644 --- a/tests/sqlx/tests/build_validation_tests.rs +++ b/tests/sqlx/tests/build_validation_tests.rs @@ -138,3 +138,55 @@ fn protect_variant_is_smaller_than_full() { full.len() ); } + +// ============================================================================= +// v3-only Variant Tests (design D9/D11 — self-contained eql_v3 surface) +// ============================================================================= + +#[test] +fn v3_variant_file_exists() { + assert!( + Path::new("../../release/cipherstash-encrypt-v3.sql").exists(), + "v3-only variant installer should exist" + ); +} + +#[test] +fn v3_uninstaller_exists() { + assert!( + Path::new("../../release/cipherstash-encrypt-v3-uninstall.sql").exists(), + "v3-only variant uninstaller should exist" + ); +} + +#[test] +fn v3_variant_creates_eql_v3_schema() { + let sql = read_release_sql("cipherstash-encrypt-v3.sql"); + assert!( + sql.contains("CREATE SCHEMA eql_v3"), + "v3 variant must create the eql_v3 schema" + ); +} + +#[test] +fn v3_variant_has_no_eql_v2_symbol() { + let sql = read_release_sql("cipherstash-encrypt-v3.sql"); + // Reject both schema-qualified refs (`eql_v2.`) and bare v2 entity names + // (`eql_v2_encrypted`, `eql_v2_configuration`, …). Prose mentions like + // "the eql_v2 original is unchanged" in doc comments are still allowed. + assert!( + !sql.contains("eql_v2.") && !sql.contains("eql_v2_"), + "v3 variant must be self-contained (no eql_v2. or eql_v2_ reference)" + ); +} + +#[test] +fn v3_variant_omits_v2_coupled_pin_search_path() { + // D11: the v3 artifact must NOT append tasks/pin_search_path.sql, which is + // eql_v2-coupled (references eql_v2_encrypted / ste_vec_entry). + let sql = read_release_sql("cipherstash-encrypt-v3.sql"); + assert!( + !sql.contains("ste_vec_entry") && !sql.contains("eql_v2_encrypted"), + "v3 variant must not carry the eql_v2-coupled pin_search_path script" + ); +} diff --git a/tests/sqlx/tests/constraint_tests.rs b/tests/sqlx/tests/constraint_tests.rs index baf51a13..7e2871c1 100644 --- a/tests/sqlx/tests/constraint_tests.rs +++ b/tests/sqlx/tests/constraint_tests.rs @@ -3,6 +3,7 @@ //! Tests UNIQUE, NOT NULL, CHECK constraints on encrypted columns use anyhow::Result; +use eql_tests::assert_db_error; use sqlx::PgPool; #[sqlx::test(fixtures(path = "../fixtures", scripts("constraint_tables")))] @@ -25,17 +26,15 @@ async fn unique_constraint_on_encrypted_column(pool: PgPool) -> Result<()> { assert_eq!(count, 1, "Should have 1 record after insert"); // Attempt duplicate insert - let result = sqlx::query( + let err = sqlx::query( "INSERT INTO constrained (unique_field, not_null_field, check_field) VALUES (create_encrypted_json(1, 'hm'), create_encrypted_json(2, 'hm'), create_encrypted_json(2, 'hm'))" ) .execute(&pool) - .await; + .await + .expect_err("UNIQUE constraint should prevent duplicate"); - assert!( - result.is_err(), - "UNIQUE constraint should prevent duplicate" - ); + assert_db_error(&err, "23505", Some("constrained_unique_field_key")); // Verify count unchanged after failed insert let count_after: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM constrained") @@ -51,14 +50,17 @@ async fn unique_constraint_on_encrypted_column(pool: PgPool) -> Result<()> { async fn not_null_constraint_on_encrypted_column(pool: PgPool) -> Result<()> { // Test: NOT NULL constraint enforced (2 assertions) - let result = sqlx::query( + let err = sqlx::query( "INSERT INTO constrained (unique_field) VALUES (create_encrypted_json(2, 'hm'))", ) .execute(&pool) - .await; + .await + .expect_err("NOT NULL constraint should prevent NULL"); - assert!(result.is_err(), "NOT NULL constraint should prevent NULL"); + // NOT NULL is a column attribute, not a named constraint — `constraint()` + // returns None, so only pin the SQLSTATE. + assert_db_error(&err, "23502", None); // Verify no records were inserted let count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM constrained") @@ -74,7 +76,7 @@ async fn not_null_constraint_on_encrypted_column(pool: PgPool) -> Result<()> { async fn check_constraint_on_encrypted_column(pool: PgPool) -> Result<()> { // Test: CHECK constraint enforced (2 assertions) - let result = sqlx::query( + let err = sqlx::query( "INSERT INTO constrained (unique_field, not_null_field, check_field) VALUES ( create_encrypted_json(3, 'hm'), @@ -83,9 +85,10 @@ async fn check_constraint_on_encrypted_column(pool: PgPool) -> Result<()> { )", ) .execute(&pool) - .await; + .await + .expect_err("CHECK constraint should prevent NULL"); - assert!(result.is_err(), "CHECK constraint should prevent NULL"); + assert_db_error(&err, "23514", Some("constrained_check_field_check")); // Verify no records were inserted let count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM constrained") @@ -199,15 +202,13 @@ async fn foreign_key_constraint_with_encrypted(pool: PgPool) -> Result<()> { ); // Attempt to insert child with different encrypted value (should fail FK check) - let different_insert_result = + let err = sqlx::query("INSERT INTO child (id, parent_id) VALUES (2, create_encrypted_json(2, 'hm'))") .execute(&pool) - .await; + .await + .expect_err("FK constraint should reject non-existent parent reference"); - assert!( - different_insert_result.is_err(), - "FK constraint should reject non-existent parent reference" - ); + assert_db_error(&err, "23503", Some("child_parent_id_fkey")); // Verify child count unchanged let final_count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM child") @@ -258,14 +259,17 @@ async fn add_encrypted_constraint_prevents_invalid_data(pool: PgPool) -> Result< .await?; // Now attempt to insert invalid data - should fail - let result = sqlx::query("INSERT INTO encrypted (e) VALUES ('{}'::jsonb::eql_v2_encrypted)") + let err = sqlx::query("INSERT INTO encrypted (e) VALUES ('{}'::jsonb::eql_v2_encrypted)") .execute(&pool) - .await; + .await + .expect_err("Constraint should prevent insert of invalid eql_v2_encrypted (empty JSONB)"); - assert!( - result.is_err(), - "Constraint should prevent insert of invalid eql_v2_encrypted (empty JSONB)" - ); + // `check_encrypted` RAISEs on invalid payloads, so the CHECK constraint + // propagates the underlying SQLSTATE (P0001 raise_exception) rather than + // 23514. The raise message identifies which check failed (missing v, + // invalid v, missing root c/sv, etc.) — that's the value over a bare + // `is_err()` check. + assert_db_error(&err, "P0001", None); // Verify count unchanged after failed insert let final_count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM encrypted") @@ -290,14 +294,17 @@ async fn remove_encrypted_constraint_allows_invalid_data(pool: PgPool) -> Result .await?; // Verify constraint is working - invalid data should be rejected - let result = sqlx::query("INSERT INTO encrypted (e) VALUES ('{}'::jsonb::eql_v2_encrypted)") + let err = sqlx::query("INSERT INTO encrypted (e) VALUES ('{}'::jsonb::eql_v2_encrypted)") .execute(&pool) - .await; + .await + .expect_err("Constraint should prevent insert of invalid eql_v2_encrypted"); - assert!( - result.is_err(), - "Constraint should prevent insert of invalid eql_v2_encrypted" - ); + // `check_encrypted` RAISEs on invalid payloads, so the CHECK constraint + // propagates the underlying SQLSTATE (P0001 raise_exception) rather than + // 23514. The raise message identifies which check failed (missing v, + // invalid v, missing root c/sv, etc.) — that's the value over a bare + // `is_err()` check. + assert_db_error(&err, "P0001", None); // Remove the constraint sqlx::query("SELECT eql_v2.remove_encrypted_constraint('encrypted', 'e')") @@ -342,18 +349,21 @@ async fn version_metadata_validation_on_insert(pool: PgPool) -> Result<()> { .fetch_one(&pool) .await?; - // Attempt to insert without version field - should fail - let result = sqlx::query(&format!( - "INSERT INTO encrypted (e) VALUES ('{}'::jsonb::eql_v2_encrypted)", - encrypted_without_version - )) - .execute(&pool) - .await; + // Attempt to insert without version field - should fail. Bind the payload + // rather than format!-interpolate it — JSONB strings can carry quotes + // and would otherwise need hand-rolled escaping. + let err = sqlx::query("INSERT INTO encrypted (e) VALUES ($1::jsonb::eql_v2_encrypted)") + .bind(&encrypted_without_version) + .execute(&pool) + .await + .expect_err("Insert should fail when version field is missing"); - assert!( - result.is_err(), - "Insert should fail when version field is missing" - ); + // `check_encrypted` RAISEs on invalid payloads, so the CHECK constraint + // propagates the underlying SQLSTATE (P0001 raise_exception) rather than + // 23514. The raise message identifies which check failed (missing v, + // invalid v, missing root c/sv, etc.) — that's the value over a bare + // `is_err()` check. + assert_db_error(&err, "P0001", None); // Create encrypted value with invalid version (v=1 instead of v=2) let encrypted_invalid_version: String = @@ -362,17 +372,18 @@ async fn version_metadata_validation_on_insert(pool: PgPool) -> Result<()> { .await?; // Attempt to insert with invalid version - should fail - let result = sqlx::query(&format!( - "INSERT INTO encrypted (e) VALUES ('{}'::jsonb::eql_v2_encrypted)", - encrypted_invalid_version - )) - .execute(&pool) - .await; + let err = sqlx::query("INSERT INTO encrypted (e) VALUES ($1::jsonb::eql_v2_encrypted)") + .bind(&encrypted_invalid_version) + .execute(&pool) + .await + .expect_err("Insert should fail when version field is invalid (v=1)"); - assert!( - result.is_err(), - "Insert should fail when version field is invalid (v=1)" - ); + // `check_encrypted` RAISEs on invalid payloads, so the CHECK constraint + // propagates the underlying SQLSTATE (P0001 raise_exception) rather than + // 23514. The raise message identifies which check failed (missing v, + // invalid v, missing root c/sv, etc.) — that's the value over a bare + // `is_err()` check. + assert_db_error(&err, "P0001", None); // Insert with valid version (v=2) should succeed sqlx::query("INSERT INTO encrypted (e) VALUES (create_encrypted_json(1))") @@ -455,17 +466,17 @@ async fn check_encrypted_accepts_stevec_payload(pool: PgPool) -> Result<()> { ); // Sanity-check the negative path: a root that carries neither `c` nor - // `sv` is still rejected with the updated error message. - let neither: Result = sqlx::query_scalar( + // `sv` is still rejected with the updated error message. Calling + // `check_encrypted` directly RAISEs (not a CHECK constraint), so + // SQLSTATE P0001 (raise_exception) rather than 23514. + let err = sqlx::query_scalar::<_, bool>( "SELECT eql_v2.check_encrypted('{\"v\": 2, \"i\": {\"t\": \"users\", \"c\": \"x\"}}'::jsonb)", ) .fetch_one(&pool) - .await; + .await + .expect_err("payload with neither c nor sv at root must be rejected"); - assert!( - neither.is_err(), - "payload with neither c nor sv at root must be rejected" - ); + assert_db_error(&err, "P0001", None); Ok(()) } diff --git a/tests/sqlx/tests/encrypted_domain.rs b/tests/sqlx/tests/encrypted_domain.rs new file mode 100644 index 00000000..0ac40b22 --- /dev/null +++ b/tests/sqlx/tests/encrypted_domain.rs @@ -0,0 +1,12 @@ +//! Umbrella integration-test binary for the encrypted-domain type family. +//! +//! Cargo's default discovery picks this file up as a test binary; the +//! module tree under `encrypted_domain/` is pulled in via the `#[path]` +//! attributes below. Legacy tests under `tests/sqlx/tests/*.rs` continue +//! to compile as their own separate binaries. + +#[path = "encrypted_domain/family/mod.rs"] +mod family; + +#[path = "encrypted_domain/scalars/mod.rs"] +mod scalars; diff --git a/tests/sqlx/tests/encrypted_domain/family/inlinability.rs b/tests/sqlx/tests/encrypted_domain/family/inlinability.rs new file mode 100644 index 00000000..8caed2bf --- /dev/null +++ b/tests/sqlx/tests/encrypted_domain/family/inlinability.rs @@ -0,0 +1,381 @@ +//! Global guard for the encrypted-domain inline-critical SQL surface. +//! +//! `tasks/pin_search_path.sql` runs after every build and pins a fixed +//! `search_path` on every `eql_v2`/`eql_v3` function — except the +//! inline-critical ones, which must stay unpinned so the planner can +//! inline them and the documented functional indexes (`eql_v3.eq_term(col)`, +//! `eql_v3.ord_term(col)`, …) engage. +//! +//! The encrypted-domain family is skipped by a structural rule anchored +//! on the *identity predicate*: a `LANGUAGE sql`, `IMMUTABLE` function +//! taking at least one argument typed as a jsonb-backed DOMAIN of the +//! encrypted-domain families — a domain in the `eql_v3` schema (e.g. +//! `eql_v3.int4_eq`) or the legacy `public.eql_v2_*` form. The identity +//! predicate is proconfig-independent — it describes what a function +//! intrinsically IS, not whether it has been pinned. +//! +//! This test is the global net for that rule. It uses the identity +//! predicate VERBATIM and appends one offender filter: +//! `proconfig IS NOT NULL` — a function matching the family shape that +//! nonetheless carries a pinned `search_path`. It asserts that offender +//! set is empty. Because the test and the pin-loop skip clause share the +//! identity predicate exactly (the guard only adds the offender filter), +//! they cannot drift apart on identity. +//! +//! A non-empty result means `pin_search_path.sql` pinned an +//! inline-critical encrypted-domain function — index engagement is +//! silently broken for that type. This is not int4-specific: a missed +//! skip for ANY encrypted-domain type — present or future — fails here, +//! so a new type's author does not have to remember to add a per-type +//! inlinability assertion. + +use anyhow::Result; +use sqlx::PgPool; + +#[sqlx::test] +async fn no_encrypted_domain_inline_critical_function_is_pinned(pool: PgPool) -> Result<()> { + // The identity predicate is shared verbatim with the structural skip + // clause in tasks/pin_search_path.sql: LANGUAGE sql, IMMUTABLE, and + // taking at least one argument typed as an encrypted-domain-family + // domain over jsonb (an `eql_v3.*` domain or the legacy + // `public.eql_v2_*` form). It is proconfig-independent. The ONLY + // addition here is the offender filter `p.proconfig IS NOT NULL` — a + // function that matches the identity predicate but DID get pinned. + // That set must be empty. + let offenders: Vec<(String, String)> = sqlx::query_as( + r#" + SELECT p.oid::regprocedure::text AS signature, + array_to_string(p.proconfig, ', ') AS proconfig + FROM pg_catalog.pg_proc p + JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace + JOIN pg_catalog.pg_language l ON l.oid = p.prolang + WHERE n.nspname IN ('eql_v2', 'eql_v3') + AND l.lanname = 'sql' + AND p.provolatile = 'i' + AND p.proconfig IS NOT NULL + 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' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) + ) + ORDER BY signature + "#, + ) + .fetch_all(&pool) + .await?; + + assert!( + offenders.is_empty(), + "pin_search_path.sql pinned {} inline-critical encrypted-domain \ + SQL function(s) — index engagement is silently broken. \ + Offenders (signature → proconfig):\n{}", + offenders.len(), + offenders + .iter() + .map(|(sig, cfg)| format!(" {sig} → {cfg}")) + .collect::>() + .join("\n"), + ); + Ok(()) +} + +/// Direct guard for the self-contained eql_v3 SEM index-term functions. Unlike +/// the structural guard above (which covers jsonb-domain-arg functions), these +/// take a composite (ore_block_u64_8_256) or raw jsonb (hmac_256/the two +/// per-encrypted-value `jsonb_array_to_*` helpers) arg, so they are NOT caught +/// by the structural pin-skip and need explicit inline_critical allowlisting. +/// If pin_search_path.sql pins any of them, v3 functional-index inlining +/// silently regresses to Seq Scan — this test fails instead. +/// +/// `jsonb_array_to_bytea_array(jsonb)` and +/// `jsonb_array_to_ore_block_u64_8_256(jsonb)` are included here: both take a +/// bare `jsonb` arg (not a jsonb-backed encrypted DOMAIN), so the structural +/// skip in tasks/pin_search_path.sql does not recognise them — they are kept +/// unpinned by the `eql-inline-critical` COMMENT marker instead. This test +/// asserts the unpinned + inlinable-SQL state directly; the companion +/// `eql_v3_sem_inline_critical_functions_carry_marker` test below asserts the +/// marker itself, so an edit that drops the marker (or a pin_search_path.sql +/// refactor that stops honouring it) fails CI even though both checks live in +/// separate tests. +#[sqlx::test] +async fn eql_v3_sem_inline_critical_functions_are_unpinned(pool: PgPool) -> Result<()> { + let rows: Vec<(String,)> = sqlx::query_as( + r#" + SELECT p.proname || '(' || pg_catalog.pg_get_function_arguments(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.pronargs = 2 AND p.proname IN ( + 'ore_block_u64_8_256_eq','ore_block_u64_8_256_neq', + 'ore_block_u64_8_256_lt','ore_block_u64_8_256_lte', + 'ore_block_u64_8_256_gt','ore_block_u64_8_256_gte')) + OR (p.pronargs = 1 AND p.proname IN ( + 'hmac_256', + 'jsonb_array_to_bytea_array', + 'jsonb_array_to_ore_block_u64_8_256') + AND p.proargtypes[0] = 'jsonb'::regtype) + ) + AND ( + -- offender: pinned search_path, or not inlinable SQL/IMMUTABLE + EXISTS (SELECT 1 FROM unnest(coalesce(p.proconfig,'{}'::text[])) c WHERE c LIKE 'search_path=%') + OR p.provolatile <> 'i' + OR p.prolang <> (SELECT l.oid FROM pg_catalog.pg_language l WHERE l.lanname = 'sql') + ) + ORDER BY 1 + "#, + ) + .fetch_all(&pool) + .await?; + + assert!( + rows.is_empty(), + "eql_v3 SEM inline-critical functions must stay unpinned + inlinable SQL; offenders: {:?}", + rows.iter().map(|r| &r.0).collect::>() + ); + Ok(()) +} + +/// Companion guard for the two bare-`jsonb` per-encrypted-value helpers +/// (`jsonb_array_to_bytea_array`, `jsonb_array_to_ore_block_u64_8_256`). The +/// unpinned state asserted above is only DURABLE because each helper carries an +/// `eql-inline-critical` COMMENT marker that `tasks/pin_search_path.sql` honours +/// (it skips pinning functions whose `pg_description` matches +/// `'eql-inline-critical%'`). Neither helper is caught by the structural +/// jsonb-domain skip, so the marker is the ONLY thing keeping them unpinned — +/// an edit that removes the marker, or a pin_search_path.sql refactor that drops +/// the marker handling, would silently re-pin them and break inlining. This test +/// asserts the marker is present (and the helpers are SQL/IMMUTABLE) so that +/// failure surfaces here. +#[sqlx::test] +async fn eql_v3_sem_inline_critical_helpers_carry_marker(pool: PgPool) -> Result<()> { + // Each expected helper must appear with a present inline-critical marker + // and be inlinable SQL/IMMUTABLE. Any helper that is missing, unmarked, or + // not inlinable SQL/IMMUTABLE is an offender. + let offenders: Vec<(String, Option, String, String)> = sqlx::query_as( + r#" + WITH expected(proname) AS ( + VALUES ('jsonb_array_to_bytea_array'), + ('jsonb_array_to_ore_block_u64_8_256') + ) + SELECT e.proname AS proname, + d.description AS marker, + l.lanname AS prolang, + p.provolatile::text AS provolatile + FROM expected e + LEFT JOIN pg_catalog.pg_proc p + ON p.proname = e.proname + AND p.pronamespace = 'eql_v3'::regnamespace + AND p.pronargs = 1 + AND p.proargtypes[0] = 'jsonb'::regtype + LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang + LEFT JOIN pg_catalog.pg_description d + ON d.objoid = p.oid AND d.classoid = 'pg_proc'::regclass + WHERE p.oid IS NULL + OR d.description IS NULL + OR d.description NOT LIKE 'eql-inline-critical%' + OR l.lanname IS DISTINCT FROM 'sql' + OR p.provolatile IS DISTINCT FROM 'i' + ORDER BY e.proname + "#, + ) + .fetch_all(&pool) + .await?; + + assert!( + offenders.is_empty(), + "eql_v3 SEM bare-jsonb helpers must carry an `eql-inline-critical` COMMENT \ + marker and be inlinable SQL/IMMUTABLE — the marker is what keeps \ + pin_search_path.sql from pinning them. Offenders \ + (proname, marker, prolang, provolatile): {offenders:#?}" + ); + Ok(()) +} + +#[sqlx::test] +async fn every_inline_critical_eligible_domain_has_inline_critical_functions( + pool: PgPool, +) -> Result<()> { + // Stronger than a bare `count > 0`: if a future change accidentally + // narrows the structural predicate (e.g. hard-codes `int4_%`), a + // `count > 0` assertion would still pass while int8/bool/date + // domains silently lose inline-critical coverage. Instead, assert + // that EVERY inline-critical-eligible domain (any encrypted-domain + // family domain over jsonb — `eql_v3.*` or legacy `public.eql_v2_*` — + // that carries a capability suffix — `_eq`, `_ord`, `_ord_ore`) + // appears as an argument type of at least one inline-critical + // function. + // + // Storage-only variants (the bare `eql_v3.` / `eql_v2_` domain, + // with no capability suffix) intentionally have NO inline-critical + // surface and are excluded from the eligibility set. + let unbound: Vec = sqlx::query_scalar( + r#" + SELECT dt.typname + 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 + WHERE dt.typtype = 'd' + AND bt.typname = 'jsonb' + AND ( + dn.nspname = 'eql_v3' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) + AND ( + dt.typname LIKE '%\_eq' + OR dt.typname LIKE '%\_ord' + OR dt.typname LIKE '%\_ord\_ore' + ) + AND NOT EXISTS ( + SELECT 1 + FROM pg_catalog.pg_proc p + JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace + JOIN pg_catalog.pg_language l ON l.oid = p.prolang + WHERE n.nspname IN ('eql_v2', 'eql_v3') + AND l.lanname = 'sql' + AND p.provolatile = 'i' + AND dt.oid = ANY(p.proargtypes::oid[]) + ) + ORDER BY dt.typname + "#, + ) + .fetch_all(&pool) + .await?; + + assert!( + unbound.is_empty(), + "the following inline-critical-eligible domains have NO \ + inline-critical function bound — index engagement is broken \ + for them: {unbound:?}" + ); + Ok(()) +} + +/// Encrypted-domain blockers must be `LANGUAGE plpgsql` and **never** +/// `STRICT`. A LANGUAGE sql blocker is inlinable (the planner can elide +/// it when the result is provably unused); a STRICT blocker returns NULL +/// on a NULL argument, silently bypassing the RAISE. Either footgun +/// re-enables an operator the storage variant exists to block. +/// +/// This is a structural guard that does NOT depend on `eql_v2.lints()` — +/// a regression to the lint catalog itself cannot hide a regression to +/// the blocker surface from this test. +#[sqlx::test] +async fn encrypted_domain_blockers_are_plpgsql_and_non_strict(pool: PgPool) -> Result<()> { + let offenders: Vec<(String, String, bool)> = sqlx::query_as( + r#" + SELECT p.oid::regprocedure::text AS signature, + l.lanname, + p.proisstrict + FROM pg_catalog.pg_proc p + JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace + JOIN pg_catalog.pg_language l ON l.oid = p.prolang + WHERE n.nspname IN ('eql_v2', 'eql_v3') + AND (p.prosrc LIKE '%encrypted_domain_unsupported_bool%' + 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' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) + ) + AND (l.lanname <> 'plpgsql' OR p.proisstrict) + ORDER BY signature + "#, + ) + .fetch_all(&pool) + .await?; + + assert!( + offenders.is_empty(), + "encrypted-domain blockers must be LANGUAGE plpgsql and non-STRICT. \ + Offenders (signature, language, isstrict): {offenders:#?}" + ); + Ok(()) +} + +/// No encrypted-domain family domain may be derived from another family +/// domain — operators resolve against the ultimate base type, so a derived +/// domain inherits jsonb's operator surface and not the base domain's +/// blockers. All family domains must be defined directly over jsonb. +#[sqlx::test] +async fn no_eql_v2_domain_is_derived_from_another_eql_v2_domain(pool: PgPool) -> Result<()> { + let offenders: Vec<(String, String)> = sqlx::query_as( + r#" + SELECT format('%I.%I', dn.nspname, dt.typname) AS derived, + format('%I.%I', bn.nspname, bt.typname) AS base + 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' + OR (dn.nspname = 'public' AND dt.typname LIKE 'eql_v2\_%') + ) + AND bt.typtype = 'd' + AND ( + bn.nspname = 'eql_v3' + OR (bn.nspname = 'public' AND bt.typname LIKE 'eql_v2\_%') + ) + ORDER BY derived + "#, + ) + .fetch_all(&pool) + .await?; + + assert!( + offenders.is_empty(), + "encrypted-domain family domains must be defined directly over jsonb, \ + not derived from another family domain. Offenders (derived, base): {offenders:#?}" + ); + Ok(()) +} + +/// No operator class may be declared `FOR TYPE` on an encrypted-domain +/// family domain. Opclasses on domains bypass the operator-resolution that +/// storage blockers depend on. The recommended index pattern is a functional +/// index on the extractor (e.g. `eql_v3.eq_term(col)`). +#[sqlx::test] +async fn no_opclass_targets_eql_v2_domain(pool: PgPool) -> Result<()> { + let offenders: Vec<(String, String)> = sqlx::query_as( + r#" + SELECT format('%I.%I', cn.nspname, oc.opcname) AS opclass, + format('%I.%I', tn.nspname, t.typname) AS for_type + 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' + OR (tn.nspname = 'public' AND t.typname LIKE 'eql_v2\_%') + ) + ORDER BY opclass + "#, + ) + .fetch_all(&pool) + .await?; + + assert!( + offenders.is_empty(), + "no operator class may target an encrypted-domain family domain — use a \ + functional index on the extractor instead. Offenders (opclass, for_type): {offenders:#?}" + ); + Ok(()) +} diff --git a/tests/sqlx/tests/encrypted_domain/family/jsonb_operator_surface.rs b/tests/sqlx/tests/encrypted_domain/family/jsonb_operator_surface.rs new file mode 100644 index 00000000..b10a848c --- /dev/null +++ b/tests/sqlx/tests/encrypted_domain/family/jsonb_operator_surface.rs @@ -0,0 +1,88 @@ +//! Structural guard for the blocked native-jsonb operator enumeration. +//! +//! The storage-only domains (`eql_v3.int4`, future scalars) promise that +//! *every* native jsonb operator is blocked, so an encrypted column can never +//! fall through to plaintext-jsonb semantics. That promise rests on three +//! hand-maintained lists in `tasks/codegen/operator_surface.py` +//! (`SYMMETRIC_OPERATORS`, `PATH_OPERATORS`, `BLOCKER_ONLY_OPERATORS`), whose +//! union is `KNOWN_JSONB_OPERATORS`. +//! +//! Those lists are an *enumeration*, not a structural guarantee: a future PG +//! version could add a jsonb operator that nobody adds here, and it would +//! silently route to native jsonb behaviour. This test closes that gap by +//! asking the live catalog which *native* operators touch `jsonb` and failing +//! if any symbol is absent from the known union. EQL's own cross-type operators +//! on the legacy `eql_v2_encrypted` composite (which also take a jsonb operand, +//! e.g. `~~` / `~~*`) are excluded — they are not native and are unreachable +//! from a storage scalar domain. +//! +//! Source of truth: `tasks/codegen/operator_surface.py::KNOWN_JSONB_OPERATORS` +//! (asserted complete by `tasks/codegen/test_operator_surface.py`). The set +//! below is hardcoded — the lowest-friction bridge from a Python constant to a +//! Rust test — and must be kept in sync with that module. If you add an +//! operator there, add it here; the Python test pins the union so the two can +//! only drift in this file. + +use anyhow::Result; +use sqlx::PgPool; + +/// Mirror of `KNOWN_JSONB_OPERATORS` in +/// `tasks/codegen/operator_surface.py`. Keep in sync with that module. +const KNOWN_JSONB_OPERATORS: &[&str] = &[ + // symmetric (supported wrappers) + "=", "<>", "<", "<=", ">", ">=", "@>", "<@", // + // path + "->", "->>", // + // blocker-only native jsonb fallbacks + "?", "?|", "?&", "@?", "@@", "#>", "#>>", "-", "#-", "||", +]; + +#[sqlx::test] +async fn every_native_jsonb_operator_is_known_to_the_generator(pool: PgPool) -> Result<()> { + // Distinct operator symbols whose left OR right argument is `jsonb` — the + // native surface a value typed as a jsonb-backed domain can reach via + // operator resolution against the ultimate base type. + // + // Exclude EQL's own cross-type operators on the legacy `eql_v2_encrypted` + // composite (e.g. `eql_v2_encrypted ~~ jsonb`, `jsonb ~~ eql_v2_encrypted`). + // They take a jsonb operand but are NOT native plaintext-jsonb operators and + // are unreachable from a storage scalar domain: a `eql_v2_int4` operand + // resolves to the domain / its jsonb base, never to `eql_v2_encrypted`, so + // `col ~~ x` finds no operator (asserted by the matrix `native_absent_ops` + // arm). Matching on `typname` is search_path-independent and a harmless + // no-op when the type is absent (e.g. the Protect build variant). + let native: Vec = sqlx::query_scalar( + r#" + SELECT DISTINCT o.oprname + FROM pg_catalog.pg_operator o + WHERE (o.oprleft = 'jsonb'::regtype OR o.oprright = 'jsonb'::regtype) + AND o.oprleft NOT IN (SELECT oid FROM pg_catalog.pg_type WHERE typname = 'eql_v2_encrypted') + AND o.oprright NOT IN (SELECT oid FROM pg_catalog.pg_type WHERE typname = 'eql_v2_encrypted') + ORDER BY 1 + "#, + ) + .fetch_all(&pool) + .await?; + + assert!( + !native.is_empty(), + "expected pg_operator to expose jsonb operators; query returned none" + ); + + let missing: Vec<&String> = native + .iter() + .filter(|sym| !KNOWN_JSONB_OPERATORS.contains(&sym.as_str())) + .collect(); + + assert!( + missing.is_empty(), + "PostgreSQL exposes jsonb operator(s) not enumerated in \ + tasks/codegen/operator_surface.py (KNOWN_JSONB_OPERATORS): {missing:#?}. \ + A storage-only encrypted domain would route these to native \ + plaintext-jsonb semantics instead of an EQL blocker. Add each symbol \ + to the appropriate list in operator_surface.py (and to the mirror in \ + this test) and regenerate the SQL surface." + ); + + Ok(()) +} diff --git a/tests/sqlx/tests/encrypted_domain/family/mod.rs b/tests/sqlx/tests/encrypted_domain/family/mod.rs new file mode 100644 index 00000000..892842a2 --- /dev/null +++ b/tests/sqlx/tests/encrypted_domain/family/mod.rs @@ -0,0 +1,8 @@ +//! Family-level tests: invariants that apply across every scalar type in +//! the encrypted-domain family (not int4-specific). + +pub mod inlinability; +pub mod jsonb_operator_surface; +pub mod mutations; +pub mod sem; +pub mod support; diff --git a/tests/sqlx/tests/encrypted_domain/family/mutations.rs b/tests/sqlx/tests/encrypted_domain/family/mutations.rs new file mode 100644 index 00000000..d78d5520 --- /dev/null +++ b/tests/sqlx/tests/encrypted_domain/family/mutations.rs @@ -0,0 +1,428 @@ +//! Negative controls (mutation tests) for the scalar-domain matrix. +//! +//! A green matrix proves the SUT behaves correctly *today*, but it cannot +//! prove the matrix arms would catch a regression — an arm could be +//! vacuous and still pass. Each test here applies one surgical mutation to +//! the installed `eql_v2` schema and asserts that the property a specific +//! matrix arm guards now flips. If a mutation does NOT flip the property, +//! that arm has no teeth. +//! +//! Mechanism: `CREATE OR REPLACE FUNCTION` keeps the function oid, so the +//! operators / aggregates that reference it keep resolving to the (now +//! mutated) body — that's what lets us re-route a comparison or disable a +//! blocker without touching operator definitions. Each `#[sqlx::test]` +//! gets its own fresh database (EQL pre-installed via the auto-applied +//! `migrations/001_install_eql.sql`), so the mutation is discarded when the +//! per-test DB is dropped — no cleanup, no rebuild. +//! +//! Pattern per test: assert the baseline property holds, mutate, assert it +//! now breaks. The baseline assertion is load-bearing — it proves the +//! probe is non-vacuous before the mutation. + +use anyhow::{ensure, Result}; +use eql_tests::{ + assert_null, assert_raises, blocker_msg, fetch_fixture_payload, ScalarType, PLACEHOLDER_PAYLOAD, +}; +use sqlx::PgPool; + +/// Apply one DDL mutation to the installed schema. +async fn mutate(pool: &PgPool, ddl: &str) -> Result<()> { + sqlx::query(ddl).execute(pool).await?; + Ok(()) +} + +// 1. Storage `=` blocker — disabling it lets the storage variant compare +// equal. Proves the `blocker` arm (and `typed_column_blocker`) would +// catch a blocker that silently stopped raising. +#[sqlx::test] +async fn disabling_storage_eq_blocker_flips_blocker_arm(pool: PgPool) -> Result<()> { + let sql = "SELECT $1::jsonb::eql_v3.int4 = $2::jsonb::eql_v3.int4"; + + // Baseline: the storage `=` blocker raises. + assert_raises( + &pool, + sql, + &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], + &blocker_msg("eql_v3.int4", "="), + ) + .await?; + + // Mutation: replace the plpgsql blocker with an inlinable SQL body that + // returns true. CREATE OR REPLACE keeps the oid, so the `=` operator on + // (eql_v3.int4, eql_v3.int4) now resolves to this no-raise body. + mutate( + &pool, + "CREATE OR REPLACE FUNCTION eql_v3.eq(a eql_v3.int4, b eql_v3.int4) \ + RETURNS boolean LANGUAGE sql IMMUTABLE PARALLEL SAFE AS $$ SELECT true $$", + ) + .await?; + + // Post: the operator returns true instead of raising — arm has teeth. + let result: Option = sqlx::query_scalar(sql) + .bind(PLACEHOLDER_PAYLOAD) + .bind(PLACEHOLDER_PAYLOAD) + .fetch_one(&pool) + .await?; + ensure!( + result == Some(true), + "after disabling the storage `=` blocker, `=` must return true (got {result:?})" + ); + Ok(()) +} + +// 2. Planner-metadata RESTRICT selectivity — unsetting it makes the +// `planner_metadata` arm's `oprrest <> 0` check report false. (COMMUTATOR +// cannot be unset via ALTER, so RESTRICT is the pragmatic teeth probe for +// this arm.) +#[sqlx::test] +async fn unsetting_restrict_flips_planner_metadata_arm(pool: PgPool) -> Result<()> { + async fn restrict_present(pool: &PgPool) -> Result { + let present: bool = sqlx::query_scalar( + r#" + SELECT o.oprrest::oid <> 0 + FROM pg_catalog.pg_operator o + JOIN pg_catalog.pg_type lt ON lt.oid = o.oprleft + JOIN pg_catalog.pg_type rt ON rt.oid = o.oprright + WHERE o.oprname = '=' + AND lt.typname = 'int4_ord' + AND rt.typname = 'int4_ord' + "#, + ) + .fetch_one(pool) + .await?; + Ok(present) + } + + // Baseline: `=` on (ord, ord) declares a RESTRICT estimator. + ensure!( + restrict_present(&pool).await?, + "baseline: `=` on eql_v3.int4_ord must declare a RESTRICT estimator" + ); + + // Mutation: unset RESTRICT. DROP OPERATOR would hit COMMUTATOR/NEGATOR + // dependency links; ALTER ... SET (RESTRICT = NONE) avoids that. + mutate( + &pool, + "ALTER OPERATOR = (eql_v3.int4_ord, eql_v3.int4_ord) SET (RESTRICT = NONE)", + ) + .await?; + + // Post: the planner-metadata check now reports false — arm has teeth. + ensure!( + !restrict_present(&pool).await?, + "after SET (RESTRICT = NONE), the planner-metadata check must report false" + ); + Ok(()) +} + +// 3. `_ord` equality must route through `ord_term` (`ob`), never HMAC. +// Rerouting it through `hmac_256` (`hm`) over hm-stripped rows makes `=` +// stop matching. Proves the `ord_routes_through_ob` arm has teeth. +#[sqlx::test(fixtures(path = "../../../fixtures", scripts("eql_v2_int4")))] +async fn rerouting_ord_eq_through_hm_flips_ord_routes_arm(pool: PgPool) -> Result<()> { + // Strip `hm` per-row inline; the `_ord` CHECK only requires `ob`, so the + // cast still succeeds. The pivot is likewise hm-stripped. + let pivot: i32 = 42; + let pivot_payload: String = sqlx::query_scalar(&format!( + "SELECT (payload - 'hm')::text FROM fixtures.eql_v2_int4 WHERE plaintext = {pivot}", + )) + .fetch_one(&pool) + .await?; + + let count_sql = "SELECT count(*) FROM fixtures.eql_v2_int4 \ + WHERE (payload - 'hm')::eql_v3.int4_ord = $1::jsonb::eql_v3.int4_ord"; + + // Baseline: with `hm` stripped, `=` still matches the pivot via `ord_term` + // (the `ob` term survives) — exactly one row. + let baseline: i64 = sqlx::query_scalar(count_sql) + .bind(&pivot_payload) + .fetch_one(&pool) + .await?; + ensure!( + baseline == 1, + "baseline: `_ord` `=` must match exactly the pivot via ob with hm stripped (got {baseline})" + ); + + // Mutation: reroute `_ord` `=` through HMAC. `eql_v3.hmac_256(jsonb)` is + // STRICT and the `hm` key is absent, so it yields NULL and `=` matches + // nothing. + mutate( + &pool, + "CREATE OR REPLACE FUNCTION eql_v3.eq(a eql_v3.int4_ord, b eql_v3.int4_ord) \ + RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE \ + AS $$ SELECT eql_v3.hmac_256(a::jsonb) = eql_v3.hmac_256(b::jsonb) $$", + ) + .await?; + + // Post: routing through the absent `hm` matches zero rows — arm has teeth. + let mutated: i64 = sqlx::query_scalar(count_sql) + .bind(&pivot_payload) + .fetch_one(&pool) + .await?; + ensure!( + mutated == 0, + "after rerouting `_ord` `=` through hm, it must match zero hm-stripped rows (got {mutated})" + ); + Ok(()) +} + +// 4. Supported `=` on `_eq` is STRICT — it must propagate NULL. Dropping +// STRICT (and returning non-NULL) makes `x = NULL` return a value. Proves +// the `supported_null` arm has teeth. +#[sqlx::test] +async fn dropping_strict_on_eq_flips_supported_null_arm(pool: PgPool) -> Result<()> { + let sql = "SELECT $1::jsonb::eql_v3.int4_eq = $2::jsonb::eql_v3.int4_eq"; + + // Baseline: STRICT `=` propagates NULL when one side is NULL. + assert_null(&pool, sql, &[Some(PLACEHOLDER_PAYLOAD), None]).await?; + + // Mutation: drop STRICT and return a constant non-NULL. CREATE OR REPLACE + // keeps the oid; the operator now ignores NULL semantics. + mutate( + &pool, + "CREATE OR REPLACE FUNCTION eql_v3.eq(a eql_v3.int4_eq, b eql_v3.int4_eq) \ + RETURNS boolean LANGUAGE sql IMMUTABLE PARALLEL SAFE AS $$ SELECT true $$", + ) + .await?; + + // Post: `x = NULL` returns true instead of NULL — arm has teeth. + let result: Option = sqlx::query_scalar(sql) + .bind(PLACEHOLDER_PAYLOAD) + .bind(Option::<&str>::None) + .fetch_one(&pool) + .await?; + ensure!( + result == Some(true), + "after dropping STRICT on `_eq` `=`, `x = NULL` must return true, not NULL (got {result:?})" + ); + Ok(()) +} + +// 5. Ord `<` correctness routes through `eql_v3.lt`. Turning `lt` into a +// blocker makes `<` raise — proving the ord `<` correctness arm has teeth. +// Crucially, ORDER BY routes through `ord_term`, NOT `<`, so it must stay +// green here. This is the #5-vs-#7 split: #5 attacks `<`, #7 attacks the +// sort key. Blocking `<` alone must not disturb ORDER BY. +#[sqlx::test(fixtures(path = "../../../fixtures", scripts("eql_v2_int4")))] +async fn blocking_lt_flips_lt_arm_but_not_order_by(pool: PgPool) -> Result<()> { + let lt_sql = "SELECT $1::jsonb::eql_v3.int4_ord < $2::jsonb::eql_v3.int4_ord"; + let order_by_sql = "SELECT plaintext FROM fixtures.eql_v2_int4 \ + ORDER BY eql_v3.ord_term(payload::eql_v3.int4_ord) ASC"; + + let mut ascending: Vec = ::fixture_values().to_vec(); + ascending.sort(); + + // Baseline: `<` works (no raise) and ORDER BY is plaintext-sorted. + let lt_baseline: Option = sqlx::query_scalar(lt_sql) + .bind(PLACEHOLDER_PAYLOAD) + .bind(PLACEHOLDER_PAYLOAD) + .fetch_one(&pool) + .await?; + ensure!( + lt_baseline.is_some(), + "baseline: `_ord` `<` must return a boolean (got {lt_baseline:?})" + ); + let order_baseline: Vec = sqlx::query_scalar(order_by_sql).fetch_all(&pool).await?; + ensure!( + order_baseline == ascending, + "baseline: ORDER BY ord_term ASC must be plaintext-sorted" + ); + + // Mutation: turn `eql_v3.lt(_ord, _ord)` into a blocker. Must be + // LANGUAGE plpgsql and non-STRICT so the RAISE always fires. + mutate( + &pool, + "CREATE OR REPLACE FUNCTION eql_v3.lt(a eql_v3.int4_ord, b eql_v3.int4_ord) \ + RETURNS boolean LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE \ + AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4_ord', '<'); END; $$", + ) + .await?; + + // Post: `<` now raises — the ord `<` arm has teeth. + assert_raises( + &pool, + lt_sql, + &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], + &blocker_msg("eql_v3.int4_ord", "<"), + ) + .await?; + + // Post: ORDER BY is UNCHANGED — it routes through ord_term, not `<`. + // This is the whole point of separating #5 from #7. + let order_after: Vec = sqlx::query_scalar(order_by_sql).fetch_all(&pool).await?; + ensure!( + order_after == ascending, + "blocking `<` must NOT disturb ORDER BY (it routes through ord_term); got {order_after:?}" + ); + Ok(()) +} + +// 6. `_eq` equality must route through `eq_term` (`hm`), never ORE — the +// mirror of #3 for the eq path. Rerouting it through +// `ore_block_u64_8_256` (`ob`) over ob-stripped rows breaks equality. +// +// Two notes on why this is shaped differently from the plan's literal +// "returns 0 where forward expects 1": +// - The fixture payloads carry BOTH `hm` and `ob`, so rerouting `_eq` +// `=` through ORE on the RAW fixture would still match (both terms are +// injective per plaintext) — vacuous. Stripping `ob` forces the +// rerouted operator onto an absent term, exactly as #3 strips `hm`. +// - `ore_block_u64_8_256(jsonb)` RAISES on an absent `ob` ("Expected an +// ore index (ob)"), whereas `hmac_256(jsonb)` returns NULL on an absent +// `hm`. So the eq path breaks via a raise, not a 0-count. Either way the +// correct hm-routed equality matches and the rerouted one does not. +#[sqlx::test(fixtures(path = "../../../fixtures", scripts("eql_v2_int4")))] +async fn rerouting_eq_eq_through_ob_flips_eq_arm(pool: PgPool) -> Result<()> { + // Strip `ob` per-row inline; the `_eq` CHECK only requires `hm`, so the + // cast still succeeds. The pivot is likewise ob-stripped. + let pivot: i32 = 42; + let pivot_payload: String = sqlx::query_scalar(&format!( + "SELECT (payload - 'ob')::text FROM fixtures.eql_v2_int4 WHERE plaintext = {pivot}", + )) + .fetch_one(&pool) + .await?; + + let count_sql = "SELECT count(*) FROM fixtures.eql_v2_int4 \ + WHERE (payload - 'ob')::eql_v3.int4_eq = $1::jsonb::eql_v3.int4_eq"; + + // Baseline: with `ob` stripped, `=` still matches the pivot via `eq_term` + // (the `hm` term survives) — exactly one row. + let baseline: i64 = sqlx::query_scalar(count_sql) + .bind(&pivot_payload) + .fetch_one(&pool) + .await?; + ensure!( + baseline == 1, + "baseline: `_eq` `=` must match exactly the pivot via hm with ob stripped (got {baseline})" + ); + + // Mutation: reroute `_eq` `=` through ORE. The `ob` key is absent, so + // `eql_v3.ore_block_u64_8_256(jsonb)` raises rather than matching. + mutate( + &pool, + "CREATE OR REPLACE FUNCTION eql_v3.eq(a eql_v3.int4_eq, b eql_v3.int4_eq) \ + RETURNS boolean LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE \ + AS $$ SELECT eql_v3.ore_block_u64_8_256(a::jsonb) = eql_v3.ore_block_u64_8_256(b::jsonb) $$", + ) + .await?; + + // Post: routing through the absent `ob` raises ("Expected an ore index") + // instead of matching the pivot — equality is broken, arm has teeth. + let err = sqlx::query_scalar::<_, i64>(count_sql) + .bind(&pivot_payload) + .fetch_one(&pool) + .await + .expect_err("rerouting `_eq` `=` through the absent ob term must fail") + .to_string(); + ensure!( + err.contains("Expected an ore index"), + "rerouted `_eq` `=` must fail on the absent ob term; got: {err}" + ); + Ok(()) +} + +// 7. ORDER BY routes through `ord_term` — the sort key, NOT `<` (see #5). +// Collapsing `ord_term` to a constant makes ORDER BY DESC no longer +// plaintext-sorted. Proves the ORDER BY arm has teeth independently of the +// `<` arm. +// +// A constant key collapses ASC and DESC to the same heap order. The +// fixture inserts rows in ascending plaintext (id 1..n), so a seq scan +// returns ascending order — which can never equal the descending +// expectation. Asserting against DESC therefore detects the collapse +// regardless of heap order (the ascending-fixture caveat from the plan). +#[sqlx::test(fixtures(path = "../../../fixtures", scripts("eql_v2_int4")))] +async fn collapsing_ord_term_flips_order_by_arm(pool: PgPool) -> Result<()> { + let order_by_desc = "SELECT plaintext FROM fixtures.eql_v2_int4 \ + ORDER BY eql_v3.ord_term(payload::eql_v3.int4_ord) DESC"; + + let mut descending: Vec = ::fixture_values().to_vec(); + descending.sort(); + descending.reverse(); + + // Baseline: ORDER BY ord_term DESC is plaintext-descending. + let baseline: Vec = sqlx::query_scalar(order_by_desc).fetch_all(&pool).await?; + ensure!( + baseline == descending, + "baseline: ORDER BY ord_term DESC must be plaintext-descending" + ); + + // Mutation: collapse ord_term to a constant ORE block. Use a REAL fixture + // payload as the source (guaranteed to construct a valid ore_block) and a + // unique dollar-quote tag so the embedded jsonb literal can't break the + // function body. + let const_payload = fetch_fixture_payload::(&pool, 0).await?; + let ddl = format!( + "CREATE OR REPLACE FUNCTION eql_v3.ord_term(a eql_v3.int4_ord) \ + RETURNS eql_v3.ore_block_u64_8_256 LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE \ + AS $mutbody$ SELECT eql_v3.ore_block_u64_8_256('{esc}'::jsonb) $mutbody$", + esc = const_payload.replace('\'', "''"), + ); + mutate(&pool, &ddl).await?; + + // Post: every row now sorts equal, so DESC collapses to heap (ascending) + // order and can no longer equal the descending expectation — arm has teeth. + let mutated: Vec = sqlx::query_scalar(order_by_desc).fetch_all(&pool).await?; + ensure!( + mutated != descending, + "after collapsing ord_term to a constant, ORDER BY DESC must no longer be \ + plaintext-descending (got {mutated:?})" + ); + Ok(()) +} + +// 8. ORDER BY NULLS placement depends on `ord_term` being STRICT: a NULL domain +// value yields a NULL sort key, so `NULLS LAST` parks those rows at the tail. +// Dropping STRICT (coalescing a NULL input to a real payload) gives NULL-valued +// rows a concrete sort key, so they stop clustering at the end. Proves the +// ORDER BY NULLS arm has teeth on the NULL-placement dimension — one #5 (block +// `lt`) and #7 (collapse `ord_term`) do not exercise, since both run on the +// NULL-free fixture. A UNION ALL subquery supplies the NULL rows inline, so no +// session-local temp table is needed and the global `mutate()` stays valid. +#[sqlx::test(fixtures(path = "../../../fixtures", scripts("eql_v2_int4")))] +async fn making_ord_term_non_strict_flips_order_by_nulls_arm(pool: PgPool) -> Result<()> { + const NULL_ROWS: usize = 3; + let order_by = format!( + "SELECT plaintext FROM ( \ + SELECT plaintext, payload::eql_v3.int4_ord AS value FROM fixtures.eql_v2_int4 \ + UNION ALL \ + SELECT NULL::int4, NULL::eql_v3.int4_ord FROM generate_series(1, {NULL_ROWS}) \ + ) s \ + ORDER BY eql_v3.ord_term(value) ASC NULLS LAST" + ); + + let tail_all_none = + |rows: &[Option]| rows.iter().rev().take(NULL_ROWS).all(|x| x.is_none()); + + // Baseline: STRICT ord_term -> NULL value -> NULL sort key -> NULLS LAST + // parks the NULL-valued rows at the tail. + let baseline: Vec> = sqlx::query_scalar(&order_by).fetch_all(&pool).await?; + ensure!( + tail_all_none(&baseline), + "baseline: the {NULL_ROWS} NULL-valued rows must cluster at the tail under \ + NULLS LAST (got {baseline:?})" + ); + + // Mutation: drop STRICT and coalesce a NULL input to a REAL fixture payload, + // so NULL-valued rows gain a concrete (non-NULL) sort key; non-NULL rows are + // unchanged. Unique dollar-quote tag guards the embedded jsonb literal. + let const_payload = fetch_fixture_payload::(&pool, 0).await?; + let ddl = format!( + "CREATE OR REPLACE FUNCTION eql_v3.ord_term(a eql_v3.int4_ord) \ + RETURNS eql_v3.ore_block_u64_8_256 LANGUAGE sql IMMUTABLE PARALLEL SAFE \ + AS $mutbody$ SELECT eql_v3.ore_block_u64_8_256(\ + coalesce(a, '{esc}'::jsonb::eql_v3.int4_ord)::jsonb) $mutbody$", + esc = const_payload.replace('\'', "''"), + ); + mutate(&pool, &ddl).await?; + + // Post: NULL-valued rows now carry a concrete key, so they no longer park at + // the tail — the NULLS arm catches the lost STRICT contract. + let mutated: Vec> = sqlx::query_scalar(&order_by).fetch_all(&pool).await?; + ensure!( + !tail_all_none(&mutated), + "after dropping STRICT on ord_term, the NULL-valued rows must no longer \ + cluster at the tail (got {mutated:?})" + ); + Ok(()) +} diff --git a/tests/sqlx/tests/encrypted_domain/family/sem.rs b/tests/sqlx/tests/encrypted_domain/family/sem.rs new file mode 100644 index 00000000..b7d2543c --- /dev/null +++ b/tests/sqlx/tests/encrypted_domain/family/sem.rs @@ -0,0 +1,395 @@ +//! Direct behavioural tests for the self-contained `eql_v3` searchable- +//! encrypted-metadata (SEM) index-term functions (`eql_v3.hmac_256`, +//! `eql_v3.ore_block_u64_8_256` and their comparators). +//! +//! These functions are a HAND-PORT of the `eql_v2` originals (`src/v3/sem/`). +//! The scalar matrix already exercises the happy path of the *array* comparator +//! end-to-end against real ciphertext fixtures (ordering, equality, min/max, +//! injectivity, index engagement). This file covers the branches the matrix +//! structurally cannot reach, and which are otherwise tested only on the +//! `eql_v2` copies (in `tests/index_compare_tests.rs`): +//! +//! - T1: differential v2↔v3 parity on real `ob` fixtures (the strongest guard +//! against a faithful-port slip — see below). +//! - T2: the `'Ciphertexts are different lengths'` RAISE (all real fixtures are +//! equal length, so the matrix never hits it). +//! - T3: NULL-term ordering inside `compare_ore_block_u64_8_256_term` — the +//! `STRICT` comparison wrappers short-circuit before these branches run. +//! - T4: array-level NULL + empty/cardinality base cases of the recursion. +//! - T5: presence checks (`has_*`) and the missing-`ob` RAISE. +//! +//! All migrations (`001`–`007`) auto-apply to every `#[sqlx::test]` pool, so the +//! real `ore` table (ids 1–1000) and both schemas are available with no setup. + +use std::collections::HashSet; + +use anyhow::Result; +use eql_tests::assert_raises; +use sqlx::PgPool; + +/// A single term built directly from hex — no encryption needed for the +/// structural/edge-case tests. +fn term(hex: &str) -> String { + format!("ROW(decode('{hex}', 'hex'))::eql_v3.ore_block_u64_8_256_term") +} + +/// T1 — Differential parity: the same real `ob` payload must compare identically +/// through the `eql_v2` and `eql_v3` array comparators. `eql_v2` is the trusted +/// oracle; `eql_v3` is the byte-port. Both sides route through the SAME path +/// (jsonb extractor → composite → `compare_ore_block_u64_8_256_terms`) so the +/// schema prefix is the only variable — any divergence is a genuine port bug. +/// v3 has no encrypted-arg `compare` overload, hence the extractor routing. +#[sqlx::test] +async fn ore_v2_v3_comparator_parity_on_real_fixtures(pool: PgPool) -> Result<()> { + // Pairs spanning equal and unequal ids. Plaintext order of the fixtures is + // undocumented, so we assert v2≡v3 agreement (not a specific sign). + let pairs = [ + (1i64, 1i64), + (1, 2), + (2, 1), + (1, 500), + (500, 1), + (42, 42), + (10, 900), + (900, 10), + ]; + + let sql = r#" + WITH a AS (SELECT e::jsonb AS j FROM ore WHERE id = $1), + b AS (SELECT e::jsonb AS j FROM ore WHERE id = $2) + SELECT + eql_v2.compare_ore_block_u64_8_256_terms( + eql_v2.ore_block_u64_8_256(a.j), eql_v2.ore_block_u64_8_256(b.j)) AS v2, + eql_v3.compare_ore_block_u64_8_256_terms( + eql_v3.ore_block_u64_8_256(a.j), eql_v3.ore_block_u64_8_256(b.j)) AS v3 + FROM a, b + "#; + + let mut v3_signs: HashSet = HashSet::new(); + for (x, y) in pairs { + let (v2, v3): (i32, i32) = sqlx::query_as(sql).bind(x).bind(y).fetch_one(&pool).await?; + assert_eq!( + v2, v3, + "eql_v2 and eql_v3 ORE comparators disagree on ids ({x},{y}): v2={v2} v3={v3}" + ); + v3_signs.insert(v3); + } + + // Non-triviality: the sample must have actually exercised lt, eq, and gt — + // otherwise the parity check could pass on a degenerate all-equal path. + assert!( + v3_signs.contains(&0), + "sample must include an equal pair (0)" + ); + assert!( + v3_signs.contains(&-1), + "sample must include a less-than pair (-1)" + ); + assert!( + v3_signs.contains(&1), + "sample must include a greater-than pair (1)" + ); + Ok(()) +} + +/// T2 — The term comparator must reject ciphertexts of different lengths. This +/// guard is unreachable via the matrix (every real fixture is equal length). +#[sqlx::test] +async fn ore_term_comparator_rejects_different_length_ciphertexts(pool: PgPool) -> Result<()> { + let sql = format!( + "SELECT eql_v3.compare_ore_block_u64_8_256_term({}, {})", + term("aabbccdd"), // 4 bytes + term("aabbccddee"), // 5 bytes + ); + assert_raises(&pool, &sql, &[], "Ciphertexts are different lengths").await?; + Ok(()) +} + +/// T3 — NULL-term ordering inside `compare_ore_block_u64_8_256_term`. The +/// function is intentionally NOT `STRICT`, so these defensive branches are +/// reachable by a direct call (the `STRICT` comparison wrappers never reach +/// them). Pins: `(NULL, t) = -1`, `(t, NULL) = 1`, `(NULL, NULL) = 0`. +#[sqlx::test] +async fn ore_term_comparator_null_ordering(pool: PgPool) -> Result<()> { + let t = term("aabb"); + let n = "NULL::eql_v3.ore_block_u64_8_256_term"; + + let cases = [ + ( + format!("SELECT eql_v3.compare_ore_block_u64_8_256_term({n}, {t})"), + -1, + ), + ( + format!("SELECT eql_v3.compare_ore_block_u64_8_256_term({t}, {n})"), + 1, + ), + ( + format!("SELECT eql_v3.compare_ore_block_u64_8_256_term({n}, {n})"), + 0, + ), + ]; + + for (sql, expected) in cases { + let got: i32 = sqlx::query_scalar(&sql).fetch_one(&pool).await?; + assert_eq!(got, expected, "null-term ordering: {sql}"); + } + Ok(()) +} + +/// T4 — Array-level NULL and empty/cardinality base cases of the recursive +/// `compare_ore_block_u64_8_256_terms(term[], term[])`. NULL array → NULL; +/// both empty → 0; empty vs non-empty → -1; non-empty vs empty → 1. +#[sqlx::test] +async fn ore_terms_array_null_and_empty_base_cases(pool: PgPool) -> Result<()> { + let t = format!("ARRAY[{}]", term("aabb")); + let empty = "ARRAY[]::eql_v3.ore_block_u64_8_256_term[]"; + let null_arr = "NULL::eql_v3.ore_block_u64_8_256_term[]"; + + // NULL array operand → NULL result (the array overload returns NULL; it is + // not STRICT). Typed as Option; the shared `assert_null` helper only + // types Option, so query directly here. + for sql in [ + format!("SELECT eql_v3.compare_ore_block_u64_8_256_terms({null_arr}, {t})"), + format!("SELECT eql_v3.compare_ore_block_u64_8_256_terms({t}, {null_arr})"), + ] { + let got: Option = sqlx::query_scalar(&sql).fetch_one(&pool).await?; + assert!(got.is_none(), "NULL array operand must yield NULL: {sql}"); + } + + let cases = [ + ( + format!("SELECT eql_v3.compare_ore_block_u64_8_256_terms({empty}, {empty})"), + 0, + ), + ( + format!("SELECT eql_v3.compare_ore_block_u64_8_256_terms({empty}, {t})"), + -1, + ), + ( + format!("SELECT eql_v3.compare_ore_block_u64_8_256_terms({t}, {empty})"), + 1, + ), + ]; + for (sql, expected) in cases { + let got: i32 = sqlx::query_scalar(&sql).fetch_one(&pool).await?; + assert_eq!(got, expected, "array base case: {sql}"); + } + Ok(()) +} + +/// T5 — SEM presence checks (`has_ore_block_u64_8_256`, `has_hmac_256`), the +/// extractor's missing-`ob` RAISE, and its NULL-jsonb short-circuit. +#[sqlx::test] +async fn sem_presence_checks_and_missing_ob_behaviour(pool: PgPool) -> Result<()> { + let bool_cases = [ + ( + r#"SELECT eql_v3.has_ore_block_u64_8_256('{"ob":["aa"]}'::jsonb)"#, + true, + ), + ( + r#"SELECT eql_v3.has_ore_block_u64_8_256('{}'::jsonb)"#, + false, + ), + // json-null `ob` → `->>` yields NULL → absent. + ( + r#"SELECT eql_v3.has_ore_block_u64_8_256('{"ob":null}'::jsonb)"#, + false, + ), + (r#"SELECT eql_v3.has_hmac_256('{"hm":"abc"}'::jsonb)"#, true), + (r#"SELECT eql_v3.has_hmac_256('{}'::jsonb)"#, false), + ]; + for (sql, expected) in bool_cases { + let got: bool = sqlx::query_scalar(sql).fetch_one(&pool).await?; + assert_eq!(got, expected, "presence check: {sql}"); + } + + // Missing `ob` → RAISE. + assert_raises( + &pool, + r#"SELECT eql_v3.ore_block_u64_8_256('{"foo":1}'::jsonb)"#, + &[], + "Expected an ore index (ob) value", + ) + .await?; + + // NULL jsonb → NULL composite (STRICT short-circuit), NOT a raise. + let is_null: bool = + sqlx::query_scalar("SELECT eql_v3.ore_block_u64_8_256(NULL::jsonb) IS NULL") + .fetch_one(&pool) + .await?; + assert!( + is_null, + "NULL jsonb must extract to a NULL composite, not raise" + ); + Ok(()) +} + +/// T6 — Characterization of `eql_v3.jsonb_array_to_bytea_array(jsonb)` across its +/// three real-world input shapes. This is the safety net for the plpgsql→sql +/// inlining refactor (the function is reached per-encrypted-value, so it must be +/// inlinable). Behaviour pinned: +/// - JSON null (`'null'`) → NULL (the load-bearing null guard) +/// - empty array (`'[]'`) → NULL (array_agg over zero rows is NULL) +/// - populated array → decoded bytea[] +/// +/// Note the deliberate divergence the inlinable CASE form introduces vs. the +/// v2 plpgsql equivalent: a non-array JSON *scalar* (e.g. a number) returns NULL +/// rather than raising `cannot extract elements from a scalar`. Both callers only +/// ever pass an array or json-null (`val->'ob'`), so this is unreachable in +/// practice; we pin it here so the divergence is intentional and visible. +#[sqlx::test] +async fn jsonb_array_to_bytea_array_input_shapes(pool: PgPool) -> Result<()> { + // SQL NULL (distinct from JSON null `'null'`). The function is NOT STRICT, + // so the body runs: `jsonb_typeof(NULL)` is NULL → the CASE guard + // `WHEN jsonb_typeof(val) = 'array'` is not-true → ELSE NULL. + let is_null: bool = + sqlx::query_scalar("SELECT eql_v3.jsonb_array_to_bytea_array(NULL::jsonb) IS NULL") + .fetch_one(&pool) + .await?; + assert!( + is_null, + "SQL NULL must yield NULL bytea[] (function is not STRICT)" + ); + + // JSON null → NULL. + let is_null: bool = + sqlx::query_scalar("SELECT eql_v3.jsonb_array_to_bytea_array('null'::jsonb) IS NULL") + .fetch_one(&pool) + .await?; + assert!(is_null, "JSON null must yield NULL bytea[]"); + + // Empty array → NULL (array_agg over zero rows). + let is_null: bool = + sqlx::query_scalar("SELECT eql_v3.jsonb_array_to_bytea_array('[]'::jsonb) IS NULL") + .fetch_one(&pool) + .await?; + assert!(is_null, "empty JSON array must yield NULL bytea[]"); + + // Single-element array → one decoded bytea element. + let decoded: Vec> = + sqlx::query_scalar("SELECT eql_v3.jsonb_array_to_bytea_array('[\"aabb\"]'::jsonb)") + .fetch_one(&pool) + .await?; + assert_eq!( + decoded, + vec![vec![0xaau8, 0xbb]], + "single-element array must hex-decode to a 1-element bytea[]" + ); + + // Populated array → hex-decoded bytea[] round-trip. + let decoded: Vec> = sqlx::query_scalar( + "SELECT eql_v3.jsonb_array_to_bytea_array('[\"aabb\",\"ccdd\"]'::jsonb)", + ) + .fetch_one(&pool) + .await?; + assert_eq!( + decoded, + vec![vec![0xaau8, 0xbb], vec![0xccu8, 0xdd]], + "populated array must hex-decode to bytea[]" + ); + + // Deliberate delta: a non-array JSON scalar returns NULL (not a raise). + let is_null: bool = + sqlx::query_scalar("SELECT eql_v3.jsonb_array_to_bytea_array('5'::jsonb) IS NULL") + .fetch_one(&pool) + .await?; + assert!( + is_null, + "non-array JSON scalar must yield NULL (documented delta)" + ); + + // Same delta for a non-array JSON object — `jsonb_typeof` is 'object', so + // the CASE guard is not-true → ELSE NULL (not a raise). + let is_null: bool = + sqlx::query_scalar("SELECT eql_v3.jsonb_array_to_bytea_array('{}'::jsonb) IS NULL") + .fetch_one(&pool) + .await?; + assert!( + is_null, + "non-array JSON object must yield NULL (documented delta)" + ); + + Ok(()) +} + +/// T7 — Characterization of `eql_v3.jsonb_array_to_ore_block_u64_8_256(jsonb)` +/// across the same three input shapes. Safety net for the same plpgsql→sql +/// inlining refactor. Behaviour pinned: +/// - JSON null (`'null'`) → NULL composite +/// - empty array (`'[]'`) → NULL composite (inner array_agg is NULL) +/// - populated array → non-NULL composite with one term per element +/// +/// Same documented delta as T6 for a non-array JSON scalar. +#[sqlx::test] +async fn jsonb_array_to_ore_block_input_shapes(pool: PgPool) -> Result<()> { + // SQL NULL (distinct from JSON null `'null'`). Not STRICT, so the body + // runs: `jsonb_typeof(NULL)` is NULL → CASE guard not-true → ELSE NULL. + let is_null: bool = + sqlx::query_scalar("SELECT eql_v3.jsonb_array_to_ore_block_u64_8_256(NULL::jsonb) IS NULL") + .fetch_one(&pool) + .await?; + assert!( + is_null, + "SQL NULL must yield NULL composite (function is not STRICT)" + ); + + // JSON null → NULL composite. + let is_null: bool = sqlx::query_scalar( + "SELECT eql_v3.jsonb_array_to_ore_block_u64_8_256('null'::jsonb) IS NULL", + ) + .fetch_one(&pool) + .await?; + assert!(is_null, "JSON null must yield NULL composite"); + + // Empty array → NULL composite. + let is_null: bool = + sqlx::query_scalar("SELECT eql_v3.jsonb_array_to_ore_block_u64_8_256('[]'::jsonb) IS NULL") + .fetch_one(&pool) + .await?; + assert!(is_null, "empty JSON array must yield NULL composite"); + + // Single-element array → non-NULL composite with exactly 1 term. + let term_count: i32 = sqlx::query_scalar( + "SELECT cardinality((eql_v3.jsonb_array_to_ore_block_u64_8_256('[\"aabb\"]'::jsonb)).terms)", + ) + .fetch_one(&pool) + .await?; + assert_eq!( + term_count, 1, + "single-element array must yield exactly one term" + ); + + // Populated array → non-NULL composite with one term per element. + let term_count: i32 = sqlx::query_scalar( + "SELECT cardinality((eql_v3.jsonb_array_to_ore_block_u64_8_256('[\"aabb\",\"ccdd\",\"eeff\"]'::jsonb)).terms)", + ) + .fetch_one(&pool) + .await?; + assert_eq!( + term_count, 3, + "populated array must yield one term per element" + ); + + // Deliberate delta: a non-array JSON scalar returns NULL (not a raise). + let is_null: bool = + sqlx::query_scalar("SELECT eql_v3.jsonb_array_to_ore_block_u64_8_256('5'::jsonb) IS NULL") + .fetch_one(&pool) + .await?; + assert!( + is_null, + "non-array JSON scalar must yield NULL (documented delta)" + ); + + // Same delta for a non-array JSON object — `jsonb_typeof` is 'object', so + // the CASE guard is not-true → ELSE NULL (not a raise). + let is_null: bool = + sqlx::query_scalar("SELECT eql_v3.jsonb_array_to_ore_block_u64_8_256('{}'::jsonb) IS NULL") + .fetch_one(&pool) + .await?; + assert!( + is_null, + "non-array JSON object must yield NULL (documented delta)" + ); + + Ok(()) +} diff --git a/tests/sqlx/tests/encrypted_domain/family/support.rs b/tests/sqlx/tests/encrypted_domain/family/support.rs new file mode 100644 index 00000000..5f1bdb6d --- /dev/null +++ b/tests/sqlx/tests/encrypted_domain/family/support.rs @@ -0,0 +1,333 @@ +//! Self-checks for the type-generic matrix substrate +//! (`tests/sqlx/src/scalar_domains.rs`). Each test pins one piece of the +//! `ScalarType` / `Variant` / assertion-helper API that the matrix +//! depends on. + +use anyhow::Result; +use eql_tests::{ + assert_null, assert_raises, assert_scalar_plaintexts, blocker_msg, fetch_fixture_payload, + sql_string_literal, ScalarDomainSpec, ScalarType, Variant, PLACEHOLDER_PAYLOAD, +}; +use sqlx::PgPool; + +#[test] +fn variant_derives_consistent_sql_domain_and_capabilities() { + let storage = ScalarDomainSpec::new::(Variant::Storage); + assert_eq!(storage.sql_domain, "eql_v3.int4"); + assert!(!storage.supports_eq()); + assert!(!storage.supports_ord()); + assert_eq!(storage.extractor_fn(), None); + assert_eq!(Variant::Storage.required_term(), None); + + let eq = ScalarDomainSpec::new::(Variant::Eq); + assert_eq!(eq.sql_domain, "eql_v3.int4_eq"); + assert!(eq.supports_eq()); + assert!(!eq.supports_ord()); + assert_eq!(eq.extractor_fn(), Some("eql_v3.eq_term")); + assert_eq!(Variant::Eq.required_term(), Some("hm")); + + let ord = ScalarDomainSpec::new::(Variant::Ord); + assert_eq!(ord.sql_domain, "eql_v3.int4_ord"); + assert!(ord.supports_ord()); + assert_eq!(ord.extractor_fn(), Some("eql_v3.ord_term")); + assert_eq!(Variant::Ord.required_term(), Some("ob")); + + let ord_ore = ScalarDomainSpec::new::(Variant::OrdOre); + assert_eq!(ord_ore.sql_domain, "eql_v3.int4_ord_ore"); + assert!(ord_ore.supports_ord()); + assert_eq!(ord_ore.extractor_fn(), Some("eql_v3.ord_term")); +} + +#[test] +fn expected_forward_default_is_numeric_ground_truth() { + // Pinned against the full 17-row fixture (extremes + zero + the + // original 14). The output is sorted-ascending by `expected_forward`, + // so a regression in the default impl's filter or sort shows up + // here. + assert_eq!(::expected_forward("=", 10), vec![10]); + assert_eq!( + ::expected_forward("<", 10), + vec![i32::MIN, -100, -1, 0, 1, 2, 5] + ); + assert_eq!( + ::expected_forward("<=", 10), + vec![i32::MIN, -100, -1, 0, 1, 2, 5, 10] + ); + assert_eq!( + ::expected_forward(">", 10), + vec![17, 25, 42, 50, 100, 250, 1000, 9999, i32::MAX] + ); + assert_eq!( + ::expected_forward(">=", 10), + vec![10, 17, 25, 42, 50, 100, 250, 1000, 9999, i32::MAX] + ); + assert_eq!( + ::expected_forward("<>", 42), + vec![ + i32::MIN, + -100, + -1, + 0, + 1, + 2, + 5, + 10, + 17, + 25, + 50, + 100, + 250, + 1000, + 9999, + i32::MAX + ] + ); +} + +#[test] +fn sql_string_literal_escapes_single_quotes() { + assert_eq!(sql_string_literal("abc'def"), "'abc''def'"); +} + +#[sqlx::test(fixtures(path = "../../../fixtures", scripts("eql_v2_int4")))] +async fn fetch_fixture_payload_returns_keyed_row(pool: PgPool) -> Result<()> { + // Parse the payload as JSON rather than substring-matching — whitespace + // and key ordering in the serialised form are not contract. + let payload = fetch_fixture_payload::(&pool, 42).await?; + let value: serde_json::Value = serde_json::from_str(&payload)?; + assert_eq!(value["v"], serde_json::json!(2), "payload must carry v=2"); + assert!(value.get("c").is_some(), "payload must carry a c field"); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../../../fixtures", scripts("eql_v2_int4")))] +async fn assert_scalar_plaintexts_reports_sql_context(pool: PgPool) -> Result<()> { + let lit = sql_string_literal(&fetch_fixture_payload::(&pool, 42).await?); + let predicate = format!("payload::eql_v3.int4_ord_ore = {lit}::jsonb::eql_v3.int4_ord_ore"); + assert_scalar_plaintexts::(&pool, "eql_v3.int4_ord_ore", "=", &predicate, &[42]).await?; + Ok(()) +} + +#[sqlx::test] +async fn placeholder_payload_satisfies_every_variant_check(pool: PgPool) -> Result<()> { + // The whole point of PLACEHOLDER_PAYLOAD: one sentinel that casts + // successfully to every domain in the family. If a variant CHECK + // tightens, this test fails and PLACEHOLDER_PAYLOAD needs updating. + // + // Iterates `Variant::ALL` for `i32`, deriving each domain name from + // `ScalarDomainSpec::new::(variant).sql_domain` rather than + // hardcoding the names. Currently `i32`-only; when `int8` (or any + // future scalar) lands, wrap this in a per-type loop so the + // PLACEHOLDER_PAYLOAD cast is exercised against every scalar. + for variant in Variant::ALL { + let spec = ScalarDomainSpec::new::(*variant); + let sql = format!("SELECT $1::jsonb::{}", spec.sql_domain); + sqlx::query(&sql) + .bind(PLACEHOLDER_PAYLOAD) + .fetch_one(&pool) + .await + .map_err(|e| { + anyhow::anyhow!("PLACEHOLDER_PAYLOAD must cast to {}: {e}", spec.sql_domain) + })?; + } + Ok(()) +} + +#[sqlx::test] +async fn assert_raises_two_bind_blocker(pool: PgPool) -> Result<()> { + let msg = blocker_msg("eql_v3.int4", "="); + assert_raises( + &pool, + "SELECT $1::jsonb::eql_v3.int4 = $2::jsonb::eql_v3.int4", + &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], + &msg, + ) + .await +} + +#[sqlx::test] +async fn assert_raises_one_bind_path_blocker(pool: PgPool) -> Result<()> { + let msg = blocker_msg("eql_v3.int4", "->"); + assert_raises( + &pool, + "SELECT $1::jsonb::eql_v3.int4 -> 'field'::text", + &[Some(PLACEHOLDER_PAYLOAD)], + &msg, + ) + .await +} + +#[sqlx::test] +async fn assert_raises_native_operator_absent(pool: PgPool) -> Result<()> { + // ~~ (LIKE) isn't declared on int4 — error message is PG's native + // "operator does not exist", not an EQL blocker message. + assert_raises( + &pool, + "SELECT $1::jsonb::eql_v3.int4 ~~ $2::jsonb::eql_v3.int4", + &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], + "operator does not exist", + ) + .await +} + +#[sqlx::test] +async fn omitted_native_jsonb_operators_raise_eql_blockers(pool: PgPool) -> Result<()> { + let cases: &[(&str, &[Option<&str>], &str)] = &[ + ( + "SELECT $1::jsonb::eql_v3.int4 ? 'c'::text", + &[Some(PLACEHOLDER_PAYLOAD)], + "?", + ), + ( + "SELECT $1::jsonb::eql_v3.int4 ?| ARRAY['c']", + &[Some(PLACEHOLDER_PAYLOAD)], + "?|", + ), + ( + "SELECT $1::jsonb::eql_v3.int4 ?& ARRAY['c']", + &[Some(PLACEHOLDER_PAYLOAD)], + "?&", + ), + ( + "SELECT $1::jsonb::eql_v3.int4 #> ARRAY['i']", + &[Some(PLACEHOLDER_PAYLOAD)], + "#>", + ), + ( + "SELECT $1::jsonb::eql_v3.int4 #>> ARRAY['i', 'c']", + &[Some(PLACEHOLDER_PAYLOAD)], + "#>>", + ), + ( + "SELECT $1::jsonb::eql_v3.int4 @? '$.c'::jsonpath", + &[Some(PLACEHOLDER_PAYLOAD)], + "@?", + ), + ( + "SELECT $1::jsonb::eql_v3.int4 @@ '$.c == \"placeholder\"'::jsonpath", + &[Some(PLACEHOLDER_PAYLOAD)], + "@@", + ), + ( + "SELECT $1::jsonb::eql_v3.int4 - 'c'::text", + &[Some(PLACEHOLDER_PAYLOAD)], + "-", + ), + ( + "SELECT $1::jsonb::eql_v3.int4 - 0", + &[Some(PLACEHOLDER_PAYLOAD)], + "-", + ), + ( + "SELECT $1::jsonb::eql_v3.int4 - ARRAY['c']", + &[Some(PLACEHOLDER_PAYLOAD)], + "-", + ), + ( + "SELECT $1::jsonb::eql_v3.int4 #- ARRAY['i']", + &[Some(PLACEHOLDER_PAYLOAD)], + "#-", + ), + ( + "SELECT $1::jsonb::eql_v3.int4 || $2::jsonb", + &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], + "||", + ), + ( + "SELECT $1::jsonb || $2::jsonb::eql_v3.int4", + &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], + "||", + ), + ( + "SELECT $1::jsonb::eql_v3.int4 || $2::jsonb::eql_v3.int4", + &[Some(PLACEHOLDER_PAYLOAD), Some(PLACEHOLDER_PAYLOAD)], + "||", + ), + ]; + + for (sql, binds, op) in cases { + assert_raises(&pool, sql, binds, &blocker_msg("eql_v3.int4", op)).await?; + } + Ok(()) +} + +#[sqlx::test] +async fn assert_raises_engages_on_all_null(pool: PgPool) -> Result<()> { + // Non-STRICT blocker proof — must raise even with NULL on both sides. + let msg = blocker_msg("eql_v3.int4", "="); + assert_raises( + &pool, + "SELECT $1::jsonb::eql_v3.int4 = $2::jsonb::eql_v3.int4", + &[None, None], + &msg, + ) + .await +} + +#[sqlx::test] +async fn assert_null_propagates_through_supported_op(pool: PgPool) -> Result<()> { + // STRICT supported op with one NULL operand yields NULL. + assert_null( + &pool, + "SELECT $1::jsonb::eql_v3.int4_eq = $2::jsonb::eql_v3.int4_eq", + &[Some(PLACEHOLDER_PAYLOAD), None], + ) + .await +} + +#[sqlx::test] +async fn neq_propagates_null_under_three_valued_logic(pool: PgPool) -> Result<()> { + // `<>` with a NULL operand must yield NULL (not true, not false). + // Three-valued logic is easy to get wrong in domain wrappers; a + // STRICT supported `<>` returns NULL on either NULL side. + for binds in [ + &[Some(PLACEHOLDER_PAYLOAD), None][..], + &[None, Some(PLACEHOLDER_PAYLOAD)][..], + &[None, None][..], + ] { + assert_null( + &pool, + "SELECT $1::jsonb::eql_v3.int4_eq <> $2::jsonb::eql_v3.int4_eq", + binds, + ) + .await?; + } + Ok(()) +} + +#[sqlx::test] +async fn no_cross_variant_operator_is_declared(pool: PgPool) -> Result<()> { + // The family deliberately does NOT define ANY operator that mixes two + // different capability variants — e.g. `eql_v3.int4_eq = eql_v3.int4_ord` + // would resolve against jsonb (the ultimate base type) and silently + // bypass the per-variant blockers. The query below has no `oprname` + // filter, so it catches a cross-variant operator of any kind, not just + // `=`. If someone accidentally adds such an operator, this test fails. + // + // The check is structural (`pg_operator`) rather than dynamic + // ("invoke and see it raise") so a future PG version with stricter + // operator resolution doesn't mask the regression. + let cross_variant: Vec = sqlx::query_scalar( + r#" + SELECT format('%s(%s, %s)', + o.oprname, lt.typname, rt.typname) + FROM pg_catalog.pg_operator o + JOIN pg_catalog.pg_type lt ON lt.oid = o.oprleft + JOIN pg_catalog.pg_namespace ln ON ln.oid = lt.typnamespace + JOIN pg_catalog.pg_type rt ON rt.oid = o.oprright + JOIN pg_catalog.pg_namespace rn ON rn.oid = rt.typnamespace + WHERE ln.nspname = 'eql_v3' + AND rn.nspname = 'eql_v3' + AND lt.typname <> rt.typname + ORDER BY 1 + "#, + ) + .fetch_all(&pool) + .await?; + + assert!( + cross_variant.is_empty(), + "no operator should mix two different eql_v3 domain types, but found: {cross_variant:#?}" + ); + Ok(()) +} diff --git a/tests/sqlx/tests/encrypted_domain/scalars/mod.rs b/tests/sqlx/tests/encrypted_domain/scalars/mod.rs new file mode 100644 index 00000000..72c64f87 --- /dev/null +++ b/tests/sqlx/tests/encrypted_domain/scalars/mod.rs @@ -0,0 +1,9 @@ +//! Per-scalar matrix suites, generated by the `scalar_types!(matrix_suites)` +//! invocation below — one module per scalar type, each holding its +//! `ordered_numeric_matrix!` suite. +//! +//! The modules are generated from the single harness list in +//! `tests/sqlx/src/scalar_types.rs` — adding a type there adds its suite here +//! automatically. The old per-type `scalars/.rs` files are gone. + +eql_tests::scalar_types!(matrix_suites); diff --git a/tests/sqlx/tests/eql_v2_int4_fixture_tests.rs b/tests/sqlx/tests/eql_v2_int4_fixture_tests.rs new file mode 100644 index 00000000..04233f15 --- /dev/null +++ b/tests/sqlx/tests/eql_v2_int4_fixture_tests.rs @@ -0,0 +1,151 @@ +//! Structural verification of the generated `eql_v2_int4` fixture. +//! +//! Vanilla SQL over `fixtures.eql_v2_int4` — `payload` is plain `jsonb`, no +//! domain type required. The `plaintext` column is the in-table oracle; no +//! Rust value constant is shared with the generator. #224 verifies the +//! fixture is well-formed; #225 verifies the domain operators on it. + +use anyhow::Result; +use sqlx::PgPool; + +/// The 17 values from `src/fixtures/eql_v2_int4.rs`, in id order. Kept here +/// only to assert the in-table `plaintext` oracle matches what was generated. +/// If `plaintext_column_matches_the_generated_values` fails, the generator's +/// `VALUES` and this constant have drifted — re-run +/// `mise run fixture:generate eql_v2_int4` and update this list to match. +const EXPECTED_PLAINTEXTS: &[i32] = &[ + i32::MIN, + -100, + -1, + 0, + 1, + 2, + 5, + 10, + 17, + 25, + 42, + 50, + 100, + 250, + 1000, + 9999, + i32::MAX, +]; + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn fixture_has_seventeen_rows(pool: PgPool) -> Result<()> { + let count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM fixtures.eql_v2_int4") + .fetch_one(&pool) + .await?; + assert_eq!(count, 17, "eql_v2_int4 fixture should have 17 rows"); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn ids_are_sequential_one_to_seventeen(pool: PgPool) -> Result<()> { + let ids: Vec = sqlx::query_scalar("SELECT id FROM fixtures.eql_v2_int4 ORDER BY id") + .fetch_all(&pool) + .await?; + assert_eq!(ids, (1..=17).collect::>()); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn plaintext_column_matches_the_generated_values(pool: PgPool) -> Result<()> { + let plaintexts: Vec = + sqlx::query_scalar("SELECT plaintext FROM fixtures.eql_v2_int4 ORDER BY id") + .fetch_all(&pool) + .await?; + assert_eq!(plaintexts, EXPECTED_PLAINTEXTS); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn every_payload_carries_the_hmac_equality_term(pool: PgPool) -> Result<()> { + // `hm` drives equality. Every row's payload must carry an `hm` string term. + let missing: i64 = sqlx::query_scalar( + "SELECT COUNT(*) FROM fixtures.eql_v2_int4 + WHERE payload->'hm' IS NULL OR jsonb_typeof(payload->'hm') <> 'string'", + ) + .fetch_one(&pool) + .await?; + assert_eq!(missing, 0, "every payload must carry an `hm` string term"); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn every_payload_carries_the_ore_block_term(pool: PgPool) -> Result<()> { + // `ob` drives ordering. Every row's payload must carry a non-null ob array. + let missing: i64 = sqlx::query_scalar( + "SELECT COUNT(*) FROM fixtures.eql_v2_int4 + WHERE payload->'ob' IS NULL OR jsonb_typeof(payload->'ob') <> 'array'", + ) + .fetch_one(&pool) + .await?; + assert_eq!(missing, 0, "every payload must carry an `ob` array term"); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn every_payload_carries_a_ciphertext(pool: PgPool) -> Result<()> { + // `c` is the ciphertext. Every row's payload must carry a `c` string. + let missing: i64 = sqlx::query_scalar( + "SELECT COUNT(*) FROM fixtures.eql_v2_int4 + WHERE payload->'c' IS NULL OR jsonb_typeof(payload->'c') <> 'string'", + ) + .fetch_one(&pool) + .await?; + assert_eq!( + missing, 0, + "every payload must carry a `c` ciphertext string" + ); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn plaintext_oracle_supports_value_filtering(pool: PgPool) -> Result<()> { + // The in-table `plaintext` oracle: a consuming test can filter on it + // directly. Exactly one row has plaintext = 42. + let ids: Vec = + sqlx::query_scalar("SELECT id FROM fixtures.eql_v2_int4 WHERE plaintext = 42 ORDER BY id") + .fetch_all(&pool) + .await?; + assert_eq!( + ids, + vec![11], + "expected exactly one row with plaintext = 42 at id 11" + ); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn hmac_equality_terms_are_distinct_for_distinct_values(pool: PgPool) -> Result<()> { + // All 17 plaintext values are distinct, so all 17 `hm` terms must be too. + let distinct_hm: i64 = + sqlx::query_scalar("SELECT COUNT(DISTINCT payload->>'hm') FROM fixtures.eql_v2_int4") + .fetch_one(&pool) + .await?; + assert_eq!( + distinct_hm, 17, + "17 distinct values -> 17 distinct hm terms" + ); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn every_payload_declares_eql_payload_version_v2(pool: PgPool) -> Result<()> { + // The EQL `v` payload-format field is checked server-side against `'2'` + // when an `eql_v2_encrypted` value is inserted. Asserting equality here + // (not just presence) means a future bump to `v=3` fails this test + // loudly, forcing the maintainer to regenerate the fixture and audit + // consumers for v2→v3 semantic changes. + let mismatched: i64 = sqlx::query_scalar( + "SELECT COUNT(*) FROM fixtures.eql_v2_int4 + WHERE payload->'v' IS NULL OR payload->>'v' <> '2'", + ) + .fetch_one(&pool) + .await?; + assert_eq!(mismatched, 0, "every payload must declare v = '2'"); + Ok(()) +} diff --git a/tests/sqlx/tests/generate_all_fixtures.rs b/tests/sqlx/tests/generate_all_fixtures.rs new file mode 100644 index 00000000..72ebbdf0 --- /dev/null +++ b/tests/sqlx/tests/generate_all_fixtures.rs @@ -0,0 +1,37 @@ +//! Catalog-driven "generate every encrypted fixture" entry point. +//! +//! Replaces the Python-era `fixture:generate ` per-type scripts and the +//! `fixture:generate:all` TOML-glob loop (which spawned a separate `cargo test` +//! per type). This runs ALL scalar fixture generators in ONE process, iterating +//! `eql_scalars::CATALOG` for the authoritative token set. +//! +//! The encrypted-fixture logic itself is unchanged — each type's +//! `fixtures::eql_v2_::spec().run()` still produces +//! `tests/sqlx/fixtures/eql_v2_.sql` exactly as before. +//! +//! Gated behind `fixture-gen` (needs a live Postgres + CS_* creds). Run via: +//! mise run fixture:generate:all +#![cfg(feature = "fixture-gen")] + +use eql_scalars::CATALOG; + +// `generate_for_token(token: &str) -> anyhow::Result<()>` is generated from the +// single harness list in `tests/sqlx/src/scalar_types.rs`: one match arm per +// token (`"int4" => fixtures::eql_v2_int4::spec().run().await`) plus a loud +// catch-all. A catalog token absent from that list hits the catch-all and fails +// the generator loudly, so a new scalar type cannot silently skip generation. +eql_tests::scalar_types!(fixture_dispatch); + +#[tokio::test] +#[ignore = "generator — run via `mise run fixture:generate:all`"] +async fn generate_all() -> anyhow::Result<()> { + let mut generated = 0usize; + for spec in CATALOG { + eprintln!("Generating fixture eql_v2_{}...", spec.token); + generate_for_token(spec.token).await?; + generated += 1; + } + assert!(generated > 0, "CATALOG is empty — nothing to generate"); + eprintln!("Regenerated {generated} scalar fixture(s)."); + Ok(()) +} diff --git a/tests/sqlx/tests/like_operator_tests.rs b/tests/sqlx/tests/like_operator_tests.rs index ad062727..679ee81d 100644 --- a/tests/sqlx/tests/like_operator_tests.rs +++ b/tests/sqlx/tests/like_operator_tests.rs @@ -53,7 +53,7 @@ async fn create_encrypted_json_with_index( }) } -#[sqlx::test(fixtures(path = "../fixtures", scripts("like_data")))] +#[sqlx::test(fixtures(path = "../fixtures", scripts("match_data")))] async fn like_operator_matches_pattern(pool: PgPool) -> Result<()> { // Test: ~~ operator (LIKE) matches encrypted values // Tests both ~~ operator and LIKE operator (they're equivalent) @@ -89,7 +89,7 @@ async fn like_operator_matches_pattern(pool: PgPool) -> Result<()> { Ok(()) } -#[sqlx::test(fixtures(path = "../fixtures", scripts("like_data")))] +#[sqlx::test(fixtures(path = "../fixtures", scripts("match_data")))] async fn like_operator_no_match(pool: PgPool) -> Result<()> { // Test: ~~ operator returns empty for non-matching pattern // This test verifies that LIKE operations correctly return no results @@ -109,7 +109,7 @@ async fn like_operator_no_match(pool: PgPool) -> Result<()> { Ok(()) } -#[sqlx::test(fixtures(path = "../fixtures", scripts("like_data")))] +#[sqlx::test(fixtures(path = "../fixtures", scripts("match_data")))] async fn like_function_matches_pattern(pool: PgPool) -> Result<()> { // Test: eql_v2.like() function // Tests the eql_v2.like() function which wraps bloom filter matching @@ -129,7 +129,7 @@ async fn like_function_matches_pattern(pool: PgPool) -> Result<()> { Ok(()) } -#[sqlx::test(fixtures(path = "../fixtures", scripts("like_data")))] +#[sqlx::test(fixtures(path = "../fixtures", scripts("match_data")))] async fn ilike_operator_case_insensitive_matches(pool: PgPool) -> Result<()> { // Test: ~~* operator (ILIKE) matches encrypted values (case-insensitive) // Tests both ~~* operator and ILIKE operator (they're equivalent) diff --git a/tests/sqlx/tests/lint_tests.rs b/tests/sqlx/tests/lint_tests.rs index 1bd080c9..a7f9152d 100644 --- a/tests/sqlx/tests/lint_tests.rs +++ b/tests/sqlx/tests/lint_tests.rs @@ -12,8 +12,15 @@ //! appropriate. use anyhow::Result; +use eql_tests::Variant; use sqlx::PgPool; +/// Pg-type tokens for the encrypted-scalar-domain families currently +/// materialised. Extending the family (e.g. when `int8`/`bool`/`date` +/// land) is a one-line array extension here — every downstream +/// parameterised test picks it up automatically. +const SCALAR_PG_TYPES: &[&str] = &["int4", "int2"]; + #[derive(Debug, sqlx::FromRow)] struct LintRow { severity: String, @@ -33,16 +40,13 @@ async fn fetch_lints(pool: &PgPool) -> Result> { } #[sqlx::test] -async fn lint_function_exists_and_returns_rows(pool: PgPool) -> Result<()> { - let rows = fetch_lints(&pool).await?; - // The current state of EQL has a non-trivial number of inlinability - // violations on the operator surface. Confirm the lint produces output - // and the columns parse correctly. - assert!( - !rows.is_empty(), - "Expected lint to surface at least one inlinability violation \ - against the current EQL surface; got 0 rows" - ); +async fn lint_function_exists_and_row_schema_parses(pool: PgPool) -> Result<()> { + // Schema-only check: `eql_v2.lints()` exists and its rows decode into + // `LintRow`. Previous incarnation asserted `!rows.is_empty()` and so + // would fail on a *cleaner* build (e.g. when Phase 1+ removes the + // current noisy violations), reading like a regression for a good + // reason. The rule-specific tests below pin actual behaviour. + let _rows = fetch_lints(&pool).await?; Ok(()) } @@ -70,6 +74,10 @@ async fn lint_categories_are_well_known(pool: PgPool) -> Result<()> { "inlinability_set_clause", "inlinability_secdef", "inlinability_transitive", + "blocker_language", + "blocker_strict", + "domain_over_domain", + "domain_opclass", ]; for row in rows { assert!( @@ -82,6 +90,175 @@ async fn lint_categories_are_well_known(pool: PgPool) -> Result<()> { Ok(()) } +/// A blocker rendered in `LANGUAGE sql` instead of `plpgsql` is the +/// inverse of the extractor/wrapper inlinability rule: a blocker's job is +/// to RAISE, and `LANGUAGE sql` bodies are inlinable — which means the +/// planner can fold or elide the call when the result is provably unused +/// (a dead CASE branch, a folded predicate), silently bypassing the RAISE +/// and re-enabling the operator. See CLAUDE.md footguns. This test plants +/// a fake LANGUAGE sql blocker on `eql_v3.int4` and asserts the lint +/// surfaces it under category `blocker_language`. +#[sqlx::test] +async fn lint_flags_blocker_in_language_sql(pool: PgPool) -> Result<()> { + sqlx::query( + r#" + CREATE FUNCTION eql_v2.test_bad_blocker_sql(a eql_v3.int4, b eql_v3.int4) + RETURNS boolean LANGUAGE sql IMMUTABLE + AS $$ SELECT eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '=') $$; + "#, + ) + .execute(&pool) + .await?; + + let rows = fetch_lints(&pool).await?; + let violations: Vec<&LintRow> = rows + .iter() + .filter(|r| { + r.category == "blocker_language" && r.object_name.contains("test_bad_blocker_sql") + }) + .collect(); + + assert!( + !violations.is_empty(), + "Expected `blocker_language` to flag the LANGUAGE sql fake blocker, \ + but got no matching row. All lint rows:\n{:#?}", + rows + ); + assert_eq!( + violations[0].severity, "error", + "blocker_language must be severity=error" + ); + Ok(()) +} + +/// A blocker marked `STRICT` lets PostgreSQL skip the body and return NULL +/// on a NULL argument — silently bypassing the "operator not supported" +/// RAISE. See CLAUDE.md footguns. This test plants a fake STRICT plpgsql +/// blocker on `eql_v3.int4` and asserts the lint surfaces it under +/// `blocker_strict`. +#[sqlx::test] +async fn lint_flags_strict_blocker(pool: PgPool) -> Result<()> { + sqlx::query( + r#" + CREATE FUNCTION eql_v2.test_bad_blocker_strict(a eql_v3.int4, b eql_v3.int4) + RETURNS boolean LANGUAGE plpgsql IMMUTABLE STRICT + AS $$ BEGIN RETURN eql_v3.encrypted_domain_unsupported_bool('eql_v3.int4', '='); END; $$; + "#, + ) + .execute(&pool) + .await?; + + let rows = fetch_lints(&pool).await?; + let violations: Vec<&LintRow> = rows + .iter() + .filter(|r| { + r.category == "blocker_strict" && r.object_name.contains("test_bad_blocker_strict") + }) + .collect(); + + assert!( + !violations.is_empty(), + "Expected `blocker_strict` to flag the STRICT fake blocker, \ + but got no matching row. All lint rows:\n{:#?}", + rows + ); + assert_eq!( + violations[0].severity, "error", + "blocker_strict must be severity=error" + ); + Ok(()) +} + +/// Generated encrypted-domain blockers intentionally use non-inlinable +/// plpgsql functions. They should be checked by the blocker-specific lint +/// rules, not reported as normal operator inlinability failures. +#[sqlx::test] +async fn lint_does_not_report_generated_blockers_as_inlinability_errors( + pool: PgPool, +) -> Result<()> { + let rows = fetch_lints(&pool).await?; + let violations: Vec<&LintRow> = rows + .iter() + .filter(|r| { + matches!( + r.category.as_str(), + "inlinability_language" + | "inlinability_volatility" + | "inlinability_set_clause" + | "inlinability_secdef" + ) && r.object_name.contains("eql_v3.int4") + && (r.object_name.contains("operator =(") + || r.object_name.contains("operator ->(") + || r.object_name.contains("operator ?(")) + }) + .collect(); + + assert!( + violations.is_empty(), + "generated encrypted-domain blockers must not be reported by direct \ + inlinability rules; got: {violations:#?}" + ); + Ok(()) +} + +/// An `eql_v2_*` domain whose base type is another `eql_v2_*` domain (not +/// jsonb) silently bypasses the storage variant's blockers: operators +/// resolve against the ultimate base type, so a derived domain does not +/// inherit the base domain's operator surface. See CLAUDE.md footguns. +/// This test plants a domain-over-domain offender and asserts the lint +/// surfaces it under `domain_over_domain`. +#[sqlx::test] +async fn lint_flags_domain_over_domain(pool: PgPool) -> Result<()> { + sqlx::query(r#"CREATE DOMAIN public.eql_v2_test_baddom AS eql_v3.int4;"#) + .execute(&pool) + .await?; + + let rows = fetch_lints(&pool).await?; + let violations: Vec<&LintRow> = rows + .iter() + .filter(|r| { + r.category == "domain_over_domain" && r.object_name.contains("eql_v2_test_baddom") + }) + .collect(); + + assert!( + !violations.is_empty(), + "Expected `domain_over_domain` to flag the derived domain, \ + but got no matching row. All lint rows:\n{:#?}", + rows + ); + assert_eq!( + violations[0].severity, "error", + "domain_over_domain must be severity=error" + ); + Ok(()) +} + +/// An operator class declared `FOR TYPE` on an `eql_v2_*` domain bypasses +/// the operator-resolution that the storage blockers depend on. The +/// recommended pattern is a functional index on the extractor; opclasses +/// on domains must never appear. See CLAUDE.md footguns. The current +/// build emits zero opclasses on `eql_v2_*` domains, so this test is +/// negative: it asserts the rule category is well-known and surfaces no +/// rows. A positive test would require constructing a valid opclass on a +/// domain, which is non-trivial scaffolding — the `domain_opclass` +/// structural guard in `tests/encrypted_domain/family/inlinability.rs` is the +/// independent net for regressions. +#[sqlx::test] +async fn lint_domain_opclass_surface_is_clean(pool: PgPool) -> Result<()> { + let rows = fetch_lints(&pool).await?; + let violations: Vec<&LintRow> = rows + .iter() + .filter(|r| r.category == "domain_opclass") + .collect(); + assert!( + violations.is_empty(), + "domain_opclass surface should be empty in a clean build, got: {:#?}", + violations + ); + Ok(()) +} + /// Phase 1 regression: the operators rewritten in #193 (=, <>, ~~, ~~*, /// @>, <@ on eql_v2_encrypted) must report zero lint violations. If this /// test fails, an inlinability regression has been introduced into one @@ -119,3 +296,68 @@ async fn lint_phase_1_operators_are_clean(pool: PgPool) -> Result<()> { ); Ok(()) } + +/// Every encrypted-scalar-domain family's inlinable operator surface +/// must report zero lint violations. The supported operators on the +/// `_eq`, `_ord`, and `_ord_ore` variants are codegen-emitted SQL +/// wrappers (LANGUAGE sql, IMMUTABLE, no pinned `search_path`); the +/// planner can fold them into the documented functional indexes. A +/// regression to plpgsql or a pinned `search_path` breaks index +/// engagement. +/// +/// Storage-only variants (the bare `eql_v2_` domain with no +/// capability suffix) are intentionally excluded — every operator on +/// them is a non-STRICT plpgsql blocker, which doesn't need to be +/// inlinable. +/// +/// Discovers the eligible operator set from `pg_operator` rather than +/// hardcoding the int4 inventory — when `int8` (or `bool`, `date`, ...) +/// lands, this test picks it up automatically with no edit. The earlier +/// hardcoded list was a copy-paste hazard. +#[sqlx::test] +async fn scalar_family_inlinable_operators_are_clean(pool: PgPool) -> Result<()> { + // Build the inline-critical signature set Rust-side from + // `SCALAR_PG_TYPES × Variant::ALL × supported-operators`. Eq-only + // variants declare `<`/`<=`/`>`/`>=` as blockers (intentionally + // non-inlinable), so they must NOT be expected to be clean here — + // only the ops the variant actually supports as wrappers count. + // + // Storage variants contribute no inline-critical surface; their + // entire operator set is blockers by design. + let mut prefixes: Vec = Vec::new(); + for pg_type in SCALAR_PG_TYPES { + for variant in Variant::ALL { + if matches!(variant, Variant::Storage) { + continue; + } + let domain = format!("eql_v3.{pg_type}{}", variant.suffix()); + let supported_ops: &[&str] = if variant.supports_ord() { + &["=", "<>", "<", "<=", ">", ">="] + } else { + // Eq variants support equality only; ordering ops on `_eq` + // are blockers. + &["=", "<>"] + }; + for op in supported_ops { + // Domain-on-left and jsonb-on-left arg shapes both + // need to be inlinable; the domain-on-right shape is + // the `(jsonb, domain)` operator. + prefixes.push(format!("operator {op}({domain},")); + prefixes.push(format!("operator {op}(jsonb, {domain})")); + } + } + } + + let rows = fetch_lints(&pool).await?; + let violations: Vec<&LintRow> = rows + .iter() + .filter(|row| prefixes.iter().any(|p| row.object_name.starts_with(p))) + .collect(); + + assert!( + violations.is_empty(), + "scalar-family inline-critical operators should report zero \ + lint violations, but got: {violations:#?}" + ); + Ok(()) +}