Skip to content

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 08:07
· 172 commits to main since this release

Added

  • Obligations: schema.sql declares, above a CREATE TABLE or CREATE VIEW, what every statement
    touching the relation must do, and vet judges each statement against it
    (checks.md, Part 2). The general form is
    -- sqlshape: require <what> [on <kinds>], where <what> is an SQL predicate, pinned(col),
    immutable(col), via view, never, paired(table) or single.
  • aggregate root (child, ...) [lock version]: the tables form one aggregate; children are reached
    through the root's key, one statement touches one aggregate, and with lock every write names
    the root's version.
  • transitions col: a -> b, b -> c | d: a status column is a state machine; an UPDATE setting it
    must compare-and-set from a declared predecessor.
  • sensitive label: col, col and context name: may read label: labelled columns are readable
    only in a context that allows the label.
  • context name: require ...; waive ...: obligations that differ per caller, selected by a
    package's // sqlshape: context name comment, vet's -context, or check -context.
  • -- sqlshape: waive table [obligation] in a statement or a view definition: an opt-out,
    reported with -strict.
  • Cross-table predicates: require EXISTS (SELECT 1 FROM parent p WHERE p.id = parent_id AND ...)
    is discharged by a join or subquery that witnesses it.
  • sqlshape check: the same judgments for SQL outside Go (files or stdin), every judgment printed
    as an audit line, exit code 1 on a failure.
  • The internal/facts package: what a statement provably does, in a form that does not depend on
    the SQL dialect, so that the obligation checker can be shared with other dialects later.

Changed

  • visible where, -require-columns, -no-table-reads and -no-tables are now obligations
    (require <expr> on read, require pinned(col), require via view, require via view on all)
    and are judged by the same checker. Judgment is per occurrence of a table: a self join or a
    subquery reading the table again owes the obligation again; -require-columns used to accept a
    statement that pinned the column anywhere in it. A row-level security policy or a composite
    foreign key can discharge a pin. MERGE's ON is judged like a WHERE.
  • Writes are counted by what the statement does to the table: each MERGE branch is a write of its
    own kind, an INSERT ... ON CONFLICT DO UPDATE is an insert and an update, TRUNCATE is a
    delete, and a write through an automatically updatable view is a write to the base table.
  • pinned on an UPDATE is satisfied by the WHERE only; assigning the column in SET is not a pin.
  • A -- sqlshape: directive above a statement that takes none (ALTER TABLE, COMMENT ON) is a
    schema problem instead of being ignored.
  • The docs are split: the README is an overview; docs/ has checks, templates, runtime,
    migrations and flags, in English and Japanese.

Fixed

  • A vet failure shared by every branch of a template is reported once without the branch tag.
  • A diagnostic on a column referenced only in GROUP BY had no position.