Skip to content

v0.18.47

Choose a tag to compare

@derekmwright derekmwright released this 05 Sep 20:43

v0.18.47

  • Security — a policy set now binds to the catalog at every place it is attached or installed, including the embedded API's wadjet.Open (the entry the wadjet mcp command uses), the provider's own update setters, and a configuration hot reload; previously the bind reached only wadjet serve, so a column mask, column deny or row filter whose policy spelled the table's name in a different case than the catalog silently did not apply, on every door, read and write, and a masked column was also readable through a DML predicate. A policy naming a relation or a policed column the catalog does not hold is now refused there — wadjet.Open and wadjet mcp refuse to start, and a caller that discards the error still gets every statement refused (SQLSTATE 42501). A hot reload that cannot bind, or a setter applied to an already-bound provider, keeps the previously running set rather than enforcing an unbound one, and a retired policy set can no longer resurface through a race in the bind's swap. A policy may name a relation either the way the catalog holds it or folded to lower case; any other spelling is a name the catalog does not hold (#882).
  • A WHERE predicate on a column whose catalog name carries upper-case letters (WHERE UserAgent = 'agent-A') stood down row-group statistics pruning and dictionary-probe pruning entirely — every row group was read regardless of the predicate. Both now engage on such a table (#731).
  • UPDATE on a column whose catalog name has upper-case letters (UPDATE hits SET UserAgent = 'NEW') reported UPDATE 1 and left the row's old value in place; it writes the new value now (#731).
  • A MERGE ... ON condition naming a mixed-case column matched no target row and silently inserted a duplicate instead of updating the row it should have matched; it updates the matching row now (#731).
  • A MERGE's WHEN MATCHED THEN UPDATE SET clause could report success while leaving the row unchanged, and its WHEN NOT MATCHED THEN INSERT clause could store NULL in every column whose catalog name carries upper-case letters; both actions now write under the schema's own column names (#731).
  • A delimited (quoted) column reference in an UPDATE, DELETE, or MERGE that differs only in case from an existing column — UPDATE t SET "USERAGENT" = ..., WHERE "WATCHID" = 1 — previously either silently applied to the wrong column or silently matched zero rows; it is now correctly refused (#731).
  • A row-filter or column mask/deny policy scoped to a mixed-case table name applied to SELECT but not to UPDATE, DELETE, or INSERT against the same table, so a denied column was writable and a masked one readable through a write. The write door now checks the same table name the read door does (#731).
  • COPY with an explicit column list against a table whose catalog names carry upper-case letters either refused a well-formed file with a spurious type error or silently filled every listed column with NULL; the column list now resolves against the catalog schema (#731).
  • COPY's column list is now parsed the way every other identifier is — an unquoted name folds, a delimited one keeps its exact case — so an unquoted upper-case list over a lower-case schema no longer wrongly refuses, a delimited name carrying upper-case letters is no longer wrongly accepted, and a genuinely missing column is reported as such instead of a confusing type-conversion error (#731).
  • A nested ROW, ARRAY, or MAP column referenced by its catalog's mixed-case spelling could come back on the wire with its ROW fields in the wrong order, or with an ARRAY and a MAP no longer distinguishable from each other; the value now renders under its declared type either way (#731).
  • Two catalog column names that fold to the same reference across a join could make one unchanged query return different wire bytes from run to run; an ambiguous folded reference now resolves consistently to no declared type instead of racing (#731).
  • Querying two columns with the same output name through the MCP query tool (wadjet mcp) returned the second column's value for both; each now reports its own value, matching the gRPC and HTTP doors (#513).
  • Disabling the WADJET_SCAN_COL_SANITIZE scan-projection switch previously changed query results on a mixed-case schema — silently dropping a GROUP BY, join, or ORDER BY key column; the correctness-critical part of that optimization no longer depends on the switch, which now also participates in the optimization-invariance gate (#731).
  • MERGE's SET and INSERT column targets, and a plain INSERT's column list, now read a quoted column name the way every other statement does: the quotes are no longer treated as part of the name, a delimited name matches byte-exact, and an unquoted one folds. A quoted MERGE ... SET "UserAgent" = ... previously refused as an unknown column even when correctly cased, while the equivalent UPDATE succeeded; a quoted wrong-case column in a bare INSERT's column list was previously accepted and written, and is now correctly refused. Two spellings of one column in an INSERT list are still refused as duplicates (#731).
  • A regression battery covering joins, outer joins, DISTINCT, grouped aggregates, windows, CTEs, set operations, and a correlated subquery over a mixed-case schema now runs 32 shapes on the single-process path, both distributed execution arms, and a forced group-key spill, and no longer accepts a same-error or same-empty result on both spellings as agreement (#731).
  • cmd/unifi-ingest — the UniFi ingest example tool moved out of the core command set; it will return in a separate examples repository.
  • wadjet mcp opens the shared catalog the way every other command does; it previously opened a private, empty catalog on every invocation, so it saw no tables and, with a policy configured, could not enforce it (the ABAC fix above now refuses to start rather than run unbound).