47
47
#include "catalog/pg_authid_d.h"
48
48
#include "catalog/pg_cast_d.h"
49
49
#include "catalog/pg_class_d.h"
50
+ #include "catalog/pg_constraint_d.h"
50
51
#include "catalog/pg_default_acl_d.h"
51
52
#include "catalog/pg_largeobject_d.h"
52
53
#include "catalog/pg_largeobject_metadata_d.h"
@@ -5929,6 +5930,7 @@ getTypes(Archive *fout, int *numTypes)
5929
5930
*/
5930
5931
tyinfo[i].nDomChecks = 0;
5931
5932
tyinfo[i].domChecks = NULL;
5933
+ tyinfo[i].notnull = NULL;
5932
5934
if ((tyinfo[i].dobj.dump & DUMP_COMPONENT_DEFINITION) &&
5933
5935
tyinfo[i].typtype == TYPTYPE_DOMAIN)
5934
5936
getDomainConstraints(fout, &(tyinfo[i]));
@@ -7949,27 +7951,33 @@ addConstrChildIdxDeps(DumpableObject *dobj, const IndxInfo *refidx)
7949
7951
static void
7950
7952
getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
7951
7953
{
7952
- int i;
7953
7954
ConstraintInfo *constrinfo;
7954
7955
PQExpBuffer query = createPQExpBuffer();
7955
7956
PGresult *res;
7956
7957
int i_tableoid,
7957
7958
i_oid,
7958
7959
i_conname,
7959
- i_consrc;
7960
+ i_consrc,
7961
+ i_convalidated,
7962
+ i_contype;
7960
7963
int ntups;
7961
7964
7962
7965
if (!fout->is_prepared[PREPQUERY_GETDOMAINCONSTRAINTS])
7963
7966
{
7964
- /* Set up query for constraint-specific details */
7965
- appendPQExpBufferStr(query,
7966
- "PREPARE getDomainConstraints(pg_catalog.oid) AS\n"
7967
- "SELECT tableoid, oid, conname, "
7968
- "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
7969
- "convalidated "
7970
- "FROM pg_catalog.pg_constraint "
7971
- "WHERE contypid = $1 AND contype = 'c' "
7972
- "ORDER BY conname");
7967
+ /*
7968
+ * Set up query for constraint-specific details. For servers 17 and
7969
+ * up, domains have constraints of type 'n' as well as 'c', otherwise
7970
+ * just the latter.
7971
+ */
7972
+ appendPQExpBuffer(query,
7973
+ "PREPARE getDomainConstraints(pg_catalog.oid) AS\n"
7974
+ "SELECT tableoid, oid, conname, "
7975
+ "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
7976
+ "convalidated, contype "
7977
+ "FROM pg_catalog.pg_constraint "
7978
+ "WHERE contypid = $1 AND contype IN (%s) "
7979
+ "ORDER BY conname",
7980
+ fout->remoteVersion < 170000 ? "'c'" : "'c', 'n'");
7973
7981
7974
7982
ExecuteSqlStatement(fout, query->data);
7975
7983
@@ -7988,33 +7996,50 @@ getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
7988
7996
i_oid = PQfnumber(res, "oid");
7989
7997
i_conname = PQfnumber(res, "conname");
7990
7998
i_consrc = PQfnumber(res, "consrc");
7999
+ i_convalidated = PQfnumber(res, "convalidated");
8000
+ i_contype = PQfnumber(res, "contype");
7991
8001
7992
8002
constrinfo = (ConstraintInfo *) pg_malloc(ntups * sizeof(ConstraintInfo));
7993
-
7994
- tyinfo->nDomChecks = ntups;
7995
8003
tyinfo->domChecks = constrinfo;
7996
8004
7997
- for (i = 0; i < ntups; i++)
8005
+ /* 'i' tracks result rows; 'j' counts CHECK constraints */
8006
+ for (int i = 0, j = 0; i < ntups; i++)
7998
8007
{
7999
- bool validated = PQgetvalue(res, i, 4)[0] == 't';
8000
-
8001
- constrinfo[i].dobj.objType = DO_CONSTRAINT;
8002
- constrinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
8003
- constrinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
8004
- AssignDumpId(&constrinfo[i].dobj);
8005
- constrinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
8006
- constrinfo[i].dobj.namespace = tyinfo->dobj.namespace;
8007
- constrinfo[i].contable = NULL;
8008
- constrinfo[i].condomain = tyinfo;
8009
- constrinfo[i].contype = 'c';
8010
- constrinfo[i].condef = pg_strdup(PQgetvalue(res, i, i_consrc));
8011
- constrinfo[i].confrelid = InvalidOid;
8012
- constrinfo[i].conindex = 0;
8013
- constrinfo[i].condeferrable = false;
8014
- constrinfo[i].condeferred = false;
8015
- constrinfo[i].conislocal = true;
8016
-
8017
- constrinfo[i].separate = !validated;
8008
+ bool validated = PQgetvalue(res, i, i_convalidated)[0] == 't';
8009
+ char contype = (PQgetvalue(res, i, i_contype))[0];
8010
+ ConstraintInfo *constraint;
8011
+
8012
+ if (contype == CONSTRAINT_CHECK)
8013
+ {
8014
+ constraint = &constrinfo[j++];
8015
+ tyinfo->nDomChecks++;
8016
+ }
8017
+ else
8018
+ {
8019
+ Assert(contype == CONSTRAINT_NOTNULL);
8020
+ Assert(tyinfo->notnull == NULL);
8021
+ /* use last item in array for the not-null constraint */
8022
+ tyinfo->notnull = &(constrinfo[ntups - 1]);
8023
+ constraint = tyinfo->notnull;
8024
+ }
8025
+
8026
+ constraint->dobj.objType = DO_CONSTRAINT;
8027
+ constraint->dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
8028
+ constraint->dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
8029
+ AssignDumpId(&(constraint->dobj));
8030
+ constraint->dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
8031
+ constraint->dobj.namespace = tyinfo->dobj.namespace;
8032
+ constraint->contable = NULL;
8033
+ constraint->condomain = tyinfo;
8034
+ constraint->contype = contype;
8035
+ constraint->condef = pg_strdup(PQgetvalue(res, i, i_consrc));
8036
+ constraint->confrelid = InvalidOid;
8037
+ constraint->conindex = 0;
8038
+ constraint->condeferrable = false;
8039
+ constraint->condeferred = false;
8040
+ constraint->conislocal = true;
8041
+
8042
+ constraint->separate = !validated;
8018
8043
8019
8044
/*
8020
8045
* Make the domain depend on the constraint, ensuring it won't be
@@ -8023,8 +8048,7 @@ getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
8023
8048
* anyway, so this doesn't matter.
8024
8049
*/
8025
8050
if (validated)
8026
- addObjectDependency(&tyinfo->dobj,
8027
- constrinfo[i].dobj.dumpId);
8051
+ addObjectDependency(&tyinfo->dobj, constraint->dobj.dumpId);
8028
8052
}
8029
8053
8030
8054
PQclear(res);
@@ -11557,8 +11581,36 @@ dumpDomain(Archive *fout, const TypeInfo *tyinfo)
11557
11581
appendPQExpBuffer(q, " COLLATE %s", fmtQualifiedDumpable(coll));
11558
11582
}
11559
11583
11584
+ /*
11585
+ * Print a not-null constraint if there's one. In servers older than 17
11586
+ * these don't have names, so just print it unadorned; in newer ones they
11587
+ * do, but most of the time it's going to be the standard generated one,
11588
+ * so omit the name in that case also.
11589
+ */
11560
11590
if (typnotnull[0] == 't')
11561
- appendPQExpBufferStr(q, " NOT NULL");
11591
+ {
11592
+ if (fout->remoteVersion < 170000 || tyinfo->notnull == NULL)
11593
+ appendPQExpBufferStr(q, " NOT NULL");
11594
+ else
11595
+ {
11596
+ ConstraintInfo *notnull = tyinfo->notnull;
11597
+
11598
+ if (!notnull->separate)
11599
+ {
11600
+ char *default_name;
11601
+
11602
+ /* XXX should match ChooseConstraintName better */
11603
+ default_name = psprintf("%s_not_null", tyinfo->dobj.name);
11604
+
11605
+ if (strcmp(default_name, notnull->dobj.name) == 0)
11606
+ appendPQExpBufferStr(q, " NOT NULL");
11607
+ else
11608
+ appendPQExpBuffer(q, " CONSTRAINT %s %s",
11609
+ fmtId(notnull->dobj.name), notnull->condef);
11610
+ free(default_name);
11611
+ }
11612
+ }
11613
+ }
11562
11614
11563
11615
if (typdefault != NULL)
11564
11616
{
@@ -11578,7 +11630,7 @@ dumpDomain(Archive *fout, const TypeInfo *tyinfo)
11578
11630
{
11579
11631
ConstraintInfo *domcheck = &(tyinfo->domChecks[i]);
11580
11632
11581
- if (!domcheck->separate)
11633
+ if (!domcheck->separate && domcheck->contype == 'c' )
11582
11634
appendPQExpBuffer(q, "\n\tCONSTRAINT %s %s",
11583
11635
fmtId(domcheck->dobj.name), domcheck->condef);
11584
11636
}
@@ -11642,6 +11694,25 @@ dumpDomain(Archive *fout, const TypeInfo *tyinfo)
11642
11694
destroyPQExpBuffer(conprefix);
11643
11695
}
11644
11696
11697
+ /*
11698
+ * And a comment on the not-null constraint, if there's one -- but only if
11699
+ * the constraint itself was dumped here
11700
+ */
11701
+ if (tyinfo->notnull != NULL && !tyinfo->notnull->separate)
11702
+ {
11703
+ PQExpBuffer conprefix = createPQExpBuffer();
11704
+
11705
+ appendPQExpBuffer(conprefix, "CONSTRAINT %s ON DOMAIN",
11706
+ fmtId(tyinfo->notnull->dobj.name));
11707
+
11708
+ if (tyinfo->notnull->dobj.dump & DUMP_COMPONENT_COMMENT)
11709
+ dumpComment(fout, conprefix->data, qtypname,
11710
+ tyinfo->dobj.namespace->dobj.name,
11711
+ tyinfo->rolname,
11712
+ tyinfo->notnull->dobj.catId, 0, tyinfo->dobj.dumpId);
11713
+ destroyPQExpBuffer(conprefix);
11714
+ }
11715
+
11645
11716
destroyPQExpBuffer(q);
11646
11717
destroyPQExpBuffer(delq);
11647
11718
destroyPQExpBuffer(query);
@@ -17336,14 +17407,23 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo)
17336
17407
.dropStmt = delq->data));
17337
17408
}
17338
17409
}
17339
- else if (coninfo->contype == 'c' && tbinfo == NULL)
17410
+ else if (tbinfo == NULL)
17340
17411
{
17341
- /* CHECK constraint on a domain */
17412
+ /* CHECK, NOT NULL constraint on a domain */
17342
17413
TypeInfo *tyinfo = coninfo->condomain;
17343
17414
17415
+ Assert(coninfo->contype == 'c' || coninfo->contype == 'n');
17416
+
17344
17417
/* Ignore if not to be dumped separately */
17345
17418
if (coninfo->separate)
17346
17419
{
17420
+ const char *keyword;
17421
+
17422
+ if (coninfo->contype == 'c')
17423
+ keyword = "CHECK CONSTRAINT";
17424
+ else
17425
+ keyword = "CONSTRAINT";
17426
+
17347
17427
appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
17348
17428
fmtQualifiedDumpable(tyinfo));
17349
17429
appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
@@ -17362,7 +17442,7 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo)
17362
17442
ARCHIVE_OPTS(.tag = tag,
17363
17443
.namespace = tyinfo->dobj.namespace->dobj.name,
17364
17444
.owner = tyinfo->rolname,
17365
- .description = "CHECK CONSTRAINT" ,
17445
+ .description = keyword ,
17366
17446
.section = SECTION_POST_DATA,
17367
17447
.createStmt = q->data,
17368
17448
.dropStmt = delq->data));
0 commit comments