44
44
#include "catalog/pg_aggregate_d.h"
45
45
#include "catalog/pg_am_d.h"
46
46
#include "catalog/pg_attribute_d.h"
47
+ #include "catalog/pg_authid_d.h"
47
48
#include "catalog/pg_cast_d.h"
48
49
#include "catalog/pg_class_d.h"
49
50
#include "catalog/pg_default_acl_d.h"
@@ -1598,6 +1599,13 @@ checkExtensionMembership(DumpableObject *dobj, Archive *fout)
1598
1599
static void
1599
1600
selectDumpableNamespace(NamespaceInfo *nsinfo, Archive *fout)
1600
1601
{
1602
+ /*
1603
+ * DUMP_COMPONENT_DEFINITION typically implies a CREATE SCHEMA statement
1604
+ * and (for --clean) a DROP SCHEMA statement. (In the absence of
1605
+ * DUMP_COMPONENT_DEFINITION, this value is irrelevant.)
1606
+ */
1607
+ nsinfo->create = true;
1608
+
1601
1609
/*
1602
1610
* If specific tables are being dumped, do not dump any complete
1603
1611
* namespaces. If specific namespaces are being dumped, dump just those
@@ -1633,10 +1641,15 @@ selectDumpableNamespace(NamespaceInfo *nsinfo, Archive *fout)
1633
1641
* no-mans-land between being a system object and a user object. We
1634
1642
* don't want to dump creation or comment commands for it, because
1635
1643
* that complicates matters for non-superuser use of pg_dump. But we
1636
- * should dump any ACL changes that have occurred for it, and of
1637
- * course we should dump contained objects.
1644
+ * should dump any ownership changes, security labels, and ACL
1645
+ * changes, and of course we should dump contained objects. pg_dump
1646
+ * ties ownership to DUMP_COMPONENT_DEFINITION. Hence, unless the
1647
+ * owner is the default, dump a "definition" bearing just a comment.
1638
1648
*/
1639
- nsinfo->dobj.dump = DUMP_COMPONENT_ACL;
1649
+ nsinfo->create = false;
1650
+ nsinfo->dobj.dump = DUMP_COMPONENT_ALL & ~DUMP_COMPONENT_COMMENT;
1651
+ if (nsinfo->nspowner == BOOTSTRAP_SUPERUSERID)
1652
+ nsinfo->dobj.dump &= ~DUMP_COMPONENT_DEFINITION;
1640
1653
nsinfo->dobj.dump_contains = DUMP_COMPONENT_ALL;
1641
1654
}
1642
1655
else
@@ -3428,8 +3441,8 @@ getBlobs(Archive *fout)
3428
3441
PQExpBuffer init_racl_subquery = createPQExpBuffer();
3429
3442
3430
3443
buildACLQueries(acl_subquery, racl_subquery, init_acl_subquery,
3431
- init_racl_subquery, "l.lomacl", "l.lomowner", "'L'",
3432
- dopt->binary_upgrade);
3444
+ init_racl_subquery, "l.lomacl", "l.lomowner",
3445
+ "pip.initprivs", "'L'", dopt->binary_upgrade);
3433
3446
3434
3447
appendPQExpBuffer(blobQry,
3435
3448
"SELECT l.oid, (%s l.lomowner) AS rolname, "
@@ -4830,6 +4843,7 @@ getNamespaces(Archive *fout, int *numNamespaces)
4830
4843
int i_tableoid;
4831
4844
int i_oid;
4832
4845
int i_nspname;
4846
+ int i_nspowner;
4833
4847
int i_rolname;
4834
4848
int i_nspacl;
4835
4849
int i_rnspacl;
@@ -4849,11 +4863,27 @@ getNamespaces(Archive *fout, int *numNamespaces)
4849
4863
PQExpBuffer init_acl_subquery = createPQExpBuffer();
4850
4864
PQExpBuffer init_racl_subquery = createPQExpBuffer();
4851
4865
4866
+ /*
4867
+ * Bypass pg_init_privs.initprivs for the public schema. Dropping and
4868
+ * recreating the schema detaches it from its pg_init_privs row, but
4869
+ * an empty destination database starts with this ACL nonetheless.
4870
+ * Also, we support dump/reload of public schema ownership changes.
4871
+ * ALTER SCHEMA OWNER filters nspacl through aclnewowner(), but
4872
+ * initprivs continues to reflect the initial owner (the bootstrap
4873
+ * superuser). Hence, synthesize the value that nspacl will have
4874
+ * after the restore's ALTER SCHEMA OWNER.
4875
+ */
4852
4876
buildACLQueries(acl_subquery, racl_subquery, init_acl_subquery,
4853
- init_racl_subquery, "n.nspacl", "n.nspowner", "'n'",
4854
- dopt->binary_upgrade);
4877
+ init_racl_subquery, "n.nspacl", "n.nspowner",
4878
+ "CASE WHEN n.nspname = 'public' THEN array["
4879
+ " format('%s=UC/%s', "
4880
+ " n.nspowner::regrole, n.nspowner::regrole),"
4881
+ " format('=UC/%s', n.nspowner::regrole)]::aclitem[] "
4882
+ "ELSE pip.initprivs END",
4883
+ "'n'", dopt->binary_upgrade);
4855
4884
4856
4885
appendPQExpBuffer(query, "SELECT n.tableoid, n.oid, n.nspname, "
4886
+ "n.nspowner, "
4857
4887
"(%s nspowner) AS rolname, "
4858
4888
"%s as nspacl, "
4859
4889
"%s as rnspacl, "
@@ -4878,7 +4908,7 @@ getNamespaces(Archive *fout, int *numNamespaces)
4878
4908
destroyPQExpBuffer(init_racl_subquery);
4879
4909
}
4880
4910
else
4881
- appendPQExpBuffer(query, "SELECT tableoid, oid, nspname, "
4911
+ appendPQExpBuffer(query, "SELECT tableoid, oid, nspname, nspowner, "
4882
4912
"(%s nspowner) AS rolname, "
4883
4913
"nspacl, NULL as rnspacl, "
4884
4914
"NULL AS initnspacl, NULL as initrnspacl "
@@ -4894,6 +4924,7 @@ getNamespaces(Archive *fout, int *numNamespaces)
4894
4924
i_tableoid = PQfnumber(res, "tableoid");
4895
4925
i_oid = PQfnumber(res, "oid");
4896
4926
i_nspname = PQfnumber(res, "nspname");
4927
+ i_nspowner = PQfnumber(res, "nspowner");
4897
4928
i_rolname = PQfnumber(res, "rolname");
4898
4929
i_nspacl = PQfnumber(res, "nspacl");
4899
4930
i_rnspacl = PQfnumber(res, "rnspacl");
@@ -4907,6 +4938,7 @@ getNamespaces(Archive *fout, int *numNamespaces)
4907
4938
nsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
4908
4939
AssignDumpId(&nsinfo[i].dobj);
4909
4940
nsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_nspname));
4941
+ nsinfo[i].nspowner = atooid(PQgetvalue(res, i, i_nspowner));
4910
4942
nsinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
4911
4943
nsinfo[i].nspacl = pg_strdup(PQgetvalue(res, i, i_nspacl));
4912
4944
nsinfo[i].rnspacl = pg_strdup(PQgetvalue(res, i, i_rnspacl));
@@ -5098,8 +5130,8 @@ getTypes(Archive *fout, int *numTypes)
5098
5130
PQExpBuffer initracl_subquery = createPQExpBuffer();
5099
5131
5100
5132
buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
5101
- initracl_subquery, "t.typacl", "t.typowner", "'T'",
5102
- dopt->binary_upgrade);
5133
+ initracl_subquery, "t.typacl", "t.typowner",
5134
+ "pip.initprivs", "'T'", dopt->binary_upgrade);
5103
5135
5104
5136
appendPQExpBuffer(query, "SELECT t.tableoid, t.oid, t.typname, "
5105
5137
"t.typnamespace, "
@@ -5800,8 +5832,8 @@ getAggregates(Archive *fout, int *numAggs)
5800
5832
const char *agg_check;
5801
5833
5802
5834
buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
5803
- initracl_subquery, "p.proacl", "p.proowner", "'f'",
5804
- dopt->binary_upgrade);
5835
+ initracl_subquery, "p.proacl", "p.proowner",
5836
+ "pip.initprivs", "'f'", dopt->binary_upgrade);
5805
5837
5806
5838
agg_check = (fout->remoteVersion >= 110000 ? "p.prokind = 'a'"
5807
5839
: "p.proisagg");
@@ -6013,8 +6045,8 @@ getFuncs(Archive *fout, int *numFuncs)
6013
6045
const char *not_agg_check;
6014
6046
6015
6047
buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
6016
- initracl_subquery, "p.proacl", "p.proowner", "'f'",
6017
- dopt->binary_upgrade);
6048
+ initracl_subquery, "p.proacl", "p.proowner",
6049
+ "pip.initprivs", "'f'", dopt->binary_upgrade);
6018
6050
6019
6051
not_agg_check = (fout->remoteVersion >= 110000 ? "p.prokind <> 'a'"
6020
6052
: "NOT p.proisagg");
@@ -6310,13 +6342,14 @@ getTables(Archive *fout, int *numTables)
6310
6342
6311
6343
buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
6312
6344
initracl_subquery, "c.relacl", "c.relowner",
6345
+ "pip.initprivs",
6313
6346
"CASE WHEN c.relkind = " CppAsString2(RELKIND_SEQUENCE)
6314
6347
" THEN 's' ELSE 'r' END::\"char\"",
6315
6348
dopt->binary_upgrade);
6316
6349
6317
6350
buildACLQueries(attacl_subquery, attracl_subquery, attinitacl_subquery,
6318
- attinitracl_subquery, "at.attacl", "c.relowner", "'c'",
6319
- dopt->binary_upgrade);
6351
+ attinitracl_subquery, "at.attacl", "c.relowner",
6352
+ "pip.initprivs", "'c'", dopt->binary_upgrade);
6320
6353
6321
6354
appendPQExpBuffer(query,
6322
6355
"SELECT c.tableoid, c.oid, c.relname, "
@@ -8241,8 +8274,8 @@ getProcLangs(Archive *fout, int *numProcLangs)
8241
8274
PQExpBuffer initracl_subquery = createPQExpBuffer();
8242
8275
8243
8276
buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
8244
- initracl_subquery, "l.lanacl", "l.lanowner", "'l'",
8245
- dopt->binary_upgrade);
8277
+ initracl_subquery, "l.lanacl", "l.lanowner",
8278
+ "pip.initprivs", "'l'", dopt->binary_upgrade);
8246
8279
8247
8280
/* pg_language has a laninline column */
8248
8281
appendPQExpBuffer(query, "SELECT l.tableoid, l.oid, "
@@ -9432,8 +9465,8 @@ getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
9432
9465
PQExpBuffer initracl_subquery = createPQExpBuffer();
9433
9466
9434
9467
buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
9435
- initracl_subquery, "f.fdwacl", "f.fdwowner", "'F'",
9436
- dopt->binary_upgrade);
9468
+ initracl_subquery, "f.fdwacl", "f.fdwowner",
9469
+ "pip.initprivs", "'F'", dopt->binary_upgrade);
9437
9470
9438
9471
appendPQExpBuffer(query, "SELECT f.tableoid, f.oid, f.fdwname, "
9439
9472
"(%s f.fdwowner) AS rolname, "
@@ -9599,8 +9632,8 @@ getForeignServers(Archive *fout, int *numForeignServers)
9599
9632
PQExpBuffer initracl_subquery = createPQExpBuffer();
9600
9633
9601
9634
buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
9602
- initracl_subquery, "f.srvacl", "f.srvowner", "'S'",
9603
- dopt->binary_upgrade);
9635
+ initracl_subquery, "f.srvacl", "f.srvowner",
9636
+ "pip.initprivs", "'S'", dopt->binary_upgrade);
9604
9637
9605
9638
appendPQExpBuffer(query, "SELECT f.tableoid, f.oid, f.srvname, "
9606
9639
"(%s f.srvowner) AS rolname, "
@@ -9746,6 +9779,7 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
9746
9779
9747
9780
buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
9748
9781
initracl_subquery, "defaclacl", "defaclrole",
9782
+ "pip.initprivs",
9749
9783
"CASE WHEN defaclobjtype = 'S' THEN 's' ELSE defaclobjtype END::\"char\"",
9750
9784
dopt->binary_upgrade);
9751
9785
@@ -10363,9 +10397,19 @@ dumpNamespace(Archive *fout, const NamespaceInfo *nspinfo)
10363
10397
10364
10398
qnspname = pg_strdup(fmtId(nspinfo->dobj.name));
10365
10399
10366
- appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
10367
-
10368
- appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
10400
+ if (nspinfo->create)
10401
+ {
10402
+ appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
10403
+ appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
10404
+ }
10405
+ else
10406
+ {
10407
+ /* see selectDumpableNamespace() */
10408
+ appendPQExpBufferStr(delq,
10409
+ "-- *not* dropping schema, since initdb creates it\n");
10410
+ appendPQExpBufferStr(q,
10411
+ "-- *not* creating schema, since initdb creates it\n");
10412
+ }
10369
10413
10370
10414
if (dopt->binary_upgrade)
10371
10415
binary_upgrade_extension_member(q, &nspinfo->dobj,
@@ -15556,8 +15600,8 @@ dumpTable(Archive *fout, const TableInfo *tbinfo)
15556
15600
PQExpBuffer initracl_subquery = createPQExpBuffer();
15557
15601
15558
15602
buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
15559
- initracl_subquery, "at.attacl", "c.relowner", "'c'",
15560
- dopt->binary_upgrade);
15603
+ initracl_subquery, "at.attacl", "c.relowner",
15604
+ "pip.initprivs", "'c'", dopt->binary_upgrade);
15561
15605
15562
15606
appendPQExpBuffer(query,
15563
15607
"SELECT at.attname, "
0 commit comments