Skip to content

All versions since 4.0.1

4.0.1

Added

  • ViewDiff.Materialized. A plain ⇄ materialized view conversion is now carried explicitly on the diff as a ValueChange<bool>, and DiffReader renders it as a label transition (view → materialized view app.name).

Fixed

  • Renamed tables. Constraint, index, and trigger drops (and privilege revokes) on a table being renamed now target the old table name, and execute before the rename.
  • Renamed schemas. The schema rename is now ordered ahead of every other action, so drops and revokes inside the renamed schema resolve correctly.
  • Renamed materialized views. In-place index drops on a renamed view target the old view name. A rename accompanying a recreate no longer emits a RenameView (which would have targeted a dropped view); the drop removes the old name and the recreate creates the new one.
  • View conversions. A plain ⇄ materialized conversion now drops the view as what it currently is, instead of using the desired side’s materialization for the drop.

4.1.0

Added

  • Schema template declaration. A TEMPLATE name BEGIN … END; block allows you to declare a reusable group of objects once.
  • Schema template application. A APPLY TEMPLATE name IN SCHEMA a, b; statement instantiates a template into each named schema.
  • Table templates. A TEMPLATE name FOR TABLE BEGIN … END; block declares reusable table members.
  • Index name validation. Duplicate index and index-backed constraint names (primary key, unique, exclusion) within a schema are now rejected at validation time.
  • DdlDocument.Templates carries the parsed template constructs for consumers of the reader — a TemplateSet of definitions, applications, and includes.
  • The formatter lays out TEMPLATE blocks canonically: header and BEGIN/END on their own lines, inner statements formatted as usual and indented one level.

4.2.0

Added

  • Data-hazard detection. A new built-in diff policy flags planned changes that are valid against the schema but can fail on the data already in a table.

4.3.0

Added

  • Data migrations. A MIGRATION ['name'] FOR <trigger> <schema>.<table>.<member> AS $$…$$; block attaches raw SQL to a structural change (ADD COLUMN, ALTER COLUMN TYPE, or ADD CONSTRAINT) and is spliced into the plan only when the matching change is planned. A block matching nothing is reported as an informational diagnostic and is safe to delete.
  • Decomposed NOT NULL adds. A required column add with no default and a matching FOR ADD COLUMN migration is planned as add-nullable → run the migration SQL → SET NOT NULL, so the add succeeds against a populated table.
  • Hazard suppression. A matching migration block silences the corresponding data-hazard diagnostic (per trigger; unique-index hazards have no trigger and are never suppressed).
  • ExecuteDataMigration plan action carrying the spliced SQL. Executing a plan containing one requires a provider that recognizes it (4.3+); plans with no matched blocks are unaffected.

4.3.1

Fixed

  • The diff now shows an added or removed column’s default expression and identity marker, so a column definition reads the same everywhere it appears.
  • DDL syntax errors now name the file the error was found in, alongside the existing line and column.
  • Import no longer repeats the CREATE SCHEMA statement in every object file; only the per-schema header declares the schema.
  • Import now writes the per-schema header to <schema>/schema.sql instead of <schema>.sql.

4.4.0

Added

  • Unified SCRIPT statement. SCRIPT '<name>' RUN [ALWAYS | ONCE] ON <event> AS $$…$$; is the new canonical form of deployment scripts and data migrations. The event is a deployment bookend (PRE DEPLOYMENT / POST DEPLOYMENT) or a structural change (ADD COLUMN / ALTER COLUMN TYPE / ADD CONSTRAINT with a target path);
  • RunCondition on scripts and data migrations, carrying the parsed RUN clause.
  • The backend state store now carries the recorded script executions.
  • A RUN ONCE script is recorded on a successful apply and skipped by later plans. A recorded script whose body has since changed stays skipped and warns.
  • Migrations in schema templates. A MIGRATION block can now be declared inside a TEMPLATE … BEGIN … END; body with an unqualified table.member path; applying the template instantiates the block once per target schema. The {schema} token in the block’s SQL is replaced with each target schema’s name.

Changed

  • Script names must now be unique across the project (they identify scripts in diagnostics and run-once tracking). A named block declared in a template applied to multiple schemas can include the {schema} token in its name to keep instances distinct.
  • DdlWriter renders deployment scripts and named data migrations in the SCRIPT form; anonymous migrations keep the legacy spelling.

Deprecated

  • The PRE|POST DEPLOYMENT '<name>' AS $$…$$; and MIGRATION ['name'] FOR <trigger> <path> AS $$…$$; forms. Both still parse into the same model, and plan/apply/validate now surface a deprecations warning naming the SCRIPT replacement. They will be removed in NSchema 5.0.

Fixed

  • The formatter no longer re-indents the interior of a dollar-quoted body inside a TEMPLATE block, which grew the indentation on every pass and changed the SQL a routine or migration body carries.

4.5.0

Added

  • Public state access. The recorded state is now a public model.
  • ISchemaStateManager, exposed as app.State, facilitates reading and writing the recorded state, with an optional ReadRaw/WriteRaw methods for moving the serialized payload without interpreting it.

Changed

  • Planning with an unreadable state payload now fails with a diagnostic instead of throwing.

4.6.0 Latest

Added

  • Public desired-schema access. IDesiredSchemaProvider is now public and exposed as app.DesiredSchema.
  • Hash on Script and DataMigration. For reading the canonical hash of the body.

Changed

  • Refresh no longer silently replaces a state payload it cannot read: it fails unless RefreshArguments.Force is set, and a forced replacement carries a warning that the run-once script ledger was reset. The state capture after an apply still replaces an unreadable payload (the SQL has already run), with the same warning.