summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2023-04-07 19:20:53 +0200
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2023-04-07 19:59:57 +0200
commite056c557aef4006c3dfbf8a4b94b7ae88eb9fd67 (patch)
tree5f3b85e2d7fada1f414bc28387116d9c28d4abe2 /src/include
parentff245a37888ae28da4e6eeacac83f00aa0986340 (diff)
downloadpostgresql-e056c557aef4006c3dfbf8a4b94b7ae88eb9fd67.tar.gz
Catalog NOT NULL constraints
We now create pg_constaint rows for NOT NULL constraints with contype='n'. We propagate these constraints during operations such as adding inheritance relationships, creating and attaching partitions, creating tables LIKE other tables. We mostly follow the well-known rules of conislocal and coninhcount that we have for CHECK constraints, with some adaptations; for example, as opposed to CHECK constraints, we don't match NOT NULL ones by name when descending a hierarchy to alter it; instead we match by column number. This means we don't require the constraint names to be identical across a hierarchy. For now, we omit them from system catalogs. Maybe this is worth reconsidering. We don't support NOT VALID nor DEFERRABLE clauses either; these can be added as separate features later (this patch is already large and complicated enough.) This has been very long in the making. The first patch was written by Bernd Helmle in 2010 to add a new pg_constraint.contype value ('n'), which I (Álvaro) then hijacked in 2011 and 2012, until that one was killed by the realization that we ought to use contype='c' instead: manufactured CHECK constraints. However, later SQL standard development, as well as nonobvious emergent properties of that design (mostly, failure to distinguish them from "normal" CHECK constraints as well as the performance implication of having to test the CHECK expression) led us to reconsider this choice, so now the current implementation uses contype='n' again. In 2016 Vitaly Burovoy also worked on this feature[1] but found no consensus for his proposed approach, which was claimed to be closer to the letter of the standard, requiring additional pg_attribute columns to track the OID of the NOT NULL constraint for that column. [1] https://postgr.es/m/CAKOSWNkN6HSyatuys8xZxzRCR-KL1OkHS5-b9qd9bf1Rad3PLA@mail.gmail.com Author: Álvaro Herrera <alvherre@alvh.no-ip.org> Author: Bernd Helmle <mailings@oopsware.de> Reviewed-by: Justin Pryzby <pryzby@telsasoft.com> Reviewed-by: Peter Eisentraut <peter.eisentraut@enterprisedb.com> Discussion: https://postgr.es/m/CACA0E642A0267EDA387AF2B%40%5B172.26.14.62%5D Discussion: https://postgr.es/m/AANLkTinLXMOEMz+0J29tf1POokKi4XDkWJ6-DDR9BKgU@mail.gmail.com Discussion: https://postgr.es/m/20110707213401.GA27098@alvh.no-ip.org Discussion: https://postgr.es/m/1343682669-sup-2532@alvh.no-ip.org Discussion: https://postgr.es/m/CAKOSWNkN6HSyatuys8xZxzRCR-KL1OkHS5-b9qd9bf1Rad3PLA@mail.gmail.com Discussion: https://postgr.es/m/20220817181249.q7qvj3okywctra3c@alvherre.pgsql
Diffstat (limited to 'src/include')
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/heap.h7
-rw-r--r--src/include/catalog/pg_constraint.h11
-rw-r--r--src/include/commands/tablecmds.h2
-rw-r--r--src/include/nodes/parsenodes.h14
5 files changed, 26 insertions, 10 deletions
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 42e881fafb..e32d50f386 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202304071
+#define CATALOG_VERSION_NO 202304072
#endif
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index d01ab504b6..1683fdcb20 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.h
@@ -34,10 +34,10 @@ typedef struct RawColumnDefault
typedef struct CookedConstraint
{
- ConstrType contype; /* CONSTR_DEFAULT or CONSTR_CHECK */
+ ConstrType contype; /* CONSTR_DEFAULT, CONSTR_CHECK, CONSTR_NOTNULL */
Oid conoid; /* constr OID if created, otherwise Invalid */
char *name; /* name, or NULL if none */
- AttrNumber attnum; /* which attr (only for DEFAULT) */
+ AttrNumber attnum; /* which attr (only for NOTNULL, DEFAULT) */
Node *expr; /* transformed default or check expr */
bool skip_validation; /* skip validation? (only for CHECK) */
bool is_local; /* constraint has local (non-inherited) def */
@@ -113,6 +113,9 @@ extern List *AddRelationNewConstraints(Relation rel,
bool is_local,
bool is_internal,
const char *queryString);
+extern List *AddRelationNotNullConstraints(Relation rel,
+ List *constraints,
+ List *additional_notnulls);
extern void RelationClearMissing(Relation rel);
extern void SetAttrMissing(Oid relid, char *attname, char *value);
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index 16bf5f5576..13573a3cf1 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -181,6 +181,7 @@ DECLARE_ARRAY_FOREIGN_KEY((confrelid, confkey), pg_attribute, (attrelid, attnum)
/* Valid values for contype */
#define CONSTRAINT_CHECK 'c'
#define CONSTRAINT_FOREIGN 'f'
+#define CONSTRAINT_NOTNULL 'n'
#define CONSTRAINT_PRIMARY 'p'
#define CONSTRAINT_UNIQUE 'u'
#define CONSTRAINT_TRIGGER 't'
@@ -237,9 +238,6 @@ extern Oid CreateConstraintEntry(const char *constraintName,
bool conNoInherit,
bool is_internal);
-extern void RemoveConstraintById(Oid conId);
-extern void RenameConstraintById(Oid conId, const char *newname);
-
extern bool ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId,
const char *conname);
extern bool ConstraintNameExists(const char *conname, Oid namespaceid);
@@ -247,6 +245,13 @@ extern char *ChooseConstraintName(const char *name1, const char *name2,
const char *label, Oid namespaceid,
List *others);
+extern HeapTuple findNotNullConstraintAttnum(Relation rel, AttrNumber attnum);
+extern HeapTuple findNotNullConstraint(Relation rel, const char *colname);
+extern AttrNumber extractNotNullColumn(HeapTuple constrTup);
+
+extern void RemoveConstraintById(Oid conId);
+extern void RenameConstraintById(Oid conId, const char *newname);
+
extern void AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
Oid newNspId, bool isType, ObjectAddresses *objsMoved);
extern void ConstraintSetParentConstraint(Oid childConstrId,
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
index 17b9404937..8f7ce96651 100644
--- a/src/include/commands/tablecmds.h
+++ b/src/include/commands/tablecmds.h
@@ -73,6 +73,8 @@ extern ObjectAddress renameatt(RenameStmt *stmt);
extern ObjectAddress RenameConstraint(RenameStmt *stmt);
+extern List *RelationGetNotNullConstraints(Relation relation, bool cooked);
+
extern ObjectAddress RenameRelation(RenameStmt *stmt);
extern void RenameRelationInternal(Oid myrelid,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index cc7b32b279..46bf610764 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2177,6 +2177,7 @@ typedef enum AlterTableType
AT_CookedColumnDefault, /* add a pre-cooked column default */
AT_DropNotNull, /* alter column drop not null */
AT_SetNotNull, /* alter column set not null */
+ AT_SetAttNotNull, /* set attnotnull w/o a constraint */
AT_DropExpression, /* alter column drop expression */
AT_CheckNotNull, /* check column is already marked not null */
AT_SetStatistics, /* alter column set statistics */
@@ -2462,10 +2463,11 @@ typedef struct VariableShowStmt
* Create Table Statement
*
* NOTE: in the raw gram.y output, ColumnDef and Constraint nodes are
- * intermixed in tableElts, and constraints is NIL. After parse analysis,
- * tableElts contains just ColumnDefs, and constraints contains just
- * Constraint nodes (in fact, only CONSTR_CHECK nodes, in the present
- * implementation).
+ * intermixed in tableElts, and constraints and notnullcols are NIL. After
+ * parse analysis, tableElts contains just ColumnDefs, notnullcols has been
+ * filled with not-nullable column names from various sources, and constraints
+ * contains just Constraint nodes (in fact, only CONSTR_CHECK nodes, in the
+ * present implementation).
* ----------------------
*/
@@ -2480,6 +2482,7 @@ typedef struct CreateStmt
PartitionSpec *partspec; /* PARTITION BY clause */
TypeName *ofTypename; /* OF typename */
List *constraints; /* constraints (list of Constraint nodes) */
+ List *nnconstraints; /* NOT NULL constraints (ditto) */
List *options; /* options from WITH clause */
OnCommitAction oncommit; /* what do we do at COMMIT? */
char *tablespacename; /* table space to use, or NULL */
@@ -2568,6 +2571,9 @@ typedef struct Constraint
char *cooked_expr; /* expr, as nodeToString representation */
char generated_when; /* ALWAYS or BY DEFAULT */
+ /* Fields used for "raw" NOT NULL constraints: */
+ char *colname; /* column it applies to */
+
/* Fields used for unique constraints (UNIQUE and PRIMARY KEY): */
bool nulls_not_distinct; /* null treatment for UNIQUE constraints */
List *keys; /* String nodes naming referenced key