Qualify table usage in dumpTable() and use regclass
All of the other tables used in the query in dumpTable(), which is collecting column-level ACLs, are qualified, so we should be qualifying the pg_init_privs, the related sub-select against pg_class and the other queries added by the pg_dump catalog ACLs work. Also, use ::regclass (or ::pg_catalog.regclass, where appropriate) instead of using a poorly constructed query to get the OID for various catalog tables. Issues identified by Noah and Alvaro, patch by me.
This commit is contained in:
parent
2d2e40e3be
commit
2e8b4bf804
@ -715,20 +715,20 @@ buildACLQueries(PQExpBuffer acl_subquery, PQExpBuffer racl_subquery,
|
|||||||
* these are run the initial privileges will be in place, even in a
|
* these are run the initial privileges will be in place, even in a
|
||||||
* binary upgrade situation (see below).
|
* binary upgrade situation (see below).
|
||||||
*/
|
*/
|
||||||
printfPQExpBuffer(acl_subquery, "(SELECT array_agg(acl) FROM "
|
printfPQExpBuffer(acl_subquery, "(SELECT pg_catalog.array_agg(acl) FROM "
|
||||||
"(SELECT unnest(coalesce(%s,acldefault(%s,%s))) AS acl "
|
"(SELECT pg_catalog.unnest(coalesce(%s,pg_catalog.acldefault(%s,%s))) AS acl "
|
||||||
"EXCEPT "
|
"EXCEPT "
|
||||||
"SELECT unnest(coalesce(pip.initprivs,acldefault(%s,%s)))) as foo)",
|
"SELECT pg_catalog.unnest(coalesce(pip.initprivs,pg_catalog.acldefault(%s,%s)))) as foo)",
|
||||||
acl_column,
|
acl_column,
|
||||||
obj_kind,
|
obj_kind,
|
||||||
acl_owner,
|
acl_owner,
|
||||||
obj_kind,
|
obj_kind,
|
||||||
acl_owner);
|
acl_owner);
|
||||||
|
|
||||||
printfPQExpBuffer(racl_subquery, "(SELECT array_agg(acl) FROM "
|
printfPQExpBuffer(racl_subquery, "(SELECT pg_catalog.array_agg(acl) FROM "
|
||||||
"(SELECT unnest(coalesce(pip.initprivs,acldefault(%s,%s))) AS acl "
|
"(SELECT pg_catalog.unnest(coalesce(pip.initprivs,pg_catalog.acldefault(%s,%s))) AS acl "
|
||||||
"EXCEPT "
|
"EXCEPT "
|
||||||
"SELECT unnest(coalesce(%s,acldefault(%s,%s)))) as foo)",
|
"SELECT pg_catalog.unnest(coalesce(%s,pg_catalog.acldefault(%s,%s)))) as foo)",
|
||||||
obj_kind,
|
obj_kind,
|
||||||
acl_owner,
|
acl_owner,
|
||||||
acl_column,
|
acl_column,
|
||||||
@ -753,19 +753,19 @@ buildACLQueries(PQExpBuffer acl_subquery, PQExpBuffer racl_subquery,
|
|||||||
{
|
{
|
||||||
printfPQExpBuffer(init_acl_subquery,
|
printfPQExpBuffer(init_acl_subquery,
|
||||||
"CASE WHEN privtype = 'e' THEN "
|
"CASE WHEN privtype = 'e' THEN "
|
||||||
"(SELECT array_agg(acl) FROM "
|
"(SELECT pg_catalog.array_agg(acl) FROM "
|
||||||
"(SELECT unnest(pip.initprivs) AS acl "
|
"(SELECT pg_catalog.unnest(pip.initprivs) AS acl "
|
||||||
"EXCEPT "
|
"EXCEPT "
|
||||||
"SELECT unnest(acldefault(%s,%s))) as foo) END",
|
"SELECT pg_catalog.unnest(pg_catalog.acldefault(%s,%s))) as foo) END",
|
||||||
obj_kind,
|
obj_kind,
|
||||||
acl_owner);
|
acl_owner);
|
||||||
|
|
||||||
printfPQExpBuffer(init_racl_subquery,
|
printfPQExpBuffer(init_racl_subquery,
|
||||||
"CASE WHEN privtype = 'e' THEN "
|
"CASE WHEN privtype = 'e' THEN "
|
||||||
"(SELECT array_agg(acl) FROM "
|
"(SELECT pg_catalog.array_agg(acl) FROM "
|
||||||
"(SELECT unnest(acldefault(%s,%s)) AS acl "
|
"(SELECT pg_catalog.unnest(pg_catalog.acldefault(%s,%s)) AS acl "
|
||||||
"EXCEPT "
|
"EXCEPT "
|
||||||
"SELECT unnest(pip.initprivs)) as foo) END",
|
"SELECT pg_catalog.unnest(pip.initprivs)) as foo) END",
|
||||||
obj_kind,
|
obj_kind,
|
||||||
acl_owner);
|
acl_owner);
|
||||||
}
|
}
|
||||||
|
@ -2825,8 +2825,8 @@ getBlobs(Archive *fout)
|
|||||||
"%s AS initrlomacl "
|
"%s AS initrlomacl "
|
||||||
"FROM pg_largeobject_metadata l "
|
"FROM pg_largeobject_metadata l "
|
||||||
"LEFT JOIN pg_init_privs pip ON "
|
"LEFT JOIN pg_init_privs pip ON "
|
||||||
"(l.oid = pip.objoid AND pip.classoid = "
|
"(l.oid = pip.objoid "
|
||||||
"(SELECT oid FROM pg_class WHERE relname = 'pg_largeobject')"
|
"AND pip.classoid = 'pg_largeobject'::regclass "
|
||||||
"AND pip.objsubid = 0) ",
|
"AND pip.objsubid = 0) ",
|
||||||
username_subquery,
|
username_subquery,
|
||||||
acl_subquery->data,
|
acl_subquery->data,
|
||||||
@ -3569,8 +3569,8 @@ getNamespaces(Archive *fout, int *numNamespaces)
|
|||||||
"%s as initrnspacl "
|
"%s as initrnspacl "
|
||||||
"FROM pg_namespace n "
|
"FROM pg_namespace n "
|
||||||
"LEFT JOIN pg_init_privs pip "
|
"LEFT JOIN pg_init_privs pip "
|
||||||
"ON (n.oid = pip.objoid AND pip.classoid = "
|
"ON (n.oid = pip.objoid "
|
||||||
"(SELECT oid FROM pg_class WHERE relname = 'pg_namespace') "
|
"AND pip.classoid = 'pg_namespace'::regclass "
|
||||||
"AND pip.objsubid = 0) ",
|
"AND pip.objsubid = 0) ",
|
||||||
username_subquery,
|
username_subquery,
|
||||||
acl_subquery->data,
|
acl_subquery->data,
|
||||||
@ -3851,9 +3851,9 @@ getTypes(Archive *fout, int *numTypes)
|
|||||||
"t.typname[0] = '_' AND t.typelem != 0 AND "
|
"t.typname[0] = '_' AND t.typelem != 0 AND "
|
||||||
"(SELECT typarray FROM pg_type te WHERE oid = t.typelem) = t.oid AS isarray "
|
"(SELECT typarray FROM pg_type te WHERE oid = t.typelem) = t.oid AS isarray "
|
||||||
"FROM pg_type t "
|
"FROM pg_type t "
|
||||||
"LEFT JOIN pg_init_privs pip "
|
"LEFT JOIN pg_init_privs pip ON "
|
||||||
"ON (t.oid = pip.objoid AND pip.classoid = "
|
"(t.oid = pip.objoid "
|
||||||
"(SELECT oid FROM pg_class WHERE relname = 'pg_type') "
|
"AND pip.classoid = 'pg_type'::regclass "
|
||||||
"AND pip.objsubid = 0) ",
|
"AND pip.objsubid = 0) ",
|
||||||
acl_subquery->data,
|
acl_subquery->data,
|
||||||
racl_subquery->data,
|
racl_subquery->data,
|
||||||
@ -4713,8 +4713,8 @@ getAggregates(Archive *fout, int *numAggs)
|
|||||||
"%s AS initraggacl "
|
"%s AS initraggacl "
|
||||||
"FROM pg_proc p "
|
"FROM pg_proc p "
|
||||||
"LEFT JOIN pg_init_privs pip ON "
|
"LEFT JOIN pg_init_privs pip ON "
|
||||||
"(p.oid = pip.objoid AND pip.classoid = "
|
"(p.oid = pip.objoid "
|
||||||
"(SELECT oid FROM pg_class WHERE relname = 'pg_proc') "
|
"AND pip.classoid = 'pg_proc'::regclass "
|
||||||
"AND pip.objsubid = 0) "
|
"AND pip.objsubid = 0) "
|
||||||
"WHERE p.proisagg AND ("
|
"WHERE p.proisagg AND ("
|
||||||
"p.pronamespace != "
|
"p.pronamespace != "
|
||||||
@ -4956,8 +4956,8 @@ getFuncs(Archive *fout, int *numFuncs)
|
|||||||
"(%s p.proowner) AS rolname "
|
"(%s p.proowner) AS rolname "
|
||||||
"FROM pg_proc p "
|
"FROM pg_proc p "
|
||||||
"LEFT JOIN pg_init_privs pip ON "
|
"LEFT JOIN pg_init_privs pip ON "
|
||||||
"(p.oid = pip.objoid AND pip.classoid = "
|
"(p.oid = pip.objoid "
|
||||||
"(SELECT oid FROM pg_class WHERE relname = 'pg_proc') "
|
"AND pip.classoid = 'pg_proc'::regclass "
|
||||||
"AND pip.objsubid = 0) "
|
"AND pip.objsubid = 0) "
|
||||||
"WHERE NOT proisagg "
|
"WHERE NOT proisagg "
|
||||||
"AND NOT EXISTS (SELECT 1 FROM pg_depend "
|
"AND NOT EXISTS (SELECT 1 FROM pg_depend "
|
||||||
@ -5246,9 +5246,10 @@ getTables(Archive *fout, int *numTables)
|
|||||||
"CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
|
"CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
|
||||||
"WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
|
"WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
|
||||||
"tc.reloptions AS toast_reloptions, "
|
"tc.reloptions AS toast_reloptions, "
|
||||||
"EXISTS (SELECT 1 FROM pg_attribute at LEFT JOIN pg_init_privs pip ON"
|
"EXISTS (SELECT 1 FROM pg_attribute at LEFT JOIN pg_init_privs pip ON "
|
||||||
"(c.oid = pip.objoid AND pip.classoid = "
|
"(c.oid = pip.objoid "
|
||||||
"(SELECT oid FROM pg_class WHERE relname = 'pg_class') AND pip.objsubid = at.attnum)"
|
"AND pip.classoid = 'pg_class'::regclass "
|
||||||
|
"AND pip.objsubid = at.attnum)"
|
||||||
"WHERE at.attrelid = c.oid AND ("
|
"WHERE at.attrelid = c.oid AND ("
|
||||||
"%s IS NOT NULL "
|
"%s IS NOT NULL "
|
||||||
"OR %s IS NOT NULL "
|
"OR %s IS NOT NULL "
|
||||||
@ -5264,9 +5265,9 @@ getTables(Archive *fout, int *numTables)
|
|||||||
"d.refclassid = c.tableoid AND d.deptype = 'a') "
|
"d.refclassid = c.tableoid AND d.deptype = 'a') "
|
||||||
"LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
|
"LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
|
||||||
"LEFT JOIN pg_init_privs pip ON "
|
"LEFT JOIN pg_init_privs pip ON "
|
||||||
"(c.oid = pip.objoid AND pip.classoid = "
|
"(c.oid = pip.objoid "
|
||||||
"(SELECT oid FROM pg_class "
|
"AND pip.classoid = 'pg_class'::regclass "
|
||||||
"WHERE relname = 'pg_class') AND pip.objsubid = 0) "
|
"AND pip.objsubid = 0) "
|
||||||
"WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
|
"WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
|
||||||
"ORDER BY c.oid",
|
"ORDER BY c.oid",
|
||||||
acl_subquery->data,
|
acl_subquery->data,
|
||||||
@ -7163,9 +7164,9 @@ getProcLangs(Archive *fout, int *numProcLangs)
|
|||||||
"%s AS initrlanacl, "
|
"%s AS initrlanacl, "
|
||||||
"(%s l.lanowner) AS lanowner "
|
"(%s l.lanowner) AS lanowner "
|
||||||
"FROM pg_language l "
|
"FROM pg_language l "
|
||||||
"LEFT JOIN pg_init_privs pip "
|
"LEFT JOIN pg_init_privs pip ON "
|
||||||
"ON (l.oid = pip.objoid AND pip.classoid = "
|
"(l.oid = pip.objoid "
|
||||||
"(SELECT oid FROM pg_class WHERE relname = 'pg_type') "
|
"AND pip.classoid = 'pg_type'::regclass "
|
||||||
"AND pip.objsubid = 0) "
|
"AND pip.objsubid = 0) "
|
||||||
"WHERE l.lanispl "
|
"WHERE l.lanispl "
|
||||||
"ORDER BY l.oid",
|
"ORDER BY l.oid",
|
||||||
@ -8583,9 +8584,9 @@ getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
|
|||||||
"ORDER BY option_name"
|
"ORDER BY option_name"
|
||||||
"), E',\n ') AS fdwoptions "
|
"), E',\n ') AS fdwoptions "
|
||||||
"FROM pg_foreign_data_wrapper f "
|
"FROM pg_foreign_data_wrapper f "
|
||||||
"LEFT JOIN pg_init_privs pip "
|
"LEFT JOIN pg_init_privs pip ON "
|
||||||
"ON (f.oid = pip.objoid AND pip.classoid = "
|
"(f.oid = pip.objoid "
|
||||||
"(SELECT oid FROM pg_class WHERE relname = 'pg_foreign_data_wrapper') "
|
"AND pip.classoid = 'pg_foreign_data_wrapper'::regclass "
|
||||||
"AND pip.objsubid = 0) ",
|
"AND pip.objsubid = 0) ",
|
||||||
username_subquery,
|
username_subquery,
|
||||||
acl_subquery->data,
|
acl_subquery->data,
|
||||||
@ -8753,8 +8754,8 @@ getForeignServers(Archive *fout, int *numForeignServers)
|
|||||||
"), E',\n ') AS srvoptions "
|
"), E',\n ') AS srvoptions "
|
||||||
"FROM pg_foreign_server f "
|
"FROM pg_foreign_server f "
|
||||||
"LEFT JOIN pg_init_privs pip "
|
"LEFT JOIN pg_init_privs pip "
|
||||||
"ON (f.oid = pip.objoid AND pip.classoid = "
|
"ON (f.oid = pip.objoid "
|
||||||
"(SELECT oid FROM pg_class WHERE relname = 'pg_foreign_server') "
|
"AND pip.classoid = 'pg_foreign_server'::regclass "
|
||||||
"AND pip.objsubid = 0) ",
|
"AND pip.objsubid = 0) ",
|
||||||
username_subquery,
|
username_subquery,
|
||||||
acl_subquery->data,
|
acl_subquery->data,
|
||||||
@ -14600,13 +14601,13 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
|
|||||||
*/
|
*/
|
||||||
if (strlen(initacls) != 0 || strlen(initracls) != 0)
|
if (strlen(initacls) != 0 || strlen(initracls) != 0)
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(sql, "SELECT binary_upgrade_set_record_init_privs(true);\n");
|
appendPQExpBuffer(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
|
||||||
if (!buildACLCommands(name, subname, type, initacls, initracls, owner,
|
if (!buildACLCommands(name, subname, type, initacls, initracls, owner,
|
||||||
"", fout->remoteVersion, sql))
|
"", fout->remoteVersion, sql))
|
||||||
exit_horribly(NULL,
|
exit_horribly(NULL,
|
||||||
"could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)\n",
|
"could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)\n",
|
||||||
initacls, initracls, name, type);
|
initacls, initracls, name, type);
|
||||||
appendPQExpBuffer(sql, "SELECT binary_upgrade_set_record_init_privs(false);\n");
|
appendPQExpBuffer(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buildACLCommands(name, subname, type, acls, racls, owner,
|
if (!buildACLCommands(name, subname, type, acls, racls, owner,
|
||||||
@ -14992,11 +14993,11 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
|
|||||||
"%s AS initrattacl "
|
"%s AS initrattacl "
|
||||||
"FROM pg_catalog.pg_attribute at "
|
"FROM pg_catalog.pg_attribute at "
|
||||||
"JOIN pg_catalog.pg_class c ON (at.attrelid = c.oid) "
|
"JOIN pg_catalog.pg_class c ON (at.attrelid = c.oid) "
|
||||||
"LEFT JOIN pg_init_privs pip ON "
|
"LEFT JOIN pg_catalog.pg_init_privs pip ON "
|
||||||
"(pip.classoid = "
|
"(at.attrelid = pip.objoid "
|
||||||
"(SELECT oid FROM pg_class WHERE relname = 'pg_class') AND "
|
"AND pip.classoid = 'pg_catalog.pg_class'::pg_catalog.regclass "
|
||||||
" at.attrelid = pip.objoid AND at.attnum = pip.objsubid) "
|
"AND at.attnum = pip.objsubid) "
|
||||||
"WHERE at.attrelid = '%u' AND "
|
"WHERE at.attrelid = '%u'::pg_catalog.oid AND "
|
||||||
"NOT at.attisdropped "
|
"NOT at.attisdropped "
|
||||||
"AND ("
|
"AND ("
|
||||||
"%s IS NOT NULL OR "
|
"%s IS NOT NULL OR "
|
||||||
@ -15025,7 +15026,7 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
|
|||||||
"SELECT attname, attacl, NULL as rattacl, "
|
"SELECT attname, attacl, NULL as rattacl, "
|
||||||
"NULL AS initattacl, NULL AS initrattacl "
|
"NULL AS initattacl, NULL AS initrattacl "
|
||||||
"FROM pg_catalog.pg_attribute "
|
"FROM pg_catalog.pg_attribute "
|
||||||
"WHERE attrelid = '%u' AND NOT attisdropped "
|
"WHERE attrelid = '%u'::pg_catalog.oid AND NOT attisdropped "
|
||||||
"AND attacl IS NOT NULL "
|
"AND attacl IS NOT NULL "
|
||||||
"ORDER BY attnum",
|
"ORDER BY attnum",
|
||||||
tbinfo->dobj.catId.oid);
|
tbinfo->dobj.catId.oid);
|
||||||
|
@ -340,9 +340,9 @@ my %tests = (
|
|||||||
},
|
},
|
||||||
'GRANT SELECT ON TABLE regress_pg_dump_table' => {
|
'GRANT SELECT ON TABLE regress_pg_dump_table' => {
|
||||||
regexp => qr/^
|
regexp => qr/^
|
||||||
\QSELECT binary_upgrade_set_record_init_privs(true);\E\n
|
\QSELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\E\n
|
||||||
\QGRANT SELECT ON TABLE regress_pg_dump_table TO dump_test;\E\n
|
\QGRANT SELECT ON TABLE regress_pg_dump_table TO dump_test;\E\n
|
||||||
\QSELECT binary_upgrade_set_record_init_privs(false);\E
|
\QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
|
||||||
$/xms,
|
$/xms,
|
||||||
like => {
|
like => {
|
||||||
binary_upgrade => 1,
|
binary_upgrade => 1,
|
||||||
@ -362,9 +362,9 @@ my %tests = (
|
|||||||
},
|
},
|
||||||
'GRANT SELECT(col1) ON regress_pg_dump_table' => {
|
'GRANT SELECT(col1) ON regress_pg_dump_table' => {
|
||||||
regexp => qr/^
|
regexp => qr/^
|
||||||
\QSELECT binary_upgrade_set_record_init_privs(true);\E\n
|
\QSELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\E\n
|
||||||
\QGRANT SELECT(col1) ON TABLE regress_pg_dump_table TO PUBLIC;\E\n
|
\QGRANT SELECT(col1) ON TABLE regress_pg_dump_table TO PUBLIC;\E\n
|
||||||
\QSELECT binary_upgrade_set_record_init_privs(false);\E
|
\QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
|
||||||
$/xms,
|
$/xms,
|
||||||
like => {
|
like => {
|
||||||
binary_upgrade => 1,
|
binary_upgrade => 1,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user