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_proc_d.h"
@@ -6122,6 +6123,7 @@ getTypes(Archive *fout)
6122
6123
*/
6123
6124
tyinfo[i].nDomChecks = 0;
6124
6125
tyinfo[i].domChecks = NULL;
6126
+ tyinfo[i].notnull = NULL;
6125
6127
if ((tyinfo[i].dobj.dump & DUMP_COMPONENT_DEFINITION) &&
6126
6128
tyinfo[i].typtype == TYPTYPE_DOMAIN)
6127
6129
getDomainConstraints(fout, &(tyinfo[i]));
@@ -8247,27 +8249,33 @@ addConstrChildIdxDeps(DumpableObject *dobj, const IndxInfo *refidx)
8247
8249
static void
8248
8250
getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
8249
8251
{
8250
- int i;
8251
8252
ConstraintInfo *constrinfo;
8252
8253
PQExpBuffer query = createPQExpBuffer();
8253
8254
PGresult *res;
8254
8255
int i_tableoid,
8255
8256
i_oid,
8256
8257
i_conname,
8257
- i_consrc;
8258
+ i_consrc,
8259
+ i_convalidated,
8260
+ i_contype;
8258
8261
int ntups;
8259
8262
8260
8263
if (!fout->is_prepared[PREPQUERY_GETDOMAINCONSTRAINTS])
8261
8264
{
8262
- /* Set up query for constraint-specific details */
8263
- appendPQExpBufferStr(query,
8264
- "PREPARE getDomainConstraints(pg_catalog.oid) AS\n"
8265
- "SELECT tableoid, oid, conname, "
8266
- "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
8267
- "convalidated "
8268
- "FROM pg_catalog.pg_constraint "
8269
- "WHERE contypid = $1 AND contype = 'c' "
8270
- "ORDER BY conname");
8265
+ /*
8266
+ * Set up query for constraint-specific details. For servers 17 and
8267
+ * up, domains have constraints of type 'n' as well as 'c', otherwise
8268
+ * just the latter.
8269
+ */
8270
+ appendPQExpBuffer(query,
8271
+ "PREPARE getDomainConstraints(pg_catalog.oid) AS\n"
8272
+ "SELECT tableoid, oid, conname, "
8273
+ "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
8274
+ "convalidated, contype "
8275
+ "FROM pg_catalog.pg_constraint "
8276
+ "WHERE contypid = $1 AND contype IN (%s) "
8277
+ "ORDER BY conname",
8278
+ fout->remoteVersion < 170000 ? "'c'" : "'c', 'n'");
8271
8279
8272
8280
ExecuteSqlStatement(fout, query->data);
8273
8281
@@ -8286,33 +8294,50 @@ getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
8286
8294
i_oid = PQfnumber(res, "oid");
8287
8295
i_conname = PQfnumber(res, "conname");
8288
8296
i_consrc = PQfnumber(res, "consrc");
8297
+ i_convalidated = PQfnumber(res, "convalidated");
8298
+ i_contype = PQfnumber(res, "contype");
8289
8299
8290
8300
constrinfo = (ConstraintInfo *) pg_malloc(ntups * sizeof(ConstraintInfo));
8291
-
8292
- tyinfo->nDomChecks = ntups;
8293
8301
tyinfo->domChecks = constrinfo;
8294
8302
8295
- for (i = 0; i < ntups; i++)
8303
+ /* 'i' tracks result rows; 'j' counts CHECK constraints */
8304
+ for (int i = 0, j = 0; i < ntups; i++)
8296
8305
{
8297
- bool validated = PQgetvalue(res, i, 4)[0] == 't';
8298
-
8299
- constrinfo[i].dobj.objType = DO_CONSTRAINT;
8300
- constrinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
8301
- constrinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
8302
- AssignDumpId(&constrinfo[i].dobj);
8303
- constrinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
8304
- constrinfo[i].dobj.namespace = tyinfo->dobj.namespace;
8305
- constrinfo[i].contable = NULL;
8306
- constrinfo[i].condomain = tyinfo;
8307
- constrinfo[i].contype = 'c';
8308
- constrinfo[i].condef = pg_strdup(PQgetvalue(res, i, i_consrc));
8309
- constrinfo[i].confrelid = InvalidOid;
8310
- constrinfo[i].conindex = 0;
8311
- constrinfo[i].condeferrable = false;
8312
- constrinfo[i].condeferred = false;
8313
- constrinfo[i].conislocal = true;
8314
-
8315
- constrinfo[i].separate = !validated;
8306
+ bool validated = PQgetvalue(res, i, i_convalidated)[0] == 't';
8307
+ char contype = (PQgetvalue(res, i, i_contype))[0];
8308
+ ConstraintInfo *constraint;
8309
+
8310
+ if (contype == CONSTRAINT_CHECK)
8311
+ {
8312
+ constraint = &constrinfo[j++];
8313
+ tyinfo->nDomChecks++;
8314
+ }
8315
+ else
8316
+ {
8317
+ Assert(contype == CONSTRAINT_NOTNULL);
8318
+ Assert(tyinfo->notnull == NULL);
8319
+ /* use last item in array for the not-null constraint */
8320
+ tyinfo->notnull = &(constrinfo[ntups - 1]);
8321
+ constraint = tyinfo->notnull;
8322
+ }
8323
+
8324
+ constraint->dobj.objType = DO_CONSTRAINT;
8325
+ constraint->dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
8326
+ constraint->dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
8327
+ AssignDumpId(&(constraint->dobj));
8328
+ constraint->dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
8329
+ constraint->dobj.namespace = tyinfo->dobj.namespace;
8330
+ constraint->contable = NULL;
8331
+ constraint->condomain = tyinfo;
8332
+ constraint->contype = contype;
8333
+ constraint->condef = pg_strdup(PQgetvalue(res, i, i_consrc));
8334
+ constraint->confrelid = InvalidOid;
8335
+ constraint->conindex = 0;
8336
+ constraint->condeferrable = false;
8337
+ constraint->condeferred = false;
8338
+ constraint->conislocal = true;
8339
+
8340
+ constraint->separate = !validated;
8316
8341
8317
8342
/*
8318
8343
* Make the domain depend on the constraint, ensuring it won't be
@@ -8321,8 +8346,7 @@ getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
8321
8346
* anyway, so this doesn't matter.
8322
8347
*/
8323
8348
if (validated)
8324
- addObjectDependency(&tyinfo->dobj,
8325
- constrinfo[i].dobj.dumpId);
8349
+ addObjectDependency(&tyinfo->dobj, constraint->dobj.dumpId);
8326
8350
}
8327
8351
8328
8352
PQclear(res);
@@ -12517,8 +12541,36 @@ dumpDomain(Archive *fout, const TypeInfo *tyinfo)
12517
12541
appendPQExpBuffer(q, " COLLATE %s", fmtQualifiedDumpable(coll));
12518
12542
}
12519
12543
12544
+ /*
12545
+ * Print a not-null constraint if there's one. In servers older than 17
12546
+ * these don't have names, so just print it unadorned; in newer ones they
12547
+ * do, but most of the time it's going to be the standard generated one,
12548
+ * so omit the name in that case also.
12549
+ */
12520
12550
if (typnotnull[0] == 't')
12521
- appendPQExpBufferStr(q, " NOT NULL");
12551
+ {
12552
+ if (fout->remoteVersion < 170000 || tyinfo->notnull == NULL)
12553
+ appendPQExpBufferStr(q, " NOT NULL");
12554
+ else
12555
+ {
12556
+ ConstraintInfo *notnull = tyinfo->notnull;
12557
+
12558
+ if (!notnull->separate)
12559
+ {
12560
+ char *default_name;
12561
+
12562
+ /* XXX should match ChooseConstraintName better */
12563
+ default_name = psprintf("%s_not_null", tyinfo->dobj.name);
12564
+
12565
+ if (strcmp(default_name, notnull->dobj.name) == 0)
12566
+ appendPQExpBufferStr(q, " NOT NULL");
12567
+ else
12568
+ appendPQExpBuffer(q, " CONSTRAINT %s %s",
12569
+ fmtId(notnull->dobj.name), notnull->condef);
12570
+ free(default_name);
12571
+ }
12572
+ }
12573
+ }
12522
12574
12523
12575
if (typdefault != NULL)
12524
12576
{
@@ -12538,7 +12590,7 @@ dumpDomain(Archive *fout, const TypeInfo *tyinfo)
12538
12590
{
12539
12591
ConstraintInfo *domcheck = &(tyinfo->domChecks[i]);
12540
12592
12541
- if (!domcheck->separate)
12593
+ if (!domcheck->separate && domcheck->contype == 'c' )
12542
12594
appendPQExpBuffer(q, "\n\tCONSTRAINT %s %s",
12543
12595
fmtId(domcheck->dobj.name), domcheck->condef);
12544
12596
}
@@ -12602,6 +12654,25 @@ dumpDomain(Archive *fout, const TypeInfo *tyinfo)
12602
12654
destroyPQExpBuffer(conprefix);
12603
12655
}
12604
12656
12657
+ /*
12658
+ * And a comment on the not-null constraint, if there's one -- but only if
12659
+ * the constraint itself was dumped here
12660
+ */
12661
+ if (tyinfo->notnull != NULL && !tyinfo->notnull->separate)
12662
+ {
12663
+ PQExpBuffer conprefix = createPQExpBuffer();
12664
+
12665
+ appendPQExpBuffer(conprefix, "CONSTRAINT %s ON DOMAIN",
12666
+ fmtId(tyinfo->notnull->dobj.name));
12667
+
12668
+ if (tyinfo->notnull->dobj.dump & DUMP_COMPONENT_COMMENT)
12669
+ dumpComment(fout, conprefix->data, qtypname,
12670
+ tyinfo->dobj.namespace->dobj.name,
12671
+ tyinfo->rolname,
12672
+ tyinfo->notnull->dobj.catId, 0, tyinfo->dobj.dumpId);
12673
+ destroyPQExpBuffer(conprefix);
12674
+ }
12675
+
12605
12676
destroyPQExpBuffer(q);
12606
12677
destroyPQExpBuffer(delq);
12607
12678
destroyPQExpBuffer(query);
@@ -18463,14 +18534,23 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo)
18463
18534
.dropStmt = delq->data));
18464
18535
}
18465
18536
}
18466
- else if (coninfo->contype == 'c' && tbinfo == NULL)
18537
+ else if (tbinfo == NULL)
18467
18538
{
18468
- /* CHECK constraint on a domain */
18539
+ /* CHECK, NOT NULL constraint on a domain */
18469
18540
TypeInfo *tyinfo = coninfo->condomain;
18470
18541
18542
+ Assert(coninfo->contype == 'c' || coninfo->contype == 'n');
18543
+
18471
18544
/* Ignore if not to be dumped separately */
18472
18545
if (coninfo->separate)
18473
18546
{
18547
+ const char *keyword;
18548
+
18549
+ if (coninfo->contype == 'c')
18550
+ keyword = "CHECK CONSTRAINT";
18551
+ else
18552
+ keyword = "CONSTRAINT";
18553
+
18474
18554
appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
18475
18555
fmtQualifiedDumpable(tyinfo));
18476
18556
appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
@@ -18489,7 +18569,7 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo)
18489
18569
ARCHIVE_OPTS(.tag = tag,
18490
18570
.namespace = tyinfo->dobj.namespace->dobj.name,
18491
18571
.owner = tyinfo->rolname,
18492
- .description = "CHECK CONSTRAINT" ,
18572
+ .description = keyword ,
18493
18573
.section = SECTION_POST_DATA,
18494
18574
.createStmt = q->data,
18495
18575
.dropStmt = delq->data));
0 commit comments