Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit da3fe65

Browse files
lathiarbCommitfest Bot
authored and
Commitfest Bot
committed
Support NOT VALID and VALIDATE CONSTRAINT for named NOT NULL constraints.
Commit also add support for pg_dump to dump NOT VALID named NOT NULL constraints, testcases as well as documentation changes.
1 parent 42534a8 commit da3fe65

File tree

28 files changed

+1083
-101
lines changed

28 files changed

+1083
-101
lines changed

contrib/postgres_fdw/postgres_fdw.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5549,7 +5549,15 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
55495549
"SELECT relname, "
55505550
" attname, "
55515551
" format_type(atttypid, atttypmod), "
5552-
" attnotnull, "
5552+
" attnotnull, ");
5553+
5554+
/* NOT VALID NOT NULL columns are supported since Postgres 18 */
5555+
if (PQserverVersion(conn) >= 180000)
5556+
appendStringInfoString(&buf, "attnotnullvalid, ");
5557+
else
5558+
appendStringInfoString(&buf, "attnotnull AS attnotnullvalid, ");
5559+
5560+
appendStringInfoString(&buf,
55535561
" pg_get_expr(adbin, adrelid), ");
55545562

55555563
/* Generated columns are supported since Postgres 12 */
@@ -5651,6 +5659,7 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
56515659
char *attname;
56525660
char *typename;
56535661
char *attnotnull;
5662+
char *attnotnullvalid;
56545663
char *attgenerated;
56555664
char *attdefault;
56565665
char *collname;
@@ -5663,14 +5672,15 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
56635672
attname = PQgetvalue(res, i, 1);
56645673
typename = PQgetvalue(res, i, 2);
56655674
attnotnull = PQgetvalue(res, i, 3);
5666-
attdefault = PQgetisnull(res, i, 4) ? NULL :
5667-
PQgetvalue(res, i, 4);
5668-
attgenerated = PQgetisnull(res, i, 5) ? NULL :
5675+
attnotnullvalid = PQgetvalue(res, i, 4);
5676+
attdefault = PQgetisnull(res, i, 5) ? NULL :
56695677
PQgetvalue(res, i, 5);
5670-
collname = PQgetisnull(res, i, 6) ? NULL :
5678+
attgenerated = PQgetisnull(res, i, 6) ? NULL :
56715679
PQgetvalue(res, i, 6);
5672-
collnamespace = PQgetisnull(res, i, 7) ? NULL :
5680+
collname = PQgetisnull(res, i, 7) ? NULL :
56735681
PQgetvalue(res, i, 7);
5682+
collnamespace = PQgetisnull(res, i, 8) ? NULL :
5683+
PQgetvalue(res, i, 8);
56745684

56755685
if (first_item)
56765686
first_item = false;
@@ -5714,7 +5724,11 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
57145724

57155725
/* Add NOT NULL if needed */
57165726
if (import_not_null && attnotnull[0] == 't')
5727+
{
57175728
appendStringInfoString(&buf, " NOT NULL");
5729+
if (attnotnullvalid[0] == 'f')
5730+
appendStringInfoString(&buf, " NOT VALID");
5731+
}
57185732
}
57195733
while (++i < numrows &&
57205734
strcmp(PQgetvalue(res, i, 0), tablename) == 0);

doc/src/sgml/catalogs.sgml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1260,7 +1260,16 @@
12601260
<structfield>attnotnull</structfield> <type>bool</type>
12611261
</para>
12621262
<para>
1263-
This column has a not-null constraint.
1263+
This column has a (possibly unvalidated) not-null constraint.
1264+
</para></entry>
1265+
</row>
1266+
1267+
<row>
1268+
<entry role="catalog_table_entry"><para role="column_definition">
1269+
<structfield>attnotnullvalid</structfield> <type>bool</type>
1270+
</para>
1271+
<para>
1272+
Whether the not-null constraint, if one exists, has been validated.
12641273
</para></entry>
12651274
</row>
12661275

doc/src/sgml/ref/alter_table.sgml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
243243
entire table; however, if a valid <literal>CHECK</literal> constraint is
244244
found which proves no <literal>NULL</literal> can exist, then the
245245
table scan is skipped.
246+
If a column has an invalid not-null constraint,
247+
<literal>SET NOT NULL</literal> validates it.
246248
</para>
247249

248250
<para>
@@ -458,8 +460,8 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
458460
<para>
459461
This form adds a new constraint to a table using the same constraint
460462
syntax as <link linkend="sql-createtable"><command>CREATE TABLE</command></link>, plus the option <literal>NOT
461-
VALID</literal>, which is currently only allowed for foreign key
462-
and CHECK constraints.
463+
VALID</literal>, which is currently only allowed for foreign key,
464+
<literal>CHECK</literal> constraints and not-null constraints.
463465
</para>
464466

465467
<para>
@@ -586,7 +588,7 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
586588
<term><literal>VALIDATE CONSTRAINT</literal></term>
587589
<listitem>
588590
<para>
589-
This form validates a foreign key or check constraint that was
591+
This form validates a foreign key, check, or not-null constraint that was
590592
previously created as <literal>NOT VALID</literal>, by scanning the
591593
table to ensure there are no rows for which the constraint is not
592594
satisfied. If the constraint is not enforced, an error is thrown.

src/backend/access/common/tupdesc.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ populate_compact_attribute_internal(Form_pg_attribute src,
7474
dst->atthasmissing = src->atthasmissing;
7575
dst->attisdropped = src->attisdropped;
7676
dst->attgenerated = (src->attgenerated != '\0');
77-
dst->attnotnull = src->attnotnull;
77+
dst->attnullability = !src->attnotnull ? ATTNULLABLE_NONE :
78+
src->attnotnullvalid ? ATTNULLABLE_VALID : ATTNULLABLE_INVALID;
7879

7980
switch (src->attalign)
8081
{
@@ -252,6 +253,7 @@ CreateTupleDescCopy(TupleDesc tupdesc)
252253
Form_pg_attribute att = TupleDescAttr(desc, i);
253254

254255
att->attnotnull = false;
256+
att->attnotnullvalid = false;
255257
att->atthasdef = false;
256258
att->atthasmissing = false;
257259
att->attidentity = '\0';
@@ -298,6 +300,7 @@ CreateTupleDescTruncatedCopy(TupleDesc tupdesc, int natts)
298300
Form_pg_attribute att = TupleDescAttr(desc, i);
299301

300302
att->attnotnull = false;
303+
att->attnotnullvalid = false;
301304
att->atthasdef = false;
302305
att->atthasmissing = false;
303306
att->attidentity = '\0';
@@ -418,6 +421,7 @@ TupleDescCopy(TupleDesc dst, TupleDesc src)
418421
Form_pg_attribute att = TupleDescAttr(dst, i);
419422

420423
att->attnotnull = false;
424+
att->attnotnullvalid = false;
421425
att->atthasdef = false;
422426
att->atthasmissing = false;
423427
att->attidentity = '\0';
@@ -464,6 +468,7 @@ TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
464468

465469
/* since we're not copying constraints or defaults, clear these */
466470
dstAtt->attnotnull = false;
471+
dstAtt->attnotnullvalid = false;
467472
dstAtt->atthasdef = false;
468473
dstAtt->atthasmissing = false;
469474
dstAtt->attidentity = '\0';
@@ -613,6 +618,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
613618
return false;
614619
if (attr1->attnotnull != attr2->attnotnull)
615620
return false;
621+
if (attr1->attnotnullvalid != attr2->attnotnullvalid)
622+
return false;
616623
if (attr1->atthasdef != attr2->atthasdef)
617624
return false;
618625
if (attr1->attidentity != attr2->attidentity)
@@ -841,6 +848,7 @@ TupleDescInitEntry(TupleDesc desc,
841848
att->attndims = attdim;
842849

843850
att->attnotnull = false;
851+
att->attnotnullvalid = false;
844852
att->atthasdef = false;
845853
att->atthasmissing = false;
846854
att->attidentity = '\0';
@@ -904,6 +912,7 @@ TupleDescInitBuiltinEntry(TupleDesc desc,
904912
att->attndims = attdim;
905913

906914
att->attnotnull = false;
915+
att->attnotnullvalid = false;
907916
att->atthasdef = false;
908917
att->atthasmissing = false;
909918
att->attidentity = '\0';

src/backend/bootstrap/bootstrap.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,9 @@ DefineAttr(char *name, char *type, int attnum, int nullness)
615615
attrtypes[attnum]->attnotnull = true;
616616
}
617617
}
618+
619+
/* Not-null constraints on system catalogs are always valid. */
620+
attrtypes[attnum]->attnotnullvalid = attrtypes[attnum]->attnotnull;
618621
}
619622

620623

src/backend/catalog/genbki.pl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,9 @@ sub morph_row_for_pgattr
986986
$row->{attnotnull} = 'f';
987987
}
988988

989+
# Not-null constraints on system catalogs are always valid.
990+
$row->{attnotnullvalid} = $row->{attnotnull};
991+
989992
Catalog::AddDefaultValues($row, $pgattr_schema, 'pg_attribute');
990993
return;
991994
}

src/backend/catalog/heap.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ static const FormData_pg_attribute a1 = {
151151
.attalign = TYPALIGN_SHORT,
152152
.attstorage = TYPSTORAGE_PLAIN,
153153
.attnotnull = true,
154+
.attnotnullvalid = true,
154155
.attislocal = true,
155156
};
156157

@@ -164,6 +165,7 @@ static const FormData_pg_attribute a2 = {
164165
.attalign = TYPALIGN_INT,
165166
.attstorage = TYPSTORAGE_PLAIN,
166167
.attnotnull = true,
168+
.attnotnullvalid = true,
167169
.attislocal = true,
168170
};
169171

@@ -177,6 +179,7 @@ static const FormData_pg_attribute a3 = {
177179
.attalign = TYPALIGN_INT,
178180
.attstorage = TYPSTORAGE_PLAIN,
179181
.attnotnull = true,
182+
.attnotnullvalid = true,
180183
.attislocal = true,
181184
};
182185

@@ -190,6 +193,7 @@ static const FormData_pg_attribute a4 = {
190193
.attalign = TYPALIGN_INT,
191194
.attstorage = TYPSTORAGE_PLAIN,
192195
.attnotnull = true,
196+
.attnotnullvalid = true,
193197
.attislocal = true,
194198
};
195199

@@ -203,6 +207,7 @@ static const FormData_pg_attribute a5 = {
203207
.attalign = TYPALIGN_INT,
204208
.attstorage = TYPSTORAGE_PLAIN,
205209
.attnotnull = true,
210+
.attnotnullvalid = true,
206211
.attislocal = true,
207212
};
208213

@@ -222,6 +227,7 @@ static const FormData_pg_attribute a6 = {
222227
.attalign = TYPALIGN_INT,
223228
.attstorage = TYPSTORAGE_PLAIN,
224229
.attnotnull = true,
230+
.attnotnullvalid = true,
225231
.attislocal = true,
226232
};
227233

@@ -753,6 +759,7 @@ InsertPgAttributeTuples(Relation pg_attribute_rel,
753759
slot[slotCount]->tts_values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(attrs->attstorage);
754760
slot[slotCount]->tts_values[Anum_pg_attribute_attcompression - 1] = CharGetDatum(attrs->attcompression);
755761
slot[slotCount]->tts_values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(attrs->attnotnull);
762+
slot[slotCount]->tts_values[Anum_pg_attribute_attnotnullvalid - 1] = BoolGetDatum(attrs->attnotnullvalid);
756763
slot[slotCount]->tts_values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(attrs->atthasdef);
757764
slot[slotCount]->tts_values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(attrs->atthasmissing);
758765
slot[slotCount]->tts_values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(attrs->attidentity);
@@ -1714,6 +1721,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
17141721

17151722
/* Remove any not-null constraint the column may have */
17161723
attStruct->attnotnull = false;
1724+
attStruct->attnotnullvalid = false;
17171725

17181726
/* Unset this so no one tries to look up the generation expression */
17191727
attStruct->attgenerated = '\0';
@@ -2616,12 +2624,17 @@ AddRelationNewConstraints(Relation rel,
26162624
errmsg("cannot add not-null constraint on system column \"%s\"",
26172625
strVal(linitial(cdef->keys))));
26182626

2627+
Assert(cdef->initially_valid != cdef->skip_validation);
2628+
26192629
/*
26202630
* If the column already has a not-null constraint, we don't want
2621-
* to add another one; just adjust inheritance status as needed.
2631+
* to add another one; adjust inheritance status as needed. This
2632+
* also checks whether the existing constraint matches the
2633+
* requested validity.
26222634
*/
2623-
if (AdjustNotNullInheritance(RelationGetRelid(rel), colnum,
2624-
is_local, cdef->is_no_inherit))
2635+
if (AdjustNotNullInheritance(rel, colnum, is_local,
2636+
cdef->is_no_inherit,
2637+
cdef->skip_validation))
26252638
continue;
26262639

26272640
/*

0 commit comments

Comments
 (0)