Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Changelog

For the full project changelog, see the repository file:

Current Highlights (v3.0.2)

  • qail pull keeps TRUNCATE triggers: information_schema.triggers lists INSERT, UPDATE and DELETE events only, so a trigger whose one event is TRUNCATE was dropped without a LOSSY PULL entry and INSERT OR TRUNCATE lost its TRUNCATE event. Both now come from pg_trigger; a TRUNCATE-only trigger with a WHEN condition is listed as lossy.
  • Release line: Rust workspace crates and install snippets are bumped to 3.0.2.

v3.0.1 Highlights

  • A rolled-back COMMIT on release is logged: PooledConnection::release() used to discard a COMMIT that PostgreSQL answered with ROLLBACK (a statement in the transaction had failed, so none of its writes were kept). It now logs pool_release_rolled_back at warn with the caller’s file and line; release_checked() is unchanged.
  • Compound CHECKs validate: qail check and qail migrate apply no longer report real columns as missing in x IS NULL or x in [...] or in a comparison to a literal (is_active = false, seats = 0). A schema that validated before still validates.
  • Release line: Rust workspace crates and install snippets are bumped to 3.0.1.

v3.0.0 Highlights

  • Upserts keep the RLS guard: ON CONFLICT DO UPDATE is sent with the tenant/owner guard in either builder order, so a conflicting row of another tenant is left untouched instead of overwritten.
  • Scoped INSERT … SELECT and OVERRIDING: with_rls() stamps the tenant on INSERT … SELECT sources and refuses OVERRIDING USER VALUE on scoped tables, where PostgreSQL discarded the stamp.
  • Pool reset skips stale replies: a caller dropped mid-request no longer leaves its reply for the next checkout (“completion before BindComplete”).
  • The statement cache compares SQL: a 64-bit hash collision can no longer run one query as another prepared statement.
  • Preview SQL and native encoding agree: HAVING, GROUP BY keys and grouping sets, aggregate DISTINCT and FILTER, bytea binds, RETURNING and payload rules render alike; unsupported forms fail instead of emitting different SQL.
  • More PostgreSQL: aggregate ORDER BY and WITHIN GROUP, FROM subqueries and set-returning functions, named arguments, array slices, write CTEs, MERGE DEFAULT/ONLY/OVERRIDING, NOWAIT and FOR … OF, GROUPS frames, JSONPath and range operators, PostgreSQL 18 temporal keys and RETURNING WITH (OLD AS .., NEW AS ..).
  • Lossless decoding: PgArray<T> keeps dimensions, lower bounds and NULL elements; infinity, NUMERIC ±Infinity, escape-format bytea and BC dates decode without silent loss.
  • Faithful qail pull: exact type names, column order, function options, trigger WHEN and arguments, view options and NOT VALID constraints are kept; objects it cannot represent are listed in a LOSSY PULL header, and it refuses to write a file that does not parse back.
  • Gateway: cache keys and allow-lists match on the full AST; queries that take row locks are never cached and are refused on read-only surfaces.
  • Breaking AST changes: Qail boxes its DDL definitions, JSON paths use JsonPathSegment, and expression and schema types gain fields and variants. A segment built with "0".into() is now an object key (->'0'), not the array index 2.x rendered; use JsonPathSegment::from_path_text or JsonPathSegment::Index. See “Changed (3.0 — migration notes)” in CHANGELOG.md.
  • Release line: Rust workspace crates and install snippets are bumped to 3.0.0.

v2.0.5 Highlights

  • Composite foreign keys in build validation: qail_core::build::validate() accepts the table-level foreign_key (a, b) references t(x, y) lines qail pull writes; a pulled schema with a composite FK no longer fails every downstream build.
  • Build scanner reads past lifetimes and loop labels: schema validation and the RLS/SuperAdmin audits no longer skip the queries after '_, 'static or 'outer:.
  • ORDER BY on a projection alias: .order_by("total") after .column_expr(count().alias("total")) validates instead of reading the alias as a missing column.
  • Release line: Rust workspace crates and install snippets are bumped to 2.0.5.

v2.0.4 Highlights

  • Linear COPY text export: copy_export and the row-streaming variants parse a frame’s rows in place and shift the consumed bytes out once, so a CopyData frame of many small rows costs linear time instead of minutes.
  • Release line: Rust workspace crates and install snippets are bumped to 2.0.4.

v2.0.3 Highlights

  • N+1 analyzer precision: lifetimes and loop labels no longer blank the code after them; exec calls with wrapped arguments, rustfmt-split iterator chains and one-line iterator closures are analyzed; a closure-free .map(fn) no longer opens a phantom loop.
  • Paced loops wait on their own path: only a directly awaited .tick()/sleep(..) or a select! whose arms are all _ with one timer, at the loop body’s top level, exempts a bare loop; a backoff-branch sleep or a data-driven select! arm no longer does.
  • Array columns in qail migrate apply: post-apply verification matches arrays on element type instead of the ARRAY data type.
  • rustls 0.23.45: the workspace lockfile resolves the fix for RUSTSEC-2026-0285.
  • Release line: Rust workspace crates and install snippets are bumped to 2.0.3.

v2.0.2 Highlights

  • Pool releases scrub session state: every return path appends CLOSE ALL; SET SESSION AUTHORIZATION DEFAULT; RESET ALL; UNLISTEN *; pg_advisory_unlock_all(); DISCARD TEMP; DISCARD SEQUENCES to the release round trip and clears the client-side notification queue, so session state can no longer cross into the next checkout. Prepared statements survive.
  • Bounded buffering: the undrained LISTEN/NOTIFY queue fails closed at 8192 entries and 16 KB per notification; COPY text export caps a cross-frame row at 16 MB. Overflow desyncs and destroys the connection instead of growing memory.
  • Exact sslmode=prefer fallback: plaintext retry requires the one sentinel a server emits when it declines the SSLRequest; handshake and certificate failures keep failing closed.
  • rustls provider pinned: qail-pg installs the aws-lc-rs crypto provider before building any ClientConfig, so feature unification with ring no longer panics on first TLS use.
  • Build validation follows migrations_dir: qail_core::build::validate() resolves [project].migrations_dir from the nearest qail.toml the way qail migrate does, so a crate keeping its migrations outside migrations/ needs no symlink.
  • Release line: Rust workspace crates and install snippets are bumped to 2.0.2.

v2.0.1 Highlights

  • Migration merge restatement tolerance: build-time validation no longer aborts the schema merge when an applied migration restates a column less specifically than the pulled schema reports it (bare VARCHAR vs VARCHAR(n), bare DECIMAL vs a precision, an enum declared before later values were added). The pulled type stays ground truth; genuinely different types remain a hard error.
  • Deterministic migration merge order: migration paths are sorted before merging, so the build-time schema no longer depends on filesystem read_dir order.

v2.0.0 Highlights

  • JOIN array membership parity: is_array_unnest expands to the same EXISTS/unnest SQL in the PostgreSQL wire encoder and the core transpiler; unsupported JOIN pattern operators fail closed.
  • Aggregate qualifier validation: GROUP BY and DISTINCT ON qualifiers are checked against the active relation scope, including alias hiding and CTE visibility rules, before application code can ship invalid SQL.
  • Qualified RLS injection: tenant/owner predicates name their primary relation, avoiding PostgreSQL 42702 ambiguity on joined queries; schema-qualified CROSS joins retain every registered relation’s predicate.
  • Fail-closed payload de-duplication: identical repeated assignments collapse, while conflicting tenant/owner stamps remain an encoder error instead of overriding the value injected by with_rls().
  • RLS scope hardening: with_rls() fails closed on registered tables, scope registries are declared once at the application boundary (init_scope_registries / declare_policy_only_isolation), owner (owner <column>) scoping joins tenant scoping, and ON CONFLICT DO UPDATE carries the scope predicate via OnConflict.where_conditions.
  • 1.x compatibility surfaces removed: the qail-encoder C ABI, SQLite/DynamoDB/MongoDB transpilers, the agent identity plane (app.current_agent_id), the function-pointer GSS callback, the JWT user_id alias, auth_mode=compat, deprecated SDK aliases, and the io_uring feature alias. See the repository CHANGELOG [2.0.0-rc.1] section for per-item migration notes.
  • Release line: Rust workspace crates and install snippets are bumped to 2.0.0; qail-workflow, qail-workflow-postgres and qail-gateway are in the crates.io publish set.

v1.4.0 Highlights

  • Views can declare security_invoker: view <name> security_invoker $$ … $$ parses, renders, compiles to CREATE VIEW … WITH (security_invoker = true), and survives qail pull by being read back from pg_class.reloptions. Without it, a view over an RLS-protected table evaluates that table’s policies as the view owner and silently bypasses them. Owner-rights stays the default, matching PostgreSQL.
  • qail pull introspects grants: relacl is parsed into schema.grants, so a relation missing a grant to the application role is now visible in schema.qail instead of failing at runtime as [42501] permission denied with nothing to diff. Recovered 229 grants on a live 217-table database that previously showed zero. Privileges with no schema.qail spelling are reported on stderr rather than dropped.
  • rls::tenant::scoping_applies(): callers and audits can assert that tenant scoping actually applied — in 1.4, with_rls failed open on unregistered relations (2.0 fails closed).
  • Release line: Rust workspace crates and install snippets were bumped to 1.4.0.

v1.3.6 Highlights

  • PostgreSQL dependency correctness: cmov 0.5.4 fixes incorrect AArch64 constant-time selection results in the dependency path used by PostgreSQL SCRAM authentication.
  • Gateway dependency safety: crossbeam-epoch 0.9.20 resolves RUSTSEC-2026-0204 in the metrics and cache dependency paths.
  • Extension build tooling: VSCE 3.9.2 resolves the form-data and markdown-it advisories without changing the shipped extension runtime.
  • PostgreSQL io_uring opt-in security: Linux io_uring plain-TCP transport no longer auto-enables on kernel support; enable it explicitly with [postgres].io_uring = true, ?io_uring=true, driver/pool options, or QAIL_PG_IO_BACKEND=io_uring.
  • Tokio remains the safe default: building with the qail-pg/io_uring feature only makes the backend available; TLS, mTLS, and GSSENC paths continue to use Tokio transport.
  • Workflow payment hardening: charge side effects now default to stable workflow idempotency keys, support order-origin metadata, and store redacted payment display payloads for chat/notification use.
  • Release line: Rust workspace crates and install snippets are bumped to 1.3.6.

v1.3.0 Highlights

  • Detailed changelog: QAIL.rs v1.3.0: Native Vertical Policy and the Audit Pass Behind It
  • Native vertical access policy: qail_core::access adds deny-by-default table policies, role/scope requirements, operation permissions, and read/write/returning column rules before AST execution.
  • Gateway policy integration: [access] in qail.toml loads TOML/JSON policies so gateway REST, QAIL text/binary/batch, transaction, RPC, nested, expanded, and live-query paths can enforce vertical table and column boundaries alongside PostgreSQL RLS.
  • PostgreSQL statement cache safety: hot prepared statements are promoted, evicted, reparsed, and retained only in states that match the real backend statement lifecycle.
  • Migration verification: composite foreign-key options now survive parse/diff/apply and strict post-apply checks verify table constraints against the live database.
  • Gateway hardening: precise numerics, oversized integers, Qdrant JSON integer drift, transaction subqueries, branch replay, and tenant guard exemptions are handled on explicit fail-closed paths.
  • Workflow and encoder fixes: workflow guards, charge amounts, branch cursors, null bind params, zero-parameter binds, and Qdrant vector byte order were tightened.
  • SDK path safety: TypeScript, Kotlin, and Swift SDK builders encode table and ID path segments before constructing REST routes.
  • Real database validation: PostgreSQL lab coverage passed for strict migrations, MERGE, access-checked execution, seeded RLS, and gateway native access policy behavior.

v1.2.1 Highlights

  • Schema parser compatibility: pulled PostgreSQL schemas now accept table-level enable_rls and force_rls directives.
  • PostgreSQL type parsing: multi-word types such as DOUBLE PRECISION and TIMESTAMP WITH TIME ZONE parse correctly from pulled schemas.
  • Comment parsing: schema comments containing quoted examples no longer break parsing.

v1.2.0 Highlights

  • PostgreSQL protocol safety: COPY, LISTEN/NOTIFY, replication, pooled fetch, driver fetch, query, and pipeline paths now fail closed and desynchronize bad connections on malformed backend state.
  • NUL and UTF-8 hardening: savepoints, SQL rendering, AST SQL buffers, gateway explain SQL, COPY text rows, backend wire strings, and PostgreSQL URL decoding now reject invalid input instead of silently mutating it.
  • Real database validation: PostgreSQL 18 lab coverage passed for MERGE, set operations, recursive CTEs, cursor cleanup, COPY callback recovery, LISTEN/NOTIFY payloads, savepoint rejection, and NUL query rejection.

v1.1.1 Highlights

  • Live migration introspection: schema pulls and shadow verification now account for generated columns, identity defaults, expression indexes, enum extensions, and composite foreign-key drift.
  • Migration replay safety: post-apply checks compare constraints, defaults, generated expressions, indexes, and extension dependencies against the real database state.
  • Branch overlay coverage: live PostgreSQL audit paths verify merge, set-operation, recursive-CTE behavior, and bad overlay replay failure modes.

v1.1.0 Highlights

  • Workflow engine hardening: fixed nested loop context preservation, wait-event resume validation, timeout fallbacks, and transition checkpointing.
  • Gateway security hardening: tightened tenant guards, RLS policy injection, write-side column policies, idempotency, transaction paths, branch overlays, and REST mutation/event semantics.
  • Qdrant tenant safety: tenant-scoped vector upserts now namespace point IDs while preserving the caller-facing original ID.
  • Branch overlay correctness: branch reads and merges now use deterministic chronological ordering with post-policy filtering and projection.
  • Durable events: webhook delivery now has an outbox-backed path and stricter old/new payload handling.
  • Runtime surface cleanup: the supported stable runtime is centered on PostgreSQL and Qdrant; legacy SQLite/DynamoDB/MongoDB transpiler symbols remain compatibility-only for 1.x consumers, and obsolete PostgreSQL examples were removed.

v1.0.0 Highlights

  • Promoted QAIL to 1.0.0 Stable, declaring the API complete and production-grade.
  • gRPC Connection State Machine: Implemented concurrent reconnection protection using a connection generation counter in the Qdrant engine.
  • Webhook Scaling: Scaled webhook concurrency limit to 512 paired with safe timeouts.
  • Connection Pool Locking: Replaced async-wait locks with standard library unwrap synchronization under heavy concurrent loads.
  • Workspace Crates: All workspace crates, internal path dependencies, and VSCode LSP extension bumped to 1.0.0.
  • API Cleanup Carried Into 1.0: try_with_rls() and try_join_on() compatibility aliases are gone; call with_rls(&ctx)? and join_on(...)? on the fallible path.
  • Raw SQL Runtime Surface: Qail::raw_sql(...), Qail::is_raw_sql(), Qail::raw_where(...), and Qail::nextval(...) are not part of the stable public runtime path.
  • Cancel-Key API: legacy i32 cancel-key wrappers are gone; use bytes-native cancel-key APIs.
  • Error Conversion: broad From<QailBuildError> for String compatibility conversion was removed so callers keep structured build errors.