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"
@@ -6187,6 +6188,7 @@ getTypes(Archive *fout)
6187
6188
*/
6188
6189
tyinfo[i].nDomChecks = 0;
6189
6190
tyinfo[i].domChecks = NULL;
6191
+ tyinfo[i].notnull = NULL;
6190
6192
if ((tyinfo[i].dobj.dump & DUMP_COMPONENT_DEFINITION) &&
6191
6193
tyinfo[i].typtype == TYPTYPE_DOMAIN)
6192
6194
getDomainConstraints(fout, &(tyinfo[i]));
@@ -8312,27 +8314,33 @@ addConstrChildIdxDeps(DumpableObject *dobj, const IndxInfo *refidx)
8312
8314
static void
8313
8315
getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
8314
8316
{
8315
- int i;
8316
8317
ConstraintInfo *constrinfo;
8317
8318
PQExpBuffer query = createPQExpBuffer();
8318
8319
PGresult *res;
8319
8320
int i_tableoid,
8320
8321
i_oid,
8321
8322
i_conname,
8322
- i_consrc;
8323
+ i_consrc,
8324
+ i_convalidated,
8325
+ i_contype;
8323
8326
int ntups;
8324
8327
8325
8328
if (!fout->is_prepared[PREPQUERY_GETDOMAINCONSTRAINTS])
8326
8329
{
8327
- /* Set up query for constraint-specific details */
8328
- appendPQExpBufferStr(query,
8329
- "PREPARE getDomainConstraints(pg_catalog.oid) AS\n"
8330
- "SELECT tableoid, oid, conname, "
8331
- "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
8332
- "convalidated "
8333
- "FROM pg_catalog.pg_constraint "
8334
- "WHERE contypid = $1 AND contype = 'c' "
8335
- "ORDER BY conname");
8330
+ /*
8331
+ * Set up query for constraint-specific details. For servers 17 and
8332
+ * up, domains have constraints of type 'n' as well as 'c', otherwise
8333
+ * just the latter.
8334
+ */
8335
+ appendPQExpBuffer(query,
8336
+ "PREPARE getDomainConstraints(pg_catalog.oid) AS\n"
8337
+ "SELECT tableoid, oid, conname, "
8338
+ "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
8339
+ "convalidated, contype "
8340
+ "FROM pg_catalog.pg_constraint "
8341
+ "WHERE contypid = $1 AND contype IN (%s) "
8342
+ "ORDER BY conname",
8343
+ fout->remoteVersion < 170000 ? "'c'" : "'c', 'n'");
8336
8344
8337
8345
ExecuteSqlStatement(fout, query->data);
8338
8346
@@ -8351,33 +8359,50 @@ getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
8351
8359
i_oid = PQfnumber(res, "oid");
8352
8360
i_conname = PQfnumber(res, "conname");
8353
8361
i_consrc = PQfnumber(res, "consrc");
8362
+ i_convalidated = PQfnumber(res, "convalidated");
8363
+ i_contype = PQfnumber(res, "contype");
8354
8364
8355
8365
constrinfo = (ConstraintInfo *) pg_malloc(ntups * sizeof(ConstraintInfo));
8356
-
8357
- tyinfo->nDomChecks = ntups;
8358
8366
tyinfo->domChecks = constrinfo;
8359
8367
8360
- for (i = 0; i < ntups; i++)
8368
+ /* 'i' tracks result rows; 'j' counts CHECK constraints */
8369
+ for (int i = 0, j = 0; i < ntups; i++)
8361
8370
{
8362
- bool validated = PQgetvalue(res, i, 4)[0] == 't';
8363
-
8364
- constrinfo[i].dobj.objType = DO_CONSTRAINT;
8365
- constrinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
8366
- constrinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
8367
- AssignDumpId(&constrinfo[i].dobj);
8368
- constrinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
8369
- constrinfo[i].dobj.namespace = tyinfo->dobj.namespace;
8370
- constrinfo[i].contable = NULL;
8371
- constrinfo[i].condomain = tyinfo;
8372
- constrinfo[i].contype = 'c';
8373
- constrinfo[i].condef = pg_strdup(PQgetvalue(res, i, i_consrc));
8374
- constrinfo[i].confrelid = InvalidOid;
8375
- constrinfo[i].conindex = 0;
8376
- constrinfo[i].condeferrable = false;
8377
- constrinfo[i].condeferred = false;
8378
- constrinfo[i].conislocal = true;
8379
-
8380
- constrinfo[i].separate = !validated;
8371
+ bool validated = PQgetvalue(res, i, i_convalidated)[0] == 't';
8372
+ char contype = (PQgetvalue(res, i, i_contype))[0];
8373
+ ConstraintInfo *constraint;
8374
+
8375
+ if (contype == CONSTRAINT_CHECK)
8376
+ {
8377
+ constraint = &constrinfo[j++];
8378
+ tyinfo->nDomChecks++;
8379
+ }
8380
+ else
8381
+ {
8382
+ Assert(contype == CONSTRAINT_NOTNULL);
8383
+ Assert(tyinfo->notnull == NULL);
8384
+ /* use last item in array for the not-null constraint */
8385
+ tyinfo->notnull = &(constrinfo[ntups - 1]);
8386
+ constraint = tyinfo->notnull;
8387
+ }
8388
+
8389
+ constraint->dobj.objType = DO_CONSTRAINT;
8390
+ constraint->dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
8391
+ constraint->dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
8392
+ AssignDumpId(&(constraint->dobj));
8393
+ constraint->dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
8394
+ constraint->dobj.namespace = tyinfo->dobj.namespace;
8395
+ constraint->contable = NULL;
8396
+ constraint->condomain = tyinfo;
8397
+ constraint->contype = contype;
8398
+ constraint->condef = pg_strdup(PQgetvalue(res, i, i_consrc));
8399
+ constraint->confrelid = InvalidOid;
8400
+ constraint->conindex = 0;
8401
+ constraint->condeferrable = false;
8402
+ constraint->condeferred = false;
8403
+ constraint->conislocal = true;
8404
+
8405
+ constraint->separate = !validated;
8381
8406
8382
8407
/*
8383
8408
* Make the domain depend on the constraint, ensuring it won't be
@@ -8386,8 +8411,7 @@ getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
8386
8411
* anyway, so this doesn't matter.
8387
8412
*/
8388
8413
if (validated)
8389
- addObjectDependency(&tyinfo->dobj,
8390
- constrinfo[i].dobj.dumpId);
8414
+ addObjectDependency(&tyinfo->dobj, constraint->dobj.dumpId);
8391
8415
}
8392
8416
8393
8417
PQclear(res);
@@ -12597,8 +12621,36 @@ dumpDomain(Archive *fout, const TypeInfo *tyinfo)
12597
12621
appendPQExpBuffer(q, " COLLATE %s", fmtQualifiedDumpable(coll));
12598
12622
}
12599
12623
12624
+ /*
12625
+ * Print a not-null constraint if there's one. In servers older than 17
12626
+ * these don't have names, so just print it unadorned; in newer ones they
12627
+ * do, but most of the time it's going to be the standard generated one,
12628
+ * so omit the name in that case also.
12629
+ */
12600
12630
if (typnotnull[0] == 't')
12601
- appendPQExpBufferStr(q, " NOT NULL");
12631
+ {
12632
+ if (fout->remoteVersion < 170000 || tyinfo->notnull == NULL)
12633
+ appendPQExpBufferStr(q, " NOT NULL");
12634
+ else
12635
+ {
12636
+ ConstraintInfo *notnull = tyinfo->notnull;
12637
+
12638
+ if (!notnull->separate)
12639
+ {
12640
+ char *default_name;
12641
+
12642
+ /* XXX should match ChooseConstraintName better */
12643
+ default_name = psprintf("%s_not_null", tyinfo->dobj.name);
12644
+
12645
+ if (strcmp(default_name, notnull->dobj.name) == 0)
12646
+ appendPQExpBufferStr(q, " NOT NULL");
12647
+ else
12648
+ appendPQExpBuffer(q, " CONSTRAINT %s %s",
12649
+ fmtId(notnull->dobj.name), notnull->condef);
12650
+ free(default_name);
12651
+ }
12652
+ }
12653
+ }
12602
12654
12603
12655
if (typdefault != NULL)
12604
12656
{
@@ -12618,7 +12670,7 @@ dumpDomain(Archive *fout, const TypeInfo *tyinfo)
12618
12670
{
12619
12671
ConstraintInfo *domcheck = &(tyinfo->domChecks[i]);
12620
12672
12621
- if (!domcheck->separate)
12673
+ if (!domcheck->separate && domcheck->contype == 'c' )
12622
12674
appendPQExpBuffer(q, "\n\tCONSTRAINT %s %s",
12623
12675
fmtId(domcheck->dobj.name), domcheck->condef);
12624
12676
}
@@ -12682,6 +12734,25 @@ dumpDomain(Archive *fout, const TypeInfo *tyinfo)
12682
12734
destroyPQExpBuffer(conprefix);
12683
12735
}
12684
12736
12737
+ /*
12738
+ * And a comment on the not-null constraint, if there's one -- but only if
12739
+ * the constraint itself was dumped here
12740
+ */
12741
+ if (tyinfo->notnull != NULL && !tyinfo->notnull->separate)
12742
+ {
12743
+ PQExpBuffer conprefix = createPQExpBuffer();
12744
+
12745
+ appendPQExpBuffer(conprefix, "CONSTRAINT %s ON DOMAIN",
12746
+ fmtId(tyinfo->notnull->dobj.name));
12747
+
12748
+ if (tyinfo->notnull->dobj.dump & DUMP_COMPONENT_COMMENT)
12749
+ dumpComment(fout, conprefix->data, qtypname,
12750
+ tyinfo->dobj.namespace->dobj.name,
12751
+ tyinfo->rolname,
12752
+ tyinfo->notnull->dobj.catId, 0, tyinfo->dobj.dumpId);
12753
+ destroyPQExpBuffer(conprefix);
12754
+ }
12755
+
12685
12756
destroyPQExpBuffer(q);
12686
12757
destroyPQExpBuffer(delq);
12687
12758
destroyPQExpBuffer(query);
@@ -18543,14 +18614,23 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo)
18543
18614
.dropStmt = delq->data));
18544
18615
}
18545
18616
}
18546
- else if (coninfo->contype == 'c' && tbinfo == NULL)
18617
+ else if (tbinfo == NULL)
18547
18618
{
18548
- /* CHECK constraint on a domain */
18619
+ /* CHECK, NOT NULL constraint on a domain */
18549
18620
TypeInfo *tyinfo = coninfo->condomain;
18550
18621
18622
+ Assert(coninfo->contype == 'c' || coninfo->contype == 'n');
18623
+
18551
18624
/* Ignore if not to be dumped separately */
18552
18625
if (coninfo->separate)
18553
18626
{
18627
+ const char *keyword;
18628
+
18629
+ if (coninfo->contype == 'c')
18630
+ keyword = "CHECK CONSTRAINT";
18631
+ else
18632
+ keyword = "CONSTRAINT";
18633
+
18554
18634
appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
18555
18635
fmtQualifiedDumpable(tyinfo));
18556
18636
appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
@@ -18569,7 +18649,7 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo)
18569
18649
ARCHIVE_OPTS(.tag = tag,
18570
18650
.namespace = tyinfo->dobj.namespace->dobj.name,
18571
18651
.owner = tyinfo->rolname,
18572
- .description = "CHECK CONSTRAINT" ,
18652
+ .description = keyword ,
18573
18653
.section = SECTION_POST_DATA,
18574
18654
.createStmt = q->data,
18575
18655
.dropStmt = delq->data));
0 commit comments