retrofit0.10.0-wip.8

retrofit import

Import one or more .sql files into an oplog. Walks DDL in
retrofit's vocabulary and appends the equivalent op-add calls. A missing
schema is registered lazily, a populated oplog is extended by default, and
--force replaces its prior content. DML is set aside in data files; other
statements outside the vocabulary (sequences, GRANT/REVOKE, publications) are
reported on the stdout skip manifest and not recorded.

Source argument: one or more filesystem paths with a `.sql` extension,
or `-` for stdin (one source per invocation when reading stdin). When
multiple sources are passed they are imported as a single batch in
argv order with one validate, one event flush, and one atomic write.

Run with --help-all for the main in-vocabulary statements and walker
semantics.

Usage:
  retrofit import <source>... [--schema <name>] [--from-file <path>] [flags]

Flags:
      --allow-capability-gaps          import anyway when capability-gap skips drop content: statements retrofit has no SMO for (exit 0 + warning instead of exit 2; the import-summary record is byte-identical either way); the one carve-out is validation-errors and rule-* refusals, which still abort
      --allow-sealed-rewrite opid      [sealed history] attest each Seal this run would demote or replace, by its full opid (repeatable, comma-separated); a value attests the Seal it names and selects nothing, and a Seal left unnamed refuses seal-removal-refused
      --data-root data_root            root that overrides the schema's data_root
      --ddl-only                       decline every preserved-DML statement in the run (authored DML, dump data bands and synthesized floors): nothing is minted, the declined tables are listed, and the run exits on its DDL alone; orthogonal to --allow-capability-gaps, which covers DDL retrofit cannot represent
      --disposition <replace|append>   asserted <replace|append> disposition on every preserved-DML record
      --dry-run                        run the full pipeline without writing the oplog file
      --engine-version <15|16|17|18>   supported major <15|16|17|18> for the imported schema (default: project engine_version)
      --extra-seed-path seed_paths     root that appends to the declared seed_paths
      --force                          overwrite an existing populated oplog (mint fresh; a bare import extends instead)
      --from-file <path>               newline-delimited <path> listing .sql files (relative to the list's directory; # comments and blank lines ignored)
  -h, --help                           help for import
      --help-all                       show extended help (vocabulary, semantics, caveats)
      --label <label>                  opaque <label> stamped onto every preserved-DML record (repeatable set; key:value accepted, not required)
      --purge-orphaned-corpus          consent to remove every corpus record whose anchor no longer exists in the replaced oplog (--force only; a same-anchor re-capture replaces its version in place)
      --purge-superseded               remove earlier same-chain data blocks superseded by this ingest (positional supersession within one continuous oplog; the anchor is alive at both positions); never a witnessed record, sealed or in the tail; each is reported kept. Default keeps them as --at render assets
      --purpose <transition|cleanse>   asserted <transition|cleanse> purpose on every preserved-DML record (one of: transition, cleanse; name a seed cohort with --label, and declare reference tables with --ref <table> or retrofit schema ref-tables add <table>)
      --ref <table>                    declare <table> reference data (repeatable): a CreateTable this run mints is written reference_data=true; a table live at the run's starting cut gets SetReferenceData(value=true) appended after the run's DDL ops
      --schema <name>                  registered schema <name> (lazy-creates when unregistered)
      --seal --seal=<text>             append a Seal op after the imported prefix (bare flag auto-derives reason from source(s); --seal=<text> overrides); refused as `op seal` refuses when the range holds an unwitnessed reference record, including one this import mints
      --seal-per-file                  emit one Seal op after each source that minted ops (sources minting none are not sealed; equivalent to a bare '--seal' import per file)
      --seed-path seed_paths           root that replaces the declared seed_paths
      --skip-manifest <path>           write one JSONL record per skipped statement to <path> (kind/schema.name/line/raw_stmt_kind/raw_text)
      --summary-file <path>            write the aggregate import-summary record to <path> as one JSON object (imported/run_raw_script/skipped/skipped_by_kind[/skipped_by_class][/sealed][/sources_zero_op])

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-import/

retrofit import --help-all adds:

Extended help:

Schema registration is lazy: naming an unregistered target with
`--schema <name>` creates its registry entry and oplog before walking the SQL.
Use `retrofit schema create <schema>` first only when you want to choose schema
settings before import.

Multiple sources in one invocation: `retrofit import 01.sql 02.sql 03.sql --schema <name>`
imports all sources as a single batch in argv order (this is what the
shell produces from a glob like `retrofit import schema/*.sql --schema lib`).
The batch is all-or-nothing: parse and validation run over the
combined op stream, `appended` events flush only after the whole
batch passes, and the oplog file is written atomically once. If any
file fails, no ops are written and no events flush. Separate per-file
runs give the same ops in the same order as one multi-file run on a
fresh schema, though not the same bytes: each run mints its own element
ids.

Re-running import on a populated oplog EXTENDS it: the new ops chain
off the existing tail, and no flag is needed (e.g. `02_indexes.sql`
added after an initial `01_tables.sql` import). To re-bootstrap from
a different `.sql` instead, pass `--force` (the prior content is
discarded); it applies to the whole batch. A pg_dump of a schema
offered against a populated oplog refuses with
`state-source-on-populated-oplog`, and an oplog whose content does
not declare `--schema` refuses with `schema-not-in-oplog`.

The main in-vocabulary statements (the import walker mints ops for
these; docs/import.md lists them all):
  - CREATE TABLE, including inline column constraints, generated
    columns (GENERATED ALWAYS AS (<expr>) STORED), and identity
    columns (GENERATED { BY DEFAULT | ALWAYS } AS IDENTITY).
  - CREATE INDEX: btree, gin, gist, brin, hash, spgist; predicate
    (WHERE) and access method (USING) bind as first-class params.
  - ALTER TABLE … ADD CONSTRAINT { PRIMARY KEY | FOREIGN KEY |
    CHECK (… IS NOT NULL …) }, including the legacy named NOT NULL
    shape, which folds to one AddNotNull per column.
  - ALTER TABLE … { ADD | DROP } COLUMN: cross-table DROP+ADD pairs
    of an unreferenced column coalesce into a single MoveColumn op.
  - ALTER TABLE … ALTER COLUMN: SET DEFAULT, DROP DEFAULT,
    SET NOT NULL → AddNotNull, DROP NOT NULL → DropNotNull,
    DROP EXPRESSION (clears a STORED generated expression; PG13+),
    ADD GENERATED, DROP GENERATED, SET GENERATED (identity mutations).
  - ALTER TABLE … ALTER CONSTRAINT … { DEFERRABLE | NOT DEFERRABLE }
    and ALTER TABLE … RENAME CONSTRAINT.
  - ALTER TABLE … REPLICA IDENTITY ….
  - CREATE VIEW / CREATE OR REPLACE VIEW / DROP VIEW: bare
    (single-schema) forms only; cross-schema views are skipped.
  - ALTER TABLE … RENAME TO / ALTER TABLE … RENAME COLUMN /
    ALTER INDEX … RENAME TO / ALTER VIEW … RENAME TO.
  - COMMENT ON TABLE | COLUMN.

Preserved DML (the data corpus):

  Custom DML (INSERT/UPDATE/DELETE/MERGE) is outside
  retrofit's vocabulary but is NOT dropped. A run mints ONE DATA FILE
  PER TABLE under the schema's declared data_root (the [[schema]]
  data_root field; default: the oplog directory). The mint key is
  (schema, table, label set, anchor-op, disposition), and a capture
  larger than the page bound splits into deterministic .p<K> pages.
  Bodies are verbatim and self-annotated. Each record carries a purpose
  (classified --purpose=transition|cleanse > declared reference data
  (--ref or schema ref-tables add) > --label cohort > unclassified), a
  disposition (replace = full observed table state, append = increment;
  a TRUNCATE/DELETE-then-INSERT reseed infers replace), an anchor-op
  (a zero-DDL data import anchors at the current oplog head), and any
  --label values. A pg_dump
  -- TABLE DATA band is NOT captured: the run lists the band's tables
  (data-band-listed) with a hint to `retrofit data capture <source>`
  and mints nothing for them. data capture accepts INSERT-style dumps;
  regenerate COPY input with pg_dump --inserts or --column-inserts first.
  snapshot and migrate discover the corpus
  automatically; re-capturing an occupied, unwitnessed mint key replaces
  the version in place as a set (git retains the old bytes); a witnessed
  key refuses. import never runs the data files.

Before 1.0, any release may change behavior; the release notes list what changed.