summaryrefslogtreecommitdiff
path: root/src/bin/pg_dump/common.c
diff options
context:
space:
mode:
authorÁlvaro Herrera <alvherre@alvh.no-ip.org>2024-11-08 13:28:48 +0100
committerÁlvaro Herrera <alvherre@alvh.no-ip.org>2024-11-08 13:28:48 +0100
commit14e87ffa5c543b5f30ead7413084c25f7735039f (patch)
tree2af8f459779aef83acf20fbb8ef480d2ddc2af89 /src/bin/pg_dump/common.c
parent075acdd93388c080c0fb0aca5723144ad7a56dac (diff)
Add pg_constraint rows for not-null constraints
We now create contype='n' pg_constraint rows for not-null constraints on user tables. Only one such constraint is allowed for a column. We propagate these constraints to other tables during operations such as adding inheritance relationships, creating and attaching partitions and creating tables LIKE other tables. These related constraints 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 or remove it, instead matching by the name of the column that they apply to. This means we don't require the constraint names to be identical across a hierarchy. The inheritance status of these constraints can be controlled: now we can be sure that if a parent table has one, then all children will have it as well. They can optionally be marked NO INHERIT, and then children are free not to have one. (There's currently no support for altering a NO INHERIT constraint into inheriting down the hierarchy, but that's a desirable future feature.) This also opens the door for having these constraints be marked NOT VALID, as well as allowing UNIQUE+NOT NULL to be used for functional dependency determination, as envisioned by commit e49ae8d3bc58. It's likely possible to allow DEFERRABLE constraints as followup work, as well. psql shows these constraints in \d+, though we may want to reconsider if this turns out to be too noisy. Earlier versions of this patch hid constraints that were on the same columns of the primary key, but I'm not sure that that's very useful. If clutter is a problem, we might be better off inventing a new \d++ command and not showing the constraints in \d+. For now, we omit these constraints on system catalog columns, because they're unlikely to achieve anything. The main difference to the previous attempt at this (b0e96f311985) is that we now require that such a constraint always exists when a primary key is in the column; we didn't require this previously which had a number of unpalatable consequences. With this requirement, the code is easier to reason about. For example: - We no longer have "throwaway constraints" during pg_dump. We needed those for the case where a table had a PK without a not-null underneath, to prevent a slow scan of the data during restore of the PK creation, which was particularly problematic for pg_upgrade. - We no longer have to cope with attnotnull being set spuriously in case a primary key is dropped indirectly (e.g., via DROP COLUMN). Some bits of code in this patch were authored by Jian He. Author: Álvaro Herrera <alvherre@alvh.no-ip.org> Author: Bernd Helmle <mailings@oopsware.de> Reviewed-by: 何建 (jian he) <jian.universality@gmail.com> Reviewed-by: 王刚 (Tender Wang) <tndrwang@gmail.com> Reviewed-by: Justin Pryzby <pryzby@telsasoft.com> Reviewed-by: Peter Eisentraut <peter.eisentraut@enterprisedb.com> Reviewed-by: Dean Rasheed <dean.a.rasheed@gmail.com> Discussion: https://postgr.es/m/202408310358.sdhumtyuy2ht@alvherre.pgsql
Diffstat (limited to 'src/bin/pg_dump/common.c')
-rw-r--r--src/bin/pg_dump/common.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 9b2d34e2815..33d323085f5 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -83,7 +83,8 @@ static catalogid_hash *catalogIdHash = NULL;
static void flagInhTables(Archive *fout, TableInfo *tblinfo, int numTables,
InhInfo *inhinfo, int numInherits);
static void flagInhIndexes(Archive *fout, TableInfo *tblinfo, int numTables);
-static void flagInhAttrs(Archive *fout, TableInfo *tblinfo, int numTables);
+static void flagInhAttrs(Archive *fout, DumpOptions *dopt, TableInfo *tblinfo,
+ int numTables);
static int strInArray(const char *pattern, char **arr, int arr_size);
static IndxInfo *findIndexByOid(Oid oid);
@@ -204,7 +205,7 @@ getSchemaData(Archive *fout, int *numTablesPtr)
getTableAttrs(fout, tblinfo, numTables);
pg_log_info("flagging inherited columns in subtables");
- flagInhAttrs(fout, tblinfo, numTables);
+ flagInhAttrs(fout, fout->dopt, tblinfo, numTables);
pg_log_info("reading partitioning data");
getPartitioningInfo(fout);
@@ -452,7 +453,8 @@ flagInhIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
* What we need to do here is:
*
* - Detect child columns that inherit NOT NULL bits from their parents, so
- * that we needn't specify that again for the child.
+ * that we needn't specify that again for the child. (Versions >= 18 no
+ * longer need this.)
*
* - Detect child columns that have DEFAULT NULL when their parents had some
* non-null default. In this case, we make up a dummy AttrDefInfo object so
@@ -472,9 +474,8 @@ flagInhIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
* modifies tblinfo
*/
static void
-flagInhAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
+flagInhAttrs(Archive *fout, DumpOptions *dopt, TableInfo *tblinfo, int numTables)
{
- DumpOptions *dopt = fout->dopt;
int i,
j,
k;
@@ -536,7 +537,15 @@ flagInhAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
{
AttrDefInfo *parentDef = parent->attrdefs[inhAttrInd];
- foundNotNull |= parent->notnull[inhAttrInd];
+ /*
+ * Account for each parent having a not-null constraint.
+ * In versions 18 and later, we don't need this (and those
+ * didn't have NO INHERIT.)
+ */
+ if (fout->remoteVersion < 180000 &&
+ parent->notnull_constrs[inhAttrInd] != NULL)
+ foundNotNull = true;
+
foundDefault |= (parentDef != NULL &&
strcmp(parentDef->adef_expr, "NULL") != 0 &&
!parent->attgenerated[inhAttrInd]);
@@ -554,8 +563,13 @@ flagInhAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
}
}
- /* Remember if we found inherited NOT NULL */
- tbinfo->inhNotNull[j] = foundNotNull;
+ /*
+ * In versions < 18, for lack of a better system, we arbitrarily
+ * decide that a not-null constraint is not locally defined if at
+ * least one of the parents has it.
+ */
+ if (fout->remoteVersion < 180000 && foundNotNull)
+ tbinfo->notnull_islocal[j] = false;
/*
* Manufacture a DEFAULT NULL clause if necessary. This breaks