From 19295ca03945f0215a04a23ffc3e61dbb6add610 Mon Sep 17 00:00:00 2001 From: Valerie Chiang Date: Wed, 14 Oct 2026 12:52:57 -0400 Subject: [PATCH 1/3] docs: document EXCLUDE ALL NOT NULL CONSTRAINTS for Postgres tables Co-Authored-By: Claude Opus 5.5 --- .../ingest-data/postgres/source-versioning.md | 35 +++++++++++++++---- .../data/examples/create_table_postgres.yml | 6 ++-- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/doc/user/content/ingest-data/postgres/source-versioning.md b/doc/user/content/ingest-data/postgres/source-versioning.md index eab23be924486..9b389aec9c928 100644 --- a/doc/user/content/ingest-data/postgres/source-versioning.md +++ b/doc/user/content/ingest-data/postgres/source-versioning.md @@ -21,7 +21,7 @@ table schema changes seamlessly, specifically: - Adding a column in the upstream database. - Dropping a column in the upstream database. -- Dropping a `PRIMARY KEY` or `UNIQUE` constraint in the upstream database. +- Dropping a `PRIMARY KEY`, `UNIQUE`, or `NOT NULL` constraint in the upstream database. This guide walks you through how to handle these changes without any downtime in Materialize. @@ -189,10 +189,10 @@ has been altered. ## Handle upstream constraint drop -{{< warn-if-unreleased "v26.42" >}} +{{< warn-if-unreleased "v26.47" >}} {{< public-preview >}} -Excluding constraints with `EXCLUDE CONSTRAINTS` or `EXCLUDE ALL CONSTRAINTS` +Excluding constraints with `EXCLUDE CONSTRAINTS`, `EXCLUDE ALL NOT NULL CONSTRAINTS`, or `EXCLUDE ALL CONSTRAINTS` {{< /public-preview >}} Materialize ignores the following constraints: foreign key, `CHECK`, and @@ -218,12 +218,35 @@ Materialize does not record the excluded constraint as a key of `v4.T`. `EXCLUDE CONSTRAINTS` only accepts `PRIMARY KEY` and `UNIQUE` constraint names. A `NOT NULL` constraint on a specific column cannot be excluded by -name. To drop a `NOT NULL` constraint safely, use `EXCLUDE ALL CONSTRAINTS` -instead, which records no constraints at all: the table has no keys and every -column is nullable, so any later constraint drop is safe. +name. To drop `NOT NULL` constraints safely, use `EXCLUDE ALL NOT NULL +CONSTRAINTS`. Every column is ingested as nullable, while `PRIMARY KEY` and +`UNIQUE` constraints are still recorded: ```sql CREATE SCHEMA v4; +CREATE TABLE v4.T + FROM SOURCE my_source(REFERENCE public.T) WITH (EXCLUDE ALL NOT NULL CONSTRAINTS); +``` + +Columns in a `PRIMARY KEY` remain `NOT NULL`, unless the primary key is also +excluded with `EXCLUDE CONSTRAINTS`. Columns in a `UNIQUE` constraint become +nullable, so Materialize no longer uses that constraint as a key when +optimizing queries. The exception is a `UNIQUE NULLS NOT DISTINCT` constraint +(PostgreSQL 15+), which Materialize still uses as a key. Dropping a `PRIMARY +KEY` or `UNIQUE` constraint upstream still puts the table into an error state +unless that constraint is also excluded. The two options combine: + +```sql +CREATE TABLE v4.T + FROM SOURCE my_source(REFERENCE public.T) + WITH (EXCLUDE ALL NOT NULL CONSTRAINTS, EXCLUDE CONSTRAINTS ('t_pkey')); +``` + +To record no constraints at all, use `EXCLUDE ALL CONSTRAINTS`: the table has +no keys and every column is nullable, so any later constraint drop is safe. +Queries that relied on those keys for optimization may run slower. + +```sql CREATE TABLE v4.T FROM SOURCE my_source(REFERENCE public.T) WITH (EXCLUDE ALL CONSTRAINTS); ``` diff --git a/doc/user/data/examples/create_table_postgres.yml b/doc/user/data/examples/create_table_postgres.yml index 8881822c8dfbd..f71b1ee27c4d4 100644 --- a/doc/user/data/examples/create_table_postgres.yml +++ b/doc/user/data/examples/create_table_postgres.yml @@ -10,6 +10,7 @@ | EXCLUDE COLUMNS ( [, ...]) | EXCLUDE CONSTRAINTS ('' [, ...]) | EXCLUDE ALL CONSTRAINTS + | EXCLUDE ALL NOT NULL CONSTRAINTS | PARTITION BY ( [, ...]) [, ...] )] @@ -67,8 +68,9 @@ |--------|-------------| | `TEXT COLUMNS ( [, ...])` |*Optional.* If specified, decode data as `text` for the listed column(s),such as for unsupported data types. See also [supported types](#supported-data-types). | | `EXCLUDE COLUMNS ( [, ...])`| *Optional.* If specified,exclude the listed column(s) from the table, such as for unsupported data types. See also [supported types](#supported-data-types).| - | `EXCLUDE CONSTRAINTS ('' [, ...])` | ***Public preview.** This option is under active development and may have stability or performance issues.* *Optional.* If specified, do not record the listed upstream `PRIMARY KEY` or `UNIQUE` constraint(s) as keys of the table, so that dropping them upstream does not put the table into an error state. Constraint names are string literals matched exactly, including case. `NOT NULL` constraints cannot be excluded by name, use `EXCLUDE ALL CONSTRAINTS` instead. See [Handle upstream constraint drop](/ingest-data/postgres/source-versioning/#handle-upstream-constraint-drop). | - | `EXCLUDE ALL CONSTRAINTS` | ***Public preview.** This option is under active development and may have stability or performance issues.* *Optional.* If specified, record no upstream constraints: the table has no keys and every column is nullable, so dropping any `PRIMARY KEY`, `UNIQUE`, or `NOT NULL` constraint upstream does not put the table into an error state. Cannot be combined with `EXCLUDE CONSTRAINTS`. | + | `EXCLUDE CONSTRAINTS ('' [, ...])` | ***Public preview.** This option is under active development and may have stability or performance issues.* *Optional.* If specified, do not record the listed upstream `PRIMARY KEY` or `UNIQUE` constraint(s) as keys of the table, so that dropping them upstream does not put the table into an error state. Constraint names are string literals matched exactly, including case. `NOT NULL` constraints cannot be excluded by name; use `EXCLUDE ALL NOT NULL CONSTRAINTS` instead. See [Handle upstream constraint drop](/ingest-data/postgres/source-versioning/#handle-upstream-constraint-drop). | + | `EXCLUDE ALL CONSTRAINTS` | ***Public preview.** This option is under active development and may have stability or performance issues.* *Optional.* If specified, record no upstream constraints: the table has no keys and every column is nullable, so dropping any `PRIMARY KEY`, `UNIQUE`, or `NOT NULL` constraint upstream does not put the table into an error state. Cannot be combined with `EXCLUDE CONSTRAINTS`. To keep keys and only relax nullability, use `EXCLUDE ALL NOT NULL CONSTRAINTS` instead. | + | `EXCLUDE ALL NOT NULL CONSTRAINTS` | ***Public preview.** This option is under active development and may have stability or performance issues.* *Optional.* If specified, ingest every column as nullable, so that dropping any `NOT NULL` constraint upstream does not put the table into an error state. `PRIMARY KEY` and `UNIQUE` constraints are still recorded; to drop one of those safely, also list it in `EXCLUDE CONSTRAINTS`. Columns in a `PRIMARY KEY` remain `NOT NULL`, unless the primary key is also excluded with `EXCLUDE CONSTRAINTS`. Columns in a `UNIQUE` constraint become nullable, so that constraint is no longer used as a key for query optimization, unless it is a `UNIQUE NULLS NOT DISTINCT` constraint. See [Handle upstream constraint drop](/ingest-data/postgres/source-versioning/#handle-upstream-constraint-drop). | | `PARTITION BY ( [, ...])` | {{< include-md file="content/headless/partition-by-option-description.md" >}} | results: | {{< include-md From 1e974892ff2f60eacd5575f4f978fbac82189cc6 Mon Sep 17 00:00:00 2001 From: Valerie Chiang Date: Wed, 14 Oct 2026 16:42:26 -0400 Subject: [PATCH 2/3] docs: restructure NOT NULL exclusion guidance per review Co-Authored-By: Claude Opus 5.5 --- .../ingest-data/postgres/source-versioning.md | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/doc/user/content/ingest-data/postgres/source-versioning.md b/doc/user/content/ingest-data/postgres/source-versioning.md index 9b389aec9c928..c480549990883 100644 --- a/doc/user/content/ingest-data/postgres/source-versioning.md +++ b/doc/user/content/ingest-data/postgres/source-versioning.md @@ -216,11 +216,11 @@ CREATE TABLE v4.T Materialize does not record the excluded constraint as a key of `v4.T`. +#### Excluding nullability constraints + `EXCLUDE CONSTRAINTS` only accepts `PRIMARY KEY` and `UNIQUE` constraint -names. A `NOT NULL` constraint on a specific column cannot be excluded by -name. To drop `NOT NULL` constraints safely, use `EXCLUDE ALL NOT NULL -CONSTRAINTS`. Every column is ingested as nullable, while `PRIMARY KEY` and -`UNIQUE` constraints are still recorded: +names. Individual `NOT NULL` constraints cannot be excluded by name. To drop +`NOT NULL` constraints safely, use `EXCLUDE ALL NOT NULL CONSTRAINTS`: ```sql CREATE SCHEMA v4; @@ -228,19 +228,25 @@ CREATE TABLE v4.T FROM SOURCE my_source(REFERENCE public.T) WITH (EXCLUDE ALL NOT NULL CONSTRAINTS); ``` -Columns in a `PRIMARY KEY` remain `NOT NULL`, unless the primary key is also -excluded with `EXCLUDE CONSTRAINTS`. Columns in a `UNIQUE` constraint become -nullable, so Materialize no longer uses that constraint as a key when -optimizing queries. The exception is a `UNIQUE NULLS NOT DISTINCT` constraint -(PostgreSQL 15+), which Materialize still uses as a key. Dropping a `PRIMARY -KEY` or `UNIQUE` constraint upstream still puts the table into an error state -unless that constraint is also excluded. The two options combine: - -```sql -CREATE TABLE v4.T - FROM SOURCE my_source(REFERENCE public.T) - WITH (EXCLUDE ALL NOT NULL CONSTRAINTS, EXCLUDE CONSTRAINTS ('t_pkey')); -``` +Note that when excluding `NOT NULL` constraints: + +- Primary key columns remain `NOT NULL`, unless the primary key is also + excluded with `EXCLUDE CONSTRAINTS`. +- Columns in a `UNIQUE` constraint become nullable. This means Materialize no + longer uses that constraint as a key when optimizing queries, which might + reduce query performance. `UNIQUE NULLS NOT DISTINCT` constraints + (PostgreSQL 15+) are still used as keys. +- `PRIMARY KEY` and `UNIQUE` constraints are still recorded. Dropping one + upstream still puts the table into an error state unless it is also + excluded: + + ```sql + CREATE TABLE v4.T + FROM SOURCE my_source(REFERENCE public.T) + WITH (EXCLUDE ALL NOT NULL CONSTRAINTS, EXCLUDE CONSTRAINTS ('t_pkey')); + ``` + +#### Excluding all constraints To record no constraints at all, use `EXCLUDE ALL CONSTRAINTS`: the table has no keys and every column is nullable, so any later constraint drop is safe. From 86510154cbbbf4972d8746d0923ddb608d90949f Mon Sep 17 00:00:00 2001 From: Valerie Chiang Date: Wed, 14 Oct 2026 16:52:56 -0400 Subject: [PATCH 3/3] docs: drop unreleased warning for constraint exclusion Co-Authored-By: Claude Opus 5.5 --- doc/user/content/ingest-data/postgres/source-versioning.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/user/content/ingest-data/postgres/source-versioning.md b/doc/user/content/ingest-data/postgres/source-versioning.md index c480549990883..e833920127ae7 100644 --- a/doc/user/content/ingest-data/postgres/source-versioning.md +++ b/doc/user/content/ingest-data/postgres/source-versioning.md @@ -189,8 +189,6 @@ has been altered. ## Handle upstream constraint drop -{{< warn-if-unreleased "v26.47" >}} - {{< public-preview >}} Excluding constraints with `EXCLUDE CONSTRAINTS`, `EXCLUDE ALL NOT NULL CONSTRAINTS`, or `EXCLUDE ALL CONSTRAINTS` {{< /public-preview >}}