retrofit snapshot
Emit canonical DDL for the materialized schema, shaped like
`pg_dump --schema-only` (docs/pg_dump-parity.md lists the differences).
Run with --help-all for the full --include-drop / --using semantics.
Usage:
retrofit snapshot [flags]
Flags:
--allow-reading-replace-body downgrade the replace-body-reads-relation refusal to a warning; emit the body verbatim under a WARNING comment, and render its table's prologue as a whole-table clear
--allow-stale-dml downgrade every stale-DML-reference refusal to a warning; emit the body under a stale-reference WARNING comment. It does NOT cover chain-collision, which is not attestable: two live chains for one element is a fork to resolve by retiring one, and exit 2 stands
--allow-unnamed-label stringArray attest that the dataset carrying this exact label is deliberately left unnamed in this run (repeatable; byte-exact, never trimmed); every other unnamed dataset still warns
--at root emit DDL for the cut at <opid> prefix or anchor (root/`last`/`seal`, optional `^`/`~N`) (default: last)
--data-only emit the data band only: the banner (unless --no-header), then the band as snapshot emits it; no DDL
--data-root data_root root that overrides the schema's data_root
--exclude-schema strings drop schemas matching <name> from emission (repeatable; pg_dump -N)
--exclude-table strings drop tables matching <name> or <schema>.<name> from emission (repeatable; pg_dump -T)
--extra-seed-path seed_paths root that appends to the declared seed_paths
-h, --help help for snapshot
--help-all show extended help (vocabulary, semantics, caveats)
--include-drop string[="scoped"] DROP prologue before the CREATEs: none | scoped | schema (default "none")
--label stringArray apply the dataset carrying this exact label (repeatable; argv order is layer order; byte-exact, never trimmed; never cuts ref data)
--no-comments suppress every COMMENT ON statement (pg_dump --no-comments)
--no-header suppress the canonical banner line
--over string with --data-only: emit only the tables the LAST-named --label's layer contributed to (a projection, never a diff)
--schema <name> registered schema <name> (resolves via the chain when omitted)
--seed-path seed_paths root that replaces the declared seed_paths
--skip-manifest string write skipped view-render records (JSONL) to <path>
--table strings restrict emission to tables matching <name> or <schema>.<name> (repeatable; pg_dump -t)
--using string one-shot emit target override (format: <engine>:<major>; read-only)
Global Flags:
--as string output mode: text | json (default "text")
-C, --chdir string treat <dir> as the working directory for the entire run
--config string retrofit.toml path (overrides discovery; also accepts $RETROFIT_CONFIG)
-f, --file string oplog file path; selects a registered [[schema]] path (overrides discovery)
--no-consolidate render every advisory occurrence instead of collapsing repeats
-q, --quiet count suppress the advisory tier on stderr; stack (-qq) to drop it whole (errors and results still print)
-v, --verbose reveal info-tier advisories on stderr
Docs: https://docs.retrofit.sh/current/commands/retrofit-snapshot/retrofit snapshot --help-all adds:
Extended help:
--include-drop modes:
none no DROP statements (default); emit pure CREATE.
Pair with external dropdb/createdb if you need a clean reflash.
scoped per-element DROP ... IF EXISTS for tables/indexes/FKs in the
emission set, then CREATE. Sibling objects in the same schema
survive. The emitted script fails at apply, and rolls back
inside its BEGIN/COMMIT, if any table outside the emission set
holds an inbound FK into the set; pick --include-drop=schema in
that case.
schema one DROP SCHEMA IF EXISTS <name> CASCADE per snapshot schema,
then CREATE. CASCADE blast radius covers every dependent
outside the emission set; use only when the developer owns
the entire schema.
Bare --include-drop (no value) resolves to scoped.
--using=<engine>:<major> overrides the emit target (read-only; one-shot).
Resolution chain when --using is absent: [[schema]] engine_version
(per-schema override) > [project] engine_version (fallback). The flag
value's <engine> must match the project engine; <major> must be in
this build's supported set.
Emit-time filters (pg_dump -N / -t / -T parity):
--exclude-schema=<name> drop schemas matching <name> from emission.
Exact-match on the registered name (no glob);
unknown name refuses with schema-not-in-cut.
--table=<name> restrict emission to the listed tables.
Accepts <name> or <schema>.<name>; both flag
forms repeat (--table=a --table=b). Unknown
name refuses with table-not-in-cut.
--exclude-table=<name> inverse of --table; drop the listed tables.
When both are supplied, exclude wins on
conflict (matches pg_dump).
Interactions:
- --schema picks one schema in scope (root flag). When both --schema
and --exclude-schema name the same value, the cut's emission body
is empty (banner survives); when --exclude-schema names a value
that isn't in the cut, the call refuses (never-silent).
- --include-drop=schema is incompatible with --table: schema-level
DROP CASCADE would remove siblings the --table filter spares
(flag-conflict).
- --include-drop=scoped + --table emits per-element DROPs ONLY for
included tables.
- FK reachability is checked against the filtered set: an FK from an
included table to an excluded table refuses with
fk-cross-schema-unreachable. Include the target or drop the FK.
Glob/pattern matching, --strict-names, --filter=<file>, and
--table-and-children are deferred; see docs/pg_dump-parity.md.
Data corpus (--label):
snapshot always reads the data corpus under the schema's declared
data_root (retrofit.toml [[schema]].data_root; addressed *.data.<format>
files, plus readable legacy *.dml.sql files): purpose=ref records (production reference
rows) apply with zero flags and are never label-filtered; seed
records are opt-in.
--label <label> is the WHOLE seed opt-in: it names the dataset to
apply, and a seed chain no --label names is not applied. The flag is
repeatable and ORDERED: argv order is layer order, lowest layer
first, and matching is byte-exact membership (the selector is NOT
trimmed; a record with no labels matches no selector). Labels are
stamped at mint time by the producer's own --label. A blank --label
is rejected (label-empty). Naming a label selects; it never reorders
the band, whose records keep their intra-anchor seq order.
Applied seed records are emitted in the
`-- retrofit:snapshot-data v1` band, between the tables and the
constraints and indexes (--as=json carries the band on its own
snapshot-data record). --data-only emits
that band alone (banner, then band, no DDL); --over <label> narrows
a --data-only run to the tables the named layer actually contributed
to (a projection, never a diff).
Whatever is NOT applied is counted per table WITH ITS CAUSE (not
selected, superseded, table dropped, or screened by schema
ownership) and never silently dropped: a machine-parseable data-excluded
count (stderr warning in text mode, stdout event under --as=json),
so a label that matched nothing reads differently from one whose
dataset was superseded. Run `retrofit data list --label <label>` to
see what a selection resolves to without emitting SQL.
Before emission, the emitted body follows table and column renames and
drops removable write-only references to dropped columns; records for
dropped tables are excluded. snapshot refuses a reference it cannot repair
(stale-dml-reference) unless --allow-stale-dml is passed.
Under --data-only, a replace floor's body that reads a relation refuses
(data-replace-body-reads-relation) unless --allow-reading-replace-body
is passed, which emits it under a WARNING and clears the table whole.
Discovery runs BEFORE any DDL byte is written, so a malformed file
(data-file-malformed), a corpus conflict (dml-data-conflict), or a
declared-but-absent data_root (data-path-missing) aborts with no
partial output.