Skip to content

All versions since 5.1.0

5.1.0

Changed

  • CREATE SCHEMA no longer hedges with IF NOT EXISTS. This was a hack from a much earlier version that should have been removed long ago, but I forgot about it.
  • public is reported as a schema Postgres provides. It is a container rather than something a migration creates, and declaring it is an error.

5.2.0

Added

  • The engine’s type vocabulary is captured. Introspection now records the types Postgres and its installed extensions provide (pg_catalog base, range, and multirange types, arrays included) as NativeTypes in the snapshot, spelled in the model’s canonical names. With a captured vocabulary, a plan can verify every type the project references — pg_catalog.tsvector and text[] columns on imported schemas now resolve instead of blocking, and a reference to a type nothing provides is reported at plan time.
  • Extension-provided types record their provenance. A type an extension installs (e.g. citext, arrays included) carries ProvidedBy, so a plan that drops the extension accounts for everything still using its types.
  • pg_catalog is reported as a schema Postgres provides, alongside public.

5.3.0

Changed

  • A create is a create. CREATE FUNCTION, CREATE PROCEDURE, and CREATE VIEW render without OR REPLACE when the plan is creating; the in-place forms render only for the new replace actions, where the plan knows the object exists.
  • Trigger changes replace in place. A changed trigger renders as CREATE OR REPLACE TRIGGER instead of a drop and a create.

Fixed

  • Functions no longer fail to create when they reference tables from the same plan. NSchema.Core 5.3 orders routines after the tables they may reference, so a LANGUAGE sql body or a rowtype signature resolves during a rebuild.

5.4.0

Added

  • Aggregates. CREATE AGGREGATE renders and introspects: the definition is reconstructed from pg_aggregate (canonical option tuple, non-default options only), a replacement decomposes to drop + create (Postgres has no CREATE OR REPLACE AGGREGATE), and every addressing statement carries the signature Postgres requires.

Fixed

  • A created materialized view brings its indexes. Creating a materialized view now renders its index definitions alongside it; previously they were left out of the plan.

5.5.0

Added

  • An index on a plain view is reported, not attempted.
  • An XML index is reported. Postgres indexes an xml column as an opaque value and has no shredded node table to build over, so the XML index forms are refused rather than flattened to an ordinary index.
  • A schema-bound view is reported.

5.6.0

Added

  • SupportsRestrict is declared, so RESTRICT is rendered rather than dropped.
  • Generated columns are reported as stored, which is the only kind Postgres has. A project declaring a virtual one now gets a warning that it will be stored, rather than that difference passing unremarked.

Changed

  • The build now writes the full dependency closure beside the assembly (CopyLocalLockFileAssemblies), so a dotnet build of this project can be loaded directly by PLUGIN ( path = '...' ) without being packed first. Package contents are unchanged.

Fixed

  • ON DELETE RESTRICT and ON UPDATE RESTRICT are no longer read as NO ACTION. Postgres records RESTRICT as confdeltype = 'r', which introspection mapped onto NO ACTION because the model had nowhere else to put it.
  • Table partitioning is reported at import. NSchema does not model it, so a partitioned table arrives as a plain one and each partition as an unrelated table, but it is now said out loud rather than passed over.

5.6.1 Latest

Fixed

  • The canonical types Postgres renders are no longer refused. tinyint, nchar, nvarchar and binary are written as smallint, character, character varying and bytea, but the engine’s vocabulary is read from its own catalog and so never names them, leaving a plan that rendered the column correctly and then refused it as an unresolved type. They now compare equal to the type they are rendered as.
  • A varbinary length no longer drifts. bytea carries none, so a declared one was never read back and every plan asked to change the column again.
  • A sequence option declared with the default value now settles.
  • An identity column reports no minimum where none was declared.
  • An identity option reset to the engine’s default is now written.
  • Changing an identity’s increment or minimum no longer restarts its counter. RESTART was appended to every identity alter. Only a start that actually moved carries a RESTART now, and that case is reported as a data hazard.