Skip to content

Commit 32c43aa

Browse files
author
Antonin Houska
committed
Copy NOT NULL constraints in PG 18.
1 parent dce5a2d commit 32c43aa

File tree

2 files changed

+51
-15
lines changed

2 files changed

+51
-15
lines changed

README.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,22 +139,27 @@ table. It's recommended to handle constraints creation this way:
139139
but it does not hurt to check them in the target table, especially if the
140140
column data type is being changed.)
141141

142-
2. Add NOT NULL constraints. `rewrite_table()` by-passes validation of these,
143-
but all the rows it inserts into the target table must have been validated
144-
in the source table. Even if the column data tape is different in the
145-
target table, the data type conversion should not turn non-NULL value to
146-
NULL or vice versa.
142+
2. If the version of PostgreSQL server is 17 or lower, add NOT NULL
143+
constraints. `rewrite_table()` by-passes validation of these, but all the
144+
rows it inserts into the target table must have been validated in the
145+
source table. Even if the column data tape is different in the target
146+
table, the data type conversion should not turn non-NULL value to NULL or
147+
vice versa.
147148

148149
3. CHECK constraints are created automatically by `rewrite_table()` when all
149150
the data changes have been applied to the target table. However, these
150151
constraints are created as NOT VALID, so you need to use the `ALTER TABLE
151152
... VALIDATE CONSTRAINT ...` command to validate them.
152153

153154
(The function does not create these constraints immediately as valid,
154-
because that would imply blocking access to the table for significant
155+
because that could imply blocking access to the table for significant
155156
time.)
156157

157-
4. FOREIGN KEY constraints are also created automatically and need to be
158+
4. If the version of PostgreSQL server is 18 or higher, NOT NULL constraints
159+
are also created automatically and need to be validated using the `ALTER
160+
TABLE ... VALIDATE CONSTRAINT ...` command.
161+
162+
5. FOREIGN KEY constraints are also created automatically and need to be
158163
validated using the `ALTER TABLE ... VALIDATE CONSTRAINT ...` command,
159164
unless the referencing table is partitioned: the NOT VALID option is
160165
currently not supported for partitioned tables.
@@ -165,7 +170,7 @@ table. It's recommended to handle constraints creation this way:
165170
to minimize the risk that applications modify the database in a way that
166171
violates the constraints.
167172

168-
5. Drop all foreign keys involving the source table.
173+
6. Drop all foreign keys involving the source table.
169174

170175
You probably want to drop the source table anyway, but if you don't, you
171176
should at least drop its FOREIGN KEY constraints. As the table was

pg_rewrite.c

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ static void dump_fk_constraint(HeapTuple tup, Oid relid_dst,
152152
StringInfo buf);
153153
static void dump_check_constraint(Oid relid_dst, const char *relname_dst,
154154
HeapTuple tup, StringInfo buf);
155+
#if PG_VERSION_NUM >= 180000
156+
static void dump_null_constraint(Oid relid_dst, const char *relname_dst,
157+
HeapTuple tup, StringInfo buf);
158+
#endif
155159
static void dump_constraint_common(const char *nsp, const char *relname,
156160
Form_pg_constraint con, StringInfo buf);
157161
static int decompile_column_index_array(Datum column_index_array, Oid relId,
@@ -2916,13 +2920,15 @@ copy_constraints(Oid relid_dst, const char *relname_dst, Oid relid_src)
29162920
break;
29172921
}
29182922

2919-
/*
2920-
* TODO Is it o.k. to assume that no data type conversion can
2921-
* change the validity of NOT NULL constraint? The problem is
2922-
* that NOT NULL cannot be set NOT VALID in PG < 18. At least
2923-
* in PG >= 18 we probably should handle NOT NULL in the same
2924-
* way as FK / CHECK constraints.
2925-
*/
2923+
#if PG_VERSION_NUM >= 180000
2924+
case CONSTRAINT_NOTNULL:
2925+
{
2926+
if (con->conrelid == relid_src)
2927+
dump_null_constraint(relid_dst, relname_dst, tuple,
2928+
buf);
2929+
break;
2930+
}
2931+
#endif
29262932
default:
29272933
break;
29282934
}
@@ -3183,6 +3189,31 @@ dump_check_constraint(Oid relid_dst, const char *relname_dst, HeapTuple tup,
31833189
con->connoinherit ? " NO INHERIT" : "");
31843190
}
31853191

3192+
#if PG_VERSION_NUM >= 180000
3193+
static void
3194+
dump_null_constraint(Oid relid_dst, const char *relname_dst,
3195+
HeapTuple tup, StringInfo buf)
3196+
{
3197+
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup);
3198+
const char *nsp;
3199+
AttrNumber attnum;
3200+
3201+
Assert(con->contype == CONSTRAINT_NOTNULL);
3202+
3203+
nsp = get_namespace_name(relid_dst);
3204+
dump_constraint_common(nsp, relname_dst, con, buf);
3205+
3206+
attnum = extractNotNullColumn(tup);
3207+
3208+
appendStringInfo(buf, "NOT NULL %s",
3209+
quote_identifier(get_attname(con->conrelid,
3210+
attnum, false)));
3211+
if (((Form_pg_constraint) GETSTRUCT(tup))->connoinherit)
3212+
appendStringInfoString(buf, " NO INHERIT");
3213+
3214+
}
3215+
#endif
3216+
31863217
static void
31873218
dump_constraint_common(const char *nsp, const char *relname,
31883219
Form_pg_constraint con, StringInfo buf)

0 commit comments

Comments
 (0)