diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index 10700d6fd4a..9b70906a4a9 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -707,6 +707,17 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1;
Remote SQL: SELECT c1, c2 FROM public.loct_empty ORDER BY c1 ASC NULLS LAST
(3 rows)
+-- test restriction on non-system foreign tables.
+SET restrict_nonsystem_relation_kind TO 'foreign-table';
+SELECT * from ft1 where c1 < 1; -- ERROR
+ERROR: access to non-system foreign table is restricted
+INSERT INTO ft1 (c1) VALUES (1); -- ERROR
+ERROR: access to non-system foreign table is restricted
+DELETE FROM ft1 WHERE c1 = 1; -- ERROR
+ERROR: access to non-system foreign table is restricted
+TRUNCATE ft1; -- ERROR
+ERROR: access to non-system foreign table is restricted
+RESET restrict_nonsystem_relation_kind;
-- ===================================================================
-- WHERE with remotely-executable conditions
-- ===================================================================
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index 793dd64811d..ac290d3ba30 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -321,6 +321,14 @@ DELETE FROM loct_empty;
ANALYZE ft_empty;
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1;
+-- test restriction on non-system foreign tables.
+SET restrict_nonsystem_relation_kind TO 'foreign-table';
+SELECT * from ft1 where c1 < 1; -- ERROR
+INSERT INTO ft1 (c1) VALUES (1); -- ERROR
+DELETE FROM ft1 WHERE c1 = 1; -- ERROR
+TRUNCATE ft1; -- ERROR
+RESET restrict_nonsystem_relation_kind;
+
-- ===================================================================
-- WHERE with remotely-executable conditions
-- ===================================================================
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 23f60cad528..9b03793f74a 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -9027,6 +9027,23 @@ SET XML OPTION { DOCUMENT | CONTENT };
+
+ restrict_nonsystem_relation_kind (string)
+
+ restrict_nonsystem_relation_kind
+ configuration parameter
+
+
+
+
+ This variable specifies relation kind to which access is restricted.
+ It contains a comma-separated list of relation kind. Currently, the
+ supported relation kinds are view and
+ foreign-table.
+
+
+
+
diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml
index d3113d76a07..6a2ad26a17d 100644
--- a/doc/src/sgml/ref/pg_dump.sgml
+++ b/doc/src/sgml/ref/pg_dump.sgml
@@ -772,6 +772,19 @@ PostgreSQL documentation
+
+
+
+
+ This is the same as
+ the / option,
+ except that it also excludes any partitions or inheritance child
+ tables of the table(s) matching the
+ pattern.
+
+
+
+
@@ -790,6 +803,18 @@ PostgreSQL documentation
+
+
+
+
+ This is the same as the option,
+ except that it also excludes data of any partitions or inheritance
+ child tables of the table(s) matching the
+ pattern.
+
+
+
+
@@ -831,6 +856,14 @@ PostgreSQL documentation
The only exception is that an empty pattern is disallowed.
+
+
+ Using wildcards in may result
+ in access to unexpected foreign servers. Also, to use this option securely,
+ make sure that the named server must have a trusted owner.
+
+
+
When is specified,
@@ -1161,6 +1194,19 @@ PostgreSQL documentation
+
+
+
+
+ This is the same as
+ the / option,
+ except that it also includes any partitions or inheritance child
+ tables of the table(s) matching the
+ pattern.
+
+
+
+
diff --git a/gpMgmt/test/behave/mgmt_utils/environment.py b/gpMgmt/test/behave/mgmt_utils/environment.py
index d79f9c18acc..217583c9c4c 100644
--- a/gpMgmt/test/behave/mgmt_utils/environment.py
+++ b/gpMgmt/test/behave/mgmt_utils/environment.py
@@ -68,6 +68,7 @@ def before_feature(context, feature):
dbconn.execSQL(context.conn, 'insert into t1 values(1, 2)')
dbconn.execSQL(context.conn, 'insert into t2 values(1, 3)')
dbconn.execSQL(context.conn, 'insert into t3 values(1, 4)')
+ dbconn.execSQL(context.conn, 'create or replace function select_one() returns integer as $$ select 1 $$ language sql')
context.conn.commit()
if 'gppkg' in feature.tags:
diff --git a/gpMgmt/test/behave/mgmt_utils/minirepro.feature b/gpMgmt/test/behave/mgmt_utils/minirepro.feature
index 15e9c666a51..03f098821ba 100644
--- a/gpMgmt/test/behave/mgmt_utils/minirepro.feature
+++ b/gpMgmt/test/behave/mgmt_utils/minirepro.feature
@@ -263,3 +263,15 @@ Feature: Dump minimum database objects that is related to the query
And the output file "/tmp/out.sql" should contain "Table: t3, Attribute: f"
And the output file "/tmp/out.sql" should be loaded to database "minidb_tmp" without error
And the file "/tmp/in.sql" should be executed in database "minidb_tmp" without error
+
+ @minirepro_core
+ Scenario: Dump database objects of only functions
+ Given the file "/tmp/in.sql" exists and contains "SELECT select_one()"
+ And the file "/tmp/out.sql" does not exist
+ When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql"
+ Then the output file "/tmp/out.sql" should exist
+ And the output file "/tmp/out.sql" should contain "CREATE FUNCTION public.select_one() RETURNS integer"
+ And the output file "/tmp/out.sql" should contain "LANGUAGE sql"
+ And the output file "/tmp/out.sql" should contain "AS $$ select 1 $$;"
+ And the output file "/tmp/out.sql" should be loaded to database "minidb_tmp" without error
+ And the file "/tmp/in.sql" should be executed in database "minidb_tmp" without error
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index 2d60eff9459..7a00c5f06db 100644
--- a/src/backend/foreign/foreign.c
+++ b/src/backend/foreign/foreign.c
@@ -33,6 +33,7 @@
#include "optimizer/planmain.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/tlist.h"
+#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/rel.h"
@@ -590,6 +591,15 @@ GetFdwRoutine(Oid fdwhandler)
Datum datum;
FdwRoutine *routine;
+ /* Check if the access to foreign tables is restricted */
+ if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0))
+ {
+ /* there must not be built-in FDW handler */
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("access to non-system foreign table is restricted")));
+ }
+
datum = OidFunctionCall0(fdwhandler);
routine = (FdwRoutine *) DatumGetPointer(datum);
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 53c1bf7d338..20c1587b062 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -47,6 +47,7 @@
#include "parser/parsetree.h"
#include "partitioning/partdesc.h"
#include "partitioning/partprune.h"
+#include "tcop/tcopprot.h"
#include "utils/lsyscache.h"
#include "utils/uri.h"
@@ -8482,7 +8483,19 @@ make_modifytable(PlannerInfo *root, Plan *subplan,
Assert(rte->rtekind == RTE_RELATION);
if (rte->relkind == RELKIND_FOREIGN_TABLE)
+ {
+ /* Check if the access to foreign tables is restricted */
+ if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0))
+ {
+ /* there must not be built-in foreign tables */
+ Assert(rte->relid >= FirstNormalObjectId);
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("access to non-system foreign table is restricted")));
+ }
+
fdwroutine = GetFdwRoutineByRelId(rte->relid);
+ }
else
fdwroutine = NULL;
}
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 46d85f3c324..8971c42fe77 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -49,6 +49,7 @@
#include "rewrite/rewriteManip.h"
#include "statistics/statistics.h"
#include "storage/bufmgr.h"
+#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/partcache.h"
@@ -484,6 +485,17 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
/* Grab foreign-table info using the relcache, while we have it */
if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
{
+ /* Check if the access to foreign tables is restricted */
+ if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0))
+ {
+ /* there must not be built-in foreign tables */
+ Assert(RelationGetRelid(relation) >= FirstNormalObjectId);
+
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("access to non-system foreign table is restricted")));
+ }
+
rel->serverid = GetForeignServerIdByRelId(RelationGetRelid(relation));
rel->segSeverids = GetForeignServerSegsByRelId(RelationGetRelid(relation));
rel->fdwroutine = GetFdwRoutineForRelation(relation, true);
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 23c528b60f9..9da36260c77 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -43,6 +43,7 @@
#include "rewrite/rewriteManip.h"
#include "rewrite/rewriteSearchCycle.h"
#include "rewrite/rowsecurity.h"
+#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
@@ -1815,6 +1816,14 @@ ApplyRetrieveRule(Query *parsetree,
if (rule->qual != NULL)
elog(ERROR, "cannot handle qualified ON SELECT rule");
+ /* Check if the expansion of non-system views are restricted */
+ if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_VIEW) != 0 &&
+ RelationGetRelid(relation) >= FirstNormalObjectId))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("access to non-system view \"%s\" is restricted",
+ RelationGetRelationName(relation))));
+
if (rt_index == parsetree->resultRelation)
{
/*
@@ -3261,6 +3270,14 @@ rewriteTargetView(Query *parsetree, Relation view)
}
}
+ /* Check if the expansion of non-system views are restricted */
+ if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_VIEW) != 0 &&
+ RelationGetRelid(view) >= FirstNormalObjectId))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("access to non-system view \"%s\" is restricted",
+ RelationGetRelationName(view))));
+
/*
* For INSERT/UPDATE the modified columns must all be updatable. Note that
* we get the modified columns from the query's targetlist, not from the
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 37cdcfba46a..6ae0202b396 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -89,6 +89,7 @@
#include "utils/snapmgr.h"
#include "utils/timeout.h"
#include "utils/timestamp.h"
+#include "utils/varlena.h"
#include "cdb/cdbutil.h"
#include "cdb/cdbvars.h"
@@ -151,6 +152,8 @@ cancel_pending_hook_type cancel_pending_hook = NULL;
* Hook for query execution.
*/
exec_simple_query_hook_type exec_simple_query_hook = NULL;
+/* flags for non-system relation kinds to restrict use */
+int restrict_nonsystem_relation_kind;
/* ----------------
* private typedefs etc
@@ -4558,6 +4561,66 @@ assign_max_stack_depth(int newval, void *extra)
max_stack_depth_bytes = newval_bytes;
}
+/*
+ * GUC check_hook for restrict_nonsystem_relation_kind
+ */
+bool
+check_restrict_nonsystem_relation_kind(char **newval, void **extra, GucSource source)
+{
+ char *rawstring;
+ List *elemlist;
+ ListCell *l;
+ int flags = 0;
+
+ /* Need a modifiable copy of string */
+ rawstring = pstrdup(*newval);
+
+ if (!SplitIdentifierString(rawstring, ',', &elemlist))
+ {
+ /* syntax error in list */
+ GUC_check_errdetail("List syntax is invalid.");
+ pfree(rawstring);
+ list_free(elemlist);
+ return false;
+ }
+
+ foreach(l, elemlist)
+ {
+ char *tok = (char *) lfirst(l);
+
+ if (pg_strcasecmp(tok, "view") == 0)
+ flags |= RESTRICT_RELKIND_VIEW;
+ else if (pg_strcasecmp(tok, "foreign-table") == 0)
+ flags |= RESTRICT_RELKIND_FOREIGN_TABLE;
+ else
+ {
+ GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
+ pfree(rawstring);
+ list_free(elemlist);
+ return false;
+ }
+ }
+
+ pfree(rawstring);
+ list_free(elemlist);
+
+ /* Save the flags in *extra, for use by the assign function */
+ *extra = malloc(sizeof(int));
+ *((int *) *extra) = flags;
+
+ return true;
+}
+
+/*
+ * GUC assign_hook for restrict_nonsystem_relation_kind
+ */
+void
+assign_restrict_nonsystem_relation_kind(const char *newval, void *extra)
+{
+ int *flags = (int *) extra;
+
+ restrict_nonsystem_relation_kind = *flags;
+}
/*
* set_debug_options --- apply "-d N" command line option
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 168f6113ce2..bc3e76d0314 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -686,6 +686,8 @@ static char *recovery_target_xid_string;
static char *recovery_target_name_string;
static char *recovery_target_lsn_string;
static char *file_encryption_method_str;
+static char *restrict_nonsystem_relation_kind_string;
+
/* should be static, but commands/variable.c needs to get at this */
char *role_string;
@@ -4761,7 +4763,18 @@ static struct config_string ConfigureNamesString[] =
"",
NULL, NULL, NULL
},
-
+
+ {
+ {"restrict_nonsystem_relation_kind", PGC_USERSET, CLIENT_CONN_STATEMENT,
+ gettext_noop("Sets relation kinds of non-system relation to restrict use"),
+ NULL,
+ GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE
+ },
+ &restrict_nonsystem_relation_kind_string,
+ "",
+ check_restrict_nonsystem_relation_kind, assign_restrict_nonsystem_relation_kind, NULL
+ },
+
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 661e19605f6..e180479d6a7 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -161,6 +161,8 @@ getSchemaData(Archive *fout, int *numTablesPtr)
pg_log_info("reading user-defined tables");
tblinfo = getTables(fout, &numTables);
+ getPartitionDefs(fout, tblinfo, numTables);
+
getOwnedSeqs(fout, tblinfo, numTables);
pg_log_info("reading user-defined functions");
@@ -606,6 +608,8 @@ AssignDumpId(DumpableObject *dobj)
dobj->namespace = NULL; /* may be set later */
dobj->dump = DUMP_COMPONENT_ALL; /* default assumption */
dobj->dump_contains = DUMP_COMPONENT_ALL; /* default assumption */
+ /* All objects have definitions; we may set more components bits later */
+ dobj->components = DUMP_COMPONENT_DEFINITION;
dobj->ext_member = false; /* default assumption */
dobj->depends_on_ext = false; /* default assumption */
dobj->dependencies = NULL;
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index ebb3654b725..2f40f0838ea 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -25,7 +25,7 @@ static bool parseAclItem(const char *item, const char *type,
const char *name, const char *subname, int remoteVersion,
PQExpBuffer grantee, PQExpBuffer grantor,
PQExpBuffer privs, PQExpBuffer privswgo);
-static char *copyAclUserName(PQExpBuffer output, char *input);
+static char *dequoteAclUserName(PQExpBuffer output, char *input);
static void AddAcl(PQExpBuffer aclbuf, const char *keyword,
const char *subname);
@@ -77,7 +77,8 @@ sanitize_line(const char *str, bool want_hyphen)
* TABLE, SEQUENCE, FUNCTION, PROCEDURE, LANGUAGE, SCHEMA, DATABASE, TABLESPACE,
* FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT)
* acls: the ACL string fetched from the database
- * racls: the ACL string of any initial-but-now-revoked privileges
+ * baseacls: the initial ACL string for this object; can be
+ * NULL or empty string to indicate "not available from server"
* owner: username of object owner (will be passed through fmtId); can be
* NULL or empty string to indicate "no owner known"
* prefix: string to prefix to each generated command; typically empty
@@ -86,6 +87,12 @@ sanitize_line(const char *str, bool want_hyphen)
* Returns true if okay, false if could not parse the acl string.
* The resulting commands (if any) are appended to the contents of 'sql'.
*
+ * baseacls is typically the result of acldefault() for the object's type
+ * and owner. However, if there is a pg_init_privs entry for the object,
+ * it should instead be the initprivs ACLs. When acls is itself a
+ * pg_init_privs entry, baseacls is what to dump that relative to; then
+ * it can be either an acldefault() value or an empty ACL "{}".
+ *
* Note: when processing a default ACL, prefix is "ALTER DEFAULT PRIVILEGES "
* or something similar, and name is an empty string.
*
@@ -94,15 +101,19 @@ sanitize_line(const char *str, bool want_hyphen)
*/
bool
buildACLCommands(const char *name, const char *subname, const char *nspname,
- const char *type, const char *acls, const char *racls,
+ const char *type, const char *acls, const char *baseacls,
const char *owner, const char *prefix, int remoteVersion,
PQExpBuffer sql)
{
bool ok = true;
char **aclitems = NULL;
- char **raclitems = NULL;
+ char **baseitems = NULL;
+ char **grantitems = NULL;
+ char **revokeitems = NULL;
int naclitems = 0;
- int nraclitems = 0;
+ int nbaseitems = 0;
+ int ngrantitems = 0;
+ int nrevokeitems = 0;
int i;
PQExpBuffer grantee,
grantor,
@@ -110,37 +121,88 @@ buildACLCommands(const char *name, const char *subname, const char *nspname,
privswgo;
PQExpBuffer firstsql,
secondsql;
- bool found_owner_privs = false;
- if (strlen(acls) == 0 && strlen(racls) == 0)
+ /*
+ * If the acl was NULL (initial default state), we need do nothing. Note
+ * that this is distinguishable from all-privileges-revoked, which will
+ * look like an empty array ("{}").
+ */
+ if (acls == NULL || *acls == '\0')
return true; /* object has default permissions */
/* treat empty-string owner same as NULL */
if (owner && *owner == '\0')
owner = NULL;
- if (strlen(acls) != 0)
+ /* Parse the acls array */
+ if (!parsePGArray(acls, &aclitems, &naclitems))
+ {
+ if (aclitems)
+ free(aclitems);
+ return false;
+ }
+
+ /* Parse the baseacls, if provided */
+ if (baseacls && *baseacls != '\0')
{
- if (!parsePGArray(acls, &aclitems, &naclitems))
+ if (!parsePGArray(baseacls, &baseitems, &nbaseitems))
{
if (aclitems)
free(aclitems);
+ if (baseitems)
+ free(baseitems);
return false;
}
}
- if (strlen(racls) != 0)
+ /*
+ * Compare the actual ACL with the base ACL, extracting the privileges
+ * that need to be granted (i.e., are in the actual ACL but not the base
+ * ACL) and the ones that need to be revoked (the reverse). We use plain
+ * string comparisons to check for matches. In principle that could be
+ * fooled by extraneous issues such as whitespace, but since all these
+ * strings are the work of aclitemout(), it should be OK in practice.
+ * Besides, a false mismatch will just cause the output to be a little
+ * more verbose than it really needed to be.
+ *
+ * (If we weren't given a base ACL, this stanza winds up with all the
+ * ACL's items in grantitems and nothing in revokeitems. It's not worth
+ * special-casing that.)
+ */
+ grantitems = (char **) pg_malloc(naclitems * sizeof(char *));
+ for (i = 0; i < naclitems; i++)
{
- if (!parsePGArray(racls, &raclitems, &nraclitems))
+ bool found = false;
+
+ for (int j = 0; j < nbaseitems; j++)
{
- if (aclitems)
- free(aclitems);
- if (raclitems)
- free(raclitems);
- return false;
+ if (strcmp(aclitems[i], baseitems[j]) == 0)
+ {
+ found = true;
+ break;
+ }
}
+ if (!found)
+ grantitems[ngrantitems++] = aclitems[i];
}
+ revokeitems = (char **) pg_malloc(nbaseitems * sizeof(char *));
+ for (i = 0; i < nbaseitems; i++)
+ {
+ bool found = false;
+ for (int j = 0; j < naclitems; j++)
+ {
+ if (strcmp(baseitems[i], aclitems[j]) == 0)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ revokeitems[nrevokeitems++] = baseitems[i];
+ }
+
+ /* Prepare working buffers */
grantee = createPQExpBuffer();
grantor = createPQExpBuffer();
privs = createPQExpBuffer();
@@ -148,50 +210,21 @@ buildACLCommands(const char *name, const char *subname, const char *nspname,
/*
* At the end, these two will be pasted together to form the result.
- *
- * For older systems we use these to ensure that the owner privileges go
- * before the other ones, as a GRANT could create the default entry for
- * the object, which generally includes all rights for the owner. In more
- * recent versions we normally handle this because the owner rights come
- * first in the ACLs, but older versions might have them after the PUBLIC
- * privileges.
- *
- * For 9.6 and later systems, much of this changes. With 9.6, we check
- * the default privileges for the objects at dump time and create two sets
- * of ACLs- "racls" which are the ACLs to REVOKE from the object (as the
- * object may have initial privileges on it, along with any default ACLs
- * which are not part of the current set of privileges), and regular
- * "acls", which are the ACLs to GRANT to the object. We handle the
- * REVOKEs first, followed by the GRANTs.
*/
firstsql = createPQExpBuffer();
secondsql = createPQExpBuffer();
/*
- * For pre-9.6 systems, we always start with REVOKE ALL FROM PUBLIC, as we
- * don't wish to make any assumptions about what the default ACLs are, and
- * we do not collect them during the dump phase (and racls will always be
- * the empty set, see above).
- *
- * For 9.6 and later, if any revoke ACLs have been provided, then include
- * them in 'firstsql'.
+ * If we weren't given baseacls information, we just revoke everything and
+ * then grant what's listed in the ACL. This avoids having to embed
+ * detailed knowledge about what the defaults are/were, and it's not very
+ * expensive since servers lacking acldefault() are now rare.
*
- * Revoke ACLs happen when an object starts out life with a set of
- * privileges (eg: GRANT SELECT ON pg_class TO PUBLIC;) and the user has
- * decided to revoke those rights. Since those objects come into being
- * with those default privileges, we have to revoke them to match what the
- * current state of affairs is. Note that we only started explicitly
- * tracking such initial rights in 9.6, and prior to that all initial
- * rights are actually handled by the simple 'REVOKE ALL .. FROM PUBLIC'
- * case, for initdb-created objects. Prior to 9.6, we didn't handle
- * extensions correctly, but we do now by tracking their initial
- * privileges, in the same way we track initdb initial privileges, see
- * pg_init_privs.
+ * Otherwise, we need only revoke what's listed in revokeitems.
*/
- if (remoteVersion < 90600)
+ if (baseacls == NULL || *baseacls == '\0')
{
- Assert(nraclitems == 0);
-
+ /* We assume the old defaults only involved the owner and PUBLIC */
appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
if (subname)
appendPQExpBuffer(firstsql, "(%s)", subname);
@@ -199,13 +232,24 @@ buildACLCommands(const char *name, const char *subname, const char *nspname,
if (nspname && *nspname)
appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
appendPQExpBuffer(firstsql, "%s FROM PUBLIC;\n", name);
+ if (owner)
+ {
+ appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
+ if (subname)
+ appendPQExpBuffer(firstsql, "(%s)", subname);
+ appendPQExpBuffer(firstsql, " ON %s ", type);
+ if (nspname && *nspname)
+ appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
+ appendPQExpBuffer(firstsql, "%s FROM %s;\n", name, fmtId(owner));
+ }
}
else
{
/* Scan individual REVOKE ACL items */
- for (i = 0; i < nraclitems; i++)
+ for (i = 0; i < nrevokeitems; i++)
{
- if (!parseAclItem(raclitems[i], type, name, subname, remoteVersion,
+ if (!parseAclItem(revokeitems[i],
+ type, name, subname, remoteVersion,
grantee, grantor, privs, NULL))
{
ok = false;
@@ -232,146 +276,92 @@ buildACLCommands(const char *name, const char *subname, const char *nspname,
}
}
- /* Scan individual ACL items */
- for (i = 0; i < naclitems; i++)
+ /*
+ * Scan individual ACL items to be granted.
+ *
+ * The order in which privileges appear in the ACL string (the order they
+ * have been GRANT'd in, which the backend maintains) must be preserved to
+ * ensure that GRANTs WITH GRANT OPTION and subsequent GRANTs based on
+ * those are dumped in the correct order. However, some old server
+ * versions will show grants to PUBLIC before the owner's own grants; for
+ * consistency's sake, force the owner's grants to be output first.
+ */
+ for (i = 0; i < ngrantitems; i++)
{
- if (!parseAclItem(aclitems[i], type, name, subname, remoteVersion,
- grantee, grantor, privs, privswgo))
- {
- ok = false;
- break;
- }
-
- if (grantor->len == 0 && owner)
- printfPQExpBuffer(grantor, "%s", owner);
-
- if (privs->len > 0 || privswgo->len > 0)
+ if (parseAclItem(grantitems[i], type, name, subname, remoteVersion,
+ grantee, grantor, privs, privswgo))
{
/*
- * Prior to 9.6, we had to handle owner privileges in a special
- * manner by first REVOKE'ing the rights and then GRANT'ing them
- * after. With 9.6 and above, what we need to REVOKE and what we
- * need to GRANT is figured out when we dump and stashed into
- * "racls" and "acls", respectively. See above.
+ * If the grantor isn't the owner, we'll need to use SET SESSION
+ * AUTHORIZATION to become the grantor. Issue the SET/RESET only
+ * if there's something useful to do.
*/
- if (remoteVersion < 90600 && owner
- && strcmp(grantee->data, owner) == 0
- && strcmp(grantor->data, owner) == 0)
+ if (privs->len > 0 || privswgo->len > 0)
{
- found_owner_privs = true;
+ PQExpBuffer thissql;
+
+ /* Set owner as grantor if that's not explicit in the ACL */
+ if (grantor->len == 0 && owner)
+ printfPQExpBuffer(grantor, "%s", owner);
+
+ /* Make sure owner's own grants are output before others */
+ if (owner &&
+ strcmp(grantee->data, owner) == 0 &&
+ strcmp(grantor->data, owner) == 0)
+ thissql = firstsql;
+ else
+ thissql = secondsql;
- /*
- * For the owner, the default privilege level is ALL WITH
- * GRANT OPTION.
- */
- if (strcmp(privswgo->data, "ALL") != 0)
- {
- appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
- if (subname)
- appendPQExpBuffer(firstsql, "(%s)", subname);
- appendPQExpBuffer(firstsql, " ON %s ", type);
- if (nspname && *nspname)
- appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
- appendPQExpBuffer(firstsql, "%s FROM %s;\n",
- name, fmtId(grantee->data));
- if (privs->len > 0)
- {
- appendPQExpBuffer(firstsql,
- "%sGRANT %s ON %s ",
- prefix, privs->data, type);
- if (nspname && *nspname)
- appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
- appendPQExpBuffer(firstsql,
- "%s TO %s;\n",
- name, fmtId(grantee->data));
- }
- if (privswgo->len > 0)
- {
- appendPQExpBuffer(firstsql,
- "%sGRANT %s ON %s ",
- prefix, privswgo->data, type);
- if (nspname && *nspname)
- appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
- appendPQExpBuffer(firstsql,
- "%s TO %s WITH GRANT OPTION;\n",
- name, fmtId(grantee->data));
- }
- }
- }
- else
- {
- /*
- * For systems prior to 9.6, we can assume we are starting
- * from no privs at this point.
- *
- * For 9.6 and above, at this point we have issued REVOKE
- * statements for all initial and default privileges which are
- * no longer present on the object (as they were passed in as
- * 'racls') and we can simply GRANT the rights which are in
- * 'acls'.
- */
if (grantor->len > 0
&& (!owner || strcmp(owner, grantor->data) != 0))
- appendPQExpBuffer(secondsql, "SET SESSION AUTHORIZATION %s;\n",
+ appendPQExpBuffer(thissql, "SET SESSION AUTHORIZATION %s;\n",
fmtId(grantor->data));
if (privs->len > 0)
{
- appendPQExpBuffer(secondsql, "%sGRANT %s ON %s ",
+ appendPQExpBuffer(thissql, "%sGRANT %s ON %s ",
prefix, privs->data, type);
if (nspname && *nspname)
- appendPQExpBuffer(secondsql, "%s.", fmtId(nspname));
- appendPQExpBuffer(secondsql, "%s TO ", name);
+ appendPQExpBuffer(thissql, "%s.", fmtId(nspname));
+ appendPQExpBuffer(thissql, "%s TO ", name);
if (grantee->len == 0)
- appendPQExpBufferStr(secondsql, "PUBLIC;\n");
+ appendPQExpBufferStr(thissql, "PUBLIC;\n");
else if (strncmp(grantee->data, "group ",
strlen("group ")) == 0)
- appendPQExpBuffer(secondsql, "GROUP %s;\n",
+ appendPQExpBuffer(thissql, "GROUP %s;\n",
fmtId(grantee->data + strlen("group ")));
else
- appendPQExpBuffer(secondsql, "%s;\n", fmtId(grantee->data));
+ appendPQExpBuffer(thissql, "%s;\n", fmtId(grantee->data));
}
if (privswgo->len > 0)
{
- appendPQExpBuffer(secondsql, "%sGRANT %s ON %s ",
+ appendPQExpBuffer(thissql, "%sGRANT %s ON %s ",
prefix, privswgo->data, type);
if (nspname && *nspname)
- appendPQExpBuffer(secondsql, "%s.", fmtId(nspname));
- appendPQExpBuffer(secondsql, "%s TO ", name);
+ appendPQExpBuffer(thissql, "%s.", fmtId(nspname));
+ appendPQExpBuffer(thissql, "%s TO ", name);
if (grantee->len == 0)
- appendPQExpBufferStr(secondsql, "PUBLIC");
+ appendPQExpBufferStr(thissql, "PUBLIC");
else if (strncmp(grantee->data, "group ",
strlen("group ")) == 0)
- appendPQExpBuffer(secondsql, "GROUP %s",
+ appendPQExpBuffer(thissql, "GROUP %s",
fmtId(grantee->data + strlen("group ")));
else
- appendPQExpBufferStr(secondsql, fmtId(grantee->data));
- appendPQExpBufferStr(secondsql, " WITH GRANT OPTION;\n");
+ appendPQExpBufferStr(thissql, fmtId(grantee->data));
+ appendPQExpBufferStr(thissql, " WITH GRANT OPTION;\n");
}
if (grantor->len > 0
&& (!owner || strcmp(owner, grantor->data) != 0))
- appendPQExpBufferStr(secondsql, "RESET SESSION AUTHORIZATION;\n");
+ appendPQExpBufferStr(thissql, "RESET SESSION AUTHORIZATION;\n");
}
}
- }
-
- /*
- * For systems prior to 9.6, if we didn't find any owner privs, the owner
- * must have revoked 'em all.
- *
- * For 9.6 and above, we handle this through the 'racls'. See above.
- */
- if (remoteVersion < 90600 && !found_owner_privs && owner)
- {
- appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
- if (subname)
- appendPQExpBuffer(firstsql, "(%s)", subname);
- appendPQExpBuffer(firstsql, " ON %s ", type);
- if (nspname && *nspname)
- appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
- appendPQExpBuffer(firstsql, "%s FROM %s;\n",
- name, fmtId(owner));
+ else
+ {
+ /* parseAclItem failed, give up */
+ ok = false;
+ break;
+ }
}
destroyPQExpBuffer(grantee);
@@ -385,19 +375,23 @@ buildACLCommands(const char *name, const char *subname, const char *nspname,
if (aclitems)
free(aclitems);
-
- if (raclitems)
- free(raclitems);
+ if (baseitems)
+ free(baseitems);
+ if (grantitems)
+ free(grantitems);
+ if (revokeitems)
+ free(revokeitems);
return ok;
}
/*
- * Build ALTER DEFAULT PRIVILEGES command(s) for single pg_default_acl entry.
+ * Build ALTER DEFAULT PRIVILEGES command(s) for a single pg_default_acl entry.
*
* type: the object type (TABLES, FUNCTIONS, etc)
* nspname: schema name, or NULL for global default privileges
* acls: the ACL string fetched from the database
+ * acldefault: the appropriate default ACL for the object type and owner
* owner: username of privileges owner (will be passed through fmtId)
* remoteVersion: version of database
*
@@ -406,8 +400,7 @@ buildACLCommands(const char *name, const char *subname, const char *nspname,
*/
bool
buildDefaultACLCommands(const char *type, const char *nspname,
- const char *acls, const char *racls,
- const char *initacls, const char *initracls,
+ const char *acls, const char *acldefault,
const char *owner,
int remoteVersion,
PQExpBuffer sql)
@@ -427,21 +420,12 @@ buildDefaultACLCommands(const char *type, const char *nspname,
if (nspname)
appendPQExpBuffer(prefix, "IN SCHEMA %s ", fmtId(nspname));
- if (strlen(initacls) != 0 || strlen(initracls) != 0)
- {
- appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
- if (!buildACLCommands("", NULL, NULL, type,
- initacls, initracls, owner,
- prefix->data, remoteVersion, sql))
- {
- destroyPQExpBuffer(prefix);
- return false;
- }
- appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
- }
-
+ /*
+ * There's no such thing as initprivs for a default ACL, so the base ACL
+ * is always just the object-type-specific default.
+ */
if (!buildACLCommands("", NULL, NULL, type,
- acls, racls, owner,
+ acls, acldefault, owner,
prefix->data, remoteVersion, sql))
{
destroyPQExpBuffer(prefix);
@@ -491,7 +475,7 @@ parseAclItem(const char *item, const char *type,
buf = pg_strdup(item);
/* user or group name is string up to = */
- eqpos = copyAclUserName(grantee, buf);
+ eqpos = dequoteAclUserName(grantee, buf);
if (*eqpos != '=')
{
pg_free(buf);
@@ -503,7 +487,7 @@ parseAclItem(const char *item, const char *type,
if (slpos)
{
*slpos++ = '\0';
- slpos = copyAclUserName(grantor, slpos);
+ slpos = dequoteAclUserName(grantor, slpos);
if (*slpos != '\0')
{
pg_free(buf);
@@ -632,13 +616,46 @@ do { \
return true;
}
+/*
+ * Transfer the role name at *input into the output buffer, adding
+ * quoting according to the same rules as putid() in backend's acl.c.
+ */
+void
+quoteAclUserName(PQExpBuffer output, const char *input)
+{
+ const char *src;
+ bool safe = true;
+
+ for (src = input; *src; src++)
+ {
+ /* This test had better match what putid() does */
+ if (!isalnum((unsigned char) *src) && *src != '_')
+ {
+ safe = false;
+ break;
+ }
+ }
+ if (!safe)
+ appendPQExpBufferChar(output, '"');
+ for (src = input; *src; src++)
+ {
+ /* A double quote character in a username is encoded as "" */
+ if (*src == '"')
+ appendPQExpBufferChar(output, '"');
+ appendPQExpBufferChar(output, *src);
+ }
+ if (!safe)
+ appendPQExpBufferChar(output, '"');
+}
+
/*
* Transfer a user or group name starting at *input into the output buffer,
* dequoting if needed. Returns a pointer to just past the input name.
* The name is taken to end at an unquoted '=' or end of string.
+ * Note: unlike quoteAclUserName(), this first clears the output buffer.
*/
static char *
-copyAclUserName(PQExpBuffer output, char *input)
+dequoteAclUserName(PQExpBuffer output, char *input)
{
resetPQExpBuffer(output);
@@ -737,132 +754,6 @@ emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer,
}
}
-/*
- * buildACLQueries
- *
- * Build the subqueries to extract out the correct set of ACLs to be
- * GRANT'd and REVOKE'd for the specific kind of object, accounting for any
- * initial privileges (from pg_init_privs) and based on if we are in binary
- * upgrade mode or not.
- *
- * Also builds subqueries to extract out the set of ACLs to go from the object
- * default privileges to the privileges in pg_init_privs, if we are in binary
- * upgrade mode, so that those privileges can be set up and recorded in the new
- * cluster before the regular privileges are added on top of those.
- */
-void
-buildACLQueries(PQExpBuffer acl_subquery, PQExpBuffer racl_subquery,
- PQExpBuffer init_acl_subquery, PQExpBuffer init_racl_subquery,
- const char *acl_column, const char *acl_owner,
- const char *obj_kind, bool binary_upgrade)
-{
- /*
- * To get the delta from what the permissions were at creation time
- * (either initdb or CREATE EXTENSION) vs. what they are now, we have to
- * look at two things:
- *
- * What privileges have been added, which we calculate by extracting all
- * the current privileges (using the set of default privileges for the
- * object type if current privileges are NULL) and then removing those
- * which existed at creation time (again, using the set of default
- * privileges for the object type if there were no creation time
- * privileges).
- *
- * What privileges have been removed, which we calculate by extracting the
- * privileges as they were at creation time (or the default privileges, as
- * above), and then removing the current privileges (or the default
- * privileges, if current privileges are NULL).
- *
- * As a good cross-check, both directions of these checks should result in
- * the empty set if both the current ACL and the initial privs are NULL
- * (meaning, in practice, that the default ACLs were there at init time
- * and is what the current privileges are).
- *
- * We always perform this delta on all ACLs and expect that by the time
- * these are run the initial privileges will be in place, even in a binary
- * upgrade situation (see below).
- *
- * Finally, the order in which privileges are in the ACL string (the order
- * they been GRANT'd in, which the backend maintains) must be preserved to
- * ensure that GRANTs WITH GRANT OPTION and subsequent GRANTs based on
- * those are dumped in the correct order.
- */
- printfPQExpBuffer(acl_subquery,
- "(SELECT pg_catalog.array_agg(acl ORDER BY row_n) FROM "
- "(SELECT acl, row_n FROM "
- "pg_catalog.unnest(coalesce(%s,pg_catalog.acldefault(%s,%s))) "
- "WITH ORDINALITY AS perm(acl,row_n) "
- "WHERE NOT EXISTS ( "
- "SELECT 1 FROM "
- "pg_catalog.unnest(coalesce(pip.initprivs,pg_catalog.acldefault(%s,%s))) "
- "AS init(init_acl) WHERE acl = init_acl)) as foo)",
- acl_column,
- obj_kind,
- acl_owner,
- obj_kind,
- acl_owner);
-
- printfPQExpBuffer(racl_subquery,
- "(SELECT pg_catalog.array_agg(acl ORDER BY row_n) FROM "
- "(SELECT acl, row_n FROM "
- "pg_catalog.unnest(coalesce(pip.initprivs,pg_catalog.acldefault(%s,%s))) "
- "WITH ORDINALITY AS initp(acl,row_n) "
- "WHERE NOT EXISTS ( "
- "SELECT 1 FROM "
- "pg_catalog.unnest(coalesce(%s,pg_catalog.acldefault(%s,%s))) "
- "AS permp(orig_acl) WHERE acl = orig_acl)) as foo)",
- obj_kind,
- acl_owner,
- acl_column,
- obj_kind,
- acl_owner);
-
- /*
- * In binary upgrade mode we don't run the extension script but instead
- * dump out the objects independently and then recreate them. To preserve
- * the initial privileges which were set on extension objects, we need to
- * grab the set of GRANT and REVOKE commands necessary to get from the
- * default privileges of an object to the initial privileges as recorded
- * in pg_init_privs.
- *
- * These will then be run ahead of the regular ACL commands, which were
- * calculated using the queries above, inside of a block which sets a flag
- * to indicate that the backend should record the results of these GRANT
- * and REVOKE statements into pg_init_privs. This is how we preserve the
- * contents of that catalog across binary upgrades.
- */
- if (binary_upgrade)
- {
- printfPQExpBuffer(init_acl_subquery,
- "CASE WHEN privtype = 'e' THEN "
- "(SELECT pg_catalog.array_agg(acl ORDER BY row_n) FROM "
- "(SELECT acl, row_n FROM pg_catalog.unnest(pip.initprivs) "
- "WITH ORDINALITY AS initp(acl,row_n) "
- "WHERE NOT EXISTS ( "
- "SELECT 1 FROM "
- "pg_catalog.unnest(pg_catalog.acldefault(%s,%s)) "
- "AS privm(orig_acl) WHERE acl = orig_acl)) as foo) END",
- obj_kind,
- acl_owner);
-
- printfPQExpBuffer(init_racl_subquery,
- "CASE WHEN privtype = 'e' THEN "
- "(SELECT pg_catalog.array_agg(acl) FROM "
- "(SELECT acl, row_n FROM "
- "pg_catalog.unnest(pg_catalog.acldefault(%s,%s)) "
- "WITH ORDINALITY AS privp(acl,row_n) "
- "WHERE NOT EXISTS ( "
- "SELECT 1 FROM pg_catalog.unnest(pip.initprivs) "
- "AS initp(init_acl) WHERE acl = init_acl)) as foo) END",
- obj_kind,
- acl_owner);
- }
- else
- {
- printfPQExpBuffer(init_acl_subquery, "NULL");
- printfPQExpBuffer(init_racl_subquery, "NULL");
- }
-}
/*
* Detect whether the given GUC variable is of GUC_LIST_QUOTE type.
diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h
index 2dc6b38992b..cf6f89c6074 100644
--- a/src/bin/pg_dump/dumputils.h
+++ b/src/bin/pg_dump/dumputils.h
@@ -37,25 +37,22 @@
extern char *sanitize_line(const char *str, bool want_hyphen);
extern bool buildACLCommands(const char *name, const char *subname, const char *nspname,
- const char *type, const char *acls, const char *racls,
+ const char *type, const char *acls, const char *baseacls,
const char *owner, const char *prefix, int remoteVersion,
PQExpBuffer sql);
extern bool buildDefaultACLCommands(const char *type, const char *nspname,
- const char *acls, const char *racls,
- const char *initacls, const char *initracls,
+ const char *acls, const char *acldefault,
const char *owner,
int remoteVersion,
PQExpBuffer sql);
+
+extern void quoteAclUserName(PQExpBuffer output, const char *input);
+
extern void buildShSecLabelQuery(const char *catalog_name,
Oid objectId, PQExpBuffer sql);
extern void emitShSecLabels(PGconn *conn, PGresult *res,
PQExpBuffer buffer, const char *objtype, const char *objname);
-extern void buildACLQueries(PQExpBuffer acl_subquery, PQExpBuffer racl_subquery,
- PQExpBuffer init_acl_subquery, PQExpBuffer init_racl_subquery,
- const char *acl_column, const char *acl_owner,
- const char *obj_kind, bool binary_upgrade);
-
extern bool variable_is_guc_list_quote(const char *name);
extern bool SplitGUCList(char *rawstring, char separator,
diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h
index 5f414e18686..9c6a6cddef9 100644
--- a/src/bin/pg_dump/pg_backup.h
+++ b/src/bin/pg_dump/pg_backup.h
@@ -26,6 +26,14 @@
#include "fe_utils/simple_list.h"
#include "libpq-fe.h"
+#define GPDB5_MAJOR_PGVERSION 80300
+#define GPDB6_MAJOR_PGVERSION 90400
+#define GPDB7_MAJOR_PGVERSION 120000
+/*
+ * GPDB7_MERGE_FIXME: it seems like we don't need those cuz for cbdb we have
+ * fout->version.type and fout->version.version, which provide better checks
+ */
+#define CBDB2_MAJOR_PGVERSION 140000
typedef enum trivalue
{
@@ -58,6 +66,23 @@ typedef enum _teSection
SECTION_POST_DATA /* stuff to be processed after data */
} teSection;
+/* We need one enum entry per prepared query in pg_dump */
+enum _dumpPreparedQueries
+{
+ PREPQUERY_DUMPAGG,
+ PREPQUERY_DUMPBASETYPE,
+ PREPQUERY_DUMPCOMPOSITETYPE,
+ PREPQUERY_DUMPDOMAIN,
+ PREPQUERY_DUMPENUMTYPE,
+ PREPQUERY_DUMPFUNC,
+ PREPQUERY_DUMPOPR,
+ PREPQUERY_DUMPRANGETYPE,
+ PREPQUERY_DUMPTABLEATTACH,
+ PREPQUERY_GETCOLUMNACLS,
+ PREPQUERY_GETDOMAINCONSTRAINTS,
+ NUM_PREP_QUERIES /* must be last */
+};
+
/* Parameters needed by ConnectDatabase; same for dump and restore */
typedef struct _connParams
{
@@ -186,6 +211,9 @@ typedef struct _dumpOptions
int do_nothing;
char *restrict_key;
+ /* GPDB */
+ bool dumpGpPolicy;
+ bool isGPbackend;
} DumpOptions;
@@ -234,6 +262,9 @@ typedef struct Archive
DatabaseVersion version;
+ /* prepared-query status */
+ bool *is_prepared; /* indexed by enum _dumpPreparedQueries */
+
/* The rest is private */
} Archive;
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index 967e35ec7f2..4964b0fd943 100644
--- a/src/bin/pg_dump/pg_backup_db.c
+++ b/src/bin/pg_dump/pg_backup_db.c
@@ -191,10 +191,17 @@ ConnectDatabase(Archive *AHX,
}
keywords[i] = "fallback_application_name";
values[i++] = progname;
+ /* GPDB: If binary upgrade, we need to use the correct
+ * session GUC to connect in utility mode, which depends on
+ * the server version. We don't know the server version until
+ * we connect for the first time, so set the correct GUC and
+ * reconnect.
+ */
if (binary_upgrade)
{
keywords[i] = "options";
- values[i++] = "-c gp_role=utility";
+ values[i++] = AH->public.remoteVersion < GPDB7_MAJOR_PGVERSION ?
+ "-c gp_session_role=utility" : "-c gp_role=utility";
keywords[i] = NULL;
values[i++] = NULL;
}
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index a484f693b43..23757c62573 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -69,6 +69,12 @@
#include "pg_dump.h"
#include "storage/block.h"
+typedef struct
+{
+ Oid roleoid; /* role's OID */
+ const char *rolename; /* role's name */
+} RoleNameItem;
+
typedef struct
{
const char *descr; /* comment for an object */
@@ -96,16 +102,8 @@ typedef enum OidOptions
/* global decls */
static bool dosync = true; /* Issue fsync() to make dump durable on disk. */
-/* GPDB_95_MERGE_FIXME: put those flags to DumpOptions to avoid using global variables */
-/* START MPP ADDITION */
-bool dumpGpPolicy;
-bool isGPbackend;
-
/* END MPP ADDITION */
-/* subquery used to convert user ID (eg, datdba) to user name */
-static const char *username_subquery;
-
/*
* For 8.0 and earlier servers, pulled from pg_database, for 8.1+ we use
* FirstNormalObjectId - 1.
@@ -127,10 +125,13 @@ static SimpleStringList schema_exclude_patterns = {NULL, NULL};
static SimpleOidList schema_exclude_oids = {NULL, NULL};
static SimpleStringList table_include_patterns = {NULL, NULL};
+static SimpleStringList table_include_patterns_and_children = {NULL, NULL};
static SimpleOidList table_include_oids = {NULL, NULL};
static SimpleStringList table_exclude_patterns = {NULL, NULL};
+static SimpleStringList table_exclude_patterns_and_children = {NULL, NULL};
static SimpleOidList table_exclude_oids = {NULL, NULL};
static SimpleStringList tabledata_exclude_patterns = {NULL, NULL};
+static SimpleStringList tabledata_exclude_patterns_and_children = {NULL, NULL};
static SimpleOidList tabledata_exclude_oids = {NULL, NULL};
static SimpleStringList relid_string_list = {NULL, NULL};
@@ -152,15 +153,22 @@ const char *EXT_PARTITION_NAME_POSTFIX = "_external_partition__";
/* pg_class.relstorage value used in GPDB 6.x and below to mark external tables. */
#define RELSTORAGE_EXTERNAL 'x'
-/* flag indicating whether or not this GP database supports partitioning */
-static bool gp_partitioning_available = false;
-
-static DumpId binary_upgrade_dumpid;
-
/* override for standard extra_float_digits setting */
static bool have_extra_float_digits = false;
static int extra_float_digits;
+/* sorted table of role names */
+static RoleNameItem *rolenames = NULL;
+static int nrolenames = 0;
+
+/* sorted table of comments */
+static CommentItem *comments = NULL;
+static int ncomments = 0;
+
+/* sorted table of security labels */
+static SecLabelItem *seclabels = NULL;
+static int nseclabels = 0;
+
/*
* The default number of rows per INSERT when
* --inserts is specified without --rows-per-insert
@@ -200,7 +208,8 @@ static void expand_foreign_server_name_patterns(Archive *fout,
static void expand_table_name_patterns(Archive *fout,
SimpleStringList *patterns,
SimpleOidList *oids,
- bool strict_names);
+ bool strict_names,
+ bool with_child_tables);
static void prohibit_crossdb_refs(PGconn *conn, const char *dbname,
const char *pattern);
@@ -211,16 +220,19 @@ static void guessConstraintInheritance(TableInfo *tblinfo, int numTables);
static void dumpComment(Archive *fout, const char *type, const char *name,
const char *namespace, const char *owner,
CatalogId catalogId, int subid, DumpId dumpId);
+static const char *getRoleName(const char *roleoid_str);
+static void collectRoleNames(Archive *fout);
+static void getAdditionalACLs(Archive *fout);
static int findComments(Archive *fout, Oid classoid, Oid objoid,
CommentItem **items);
-static int collectComments(Archive *fout, CommentItem **items);
+static void collectComments(Archive *fout);
static void dumpSecLabel(Archive *fout, const char *type, const char *name,
const char *namespace, const char *owner,
CatalogId catalogId, int subid, DumpId dumpId);
static int findSecLabels(Archive *fout, Oid classoid, Oid objoid,
SecLabelItem **items);
-static int collectSecLabels(Archive *fout, SecLabelItem **items);
-static void dumpDumpableObject(Archive *fout, const DumpableObject *dobj);
+static void collectSecLabels(Archive *fout);
+static void dumpDumpableObject(Archive *fout, DumpableObject *dobj);
static void dumpNamespace(Archive *fout, const NamespaceInfo *nspinfo);
static void dumpExtension(Archive *fout, const ExtensionInfo *extinfo);
static void dumpType(Archive *fout, const TypeInfo *tyinfo);
@@ -275,8 +287,7 @@ static void dumpDefaultACL(Archive *fout, const DefaultACLInfo *daclinfo);
static DumpId dumpACL(Archive *fout, DumpId objDumpId, DumpId altDumpId,
const char *type, const char *name, const char *subname,
const char *nspname, const char *owner,
- const char *acls, const char *racls,
- const char *initacls, const char *initracls);
+ const DumpableAcl *dacl);
static void getDependencies(Archive *fout);
static void BuildArchiveDependencies(Archive *fout);
@@ -305,7 +316,6 @@ static char *format_function_signature(Archive *fout,
static char *convertRegProcReference(const char *proc);
static char *getFormattedOperatorName(const char *oproid);
static char *convertTSFunction(Archive *fout, Oid funcOid);
-static Oid findLastBuiltinOid_V71(Archive *fout);
static const char *getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts);
static void getBlobs(Archive *fout);
static void dumpBlob(Archive *fout, const BlobInfo *binfo);
@@ -362,6 +372,7 @@ static void appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
const char *prefix, Archive *fout);
static char *get_synchronized_snapshot(Archive *fout);
static void setupDumpWorker(Archive *AHX);
+static void set_restrict_relation_kind(Archive *AH, const char *value);
static TableInfo *getRootTableInfo(const TableInfo *tbinfo);
static bool forcePartitionRootLoad(const TableInfo *tbinfo);
@@ -377,69 +388,15 @@ static void expand_oid_patterns(SimpleStringList *patterns,
SimpleOidList *oids);
static bool is_returns_table_function(int nallargs, char **argmodes);
-static bool testGPbackend(Archive *fout);
-static bool testPartitioningSupport(Archive *fout);
+static void testGPbackend(Archive *fout);
static char *nextToken(register char **stringp, register const char *delim);
static void addDistributedBy(Archive *fout, PQExpBuffer q, const TableInfo *tbinfo, int actual_atts);
static void addDistributedByOld(Archive *fout, PQExpBuffer q, const TableInfo *tbinfo, int actual_atts);
static void addSchedule(Archive *fout, PQExpBuffer q, const TableInfo *tbinfo);
-static bool isGPDB(Archive *fout);
-static bool isGPDB5000OrLater(Archive *fout);
-static bool isGPDB6000OrLater(Archive *fout);
/* END MPP ADDITION */
-/*
- * Check if we are talking to GPDB
- */
-static bool
-isGPDB(Archive *fout)
-{
- static int value = -1; /* -1 = not known yet, 0 = no, 1 = yes */
-
- /* Query the server on first call, and cache the result */
- if (value == -1)
- {
- const char *query = "select pg_catalog.version()";
- PGresult *res;
- char *ver;
-
- res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK);
-
- ver = (PQgetvalue(res, 0, 0));
- if (strstr(ver, "Cloudberry") != NULL)
- value = 1;
- else
- value = 0;
-
- PQclear(res);
- }
- return (value == 1) ? true : false;
-}
-
-
-static bool
-isGPDB5000OrLater(Archive *fout)
-{
- if (!isGPDB(fout))
- return false; /* Not Cloudberry at all. */
-
- /* GPDB 5 is based on PostgreSQL 8.3 */
- return fout->remoteVersion >= 80300;
-}
-
-
-static bool
-isGPDB6000OrLater(Archive *fout)
-{
- if (!isGPDB(fout))
- return false; /* Not Cloudberry at all. */
-
- /* GPDB 6 is based on PostgreSQL 9.4 */
- return fout->remoteVersion >= 90400;
-}
-
int
main(int argc, char **argv)
{
@@ -545,6 +502,9 @@ main(int argc, char **argv)
{"rows-per-insert", required_argument, NULL, 10},
{"include-foreign-data", required_argument, NULL, 11},
{"restrict-key", required_argument, NULL, 25},
+ {"table-and-children", required_argument, NULL, 12},
+ {"exclude-table-and-children", required_argument, NULL, 13},
+ {"exclude-table-data-and-children", required_argument, NULL, 14},
/* START MPP ADDITION */
@@ -805,6 +765,21 @@ main(int argc, char **argv)
simple_string_list_append(&foreign_servers_include_patterns,
optarg);
break;
+ case 12: /* include table(s) and their children */
+ simple_string_list_append(&table_include_patterns_and_children,
+ optarg);
+ dopt.include_everything = false;
+ break;
+
+ case 13: /* exclude table(s) and their children */
+ simple_string_list_append(&table_exclude_patterns_and_children,
+ optarg);
+ break;
+
+ case 14: /* exclude data of table(s) and children */
+ simple_string_list_append(&tabledata_exclude_patterns_and_children,
+ optarg);
+ break;
case 25:
dopt.restrict_key = pg_strdup(optarg);
@@ -952,7 +927,7 @@ main(int argc, char **argv)
* We allow the server to be back to 8.3, and up to any minor release of
* our own major version. (See also version check in pg_dumpall.c.)
*/
- fout->minRemoteVersion = 80300; /* we can handle back to 8.3 */
+ fout->minRemoteVersion = GPDB5_MAJOR_PGVERSION; /* we can handle back to 8.3 */
fout->maxRemoteVersion = (PG_VERSION_NUM / 100) * 100 + 99;
fout->numWorkers = numWorkers;
@@ -967,7 +942,7 @@ main(int argc, char **argv)
/*
* Determine whether or not we're interacting with a GP backend.
*/
- isGPbackend = testGPbackend(fout);
+ testGPbackend(fout);
/*
* Now that the type of backend is known, determine the gp-syntax option
@@ -976,15 +951,15 @@ main(int argc, char **argv)
switch (gp_syntax_option)
{
case GPS_NOT_SPECIFIED:
- dumpGpPolicy = isGPbackend;
+ dopt.dumpGpPolicy = dopt.isGPbackend;
break;
case GPS_DISABLED:
- dumpGpPolicy = false;
+ dopt.dumpGpPolicy = false;
break;
case GPS_ENABLED:
- dumpGpPolicy = isGPbackend;
- if (!isGPbackend)
- pg_log_warning("server is not a Apache Cloudberry instance; --gp-syntax option ignored");
+ dopt.dumpGpPolicy = dopt.isGPbackend;
+ if (!dopt.isGPbackend)
+ pg_log_warning("server is not an Apache Cloudberry instance; --gp-syntax option ignored");
break;
}
@@ -1002,13 +977,6 @@ main(int argc, char **argv)
if (fout->isStandby)
dopt.no_unlogged_table_data = true;
- username_subquery = "SELECT rolname FROM pg_catalog.pg_roles WHERE oid =";
-
- /*
- * Remember whether or not this GP database supports partitioning.
- */
- gp_partitioning_available = testPartitioningSupport(fout);
-
/* check the version for the synchronized snapshots feature */
if (numWorkers > 1 && fout->remoteVersion < 90200
&& !dopt.no_synchronized_snapshots)
@@ -1020,15 +988,7 @@ main(int argc, char **argv)
if (dumpsnapshot && fout->remoteVersion < 90200)
fatal("Exported snapshots are not supported by this server version.");
- /*
- * Find the last built-in OID, if needed (prior to 8.1)
- *
- * With 8.1 and above, we can just use FirstNormalObjectId - 1.
- */
- if (fout->remoteVersion < 80100)
- g_last_builtin_oid = findLastBuiltinOid_V71(fout);
- else
- g_last_builtin_oid = FirstNormalObjectId - 1;
+ g_last_builtin_oid = FirstNormalObjectId - 1;
pg_log_info("last built-in OID is %u", g_last_builtin_oid);
@@ -1041,27 +1001,43 @@ main(int argc, char **argv)
if (schema_include_oids.head == NULL)
fatal("no matching schemas were found");
}
+ /*
+ * As of GPDB7 gp_toolkit is an extension. It gets installed into template1
+ * when the cluster is initialized by gpinitsystem. For 6 > 7 upgrade we
+ * assume it will always be present and excluded it from being dumped.
+ */
+ if (fout->remoteVersion < GPDB7_MAJOR_PGVERSION)
+ simple_string_list_append(&schema_exclude_patterns, "gp_toolkit");
expand_schema_name_patterns(fout, &schema_exclude_patterns,
&schema_exclude_oids,
false);
/* non-matching exclusion patterns aren't an error */
/* Expand table selection patterns into OID lists */
- if (table_include_patterns.head != NULL)
- {
- expand_table_name_patterns(fout, &table_include_patterns,
- &table_include_oids,
- strict_names);
- if (table_include_oids.head == NULL)
- fatal("no matching tables were found");
- }
+ expand_table_name_patterns(fout, &table_include_patterns,
+ &table_include_oids,
+ strict_names, false);
+ expand_table_name_patterns(fout, &table_include_patterns_and_children,
+ &table_include_oids,
+ strict_names, true);
+ if ((table_include_patterns.head != NULL ||
+ table_include_patterns_and_children.head != NULL) &&
+ table_include_oids.head == NULL)
+ fatal("no matching tables were found");
+
expand_table_name_patterns(fout, &table_exclude_patterns,
&table_exclude_oids,
- false);
+ false, false);
+ expand_table_name_patterns(fout, &table_exclude_patterns_and_children,
+ &table_exclude_oids,
+ false, true);
expand_table_name_patterns(fout, &tabledata_exclude_patterns,
&tabledata_exclude_oids,
- false);
+ false, false);
+ expand_table_name_patterns(fout, &tabledata_exclude_patterns_and_children,
+ &tabledata_exclude_oids,
+ false, true);
expand_foreign_server_name_patterns(fout, &foreign_servers_include_patterns,
&foreign_servers_include_oids);
@@ -1094,6 +1070,11 @@ main(int argc, char **argv)
if (dopt.include_everything && !dopt.schemaOnly && !dopt.dontOutputBlobs)
dopt.outputBlobs = true;
+ /*
+ * Collect role names so we can map object owner OIDs to names.
+ */
+ collectRoleNames(fout);
+
/*
* Now scan the database and create DumpableObject structs for all the
* objects we intend to dump.
@@ -1132,6 +1113,16 @@ main(int argc, char **argv)
setExtPartDependency(tblinfo, numTables);
+ /*
+ * Collect ACLs, comments, and security labels, if wanted.
+ */
+ if (!dopt.aclsSkip)
+ getAdditionalACLs(fout);
+ if (!dopt.no_comments)
+ collectComments(fout);
+ if (!dopt.no_security_labels)
+ collectSecLabels(fout);
+
/* Lastly, create dummy objects to represent the section boundaries */
boundaryObjs = createBoundaryObjects();
@@ -1291,7 +1282,7 @@ help(const char *progname)
" plain-text format\n"));
printf(_(" -s, --schema-only dump only the schema, no data\n"));
printf(_(" -S, --superuser=NAME superuser user name to use in plain-text format\n"));
- printf(_(" -t, --table=PATTERN dump the specified table(s) only\n"));
+ printf(_(" -t, --table=PATTERN dump only the specified table(s)\n"));
printf(_(" -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n"));
printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
@@ -1300,7 +1291,13 @@ help(const char *progname)
printf(_(" --disable-triggers disable triggers during data-only restore\n"));
printf(_(" --enable-row-security enable row security (dump only content user has\n"
" access to)\n"));
+ printf(_(" --exclude-table-and-children=PATTERN\n"
+ " do NOT dump the specified table(s),\n"
+ " including child and partition tables\n"));
printf(_(" --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n"));
+ printf(_(" --exclude-table-data-and-children=PATTERN\n"
+ " do NOT dump data for the specified table(s),\n"
+ " including child and partition tables\n"));
printf(_(" --extra-float-digits=NUM override default setting for extra_float_digits\n"));
printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
printf(_(" --include-foreign-data=PATTERN\n"
@@ -1325,6 +1322,8 @@ help(const char *progname)
printf(_(" --snapshot=SNAPSHOT use given snapshot for the dump\n"));
printf(_(" --strict-names require table and/or schema include patterns to\n"
" match at least one entity each\n"));
+ printf(_(" --table-and-children=PATTERN dump only the specified table(s),\n"
+ " including child and partition tables\n"));
printf(_(" --use-set-session-authorization\n"
" use SET SESSION AUTHORIZATION commands instead of\n"
" ALTER OWNER commands to set ownership\n"));
@@ -1430,11 +1429,10 @@ setup_connection(Archive *AH, const char *dumpencoding,
ExecuteSqlStatement(AH, "SET extra_float_digits TO 2");
/*
- * If synchronized scanning is supported, disable it, to prevent
- * unpredictable changes in row ordering across a dump and reload.
+ * Disable synchronized scanning to prevent unpredictable
+ * changes in row ordering across a dump and reload.
*/
- if (AH->remoteVersion >= 80300)
- ExecuteSqlStatement(AH, "SET synchronize_seqscans TO off");
+ ExecuteSqlStatement(AH, "SET synchronize_seqscans TO off");
/*
* The default for enable_nestloop is off in GPDB. However, many of the queries
@@ -1454,7 +1452,7 @@ setup_connection(Archive *AH, const char *dumpencoding,
/*
* Quote all identifiers, if requested.
*/
- if (quote_all_identifiers && AH->remoteVersion >= 80300)
+ if (quote_all_identifiers)
ExecuteSqlStatement(AH, "SET quote_all_identifiers = true");
/*
@@ -1468,6 +1466,19 @@ setup_connection(Archive *AH, const char *dumpencoding,
ExecuteSqlStatement(AH, "SET row_security = off");
}
+ /*
+ * For security reasons, we restrict the expansion of non-system views and
+ * access to foreign tables during the pg_dump process. This restriction
+ * is adjusted when dumping foreign table data.
+ */
+ set_restrict_relation_kind(AH, "view, foreign-table");
+
+ /*
+ * Initialize prepared-query state to "nothing prepared". We do this here
+ * so that a parallel dump worker will have its own state.
+ */
+ AH->is_prepared = (bool *) pg_malloc0(NUM_PREP_QUERIES * sizeof(bool));
+
/*
* Start transaction-snapshot mode transaction to dump consistent data.
*/
@@ -1764,7 +1775,7 @@ expand_foreign_server_name_patterns(Archive *fout,
static void
expand_table_name_patterns(Archive *fout,
SimpleStringList *patterns, SimpleOidList *oids,
- bool strict_names)
+ bool strict_names, bool with_child_tables)
{
PQExpBuffer query;
PGresult *res;
@@ -1790,7 +1801,15 @@ expand_table_name_patterns(Archive *fout,
* Query must remain ABSOLUTELY devoid of unqualified names. This
* would be unnecessary given a pg_table_is_visible() variant taking a
* search_path argument.
+ *
+ * For with_child_tables, we start with the basic query's results and
+ * recursively search the inheritance tree to add child tables.
*/
+ if (with_child_tables)
+ {
+ appendPQExpBuffer(query, "WITH RECURSIVE partition_tree (relid) AS (\n");
+ }
+
appendPQExpBuffer(query,
"SELECT c.oid"
"\nFROM pg_catalog.pg_class c"
@@ -1813,6 +1832,17 @@ expand_table_name_patterns(Archive *fout,
prohibit_crossdb_refs(GetConnection(fout), dbbuf.data, cell->val);
termPQExpBuffer(&dbbuf);
+ if (with_child_tables)
+ {
+ appendPQExpBuffer(query, "UNION"
+ "\nSELECT i.inhrelid"
+ "\nFROM partition_tree p"
+ "\n JOIN pg_catalog.pg_inherits i"
+ "\n ON p.relid OPERATOR(pg_catalog.=) i.inhparent"
+ "\n)"
+ "\nSELECT relid FROM partition_tree");
+ }
+
ExecuteSqlStatement(fout, "RESET search_path");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
PQclear(ExecuteSqlQueryForSingleRow(fout,
@@ -2006,6 +2036,13 @@ selectDumpableNamespace(NamespaceInfo *nsinfo, Archive *fout)
else
nsinfo->dobj.dump = DUMP_COMPONENT_ACL;
nsinfo->dobj.dump_contains = DUMP_COMPONENT_ALL;
+
+ /*
+ * Also, make like it has a comment even if it doesn't; this is so
+ * that we'll emit a command to drop the comment, if appropriate.
+ * (Without this, we'd not call dumpComment for it.)
+ */
+ nsinfo->dobj.components |= DUMP_COMPONENT_COMMENT;
}
else
nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_ALL;
@@ -2123,20 +2160,49 @@ selectDumpableType(TypeInfo *tyinfo, Archive *fout)
* Mark a function as to be dumped or not
*/
static void
-selectDumpableFunction(FuncInfo *finfo)
+selectDumpableFunction(FuncInfo *finfo, Archive *fout)
{
+
+ if (checkExtensionMembership(&finfo->dobj, fout))
+ return; /* extension membership overrides all else */
+
/*
* If specific functions are being dumped, dump just those functions; else, dump
* according to the parent namespace's dump flag if parent namespace is not null;
* else, always dump the function.
*/
- if (function_include_oids.head != NULL)
- finfo->dobj.dump = simple_oid_list_member(&function_include_oids,
- finfo->dobj.catId.oid);
+ if (function_include_oids.head != NULL &&
+ simple_oid_list_member(&function_include_oids, finfo->dobj.catId.oid))
+ finfo->dobj.dump = DUMP_COMPONENT_ALL;
else if (finfo->dobj.namespace)
finfo->dobj.dump = finfo->dobj.namespace->dobj.dump;
else
- finfo->dobj.dump = true;
+ finfo->dobj.dump = DUMP_COMPONENT_ALL;
+}
+
+/*
+ * selectDumpableAggregate: policy-setting subroutine
+ * Mark a function as to be dumped or not
+ */
+static void
+selectDumpableAggregate(AggInfo *agginfo, Archive *fout)
+{
+
+ if (checkExtensionMembership(&agginfo->aggfn.dobj, fout))
+ return; /* extension membership overrides all else */
+
+ /*
+ * If specific aggregates are being dumped, dump just those aggregates; else, dump
+ * according to the parent namespace's dump flag if parent namespace is not null;
+ * else, always dump the function.
+ */
+ if (function_include_oids.head != NULL &&
+ simple_oid_list_member(&function_include_oids, agginfo->aggfn.dobj.catId.oid))
+ agginfo->aggfn.dobj.dump = DUMP_COMPONENT_ALL;
+ else if (agginfo->aggfn.dobj.namespace)
+ agginfo->aggfn.dobj.dump = agginfo->aggfn.dobj.namespace->dobj.dump;
+ else
+ agginfo->aggfn.dobj.dump = DUMP_COMPONENT_ALL;
}
/*
@@ -2362,6 +2428,11 @@ dumpTableData_copy(Archive *fout, const void *dcontext)
*/
if (tdinfo->filtercond || tbinfo->relkind == RELKIND_FOREIGN_TABLE)
{
+ /* Temporary allows to access to foreign tables to dump data */
+ if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
+ set_restrict_relation_kind(fout, "view");
+
+ /* Note: this syntax is only supported in 8.2 and up */
appendPQExpBufferStr(q, "COPY (SELECT ");
/* klugery to get rid of parens in column list */
if (strlen(column_list) > 2)
@@ -2473,6 +2544,11 @@ dumpTableData_copy(Archive *fout, const void *dcontext)
classname);
destroyPQExpBuffer(q);
+
+ /* Revert back the setting */
+ if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
+ set_restrict_relation_kind(fout, "view, foreign-table");
+
return 1;
}
@@ -2499,6 +2575,10 @@ dumpTableData_insert(Archive *fout, const void *dcontext)
int rows_per_statement = dopt->dump_inserts;
int rows_this_statement = 0;
+ /* Temporary allows to access to foreign tables to dump data */
+ if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
+ set_restrict_relation_kind(fout, "view");
+
/*
* If we're going to emit INSERTs with column names, the most efficient
* way to deal with generated columns is to exclude them entirely. For
@@ -2738,6 +2818,10 @@ dumpTableData_insert(Archive *fout, const void *dcontext)
destroyPQExpBuffer(insertStmt);
free(attgenerated);
+ /* Revert back the setting */
+ if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
+ set_restrict_relation_kind(fout, "view, foreign-table");
+
return 1;
}
@@ -2960,7 +3044,7 @@ getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, char relkind)
* Make a dumpable object for the data of this specific table
*
* Note: we make a TableDataInfo if and only if we are going to dump the
- * table data; the "dump" flag in such objects isn't used.
+ * table data; the "dump" field in such objects isn't very interesting.
*/
static void
makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo)
@@ -3023,6 +3107,9 @@ makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo)
tdinfo->filtercond = NULL; /* might get set later */
addObjectDependency(&tdinfo->dobj, tbinfo->dobj.dumpId);
+ /* A TableDataInfo contains data, of course */
+ tdinfo->dobj.components |= DUMP_COMPONENT_DATA;
+
tbinfo->dataObj = tdinfo;
/* Make sure that we'll collect per-column info for this table. */
@@ -3328,26 +3415,25 @@ dumpDatabase(Archive *fout)
int i_tableoid,
i_oid,
i_datname,
- i_dba,
+ i_datdba,
i_encoding,
i_collate,
i_ctype,
i_frozenxid,
i_minmxid,
i_datacl,
- i_rdatacl,
+ i_acldefault,
i_datistemplate,
i_datconnlimit,
i_tablespace;
CatalogId dbCatId;
DumpId dbDumpId;
+ DumpableAcl dbdacl;
const char *datname,
*dba,
*encoding,
*collate,
*ctype,
- *datacl,
- *rdatacl,
*datistemplate,
*datconnlimit,
*tablespace;
@@ -3359,89 +3445,62 @@ dumpDatabase(Archive *fout)
/*
* Fetch the database-level properties for this database.
- *
- * The order in which privileges are in the ACL string (the order they
- * have been GRANT'd in, which the backend maintains) must be preserved to
- * ensure that GRANTs WITH GRANT OPTION and subsequent GRANTs based on
- * those are dumped in the correct order. Note that initial privileges
- * (pg_init_privs) are not supported on databases, so this logic cannot
- * make use of buildACLQueries().
*/
- if (fout->remoteVersion >= 90600)
+ if (fout->remoteVersion >= 90300)
{
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
- "(%s datdba) AS dba, "
+ "datdba, "
"pg_encoding_to_char(encoding) AS encoding, "
"datcollate, datctype, datfrozenxid, datminmxid, "
- "(SELECT array_agg(acl ORDER BY row_n) FROM "
- " (SELECT acl, row_n FROM "
- " unnest(coalesce(datacl,acldefault('d',datdba))) "
- " WITH ORDINALITY AS perm(acl,row_n) "
- " WHERE NOT EXISTS ( "
- " SELECT 1 "
- " FROM unnest(acldefault('d',datdba)) "
- " AS init(init_acl) "
- " WHERE acl = init_acl)) AS datacls) "
- " AS datacl, "
- "(SELECT array_agg(acl ORDER BY row_n) FROM "
- " (SELECT acl, row_n FROM "
- " unnest(acldefault('d',datdba)) "
- " WITH ORDINALITY AS initp(acl,row_n) "
- " WHERE NOT EXISTS ( "
- " SELECT 1 "
- " FROM unnest(coalesce(datacl,acldefault('d',datdba))) "
- " AS permp(orig_acl) "
- " WHERE acl = orig_acl)) AS rdatacls) "
- " AS rdatacl, "
+ "datacl, acldefault('d', datdba) AS acldefault, "
"datistemplate, datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
"shobj_description(oid, 'pg_database') AS description "
"FROM pg_database "
- "WHERE datname = current_database()",
- username_subquery);
+ "WHERE datname = current_database()");
}
- else if (fout->remoteVersion >= 90300)
+ else if (fout->remoteVersion >= 90200)
{
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
- "(%s datdba) AS dba, "
+ "datdba, "
"pg_encoding_to_char(encoding) AS encoding, "
- "datcollate, datctype, datfrozenxid, datminmxid, "
- "datacl, '' as rdatacl, datistemplate, datconnlimit, "
+ "datcollate, datctype, datfrozenxid, 0 AS datminmxid, "
+ "datacl, acldefault('d', datdba) AS acldefault, "
+ "datistemplate, datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
"shobj_description(oid, 'pg_database') AS description "
"FROM pg_database "
- "WHERE datname = current_database()",
- username_subquery);
+ "WHERE datname = current_database()");
}
else if (fout->remoteVersion >= 80400)
{
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
- "(%s datdba) AS dba, "
+ "datdba, "
"pg_encoding_to_char(encoding) AS encoding, "
"datcollate, datctype, datfrozenxid, 0 AS datminmxid, "
- "datacl, '' as rdatacl, datistemplate, datconnlimit, "
+ "datacl, NULL AS acldefault, "
+ "datistemplate, datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
"shobj_description(oid, 'pg_database') AS description "
"FROM pg_database "
- "WHERE datname = current_database()",
- username_subquery);
+ "WHERE datname = current_database()");
}
else
{
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
- "(%s datdba) AS dba, "
+ "datdba, "
"pg_encoding_to_char(encoding) AS encoding, "
"NULL AS datcollate, NULL AS datctype, datfrozenxid, 0 AS datminmxid, "
- "datacl, '' as rdatacl, datistemplate, datconnlimit, "
+ "datacl, NULL AS acldefault, "
+ "datistemplate, datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
"shobj_description(oid, 'pg_database') AS description "
"FROM pg_database "
- "WHERE datname = current_database()",
- username_subquery);
+ "WHERE datname = current_database()");
}
res = ExecuteSqlQueryForSingleRow(fout, dbQry->data);
@@ -3449,14 +3508,14 @@ dumpDatabase(Archive *fout)
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
i_datname = PQfnumber(res, "datname");
- i_dba = PQfnumber(res, "dba");
+ i_datdba = PQfnumber(res, "datdba");
i_encoding = PQfnumber(res, "encoding");
i_collate = PQfnumber(res, "datcollate");
i_ctype = PQfnumber(res, "datctype");
i_frozenxid = PQfnumber(res, "datfrozenxid");
i_minmxid = PQfnumber(res, "datminmxid");
i_datacl = PQfnumber(res, "datacl");
- i_rdatacl = PQfnumber(res, "rdatacl");
+ i_acldefault = PQfnumber(res, "acldefault");
i_datistemplate = PQfnumber(res, "datistemplate");
i_datconnlimit = PQfnumber(res, "datconnlimit");
i_tablespace = PQfnumber(res, "tablespace");
@@ -3464,14 +3523,14 @@ dumpDatabase(Archive *fout)
dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid));
dbCatId.oid = atooid(PQgetvalue(res, 0, i_oid));
datname = PQgetvalue(res, 0, i_datname);
- dba = PQgetvalue(res, 0, i_dba);
+ dba = getRoleName(PQgetvalue(res, 0, i_datdba));
encoding = PQgetvalue(res, 0, i_encoding);
collate = PQgetvalue(res, 0, i_collate);
ctype = PQgetvalue(res, 0, i_ctype);
frozenxid = atooid(PQgetvalue(res, 0, i_frozenxid));
minmxid = atooid(PQgetvalue(res, 0, i_minmxid));
- datacl = PQgetvalue(res, 0, i_datacl);
- rdatacl = PQgetvalue(res, 0, i_rdatacl);
+ dbdacl.acl = PQgetvalue(res, 0, i_datacl);
+ dbdacl.acldefault = PQgetvalue(res, 0, i_acldefault);
datistemplate = PQgetvalue(res, 0, i_datistemplate);
datconnlimit = PQgetvalue(res, 0, i_datconnlimit);
tablespace = PQgetvalue(res, 0, i_tablespace);
@@ -3595,9 +3654,12 @@ dumpDatabase(Archive *fout)
* Dump ACL if any. Note that we do not support initial privileges
* (pg_init_privs) on databases.
*/
+ dbdacl.privtype = 0;
+ dbdacl.initprivs = NULL;
+
dumpACL(fout, dbDumpId, InvalidDumpId, "DATABASE",
qdatname, NULL, NULL,
- dba, datacl, rdatacl, "", "");
+ dba, &dbdacl);
/*
* Now construct a DATABASE PROPERTIES archive entry to restore any
@@ -3797,9 +3859,9 @@ dumpDatabaseConfig(Archive *AH, PQExpBuffer outbuf,
}
/*
- * If we're upgrading from GPDB 5 or below, use the legacy hash ops.
+ * If we're upgrading from GPDB 5, use the legacy hash ops.
*/
- if (AH->dopt->binary_upgrade && AH->remoteVersion < 90400)
+ if (AH->dopt->binary_upgrade && AH->remoteVersion < GPDB6_MAJOR_PGVERSION)
{
makeAlterConfigCommand(conn, "gp_use_legacy_hashops=on",
"DATABASE", dbname, NULL, NULL, outbuf);
@@ -3936,69 +3998,36 @@ getBlobs(Archive *fout)
int i_oid;
int i_lomowner;
int i_lomacl;
- int i_rlomacl;
- int i_initlomacl;
- int i_initrlomacl;
+ int i_acldefault;
pg_log_info("reading large objects");
/* Fetch BLOB OIDs, and owner/ACL data if >= 9.0 */
- if (fout->remoteVersion >= 90600)
+ if (fout->remoteVersion >= 90200)
{
- PQExpBuffer acl_subquery = createPQExpBuffer();
- PQExpBuffer racl_subquery = createPQExpBuffer();
- PQExpBuffer init_acl_subquery = createPQExpBuffer();
- PQExpBuffer init_racl_subquery = createPQExpBuffer();
-
- buildACLQueries(acl_subquery, racl_subquery, init_acl_subquery,
- init_racl_subquery, "l.lomacl", "l.lomowner", "'L'",
- dopt->binary_upgrade);
-
appendPQExpBuffer(blobQry,
- "SELECT l.oid, (%s l.lomowner) AS rolname, "
- "%s AS lomacl, "
- "%s AS rlomacl, "
- "%s AS initlomacl, "
- "%s AS initrlomacl "
- "FROM pg_largeobject_metadata l "
- "LEFT JOIN pg_init_privs pip ON "
- "(l.oid = pip.objoid "
- "AND pip.classoid = 'pg_largeobject'::regclass "
- "AND pip.objsubid = 0) ",
- username_subquery,
- acl_subquery->data,
- racl_subquery->data,
- init_acl_subquery->data,
- init_racl_subquery->data);
-
- destroyPQExpBuffer(acl_subquery);
- destroyPQExpBuffer(racl_subquery);
- destroyPQExpBuffer(init_acl_subquery);
- destroyPQExpBuffer(init_racl_subquery);
+ "SELECT oid, lomowner, lomacl, "
+ "acldefault('L', lomowner) AS acldefault "
+ "FROM pg_largeobject_metadata");
}
else if (fout->remoteVersion >= 90000)
appendPQExpBuffer(blobQry,
- "SELECT oid, (%s lomowner) AS rolname, lomacl, "
- "NULL AS rlomacl, NULL AS initlomacl, "
- "NULL AS initrlomacl "
- " FROM pg_largeobject_metadata",
- username_subquery);
+ "SELECT oid, lomowner, lomacl, "
+ "NULL AS acldefault "
+ "FROM pg_largeobject_metadata");
else
appendPQExpBufferStr(blobQry,
"SELECT DISTINCT loid AS oid, "
"NULL::name AS rolname, NULL::oid AS lomacl, "
- "NULL::oid AS rlomacl, NULL::oid AS initlomacl, "
- "NULL::oid AS initrlomacl "
+ "NULL::oid AS acldefault "
" FROM pg_largeobject");
res = ExecuteSqlQuery(fout, blobQry->data, PGRES_TUPLES_OK);
i_oid = PQfnumber(res, "oid");
- i_lomowner = PQfnumber(res, "rolname");
+ i_lomowner = PQfnumber(res, "lomowner");
i_lomacl = PQfnumber(res, "lomacl");
- i_rlomacl = PQfnumber(res, "rlomacl");
- i_initlomacl = PQfnumber(res, "initlomacl");
- i_initrlomacl = PQfnumber(res, "initrlomacl");
+ i_acldefault = PQfnumber(res, "acldefault");
ntups = PQntuples(res);
@@ -4015,17 +4044,18 @@ getBlobs(Archive *fout)
AssignDumpId(&binfo[i].dobj);
binfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_oid));
- binfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_lomowner));
- binfo[i].blobacl = pg_strdup(PQgetvalue(res, i, i_lomacl));
- binfo[i].rblobacl = pg_strdup(PQgetvalue(res, i, i_rlomacl));
- binfo[i].initblobacl = pg_strdup(PQgetvalue(res, i, i_initlomacl));
- binfo[i].initrblobacl = pg_strdup(PQgetvalue(res, i, i_initrlomacl));
-
- if (PQgetisnull(res, i, i_lomacl) &&
- PQgetisnull(res, i, i_rlomacl) &&
- PQgetisnull(res, i, i_initlomacl) &&
- PQgetisnull(res, i, i_initrlomacl))
- binfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ binfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_lomacl));
+ binfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
+ binfo[i].dacl.privtype = 0;
+ binfo[i].dacl.initprivs = NULL;
+ binfo[i].rolname = getRoleName(PQgetvalue(res, i, i_lomowner));
+
+ /* Blobs have data */
+ binfo[i].dobj.components |= DUMP_COMPONENT_DATA;
+
+ /* Mark whether blob has an ACL */
+ if (!PQgetisnull(res, i, i_lomacl))
+ binfo[i].dobj.components |= DUMP_COMPONENT_ACL;
/*
* In binary-upgrade mode for blobs, we do *not* dump out the blob
@@ -4049,6 +4079,7 @@ getBlobs(Archive *fout)
bdata->catId = nilCatalogId;
AssignDumpId(bdata);
bdata->name = pg_strdup("BLOBS");
+ bdata->components |= DUMP_COMPONENT_DATA;
}
PQclear(res);
@@ -4096,11 +4127,10 @@ dumpBlob(Archive *fout, const BlobInfo *binfo)
binfo->dobj.catId, 0, binfo->dobj.dumpId);
/* Dump ACL if any */
- if (binfo->blobacl && (binfo->dobj.dump & DUMP_COMPONENT_ACL))
+ if (binfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, binfo->dobj.dumpId, InvalidDumpId, "LARGE OBJECT",
binfo->dobj.name, NULL,
- NULL, binfo->rolname, binfo->blobacl, binfo->rblobacl,
- binfo->initblobacl, binfo->initrblobacl);
+ NULL, binfo->rolname, &binfo->dacl);
destroyPQExpBuffer(cquery);
destroyPQExpBuffer(dquery);
@@ -4241,6 +4271,8 @@ getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
/* Is RLS enabled? (That's separate from whether it has policies) */
if (tbinfo->rowsec)
{
+ tbinfo->dobj.components |= DUMP_COMPONENT_POLICY;
+
/*
* We represent RLS being enabled on a table by creating a
* PolicyInfo object with null polname.
@@ -4364,6 +4396,7 @@ dumpPolicy(Archive *fout, const PolicyInfo *polinfo)
const char *cmd;
char *tag;
+ /* Do nothing in data-only dump */
if (dopt->dataOnly)
return;
@@ -4384,7 +4417,7 @@ dumpPolicy(Archive *fout, const PolicyInfo *polinfo)
* explicitly, because it will not match anything in pg_depend (unlike
* the case for other PolicyInfo objects).
*/
- if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
+ if (polinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
ARCHIVE_OPTS(.tag = polinfo->dobj.name,
.namespace = polinfo->dobj.namespace->dobj.name,
@@ -4446,7 +4479,7 @@ dumpPolicy(Archive *fout, const PolicyInfo *polinfo)
tag = psprintf("%s %s", tbinfo->dobj.name, polinfo->dobj.name);
- if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
+ if (polinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
ARCHIVE_OPTS(.tag = tag,
.namespace = polinfo->dobj.namespace->dobj.name,
@@ -4482,7 +4515,7 @@ getPublications(Archive *fout, int *numPublications)
int i_tableoid;
int i_oid;
int i_pubname;
- int i_rolname;
+ int i_pubowner;
int i_puballtables;
int i_pubinsert;
int i_pubupdate;
@@ -4506,24 +4539,15 @@ getPublications(Archive *fout, int *numPublications)
if (fout->remoteVersion >= 130000)
appendPQExpBuffer(query,
"SELECT p.tableoid, p.oid, p.pubname, "
- "(%s p.pubowner) AS rolname, "
- "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, p.pubviaroot "
- "FROM pg_publication p",
- username_subquery);
- else if (fout->remoteVersion >= 110000)
- appendPQExpBuffer(query,
- "SELECT p.tableoid, p.oid, p.pubname, "
- "(%s p.pubowner) AS rolname, "
+ "p.pubowner, "
"p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false AS pubviaroot "
- "FROM pg_publication p",
- username_subquery);
+ "FROM pg_publication p");
else
appendPQExpBuffer(query,
"SELECT p.tableoid, p.oid, p.pubname, "
- "(%s p.pubowner) AS rolname, "
+ "p.pubowner, "
"p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate, false AS pubviaroot "
- "FROM pg_publication p",
- username_subquery);
+ "FROM pg_publication p");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -4532,7 +4556,7 @@ getPublications(Archive *fout, int *numPublications)
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
i_pubname = PQfnumber(res, "pubname");
- i_rolname = PQfnumber(res, "rolname");
+ i_pubowner = PQfnumber(res, "pubowner");
i_puballtables = PQfnumber(res, "puballtables");
i_pubinsert = PQfnumber(res, "pubinsert");
i_pubupdate = PQfnumber(res, "pubupdate");
@@ -4550,7 +4574,7 @@ getPublications(Archive *fout, int *numPublications)
pubinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&pubinfo[i].dobj);
pubinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_pubname));
- pubinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ pubinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_pubowner));
pubinfo[i].puballtables =
(strcmp(PQgetvalue(res, i, i_puballtables), "t") == 0);
pubinfo[i].pubinsert =
@@ -4564,10 +4588,6 @@ getPublications(Archive *fout, int *numPublications)
pubinfo[i].pubviaroot =
(strcmp(PQgetvalue(res, i, i_pubviaroot), "t") == 0);
- if (strlen(pubinfo[i].rolname) == 0)
- pg_log_warning("owner of publication \"%s\" appears to be invalid",
- pubinfo[i].dobj.name);
-
/* Decide whether we want to dump it */
selectDumpableObject(&(pubinfo[i].dobj), fout);
}
@@ -4591,9 +4611,6 @@ dumpPublication(Archive *fout, const PublicationInfo *pubinfo)
char *qpubname;
bool first = true;
- if (!(pubinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
- return;
-
delq = createPQExpBuffer();
query = createPQExpBuffer();
@@ -4649,13 +4666,14 @@ dumpPublication(Archive *fout, const PublicationInfo *pubinfo)
appendPQExpBufferStr(query, ");\n");
- ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId,
- ARCHIVE_OPTS(.tag = pubinfo->dobj.name,
- .owner = pubinfo->rolname,
- .description = "PUBLICATION",
- .section = SECTION_POST_DATA,
- .createStmt = query->data,
- .dropStmt = delq->data));
+ if (pubinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
+ ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId,
+ ARCHIVE_OPTS(.tag = pubinfo->dobj.name,
+ .owner = pubinfo->rolname,
+ .description = "PUBLICATION",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data,
+ .dropStmt = delq->data));
if (pubinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
dumpComment(fout, "PUBLICATION", qpubname,
@@ -4771,9 +4789,6 @@ dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo)
PQExpBuffer query;
char *tag;
- if (!(pubrinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
- return;
-
tag = psprintf("%s %s", pubinfo->dobj.name, tbinfo->dobj.name);
query = createPQExpBuffer();
@@ -4790,13 +4805,14 @@ dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo)
* owner field anyway to ensure that the command is run by the correct
* role at restore time.
*/
- ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
- ARCHIVE_OPTS(.tag = tag,
- .namespace = tbinfo->dobj.namespace->dobj.name,
- .owner = pubinfo->rolname,
- .description = "PUBLICATION TABLE",
- .section = SECTION_POST_DATA,
- .createStmt = query->data));
+ if (pubrinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
+ ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
+ ARCHIVE_OPTS(.tag = tag,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = pubinfo->rolname,
+ .description = "PUBLICATION TABLE",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data));
free(tag);
destroyPQExpBuffer(query);
@@ -4819,6 +4835,28 @@ is_superuser(Archive *fout)
return false;
}
+/*
+ * Set the given value to restrict_nonsystem_relation_kind value. Since
+ * restrict_nonsystem_relation_kind is introduced in minor version releases,
+ * the setting query is effective only where available.
+ */
+static void
+set_restrict_relation_kind(Archive *AH, const char *value)
+{
+ PQExpBuffer query = createPQExpBuffer();
+ PGresult *res;
+
+ appendPQExpBuffer(query,
+ "SELECT set_config(name, '%s', false) "
+ "FROM pg_settings "
+ "WHERE name = 'restrict_nonsystem_relation_kind'",
+ value);
+ res = ExecuteSqlQuery(AH, query->data, PGRES_TUPLES_OK);
+
+ PQclear(res);
+ destroyPQExpBuffer(query);
+}
+
/*
* getSubscriptions
* get information about subscriptions
@@ -4833,7 +4871,7 @@ getSubscriptions(Archive *fout)
int i_tableoid;
int i_oid;
int i_subname;
- int i_rolname;
+ int i_subowner;
int i_substream;
int i_subconninfo;
int i_subslotname;
@@ -4866,26 +4904,21 @@ getSubscriptions(Archive *fout)
/* Get the subscriptions in current database. */
appendPQExpBuffer(query,
- "SELECT s.tableoid, s.oid, s.subname,\n"
- " (%s s.subowner) AS rolname,\n"
- " s.subconninfo, s.subslotname, s.subsynccommit,\n"
- " s.subpublications,\n",
- username_subquery);
-
- if (fout->remoteVersion >= 140000)
- appendPQExpBufferStr(query, " s.subbinary,\n");
- else
- appendPQExpBufferStr(query, " false AS subbinary,\n");
-
+ "SELECT s.tableoid, s.oid, s.subname, "
+ "s.subowner, "
+ "s.subconninfo, s.subslotname, s.subsynccommit, "
+ "s.subpublications, ");
+
if (fout->remoteVersion >= 140000)
- appendPQExpBufferStr(query, " s.substream\n");
+ appendPQExpBufferStr(query, " s.subbinary, s.substream\n");
else
- appendPQExpBufferStr(query, " false AS substream\n");
-
- appendPQExpBufferStr(query,
- "FROM pg_subscription s\n"
- "WHERE s.subdbid = (SELECT oid FROM pg_database\n"
- " WHERE datname = current_database())");
+ appendPQExpBufferStr(query, " false AS subbinary, false AS substream\n");
+
+
+ appendPQExpBuffer(query,
+ "FROM pg_subscription s "
+ "WHERE s.subdbid = (SELECT oid FROM pg_database"
+ " WHERE datname = current_database())");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -4894,7 +4927,7 @@ getSubscriptions(Archive *fout)
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
i_subname = PQfnumber(res, "subname");
- i_rolname = PQfnumber(res, "rolname");
+ i_subowner = PQfnumber(res, "subowner");
i_subconninfo = PQfnumber(res, "subconninfo");
i_subslotname = PQfnumber(res, "subslotname");
i_subsynccommit = PQfnumber(res, "subsynccommit");
@@ -4912,7 +4945,7 @@ getSubscriptions(Archive *fout)
subinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&subinfo[i].dobj);
subinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_subname));
- subinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ subinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_subowner));
subinfo[i].subconninfo = pg_strdup(PQgetvalue(res, i, i_subconninfo));
if (PQgetisnull(res, i, i_subslotname))
subinfo[i].subslotname = NULL;
@@ -4927,10 +4960,6 @@ getSubscriptions(Archive *fout)
subinfo[i].substream =
pg_strdup(PQgetvalue(res, i, i_substream));
- if (strlen(subinfo[i].rolname) == 0)
- pg_log_warning("owner of subscription \"%s\" appears to be invalid",
- subinfo[i].dobj.name);
-
/* Decide whether we want to dump it */
selectDumpableObject(&(subinfo[i].dobj), fout);
}
@@ -4954,9 +4983,6 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo)
int npubnames = 0;
int i;
- if (!(subinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
- return;
-
delq = createPQExpBuffer();
query = createPQExpBuffer();
@@ -4999,13 +5025,14 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo)
appendPQExpBufferStr(query, ");\n");
- ArchiveEntry(fout, subinfo->dobj.catId, subinfo->dobj.dumpId,
- ARCHIVE_OPTS(.tag = subinfo->dobj.name,
- .owner = subinfo->rolname,
- .description = "SUBSCRIPTION",
- .section = SECTION_POST_DATA,
- .createStmt = query->data,
- .dropStmt = delq->data));
+ if (subinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
+ ArchiveEntry(fout, subinfo->dobj.catId, subinfo->dobj.dumpId,
+ ARCHIVE_OPTS(.tag = subinfo->dobj.name,
+ .owner = subinfo->rolname,
+ .description = "SUBSCRIPTION",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data,
+ .dropStmt = delq->data));
if (subinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
dumpComment(fout, "SUBSCRIPTION", qsubname,
@@ -5720,7 +5747,6 @@ binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
NamespaceInfo *
getNamespaces(Archive *fout, int *numNamespaces)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
@@ -5729,11 +5755,9 @@ getNamespaces(Archive *fout, int *numNamespaces)
int i_tableoid;
int i_oid;
int i_nspname;
- int i_rolname;
+ int i_nspowner;
int i_nspacl;
- int i_rnspacl;
- int i_initnspacl;
- int i_initrnspacl;
+ int i_acldefault;
query = createPQExpBuffer();
@@ -5741,48 +5765,17 @@ getNamespaces(Archive *fout, int *numNamespaces)
* we fetch all namespaces including system ones, so that every object we
* read in can be linked to a containing namespace.
*/
- if (fout->remoteVersion >= 90600)
- {
- PQExpBuffer acl_subquery = createPQExpBuffer();
- PQExpBuffer racl_subquery = createPQExpBuffer();
- PQExpBuffer init_acl_subquery = createPQExpBuffer();
- PQExpBuffer init_racl_subquery = createPQExpBuffer();
-
- buildACLQueries(acl_subquery, racl_subquery, init_acl_subquery,
- init_racl_subquery, "n.nspacl", "n.nspowner", "'n'",
- dopt->binary_upgrade);
-
+ if (fout->remoteVersion >= 90200)
appendPQExpBuffer(query, "SELECT n.tableoid, n.oid, n.nspname, "
- "(%s nspowner) AS rolname, "
- "%s as nspacl, "
- "%s as rnspacl, "
- "%s as initnspacl, "
- "%s as initrnspacl "
- "FROM pg_namespace n "
- "LEFT JOIN pg_init_privs pip "
- "ON (n.oid = pip.objoid "
- "AND pip.classoid = 'pg_namespace'::regclass "
- "AND pip.objsubid = 0",
- username_subquery,
- acl_subquery->data,
- racl_subquery->data,
- init_acl_subquery->data,
- init_racl_subquery->data);
-
- appendPQExpBufferStr(query, ") ");
-
- destroyPQExpBuffer(acl_subquery);
- destroyPQExpBuffer(racl_subquery);
- destroyPQExpBuffer(init_acl_subquery);
- destroyPQExpBuffer(init_racl_subquery);
- }
+ "n.nspowner, "
+ "n.nspacl, "
+ "acldefault('n', n.nspowner) AS acldefault "
+ "FROM pg_namespace n");
else
- appendPQExpBuffer(query, "SELECT tableoid, oid, nspname, "
- "(%s nspowner) AS rolname, "
- "nspacl, NULL as rnspacl, "
- "NULL AS initnspacl, NULL as initrnspacl "
- "FROM pg_namespace",
- username_subquery);
+ appendPQExpBuffer(query, "SELECT n.tableoid, n.oid, n.nspname, "
+ "n.nspowner, "
+ "n.nspacl, NULL AS acldefault "
+ "FROM pg_namespace n");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -5793,44 +5786,33 @@ getNamespaces(Archive *fout, int *numNamespaces)
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
i_nspname = PQfnumber(res, "nspname");
- i_rolname = PQfnumber(res, "rolname");
+ i_nspowner = PQfnumber(res, "nspowner");
i_nspacl = PQfnumber(res, "nspacl");
- i_rnspacl = PQfnumber(res, "rnspacl");
- i_initnspacl = PQfnumber(res, "initnspacl");
- i_initrnspacl = PQfnumber(res, "initrnspacl");
+ i_acldefault = PQfnumber(res, "acldefault");
for (i = 0; i < ntups; i++)
{
+ const char *nspowner;
+
nsinfo[i].dobj.objType = DO_NAMESPACE;
nsinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
nsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&nsinfo[i].dobj);
nsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_nspname));
- nsinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
- nsinfo[i].nspacl = pg_strdup(PQgetvalue(res, i, i_nspacl));
- nsinfo[i].rnspacl = pg_strdup(PQgetvalue(res, i, i_rnspacl));
- nsinfo[i].initnspacl = pg_strdup(PQgetvalue(res, i, i_initnspacl));
- nsinfo[i].initrnspacl = pg_strdup(PQgetvalue(res, i, i_initrnspacl));
+ nsinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_nspacl));
+ nsinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
+ nsinfo[i].dacl.privtype = 0;
+ nsinfo[i].dacl.initprivs = NULL;
+ nspowner = PQgetvalue(res, i, i_nspowner);
+ nsinfo[i].nspowner = atooid(nspowner);
+ nsinfo[i].rolname = getRoleName(nspowner);
/* Decide whether to dump this namespace */
selectDumpableNamespace(&nsinfo[i], fout);
- /*
- * Do not try to dump ACL if the ACL is empty or the default.
- *
- * This is useful because, for some schemas/objects, the only
- * component we are going to try and dump is the ACL and if we can
- * remove that then 'dump' goes to zero/false and we don't consider
- * this object for dumping at all later on.
- */
- if (PQgetisnull(res, i, i_nspacl) && PQgetisnull(res, i, i_rnspacl) &&
- PQgetisnull(res, i, i_initnspacl) &&
- PQgetisnull(res, i, i_initrnspacl))
- nsinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
-
- if (strlen(nsinfo[i].rolname) == 0)
- pg_log_warning("owner of schema \"%s\" appears to be invalid",
- nsinfo[i].dobj.name);
+ /* Mark whether namespace has an ACL */
+ if (!PQgetisnull(res, i, i_nspacl))
+ nsinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -5881,15 +5863,6 @@ getExtensions(Archive *fout, int *numExtensions)
int i_extconfig;
int i_extcondition;
- /*
- * Before 8.3 (porting from PG 9.1), there are no extensions.
- */
- if (fout->remoteVersion < 80300)
- {
- *numExtensions = 0;
- return NULL;
- }
-
query = createPQExpBuffer();
appendPQExpBufferStr(query, "SELECT x.tableoid, x.oid, "
@@ -5948,8 +5921,6 @@ getBinaryUpgradeObjects(void)
AssignDumpId(&binfo->dobj);
binfo->dobj.name = pg_strdup("__binary_upgrade");
- binary_upgrade_dumpid = binfo->dobj.dumpId;
-
return binfo;
}
@@ -5966,7 +5937,6 @@ getBinaryUpgradeObjects(void)
TypeInfo *
getTypes(Archive *fout, int *numTypes)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
@@ -5978,10 +5948,8 @@ getTypes(Archive *fout, int *numTypes)
int i_typname;
int i_typnamespace;
int i_typacl;
- int i_rtypacl;
- int i_inittypacl;
- int i_initrtypacl;
- int i_rolname;
+ int i_acldefault;
+ int i_typowner;
int i_typelem;
int i_typrelid;
int i_typrelkind;
@@ -6004,26 +5972,14 @@ getTypes(Archive *fout, int *numTypes)
* still check for name beginning with '_', though, so as to avoid the
* cost of the subselect probe for all standard types. This would have to
* be revisited if the backend ever allows renaming of array types.
+ *
*/
-
- if (fout->remoteVersion >= 90600)
+ if (fout->remoteVersion >= 90200)
{
- PQExpBuffer acl_subquery = createPQExpBuffer();
- PQExpBuffer racl_subquery = createPQExpBuffer();
- PQExpBuffer initacl_subquery = createPQExpBuffer();
- PQExpBuffer initracl_subquery = createPQExpBuffer();
-
- buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
- initracl_subquery, "t.typacl", "t.typowner", "'T'",
- dopt->binary_upgrade);
-
appendPQExpBuffer(query, "SELECT t.tableoid, t.oid, t.typname, "
- "t.typnamespace, "
- "%s AS typacl, "
- "%s AS rtypacl, "
- "%s AS inittypacl, "
- "%s AS initrtypacl, "
- "(%s t.typowner) AS rolname, "
+ "t.typnamespace, t.typacl, "
+ "acldefault('T', t.typowner) AS acldefault, "
+ "typowner, "
"t.typelem, t.typrelid, "
"CASE WHEN t.typrelid = 0 THEN ' '::\"char\" "
"ELSE (SELECT relkind FROM pg_class WHERE oid = t.typrelid) END AS typrelkind, "
@@ -6032,51 +5988,23 @@ getTypes(Archive *fout, int *numTypes)
"(SELECT typarray FROM pg_type te WHERE oid = t.typelem) = t.oid AS isarray, "
"coalesce(array_to_string(e.typoptions, ', '), '') AS typstorage "
"FROM pg_type t "
- "LEFT JOIN pg_type_encoding e ON t.oid = e.typid "
- "LEFT JOIN pg_init_privs pip ON "
- "(t.oid = pip.objoid "
- "AND pip.classoid = 'pg_type'::regclass "
- "AND pip.objsubid = 0) ",
- acl_subquery->data,
- racl_subquery->data,
- initacl_subquery->data,
- initracl_subquery->data,
- username_subquery);
-
- destroyPQExpBuffer(acl_subquery);
- destroyPQExpBuffer(racl_subquery);
- destroyPQExpBuffer(initacl_subquery);
- destroyPQExpBuffer(initracl_subquery);
- }
- else if (fout->remoteVersion >= 90200)
- {
- appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
- "typnamespace, typacl, NULL as rtypacl, "
- "NULL AS inittypacl, NULL AS initrtypacl, "
- "(%s typowner) AS rolname, "
- "typelem, typrelid, "
- "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
- "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
- "typtype, typisdefined, "
- "typname[0] = '_' AND typelem != 0 AND "
- "(SELECT typarray FROM pg_type te WHERE oid = pg_type.typelem) = oid AS isarray "
- "FROM pg_type",
- username_subquery);
+ "LEFT JOIN pg_type_encoding e ON t.oid = e.typid ");
}
else
{
- appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
- "typnamespace, NULL AS typacl, NULL as rtypacl, "
- "NULL AS inittypacl, NULL AS initrtypacl, "
- "(%s typowner) AS rolname, "
- "typelem, typrelid, "
- "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
- "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
- "typtype, typisdefined, "
- "typname[0] = '_' AND typelem != 0 AND "
- "(SELECT typarray FROM pg_type te WHERE oid = pg_type.typelem) = oid AS isarray "
- "FROM pg_type",
- username_subquery);
+ appendPQExpBuffer(query, "SELECT t.tableoid, t.oid, t.typname, "
+ "t.typnamespace, NULL AS typacl, "
+ "NULL AS acldefault, "
+ "typowner, "
+ "t.typelem, t.typrelid, "
+ "CASE WHEN t.typrelid = 0 THEN ' '::\"char\" "
+ "ELSE (SELECT relkind FROM pg_class WHERE oid = t.typrelid) END AS typrelkind, "
+ "t.typtype, t.typisdefined, "
+ "t.typname[0] = '_' AND t.typelem != 0 AND "
+ "(SELECT typarray FROM pg_type te WHERE oid = t.typelem) = t.oid AS isarray, "
+ "coalesce(array_to_string(e.typoptions, ', '), '') AS typstorage "
+ "FROM pg_type t "
+ "LEFT JOIN pg_type_encoding e ON t.oid = e.typid ");
}
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -6090,10 +6018,8 @@ getTypes(Archive *fout, int *numTypes)
i_typname = PQfnumber(res, "typname");
i_typnamespace = PQfnumber(res, "typnamespace");
i_typacl = PQfnumber(res, "typacl");
- i_rtypacl = PQfnumber(res, "rtypacl");
- i_inittypacl = PQfnumber(res, "inittypacl");
- i_initrtypacl = PQfnumber(res, "initrtypacl");
- i_rolname = PQfnumber(res, "rolname");
+ i_acldefault = PQfnumber(res, "acldefault");
+ i_typowner = PQfnumber(res, "typowner");
i_typelem = PQfnumber(res, "typelem");
i_typrelid = PQfnumber(res, "typrelid");
i_typrelkind = PQfnumber(res, "typrelkind");
@@ -6111,12 +6037,12 @@ getTypes(Archive *fout, int *numTypes)
tyinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_typname));
tyinfo[i].dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_typnamespace)));
+ tyinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_typacl));
+ tyinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
+ tyinfo[i].dacl.privtype = 0;
+ tyinfo[i].dacl.initprivs = NULL;
tyinfo[i].ftypname = NULL; /* may get filled later */
- tyinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
- tyinfo[i].typacl = pg_strdup(PQgetvalue(res, i, i_typacl));
- tyinfo[i].rtypacl = pg_strdup(PQgetvalue(res, i, i_rtypacl));
- tyinfo[i].inittypacl = pg_strdup(PQgetvalue(res, i, i_inittypacl));
- tyinfo[i].initrtypacl = pg_strdup(PQgetvalue(res, i, i_initrtypacl));
+ tyinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_typowner));
tyinfo[i].typelem = atooid(PQgetvalue(res, i, i_typelem));
tyinfo[i].typrelid = atooid(PQgetvalue(res, i, i_typrelid));
tyinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind);
@@ -6143,11 +6069,9 @@ getTypes(Archive *fout, int *numTypes)
/* Decide whether we want to dump it */
selectDumpableType(&tyinfo[i], fout);
- /* Do not try to dump ACL if no ACL exists. */
- if (PQgetisnull(res, i, i_typacl) && PQgetisnull(res, i, i_rtypacl) &&
- PQgetisnull(res, i, i_inittypacl) &&
- PQgetisnull(res, i, i_initrtypacl))
- tyinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Mark whether type has an ACL */
+ if (!PQgetisnull(res, i, i_typacl))
+ tyinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
/*
* If it's a domain, fetch info about its constraints, if any
@@ -6188,10 +6112,6 @@ getTypes(Archive *fout, int *numTypes)
*/
stinfo->dobj.dump = DUMP_COMPONENT_NONE;
}
-
- if (strlen(tyinfo[i].rolname) == 0)
- pg_log_warning("owner of data type \"%s\" appears to be invalid",
- tyinfo[i].dobj.name);
}
*numTypes = ntups;
@@ -6222,7 +6142,7 @@ getOperators(Archive *fout, int *numOprs)
int i_oid;
int i_oprname;
int i_oprnamespace;
- int i_rolname;
+ int i_oprowner;
int i_oprkind;
int i_oprcode;
@@ -6233,11 +6153,10 @@ getOperators(Archive *fout, int *numOprs)
appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, "
"oprnamespace, "
- "(%s oprowner) AS rolname, "
+ "oprowner, "
"oprkind, "
"oprcode::oid AS oprcode "
- "FROM pg_operator",
- username_subquery);
+ "FROM pg_operator");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -6250,7 +6169,7 @@ getOperators(Archive *fout, int *numOprs)
i_oid = PQfnumber(res, "oid");
i_oprname = PQfnumber(res, "oprname");
i_oprnamespace = PQfnumber(res, "oprnamespace");
- i_rolname = PQfnumber(res, "rolname");
+ i_oprowner = PQfnumber(res, "oprowner");
i_oprkind = PQfnumber(res, "oprkind");
i_oprcode = PQfnumber(res, "oprcode");
@@ -6263,19 +6182,12 @@ getOperators(Archive *fout, int *numOprs)
oprinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_oprname));
oprinfo[i].dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_oprnamespace)));
- oprinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ oprinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_oprowner));
oprinfo[i].oprkind = (PQgetvalue(res, i, i_oprkind))[0];
oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));
/* Decide whether we want to dump it */
selectDumpableObject(&(oprinfo[i].dobj), fout);
-
- /* Operators do not currently have ACLs. */
- oprinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
-
- if (strlen(oprinfo[i].rolname) == 0)
- pg_log_warning("owner of operator \"%s\" appears to be invalid",
- oprinfo[i].dobj.name);
}
PQclear(res);
@@ -6304,7 +6216,7 @@ getCollations(Archive *fout, int *numCollations)
int i_oid;
int i_collname;
int i_collnamespace;
- int i_rolname;
+ int i_collowner;
/* Collations didn't exist pre-9.1 */
if (fout->remoteVersion < 90100)
@@ -6322,9 +6234,8 @@ getCollations(Archive *fout, int *numCollations)
appendPQExpBuffer(query, "SELECT tableoid, oid, collname, "
"collnamespace, "
- "(%s collowner) AS rolname "
- "FROM pg_collation",
- username_subquery);
+ "collowner "
+ "FROM pg_collation");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -6337,7 +6248,7 @@ getCollations(Archive *fout, int *numCollations)
i_oid = PQfnumber(res, "oid");
i_collname = PQfnumber(res, "collname");
i_collnamespace = PQfnumber(res, "collnamespace");
- i_rolname = PQfnumber(res, "rolname");
+ i_collowner = PQfnumber(res, "collowner");
for (i = 0; i < ntups; i++)
{
@@ -6348,13 +6259,10 @@ getCollations(Archive *fout, int *numCollations)
collinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_collname));
collinfo[i].dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_collnamespace)));
- collinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ collinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_collowner));
/* Decide whether we want to dump it */
selectDumpableObject(&(collinfo[i].dobj), fout);
-
- /* Collations do not currently have ACLs. */
- collinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -6383,7 +6291,7 @@ getConversions(Archive *fout, int *numConversions)
int i_oid;
int i_conname;
int i_connamespace;
- int i_rolname;
+ int i_conowner;
query = createPQExpBuffer();
@@ -6394,9 +6302,8 @@ getConversions(Archive *fout, int *numConversions)
appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
"connamespace, "
- "(%s conowner) AS rolname "
- "FROM pg_conversion",
- username_subquery);
+ "conowner "
+ "FROM pg_conversion");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -6409,7 +6316,7 @@ getConversions(Archive *fout, int *numConversions)
i_oid = PQfnumber(res, "oid");
i_conname = PQfnumber(res, "conname");
i_connamespace = PQfnumber(res, "connamespace");
- i_rolname = PQfnumber(res, "rolname");
+ i_conowner = PQfnumber(res, "conowner");
for (i = 0; i < ntups; i++)
{
@@ -6420,13 +6327,10 @@ getConversions(Archive *fout, int *numConversions)
convinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
convinfo[i].dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_connamespace)));
- convinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ convinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_conowner));
/* Decide whether we want to dump it */
selectDumpableObject(&(convinfo[i].dobj), fout);
-
- /* Conversions do not currently have ACLs. */
- convinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -6497,9 +6401,6 @@ getAccessMethods(Archive *fout, int *numAccessMethods)
/* Decide whether we want to dump it */
selectDumpableAccessMethod(&(aminfo[i]), fout);
-
- /* Access methods do not currently have ACLs. */
- aminfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -6529,7 +6430,7 @@ getOpclasses(Archive *fout, int *numOpclasses)
int i_oid;
int i_opcname;
int i_opcnamespace;
- int i_rolname;
+ int i_opcowner;
/*
* find all opclasses, including builtin opclasses; we filter out
@@ -6538,9 +6439,8 @@ getOpclasses(Archive *fout, int *numOpclasses)
appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
"opcnamespace, "
- "(%s opcowner) AS rolname "
- "FROM pg_opclass",
- username_subquery);
+ "opcowner "
+ "FROM pg_opclass");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -6553,7 +6453,7 @@ getOpclasses(Archive *fout, int *numOpclasses)
i_oid = PQfnumber(res, "oid");
i_opcname = PQfnumber(res, "opcname");
i_opcnamespace = PQfnumber(res, "opcnamespace");
- i_rolname = PQfnumber(res, "rolname");
+ i_opcowner = PQfnumber(res, "opcowner");
for (i = 0; i < ntups; i++)
{
@@ -6564,17 +6464,10 @@ getOpclasses(Archive *fout, int *numOpclasses)
opcinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opcname));
opcinfo[i].dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_opcnamespace)));
- opcinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ opcinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_opcowner));
/* Decide whether we want to dump it */
selectDumpableObject(&(opcinfo[i].dobj), fout);
-
- /* Op Classes do not currently have ACLs. */
- opcinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
-
- if (strlen(opcinfo[i].rolname) == 0)
- pg_log_warning("owner of operator class \"%s\" appears to be invalid",
- opcinfo[i].dobj.name);
}
PQclear(res);
@@ -6603,14 +6496,7 @@ getOpfamilies(Archive *fout, int *numOpfamilies)
int i_oid;
int i_opfname;
int i_opfnamespace;
- int i_rolname;
-
- /* Before 8.3, there is no separate concept of opfamilies */
- if (fout->remoteVersion < 80300)
- {
- *numOpfamilies = 0;
- return NULL;
- }
+ int i_opfowner;
query = createPQExpBuffer();
@@ -6621,9 +6507,8 @@ getOpfamilies(Archive *fout, int *numOpfamilies)
appendPQExpBuffer(query, "SELECT tableoid, oid, opfname, "
"opfnamespace, "
- "(%s opfowner) AS rolname "
- "FROM pg_opfamily",
- username_subquery);
+ "opfowner "
+ "FROM pg_opfamily");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -6636,7 +6521,7 @@ getOpfamilies(Archive *fout, int *numOpfamilies)
i_oid = PQfnumber(res, "oid");
i_opfname = PQfnumber(res, "opfname");
i_opfnamespace = PQfnumber(res, "opfnamespace");
- i_rolname = PQfnumber(res, "rolname");
+ i_opfowner = PQfnumber(res, "opfowner");
for (i = 0; i < ntups; i++)
{
@@ -6647,17 +6532,10 @@ getOpfamilies(Archive *fout, int *numOpfamilies)
opfinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opfname));
opfinfo[i].dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_opfnamespace)));
- opfinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ opfinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_opfowner));
/* Decide whether we want to dump it */
selectDumpableObject(&(opfinfo[i].dobj), fout);
-
- /* Extensions do not currently have ACLs. */
- opfinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
-
- if (strlen(opfinfo[i].rolname) == 0)
- pg_log_warning("owner of operator family \"%s\" appears to be invalid",
- opfinfo[i].dobj.name);
}
PQclear(res);
@@ -6689,11 +6567,9 @@ getAggregates(Archive *fout, int *numAggs)
int i_aggnamespace;
int i_pronargs;
int i_proargtypes;
- int i_rolname;
+ int i_proowner;
int i_aggacl;
- int i_raggacl;
- int i_initaggacl;
- int i_initraggacl;
+ int i_acldefault;
/*
* Find all interesting aggregates. See comment in getFuncs() for the
@@ -6701,16 +6577,8 @@ getAggregates(Archive *fout, int *numAggs)
*/
if (fout->remoteVersion >= 90600)
{
- PQExpBuffer acl_subquery = createPQExpBuffer();
- PQExpBuffer racl_subquery = createPQExpBuffer();
- PQExpBuffer initacl_subquery = createPQExpBuffer();
- PQExpBuffer initracl_subquery = createPQExpBuffer();
const char *agg_check;
- buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
- initracl_subquery, "p.proacl", "p.proowner", "'f'",
- dopt->binary_upgrade);
-
agg_check = (fout->remoteVersion >= 110000 ? "p.prokind = 'a'"
: "p.proisagg");
@@ -6718,11 +6586,9 @@ getAggregates(Archive *fout, int *numAggs)
"p.proname AS aggname, "
"p.pronamespace AS aggnamespace, "
"p.pronargs, p.proargtypes, "
- "(%s p.proowner) AS rolname, "
- "%s AS aggacl, "
- "%s AS raggacl, "
- "%s AS initaggacl, "
- "%s AS initraggacl "
+ "p.proowner, "
+ "p.proacl AS aggacl, "
+ "acldefault('f', p.proowner) AS acldefault "
"FROM pg_proc p "
"LEFT JOIN pg_init_privs pip ON "
"(p.oid = pip.objoid "
@@ -6733,11 +6599,6 @@ getAggregates(Archive *fout, int *numAggs)
"(SELECT oid FROM pg_namespace "
"WHERE nspname = 'pg_catalog') OR "
"p.proacl IS DISTINCT FROM pip.initprivs",
- username_subquery,
- acl_subquery->data,
- racl_subquery->data,
- initacl_subquery->data,
- initracl_subquery->data,
agg_check);
if (dopt->binary_upgrade)
appendPQExpBufferStr(query,
@@ -6747,27 +6608,42 @@ getAggregates(Archive *fout, int *numAggs)
"refclassid = 'pg_extension'::regclass AND "
"deptype = 'e')");
appendPQExpBufferChar(query, ')');
-
- destroyPQExpBuffer(acl_subquery);
- destroyPQExpBuffer(racl_subquery);
- destroyPQExpBuffer(initacl_subquery);
- destroyPQExpBuffer(initracl_subquery);
+ }
+ else if (fout->remoteVersion >= 90200)
+ {
+ appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
+ "pronamespace AS aggnamespace, "
+ "pronargs, proargtypes, "
+ "proowner, "
+ "proacl AS aggacl, "
+ "acldefault('f', proowner) AS acldefault "
+ "FROM pg_proc p "
+ "WHERE proisagg AND ("
+ "pronamespace != "
+ "(SELECT oid FROM pg_namespace "
+ "WHERE nspname = 'pg_catalog')");
+ if (dopt->binary_upgrade)
+ appendPQExpBufferStr(query,
+ " OR EXISTS(SELECT 1 FROM pg_depend WHERE "
+ "classid = 'pg_proc'::regclass AND "
+ "objid = p.oid AND "
+ "refclassid = 'pg_extension'::regclass AND "
+ "deptype = 'e')");
+ appendPQExpBufferChar(query, ')');
}
else
{
appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
"pronamespace AS aggnamespace, "
"pronargs, proargtypes, "
- "(%s proowner) AS rolname, "
+ "proowner, "
"proacl AS aggacl, "
- "NULL AS raggacl, "
- "NULL AS initaggacl, NULL AS initraggacl "
+ "NULL AS acldefault "
"FROM pg_proc p "
"WHERE proisagg AND ("
"pronamespace != "
"(SELECT oid FROM pg_namespace "
- "WHERE nspname = 'pg_catalog')",
- username_subquery);
+ "WHERE nspname = 'pg_catalog')");
if (dopt->binary_upgrade && fout->remoteVersion >= 90100)
appendPQExpBufferStr(query,
" OR EXISTS(SELECT 1 FROM pg_depend WHERE "
@@ -6791,11 +6667,9 @@ getAggregates(Archive *fout, int *numAggs)
i_aggnamespace = PQfnumber(res, "aggnamespace");
i_pronargs = PQfnumber(res, "pronargs");
i_proargtypes = PQfnumber(res, "proargtypes");
- i_rolname = PQfnumber(res, "rolname");
+ i_proowner = PQfnumber(res, "proowner");
i_aggacl = PQfnumber(res, "aggacl");
- i_raggacl = PQfnumber(res, "raggacl");
- i_initaggacl = PQfnumber(res, "initaggacl");
- i_initraggacl = PQfnumber(res, "initraggacl");
+ i_acldefault = PQfnumber(res, "acldefault");
for (i = 0; i < ntups; i++)
{
@@ -6806,16 +6680,13 @@ getAggregates(Archive *fout, int *numAggs)
agginfo[i].aggfn.dobj.name = pg_strdup(PQgetvalue(res, i, i_aggname));
agginfo[i].aggfn.dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_aggnamespace)));
- agginfo[i].aggfn.rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
- if (strlen(agginfo[i].aggfn.rolname) == 0)
- pg_log_warning("owner of aggregate function \"%s\" appears to be invalid",
- agginfo[i].aggfn.dobj.name);
+ agginfo[i].aggfn.dacl.acl = pg_strdup(PQgetvalue(res, i, i_aggacl));
+ agginfo[i].aggfn.dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
+ agginfo[i].aggfn.dacl.privtype = 0;
+ agginfo[i].aggfn.dacl.initprivs = NULL;
+ agginfo[i].aggfn.rolname = getRoleName(PQgetvalue(res, i, i_proowner));
agginfo[i].aggfn.lang = InvalidOid; /* not currently interesting */
agginfo[i].aggfn.prorettype = InvalidOid; /* not saved */
- agginfo[i].aggfn.proacl = pg_strdup(PQgetvalue(res, i, i_aggacl));
- agginfo[i].aggfn.rproacl = pg_strdup(PQgetvalue(res, i, i_raggacl));
- agginfo[i].aggfn.initproacl = pg_strdup(PQgetvalue(res, i, i_initaggacl));
- agginfo[i].aggfn.initrproacl = pg_strdup(PQgetvalue(res, i, i_initraggacl));
agginfo[i].aggfn.nargs = atoi(PQgetvalue(res, i, i_pronargs));
if (agginfo[i].aggfn.nargs == 0)
agginfo[i].aggfn.argtypes = NULL;
@@ -6828,13 +6699,11 @@ getAggregates(Archive *fout, int *numAggs)
}
/* Decide whether we want to dump it */
- selectDumpableObject(&(agginfo[i].aggfn.dobj), fout);
+ selectDumpableAggregate(&(agginfo[i]), fout);
- /* Do not try to dump ACL if no ACL exists. */
- if (PQgetisnull(res, i, i_aggacl) && PQgetisnull(res, i, i_raggacl) &&
- PQgetisnull(res, i, i_initaggacl) &&
- PQgetisnull(res, i, i_initraggacl))
- agginfo[i].aggfn.dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Mark whether aggregate has an ACL */
+ if (!PQgetisnull(res, i, i_aggacl))
+ agginfo[i].aggfn.dobj.components |= DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -6863,74 +6732,40 @@ getExtProtocols(Archive *fout, int *numExtProtocols)
int i_oid;
int i_tableoid;
int i_ptcname;
- int i_rolname;
+ int i_ptcowner;
int i_ptcacl;
- int i_ptcracl;
- int i_ptcinitacl;
- int i_ptcinitracl;
+ int i_acldefault;
int i_ptctrusted;
int i_ptcreadid;
int i_ptcwriteid;
int i_ptcvalidid;
/* find all user-defined external protocol */
-
-
if (fout->remoteVersion >= 90600)
{
- PQExpBuffer acl_subquery = createPQExpBuffer();
- PQExpBuffer racl_subquery = createPQExpBuffer();
- PQExpBuffer initacl_subquery = createPQExpBuffer();
- PQExpBuffer initracl_subquery = createPQExpBuffer();
-
- buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
- initracl_subquery, "ptc.ptcacl", "ptc.ptcowner", "'E'",
- fout->dopt->binary_upgrade);
-
- appendPQExpBuffer(query, "SELECT ptc.tableoid as tableoid, "
- " ptc.oid as oid, "
- " ptc.ptcname as ptcname, "
- " ptcreadfn as ptcreadoid, "
- " ptcwritefn as ptcwriteoid, "
- " ptcvalidatorfn as ptcvaloid, "
- " (%s ptc.ptcowner) as rolname, "
- " ptc.ptctrusted as ptctrusted, "
- " %s AS ptcacl, "
- " %s AS ptcracl, "
- " %s AS ptcinitacl, "
- " %s AS ptcinitracl "
- "FROM pg_extprotocol ptc "
- "LEFT JOIN pg_init_privs pip ON "
- " (ptc.oid = pip.objoid "
- " AND pip.classoid = 'pg_extprotocol'::regclass "
- " AND pip.objsubid = 0)",
- username_subquery,
- acl_subquery->data,
- racl_subquery->data,
- initacl_subquery->data,
- initracl_subquery->data);
-
- destroyPQExpBuffer(acl_subquery);
- destroyPQExpBuffer(racl_subquery);
- destroyPQExpBuffer(initacl_subquery);
- destroyPQExpBuffer(initracl_subquery);
+ appendPQExpBuffer(query, "SELECT tableoid, "
+ "oid, "
+ "ptcname, "
+ "ptcreadfn as ptcreadoid, "
+ "ptcwritefn as ptcwriteoid, "
+ "ptcvalidatorfn as ptcvaloid, "
+ "ptcowner, "
+ "ptctrusted, ptcacl, "
+ "acldefault('E', ptcowner) AS acldefault "
+ "FROM pg_extprotocol ");
}
else
{
- appendPQExpBuffer(query, "SELECT ptc.tableoid as tableoid, "
- " ptc.oid as oid, "
- " ptc.ptcname as ptcname, "
- " ptcreadfn as ptcreadoid, "
- " ptcwritefn as ptcwriteoid, "
- " ptcvalidatorfn as ptcvaloid, "
- " (%s ptc.ptcowner) as rolname, "
- " ptc.ptctrusted as ptctrusted, "
- " ptc.ptcacl as ptcacl, "
- " NULL as ptcracl, "
- " NULL as ptcinitacl, "
- " NULL as ptcinitracl "
- "FROM pg_extprotocol ptc",
- username_subquery);
+ appendPQExpBuffer(query, "SELECT tableoid, "
+ "oid, "
+ "ptcname, "
+ "ptcreadfn as ptcreadoid, "
+ "ptcwritefn as ptcwriteoid, "
+ "ptcvalidatorfn as ptcvaloid, "
+ "ptcowner, "
+ "ptctrusted, ptcacl, "
+ "NULL AS acldefault "
+ "FROM pg_extprotocol ");
}
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -6943,11 +6778,9 @@ getExtProtocols(Archive *fout, int *numExtProtocols)
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
i_ptcname = PQfnumber(res, "ptcname");
- i_rolname = PQfnumber(res, "rolname");
+ i_ptcowner = PQfnumber(res, "ptcowner");
i_ptcacl = PQfnumber(res, "ptcacl");
- i_ptcracl = PQfnumber(res, "ptcracl");
- i_ptcinitacl = PQfnumber(res, "ptcinitacl");
- i_ptcinitracl = PQfnumber(res, "ptcinitracl");
+ i_acldefault = PQfnumber(res, "acldefault");
i_ptctrusted = PQfnumber(res, "ptctrusted");
i_ptcreadid = PQfnumber(res, "ptcreadoid");
i_ptcwriteid = PQfnumber(res, "ptcwriteoid");
@@ -6961,10 +6794,7 @@ getExtProtocols(Archive *fout, int *numExtProtocols)
AssignDumpId(&ptcinfo[i].dobj);
ptcinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_ptcname));
ptcinfo[i].dobj.namespace = NULL;
- ptcinfo[i].ptcowner = pg_strdup(PQgetvalue(res, i, i_rolname));
- if (strlen(ptcinfo[i].ptcowner) == 0)
- pg_log_warning("owner of external protocol \"%s\" appears to be invalid",
- ptcinfo[i].dobj.name);
+ ptcinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_ptcowner));
if (PQgetisnull(res, i, i_ptcreadid))
ptcinfo[i].ptcreadid = InvalidOid;
@@ -6981,14 +6811,20 @@ getExtProtocols(Archive *fout, int *numExtProtocols)
else
ptcinfo[i].ptcvalidid = atooid(PQgetvalue(res, i, i_ptcvalidid));
- ptcinfo[i].ptcacl = pg_strdup(PQgetvalue(res, i, i_ptcacl));
- ptcinfo[i].rproacl = pg_strdup(PQgetvalue(res, i, i_ptcracl));
- ptcinfo[i].initproacl = pg_strdup(PQgetvalue(res, i, i_ptcinitacl));
- ptcinfo[i].initrproacl = pg_strdup(PQgetvalue(res, i, i_ptcinitracl));
ptcinfo[i].ptctrusted = *(PQgetvalue(res, i, i_ptctrusted)) == 't';
+ ptcinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_ptcacl));
+ ptcinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
+ ptcinfo[i].dacl.privtype = 0;
+ ptcinfo[i].dacl.initprivs = NULL;
+
+
/* Decide whether we want to dump it */
selectDumpableObject(&(ptcinfo[i].dobj), fout);
+
+ /* Mark whether function has an ACL */
+ if (!PQgetisnull(res, i, i_ptcacl))
+ ptcinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -7018,15 +6854,13 @@ getFuncs(Archive *fout, int *numFuncs)
int i_oid;
int i_proname;
int i_pronamespace;
- int i_rolname;
+ int i_proowner;
int i_prolang;
int i_pronargs;
int i_proargtypes;
int i_prorettype;
int i_proacl;
- int i_rproacl;
- int i_initproacl;
- int i_initrproacl;
+ int i_acldefault;
/*
* Find all interesting functions. This is a bit complicated:
@@ -7048,32 +6882,22 @@ getFuncs(Archive *fout, int *numFuncs)
* to gather the information about them, though they won't be dumped if
* they are built-in. Also, in 9.6 and up, include functions in
* pg_catalog if they have an ACL different from what's shown in
- * pg_init_privs.
+ * pg_init_privs (so we have to join to pg_init_privs; annoying).
*/
if (fout->remoteVersion >= 90600)
{
- PQExpBuffer acl_subquery = createPQExpBuffer();
- PQExpBuffer racl_subquery = createPQExpBuffer();
- PQExpBuffer initacl_subquery = createPQExpBuffer();
- PQExpBuffer initracl_subquery = createPQExpBuffer();
const char *not_agg_check;
- buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
- initracl_subquery, "p.proacl", "p.proowner", "'f'",
- dopt->binary_upgrade);
-
not_agg_check = (fout->remoteVersion >= 110000 ? "p.prokind <> 'a'"
: "NOT p.proisagg");
appendPQExpBuffer(query,
"SELECT p.tableoid, p.oid, p.proname, p.prolang, "
"p.pronargs, p.proargtypes, p.prorettype, "
- "%s AS proacl, "
- "%s AS rproacl, "
- "%s AS initproacl, "
- "%s AS initrproacl, "
+ "p.proacl, "
+ "acldefault('f', p.proowner) AS acldefault, "
"p.pronamespace, "
- "(%s p.proowner) AS rolname "
+ "p.proowner "
"FROM pg_proc p "
"LEFT JOIN pg_init_privs pip ON "
"(p.oid = pip.objoid "
@@ -7094,11 +6918,6 @@ getFuncs(Archive *fout, int *numFuncs)
"\n WHERE pg_transform.oid > %u AND "
"\n (p.oid = pg_transform.trffromsql"
"\n OR p.oid = pg_transform.trftosql))",
- acl_subquery->data,
- racl_subquery->data,
- initacl_subquery->data,
- initracl_subquery->data,
- username_subquery,
not_agg_check,
g_last_builtin_oid,
g_last_builtin_oid);
@@ -7112,24 +6931,23 @@ getFuncs(Archive *fout, int *numFuncs)
appendPQExpBufferStr(query,
"\n OR p.proacl IS DISTINCT FROM pip.initprivs");
appendPQExpBufferChar(query, ')');
-
- destroyPQExpBuffer(acl_subquery);
- destroyPQExpBuffer(racl_subquery);
- destroyPQExpBuffer(initacl_subquery);
- destroyPQExpBuffer(initracl_subquery);
}
else
{
+ const char *acldefault_call;
+
+ acldefault_call = (fout->remoteVersion >= 90200 ?
+ "acldefault('f', proowner)" : "NULL");
+
appendPQExpBuffer(query,
"SELECT tableoid, oid, proname, prolang, "
"pronargs, proargtypes, prorettype, proacl, "
- "NULL as rproacl, "
- "NULL as initproacl, NULL AS initrproacl, "
+ "%s AS acldefault, "
"pronamespace, "
- "(%s proowner) AS rolname "
+ "proowner "
"FROM pg_proc p "
"WHERE NOT proisagg",
- username_subquery);
+ acldefault_call);
if (fout->remoteVersion >= 90200)
appendPQExpBufferStr(query,
"\n AND NOT EXISTS (SELECT 1 FROM pg_depend "
@@ -7155,12 +6973,9 @@ getFuncs(Archive *fout, int *numFuncs)
/*
* GPDB: Much of the extension machinery was backported into GPDB 5 from higher
- * major versions. So include the clause if we are running against GPDB 5.
+ * major versions, so include the clause.
*/
-#if 0
- if (dopt->binary_upgrade && fout->remoteVersion >= 90100)
-#endif
- if (dopt->binary_upgrade && fout->remoteVersion >= 80300)
+ if (dopt->binary_upgrade)
appendPQExpBufferStr(query,
"\n OR EXISTS(SELECT 1 FROM pg_depend WHERE "
"classid = 'pg_proc'::regclass AND "
@@ -7182,15 +6997,13 @@ getFuncs(Archive *fout, int *numFuncs)
i_oid = PQfnumber(res, "oid");
i_proname = PQfnumber(res, "proname");
i_pronamespace = PQfnumber(res, "pronamespace");
- i_rolname = PQfnumber(res, "rolname");
+ i_proowner = PQfnumber(res, "proowner");
i_prolang = PQfnumber(res, "prolang");
i_pronargs = PQfnumber(res, "pronargs");
i_proargtypes = PQfnumber(res, "proargtypes");
i_prorettype = PQfnumber(res, "prorettype");
i_proacl = PQfnumber(res, "proacl");
- i_rproacl = PQfnumber(res, "rproacl");
- i_initproacl = PQfnumber(res, "initproacl");
- i_initrproacl = PQfnumber(res, "initrproacl");
+ i_acldefault = PQfnumber(res, "acldefault");
for (i = 0; i < ntups; i++)
{
@@ -7201,13 +7014,13 @@ getFuncs(Archive *fout, int *numFuncs)
finfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_proname));
finfo[i].dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_pronamespace)));
- finfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ finfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_proacl));
+ finfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
+ finfo[i].dacl.privtype = 0;
+ finfo[i].dacl.initprivs = NULL;
+ finfo[i].rolname = getRoleName(PQgetvalue(res, i, i_proowner));
finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
- finfo[i].proacl = pg_strdup(PQgetvalue(res, i, i_proacl));
- finfo[i].rproacl = pg_strdup(PQgetvalue(res, i, i_rproacl));
- finfo[i].initproacl = pg_strdup(PQgetvalue(res, i, i_initproacl));
- finfo[i].initrproacl = pg_strdup(PQgetvalue(res, i, i_initrproacl));
finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
if (finfo[i].nargs == 0)
finfo[i].argtypes = NULL;
@@ -7219,18 +7032,11 @@ getFuncs(Archive *fout, int *numFuncs)
}
/* Decide whether we want to dump it */
- selectDumpableFunction(&finfo[i]);
- selectDumpableObject(&(finfo[i].dobj), fout);
+ selectDumpableFunction(&finfo[i], fout);
- /* Do not try to dump ACL if no ACL exists. */
- if (PQgetisnull(res, i, i_proacl) && PQgetisnull(res, i, i_rproacl) &&
- PQgetisnull(res, i, i_initproacl) &&
- PQgetisnull(res, i, i_initrproacl))
- finfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
-
- if (strlen(finfo[i].rolname) == 0)
- pg_log_warning("owner of function \"%s\" appears to be invalid",
- finfo[i].dobj.name);
+ /* Mark whether function has an ACL */
+ if (!PQgetisnull(res, i, i_proacl))
+ finfo[i].dobj.components |= DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -7262,12 +7068,8 @@ getTables(Archive *fout, int *numTables)
int i_relname;
int i_relnamespace;
int i_relkind;
- int i_relstorage;
- int i_relacl;
- int i_rrelacl;
- int i_initrelacl;
- int i_initrrelacl;
- int i_rolname;
+ int i_reltype;
+ int i_relowner;
int i_relchecks;
int i_relhastriggers;
int i_relhasindex;
@@ -7291,14 +7093,14 @@ getTables(Archive *fout, int *numTables)
int i_toastreloptions;
int i_reloftype;
int i_relpages;
+ int i_relstorage;
int i_parrelid;
int i_parlevel;
int i_foreignserver;
int i_is_identity_sequence;
- int i_changed_acl;
- int i_partkeydef;
+ int i_relacl;
+ int i_acldefault;
int i_ispartition;
- int i_partbound;
int i_amname;
int i_amoid;
int i_isivm;
@@ -7307,6 +7109,9 @@ getTables(Archive *fout, int *numTables)
/*
* Find all the tables and table-like objects.
*
+ * We must fetch all tables in this phase because otherwise we cannot
+ * correctly identify inherited columns, owned sequences, etc.
+ *
* We include system catalogs, so that we can work if a user table is
* defined to inherit from a system catalog (pretty weird, but...)
*
@@ -7320,571 +7125,234 @@ getTables(Archive *fout, int *numTables)
*
* Note: in this phase we should collect only a minimal amount of
* information about each table, basically just enough to decide if it is
- * interesting. We must fetch all tables in this phase because otherwise
- * we cannot correctly identify inherited columns, owned sequences, etc.
- *
- * We purposefully ignore toast OIDs for partitioned tables; the reason is
- * that versions 10 and 11 have them, but 12 does not, so emitting them
- * causes the upgrade to fail.
+ * interesting. In particular, since we do not yet have lock on any user
+ * table, we MUST NOT invoke any server-side data collection functions
+ * (for instance, pg_get_partkeydef()). Those are likely to fail or give
+ * wrong answers if any concurrent DDL is happening.
*/
- if (fout->remoteVersion >= 90600)
- {
- char *partkeydef = "NULL";
- char *ispartition = "false";
- char *partbound = "NULL";
- char *relhasoids = "c.relhasoids";
+ appendPQExpBuffer(query,
+ "SELECT c.tableoid, c.oid, c.relname, "
+ "c.relnamespace, c.relkind, c.reltype, "
+ "c.relowner, "
+ "c.relchecks, "
+ "c.relhasindex, c.relhasrules, c.relpages, "
+ "d.refobjid AS owning_tab, "
+ "d.refobjsubid AS owning_col, "
+ "tsp.spcname AS reltablespace, "
+ "c.relfrozenxid, tc.relfrozenxid AS tfrozenxid, "
+ "tc.oid AS toid, ");
- PQExpBuffer acl_subquery = createPQExpBuffer();
- PQExpBuffer racl_subquery = createPQExpBuffer();
- PQExpBuffer initacl_subquery = createPQExpBuffer();
- PQExpBuffer initracl_subquery = createPQExpBuffer();
+ if (fout->remoteVersion >= 90600)
+ appendPQExpBufferStr(query,
+ "'' AS relstorage, ");
+ else
+ appendPQExpBufferStr(query,
+ "c.relstorage, ");
- PQExpBuffer attacl_subquery = createPQExpBuffer();
- PQExpBuffer attracl_subquery = createPQExpBuffer();
- PQExpBuffer attinitacl_subquery = createPQExpBuffer();
- PQExpBuffer attinitracl_subquery = createPQExpBuffer();
+ if (fout->remoteVersion >= 120000)
+ appendPQExpBufferStr(query,
+ "false AS relhasoids, ");
+ else
+ appendPQExpBufferStr(query,
+ "c.relhasoids, ");
- /*
- * Collect the information about any partitioned tables, which were
- * added in PG10.
- */
+ if (fout->remoteVersion >= 80400)
+ appendPQExpBufferStr(query,
+ "c.relhastriggers, ");
+ else
+ appendPQExpBufferStr(query,
+ "(c.reltriggers <> 0) AS relhastriggers, ");
- if (fout->remoteVersion >= 100000)
- {
- partkeydef = "pg_get_partkeydef(c.oid)";
- ispartition = "c.relispartition";
- partbound = "pg_get_expr(c.relpartbound, c.oid)";
- }
+ if (fout->remoteVersion >= 90100)
+ appendPQExpBufferStr(query,
+ "c.relpersistence, ");
+ else
+ appendPQExpBufferStr(query,
+ "'p' AS relpersistence, ");
- /* In PG12 upwards WITH OIDS does not exist anymore. */
- if (fout->remoteVersion >= 120000)
- relhasoids = "'f'::bool";
+ if (fout->remoteVersion >= 90300)
+ appendPQExpBufferStr(query,
+ "c.relispopulated, ");
+ else
+ appendPQExpBufferStr(query,
+ "'t' as relispopulated, ");
- /*
- * Left join to pick up dependency info linking sequences to their
- * owning column, if any (note this dependency is AUTO as of 8.2)
- *
- * Left join to detect if any privileges are still as-set-at-init, in
- * which case we won't dump out ACL commands for those.
- */
+ if (fout->remoteVersion >= 90400)
+ appendPQExpBufferStr(query,
+ "c.relreplident, ");
+ else
+ appendPQExpBufferStr(query,
+ "'d' AS relreplident, ");
- buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
- initracl_subquery, "c.relacl", "c.relowner",
- "CASE WHEN c.relkind = " CppAsString2(RELKIND_SEQUENCE)
- " THEN 's' ELSE 'r' END::\"char\"",
- dopt->binary_upgrade);
+ if (fout->remoteVersion >= 90500)
+ appendPQExpBufferStr(query,
+ "c.relrowsecurity, c.relforcerowsecurity, ");
+ else
+ appendPQExpBufferStr(query,
+ "false AS relrowsecurity, "
+ "false AS relforcerowsecurity, ");
- buildACLQueries(attacl_subquery, attracl_subquery, attinitacl_subquery,
- attinitracl_subquery, "at.attacl", "c.relowner", "'c'",
- dopt->binary_upgrade);
+ if (fout->remoteVersion >= 90300)
+ appendPQExpBufferStr(query,
+ "c.relminmxid, tc.relminmxid AS tminmxid, ");
+ else
+ appendPQExpBufferStr(query,
+ "0 AS relminmxid, 0 AS tminmxid, ");
- appendPQExpBuffer(query,
- "SELECT c.tableoid, c.oid, c.relname, "
- "'' AS relstorage, "
- "%s AS relacl, %s as rrelacl, "
- "%s AS initrelacl, %s as initrrelacl, "
- "c.relkind, c.relnamespace, "
- "(%s c.relowner) AS rolname, "
- "c.relchecks, c.relhastriggers, "
- "c.relhasindex, c.relhasrules, %s AS relhasoids, "
- "c.relrowsecurity, c.relforcerowsecurity, "
- "c.relfrozenxid, c.relminmxid, tc.oid AS toid, "
- "tc.relfrozenxid AS tfrozenxid, "
- "tc.relminmxid AS tminmxid, "
- "c.relpersistence, c.relispopulated, "
- "c.relreplident, c.relpages, am.amname, "
- "am.oid AS amoid, "
- "CASE WHEN c.relkind = 'f' THEN "
- "(SELECT ftserver FROM pg_catalog.pg_foreign_table WHERE ftrelid = c.oid) "
- "ELSE 0 END AS foreignserver, "
- "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
- "d.refobjid AS owning_tab, "
- "d.refobjsubid AS owning_col, "
- "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
+ if (fout->remoteVersion >= 90300)
+ appendPQExpBufferStr(query,
"array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
"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, "
- "tc.reloptions AS toast_reloptions, "
- "0 as parrelid, "
- "0 as parlevel, "
- "c.relkind = '%c' AND EXISTS (SELECT 1 FROM pg_depend WHERE classid = 'pg_class'::regclass AND objid = c.oid AND objsubid = 0 AND refclassid = 'pg_class'::regclass AND deptype = 'i') AS is_identity_sequence, "
- "EXISTS (SELECT 1 FROM pg_attribute at LEFT JOIN pg_init_privs pip ON "
- "(c.oid = pip.objoid "
- "AND pip.classoid = 'pg_class'::regclass "
- "AND pip.objsubid = at.attnum)"
- "WHERE at.attrelid = c.oid AND ("
- "%s IS NOT NULL "
- "OR %s IS NOT NULL "
- "OR %s IS NOT NULL "
- "OR %s IS NOT NULL"
- "))"
- "AS changed_acl, "
- "%s AS partkeydef, "
- "%s AS ispartition, "
- "%s AS partbound, "
- "c.relisivm AS isivm, "
- "%s"
- "FROM pg_class c "
- "LEFT JOIN pg_depend d ON "
- "(c.relkind = '%c' AND "
- "d.classid = c.tableoid AND d.objid = c.oid AND "
- "d.objsubid = 0 AND "
- "d.refclassid = c.tableoid AND d.deptype IN ('a', 'i')) "
- "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid AND c.relkind <> '%c') "
- "LEFT JOIN pg_am am ON (c.relam = am.oid) "
- "LEFT JOIN pg_init_privs pip ON "
- "(c.oid = pip.objoid "
- "AND pip.classoid = 'pg_class'::regclass "
- "AND pip.objsubid = 0) "
- "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c', '%c') "
- "AND c.relnamespace <> 7012 " /* BM_BITMAPINDEX_NAMESPACE */
- "ORDER BY c.oid",
- acl_subquery->data,
- racl_subquery->data,
- initacl_subquery->data,
- initracl_subquery->data,
- username_subquery,
- relhasoids,
- RELKIND_SEQUENCE,
- attacl_subquery->data,
- attracl_subquery->data,
- attinitacl_subquery->data,
- attinitracl_subquery->data,
- partkeydef,
- ispartition,
- partbound,
- (fout->version.type == Cloudberry && fout->version.version >= 2) ? "c.relisdynamic AS isdynamic " : "false AS isdynamic ",
- RELKIND_SEQUENCE,
- RELKIND_PARTITIONED_TABLE,
- RELKIND_RELATION, RELKIND_SEQUENCE,
- RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
- RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE,
- RELKIND_PARTITIONED_TABLE);
+ "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, ");
+ else
+ appendPQExpBufferStr(query,
+ "c.reloptions, NULL AS checkoption, ");
- destroyPQExpBuffer(acl_subquery);
- destroyPQExpBuffer(racl_subquery);
- destroyPQExpBuffer(initacl_subquery);
- destroyPQExpBuffer(initracl_subquery);
+ if (fout->remoteVersion >= 80400)
+ appendPQExpBufferStr(query,
+ "tc.reloptions AS toast_reloptions, ");
+ else
+ appendPQExpBufferStr(query,
+ "NULL AS toast_reloptions, ");
- destroyPQExpBuffer(attacl_subquery);
- destroyPQExpBuffer(attracl_subquery);
- destroyPQExpBuffer(attinitacl_subquery);
- destroyPQExpBuffer(attinitracl_subquery);
- }
- else if (fout->remoteVersion >= 90500)
- {
- /*
- * Left join to pick up dependency info linking sequences to their
- * owning column, if any (note this dependency is AUTO as of 8.2)
- */
- appendPQExpBuffer(query,
- "SELECT c.tableoid, c.oid, c.relname, "
- "c.relacl, NULL as rrelacl, "
- "NULL AS initrelacl, NULL AS initrrelacl, "
- "c.relkind, "
- "c.relnamespace, "
- "(%s c.relowner) AS rolname, "
- "c.relchecks, c.relhastriggers, "
- "c.relhasindex, c.relhasrules, c.relhasoids, "
- "c.relrowsecurity, c.relforcerowsecurity, "
- "c.relfrozenxid, c.relminmxid, tc.oid AS toid, "
- "tc.relfrozenxid AS tfrozenxid, "
- "tc.relminmxid AS tminmxid, "
- "c.relpersistence, c.relispopulated, "
- "c.relreplident, c.relpages, "
- "NULL AS amname, "
- "CASE WHEN c.relkind = 'f' THEN "
- "(SELECT ftserver FROM pg_catalog.pg_foreign_table WHERE ftrelid = c.oid) "
- "ELSE 0 END AS foreignserver, "
- "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
- "d.refobjid AS owning_tab, "
- "d.refobjsubid AS owning_col, "
- "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
- "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
- "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, "
- "tc.reloptions AS toast_reloptions, "
- "p.parrelid as parrelid, "
- "pl.parlevel as parlevel, "
- "NULL AS changed_acl, "
- "NULL AS partkeydef, "
- "false AS ispartition, "
- "NULL AS partbound "
- "FROM pg_class c "
- "LEFT JOIN pg_depend d ON "
- "(c.relkind = '%c' AND "
- "d.classid = c.tableoid AND d.objid = c.oid AND "
- "d.objsubid = 0 AND "
- "d.refclassid = c.tableoid AND d.deptype = 'a') "
- "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
- "LEFT JOIN pg_partition_rule pr ON c.oid = pr.parchildrelid "
- "LEFT JOIN pg_partition p ON pr.paroid = p.oid "
- "LEFT JOIN pg_partition pl ON (c.oid = pl.parrelid AND pl.parlevel = 0)"
- "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
- "AND c.relnamespace <> 7012 " /* BM_BITMAPINDEX_NAMESPACE */
- "AND c.oid NOT IN (SELECT p.parchildrelid FROM pg_partition_rule p LEFT "
- "JOIN pg_exttable e ON p.parchildrelid=e.reloid WHERE e.reloid IS NULL)"
- "ORDER BY c.oid",
- username_subquery,
- RELKIND_SEQUENCE,
- RELKIND_RELATION, RELKIND_SEQUENCE,
- RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
- RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
- }
- else if (fout->remoteVersion >= 90400)
- {
- /*
- * Left join to pick up dependency info linking sequences to their
- * owning column, if any (note this dependency is AUTO as of 8.2)
- */
- appendPQExpBuffer(query,
- "SELECT c.tableoid, c.oid, c.relname, "
- "c.relstorage, "
- "c.relacl, NULL as rrelacl, "
- "NULL AS initrelacl, NULL AS initrrelacl, "
- "c.relkind, "
- "c.relnamespace, "
- "(%s c.relowner) AS rolname, "
- "c.relchecks, c.relhastriggers, "
- "c.relhasindex, c.relhasrules, c.relhasoids, "
- "'f'::bool AS relrowsecurity, "
- "'f'::bool AS relforcerowsecurity, "
- "c.relfrozenxid, c.relminmxid, tc.oid AS toid, "
- "tc.relfrozenxid AS tfrozenxid, "
- "tc.relminmxid AS tminmxid, "
- "c.relpersistence, c.relispopulated, "
- "c.relreplident, c.relpages, "
- "NULL AS amname, "
- "CASE WHEN c.relkind = 'f' THEN "
- "(SELECT ftserver FROM pg_catalog.pg_foreign_table WHERE ftrelid = c.oid) "
- "ELSE 0 END AS foreignserver, "
- "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
- "d.refobjid AS owning_tab, "
- "d.refobjsubid AS owning_col, "
- "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
- "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
- "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, "
- "tc.reloptions AS toast_reloptions, "
- "p.parrelid as parrelid, "
- "pl.parlevel as parlevel, "
- "NULL AS changed_acl, "
- "NULL AS partkeydef, "
- "false AS ispartition, "
- "NULL AS partbound "
- "FROM pg_class c "
- "LEFT JOIN pg_depend d ON "
- "(c.relkind = '%c' AND "
- "d.classid = c.tableoid AND d.objid = c.oid AND "
- "d.objsubid = 0 AND "
- "d.refclassid = c.tableoid AND d.deptype = 'a') "
- "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid AND c.relstorage <> 'c') "
- "LEFT JOIN pg_partition_rule pr ON c.oid = pr.parchildrelid "
- "LEFT JOIN pg_partition p ON pr.paroid = p.oid "
- "LEFT JOIN pg_partition pl ON (c.oid = pl.parrelid AND pl.parlevel = 0)"
- "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
- "AND c.relnamespace <> 7012 " /* BM_BITMAPINDEX_NAMESPACE */
- "AND c.oid NOT IN (SELECT p.parchildrelid FROM pg_partition_rule p LEFT "
- "JOIN pg_exttable e ON p.parchildrelid=e.reloid WHERE e.reloid IS NULL)"
- "ORDER BY c.oid",
- username_subquery,
- RELKIND_SEQUENCE,
- RELKIND_RELATION, RELKIND_SEQUENCE,
- RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
- RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
- }
- else if (fout->remoteVersion >= 90300)
- {
- /*
- * Left join to pick up dependency info linking sequences to their
- * owning column, if any (note this dependency is AUTO as of 8.2)
- */
- appendPQExpBuffer(query,
- "SELECT c.tableoid, c.oid, c.relname, "
- "c.relacl, NULL as rrelacl, "
- "NULL AS initrelacl, NULL AS initrrelacl, "
- "c.relkind, "
- "c.relnamespace, "
- "(%s c.relowner) AS rolname, "
- "c.relchecks, c.relhastriggers, "
- "c.relhasindex, c.relhasrules, c.relhasoids, "
- "'f'::bool AS relrowsecurity, "
- "'f'::bool AS relforcerowsecurity, "
- "c.relfrozenxid, c.relminmxid, tc.oid AS toid, "
- "tc.relfrozenxid AS tfrozenxid, "
- "tc.relminmxid AS tminmxid, "
- "c.relpersistence, c.relispopulated, "
- "'d' AS relreplident, c.relpages, "
- "NULL AS amname, "
- "CASE WHEN c.relkind = 'f' THEN "
- "(SELECT ftserver FROM pg_catalog.pg_foreign_table WHERE ftrelid = c.oid) "
- "ELSE 0 END AS foreignserver, "
- "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
- "d.refobjid AS owning_tab, "
- "d.refobjsubid AS owning_col, "
- "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
- "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
- "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, "
- "tc.reloptions AS toast_reloptions, "
+ if (fout->remoteVersion >= 90000)
+ appendPQExpBufferStr(query,
+ "c.reloftype, ");
+ else
+ appendPQExpBufferStr(query,
+ "0 AS reloftype, ");
+
+ if (fout->remoteVersion >= 90600)
+ appendPQExpBufferStr(query,
+ "am.amname, am.oid as amoid, ");
+ else
+ appendPQExpBufferStr(query,
+ "NULL AS amname, NULL as amoid, ");
+
+ if (fout->remoteVersion >= 90600)
+ appendPQExpBufferStr(query,
+ "c.relkind = " CppAsString2(RELKIND_SEQUENCE)
+ "AND EXISTS (SELECT 1 FROM pg_depend "
+ "WHERE classid = 'pg_class'::regclass AND "
+ "objid = c.oid AND objsubid = 0 AND "
+ "refclassid = 'pg_class'::regclass AND "
+ "deptype = 'i') AS is_identity_sequence, ");
+ else
+ appendPQExpBufferStr(query,
+ "false AS is_identity_sequence, ");
+
+ if (fout->remoteVersion >= 90600)
+ appendPQExpBufferStr(query,
+ "0 as parrelid, "
+ "0 as parlevel, ");
+ else
+ appendPQExpBufferStr(query,
"p.parrelid as parrelid, "
- "pl.parlevel as parlevel, "
- "NULL AS changed_acl, "
- "NULL AS partkeydef, "
- "false AS ispartition, "
- "NULL AS partbound "
- "FROM pg_class c "
- "LEFT JOIN pg_depend d ON "
- "(c.relkind = '%c' AND "
- "d.classid = c.tableoid AND d.objid = c.oid AND "
- "d.objsubid = 0 AND "
- "d.refclassid = c.tableoid AND d.deptype = 'a') "
- "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
- "LEFT JOIN pg_partition_rule pr ON c.oid = pr.parchildrelid "
- "LEFT JOIN pg_partition p ON pr.paroid = p.oid "
- "LEFT JOIN pg_partition pl ON (c.oid = pl.parrelid AND pl.parlevel = 0)"
- "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
- "AND c.relnamespace <> 7012 " /* BM_BITMAPINDEX_NAMESPACE */
- "AND c.oid NOT IN (SELECT p.parchildrelid FROM pg_partition_rule p LEFT "
- "JOIN pg_exttable e ON p.parchildrelid=e.reloid WHERE e.reloid IS NULL)"
- "ORDER BY c.oid",
- username_subquery,
- RELKIND_SEQUENCE,
- RELKIND_RELATION, RELKIND_SEQUENCE,
- RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
- RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
- }
- else if (fout->remoteVersion >= 90100)
- {
- /*
- * Left join to pick up dependency info linking sequences to their
- * owning column, if any (note this dependency is AUTO as of 8.2)
- */
- appendPQExpBuffer(query,
- "SELECT c.tableoid, c.oid, c.relname, "
- "c.relstorage, "
- "c.relacl, NULL as rrelacl, "
- "NULL AS initrelacl, NULL AS initrrelacl, "
- "c.relkind, "
- "c.relnamespace, "
- "(%s c.relowner) AS rolname, "
- "c.relchecks, c.relhastriggers, "
- "c.relhasindex, c.relhasrules, c.relhasoids, "
- "'f'::bool AS relrowsecurity, "
- "'f'::bool AS relforcerowsecurity, "
- "c.relfrozenxid, 0 AS relminmxid, tc.oid AS toid, "
- "tc.relfrozenxid AS tfrozenxid, "
- "0 AS tminmxid, "
- "c.relpersistence, 't' as relispopulated, "
- "'d' AS relreplident, c.relpages, "
- "NULL AS amname, "
+ "pl.parlevel as parlevel, ");
+
+ if (fout->remoteVersion >= 90100)
+ appendPQExpBufferStr(query,
"CASE WHEN c.relkind = 'f' THEN "
"(SELECT ftserver FROM pg_catalog.pg_foreign_table WHERE ftrelid = c.oid) "
- "ELSE 0 END AS foreignserver, "
- "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
- "d.refobjid AS owning_tab, "
- "d.refobjsubid AS owning_col, "
- "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
- "c.reloptions AS reloptions, "
- "tc.reloptions AS toast_reloptions, "
- "p.parrelid as parrelid, "
- "pl.parlevel as parlevel, "
- "NULL AS changed_acl, "
- "NULL AS partkeydef, "
- "false AS ispartition, "
- "NULL AS partbound "
- "FROM pg_class c "
- "LEFT JOIN pg_depend d ON "
- "(c.relkind = '%c' AND "
- "d.classid = c.tableoid AND d.objid = c.oid AND "
- "d.objsubid = 0 AND "
- "d.refclassid = c.tableoid AND d.deptype = 'a') "
- "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
- "LEFT JOIN pg_partition_rule pr ON c.oid = pr.parchildrelid "
- "LEFT JOIN pg_partition p ON pr.paroid = p.oid "
- "LEFT JOIN pg_partition pl ON (c.oid = pl.parrelid AND pl.parlevel = 0)"
- "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
- "AND c.relnamespace <> 7012 " /* BM_BITMAPINDEX_NAMESPACE */
- "AND c.oid NOT IN (SELECT p.parchildrelid FROM pg_partition_rule p LEFT "
- "JOIN pg_exttable e ON p.parchildrelid=e.reloid WHERE e.reloid IS NULL)"
- "ORDER BY c.oid",
- username_subquery,
- RELKIND_SEQUENCE,
- RELKIND_RELATION, RELKIND_SEQUENCE,
- RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
- RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
- }
- else if (fout->remoteVersion >= 90000)
- {
- /*
- * Left join to pick up dependency info linking sequences to their
- * owning column, if any (note this dependency is AUTO as of 8.2)
- */
- appendPQExpBuffer(query,
- "SELECT c.tableoid, c.oid, c.relname, "
- "c.relstorage, "
- "c.relacl, NULL as rrelacl, "
- "NULL AS initrelacl, NULL AS initrrelacl, "
- "c.relkind, "
- "c.relnamespace, "
- "(%s c.relowner) AS rolname, "
- "c.relchecks, c.relhastriggers, "
- "c.relhasindex, c.relhasrules, c.relhasoids, "
- "'f'::bool AS relrowsecurity, "
- "'f'::bool AS relforcerowsecurity, "
- "c.relfrozenxid, 0 AS relminmxid, tc.oid AS toid, "
- "tc.relfrozenxid AS tfrozenxid, "
- "0 AS tminmxid, "
- "'p' AS relpersistence, 't' as relispopulated, "
- "'d' AS relreplident, c.relpages, "
- "NULL AS amname, "
- "NULL AS foreignserver, "
- "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
- "d.refobjid AS owning_tab, "
- "d.refobjsubid AS owning_col, "
- "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
- "c.reloptions AS reloptions, "
- "tc.reloptions AS toast_reloptions, "
- "p.parrelid as parrelid, "
- "pl.parlevel as parlevel, "
- "NULL AS changed_acl, "
- "NULL AS partkeydef, "
- "false AS ispartition, "
- "NULL AS partbound "
- "FROM pg_class c "
- "LEFT JOIN pg_depend d ON "
- "(c.relkind = '%c' AND "
- "d.classid = c.tableoid AND d.objid = c.oid AND "
- "d.objsubid = 0 AND "
- "d.refclassid = c.tableoid AND d.deptype = 'a') "
- "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
- "LEFT JOIN pg_partition_rule pr ON c.oid = pr.parchildrelid "
- "LEFT JOIN pg_partition p ON pr.paroid = p.oid "
- "LEFT JOIN pg_partition pl ON (c.oid = pl.parrelid AND pl.parlevel = 0)"
- "WHERE c.relkind in ('%c', '%c', '%c', '%c') "
- "AND c.relnamespace <> 7012 " /* BM_BITMAPINDEX_NAMESPACE */
- "AND c.oid NOT IN (SELECT p.parchildrelid FROM pg_partition_rule p LEFT "
- "JOIN pg_exttable e ON p.parchildrelid=e.reloid WHERE e.reloid IS NULL)"
- "ORDER BY c.oid",
- username_subquery,
- RELKIND_SEQUENCE,
- RELKIND_RELATION, RELKIND_SEQUENCE,
- RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
- }
- else if (fout->remoteVersion >= 80400)
- {
- /*
- * Left join to pick up dependency info linking sequences to their
- * owning column, if any (note this dependency is AUTO as of 8.2)
- */
- appendPQExpBuffer(query,
- "SELECT c.tableoid, c.oid, c.relname, "
- "c.relacl, NULL as rrelacl, "
- "NULL AS initrelacl, NULL AS initrrelacl, "
- "c.relkind, "
- "c.relnamespace, "
- "(%s c.relowner) AS rolname, "
- "c.relchecks, c.relhastriggers, "
- "c.relhasindex, c.relhasrules, c.relhasoids, "
- "'f'::bool AS relrowsecurity, "
- "'f'::bool AS relforcerowsecurity, "
- "c.relfrozenxid, 0 AS relminmxid, tc.oid AS toid, "
- "tc.relfrozenxid AS tfrozenxid, "
- "0 AS tminmxid, "
- "'p' AS relpersistence, 't' as relispopulated, "
- "'d' AS relreplident, c.relpages, "
- "NULL AS amname, "
- "NULL AS foreignserver, "
- "NULL AS reloftype, "
- "d.refobjid AS owning_tab, "
- "d.refobjsubid AS owning_col, "
- "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
- "c.reloptions AS reloptions, "
- "tc.reloptions AS toast_reloptions, "
- "p.parrelid as parrelid, "
- "pl.parlevel as parlevel, "
- "NULL AS changed_acl, "
- "NULL AS partkeydef, "
- "false AS ispartition, "
- "NULL AS partbound "
- "FROM pg_class c "
- "LEFT JOIN pg_depend d ON "
- "(c.relkind = '%c' AND "
- "d.classid = c.tableoid AND d.objid = c.oid AND "
- "d.objsubid = 0 AND "
- "d.refclassid = c.tableoid AND d.deptype = 'a') "
- "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
- "LEFT JOIN pg_partition_rule pr ON c.oid = pr.parchildrelid "
- "LEFT JOIN pg_partition p ON pr.paroid = p.oid "
- "LEFT JOIN pg_partition pl ON (c.oid = pl.parrelid AND pl.parlevel = 0)"
- "WHERE c.relkind in ('%c', '%c', '%c', '%c') "
- "AND c.relnamespace <> 7012 " /* BM_BITMAPINDEX_NAMESPACE */
- "AND c.oid NOT IN (SELECT p.parchildrelid FROM pg_partition_rule p LEFT "
- "JOIN pg_exttable e ON p.parchildrelid=e.reloid WHERE e.reloid IS NULL)"
- "ORDER BY c.oid",
- username_subquery,
- RELKIND_SEQUENCE,
- RELKIND_RELATION, RELKIND_SEQUENCE,
- RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
- }
+ "ELSE 0 END AS foreignserver, ");
else
- {
- /*
- * Left join to pick up dependency info linking sequences to their
- * owning column, if any (note this dependency is AUTO as of 8.2)
- */
+ appendPQExpBufferStr(query,
+ "NULL AS foreignserver, ");
+
+ if (fout->remoteVersion >= 90600)
appendPQExpBuffer(query,
- "SELECT c.tableoid, c.oid, c.relname, "
- "c.relstorage, "
- "c.relacl, NULL as rrelacl, "
- "NULL AS initrelacl, NULL AS initrrelacl, "
- "c.relkind, "
- "c.relnamespace, "
- "(%s c.relowner) AS rolname, "
- "c.relchecks, (c.reltriggers <> 0) AS relhastriggers, "
- "c.relhasindex, c.relhasrules, c.relhasoids, "
- "'f'::bool AS relrowsecurity, "
- "'f'::bool AS relforcerowsecurity, "
- "c.relfrozenxid, 0 AS relminmxid, tc.oid AS toid, "
- "tc.relfrozenxid AS tfrozenxid, "
- "0 AS tminmxid, "
- "'p' AS relpersistence, 't' as relispopulated, "
- "'d' AS relreplident, c.relpages, "
- "NULL AS amname, "
- "NULL AS foreignserver, "
- "NULL AS reloftype, "
- "d.refobjid AS owning_tab, "
- "d.refobjsubid AS owning_col, "
- "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
- "c.reloptions AS reloptions, "
- "p.parrelid as parrelid, "
- "pl.parlevel as parlevel, "
- "NULL AS toast_reloptions, "
- "NULL AS changed_acl, "
- "NULL AS partkeydef, "
- "false AS ispartition, "
- "NULL AS partbound "
- "FROM pg_class c "
- "LEFT JOIN pg_depend d ON "
- "(c.relkind = '%c' AND "
- "d.classid = c.tableoid AND d.objid = c.oid AND "
- "d.objsubid = 0 AND "
- "d.refclassid = c.tableoid AND d.deptype = 'a') "
- "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
- "LEFT JOIN pg_partition_rule pr ON c.oid = pr.parchildrelid "
- "LEFT JOIN pg_partition p ON pr.paroid = p.oid "
- "LEFT JOIN pg_partition pl ON (c.oid = pl.parrelid AND pl.parlevel = 0) "
- "WHERE c.relkind in ('%c', '%c', '%c', '%c') "
- "AND c.oid NOT IN (select p.parchildrelid from pg_partition_rule p "
- "LEFT JOIN pg_exttable e on p.parchildrelid=e.reloid where e.reloid is null) "
- "AND c.relnamespace <> 3012 " /* BM_BITMAPINDEX_NAMESPACE in GPDB 5 and below */
- "ORDER BY c.oid",
- username_subquery,
- RELKIND_SEQUENCE,
- RELKIND_RELATION, RELKIND_SEQUENCE,
- RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
- }
+ "c.relisivm AS isivm, %s",
+ (fout->version.type == Cloudberry && fout->version.version >= 2) ?
+ "c.relisdynamic AS isdynamic, " : "false AS isdynamic, ");
+ else
+ appendPQExpBufferStr(query, "false as isivm, false as isdynamic, ");
+
+ if (fout->remoteVersion >= 90200)
+ appendPQExpBufferStr(query,
+ "c.relacl, "
+ "acldefault(CASE WHEN c.relkind = " CppAsString2(RELKIND_SEQUENCE)
+ " THEN 's'::\"char\" ELSE 'r'::\"char\" END, c.relowner) AS acldefault, ");
+ else
+ appendPQExpBufferStr(query,
+ "c.relacl, NULL AS acldefault, ");
+
+ if (fout->remoteVersion >= 100000)
+ appendPQExpBufferStr(query,
+ "c.relispartition AS ispartition ");
+ else
+ appendPQExpBufferStr(query,
+ "false AS ispartition ");
+
+ /*
+ * Left join to pg_depend to pick up dependency info linking sequences to
+ * their owning column, if any (note this dependency is AUTO as of 8.2).
+ * Also join to pg_tablespace to collect the spcname.
+ */
+ appendPQExpBufferStr(query,
+ "\nFROM pg_class c\n"
+ "LEFT JOIN pg_depend d ON "
+ "(c.relkind = " CppAsString2(RELKIND_SEQUENCE) " AND "
+ "d.classid = 'pg_class'::regclass AND d.objid = c.oid AND "
+ "d.objsubid = 0 AND "
+ "d.refclassid = 'pg_class'::regclass AND d.deptype IN ('a', 'i'))\n"
+ "LEFT JOIN pg_tablespace tsp ON (tsp.oid = c.reltablespace)\n");
+
+ /*
+ * In 9.6 and up, left join to pg_am to pick up the amname.
+ */
+ if (fout->remoteVersion >= 90600)
+ appendPQExpBufferStr(query,
+ "LEFT JOIN pg_am am ON (c.relam = am.oid)\n");
+
+ /*
+ *
+ * We purposefully ignore toast OIDs for partitioned tables; the reason is
+ * that versions 10 and 11 have them, but later versions do not, so
+ * emitting them causes the upgrade to fail.
+ */
+
+ appendPQExpBufferStr(query,
+ "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid"
+ " AND tc.relkind = " CppAsString2(RELKIND_TOASTVALUE)
+ " AND c.relkind <> " CppAsString2(RELKIND_PARTITIONED_TABLE) ")\n");
+
+ if (fout->remoteVersion < GPDB7_MAJOR_PGVERSION)
+ appendPQExpBufferStr(query,
+ "LEFT JOIN pg_partition_rule pr ON c.oid = pr.parchildrelid\n"
+ "LEFT JOIN pg_partition p ON pr.paroid = p.oid\n"
+ "LEFT JOIN pg_partition pl ON (c.oid = pl.parrelid AND pl.parlevel = 0)\n");
+
+ /*
+ * Restrict to interesting relkinds (in particular, not indexes). Not all
+ * relkinds are possible in older servers, but it's not worth the trouble
+ * to emit a version-dependent list.
+ *
+ * Composite-type table entries won't be dumped as such, but we have to
+ * make a DumpableObject for them so that we can track dependencies of the
+ * composite type (pg_depend entries for columns of the composite type
+ * link to the pg_class entry not the pg_type entry).
+ */
+ appendPQExpBufferStr(query,
+ "WHERE c.relkind IN ("
+ CppAsString2(RELKIND_RELATION) ", "
+ CppAsString2(RELKIND_SEQUENCE) ", "
+ CppAsString2(RELKIND_VIEW) ", "
+ CppAsString2(RELKIND_COMPOSITE_TYPE) ", "
+ CppAsString2(RELKIND_MATVIEW) ", "
+ CppAsString2(RELKIND_FOREIGN_TABLE) ", "
+ CppAsString2(RELKIND_PARTITIONED_TABLE) ")\n");
+
+
+ if (fout->remoteVersion >= 80400)
+ appendPQExpBufferStr(query,
+ "AND c.relnamespace <> 7012\n"); /* BM_BITMAPINDEX_NAMESPACE */
+ else
+ appendPQExpBufferStr(query,
+ "AND c.relnamespace <> 3012\n"); /* BM_BITMAPINDEX_NAMESPACE in GPDB 5 and below */
+
+ appendPQExpBufferStr(query,
+ "ORDER BY c.oid");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -7907,48 +7375,44 @@ getTables(Archive *fout, int *numTables)
i_reloid = PQfnumber(res, "oid");
i_relname = PQfnumber(res, "relname");
i_relnamespace = PQfnumber(res, "relnamespace");
- i_relacl = PQfnumber(res, "relacl");
- i_rrelacl = PQfnumber(res, "rrelacl");
- i_initrelacl = PQfnumber(res, "initrelacl");
- i_initrrelacl = PQfnumber(res, "initrrelacl");
i_relkind = PQfnumber(res, "relkind");
- i_relstorage = PQfnumber(res, "relstorage");
- i_rolname = PQfnumber(res, "rolname");
+ i_reltype = PQfnumber(res, "reltype");
+ i_relowner = PQfnumber(res, "relowner");
i_relchecks = PQfnumber(res, "relchecks");
- i_relhastriggers = PQfnumber(res, "relhastriggers");
i_relhasindex = PQfnumber(res, "relhasindex");
i_relhasrules = PQfnumber(res, "relhasrules");
- i_relrowsec = PQfnumber(res, "relrowsecurity");
- i_relforcerowsec = PQfnumber(res, "relforcerowsecurity");
- i_relhasoids = PQfnumber(res, "relhasoids");
- i_relfrozenxid = PQfnumber(res, "relfrozenxid");
- i_relminmxid = PQfnumber(res, "relminmxid");
- i_toastoid = PQfnumber(res, "toid");
- i_toastfrozenxid = PQfnumber(res, "tfrozenxid");
- i_toastminmxid = PQfnumber(res, "tminmxid");
- i_relpersistence = PQfnumber(res, "relpersistence");
- i_relispopulated = PQfnumber(res, "relispopulated");
- i_relreplident = PQfnumber(res, "relreplident");
i_relpages = PQfnumber(res, "relpages");
i_foreignserver = PQfnumber(res, "foreignserver");
i_owning_tab = PQfnumber(res, "owning_tab");
i_owning_col = PQfnumber(res, "owning_col");
i_reltablespace = PQfnumber(res, "reltablespace");
+ i_relhasoids = PQfnumber(res, "relhasoids");
+ i_relhastriggers = PQfnumber(res, "relhastriggers");
+ i_relpersistence = PQfnumber(res, "relpersistence");
+ i_relispopulated = PQfnumber(res, "relispopulated");
+ i_relreplident = PQfnumber(res, "relreplident");
+ i_relrowsec = PQfnumber(res, "relrowsecurity");
+ i_relforcerowsec = PQfnumber(res, "relforcerowsecurity");
+ i_relfrozenxid = PQfnumber(res, "relfrozenxid");
+ i_toastfrozenxid = PQfnumber(res, "tfrozenxid");
+ i_toastoid = PQfnumber(res, "toid");
+ i_relminmxid = PQfnumber(res, "relminmxid");
+ i_toastminmxid = PQfnumber(res, "tminmxid");
i_reloptions = PQfnumber(res, "reloptions");
i_checkoption = PQfnumber(res, "checkoption");
i_toastreloptions = PQfnumber(res, "toast_reloptions");
i_reloftype = PQfnumber(res, "reloftype");
- i_parrelid = PQfnumber(res, "parrelid");
- i_parlevel = PQfnumber(res, "parlevel");
+ i_amname = PQfnumber(res, "amname");
i_is_identity_sequence = PQfnumber(res, "is_identity_sequence");
- i_changed_acl = PQfnumber(res, "changed_acl");
- i_partkeydef = PQfnumber(res, "partkeydef");
+ i_relacl = PQfnumber(res, "relacl");
+ i_acldefault = PQfnumber(res, "acldefault");
i_ispartition = PQfnumber(res, "ispartition");
- i_partbound = PQfnumber(res, "partbound");
- i_amname = PQfnumber(res, "amname");
i_amoid = PQfnumber(res, "amoid");
i_isivm = PQfnumber(res, "isivm");
i_isdynamic = PQfnumber(res, "isdynamic");
+ i_relstorage = PQfnumber(res, "relstorage");
+ i_parrelid = PQfnumber(res, "parrelid");
+ i_parlevel = PQfnumber(res, "parlevel");
if (dopt->lockWaitTimeout)
{
@@ -7976,33 +7440,17 @@ getTables(Archive *fout, int *numTables)
tblinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_relname));
tblinfo[i].dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_relnamespace)));
- tblinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
- tblinfo[i].relacl = pg_strdup(PQgetvalue(res, i, i_relacl));
- tblinfo[i].rrelacl = pg_strdup(PQgetvalue(res, i, i_rrelacl));
- tblinfo[i].initrelacl = pg_strdup(PQgetvalue(res, i, i_initrelacl));
- tblinfo[i].initrrelacl = pg_strdup(PQgetvalue(res, i, i_initrrelacl));
+ tblinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_relacl));
+ tblinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
+ tblinfo[i].dacl.privtype = 0;
+ tblinfo[i].dacl.initprivs = NULL;
tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
- tblinfo[i].relstorage = *(PQgetvalue(res, i, i_relstorage));
- tblinfo[i].relpersistence = *(PQgetvalue(res, i, i_relpersistence));
+ tblinfo[i].reltype = atooid(PQgetvalue(res, i, i_reltype));
+ tblinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_relowner));
+ tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0);
tblinfo[i].hasrules = (strcmp(PQgetvalue(res, i, i_relhasrules), "t") == 0);
- tblinfo[i].hastriggers = (strcmp(PQgetvalue(res, i, i_relhastriggers), "t") == 0);
- tblinfo[i].rowsec = (strcmp(PQgetvalue(res, i, i_relrowsec), "t") == 0);
- tblinfo[i].forcerowsec = (strcmp(PQgetvalue(res, i, i_relforcerowsec), "t") == 0);
- tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
- tblinfo[i].relispopulated = (strcmp(PQgetvalue(res, i, i_relispopulated), "t") == 0);
- tblinfo[i].relreplident = *(PQgetvalue(res, i, i_relreplident));
tblinfo[i].relpages = atoi(PQgetvalue(res, i, i_relpages));
- tblinfo[i].frozenxid = atooid(PQgetvalue(res, i, i_relfrozenxid));
- tblinfo[i].minmxid = atooid(PQgetvalue(res, i, i_relminmxid));
- tblinfo[i].toast_oid = atooid(PQgetvalue(res, i, i_toastoid));
- tblinfo[i].toast_frozenxid = atooid(PQgetvalue(res, i, i_toastfrozenxid));
- tblinfo[i].toast_minmxid = atooid(PQgetvalue(res, i, i_toastminmxid));
- if (PQgetisnull(res, i, i_reloftype))
- tblinfo[i].reloftype = NULL;
- else
- tblinfo[i].reloftype = pg_strdup(PQgetvalue(res, i, i_reloftype));
- tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
if (PQgetisnull(res, i, i_owning_tab))
{
tblinfo[i].owning_tab = InvalidOid;
@@ -8014,14 +7462,42 @@ getTables(Archive *fout, int *numTables)
tblinfo[i].owning_col = atoi(PQgetvalue(res, i, i_owning_col));
}
tblinfo[i].reltablespace = pg_strdup(PQgetvalue(res, i, i_reltablespace));
+ tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
+ tblinfo[i].hastriggers = (strcmp(PQgetvalue(res, i, i_relhastriggers), "t") == 0);
+ tblinfo[i].relpersistence = *(PQgetvalue(res, i, i_relpersistence));
+ tblinfo[i].relispopulated = (strcmp(PQgetvalue(res, i, i_relispopulated), "t") == 0);
+ tblinfo[i].relreplident = *(PQgetvalue(res, i, i_relreplident));
+ tblinfo[i].rowsec = (strcmp(PQgetvalue(res, i, i_relrowsec), "t") == 0);
+ tblinfo[i].forcerowsec = (strcmp(PQgetvalue(res, i, i_relforcerowsec), "t") == 0);
+ tblinfo[i].frozenxid = atooid(PQgetvalue(res, i, i_relfrozenxid));
+ tblinfo[i].toast_frozenxid = atooid(PQgetvalue(res, i, i_toastfrozenxid));
+ tblinfo[i].toast_oid = atooid(PQgetvalue(res, i, i_toastoid));
+ tblinfo[i].minmxid = atooid(PQgetvalue(res, i, i_relminmxid));
+ tblinfo[i].toast_minmxid = atooid(PQgetvalue(res, i, i_toastminmxid));
tblinfo[i].reloptions = pg_strdup(PQgetvalue(res, i, i_reloptions));
- if (i_checkoption == -1 || PQgetisnull(res, i, i_checkoption))
+ if (PQgetisnull(res, i, i_checkoption))
tblinfo[i].checkoption = NULL;
else
tblinfo[i].checkoption = pg_strdup(PQgetvalue(res, i, i_checkoption));
tblinfo[i].toast_reloptions = pg_strdup(PQgetvalue(res, i, i_toastreloptions));
tblinfo[i].parrelid = atooid(PQgetvalue(res, i, i_parrelid));
- if (tblinfo[i].parrelid != 0)
+ tblinfo[i].reloftype = atooid(PQgetvalue(res, i, i_reloftype));
+ if (PQgetisnull(res, i, i_amname))
+ tblinfo[i].amname = NULL;
+ else
+ tblinfo[i].amname = pg_strdup(PQgetvalue(res, i, i_amname));
+ tblinfo[i].is_identity_sequence = (strcmp(PQgetvalue(res, i, i_is_identity_sequence), "t") == 0);
+ tblinfo[i].ispartition = (strcmp(PQgetvalue(res, i, i_ispartition), "t") == 0);
+
+ tblinfo[i].relstorage = *(PQgetvalue(res, i, i_relstorage));
+
+ if (PQgetisnull(res, i, i_parlevel) ||
+ atoi(PQgetvalue(res, i, i_parlevel)) > 0)
+ tblinfo[i].parparent = false;
+ else
+ tblinfo[i].parparent = true;
+
+ if (!tblinfo[i].parparent && tblinfo[i].parrelid != 0 && tblinfo[i].relstorage == 'x')
{
/*
* Length of tmpStr is bigger than the sum of NAMEDATALEN
@@ -8031,15 +7507,6 @@ getTables(Archive *fout, int *numTables)
snprintf(tmpStr, sizeof(tmpStr), "%s%s", tblinfo[i].dobj.name, EXT_PARTITION_NAME_POSTFIX);
tblinfo[i].dobj.name = pg_strdup(tmpStr);
}
- if (PQgetisnull(res, i, i_parlevel) ||
- atoi(PQgetvalue(res, i, i_parlevel)) > 0)
- tblinfo[i].parparent = false;
- else
- tblinfo[i].parparent = true;
- if (PQgetisnull(res, i, i_amname))
- tblinfo[i].amname = NULL;
- else
- tblinfo[i].amname = pg_strdup(PQgetvalue(res, i, i_amname));
if (PQgetisnull(res, i, i_amoid))
tblinfo[i].amoid = InvalidOid;
@@ -8049,45 +7516,52 @@ getTables(Archive *fout, int *numTables)
/* other fields were zeroed above */
/*
- * Decide whether we want to dump this table.
+ * GPDB5/6: To gather binary upgrade information for GP partition children,
+ * they need to exist in the tblinfo array for findTableByOid.
+ * This requires the getTable query to also collect all
+ * partition children so they can be referenced, but we do not want
+ * to dump the partition children as their DDL will be handled by the parent.
*/
- if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
+ if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE || tblinfo[i].parrelid != 0)
tblinfo[i].dobj.dump = DUMP_COMPONENT_NONE;
else
selectDumpableTable(&tblinfo[i], fout);
/*
- * If the table-level and all column-level ACLs for this table are
- * unchanged, then we don't need to worry about including the ACLs for
- * this table. If any column-level ACLs have been changed, the
- * 'changed_acl' column from the query will indicate that.
+ * Now, consider the table "interesting" if we need to dump its
+ * definition or its data. Later on, we'll skip a lot of data
+ * collection for uninteresting tables.
*
- * This can result in a significant performance improvement in cases
- * where we are only looking to dump out the ACL (eg: pg_catalog).
+ * Note: the "interesting" flag will also be set by flagInhTables for
+ * parents of interesting tables, so that we collect necessary
+ * inheritance info even when the parents are not themselves being
+ * dumped. This is the main reason why we need an "interesting" flag
+ * that's separate from the components-to-dump bitmask.
*/
- if (PQgetisnull(res, i, i_relacl) && PQgetisnull(res, i, i_rrelacl) &&
- PQgetisnull(res, i, i_initrelacl) &&
- PQgetisnull(res, i, i_initrrelacl) &&
- strcmp(PQgetvalue(res, i, i_changed_acl), "f") == 0)
- tblinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ tblinfo[i].interesting = (tblinfo[i].dobj.dump &
+ (DUMP_COMPONENT_DEFINITION |
+ DUMP_COMPONENT_DATA)) != 0;
- tblinfo[i].interesting = tblinfo[i].dobj.dump ? true : false;
tblinfo[i].dummy_view = false; /* might get set during sort */
tblinfo[i].postponed_def = false; /* might get set during sort */
-
+
tblinfo[i].is_identity_sequence = (i_is_identity_sequence >= 0 &&
strcmp(PQgetvalue(res, i, i_is_identity_sequence), "t") == 0);
- /* Partition key string or NULL */
- tblinfo[i].partkeydef = pg_strdup(PQgetvalue(res, i, i_partkeydef));
- tblinfo[i].ispartition = (strcmp(PQgetvalue(res, i, i_ispartition), "t") == 0);
- tblinfo[i].partbound = pg_strdup(PQgetvalue(res, i, i_partbound));
tblinfo[i].isivm = (strcmp(PQgetvalue(res, i, i_isivm), "t") == 0);
tblinfo[i].isdynamic = (strcmp(PQgetvalue(res, i, i_isdynamic), "t") == 0);
/* foreign server */
tblinfo[i].foreign_server = atooid(PQgetvalue(res, i, i_foreignserver));
+ /* Tables have data */
+ tblinfo[i].dobj.components |= DUMP_COMPONENT_DATA;
+
+ /* Mark whether table has an ACL */
+ if (!PQgetisnull(res, i, i_relacl))
+ tblinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
+ tblinfo[i].hascolumnACLs = false; /* may get set later */
+
/*
* Read-lock target tables to make sure they aren't DROPPED or altered
* in schema before we get around to dumping them.
@@ -8102,18 +7576,17 @@ getTables(Archive *fout, int *numTables)
*
* We only need to lock the table for certain components; see
* pg_dump.h
- *
+ *
* GPDB: Build a single LOCK TABLE statement to lock all interesting tables.
* This is more performant than issuing a separate LOCK TABLE statement for each table,
* with considerable savings in FE/BE overhead. It does come at the cost of some increased
* memory usage in both FE and BE, which we will be able to tolerate.
*/
+
/* GPDB_14_MERGE_FIXME: GPDB_96_MERGE_FIXME: Is the parrelid check still needed? */
- if (tblinfo[i].dobj.dump &&
+ if ((tblinfo[i].dobj.dump & DUMP_COMPONENTS_REQUIRING_LOCK) &&
(tblinfo[i].relkind == RELKIND_RELATION ||
- tblinfo[i].relkind == RELKIND_PARTITIONED_TABLE) &&
- tblinfo[i].parrelid == 0 &&
- (tblinfo[i].dobj.dump & DUMP_COMPONENTS_REQUIRING_LOCK))
+ tblinfo[i].relkind == RELKIND_PARTITIONED_TABLE))
{
if (!lockTableDumped)
appendPQExpBuffer(query,
@@ -8125,11 +7598,6 @@ getTables(Archive *fout, int *numTables)
fmtQualifiedDumpable(&tblinfo[i]));
lockTableDumped = true;
}
-
- /* Emit notice if join for owner failed */
- if (strlen(tblinfo[i].rolname) == 0)
- pg_log_warning("owner of table \"%s\" appears to be invalid",
- tblinfo[i].dobj.name);
}
/* Are there any tables to lock? */
if (lockTableDumped)
@@ -8292,43 +7760,126 @@ getPartitioningInfo(Archive *fout)
if (fout->dopt->schemaOnly)
return;
- query = createPQExpBuffer();
+ query = createPQExpBuffer();
+
+ /*
+ * Unsafe partitioning schemes are exactly those for which hash enum_ops
+ * appears among the partition opclasses. We needn't check partstrat.
+ *
+ * Note that this query may well retrieve info about tables we aren't
+ * going to dump and hence have no lock on. That's okay since we need not
+ * invoke any unsafe server-side functions.
+ */
+ appendPQExpBufferStr(query,
+ "SELECT partrelid FROM pg_partitioned_table WHERE\n"
+ "(SELECT c.oid FROM pg_opclass c JOIN pg_am a "
+ "ON c.opcmethod = a.oid\n"
+ "WHERE opcname = 'enum_ops' "
+ "AND opcnamespace = 'pg_catalog'::regnamespace "
+ "AND amname = 'hash') = ANY(partclass)");
+
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+
+ ntups = PQntuples(res);
+
+ for (int i = 0; i < ntups; i++)
+ {
+ Oid tabrelid = atooid(PQgetvalue(res, i, 0));
+ TableInfo *tbinfo;
+
+ tbinfo = findTableByOid(tabrelid);
+ if (tbinfo == NULL)
+ fatal("failed sanity check, table OID %u appearing in pg_partitioned_table not found",
+ tabrelid);
+ tbinfo->unsafe_partitions = true;
+ }
+
+ PQclear(res);
+
+ destroyPQExpBuffer(query);
+}
+
+/*
+ * getPartitionDefs
+ * get information about GPDB partition definitions on a dumpable table
+ */
+
+void
+getPartitionDefs(Archive *fout, TableInfo tblinfo[], int numTables)
+{
+
+ PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer tbloids = createPQExpBuffer();
+ PGresult *res;
+ int ntups;
+ int i_oid;
+ int i_partclause;
+ int i_parttemplate;
+
+ /* Only relevant for GP5/GP6 */
+ if (fout->remoteVersion > GPDB6_MAJOR_PGVERSION)
+ return;
+
+ /*
+ * We want to perform just one query against pg_class.
+ * However, we mustn't try to select every row of those catalogs and then
+ * sort it out on the client side, because some of the server-side functions
+ * we need would be unsafe to apply to tables we don't have lock on.
+ * Hence, we build an array of the OIDs of tables we care about
+ * (and now have lock on!), and use a WHERE clause to constrain which rows are selected.
+ */
+ appendPQExpBufferChar(tbloids, '{');
+ for (int i = 0; i < numTables; i++)
+ {
+ TableInfo *tbinfo = &tblinfo[i];
+
+ /* We're only interested in dumping the partition definition for parent partitions */
+ if (!tbinfo->parparent)
+ continue;
+
+ /*
+ * We can ignore uninteresting tables, i.e. tables that will not be dumped.
+ */
+ if (!tbinfo->interesting)
+ continue;
+
+ /* OK, we need info for this table */
+ if (tbloids->len > 1) /* do we have more than the '{'? */
+ appendPQExpBufferChar(tbloids, ',');
+ appendPQExpBuffer(tbloids, "%u", tbinfo->dobj.catId.oid);
+ }
- /*
- * Unsafe partitioning schemes are exactly those for which hash enum_ops
- * appears among the partition opclasses. We needn't check partstrat.
- *
- * Note that this query may well retrieve info about tables we aren't
- * going to dump and hence have no lock on. That's okay since we need not
- * invoke any unsafe server-side functions.
- */
- appendPQExpBufferStr(query,
- "SELECT partrelid FROM pg_partitioned_table WHERE\n"
- "(SELECT c.oid FROM pg_opclass c JOIN pg_am a "
- "ON c.opcmethod = a.oid\n"
- "WHERE opcname = 'enum_ops' "
- "AND opcnamespace = 'pg_catalog'::regnamespace "
- "AND amname = 'hash') = ANY(partclass)");
+ appendPQExpBufferChar(tbloids, '}');
+ resetPQExpBuffer(query);
+
+ appendPQExpBuffer(query,
+ "SELECT src.oid,\n"
+ "(SELECT pg_get_partition_def(src.oid, true, true)) AS partclause,\n"
+ "(SELECT pg_get_partition_template_def(src.oid, true, true)) AS parttemplate\n"
+ "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n", tbloids->data);
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
+
+ i_oid = PQfnumber(res, "oid");
+ i_partclause = PQfnumber(res, "partclause");
+ i_parttemplate = PQfnumber(res, "parttemplate");
for (int i = 0; i < ntups; i++)
{
- Oid tabrelid = atooid(PQgetvalue(res, i, 0));
- TableInfo *tbinfo;
+ TableInfo *tbinfo = findTableByOid(atooid(PQgetvalue(res, i, i_oid)));
+ if (tblinfo)
+ {
+ tbinfo->partclause = pg_strdup(PQgetvalue(res, i, i_partclause));
+ tbinfo->parttemplate = pg_strdup(PQgetvalue(res, i, i_parttemplate));
+ }
- tbinfo = findTableByOid(tabrelid);
- if (tbinfo == NULL)
- fatal("failed sanity check, table OID %u appearing in pg_partitioned_table not found",
- tabrelid);
- tbinfo->unsafe_partitions = true;
}
-
PQclear(res);
destroyPQExpBuffer(query);
+ destroyPQExpBuffer(tbloids);
}
/*
@@ -8341,13 +7892,15 @@ getPartitioningInfo(Archive *fout)
void
getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
{
- int i,
- j;
PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer tbloids = createPQExpBuffer();
PGresult *res;
+ int ntups;
+ int curtblindx;
IndxInfo *indxinfo;
int i_tableoid,
i_oid,
+ i_indrelid,
i_indexname,
i_parentidx,
i_indexdef,
@@ -8367,9 +7920,17 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
i_indreloptions,
i_indstatcols,
i_indstatvals;
- int ntups;
- for (i = 0; i < numTables; i++)
+ /*
+ * We want to perform just one query against pg_index. However, we
+ * mustn't try to select every row of the catalog and then sort it out on
+ * the client side, because some of the server-side functions we need
+ * would be unsafe to apply to tables we don't have lock on. Hence, we
+ * build an array of the OIDs of tables we care about (and now have lock
+ * on!), and use a WHERE clause to constrain which rows are selected.
+ */
+ appendPQExpBufferChar(tbloids, '{');
+ for (int i = 0; i < numTables; i++)
{
TableInfo *tbinfo = &tblinfo[i];
@@ -8377,208 +7938,187 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
continue;
/*
- * Ignore indexes of tables whose definitions are not to be dumped.
- *
- * We also need indexes on partitioned tables which have partitions to
- * be dumped, in order to dump the indexes on the partitions.
+ * We can ignore indexes of uninteresting tables.
*/
- if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) &&
- !tbinfo->interesting)
+ if (!tbinfo->interesting)
continue;
- pg_log_info("reading indexes for table \"%s.%s\"",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
+ /* OK, we need info for this table */
+ if (tbloids->len > 1) /* do we have more than the '{'? */
+ appendPQExpBufferChar(tbloids, ',');
+ appendPQExpBuffer(tbloids, "%u", tbinfo->dobj.catId.oid);
+ }
+ appendPQExpBufferChar(tbloids, '}');
+
+ resetPQExpBuffer(query);
+
+ appendPQExpBuffer(query,
+ "SELECT t.tableoid, t.oid, i.indrelid, "
+ "t.relname AS indexname, "
+ "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
+ "i.indkey, i.indisclustered, "
+ "c.contype, c.conname, "
+ "c.condeferrable, c.condeferred, "
+ "c.tableoid AS contableoid, "
+ "c.oid AS conoid, "
+ "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
+ "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
+ "t.reloptions AS indreloptions, ");
+
+
+ if (fout->remoteVersion >= 90400)
+ appendPQExpBuffer(query,
+ "i.indisreplident, ");
+ else
+ appendPQExpBuffer(query,
+ "false AS indisreplident, ");
+
+ if (fout->remoteVersion >= 110000)
+ appendPQExpBuffer(query,
+ "inh.inhparent AS parentidx, "
+ "i.indnkeyatts AS indnkeyatts, "
+ "i.indnatts AS indnatts, "
+ "(SELECT pg_catalog.array_agg(attnum ORDER BY attnum) "
+ " FROM pg_catalog.pg_attribute "
+ " WHERE attrelid = i.indexrelid AND "
+ " attstattarget >= 0) AS indstatcols, "
+ "(SELECT pg_catalog.array_agg(attstattarget ORDER BY attnum) "
+ " FROM pg_catalog.pg_attribute "
+ " WHERE attrelid = i.indexrelid AND "
+ " attstattarget >= 0) AS indstatvals ");
+ else
+ appendPQExpBuffer(query,
+ "0 AS parentidx, "
+ "i.indnatts AS indnkeyatts, "
+ "i.indnatts AS indnatts, "
+ "'' AS indstatcols, "
+ "'' AS indstatvals ");
+ appendPQExpBuffer(query,
+ "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
+ "JOIN pg_catalog.pg_index i ON (src.tbloid = i.indrelid) "
+ "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) ",
+ tbloids->data);
+ /*
+ * The point of the messy-looking outer join is to find a constraint that
+ * is related by an internal dependency link to the index. If we find one,
+ * create a CONSTRAINT entry linked to the INDEX entry. We assume an
+ * index won't have more than one internal dependency.
+ *
+ * As of 9.0 we don't need to look at pg_depend but can check for a match
+ * to pg_constraint.conindid. The check on conrelid is redundant but
+ * useful because that column is indexed while conindid is not.
+ */
+ if (fout->remoteVersion >= 110000)
+ {
+ appendPQExpBuffer(query,
+ "JOIN pg_catalog.pg_class t2 ON (t2.oid = i.indrelid) "
+ "LEFT JOIN pg_catalog.pg_constraint c "
+ "ON (i.indrelid = c.conrelid AND "
+ "i.indexrelid = c.conindid AND "
+ "c.contype IN ('p','u','x')) "
+ "LEFT JOIN pg_catalog.pg_inherits inh "
+ "ON (inh.inhrelid = indexrelid) "
+ "WHERE (i.indisvalid OR t2.relkind = 'p') "
+ "AND i.indisready "
+ "ORDER BY i.indrelid, indexname");
+ }
+ else if (fout->remoteVersion >= 90400)
+ {
/*
- * The point of the messy-looking outer join is to find a constraint
- * that is related by an internal dependency link to the index. If we
- * find one, create a CONSTRAINT entry linked to the INDEX entry. We
- * assume an index won't have more than one internal dependency.
- *
- * As of 9.0 we don't need to look at pg_depend but can check for a
- * match to pg_constraint.conindid. The check on conrelid is
- * redundant but useful because that column is indexed while conindid
- * is not.
+ * the test on indisready is necessary in 9.2, and harmless in
+ * earlier/later versions
*/
- resetPQExpBuffer(query);
- if (fout->remoteVersion >= 110000)
- {
- appendPQExpBuffer(query,
- "SELECT t.tableoid, t.oid, "
- "t.relname AS indexname, "
- "inh.inhparent AS parentidx, "
- "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
- "i.indnkeyatts AS indnkeyatts, "
- "i.indnatts AS indnatts, "
- "i.indkey, i.indisclustered, "
- "i.indisreplident, "
- "c.contype, c.conname, "
- "c.condeferrable, c.condeferred, "
- "c.tableoid AS contableoid, "
- "c.oid AS conoid, "
- "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
- "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
- "t.reloptions AS indreloptions, "
- "(SELECT pg_catalog.array_agg(attnum ORDER BY attnum) "
- " FROM pg_catalog.pg_attribute "
- " WHERE attrelid = i.indexrelid AND "
- " attstattarget >= 0) AS indstatcols,"
- "(SELECT pg_catalog.array_agg(attstattarget ORDER BY attnum) "
- " FROM pg_catalog.pg_attribute "
- " WHERE attrelid = i.indexrelid AND "
- " attstattarget >= 0) AS indstatvals "
- "FROM pg_catalog.pg_index i "
- "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
- "JOIN pg_catalog.pg_class t2 ON (t2.oid = i.indrelid) "
- "LEFT JOIN pg_catalog.pg_constraint c "
- "ON (i.indrelid = c.conrelid AND "
- "i.indexrelid = c.conindid AND "
- "c.contype IN ('p','u','x')) "
- "LEFT JOIN pg_catalog.pg_inherits inh "
- "ON (inh.inhrelid = indexrelid) "
- "WHERE i.indrelid = '%u'::pg_catalog.oid "
- "AND (i.indisvalid OR t2.relkind = 'p') "
- "AND i.indisready "
- "ORDER BY indexname",
- tbinfo->dobj.catId.oid);
- }
- else if (fout->remoteVersion >= 90400)
- {
- /*
- * the test on indisready is necessary in 9.2, and harmless in
- * earlier/later versions
- */
- appendPQExpBuffer(query,
- "SELECT t.tableoid, t.oid, "
- "t.relname AS indexname, "
- "0 AS parentidx, "
- "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
- "i.indnatts AS indnkeyatts, "
- "i.indnatts AS indnatts, "
- "i.indkey, i.indisclustered, "
- "i.indisreplident, "
- "c.contype, c.conname, "
- "c.condeferrable, c.condeferred, "
- "c.tableoid AS contableoid, "
- "c.oid AS conoid, "
- "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
- "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
- "t.reloptions AS indreloptions, "
- "'' AS indstatcols, "
- "'' AS indstatvals "
- "FROM pg_catalog.pg_index i "
- "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
- "LEFT JOIN pg_catalog.pg_constraint c "
- "ON (i.indrelid = c.conrelid AND "
- "i.indexrelid = c.conindid AND "
- "c.contype IN ('p','u','x')) "
- "WHERE i.indrelid = '%u'::pg_catalog.oid "
- "AND i.indisvalid AND i.indisready "
- "ORDER BY indexname",
- tbinfo->dobj.catId.oid);
- }
- else if (fout->remoteVersion >= 90000)
- {
- /*
- * the test on indisready is necessary in 9.2, and harmless in
- * earlier/later versions
- */
- appendPQExpBuffer(query,
- "SELECT t.tableoid, t.oid, "
- "t.relname AS indexname, "
- "0 AS parentidx, "
- "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
- "i.indnatts AS indnkeyatts, "
- "i.indnatts AS indnatts, "
- "i.indkey, i.indisclustered, "
- "false AS indisreplident, "
- "c.contype, c.conname, "
- "c.condeferrable, c.condeferred, "
- "c.tableoid AS contableoid, "
- "c.oid AS conoid, "
- "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
- "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
- "t.reloptions AS indreloptions, "
- "'' AS indstatcols, "
- "'' AS indstatvals "
- "FROM pg_catalog.pg_index i "
- "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
- "LEFT JOIN pg_catalog.pg_constraint c "
- "ON (i.indrelid = c.conrelid AND "
- "i.indexrelid = c.conindid AND "
- "c.contype IN ('p','u','x')) "
- "WHERE i.indrelid = '%u'::pg_catalog.oid "
- "AND i.indisvalid AND i.indisready "
- "ORDER BY indexname",
- tbinfo->dobj.catId.oid);
- }
- else
- {
- appendPQExpBuffer(query,
- "SELECT t.tableoid, t.oid, "
- "t.relname AS indexname, "
- "0 AS parentidx, "
- "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
- "i.indnatts AS indnkeyatts, "
- "i.indnatts AS indnatts, "
- "i.indkey, i.indisclustered, "
- "false AS indisreplident, "
- "c.contype, c.conname, "
- "c.condeferrable, c.condeferred, "
- "c.tableoid AS contableoid, "
- "c.oid AS conoid, "
- "null AS condef, "
- "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
- "t.reloptions AS indreloptions, "
- "'' AS indstatcols, "
- "'' AS indstatvals "
- "FROM pg_catalog.pg_index i "
- "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
- "LEFT JOIN pg_catalog.pg_depend d "
- "ON (d.classid = t.tableoid "
- "AND d.objid = t.oid "
- "AND d.deptype = 'i') "
- "LEFT JOIN pg_catalog.pg_constraint c "
- "ON (d.refclassid = c.tableoid "
- "AND d.refobjid = c.oid) "
- "WHERE i.indrelid = '%u'::pg_catalog.oid "
- "AND i.indisvalid "
- "ORDER BY indexname",
- tbinfo->dobj.catId.oid);
- }
+ appendPQExpBuffer(query,
+ "LEFT JOIN pg_catalog.pg_constraint c "
+ "ON (i.indrelid = c.conrelid AND "
+ "i.indexrelid = c.conindid AND "
+ "c.contype IN ('p','u','x')) "
+ "WHERE i.indisvalid AND i.indisready "
+ "ORDER BY i.indrelid, indexname");
+ }
+ else
+ {
+ appendPQExpBuffer(query,
+ "LEFT JOIN pg_catalog.pg_depend d "
+ "ON (d.classid = t.tableoid "
+ "AND d.objid = t.oid "
+ "AND d.deptype = 'i') "
+ "LEFT JOIN pg_catalog.pg_constraint c "
+ "ON (d.refclassid = c.tableoid "
+ "AND d.refobjid = c.oid) "
+ "WHERE i.indisvalid "
+ "ORDER BY i.indrelid, indexname");
+ }
- res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
- ntups = PQntuples(res);
+ ntups = PQntuples(res);
- i_tableoid = PQfnumber(res, "tableoid");
- i_oid = PQfnumber(res, "oid");
- i_indexname = PQfnumber(res, "indexname");
- i_parentidx = PQfnumber(res, "parentidx");
- i_indexdef = PQfnumber(res, "indexdef");
- i_indnkeyatts = PQfnumber(res, "indnkeyatts");
- i_indnatts = PQfnumber(res, "indnatts");
- i_indkey = PQfnumber(res, "indkey");
- i_indisclustered = PQfnumber(res, "indisclustered");
- i_indisreplident = PQfnumber(res, "indisreplident");
- i_contype = PQfnumber(res, "contype");
- i_conname = PQfnumber(res, "conname");
- i_condeferrable = PQfnumber(res, "condeferrable");
- i_condeferred = PQfnumber(res, "condeferred");
- i_contableoid = PQfnumber(res, "contableoid");
- i_conoid = PQfnumber(res, "conoid");
- i_condef = PQfnumber(res, "condef");
- i_tablespace = PQfnumber(res, "tablespace");
- i_indreloptions = PQfnumber(res, "indreloptions");
- i_indstatcols = PQfnumber(res, "indstatcols");
- i_indstatvals = PQfnumber(res, "indstatvals");
-
- tbinfo->indexes = indxinfo =
- (IndxInfo *) pg_malloc(ntups * sizeof(IndxInfo));
- tbinfo->numIndexes = ntups;
+ i_tableoid = PQfnumber(res, "tableoid");
+ i_oid = PQfnumber(res, "oid");
+ i_indrelid = PQfnumber(res, "indrelid");
+ i_indexname = PQfnumber(res, "indexname");
+ i_parentidx = PQfnumber(res, "parentidx");
+ i_indexdef = PQfnumber(res, "indexdef");
+ i_indnkeyatts = PQfnumber(res, "indnkeyatts");
+ i_indnatts = PQfnumber(res, "indnatts");
+ i_indkey = PQfnumber(res, "indkey");
+ i_indisclustered = PQfnumber(res, "indisclustered");
+ i_indisreplident = PQfnumber(res, "indisreplident");
+ i_contype = PQfnumber(res, "contype");
+ i_conname = PQfnumber(res, "conname");
+ i_condeferrable = PQfnumber(res, "condeferrable");
+ i_condeferred = PQfnumber(res, "condeferred");
+ i_contableoid = PQfnumber(res, "contableoid");
+ i_conoid = PQfnumber(res, "conoid");
+ i_condef = PQfnumber(res, "condef");
+ i_tablespace = PQfnumber(res, "tablespace");
+ i_indreloptions = PQfnumber(res, "indreloptions");
+ i_indstatcols = PQfnumber(res, "indstatcols");
+ i_indstatvals = PQfnumber(res, "indstatvals");
- for (j = 0; j < ntups; j++)
+ indxinfo = (IndxInfo *) pg_malloc(ntups * sizeof(IndxInfo));
+
+ /*
+ * Outer loop iterates once per table, not once per row. Incrementing of
+ * j is handled by the inner loop.
+ */
+ curtblindx = -1;
+ for (int j = 0; j < ntups;)
+ {
+ Oid indrelid = atooid(PQgetvalue(res, j, i_indrelid));
+ TableInfo *tbinfo = NULL;
+ int numinds;
+
+ /* Count rows for this table */
+ for (numinds = 1; numinds < ntups - j; numinds++)
+ if (atooid(PQgetvalue(res, j + numinds, i_indrelid)) != indrelid)
+ break;
+
+ /*
+ * Locate the associated TableInfo; we rely on tblinfo[] being in OID
+ * order.
+ */
+ while (++curtblindx < numTables)
+ {
+ tbinfo = &tblinfo[curtblindx];
+ if (tbinfo->dobj.catId.oid == indrelid)
+ break;
+ }
+ if (curtblindx >= numTables)
+ fatal("unrecognized table OID %u", indrelid);
+ /* cross-check that we only got requested tables */
+ if (!tbinfo->hasindex ||
+ !tbinfo->interesting)
+ fatal("unexpected index data for table \"%s\"",
+ tbinfo->dobj.name);
+
+ /* Save data for this table */
+ tbinfo->indexes = indxinfo + j;
+ tbinfo->numIndexes = numinds;
+
+ for (int c = 0; c < numinds; c++, j++)
{
char contype;
@@ -8647,11 +8187,12 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
indxinfo[j].indexconstraint = 0;
}
}
-
- PQclear(res);
}
+ PQclear(res);
+
destroyPQExpBuffer(query);
+ destroyPQExpBuffer(tbloids);
}
/*
@@ -8672,7 +8213,7 @@ getExtendedStatistics(Archive *fout)
int i_oid;
int i_stxname;
int i_stxnamespace;
- int i_rolname;
+ int i_stxowner;
int i_stattarget;
int i;
@@ -8684,14 +8225,13 @@ getExtendedStatistics(Archive *fout)
if (fout->remoteVersion < 130000)
appendPQExpBuffer(query, "SELECT tableoid, oid, stxname, "
- "stxnamespace, (%s stxowner) AS rolname, (-1) AS stxstattarget "
- "FROM pg_catalog.pg_statistic_ext",
- username_subquery);
+ "stxnamespace, stxowner, (-1) AS stxstattarget "
+ "FROM pg_catalog.pg_statistic_ext");
else
appendPQExpBuffer(query, "SELECT tableoid, oid, stxname, "
- "stxnamespace, (%s stxowner) AS rolname, stxstattarget "
- "FROM pg_catalog.pg_statistic_ext",
- username_subquery);
+ "stxnamespace, stxowner, stxstattarget "
+ "FROM pg_catalog.pg_statistic_ext");
+
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -8701,7 +8241,7 @@ getExtendedStatistics(Archive *fout)
i_oid = PQfnumber(res, "oid");
i_stxname = PQfnumber(res, "stxname");
i_stxnamespace = PQfnumber(res, "stxnamespace");
- i_rolname = PQfnumber(res, "rolname");
+ i_stxowner = PQfnumber(res, "stxowner");
i_stattarget = PQfnumber(res, "stxstattarget");
statsextinfo = (StatsExtInfo *) pg_malloc(ntups * sizeof(StatsExtInfo));
@@ -8715,14 +8255,11 @@ getExtendedStatistics(Archive *fout)
statsextinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_stxname));
statsextinfo[i].dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_stxnamespace)));
- statsextinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ statsextinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_stxowner));
statsextinfo[i].stattarget = atoi(PQgetvalue(res, i, i_stattarget));
/* Decide whether we want to dump it */
selectDumpableObject(&(statsextinfo[i].dobj), fout);
-
- /* Stats objects do not currently have ACLs. */
- statsextinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -8741,22 +8278,31 @@ getExtendedStatistics(Archive *fout)
void
getConstraints(Archive *fout, TableInfo tblinfo[], int numTables)
{
- int i,
- j;
- ConstraintInfo *constrinfo;
- PQExpBuffer query;
+ PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer tbloids = createPQExpBuffer();
PGresult *res;
+ int ntups;
+ int curtblindx;
+ TableInfo *tbinfo = NULL;
+ ConstraintInfo *constrinfo;
int i_contableoid,
i_conoid,
+ i_conrelid,
i_conname,
i_confrelid,
i_conindid,
i_condef;
- int ntups;
-
- query = createPQExpBuffer();
- for (i = 0; i < numTables; i++)
+ /*
+ * We want to perform just one query against pg_constraint. However, we
+ * mustn't try to select every row of the catalog and then sort it out on
+ * the client side, because some of the server-side functions we need
+ * would be unsafe to apply to tables we don't have lock on. Hence, we
+ * build an array of the OIDs of tables we care about (and now have lock
+ * on!), and use a WHERE clause to constrain which rows are selected.
+ */
+ appendPQExpBufferChar(tbloids, '{');
+ for (int i = 0; i < numTables; i++)
{
TableInfo *tbinfo = &tblinfo[i];
@@ -8769,95 +8315,118 @@ getConstraints(Archive *fout, TableInfo tblinfo[], int numTables)
!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
continue;
- pg_log_info("reading foreign key constraints for table \"%s.%s\"",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
+ /* OK, we need info for this table */
+ if (tbloids->len > 1) /* do we have more than the '{'? */
+ appendPQExpBufferChar(tbloids, ',');
+ appendPQExpBuffer(tbloids, "%u", tbinfo->dobj.catId.oid);
+ }
+ appendPQExpBufferChar(tbloids, '}');
- resetPQExpBuffer(query);
- if (fout->remoteVersion >= 110000)
- appendPQExpBuffer(query,
- "SELECT tableoid, oid, conname, confrelid, conindid, "
- "pg_catalog.pg_get_constraintdef(oid) AS condef "
- "FROM pg_catalog.pg_constraint "
- "WHERE conrelid = '%u'::pg_catalog.oid "
- "AND conparentid = 0 "
- "AND contype = 'f'",
- tbinfo->dobj.catId.oid);
- else
- appendPQExpBuffer(query,
- "SELECT tableoid, oid, conname, confrelid, 0 as conindid, "
- "pg_catalog.pg_get_constraintdef(oid) AS condef "
- "FROM pg_catalog.pg_constraint "
- "WHERE conrelid = '%u'::pg_catalog.oid "
- "AND contype = 'f'",
- tbinfo->dobj.catId.oid);
- res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+ appendPQExpBufferStr(query,
+ "SELECT c.tableoid, c.oid, "
+ "conrelid, conname, confrelid, ");
+ if (fout->remoteVersion >= 110000)
+ appendPQExpBufferStr(query, "conindid, ");
+ else
+ appendPQExpBufferStr(query, "0 AS conindid, ");
+ appendPQExpBuffer(query,
+ "pg_catalog.pg_get_constraintdef(c.oid) AS condef\n"
+ "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
+ "JOIN pg_catalog.pg_constraint c ON (src.tbloid = c.conrelid)\n"
+ "WHERE contype = 'f' ",
+ tbloids->data);
+ if (fout->remoteVersion >= 110000)
+ appendPQExpBufferStr(query,
+ "AND conparentid = 0 ");
+ appendPQExpBufferStr(query,
+ "ORDER BY conrelid, conname");
- ntups = PQntuples(res);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
- i_contableoid = PQfnumber(res, "tableoid");
- i_conoid = PQfnumber(res, "oid");
- i_conname = PQfnumber(res, "conname");
- i_confrelid = PQfnumber(res, "confrelid");
- i_conindid = PQfnumber(res, "conindid");
- i_condef = PQfnumber(res, "condef");
+ ntups = PQntuples(res);
+
+ i_contableoid = PQfnumber(res, "tableoid");
+ i_conoid = PQfnumber(res, "oid");
+ i_conrelid = PQfnumber(res, "conrelid");
+ i_conname = PQfnumber(res, "conname");
+ i_confrelid = PQfnumber(res, "confrelid");
+ i_conindid = PQfnumber(res, "conindid");
+ i_condef = PQfnumber(res, "condef");
- constrinfo = (ConstraintInfo *) pg_malloc(ntups * sizeof(ConstraintInfo));
+ constrinfo = (ConstraintInfo *) pg_malloc(ntups * sizeof(ConstraintInfo));
- for (j = 0; j < ntups; j++)
- {
- TableInfo *reftable;
-
- constrinfo[j].dobj.objType = DO_FK_CONSTRAINT;
- constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid));
- constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
- AssignDumpId(&constrinfo[j].dobj);
- constrinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname));
- constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
- constrinfo[j].contable = tbinfo;
- constrinfo[j].condomain = NULL;
- constrinfo[j].contype = 'f';
- constrinfo[j].condef = pg_strdup(PQgetvalue(res, j, i_condef));
- constrinfo[j].confrelid = atooid(PQgetvalue(res, j, i_confrelid));
- constrinfo[j].conindex = 0;
- constrinfo[j].condeferrable = false;
- constrinfo[j].condeferred = false;
- constrinfo[j].conislocal = true;
- constrinfo[j].separate = true;
+ curtblindx = -1;
+ for (int j = 0; j < ntups; j++)
+ {
+ Oid conrelid = atooid(PQgetvalue(res, j, i_conrelid));
+ TableInfo *reftable;
- /*
- * Restoring an FK that points to a partitioned table requires
- * that all partition indexes have been attached beforehand.
- * Ensure that happens by making the constraint depend on each
- * index partition attach object.
- */
- reftable = findTableByOid(constrinfo[j].confrelid);
- if (reftable && reftable->relkind == RELKIND_PARTITIONED_TABLE)
+ /*
+ * Locate the associated TableInfo; we rely on tblinfo[] being in OID
+ * order.
+ */
+ if (tbinfo == NULL || tbinfo->dobj.catId.oid != conrelid)
+ {
+ while (++curtblindx < numTables)
{
- Oid indexOid = atooid(PQgetvalue(res, j, i_conindid));
+ tbinfo = &tblinfo[curtblindx];
+ if (tbinfo->dobj.catId.oid == conrelid)
+ break;
+ }
+ if (curtblindx >= numTables)
+ fatal("unrecognized table OID %u", conrelid);
+ }
+
+ constrinfo[j].dobj.objType = DO_FK_CONSTRAINT;
+ constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid));
+ constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
+ AssignDumpId(&constrinfo[j].dobj);
+ constrinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname));
+ constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
+ constrinfo[j].contable = tbinfo;
+ constrinfo[j].condomain = NULL;
+ constrinfo[j].contype = 'f';
+ constrinfo[j].condef = pg_strdup(PQgetvalue(res, j, i_condef));
+ constrinfo[j].confrelid = atooid(PQgetvalue(res, j, i_confrelid));
+ constrinfo[j].conindex = 0;
+ constrinfo[j].condeferrable = false;
+ constrinfo[j].condeferred = false;
+ constrinfo[j].conislocal = true;
+ constrinfo[j].separate = true;
+
+ /*
+ * Restoring an FK that points to a partitioned table requires that
+ * all partition indexes have been attached beforehand. Ensure that
+ * happens by making the constraint depend on each index partition
+ * attach object.
+ */
+ reftable = findTableByOid(constrinfo[j].confrelid);
+ if (reftable && reftable->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ Oid indexOid = atooid(PQgetvalue(res, j, i_conindid));
- if (indexOid != InvalidOid)
+ if (indexOid != InvalidOid)
+ {
+ for (int k = 0; k < reftable->numIndexes; k++)
{
- for (int k = 0; k < reftable->numIndexes; k++)
- {
- IndxInfo *refidx;
+ IndxInfo *refidx;
- /* not our index? */
- if (reftable->indexes[k].dobj.catId.oid != indexOid)
- continue;
+ /* not our index? */
+ if (reftable->indexes[k].dobj.catId.oid != indexOid)
+ continue;
- refidx = &reftable->indexes[k];
- addConstrChildIdxDeps(&constrinfo[j].dobj, refidx);
- break;
- }
+ refidx = &reftable->indexes[k];
+ addConstrChildIdxDeps(&constrinfo[j].dobj, refidx);
+ break;
}
}
}
-
- PQclear(res);
}
+ PQclear(res);
+
destroyPQExpBuffer(query);
+ destroyPQExpBuffer(tbloids);
}
/*
@@ -8899,7 +8468,7 @@ getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
{
int i;
ConstraintInfo *constrinfo;
- PQExpBuffer query;
+ PQExpBuffer query = createPQExpBuffer();
PGresult *res;
int i_tableoid,
i_oid,
@@ -8907,25 +8476,35 @@ getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
i_consrc;
int ntups;
- query = createPQExpBuffer();
+ if (!fout->is_prepared[PREPQUERY_GETDOMAINCONSTRAINTS])
+ {
+ /* Set up query for constraint-specific details */
+ appendPQExpBufferStr(query,
+ "PREPARE getDomainConstraints(pg_catalog.oid) AS\n");
- if (fout->remoteVersion >= 90100)
- appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
- "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
- "convalidated "
- "FROM pg_catalog.pg_constraint "
- "WHERE contypid = '%u'::pg_catalog.oid "
- "ORDER BY conname",
- tyinfo->dobj.catId.oid);
+ if (fout->remoteVersion >= 90100)
+ appendPQExpBufferStr(query, "SELECT tableoid, oid, conname, "
+ "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
+ "convalidated "
+ "FROM pg_catalog.pg_constraint "
+ "WHERE contypid = $1 "
+ "ORDER BY conname");
+ else
+ appendPQExpBufferStr(query, "SELECT tableoid, oid, conname, "
+ "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
+ "true as convalidated "
+ "FROM pg_catalog.pg_constraint "
+ "WHERE contypid = $1 "
+ "ORDER BY conname");
- else
- appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
- "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
- "true as convalidated "
- "FROM pg_catalog.pg_constraint "
- "WHERE contypid = '%u'::pg_catalog.oid "
- "ORDER BY conname",
- tyinfo->dobj.catId.oid);
+ ExecuteSqlStatement(fout, query->data);
+
+ fout->is_prepared[PREPQUERY_GETDOMAINCONSTRAINTS] = true;
+ }
+
+ printfPQExpBuffer(query,
+ "EXECUTE getDomainConstraints('%u')",
+ tyinfo->dobj.catId.oid);
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -9001,24 +8580,12 @@ getRules(Archive *fout, int *numRules)
int i_is_instead;
int i_ev_enabled;
- if (fout->remoteVersion >= 80300)
- {
- appendPQExpBufferStr(query, "SELECT "
- "tableoid, oid, rulename, "
- "ev_class AS ruletable, ev_type, is_instead, "
- "ev_enabled "
- "FROM pg_rewrite "
- "ORDER BY oid");
- }
- else
- {
- appendPQExpBufferStr(query, "SELECT "
- "tableoid, oid, rulename, "
- "ev_class AS ruletable, ev_type, is_instead, "
- "'O'::char AS ev_enabled "
- "FROM pg_rewrite "
- "ORDER BY oid");
- }
+ appendPQExpBufferStr(query, "SELECT "
+ "tableoid, oid, rulename, "
+ "ev_class AS ruletable, ev_type, is_instead, "
+ "ev_enabled "
+ "FROM pg_rewrite "
+ "ORDER BY oid");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -9101,13 +8668,15 @@ getRules(Archive *fout, int *numRules)
void
getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
{
- int i,
- j;
PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer tbloids = createPQExpBuffer();
PGresult *res;
+ int ntups;
+ int curtblindx;
TriggerInfo *tginfo;
int i_tableoid,
i_oid,
+ i_tgrelid,
i_tgname,
i_tgfname,
i_tgtype,
@@ -9122,153 +8691,172 @@ getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
i_tgdeferrable,
i_tginitdeferred,
i_tgdef;
- int ntups;
- for (i = 0; i < numTables; i++)
+ /*
+ * We want to perform just one query against pg_trigger. However, we
+ * mustn't try to select every row of the catalog and then sort it out on
+ * the client side, because some of the server-side functions we need
+ * would be unsafe to apply to tables we don't have lock on. Hence, we
+ * build an array of the OIDs of tables we care about (and now have lock
+ * on!), and use a WHERE clause to constrain which rows are selected.
+ */
+ appendPQExpBufferChar(tbloids, '{');
+ for (int i = 0; i < numTables; i++)
+ {
+ TableInfo *tbinfo = &tblinfo[i];
+
+ if (!tbinfo->hastriggers ||
+ !(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
+ continue;
+
+ /* OK, we need info for this table */
+ if (tbloids->len > 1) /* do we have more than the '{'? */
+ appendPQExpBufferChar(tbloids, ',');
+ appendPQExpBuffer(tbloids, "%u", tbinfo->dobj.catId.oid);
+ }
+ appendPQExpBufferChar(tbloids, '}');
+
+ resetPQExpBuffer(query);
+ if (fout->remoteVersion >= 130000)
{
- TableInfo *tbinfo = &tblinfo[i];
+ /*
+ * NB: think not to use pretty=true in pg_get_triggerdef. It could
+ * result in non-forward-compatible dumps of WHEN clauses due to
+ * under-parenthesization.
+ *
+ * NB: We need to see tgisinternal triggers in partitions, in case the
+ * tgenabled flag has been changed from the parent.
+ */
+ appendPQExpBuffer(query,
+ "SELECT t.tgrelid, t.tgname, "
+ "t.tgfoid::pg_catalog.regproc AS tgfname, "
+ "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
+ "t.tgenabled, t.tableoid, t.oid, t.tgisinternal as tgispartition\n"
+ "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
+ "JOIN pg_catalog.pg_trigger t ON (src.tbloid = t.tgrelid) "
+ "LEFT JOIN pg_catalog.pg_trigger u ON (u.oid = t.tgparentid) "
+ "WHERE (NOT t.tgisinternal OR t.tgenabled != u.tgenabled) "
+ "ORDER BY t.tgrelid, t.tgname",
+ tbloids->data);
+ }
+ else if (fout->remoteVersion >= 110000)
+ {
+ /*
+ * NB: We need to see tgisinternal triggers in partitions, in case the
+ * tgenabled flag has been changed from the parent. No tgparentid in
+ * version 11-12, so we have to match them via pg_depend.
+ *
+ * See above about pretty=true in pg_get_triggerdef.
+ */
+ appendPQExpBuffer(query,
+ "SELECT t.tgrelid, t.tgname, "
+ "t.tgfoid::pg_catalog.regproc AS tgfname, "
+ "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
+ "t.tgenabled, t.tableoid, t.oid, t.tgisinternal as tgispartition "
+ "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
+ "JOIN pg_catalog.pg_trigger t ON (src.tbloid = t.tgrelid) "
+ "LEFT JOIN pg_catalog.pg_depend AS d ON "
+ " d.classid = 'pg_catalog.pg_trigger'::pg_catalog.regclass AND "
+ " d.refclassid = 'pg_catalog.pg_trigger'::pg_catalog.regclass AND "
+ " d.objid = t.oid "
+ "LEFT JOIN pg_catalog.pg_trigger AS pt ON pt.oid = refobjid "
+ "WHERE (NOT t.tgisinternal OR t.tgenabled != pt.tgenabled) "
+ "ORDER BY t.tgrelid, t.tgname",
+ tbloids->data);
+ }
+ else if (fout->remoteVersion >= 90000)
+ {
+ /* See above about pretty=true in pg_get_triggerdef */
+ appendPQExpBuffer(query,
+ "SELECT t.tgrelid, t.tgname, "
+ "t.tgfoid::pg_catalog.regproc AS tgfname, "
+ "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
+ "t.tgenabled, false as tgisinternal, "
+ "t.tableoid, t.oid "
+ "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
+ "JOIN pg_catalog.pg_trigger t ON (src.tbloid = t.tgrelid) "
+ "WHERE NOT t.tgisinternal "
+ "ORDER BY t.tgrelid, t.tgname",
+ tbloids->data);
+ }
+ else
+ {
+ /*
+ * We ignore triggers that are tied to a foreign-key constraint
+ */
+ appendPQExpBuffer(query,
+ "SELECT t.tgrelid, tgname, "
+ "tgfoid::pg_catalog.regproc AS tgfname, "
+ "tgtype, tgnargs, tgargs, tgenabled, "
+ "false as tgisinternal, "
+ "tgisconstraint, tgconstrname, tgdeferrable, "
+ "tgconstrrelid, tginitdeferred, t.tableoid, t.oid, "
+ "tgconstrrelid::pg_catalog.regclass AS tgconstrrelname "
+ "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
+ "JOIN pg_catalog.pg_trigger t ON (src.tbloid = t.tgrelid) "
+ "WHERE tgconstraint = 0 "
+ "ORDER BY t.tgrelid, t.tgname",
+ tbloids->data);
+ }
- if (!tbinfo->hastriggers ||
- !(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
- continue;
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
- pg_log_info("reading triggers for table \"%s.%s\"",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
+ ntups = PQntuples(res);
- resetPQExpBuffer(query);
- if (fout->remoteVersion >= 130000)
- {
- /*
- * NB: think not to use pretty=true in pg_get_triggerdef. It
- * could result in non-forward-compatible dumps of WHEN clauses
- * due to under-parenthesization.
- *
- * NB: We need to see tgisinternal triggers in partitions, in case
- * the tgenabled flag has been changed from the parent.
- */
- appendPQExpBuffer(query,
- "SELECT t.tgname, "
- "t.tgfoid::pg_catalog.regproc AS tgfname, "
- "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
- "t.tgenabled, t.tableoid, t.oid, t.tgisinternal "
- "FROM pg_catalog.pg_trigger t "
- "LEFT JOIN pg_catalog.pg_trigger u ON u.oid = t.tgparentid "
- "WHERE t.tgrelid = '%u'::pg_catalog.oid "
- "AND (NOT t.tgisinternal OR t.tgenabled != u.tgenabled)",
- tbinfo->dobj.catId.oid);
- }
- else if (fout->remoteVersion >= 110000)
- {
- /*
- * NB: We need to see tgisinternal triggers in partitions, in case
- * the tgenabled flag has been changed from the parent. No
- * tgparentid in version 11-12, so we have to match them via
- * pg_depend.
- *
- * See above about pretty=true in pg_get_triggerdef.
- */
- appendPQExpBuffer(query,
- "SELECT t.tgname, "
- "t.tgfoid::pg_catalog.regproc AS tgfname, "
- "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
- "t.tgenabled, t.tableoid, t.oid, t.tgisinternal "
- "FROM pg_catalog.pg_trigger t "
- "LEFT JOIN pg_catalog.pg_depend AS d ON "
- " d.classid = 'pg_catalog.pg_trigger'::pg_catalog.regclass AND "
- " d.refclassid = 'pg_catalog.pg_trigger'::pg_catalog.regclass AND "
- " d.objid = t.oid "
- "LEFT JOIN pg_catalog.pg_trigger AS pt ON pt.oid = refobjid "
- "WHERE t.tgrelid = '%u'::pg_catalog.oid "
- "AND (NOT t.tgisinternal%s)",
- tbinfo->dobj.catId.oid,
- tbinfo->ispartition ?
- " OR t.tgenabled != pt.tgenabled" : "");
- }
- else if (fout->remoteVersion >= 90000)
- {
- /* See above about pretty=true in pg_get_triggerdef */
- appendPQExpBuffer(query,
- "SELECT t.tgname, "
- "t.tgfoid::pg_catalog.regproc AS tgfname, "
- "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
- "t.tgenabled, false as tgisinternal, "
- "t.tableoid, t.oid "
- "FROM pg_catalog.pg_trigger t "
- "WHERE tgrelid = '%u'::pg_catalog.oid "
- "AND NOT tgisinternal",
- tbinfo->dobj.catId.oid);
- }
- else if (fout->remoteVersion >= 80300)
- {
- /*
- * We ignore triggers that are tied to a foreign-key constraint
- */
- appendPQExpBuffer(query,
- "SELECT tgname, "
- "tgfoid::pg_catalog.regproc AS tgfname, "
- "tgtype, tgnargs, tgargs, tgenabled, "
- "false as tgisinternal, "
- "tgisconstraint, tgconstrname, tgdeferrable, "
- "tgconstrrelid, tginitdeferred, tableoid, oid, "
- "tgconstrrelid::pg_catalog.regclass AS tgconstrrelname "
- "FROM pg_catalog.pg_trigger t "
- "WHERE tgrelid = '%u'::pg_catalog.oid "
- "AND tgconstraint = 0",
- tbinfo->dobj.catId.oid);
- }
- else
- {
- /*
- * We ignore triggers that are tied to a foreign-key constraint,
- * but in these versions we have to grovel through pg_constraint
- * to find out
- */
- appendPQExpBuffer(query,
- "SELECT tgname, "
- "tgfoid::pg_catalog.regproc AS tgfname, "
- "tgtype, tgnargs, tgargs, tgenabled, "
- "false as tgisinternal, "
- "tgisconstraint, tgconstrname, tgdeferrable, "
- "tgconstrrelid, tginitdeferred, tableoid, oid, "
- "tgconstrrelid::pg_catalog.regclass AS tgconstrrelname "
- "FROM pg_catalog.pg_trigger t "
- "WHERE tgrelid = '%u'::pg_catalog.oid "
- "AND (NOT tgisconstraint "
- " OR NOT EXISTS"
- " (SELECT 1 FROM pg_catalog.pg_depend d "
- " JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) "
- " WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))",
- tbinfo->dobj.catId.oid);
- }
+ i_tableoid = PQfnumber(res, "tableoid");
+ i_oid = PQfnumber(res, "oid");
+ i_tgrelid = PQfnumber(res, "tgrelid");
+ i_tgname = PQfnumber(res, "tgname");
+ i_tgfname = PQfnumber(res, "tgfname");
+ i_tgtype = PQfnumber(res, "tgtype");
+ i_tgnargs = PQfnumber(res, "tgnargs");
+ i_tgargs = PQfnumber(res, "tgargs");
+ i_tgisconstraint = PQfnumber(res, "tgisconstraint");
+ i_tgconstrname = PQfnumber(res, "tgconstrname");
+ i_tgconstrrelid = PQfnumber(res, "tgconstrrelid");
+ i_tgconstrrelname = PQfnumber(res, "tgconstrrelname");
+ i_tgenabled = PQfnumber(res, "tgenabled");
+ i_tgisinternal = PQfnumber(res, "tgisinternal");
+ i_tgdeferrable = PQfnumber(res, "tgdeferrable");
+ i_tginitdeferred = PQfnumber(res, "tginitdeferred");
+ i_tgdef = PQfnumber(res, "tgdef");
+
+ tginfo = (TriggerInfo *) pg_malloc(ntups * sizeof(TriggerInfo));
- res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+ /*
+ * Outer loop iterates once per table, not once per row. Incrementing of
+ * j is handled by the inner loop.
+ */
+ curtblindx = -1;
+ for (int j = 0; j < ntups;)
+ {
+ Oid tgrelid = atooid(PQgetvalue(res, j, i_tgrelid));
+ TableInfo *tbinfo = NULL;
+ int numtrigs;
- ntups = PQntuples(res);
+ /* Count rows for this table */
+ for (numtrigs = 1; numtrigs < ntups - j; numtrigs++)
+ if (atooid(PQgetvalue(res, j + numtrigs, i_tgrelid)) != tgrelid)
+ break;
- i_tableoid = PQfnumber(res, "tableoid");
- i_oid = PQfnumber(res, "oid");
- i_tgname = PQfnumber(res, "tgname");
- i_tgfname = PQfnumber(res, "tgfname");
- i_tgtype = PQfnumber(res, "tgtype");
- i_tgnargs = PQfnumber(res, "tgnargs");
- i_tgargs = PQfnumber(res, "tgargs");
- i_tgisconstraint = PQfnumber(res, "tgisconstraint");
- i_tgconstrname = PQfnumber(res, "tgconstrname");
- i_tgconstrrelid = PQfnumber(res, "tgconstrrelid");
- i_tgconstrrelname = PQfnumber(res, "tgconstrrelname");
- i_tgenabled = PQfnumber(res, "tgenabled");
- i_tgisinternal = PQfnumber(res, "tgisinternal");
- i_tgdeferrable = PQfnumber(res, "tgdeferrable");
- i_tginitdeferred = PQfnumber(res, "tginitdeferred");
- i_tgdef = PQfnumber(res, "tgdef");
-
- tginfo = (TriggerInfo *) pg_malloc(ntups * sizeof(TriggerInfo));
-
- tbinfo->numTriggers = ntups;
- tbinfo->triggers = tginfo;
+ /*
+ * Locate the associated TableInfo; we rely on tblinfo[] being in OID
+ * order.
+ */
+ while (++curtblindx < numTables)
+ {
+ tbinfo = &tblinfo[curtblindx];
+ if (tbinfo->dobj.catId.oid == tgrelid)
+ break;
+ }
+ if (curtblindx >= numTables)
+ fatal("unrecognized table OID %u", tgrelid);
- for (j = 0; j < ntups; j++)
+ /* Save data for this table */
+ tbinfo->triggers = tginfo + j;
+ tbinfo->numTriggers = numtrigs;
+
+ for (int c = 0; c < numtrigs; c++, j++)
{
tginfo[j].dobj.objType = DO_TRIGGER;
tginfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
@@ -9331,11 +8919,12 @@ getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
}
}
}
-
- PQclear(res);
}
+ PQclear(res);
+
destroyPQExpBuffer(query);
+ destroyPQExpBuffer(tbloids);
}
/*
@@ -9370,14 +8959,13 @@ getEventTriggers(Archive *fout, int *numEventTriggers)
appendPQExpBuffer(query,
"SELECT e.tableoid, e.oid, evtname, evtenabled, "
- "evtevent, (%s evtowner) AS evtowner, "
+ "evtevent, evtowner, "
"array_to_string(array("
"select quote_literal(x) "
" from unnest(evttags) as t(x)), ', ') as evttags, "
"e.evtfoid::regproc as evtfname "
"FROM pg_event_trigger e "
- "ORDER BY e.oid",
- username_subquery);
+ "ORDER BY e.oid");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -9405,16 +8993,13 @@ getEventTriggers(Archive *fout, int *numEventTriggers)
evtinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_evtname));
evtinfo[i].evtname = pg_strdup(PQgetvalue(res, i, i_evtname));
evtinfo[i].evtevent = pg_strdup(PQgetvalue(res, i, i_evtevent));
- evtinfo[i].evtowner = pg_strdup(PQgetvalue(res, i, i_evtowner));
+ evtinfo[i].evtowner = getRoleName(PQgetvalue(res, i, i_evtowner));
evtinfo[i].evttags = pg_strdup(PQgetvalue(res, i, i_evttags));
evtinfo[i].evtfname = pg_strdup(PQgetvalue(res, i, i_evtfname));
evtinfo[i].evtenabled = *(PQgetvalue(res, i, i_evtenabled));
/* Decide whether we want to dump it */
selectDumpableObject(&(evtinfo[i].dobj), fout);
-
- /* Event Triggers do not currently have ACLs. */
- evtinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -9436,7 +9021,6 @@ getEventTriggers(Archive *fout, int *numEventTriggers)
ProcLangInfo *
getProcLangs(Archive *fout, int *numProcLangs)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
@@ -9450,9 +9034,7 @@ getProcLangs(Archive *fout, int *numProcLangs)
int i_laninline;
int i_lanvalidator;
int i_lanacl;
- int i_rlanacl;
- int i_initlanacl;
- int i_initrlanacl;
+ int i_acldefault;
int i_lanowner;
/*
@@ -9460,86 +9042,44 @@ getProcLangs(Archive *fout, int *numProcLangs)
* Cloudberry 5, so the check needs to go further back than 90000.
*/
- if (fout->remoteVersion >= 90600)
- {
- PQExpBuffer acl_subquery = createPQExpBuffer();
- PQExpBuffer racl_subquery = createPQExpBuffer();
- PQExpBuffer initacl_subquery = createPQExpBuffer();
- PQExpBuffer initracl_subquery = createPQExpBuffer();
-
- buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
- initracl_subquery, "l.lanacl", "l.lanowner", "'l'",
- dopt->binary_upgrade);
-
- /* pg_language has a laninline column */
- appendPQExpBuffer(query, "SELECT l.tableoid, l.oid, "
- "l.lanname, l.lanpltrusted, l.lanplcallfoid, "
- "l.laninline, l.lanvalidator, "
- "%s AS lanacl, "
- "%s AS rlanacl, "
- "%s AS initlanacl, "
- "%s AS initrlanacl, "
- "(%s l.lanowner) AS lanowner "
- "FROM pg_language l "
- "LEFT JOIN pg_init_privs pip ON "
- "(l.oid = pip.objoid "
- "AND pip.classoid = 'pg_language'::regclass "
- "AND pip.objsubid = 0) "
- "WHERE l.lanispl "
- "ORDER BY l.oid",
- acl_subquery->data,
- racl_subquery->data,
- initacl_subquery->data,
- initracl_subquery->data,
- username_subquery);
-
- destroyPQExpBuffer(acl_subquery);
- destroyPQExpBuffer(racl_subquery);
- destroyPQExpBuffer(initacl_subquery);
- destroyPQExpBuffer(initracl_subquery);
- }
- else if (fout->remoteVersion >= 90000)
+ if (fout->remoteVersion >= 90200)
{
- /* pg_language has a laninline column */
+ /* acldefault() exists */
appendPQExpBuffer(query, "SELECT tableoid, oid, "
"lanname, lanpltrusted, lanplcallfoid, "
- "laninline, lanvalidator, lanacl, NULL AS rlanacl, "
- "NULL AS initlanacl, NULL AS initrlanacl, "
- "(%s lanowner) AS lanowner "
+ "laninline, lanvalidator, "
+ "lanacl, "
+ "acldefault('l', lanowner) AS acldefault, "
+ "lanowner "
"FROM pg_language "
"WHERE lanispl "
- "ORDER BY oid",
- username_subquery);
+ "ORDER BY oid");
}
- else if (fout->remoteVersion >= 80300)
+ else if (fout->remoteVersion >= 90000)
{
/* pg_language has a laninline column */
- /* pg_language has a lanowner column */
appendPQExpBuffer(query, "SELECT tableoid, oid, "
"lanname, lanpltrusted, lanplcallfoid, "
- "laninline, lanvalidator, lanacl, "
- "0 AS laninline, lanvalidator, lanacl, "
- "NULL AS rlanacl, "
- "NULL AS initlanacl, NULL AS initrlanacl, "
- "(%s lanowner) AS lanowner "
+ "laninline, lanvalidator, "
+ "lanacl, NULL AS acldefault, "
+ "lanowner "
"FROM pg_language "
"WHERE lanispl "
- "ORDER BY oid",
- username_subquery);
+ "ORDER BY oid");
}
- else
+ else /* GPDB5 */
{
- /* Languages are owned by the bootstrap superuser, OID 10 */
+ /* pg_language has a laninline column */
+ /* pg_language has a lanowner column */
appendPQExpBuffer(query, "SELECT tableoid, oid, "
"lanname, lanpltrusted, lanplcallfoid, "
+ "laninline, lanvalidator, lanacl, "
"0 AS laninline, lanvalidator, lanacl, "
- "NULL AS rlanacl, "
- "NULL AS initlanacl, NULL AS initrlanacl, "
- "(%s '10') AS lanowner "
+ "NULL AS acldefault, "
+ "lanowner "
"FROM pg_language "
"WHERE lanispl "
- "ORDER BY oid",
- username_subquery);
+ "ORDER BY oid");
}
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -9558,9 +9098,7 @@ getProcLangs(Archive *fout, int *numProcLangs)
i_laninline = PQfnumber(res, "laninline");
i_lanvalidator = PQfnumber(res, "lanvalidator");
i_lanacl = PQfnumber(res, "lanacl");
- i_rlanacl = PQfnumber(res, "rlanacl");
- i_initlanacl = PQfnumber(res, "initlanacl");
- i_initrlanacl = PQfnumber(res, "initrlanacl");
+ i_acldefault = PQfnumber(res, "acldefault");
i_lanowner = PQfnumber(res, "lanowner");
for (i = 0; i < ntups; i++)
@@ -9571,24 +9109,22 @@ getProcLangs(Archive *fout, int *numProcLangs)
AssignDumpId(&planginfo[i].dobj);
planginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_lanname));
+ planginfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_lanacl));
+ planginfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
+ planginfo[i].dacl.privtype = 0;
+ planginfo[i].dacl.initprivs = NULL;
planginfo[i].lanpltrusted = *(PQgetvalue(res, i, i_lanpltrusted)) == 't';
planginfo[i].lanplcallfoid = atooid(PQgetvalue(res, i, i_lanplcallfoid));
planginfo[i].laninline = atooid(PQgetvalue(res, i, i_laninline));
planginfo[i].lanvalidator = atooid(PQgetvalue(res, i, i_lanvalidator));
- planginfo[i].lanacl = pg_strdup(PQgetvalue(res, i, i_lanacl));
- planginfo[i].rlanacl = pg_strdup(PQgetvalue(res, i, i_rlanacl));
- planginfo[i].initlanacl = pg_strdup(PQgetvalue(res, i, i_initlanacl));
- planginfo[i].initrlanacl = pg_strdup(PQgetvalue(res, i, i_initrlanacl));
- planginfo[i].lanowner = pg_strdup(PQgetvalue(res, i, i_lanowner));
+ planginfo[i].lanowner = getRoleName(PQgetvalue(res, i, i_lanowner));
/* Decide whether we want to dump it */
selectDumpableProcLang(&(planginfo[i]), fout);
- /* Do not try to dump ACL if no ACL exists. */
- if (PQgetisnull(res, i, i_lanacl) && PQgetisnull(res, i, i_rlanacl) &&
- PQgetisnull(res, i, i_initlanacl) &&
- PQgetisnull(res, i, i_initrlanacl))
- planginfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Mark whether language has an ACL */
+ if (!PQgetisnull(res, i, i_lanacl))
+ planginfo[i].dobj.components |= DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -9698,9 +9234,6 @@ getCasts(Archive *fout, int *numCasts)
/* Decide whether we want to dump it */
selectDumpableCast(&(castinfo[i]), fout);
-
- /* Casts do not currently have ACLs. */
- castinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -9822,12 +9355,6 @@ getTransforms(Archive *fout, int *numTransforms)
* for each interesting table, read info about its attributes
* (names, types, default values, CHECK constraints, etc)
*
- * This is implemented in a very inefficient way right now, looping
- * through the tblinfo and doing a join per table to find the attrs and their
- * types. However, because we want type names and so forth to be named
- * relative to the schema of each table, we couldn't do it in just one
- * query. (Maybe one query per schema?)
- *
* modifies tblinfo
*/
void
@@ -9835,16 +9362,49 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
{
DumpOptions *dopt = fout->dopt;
PQExpBuffer q = createPQExpBuffer();
-
- /* GPDB_14_MERGE_FIXME: GPDB specific column, need to keep this for easy to use*/
+ PQExpBuffer tbloids = createPQExpBuffer();
+ PQExpBuffer checkoids = createPQExpBuffer();
+ PGresult *res;
+ int ntups;
+ int curtblindx;
+ int i_attrelid;
+ int i_attnum;
+ int i_attname;
+ int i_atttypname;
+ int i_atttypmod;
+ int i_attstattarget;
+ int i_attstorage;
+ int i_typstorage;
+ int i_attidentity;
+ int i_attgenerated;
+ int i_attisdropped;
+ int i_attlen;
+ int i_attalign;
+ int i_attislocal;
+ int i_attnotnull;
+ int i_attoptions;
+ int i_attcollation;
+ int i_attcompression;
+ int i_attfdwoptions;
+ int i_attmissingval;
+ int i_atthasdef;
int i_attencoding;
+ /*
+ * We want to perform just one query against pg_attribute, and then just
+ * one against pg_attrdef (for DEFAULTs) and one against pg_constraint
+ * (for CHECK constraints). However, we mustn't try to select every row
+ * of those catalogs and then sort it out on the client side, because some
+ * of the server-side functions we need would be unsafe to apply to tables
+ * we don't have lock on. Hence, we build an array of the OIDs of tables
+ * we care about (and now have lock on!), and use a WHERE clause to
+ * constrain which rows are selected.
+ */
+ appendPQExpBufferChar(tbloids, '{');
+ appendPQExpBufferChar(checkoids, '{');
for (int i = 0; i < numTables; i++)
{
TableInfo *tbinfo = &tblinfo[i];
- PGresult *res;
- int ntups;
- bool hasdefaults;
/* Don't bother to collect info for sequences */
if (tbinfo->relkind == RELKIND_SEQUENCE)
@@ -9854,170 +9414,236 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
if (!tbinfo->interesting)
continue;
- /* find all the user attributes and their types */
-
- /*
- * we must read the attribute names in attribute number order! because
- * we will use the attnum to index into the attnames array later.
- */
- pg_log_info("finding the columns and types of table \"%s.%s\"",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
-
- resetPQExpBuffer(q);
-
- appendPQExpBufferStr(q,
- "SELECT\n"
- "a.attnum,\n"
- "a.attname,\n"
- "a.atttypmod,\n"
- "a.attstattarget,\n"
- "a.attstorage,\n"
- "t.typstorage,\n"
- "a.attnotnull,\n"
- "a.atthasdef,\n"
- "a.attisdropped,\n"
- "a.attlen,\n"
- "a.attalign,\n"
- "a.attislocal,\n"
- "pg_catalog.format_type(t.oid, a.atttypmod) AS atttypname,\n");
-
- if (fout->remoteVersion >= 90000)
- appendPQExpBufferStr(q,
- "array_to_string(a.attoptions, ', ') AS attoptions,\n");
- else
- appendPQExpBufferStr(q,
- "'' AS attoptions,\n");
+ /* OK, we need info for this table */
+ if (tbloids->len > 1) /* do we have more than the '{'? */
+ appendPQExpBufferChar(tbloids, ',');
+ appendPQExpBuffer(tbloids, "%u", tbinfo->dobj.catId.oid);
- if (fout->remoteVersion >= 90100)
+ if (tbinfo->ncheck > 0)
{
- /*
- * Since we only want to dump COLLATE clauses for attributes whose
- * collation is different from their type's default, we use a CASE
- * here to suppress uninteresting attcollations cheaply.
- */
- appendPQExpBufferStr(q,
- "CASE WHEN a.attcollation <> t.typcollation "
- "THEN a.attcollation ELSE 0 END AS attcollation,\n");
+ /* Also make a list of the ones with check constraints */
+ if (checkoids->len > 1) /* do we have more than the '{'? */
+ appendPQExpBufferChar(checkoids, ',');
+ appendPQExpBuffer(checkoids, "%u", tbinfo->dobj.catId.oid);
}
- else
- appendPQExpBufferStr(q,
- "0 AS attcollation,\n");
+ }
+ appendPQExpBufferChar(tbloids, '}');
+ appendPQExpBufferChar(checkoids, '}');
- if (fout->remoteVersion >= 140000)
+ /* find all the user attributes and their types */
+ appendPQExpBufferStr(q,
+ "SELECT\n"
+ "a.attrelid,\n"
+ "a.attnum,\n"
+ "a.attname,\n"
+ "a.atttypmod,\n"
+ "a.attstattarget,\n"
+ "a.attstorage,\n"
+ "t.typstorage,\n"
+ "a.attnotnull,\n"
+ "a.atthasdef,\n"
+ "a.attisdropped,\n"
+ "a.attlen,\n"
+ "a.attalign,\n"
+ "a.attislocal,\n"
+ "pg_catalog.format_type(t.oid, a.atttypmod) AS atttypname,\n"
+ "pg_catalog.array_to_string(e.attoptions, ',') AS attencoding,\n");
+
+ if (fout->remoteVersion >= 140000)
appendPQExpBuffer(q,
"a.attcompression AS attcompression,\n");
else
appendPQExpBuffer(q,
"'' AS attcompression,\n");
- appendPQExpBuffer(q,
- "pg_catalog.array_to_string(e.attoptions, ',') AS attencoding,\n");
+ if (fout->remoteVersion >= 90000)
+ appendPQExpBufferStr(q,
+ "array_to_string(a.attoptions, ', ') AS attoptions,\n");
+ else
+ appendPQExpBufferStr(q,
+ "'' AS attoptions,\n");
- if (fout->remoteVersion >= 90200)
- appendPQExpBufferStr(q,
- "pg_catalog.array_to_string(ARRAY("
- "SELECT pg_catalog.quote_ident(option_name) || "
- "' ' || pg_catalog.quote_literal(option_value) "
- "FROM pg_catalog.pg_options_to_table(attfdwoptions) "
- "ORDER BY option_name"
- "), E',\n ') AS attfdwoptions,\n");
- else
- appendPQExpBufferStr(q,
- "'' AS attfdwoptions,\n");
+ if (fout->remoteVersion >= 90100)
+ {
+ /*
+ * Since we only want to dump COLLATE clauses for attributes whose
+ * collation is different from their type's default, we use a CASE
+ * here to suppress uninteresting attcollations cheaply.
+ */
+ appendPQExpBufferStr(q,
+ "CASE WHEN a.attcollation <> t.typcollation "
+ "THEN a.attcollation ELSE 0 END AS attcollation,\n");
+ }
+ else
+ appendPQExpBufferStr(q,
+ "0 AS attcollation,\n");
- if (fout->remoteVersion >= 100000)
- appendPQExpBufferStr(q,
- "a.attidentity,\n");
- else
- appendPQExpBufferStr(q,
- "'' AS attidentity,\n");
+ if (fout->remoteVersion >= 90200)
+ appendPQExpBufferStr(q,
+ "pg_catalog.array_to_string(ARRAY("
+ "SELECT pg_catalog.quote_ident(option_name) || "
+ "' ' || pg_catalog.quote_literal(option_value) "
+ "FROM pg_catalog.pg_options_to_table(attfdwoptions) "
+ "ORDER BY option_name"
+ "), E',\n ') AS attfdwoptions,\n");
+ else
+ appendPQExpBufferStr(q,
+ "'' AS attfdwoptions,\n");
- if (fout->remoteVersion >= 110000)
- appendPQExpBufferStr(q,
- "CASE WHEN a.atthasmissing AND NOT a.attisdropped "
- "THEN a.attmissingval ELSE null END AS attmissingval,\n");
- else
- appendPQExpBufferStr(q,
- "NULL AS attmissingval,\n");
+ if (fout->remoteVersion >= 100000)
+ appendPQExpBufferStr(q,
+ "a.attidentity,\n");
+ else
+ appendPQExpBufferStr(q,
+ "'' AS attidentity,\n");
- if (fout->remoteVersion >= 120000)
- appendPQExpBufferStr(q,
- "a.attgenerated\n");
- else
- appendPQExpBufferStr(q,
- "'' AS attgenerated\n");
+ if (fout->remoteVersion >= 110000)
+ appendPQExpBufferStr(q,
+ "CASE WHEN a.atthasmissing AND NOT a.attisdropped "
+ "THEN a.attmissingval ELSE null END AS attmissingval,\n");
+ else
+ appendPQExpBufferStr(q,
+ "NULL AS attmissingval,\n");
- /* need left join here to not fail on dropped columns ... */
- appendPQExpBuffer(q,
- "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
- "ON a.atttypid = t.oid\n"
- "LEFT OUTER JOIN pg_catalog.pg_attribute_encoding e ON e.attrelid = a.attrelid AND e.attnum = a.attnum \n"
- "WHERE a.attrelid = '%u'::pg_catalog.oid "
- "AND a.attnum > 0::pg_catalog.int2\n"
- "ORDER BY a.attnum",
- tbinfo->dobj.catId.oid);
+ if (fout->remoteVersion >= 120000)
+ appendPQExpBufferStr(q,
+ "a.attgenerated\n");
+ else
+ appendPQExpBufferStr(q,
+ "'' AS attgenerated\n");
- res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
+ /* need left join to pg_type to not fail on dropped columns ... */
+ appendPQExpBuffer(q,
+ "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
+ "JOIN pg_catalog.pg_attribute a ON (src.tbloid = a.attrelid) "
+ "LEFT JOIN pg_catalog.pg_type t "
+ "ON (a.atttypid = t.oid)\n"
+ "LEFT OUTER JOIN pg_catalog.pg_attribute_encoding e "
+ "ON e.attrelid = a.attrelid AND e.attnum = a.attnum \n"
+ "WHERE a.attnum > 0::pg_catalog.int2\n"
+ "ORDER BY a.attrelid, a.attnum",
+ tbloids->data);
- ntups = PQntuples(res);
+ res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
+
+ ntups = PQntuples(res);
+
+ i_attrelid = PQfnumber(res, "attrelid");
+ i_attnum = PQfnumber(res, "attnum");
+ i_attname = PQfnumber(res, "attname");
+ i_atttypname = PQfnumber(res, "atttypname");
+ i_atttypmod = PQfnumber(res, "atttypmod");
+ i_attstattarget = PQfnumber(res, "attstattarget");
+ i_attstorage = PQfnumber(res, "attstorage");
+ i_typstorage = PQfnumber(res, "typstorage");
+ i_attidentity = PQfnumber(res, "attidentity");
+ i_attgenerated = PQfnumber(res, "attgenerated");
+ i_attisdropped = PQfnumber(res, "attisdropped");
+ i_attlen = PQfnumber(res, "attlen");
+ i_attalign = PQfnumber(res, "attalign");
+ i_attislocal = PQfnumber(res, "attislocal");
+ i_attnotnull = PQfnumber(res, "attnotnull");
+ i_attoptions = PQfnumber(res, "attoptions");
+ i_attcollation = PQfnumber(res, "attcollation");
+ i_attcompression = PQfnumber(res, "attcompression");
+ i_attfdwoptions = PQfnumber(res, "attfdwoptions");
+ i_attmissingval = PQfnumber(res, "attmissingval");
+ i_atthasdef = PQfnumber(res, "atthasdef");
+ i_attencoding = PQfnumber(res, "attencoding");
+
+ /* Within the next loop, we'll accumulate OIDs of tables with defaults */
+ resetPQExpBuffer(tbloids);
+ appendPQExpBufferChar(tbloids, '{');
+
+ /*
+ * Outer loop iterates once per table, not once per row. Incrementing of
+ * r is handled by the inner loop.
+ */
+ curtblindx = -1;
+ for (int r = 0; r < ntups;)
+ {
+ Oid attrelid = atooid(PQgetvalue(res, r, i_attrelid));
+ TableInfo *tbinfo = NULL;
+ int numatts;
+ bool hasdefaults;
+
+ /* Count rows for this table */
+ for (numatts = 1; numatts < ntups - r; numatts++)
+ if (atooid(PQgetvalue(res, r + numatts, i_attrelid)) != attrelid)
+ break;
+
+ /*
+ * Locate the associated TableInfo; we rely on tblinfo[] being in OID
+ * order.
+ */
+ while (++curtblindx < numTables)
+ {
+ tbinfo = &tblinfo[curtblindx];
+ if (tbinfo->dobj.catId.oid == attrelid)
+ break;
+ }
+ if (curtblindx >= numTables)
+ fatal("unrecognized table OID %u", attrelid);
+ /* cross-check that we only got requested tables */
+ if (tbinfo->relkind == RELKIND_SEQUENCE ||
+ !tbinfo->interesting)
+ fatal("unexpected column data for table \"%s\"",
+ tbinfo->dobj.name);
- i_attencoding = PQfnumber(res, "attencoding");
-
- tbinfo->numatts = ntups;
- tbinfo->attnames = (char **) pg_malloc(ntups * sizeof(char *));
- tbinfo->atttypnames = (char **) pg_malloc(ntups * sizeof(char *));
- tbinfo->atttypmod = (int *) pg_malloc(ntups * sizeof(int));
- tbinfo->attstattarget = (int *) pg_malloc(ntups * sizeof(int));
- tbinfo->attstorage = (char *) pg_malloc(ntups * sizeof(char));
- tbinfo->typstorage = (char *) pg_malloc(ntups * sizeof(char));
- tbinfo->attidentity = (char *) pg_malloc(ntups * sizeof(char));
- tbinfo->attgenerated = (char *) pg_malloc(ntups * sizeof(char));
- tbinfo->attisdropped = (bool *) pg_malloc(ntups * sizeof(bool));
- tbinfo->attlen = (int *) pg_malloc(ntups * sizeof(int));
- tbinfo->attalign = (char *) pg_malloc(ntups * sizeof(char));
- tbinfo->attislocal = (bool *) pg_malloc(ntups * sizeof(bool));
- tbinfo->attoptions = (char **) pg_malloc(ntups * sizeof(char *));
- tbinfo->attcollation = (Oid *) pg_malloc(ntups * sizeof(Oid));
- tbinfo->attcompression = (char *) pg_malloc(ntups * sizeof(char));
- tbinfo->attfdwoptions = (char **) pg_malloc(ntups * sizeof(char *));
- tbinfo->attmissingval = (char **) pg_malloc(ntups * sizeof(char *));
- tbinfo->notnull = (bool *) pg_malloc(ntups * sizeof(bool));
- tbinfo->inhNotNull = (bool *) pg_malloc(ntups * sizeof(bool));
+ /* Save data for this table */
+ tbinfo->numatts = numatts;
+ tbinfo->attnames = (char **) pg_malloc(numatts * sizeof(char *));
+ tbinfo->atttypnames = (char **) pg_malloc(numatts * sizeof(char *));
+ tbinfo->atttypmod = (int *) pg_malloc(numatts * sizeof(int));
+ tbinfo->attstattarget = (int *) pg_malloc(numatts * sizeof(int));
+ tbinfo->attstorage = (char *) pg_malloc(numatts * sizeof(char));
+ tbinfo->typstorage = (char *) pg_malloc(numatts * sizeof(char));
+ tbinfo->attidentity = (char *) pg_malloc(numatts * sizeof(char));
+ tbinfo->attgenerated = (char *) pg_malloc(numatts * sizeof(char));
+ tbinfo->attisdropped = (bool *) pg_malloc(numatts * sizeof(bool));
+ tbinfo->attlen = (int *) pg_malloc(numatts * sizeof(int));
+ tbinfo->attalign = (char *) pg_malloc(numatts * sizeof(char));
+ tbinfo->attislocal = (bool *) pg_malloc(numatts * sizeof(bool));
+ tbinfo->attoptions = (char **) pg_malloc(numatts * sizeof(char *));
+ tbinfo->attcollation = (Oid *) pg_malloc(numatts * sizeof(Oid));
+ tbinfo->attcompression = (char *) pg_malloc(numatts * sizeof(char));
+ tbinfo->attfdwoptions = (char **) pg_malloc(numatts * sizeof(char *));
+ tbinfo->attmissingval = (char **) pg_malloc(numatts * sizeof(char *));
+ tbinfo->notnull = (bool *) pg_malloc(numatts * sizeof(bool));
+ tbinfo->inhNotNull = (bool *) pg_malloc(numatts * sizeof(bool));
+ tbinfo->attrdefs = (AttrDefInfo **) pg_malloc(numatts * sizeof(AttrDefInfo *));
tbinfo->attencoding = (char **) pg_malloc(ntups * sizeof(char *));
- tbinfo->attrdefs = (AttrDefInfo **) pg_malloc(ntups * sizeof(AttrDefInfo *));
hasdefaults = false;
- for (int j = 0; j < ntups; j++)
+ for (int j = 0; j < numatts; j++, r++)
{
- if (j + 1 != atoi(PQgetvalue(res, j, PQfnumber(res, "attnum"))))
+ if (j + 1 != atoi(PQgetvalue(res, r, i_attnum)))
fatal("invalid column numbering in table \"%s\"",
tbinfo->dobj.name);
- tbinfo->attnames[j] = pg_strdup(PQgetvalue(res, j, PQfnumber(res, "attname")));
- tbinfo->atttypnames[j] = pg_strdup(PQgetvalue(res, j, PQfnumber(res, "atttypname")));
- tbinfo->atttypmod[j] = atoi(PQgetvalue(res, j, PQfnumber(res, "atttypmod")));
- tbinfo->attstattarget[j] = atoi(PQgetvalue(res, j, PQfnumber(res, "attstattarget")));
- tbinfo->attstorage[j] = *(PQgetvalue(res, j, PQfnumber(res, "attstorage")));
- tbinfo->typstorage[j] = *(PQgetvalue(res, j, PQfnumber(res, "typstorage")));
- tbinfo->attidentity[j] = *(PQgetvalue(res, j, PQfnumber(res, "attidentity")));
- tbinfo->attgenerated[j] = *(PQgetvalue(res, j, PQfnumber(res, "attgenerated")));
+ tbinfo->attnames[j] = pg_strdup(PQgetvalue(res, r, i_attname));
+ tbinfo->atttypnames[j] = pg_strdup(PQgetvalue(res, r, i_atttypname));
+ tbinfo->atttypmod[j] = atoi(PQgetvalue(res, r, i_atttypmod));
+ tbinfo->attstattarget[j] = atoi(PQgetvalue(res, r, i_attstattarget));
+ tbinfo->attstorage[j] = *(PQgetvalue(res, r, i_attstorage));
+ tbinfo->typstorage[j] = *(PQgetvalue(res, r, i_typstorage));
+ tbinfo->attidentity[j] = *(PQgetvalue(res, r, i_attidentity));
+ tbinfo->attgenerated[j] = *(PQgetvalue(res, r, i_attgenerated));
tbinfo->needs_override = tbinfo->needs_override || (tbinfo->attidentity[j] == ATTRIBUTE_IDENTITY_ALWAYS);
- tbinfo->attisdropped[j] = (PQgetvalue(res, j, PQfnumber(res, "attisdropped"))[0] == 't');
- tbinfo->attlen[j] = atoi(PQgetvalue(res, j, PQfnumber(res, "attlen")));
- tbinfo->attalign[j] = *(PQgetvalue(res, j, PQfnumber(res, "attalign")));
- tbinfo->attislocal[j] = (PQgetvalue(res, j, PQfnumber(res, "attislocal"))[0] == 't');
- tbinfo->notnull[j] = (PQgetvalue(res, j, PQfnumber(res, "attnotnull"))[0] == 't');
- tbinfo->attoptions[j] = pg_strdup(PQgetvalue(res, j, PQfnumber(res, "attoptions")));
- tbinfo->attcollation[j] = atooid(PQgetvalue(res, j, PQfnumber(res, "attcollation")));
- tbinfo->attcompression[j] = *(PQgetvalue(res, j, PQfnumber(res, "attcompression")));
- tbinfo->attfdwoptions[j] = pg_strdup(PQgetvalue(res, j, PQfnumber(res, "attfdwoptions")));
- tbinfo->attmissingval[j] = pg_strdup(PQgetvalue(res, j, PQfnumber(res, "attmissingval")));
+ tbinfo->attisdropped[j] = (PQgetvalue(res, r, i_attisdropped)[0] == 't');
+ tbinfo->attlen[j] = atoi(PQgetvalue(res, r, i_attlen));
+ tbinfo->attalign[j] = *(PQgetvalue(res, r, i_attalign));
+ tbinfo->attislocal[j] = (PQgetvalue(res, r, i_attislocal)[0] == 't');
+ tbinfo->notnull[j] = (PQgetvalue(res, r, i_attnotnull)[0] == 't');
+ tbinfo->attoptions[j] = pg_strdup(PQgetvalue(res, r, i_attoptions));
+ tbinfo->attcollation[j] = atooid(PQgetvalue(res, r, i_attcollation));
+ tbinfo->attcompression[j] = *(PQgetvalue(res, r, i_attcompression));
+ tbinfo->attfdwoptions[j] = pg_strdup(PQgetvalue(res, r, i_attfdwoptions));
+ tbinfo->attmissingval[j] = pg_strdup(PQgetvalue(res, r, i_attmissingval));
tbinfo->attrdefs[j] = NULL; /* fix below */
- if (PQgetvalue(res, j, PQfnumber(res, "atthasdef"))[0] == 't')
+ if (PQgetvalue(res, r, i_atthasdef)[0] == 't')
hasdefaults = true;
/* these flags will be set in flagInhAttrs() */
tbinfo->inhNotNull[j] = false;
-
/* column storage attributes */
if (!PQgetisnull(res, j, i_attencoding))
tbinfo->attencoding[j] = pg_strdup(PQgetvalue(res, j, i_attencoding));
@@ -10025,211 +9651,272 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
tbinfo->attencoding[j] = NULL;
}
- PQclear(res);
-
- /*
- * Get info about column defaults. This is skipped for a data-only
- * dump, as it is only needed for table schemas.
- */
- if (!dopt->dataOnly && hasdefaults)
+ if (hasdefaults)
{
- AttrDefInfo *attrdefs;
- int numDefaults;
-
- pg_log_info("finding default expressions of table \"%s.%s\"",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
-
- printfPQExpBuffer(q, "SELECT tableoid, oid, adnum, "
- "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc "
- "FROM pg_catalog.pg_attrdef "
- "WHERE adrelid = '%u'::pg_catalog.oid",
- tbinfo->dobj.catId.oid);
-
- res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
+ /* Collect OIDs of interesting tables that have defaults */
+ if (tbloids->len > 1) /* do we have more than the '{'? */
+ appendPQExpBufferChar(tbloids, ',');
+ appendPQExpBuffer(tbloids, "%u", tbinfo->dobj.catId.oid);
+ }
+ }
- numDefaults = PQntuples(res);
- attrdefs = (AttrDefInfo *) pg_malloc(numDefaults * sizeof(AttrDefInfo));
+ PQclear(res);
- for (int j = 0; j < numDefaults; j++)
- {
- int adnum;
+ /*
+ * Now get info about column defaults. This is skipped for a data-only
+ * dump, as it is only needed for table schemas.
+ */
+ if (!dopt->dataOnly && tbloids->len > 1)
+ {
+ AttrDefInfo *attrdefs;
+ int numDefaults;
+ TableInfo *tbinfo = NULL;
- adnum = atoi(PQgetvalue(res, j, 2));
+ pg_log_info("finding table default expressions");
- if (adnum <= 0 || adnum > ntups)
- fatal("invalid adnum value %d for table \"%s\"",
- adnum, tbinfo->dobj.name);
+ appendPQExpBufferChar(tbloids, '}');
- /*
- * dropped columns shouldn't have defaults, but just in case,
- * ignore 'em
- */
- if (tbinfo->attisdropped[adnum - 1])
- continue;
+ printfPQExpBuffer(q, "SELECT a.tableoid, a.oid, adrelid, adnum, "
+ "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc\n"
+ "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
+ "JOIN pg_catalog.pg_attrdef a ON (src.tbloid = a.adrelid)\n"
+ "ORDER BY a.adrelid, a.adnum",
+ tbloids->data);
- attrdefs[j].dobj.objType = DO_ATTRDEF;
- attrdefs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0));
- attrdefs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1));
- AssignDumpId(&attrdefs[j].dobj);
- attrdefs[j].adtable = tbinfo;
- attrdefs[j].adnum = adnum;
- attrdefs[j].adef_expr = pg_strdup(PQgetvalue(res, j, 3));
+ res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
- attrdefs[j].dobj.name = pg_strdup(tbinfo->dobj.name);
- attrdefs[j].dobj.namespace = tbinfo->dobj.namespace;
+ numDefaults = PQntuples(res);
+ attrdefs = (AttrDefInfo *) pg_malloc(numDefaults * sizeof(AttrDefInfo));
- attrdefs[j].dobj.dump = tbinfo->dobj.dump;
+ curtblindx = -1;
+ for (int j = 0; j < numDefaults; j++)
+ {
+ Oid adtableoid = atooid(PQgetvalue(res, j, 0));
+ Oid adoid = atooid(PQgetvalue(res, j, 1));
+ Oid adrelid = atooid(PQgetvalue(res, j, 2));
+ int adnum = atoi(PQgetvalue(res, j, 3));
+ char *adsrc = PQgetvalue(res, j, 4);
- /*
- * Figure out whether the default/generation expression should
- * be dumped as part of the main CREATE TABLE (or similar)
- * command or as a separate ALTER TABLE (or similar) command.
- * The preference is to put it into the CREATE command, but in
- * some cases that's not possible.
- */
- if (tbinfo->attgenerated[adnum - 1])
- {
- /*
- * Column generation expressions cannot be dumped
- * separately, because there is no syntax for it. The
- * !shouldPrintColumn case below will be tempted to set
- * them to separate if they are attached to an inherited
- * column without a local definition, but that would be
- * wrong and unnecessary, because generation expressions
- * are always inherited, so there is no need to set them
- * again in child tables, and there is no syntax for it
- * either. By setting separate to false here we prevent
- * the "default" from being processed as its own dumpable
- * object, and flagInhAttrs() will remove it from the
- * table when it detects that it belongs to an inherited
- * column.
- */
- attrdefs[j].separate = false;
- }
- else if (tbinfo->relkind == RELKIND_VIEW)
- {
- /*
- * Defaults on a VIEW must always be dumped as separate
- * ALTER TABLE commands.
- */
- attrdefs[j].separate = true;
- }
- else if (!shouldPrintColumn(dopt, tbinfo, adnum - 1))
- {
- /* column will be suppressed, print default separately */
- attrdefs[j].separate = true;
- }
- else
+ /*
+ * Locate the associated TableInfo; we rely on tblinfo[] being in
+ * OID order.
+ */
+ if (tbinfo == NULL || tbinfo->dobj.catId.oid != adrelid)
+ {
+ while (++curtblindx < numTables)
{
- attrdefs[j].separate = false;
+ tbinfo = &tblinfo[curtblindx];
+ if (tbinfo->dobj.catId.oid == adrelid)
+ break;
}
+ if (curtblindx >= numTables)
+ fatal("unrecognized table OID %u", adrelid);
+ }
- if (!attrdefs[j].separate)
- {
- /*
- * Mark the default as needing to appear before the table,
- * so that any dependencies it has must be emitted before
- * the CREATE TABLE. If this is not possible, we'll
- * change to "separate" mode while sorting dependencies.
- */
- addObjectDependency(&tbinfo->dobj,
- attrdefs[j].dobj.dumpId);
- }
+ if (adnum <= 0 || adnum > tbinfo->numatts)
+ fatal("invalid adnum value %d for table \"%s\"",
+ adnum, tbinfo->dobj.name);
- tbinfo->attrdefs[adnum - 1] = &attrdefs[j];
- }
- PQclear(res);
- }
+ /*
+ * dropped columns shouldn't have defaults, but just in case,
+ * ignore 'em
+ */
+ if (tbinfo->attisdropped[adnum - 1])
+ continue;
- /*
- * Get info about table CHECK constraints. This is skipped for a
- * data-only dump, as it is only needed for table schemas.
- */
- if (tbinfo->ncheck > 0 && !dopt->dataOnly)
- {
- ConstraintInfo *constrs;
- int numConstrs;
+ attrdefs[j].dobj.objType = DO_ATTRDEF;
+ attrdefs[j].dobj.catId.tableoid = adtableoid;
+ attrdefs[j].dobj.catId.oid = adoid;
+ AssignDumpId(&attrdefs[j].dobj);
+ attrdefs[j].adtable = tbinfo;
+ attrdefs[j].adnum = adnum;
+ attrdefs[j].adef_expr = pg_strdup(adsrc);
- pg_log_info("finding check constraints for table \"%s.%s\"",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
+ attrdefs[j].dobj.name = pg_strdup(tbinfo->dobj.name);
+ attrdefs[j].dobj.namespace = tbinfo->dobj.namespace;
- resetPQExpBuffer(q);
- if (fout->remoteVersion >= 90200)
+ attrdefs[j].dobj.dump = tbinfo->dobj.dump;
+
+ /*
+ * Figure out whether the default/generation expression should be
+ * dumped as part of the main CREATE TABLE (or similar) command or
+ * as a separate ALTER TABLE (or similar) command. The preference
+ * is to put it into the CREATE command, but in some cases that's
+ * not possible.
+ */
+ if (tbinfo->attgenerated[adnum - 1])
+ {
+ /*
+ * Column generation expressions cannot be dumped separately,
+ * because there is no syntax for it. The !shouldPrintColumn
+ * case below will be tempted to set them to separate if they
+ * are attached to an inherited column without a local
+ * definition, but that would be wrong and unnecessary,
+ * because generation expressions are always inherited, so
+ * there is no need to set them again in child tables, and
+ * there is no syntax for it either. By setting separate to
+ * false here we prevent the "default" from being processed as
+ * its own dumpable object, and flagInhAttrs() will remove it
+ * from the table when it detects that it belongs to an
+ * inherited column.
+ */
+ attrdefs[j].separate = false;
+ }
+ else if (tbinfo->relkind == RELKIND_VIEW)
{
/*
- * convalidated is new in 9.2 (actually, it is there in 9.1,
- * but it wasn't ever false for check constraints until 9.2).
+ * Defaults on a VIEW must always be dumped as separate ALTER
+ * TABLE commands.
*/
- appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
- "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
- "conislocal, convalidated "
- "FROM pg_catalog.pg_constraint "
- "WHERE conrelid = '%u'::pg_catalog.oid "
- " AND contype = 'c' "
- "ORDER BY conname",
- tbinfo->dobj.catId.oid);
+ attrdefs[j].separate = true;
}
- else if (fout->remoteVersion >= 80400)
+ else if (!shouldPrintColumn(dopt, tbinfo, adnum - 1))
{
- /* conislocal is new in 8.4 */
- appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
- "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
- "conislocal, true AS convalidated "
- "FROM pg_catalog.pg_constraint "
- "WHERE conrelid = '%u'::pg_catalog.oid "
- " AND contype = 'c' "
- "ORDER BY conname",
- tbinfo->dobj.catId.oid);
+ /* column will be suppressed, print default separately */
+ attrdefs[j].separate = true;
}
else
{
- appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
- "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
- "true AS conislocal, true AS convalidated "
- "FROM pg_catalog.pg_constraint "
- "WHERE conrelid = '%u'::pg_catalog.oid "
- " AND contype = 'c' "
- "ORDER BY conname",
- tbinfo->dobj.catId.oid);
+ attrdefs[j].separate = false;
+ }
+
+ if (!attrdefs[j].separate)
+ {
+ /*
+ * Mark the default as needing to appear before the table, so
+ * that any dependencies it has must be emitted before the
+ * CREATE TABLE. If this is not possible, we'll change to
+ * "separate" mode while sorting dependencies.
+ */
+ addObjectDependency(&tbinfo->dobj,
+ attrdefs[j].dobj.dumpId);
}
- res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
+ tbinfo->attrdefs[adnum - 1] = &attrdefs[j];
+ }
+
+ PQclear(res);
+ }
+
+ /*
+ * Get info about table CHECK constraints. This is skipped for a
+ * data-only dump, as it is only needed for table schemas.
+ */
+ if (!dopt->dataOnly && checkoids->len > 2)
+ {
+ ConstraintInfo *constrs;
+ int numConstrs;
+ int i_tableoid;
+ int i_oid;
+ int i_conrelid;
+ int i_conname;
+ int i_consrc;
+ int i_conislocal;
+ int i_convalidated;
+
+ pg_log_info("finding table check constraints");
+
+ resetPQExpBuffer(q);
+ appendPQExpBufferStr(q,
+ "SELECT c.tableoid, c.oid, conrelid, conname, "
+ "pg_catalog.pg_get_constraintdef(c.oid) AS consrc, ");
+ if (fout->remoteVersion >= 90200)
+ {
+ /*
+ * convalidated is new in 9.2 (actually, it is there in 9.1, but
+ * it wasn't ever false for check constraints until 9.2).
+ */
+ appendPQExpBufferStr(q,
+ "conislocal, convalidated ");
+ }
+ else if (fout->remoteVersion >= 80400)
+ {
+ /* conislocal is new in 8.4 */
+ appendPQExpBufferStr(q,
+ "conislocal, true AS convalidated ");
+ }
+ else
+ {
+ appendPQExpBufferStr(q,
+ "true AS conislocal, true AS convalidated ");
+ }
+ appendPQExpBuffer(q,
+ "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
+ "JOIN pg_catalog.pg_constraint c ON (src.tbloid = c.conrelid)\n"
+ "WHERE contype = 'c' "
+ "ORDER BY c.conrelid, c.conname",
+ checkoids->data);
+
+ res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
+
+ numConstrs = PQntuples(res);
+ constrs = (ConstraintInfo *) pg_malloc(numConstrs * sizeof(ConstraintInfo));
+
+ i_tableoid = PQfnumber(res, "tableoid");
+ i_oid = PQfnumber(res, "oid");
+ i_conrelid = PQfnumber(res, "conrelid");
+ i_conname = PQfnumber(res, "conname");
+ i_consrc = PQfnumber(res, "consrc");
+ i_conislocal = PQfnumber(res, "conislocal");
+ i_convalidated = PQfnumber(res, "convalidated");
+
+ /* As above, this loop iterates once per table, not once per row */
+ curtblindx = -1;
+ for (int j = 0; j < numConstrs;)
+ {
+ Oid conrelid = atooid(PQgetvalue(res, j, i_conrelid));
+ TableInfo *tbinfo = NULL;
+ int numcons;
+
+ /* Count rows for this table */
+ for (numcons = 1; numcons < numConstrs - j; numcons++)
+ if (atooid(PQgetvalue(res, j + numcons, i_conrelid)) != conrelid)
+ break;
+
+ /*
+ * Locate the associated TableInfo; we rely on tblinfo[] being in
+ * OID order.
+ */
+ while (++curtblindx < numTables)
+ {
+ tbinfo = &tblinfo[curtblindx];
+ if (tbinfo->dobj.catId.oid == conrelid)
+ break;
+ }
+ if (curtblindx >= numTables)
+ fatal("unrecognized table OID %u", conrelid);
- numConstrs = PQntuples(res);
- if (numConstrs != tbinfo->ncheck)
+ if (numcons != tbinfo->ncheck)
{
pg_log_error(ngettext("expected %d check constraint on table \"%s\" but found %d",
"expected %d check constraints on table \"%s\" but found %d",
tbinfo->ncheck),
- tbinfo->ncheck, tbinfo->dobj.name, numConstrs);
+ tbinfo->ncheck, tbinfo->dobj.name, numcons);
pg_log_error("(The system catalogs might be corrupted.)");
exit_nicely(1);
}
- constrs = (ConstraintInfo *) pg_malloc(numConstrs * sizeof(ConstraintInfo));
- tbinfo->checkexprs = constrs;
+ tbinfo->checkexprs = constrs + j;
- for (int j = 0; j < numConstrs; j++)
+ for (int c = 0; c < numcons; c++, j++)
{
- bool validated = PQgetvalue(res, j, 5)[0] == 't';
+ bool validated = PQgetvalue(res, j, i_convalidated)[0] == 't';
constrs[j].dobj.objType = DO_CONSTRAINT;
- constrs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0));
- constrs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1));
+ constrs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
+ constrs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
AssignDumpId(&constrs[j].dobj);
- constrs[j].dobj.name = pg_strdup(PQgetvalue(res, j, 2));
+ constrs[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname));
constrs[j].dobj.namespace = tbinfo->dobj.namespace;
constrs[j].contable = tbinfo;
constrs[j].condomain = NULL;
constrs[j].contype = 'c';
- constrs[j].condef = pg_strdup(PQgetvalue(res, j, 3));
+ constrs[j].condef = pg_strdup(PQgetvalue(res, j, i_consrc));
constrs[j].confrelid = InvalidOid;
constrs[j].conindex = 0;
constrs[j].condeferrable = false;
constrs[j].condeferred = false;
- constrs[j].conislocal = (PQgetvalue(res, j, 4)[0] == 't');
+ constrs[j].conislocal = (PQgetvalue(res, j, i_conislocal)[0] == 't');
/*
* An unvalidated constraint needs to be dumped separately, so
@@ -10259,11 +9946,14 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
* constraint must be split out from the table definition.
*/
}
- PQclear(res);
}
+
+ PQclear(res);
}
destroyPQExpBuffer(q);
+ destroyPQExpBuffer(tbloids);
+ destroyPQExpBuffer(checkoids);
}
/*
@@ -10319,13 +10009,6 @@ getTSParsers(Archive *fout, int *numTSParsers)
int i_prsheadline;
int i_prslextype;
- /* Before 8.3, there is no built-in text search support */
- if (fout->remoteVersion < 80300)
- {
- *numTSParsers = 0;
- return NULL;
- }
-
query = createPQExpBuffer();
/*
@@ -10372,9 +10055,6 @@ getTSParsers(Archive *fout, int *numTSParsers)
/* Decide whether we want to dump it */
selectDumpableObject(&(prsinfo[i].dobj), fout);
-
- /* Text Search Parsers do not currently have ACLs. */
- prsinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -10403,24 +10083,16 @@ getTSDictionaries(Archive *fout, int *numTSDicts)
int i_oid;
int i_dictname;
int i_dictnamespace;
- int i_rolname;
+ int i_dictowner;
int i_dicttemplate;
int i_dictinitoption;
- /* Before 8.3, there is no built-in text search support */
- if (fout->remoteVersion < 80300)
- {
- *numTSDicts = 0;
- return NULL;
- }
-
query = createPQExpBuffer();
appendPQExpBuffer(query, "SELECT tableoid, oid, dictname, "
- "dictnamespace, (%s dictowner) AS rolname, "
+ "dictnamespace, dictowner, "
"dicttemplate, dictinitoption "
- "FROM pg_ts_dict",
- username_subquery);
+ "FROM pg_ts_dict");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -10433,7 +10105,7 @@ getTSDictionaries(Archive *fout, int *numTSDicts)
i_oid = PQfnumber(res, "oid");
i_dictname = PQfnumber(res, "dictname");
i_dictnamespace = PQfnumber(res, "dictnamespace");
- i_rolname = PQfnumber(res, "rolname");
+ i_dictowner = PQfnumber(res, "dictowner");
i_dictinitoption = PQfnumber(res, "dictinitoption");
i_dicttemplate = PQfnumber(res, "dicttemplate");
@@ -10446,7 +10118,7 @@ getTSDictionaries(Archive *fout, int *numTSDicts)
dictinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_dictname));
dictinfo[i].dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_dictnamespace)));
- dictinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ dictinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_dictowner));
dictinfo[i].dicttemplate = atooid(PQgetvalue(res, i, i_dicttemplate));
if (PQgetisnull(res, i, i_dictinitoption))
dictinfo[i].dictinitoption = NULL;
@@ -10455,9 +10127,6 @@ getTSDictionaries(Archive *fout, int *numTSDicts)
/* Decide whether we want to dump it */
selectDumpableObject(&(dictinfo[i].dobj), fout);
-
- /* Text Search Dictionaries do not currently have ACLs. */
- dictinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -10489,13 +10158,6 @@ getTSTemplates(Archive *fout, int *numTSTemplates)
int i_tmplinit;
int i_tmpllexize;
- /* Before 8.3, there is no built-in text search support */
- if (fout->remoteVersion < 80300)
- {
- *numTSTemplates = 0;
- return NULL;
- }
-
query = createPQExpBuffer();
appendPQExpBufferStr(query, "SELECT tableoid, oid, tmplname, "
@@ -10530,9 +10192,6 @@ getTSTemplates(Archive *fout, int *numTSTemplates)
/* Decide whether we want to dump it */
selectDumpableObject(&(tmplinfo[i].dobj), fout);
-
- /* Text Search Templates do not currently have ACLs. */
- tmplinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -10561,22 +10220,14 @@ getTSConfigurations(Archive *fout, int *numTSConfigs)
int i_oid;
int i_cfgname;
int i_cfgnamespace;
- int i_rolname;
+ int i_cfgowner;
int i_cfgparser;
- /* Before 8.3, there is no built-in text search support */
- if (fout->remoteVersion < 80300)
- {
- *numTSConfigs = 0;
- return NULL;
- }
-
query = createPQExpBuffer();
appendPQExpBuffer(query, "SELECT tableoid, oid, cfgname, "
- "cfgnamespace, (%s cfgowner) AS rolname, cfgparser "
- "FROM pg_ts_config",
- username_subquery);
+ "cfgnamespace, cfgowner, cfgparser "
+ "FROM pg_ts_config");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -10589,7 +10240,7 @@ getTSConfigurations(Archive *fout, int *numTSConfigs)
i_oid = PQfnumber(res, "oid");
i_cfgname = PQfnumber(res, "cfgname");
i_cfgnamespace = PQfnumber(res, "cfgnamespace");
- i_rolname = PQfnumber(res, "rolname");
+ i_cfgowner = PQfnumber(res, "cfgowner");
i_cfgparser = PQfnumber(res, "cfgparser");
for (i = 0; i < ntups; i++)
@@ -10601,14 +10252,11 @@ getTSConfigurations(Archive *fout, int *numTSConfigs)
cfginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_cfgname));
cfginfo[i].dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_cfgnamespace)));
- cfginfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ cfginfo[i].rolname = getRoleName(PQgetvalue(res, i, i_cfgowner));
cfginfo[i].cfgparser = atooid(PQgetvalue(res, i, i_cfgparser));
/* Decide whether we want to dump it */
selectDumpableObject(&(cfginfo[i].dobj), fout);
-
- /* Text Search Configurations do not currently have ACLs. */
- cfginfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -10628,7 +10276,6 @@ getTSConfigurations(Archive *fout, int *numTSConfigs)
FdwInfo *
getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
@@ -10637,13 +10284,11 @@ getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
int i_tableoid;
int i_oid;
int i_fdwname;
- int i_rolname;
+ int i_fdwowner;
int i_fdwhandler;
int i_fdwvalidator;
int i_fdwacl;
- int i_rfdwacl;
- int i_initfdwacl;
- int i_initrfdwacl;
+ int i_acldefault;
int i_fdwoptions;
/* Before 8.4, there are no foreign-data wrappers */
@@ -10655,80 +10300,51 @@ getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
query = createPQExpBuffer();
- if (fout->remoteVersion >= 90600)
+ if (fout->remoteVersion >= 90200)
{
- PQExpBuffer acl_subquery = createPQExpBuffer();
- PQExpBuffer racl_subquery = createPQExpBuffer();
- PQExpBuffer initacl_subquery = createPQExpBuffer();
- PQExpBuffer initracl_subquery = createPQExpBuffer();
-
- buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
- initracl_subquery, "f.fdwacl", "f.fdwowner", "'F'",
- dopt->binary_upgrade);
-
- appendPQExpBuffer(query, "SELECT f.tableoid, f.oid, f.fdwname, "
- "(%s f.fdwowner) AS rolname, "
- "f.fdwhandler::pg_catalog.regproc, "
- "f.fdwvalidator::pg_catalog.regproc, "
- "%s AS fdwacl, "
- "%s AS rfdwacl, "
- "%s AS initfdwacl, "
- "%s AS initrfdwacl, "
+ appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
+ "fdwowner, "
+ "fdwhandler::pg_catalog.regproc, "
+ "fdwvalidator::pg_catalog.regproc, "
+ "fdwacl, "
+ "acldefault('F', fdwowner) AS acldefault, "
"array_to_string(ARRAY("
"SELECT quote_ident(option_name) || ' ' || "
"quote_literal(option_value) "
- "FROM pg_options_to_table(f.fdwoptions) "
+ "FROM pg_options_to_table(fdwoptions) "
"ORDER BY option_name"
"), E',\n ') AS fdwoptions "
- "FROM pg_foreign_data_wrapper f "
- "LEFT JOIN pg_init_privs pip ON "
- "(f.oid = pip.objoid "
- "AND pip.classoid = 'pg_foreign_data_wrapper'::regclass "
- "AND pip.objsubid = 0) ",
- username_subquery,
- acl_subquery->data,
- racl_subquery->data,
- initacl_subquery->data,
- initracl_subquery->data);
-
- destroyPQExpBuffer(acl_subquery);
- destroyPQExpBuffer(racl_subquery);
- destroyPQExpBuffer(initacl_subquery);
- destroyPQExpBuffer(initracl_subquery);
+ "FROM pg_foreign_data_wrapper");
}
else if (fout->remoteVersion >= 90100)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
- "(%s fdwowner) AS rolname, "
+ "fdwowner, "
"fdwhandler::pg_catalog.regproc, "
"fdwvalidator::pg_catalog.regproc, fdwacl, "
- "NULL as rfdwacl, "
- "NULL as initfdwacl, NULL AS initrfdwacl, "
+ "NULL AS acldefault, "
"array_to_string(ARRAY("
"SELECT quote_ident(option_name) || ' ' || "
"quote_literal(option_value) "
"FROM pg_options_to_table(fdwoptions) "
"ORDER BY option_name"
"), E',\n ') AS fdwoptions "
- "FROM pg_foreign_data_wrapper",
- username_subquery);
+ "FROM pg_foreign_data_wrapper");
}
else
{
appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
- "(%s fdwowner) AS rolname, "
+ "fdwowner, "
"'-' AS fdwhandler, "
"fdwvalidator::pg_catalog.regproc, fdwacl, "
- "NULL as rfdwacl, "
- "NULL as initfdwacl, NULL AS initrfdwacl, "
+ "NULL AS acldefault, "
"array_to_string(ARRAY("
"SELECT quote_ident(option_name) || ' ' || "
"quote_literal(option_value) "
"FROM pg_options_to_table(fdwoptions) "
"ORDER BY option_name"
"), E',\n ') AS fdwoptions "
- "FROM pg_foreign_data_wrapper",
- username_subquery);
+ "FROM pg_foreign_data_wrapper");
}
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -10741,13 +10357,11 @@ getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
i_fdwname = PQfnumber(res, "fdwname");
- i_rolname = PQfnumber(res, "rolname");
+ i_fdwowner = PQfnumber(res, "fdwowner");
i_fdwhandler = PQfnumber(res, "fdwhandler");
i_fdwvalidator = PQfnumber(res, "fdwvalidator");
i_fdwacl = PQfnumber(res, "fdwacl");
- i_rfdwacl = PQfnumber(res, "rfdwacl");
- i_initfdwacl = PQfnumber(res, "initfdwacl");
- i_initrfdwacl = PQfnumber(res, "initrfdwacl");
+ i_acldefault = PQfnumber(res, "acldefault");
i_fdwoptions = PQfnumber(res, "fdwoptions");
for (i = 0; i < ntups; i++)
@@ -10758,14 +10372,14 @@ getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
AssignDumpId(&fdwinfo[i].dobj);
fdwinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_fdwname));
fdwinfo[i].dobj.namespace = NULL;
- fdwinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ fdwinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_fdwacl));
+ fdwinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
+ fdwinfo[i].dacl.privtype = 0;
+ fdwinfo[i].dacl.initprivs = NULL;
+ fdwinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_fdwowner));
fdwinfo[i].fdwhandler = pg_strdup(PQgetvalue(res, i, i_fdwhandler));
fdwinfo[i].fdwvalidator = pg_strdup(PQgetvalue(res, i, i_fdwvalidator));
fdwinfo[i].fdwoptions = pg_strdup(PQgetvalue(res, i, i_fdwoptions));
- fdwinfo[i].fdwacl = pg_strdup(PQgetvalue(res, i, i_fdwacl));
- fdwinfo[i].rfdwacl = pg_strdup(PQgetvalue(res, i, i_rfdwacl));
- fdwinfo[i].initfdwacl = pg_strdup(PQgetvalue(res, i, i_initfdwacl));
- fdwinfo[i].initrfdwacl = pg_strdup(PQgetvalue(res, i, i_initrfdwacl));
/* Decide whether we want to dump it */
selectDumpableObject(&(fdwinfo[i].dobj), fout);
@@ -10774,11 +10388,9 @@ getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
if (fdwinfo[i].dobj.catId.oid < (Oid) FirstNormalObjectId)
fdwinfo[i].dobj.dump = DUMP_COMPONENT_NONE;
- /* Do not try to dump ACL if no ACL exists. */
- if (PQgetisnull(res, i, i_fdwacl) && PQgetisnull(res, i, i_rfdwacl) &&
- PQgetisnull(res, i, i_initfdwacl) &&
- PQgetisnull(res, i, i_initrfdwacl))
- fdwinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Mark whether FDW has an ACL */
+ if (!PQgetisnull(res, i, i_fdwacl))
+ fdwinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -10798,7 +10410,6 @@ getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
ForeignServerInfo *
getForeignServers(Archive *fout, int *numForeignServers)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
@@ -10807,14 +10418,12 @@ getForeignServers(Archive *fout, int *numForeignServers)
int i_tableoid;
int i_oid;
int i_srvname;
- int i_rolname;
+ int i_srvowner;
int i_srvfdw;
int i_srvtype;
int i_srvversion;
int i_srvacl;
- int i_rsrvacl;
- int i_initsrvacl;
- int i_initrsrvacl;
+ int i_acldefault;
int i_srvoptions;
/* Before 8.4, there are no foreign servers */
@@ -10826,61 +10435,33 @@ getForeignServers(Archive *fout, int *numForeignServers)
query = createPQExpBuffer();
- if (fout->remoteVersion >= 90600)
+ if (fout->remoteVersion >= 90200)
{
- PQExpBuffer acl_subquery = createPQExpBuffer();
- PQExpBuffer racl_subquery = createPQExpBuffer();
- PQExpBuffer initacl_subquery = createPQExpBuffer();
- PQExpBuffer initracl_subquery = createPQExpBuffer();
-
- buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
- initracl_subquery, "f.srvacl", "f.srvowner", "'S'",
- dopt->binary_upgrade);
-
- appendPQExpBuffer(query, "SELECT f.tableoid, f.oid, f.srvname, "
- "(%s f.srvowner) AS rolname, "
- "f.srvfdw, f.srvtype, f.srvversion, "
- "%s AS srvacl, "
- "%s AS rsrvacl, "
- "%s AS initsrvacl, "
- "%s AS initrsrvacl, "
+ appendPQExpBuffer(query, "SELECT tableoid, oid, srvname, "
+ "srvowner, "
+ "srvfdw, srvtype, srvversion, srvacl, "
+ "acldefault('S', srvowner) AS acldefault, "
"array_to_string(ARRAY("
"SELECT quote_ident(option_name) || ' ' || "
"quote_literal(option_value) "
- "FROM pg_options_to_table(f.srvoptions) "
+ "FROM pg_options_to_table(srvoptions) "
"ORDER BY option_name"
"), E',\n ') AS srvoptions "
- "FROM pg_foreign_server f "
- "LEFT JOIN pg_init_privs pip "
- "ON (f.oid = pip.objoid "
- "AND pip.classoid = 'pg_foreign_server'::regclass "
- "AND pip.objsubid = 0) ",
- username_subquery,
- acl_subquery->data,
- racl_subquery->data,
- initacl_subquery->data,
- initracl_subquery->data);
-
- destroyPQExpBuffer(acl_subquery);
- destroyPQExpBuffer(racl_subquery);
- destroyPQExpBuffer(initacl_subquery);
- destroyPQExpBuffer(initracl_subquery);
+ "FROM pg_foreign_server");
}
else
{
appendPQExpBuffer(query, "SELECT tableoid, oid, srvname, "
- "(%s srvowner) AS rolname, "
+ "srvowner, "
"srvfdw, srvtype, srvversion, srvacl, "
- "NULL AS rsrvacl, "
- "NULL AS initsrvacl, NULL AS initrsrvacl, "
+ "NULL AS acldefault, "
"array_to_string(ARRAY("
"SELECT quote_ident(option_name) || ' ' || "
"quote_literal(option_value) "
"FROM pg_options_to_table(srvoptions) "
"ORDER BY option_name"
"), E',\n ') AS srvoptions "
- "FROM pg_foreign_server",
- username_subquery);
+ "FROM pg_foreign_server");
}
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -10893,14 +10474,12 @@ getForeignServers(Archive *fout, int *numForeignServers)
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
i_srvname = PQfnumber(res, "srvname");
- i_rolname = PQfnumber(res, "rolname");
+ i_srvowner = PQfnumber(res, "srvowner");
i_srvfdw = PQfnumber(res, "srvfdw");
i_srvtype = PQfnumber(res, "srvtype");
i_srvversion = PQfnumber(res, "srvversion");
i_srvacl = PQfnumber(res, "srvacl");
- i_rsrvacl = PQfnumber(res, "rsrvacl");
- i_initsrvacl = PQfnumber(res, "initsrvacl");
- i_initrsrvacl = PQfnumber(res, "initrsrvacl");
+ i_acldefault = PQfnumber(res, "acldefault");
i_srvoptions = PQfnumber(res, "srvoptions");
for (i = 0; i < ntups; i++)
@@ -10911,15 +10490,15 @@ getForeignServers(Archive *fout, int *numForeignServers)
AssignDumpId(&srvinfo[i].dobj);
srvinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_srvname));
srvinfo[i].dobj.namespace = NULL;
- srvinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ srvinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_srvacl));
+ srvinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
+ srvinfo[i].dacl.privtype = 0;
+ srvinfo[i].dacl.initprivs = NULL;
+ srvinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_srvowner));
srvinfo[i].srvfdw = atooid(PQgetvalue(res, i, i_srvfdw));
srvinfo[i].srvtype = pg_strdup(PQgetvalue(res, i, i_srvtype));
srvinfo[i].srvversion = pg_strdup(PQgetvalue(res, i, i_srvversion));
srvinfo[i].srvoptions = pg_strdup(PQgetvalue(res, i, i_srvoptions));
- srvinfo[i].srvacl = pg_strdup(PQgetvalue(res, i, i_srvacl));
- srvinfo[i].rsrvacl = pg_strdup(PQgetvalue(res, i, i_rsrvacl));
- srvinfo[i].initsrvacl = pg_strdup(PQgetvalue(res, i, i_initsrvacl));
- srvinfo[i].initrsrvacl = pg_strdup(PQgetvalue(res, i, i_initrsrvacl));
/* Decide whether we want to dump it */
selectDumpableObject(&(srvinfo[i].dobj), fout);
@@ -10928,11 +10507,12 @@ getForeignServers(Archive *fout, int *numForeignServers)
if (srvinfo[i].dobj.catId.oid < (Oid) FirstNormalObjectId)
srvinfo[i].dobj.dump = DUMP_COMPONENT_NONE;
- /* Do not try to dump ACL if no ACL exists. */
- if (PQgetisnull(res, i, i_srvacl) && PQgetisnull(res, i, i_rsrvacl) &&
- PQgetisnull(res, i, i_initsrvacl) &&
- PQgetisnull(res, i, i_initrsrvacl))
- srvinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Servers have user mappings */
+ srvinfo[i].dobj.components |= DUMP_COMPONENT_USERMAP;
+
+ /* Mark whether server has an ACL */
+ if (!PQgetisnull(res, i, i_srvacl))
+ srvinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
}
PQclear(res);
@@ -10962,9 +10542,7 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
int i_defaclnamespace;
int i_defaclobjtype;
int i_defaclacl;
- int i_rdefaclacl;
- int i_initdefaclacl;
- int i_initrdefaclacl;
+ int i_acldefault;
int i,
ntups;
@@ -10976,13 +10554,15 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
query = createPQExpBuffer();
- if (fout->remoteVersion >= 90600)
- {
- PQExpBuffer acl_subquery = createPQExpBuffer();
- PQExpBuffer racl_subquery = createPQExpBuffer();
- PQExpBuffer initacl_subquery = createPQExpBuffer();
- PQExpBuffer initracl_subquery = createPQExpBuffer();
+ appendPQExpBuffer(query,
+ "SELECT oid, tableoid, "
+ "defaclrole, "
+ "defaclnamespace, "
+ "defaclobjtype, "
+ "defaclacl, ");
+ if (fout->remoteVersion >= 90200)
+ {
/*
* Global entries (with defaclnamespace=0) replace the hard-wired
* default ACL for their object type. We should dump them as deltas
@@ -10990,58 +10570,24 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
* for interpreting the ALTER DEFAULT PRIVILEGES commands. On the
* other hand, non-global entries can only add privileges not revoke
* them. We must dump those as-is (i.e., as deltas from an empty
- * ACL). We implement that by passing NULL as the object type for
- * acldefault(), which works because acldefault() is STRICT.
+ * ACL).
*
* We can use defaclobjtype as the object type for acldefault(),
* except for the case of 'S' (DEFACLOBJ_SEQUENCE) which must be
* converted to 's'.
*/
- buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
- initracl_subquery, "defaclacl", "defaclrole",
- "CASE WHEN defaclnamespace = 0 THEN"
- " CASE WHEN defaclobjtype = 'S' THEN 's'::\"char\""
- " ELSE defaclobjtype END "
- "ELSE NULL END",
- dopt->binary_upgrade);
-
- appendPQExpBuffer(query, "SELECT d.oid, d.tableoid, "
- "(%s d.defaclrole) AS defaclrole, "
- "d.defaclnamespace, "
- "d.defaclobjtype, "
- "%s AS defaclacl, "
- "%s AS rdefaclacl, "
- "%s AS initdefaclacl, "
- "%s AS initrdefaclacl "
- "FROM pg_default_acl d "
- "LEFT JOIN pg_init_privs pip ON "
- "(d.oid = pip.objoid "
- "AND pip.classoid = 'pg_default_acl'::regclass "
- "AND pip.objsubid = 0) ",
- username_subquery,
- acl_subquery->data,
- racl_subquery->data,
- initacl_subquery->data,
- initracl_subquery->data);
-
- destroyPQExpBuffer(acl_subquery);
- destroyPQExpBuffer(racl_subquery);
- destroyPQExpBuffer(initacl_subquery);
- destroyPQExpBuffer(initracl_subquery);
+ appendPQExpBufferStr(query,
+ "CASE WHEN defaclnamespace = 0 THEN "
+ "acldefault(CASE WHEN defaclobjtype = 'S' "
+ "THEN 's'::\"char\" ELSE defaclobjtype END, "
+ "defaclrole) ELSE '{}' END AS acldefault ");
}
else
- {
- appendPQExpBuffer(query, "SELECT oid, tableoid, "
- "(%s defaclrole) AS defaclrole, "
- "defaclnamespace, "
- "defaclobjtype, "
- "defaclacl, "
- "NULL AS rdefaclacl, "
- "NULL AS initdefaclacl, "
- "NULL AS initrdefaclacl "
- "FROM pg_default_acl",
- username_subquery);
- }
+ appendPQExpBufferStr(query,
+ "NULL AS acldefault ");
+
+ appendPQExpBufferStr(query,
+ "FROM pg_default_acl");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -11056,9 +10602,7 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
i_defaclnamespace = PQfnumber(res, "defaclnamespace");
i_defaclobjtype = PQfnumber(res, "defaclobjtype");
i_defaclacl = PQfnumber(res, "defaclacl");
- i_rdefaclacl = PQfnumber(res, "rdefaclacl");
- i_initdefaclacl = PQfnumber(res, "initdefaclacl");
- i_initrdefaclacl = PQfnumber(res, "initrdefaclacl");
+ i_acldefault = PQfnumber(res, "acldefault");
for (i = 0; i < ntups; i++)
{
@@ -11076,12 +10620,15 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
else
daclinfo[i].dobj.namespace = NULL;
- daclinfo[i].defaclrole = pg_strdup(PQgetvalue(res, i, i_defaclrole));
+ daclinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_defaclacl));
+ daclinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
+ daclinfo[i].dacl.privtype = 0;
+ daclinfo[i].dacl.initprivs = NULL;
+ daclinfo[i].defaclrole = getRoleName(PQgetvalue(res, i, i_defaclrole));
daclinfo[i].defaclobjtype = *(PQgetvalue(res, i, i_defaclobjtype));
- daclinfo[i].defaclacl = pg_strdup(PQgetvalue(res, i, i_defaclacl));
- daclinfo[i].rdefaclacl = pg_strdup(PQgetvalue(res, i, i_rdefaclacl));
- daclinfo[i].initdefaclacl = pg_strdup(PQgetvalue(res, i, i_initdefaclacl));
- daclinfo[i].initrdefaclacl = pg_strdup(PQgetvalue(res, i, i_initrdefaclacl));
+
+ /* Default ACLs are ACLs, of course */
+ daclinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
/* Decide whether we want to dump it */
selectDumpableDefaultACL(&(daclinfo[i]), dopt);
@@ -11094,6 +10641,183 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
return daclinfo;
}
+/*
+ * getRoleName -- look up the name of a role, given its OID
+ *
+ * In current usage, we don't expect failures, so error out for a bad OID.
+ */
+static const char *
+getRoleName(const char *roleoid_str)
+{
+ Oid roleoid = atooid(roleoid_str);
+
+ /*
+ * Do binary search to find the appropriate item.
+ */
+ if (nrolenames > 0)
+ {
+ RoleNameItem *low = &rolenames[0];
+ RoleNameItem *high = &rolenames[nrolenames - 1];
+
+ while (low <= high)
+ {
+ RoleNameItem *middle = low + (high - low) / 2;
+
+ if (roleoid < middle->roleoid)
+ high = middle - 1;
+ else if (roleoid > middle->roleoid)
+ low = middle + 1;
+ else
+ return middle->rolename; /* found a match */
+ }
+ }
+
+ fatal("role with OID %u does not exist", roleoid);
+ return NULL; /* keep compiler quiet */
+}
+
+/*
+ * collectRoleNames --
+ *
+ * Construct a table of all known roles.
+ * The table is sorted by OID for speed in lookup.
+ */
+static void
+collectRoleNames(Archive *fout)
+{
+ PGresult *res;
+ const char *query;
+ int i;
+
+ query = "SELECT oid, rolname FROM pg_catalog.pg_roles ORDER BY 1";
+
+ res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK);
+
+ nrolenames = PQntuples(res);
+
+ rolenames = (RoleNameItem *) pg_malloc(nrolenames * sizeof(RoleNameItem));
+
+ for (i = 0; i < nrolenames; i++)
+ {
+ rolenames[i].roleoid = atooid(PQgetvalue(res, i, 0));
+ rolenames[i].rolename = pg_strdup(PQgetvalue(res, i, 1));
+ }
+
+ PQclear(res);
+}
+
+/*
+ * getAdditionalACLs
+ *
+ * We have now created all the DumpableObjects, and collected the ACL data
+ * that appears in the directly-associated catalog entries. However, there's
+ * more ACL-related info to collect. If any of a table's columns have ACLs,
+ * we must set the TableInfo's DUMP_COMPONENT_ACL components flag, as well as
+ * its hascolumnACLs flag (we won't store the ACLs themselves here, though).
+ * Also, in versions having the pg_init_privs catalog, read that and load the
+ * information into the relevant DumpableObjects.
+ */
+static void
+getAdditionalACLs(Archive *fout)
+{
+ PQExpBuffer query = createPQExpBuffer();
+ PGresult *res;
+ int ntups,
+ i;
+
+ /* Check for per-column ACLs */
+ if (fout->remoteVersion >= 80400)
+ {
+ appendPQExpBufferStr(query,
+ "SELECT DISTINCT attrelid FROM pg_attribute "
+ "WHERE attacl IS NOT NULL");
+
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+
+ ntups = PQntuples(res);
+ for (i = 0; i < ntups; i++)
+ {
+ Oid relid = atooid(PQgetvalue(res, i, 0));
+ TableInfo *tblinfo;
+
+ tblinfo = findTableByOid(relid);
+ /* OK to ignore tables we haven't got a DumpableObject for */
+ if (tblinfo)
+ {
+ tblinfo->dobj.components |= DUMP_COMPONENT_ACL;
+ tblinfo->hascolumnACLs = true;
+ }
+ }
+ PQclear(res);
+ }
+
+ /* Fetch initial-privileges data */
+ if (fout->remoteVersion >= 90600)
+ {
+ printfPQExpBuffer(query,
+ "SELECT objoid, classoid, objsubid, privtype, initprivs "
+ "FROM pg_init_privs");
+
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+
+ ntups = PQntuples(res);
+ for (i = 0; i < ntups; i++)
+ {
+ Oid objoid = atooid(PQgetvalue(res, i, 0));
+ Oid classoid = atooid(PQgetvalue(res, i, 1));
+ int objsubid = atoi(PQgetvalue(res, i, 2));
+ char privtype = *(PQgetvalue(res, i, 3));
+ char *initprivs = PQgetvalue(res, i, 4);
+ CatalogId objId;
+ DumpableObject *dobj;
+
+ objId.tableoid = classoid;
+ objId.oid = objoid;
+ dobj = findObjectByCatalogId(objId);
+ /* OK to ignore entries we haven't got a DumpableObject for */
+ if (dobj)
+ {
+ /* Cope with sub-object initprivs */
+ if (objsubid != 0)
+ {
+ if (dobj->objType == DO_TABLE)
+ {
+ /* For a column initpriv, set the table's ACL flags */
+ dobj->components |= DUMP_COMPONENT_ACL;
+ ((TableInfo *) dobj)->hascolumnACLs = true;
+ }
+ else
+ pg_log_warning("unsupported pg_init_privs entry: %u %u %d",
+ classoid, objoid, objsubid);
+ continue;
+ }
+
+ /* Else it had better be of a type we think has ACLs */
+ if (dobj->objType == DO_NAMESPACE ||
+ dobj->objType == DO_TYPE ||
+ dobj->objType == DO_FUNC ||
+ dobj->objType == DO_AGG ||
+ dobj->objType == DO_TABLE ||
+ dobj->objType == DO_PROCLANG ||
+ dobj->objType == DO_FDW ||
+ dobj->objType == DO_FOREIGN_SERVER)
+ {
+ DumpableObjectWithAcl *daobj = (DumpableObjectWithAcl *) dobj;
+
+ daobj->dacl.privtype = privtype;
+ daobj->dacl.initprivs = pstrdup(initprivs);
+ }
+ else
+ pg_log_warning("unsupported pg_init_privs entry: %u %u %d",
+ classoid, objoid, objsubid);
+ }
+ }
+ PQclear(res);
+ }
+
+ destroyPQExpBuffer(query);
+}
+
/*
* dumpComment --
*
@@ -11303,19 +11027,11 @@ static int
findComments(Archive *fout, Oid classoid, Oid objoid,
CommentItem **items)
{
- /* static storage for table of comments */
- static CommentItem *comments = NULL;
- static int ncomments = -1;
-
CommentItem *middle = NULL;
CommentItem *low;
CommentItem *high;
int nmatch;
- /* Get comments if we didn't already */
- if (ncomments < 0)
- ncomments = collectComments(fout, &comments);
-
/*
* Do binary search to find some item matching the object.
*/
@@ -11376,15 +11092,17 @@ findComments(Archive *fout, Oid classoid, Oid objoid,
/*
* collectComments --
*
- * Construct a table of all comments available for database objects.
+ * Construct a table of all comments available for database objects;
+ * also set the has-comment component flag for each relevant object.
+ *
* We used to do per-object queries for the comments, but it's much faster
* to pull them all over at once, and on most databases the memory cost
* isn't high.
*
* The table is sorted by classoid/objid/objsubid for speed in lookup.
*/
-static int
-collectComments(Archive *fout, CommentItem **items)
+static void
+collectComments(Archive *fout)
{
PGresult *res;
PQExpBuffer query;
@@ -11394,7 +11112,7 @@ collectComments(Archive *fout, CommentItem **items)
int i_objsubid;
int ntups;
int i;
- CommentItem *comments;
+ DumpableObject *dobj;
query = createPQExpBuffer();
@@ -11414,20 +11132,52 @@ collectComments(Archive *fout, CommentItem **items)
ntups = PQntuples(res);
comments = (CommentItem *) pg_malloc(ntups * sizeof(CommentItem));
+ ncomments = 0;
+ dobj = NULL;
for (i = 0; i < ntups; i++)
{
- comments[i].descr = PQgetvalue(res, i, i_description);
- comments[i].classoid = atooid(PQgetvalue(res, i, i_classoid));
- comments[i].objoid = atooid(PQgetvalue(res, i, i_objoid));
- comments[i].objsubid = atoi(PQgetvalue(res, i, i_objsubid));
+ CatalogId objId;
+ int subid;
+
+ objId.tableoid = atooid(PQgetvalue(res, i, i_classoid));
+ objId.oid = atooid(PQgetvalue(res, i, i_objoid));
+ subid = atoi(PQgetvalue(res, i, i_objsubid));
+
+ /* We needn't remember comments that don't match any dumpable object */
+ if (dobj == NULL ||
+ dobj->catId.tableoid != objId.tableoid ||
+ dobj->catId.oid != objId.oid)
+ dobj = findObjectByCatalogId(objId);
+ if (dobj == NULL)
+ continue;
+
+ /*
+ * Comments on columns of composite types are linked to the type's
+ * pg_class entry, but we need to set the DUMP_COMPONENT_COMMENT flag
+ * in the type's own DumpableObject.
+ */
+ if (subid != 0 && dobj->objType == DO_TABLE &&
+ ((TableInfo *) dobj)->relkind == RELKIND_COMPOSITE_TYPE)
+ {
+ TypeInfo *cTypeInfo;
+
+ cTypeInfo = findTypeByOid(((TableInfo *) dobj)->reltype);
+ if (cTypeInfo)
+ cTypeInfo->dobj.components |= DUMP_COMPONENT_COMMENT;
+ }
+ else
+ dobj->components |= DUMP_COMPONENT_COMMENT;
+
+ comments[ncomments].descr = pg_strdup(PQgetvalue(res, i, i_description));
+ comments[ncomments].classoid = objId.tableoid;
+ comments[ncomments].objoid = objId.oid;
+ comments[ncomments].objsubid = subid;
+ ncomments++;
}
- /* Do NOT free the PGresult since we are keeping pointers into it */
+ PQclear(res);
destroyPQExpBuffer(query);
-
- *items = comments;
- return ntups;
}
/*
@@ -11437,8 +11187,19 @@ collectComments(Archive *fout, CommentItem **items)
* ArchiveEntries (TOC objects) for each object to be dumped.
*/
static void
-dumpDumpableObject(Archive *fout, const DumpableObject *dobj)
+dumpDumpableObject(Archive *fout, DumpableObject *dobj)
{
+ /*
+ * Clear any dump-request bits for components that don't exist for this
+ * object. (This makes it safe to initially use DUMP_COMPONENT_ALL as the
+ * request for every kind of object.)
+ */
+ dobj->dump &= dobj->components;
+
+ /* Now, short-circuit if there's nothing to be done here. */
+ if (dobj->dump == 0)
+ return;
+
switch (dobj->objType)
{
case DO_NAMESPACE:
@@ -11621,8 +11382,8 @@ dumpNamespace(Archive *fout, const NamespaceInfo *nspinfo)
PQExpBuffer delq;
char *qnspname;
- /* Skip if not to be dumped */
- if (!nspinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
@@ -11664,8 +11425,7 @@ dumpNamespace(Archive *fout, const NamespaceInfo *nspinfo)
if (nspinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, nspinfo->dobj.dumpId, InvalidDumpId, "SCHEMA",
qnspname, NULL, NULL,
- nspinfo->rolname, nspinfo->nspacl, nspinfo->rnspacl,
- nspinfo->initnspacl, nspinfo->initrnspacl);
+ nspinfo->rolname, &nspinfo->dacl);
free(qnspname);
@@ -11685,8 +11445,8 @@ dumpExtension(Archive *fout, const ExtensionInfo *extinfo)
PQExpBuffer delq;
char *qextname;
- /* Skip if not to be dumped */
- if (!extinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
@@ -11810,8 +11570,8 @@ dumpType(Archive *fout, const TypeInfo *tyinfo)
{
DumpOptions *dopt = fout->dopt;
- /* Skip if not to be dumped */
- if (!tyinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/* Dump out in proper style */
@@ -11854,19 +11614,34 @@ dumpEnumType(Archive *fout, const TypeInfo *tyinfo)
char *qtypname;
char *qualtypname;
char *label;
+ int i_enumlabel;
+ int i_oid;
+
+ if (!fout->is_prepared[PREPQUERY_DUMPENUMTYPE])
+ {
+ /* Set up query for enum-specific details */
+ appendPQExpBufferStr(query,
+ "PREPARE dumpEnumType(pg_catalog.oid) AS\n");
+
+ if (fout->remoteVersion >= 90100)
+ appendPQExpBufferStr(query, "SELECT oid, enumlabel "
+ "FROM pg_catalog.pg_enum "
+ "WHERE enumtypid = $1 "
+ "ORDER BY enumsortorder");
+ else
+ appendPQExpBufferStr(query, "SELECT oid, enumlabel "
+ "FROM pg_catalog.pg_enum "
+ "WHERE enumtypid = $1 "
+ "ORDER BY oid");
- if (fout->remoteVersion >= 90100)
- appendPQExpBuffer(query, "SELECT oid, enumlabel "
- "FROM pg_catalog.pg_enum "
- "WHERE enumtypid = '%u'"
- "ORDER BY enumsortorder",
- tyinfo->dobj.catId.oid);
- else
- appendPQExpBuffer(query, "SELECT oid, enumlabel "
- "FROM pg_catalog.pg_enum "
- "WHERE enumtypid = '%u'"
- "ORDER BY oid",
- tyinfo->dobj.catId.oid);
+ ExecuteSqlStatement(fout, query->data);
+
+ fout->is_prepared[PREPQUERY_DUMPENUMTYPE] = true;
+ }
+
+ printfPQExpBuffer(query,
+ "EXECUTE dumpEnumType('%u')",
+ tyinfo->dobj.catId.oid);
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -11893,10 +11668,12 @@ dumpEnumType(Archive *fout, const TypeInfo *tyinfo)
if (!dopt->binary_upgrade)
{
+ i_enumlabel = PQfnumber(res, "enumlabel");
+
/* Labels with server-assigned oids */
for (i = 0; i < num; i++)
{
- label = PQgetvalue(res, i, PQfnumber(res, "enumlabel"));
+ label = PQgetvalue(res, i, i_enumlabel);
if (i > 0)
appendPQExpBufferChar(q, ',');
appendPQExpBufferStr(q, "\n ");
@@ -11908,11 +11685,14 @@ dumpEnumType(Archive *fout, const TypeInfo *tyinfo)
if (dopt->binary_upgrade)
{
+ i_oid = PQfnumber(res, "oid");
+ i_enumlabel = PQfnumber(res, "enumlabel");
+
/* Labels with dump-assigned (preserved) oids */
for (i = 0; i < num; i++)
{
- enum_oid = atooid(PQgetvalue(res, i, PQfnumber(res, "oid")));
- label = PQgetvalue(res, i, PQfnumber(res, "enumlabel"));
+ enum_oid = atooid(PQgetvalue(res, i, i_oid));
+ label = PQgetvalue(res, i, i_enumlabel);
if (i == 0)
appendPQExpBufferStr(q, "\n-- For binary upgrade, must preserve pg_enum oids\n");
@@ -11955,8 +11735,7 @@ dumpEnumType(Archive *fout, const TypeInfo *tyinfo)
dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
qtypname, NULL,
tyinfo->dobj.namespace->dobj.name,
- tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
- tyinfo->inittypacl, tyinfo->initrtypacl);
+ tyinfo->rolname, &tyinfo->dacl);
PQclear(res);
destroyPQExpBuffer(q);
@@ -11983,29 +11762,43 @@ dumpRangeType(Archive *fout, const TypeInfo *tyinfo)
char *qualtypname;
char *procname;
- appendPQExpBuffer(query,
- "SELECT ");
+ if (!fout->is_prepared[PREPQUERY_DUMPRANGETYPE])
+ {
+ /* Set up query for range-specific details */
+ appendPQExpBufferStr(query,
+ "PREPARE dumpRangeType(pg_catalog.oid) AS\n");
- if (fout->remoteVersion >= 140000)
- appendPQExpBuffer(query,
- "pg_catalog.format_type(rngmultitypid, NULL) AS rngmultitype, ");
- else
- appendPQExpBuffer(query,
- "NULL AS rngmultitype, ");
+ appendPQExpBufferStr(query,
+ "SELECT ");
- appendPQExpBuffer(query,
- "pg_catalog.format_type(rngsubtype, NULL) AS rngsubtype, "
- "opc.opcname AS opcname, "
- "(SELECT nspname FROM pg_catalog.pg_namespace nsp "
- " WHERE nsp.oid = opc.opcnamespace) AS opcnsp, "
- "opc.opcdefault, "
- "CASE WHEN rngcollation = st.typcollation THEN 0 "
- " ELSE rngcollation END AS collation, "
- "rngcanonical, rngsubdiff "
- "FROM pg_catalog.pg_range r, pg_catalog.pg_type st, "
- " pg_catalog.pg_opclass opc "
- "WHERE st.oid = rngsubtype AND opc.oid = rngsubopc AND "
- "rngtypid = '%u'",
+ if (fout->remoteVersion >= 140000)
+ appendPQExpBuffer(query,
+ "pg_catalog.format_type(rngmultitypid, NULL) AS rngmultitype, ");
+ else
+ appendPQExpBuffer(query,
+ "NULL AS rngmultitype, ");
+
+ appendPQExpBufferStr(query,
+ "pg_catalog.format_type(rngsubtype, NULL) AS rngsubtype, "
+ "opc.opcname AS opcname, "
+ "(SELECT nspname FROM pg_catalog.pg_namespace nsp "
+ " WHERE nsp.oid = opc.opcnamespace) AS opcnsp, "
+ "opc.opcdefault, "
+ "CASE WHEN rngcollation = st.typcollation THEN 0 "
+ " ELSE rngcollation END AS collation, "
+ "rngcanonical, rngsubdiff "
+ "FROM pg_catalog.pg_range r, pg_catalog.pg_type st, "
+ " pg_catalog.pg_opclass opc "
+ "WHERE st.oid = rngsubtype AND opc.oid = rngsubopc AND "
+ "rngtypid = $1");
+
+ ExecuteSqlStatement(fout, query->data);
+
+ fout->is_prepared[PREPQUERY_DUMPRANGETYPE] = true;
+ }
+
+ printfPQExpBuffer(query,
+ "EXECUTE dumpRangeType('%u')",
tyinfo->dobj.catId.oid);
res = ExecuteSqlQueryForSingleRow(fout, query->data);
@@ -12097,8 +11890,7 @@ dumpRangeType(Archive *fout, const TypeInfo *tyinfo)
dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
qtypname, NULL,
tyinfo->dobj.namespace->dobj.name,
- tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
- tyinfo->inittypacl, tyinfo->initrtypacl);
+ tyinfo->rolname, &tyinfo->dacl);
PQclear(res);
destroyPQExpBuffer(q);
@@ -12171,8 +11963,7 @@ dumpUndefinedType(Archive *fout, const TypeInfo *tyinfo)
dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
qtypname, NULL,
tyinfo->dobj.namespace->dobj.name,
- tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
- tyinfo->inittypacl, tyinfo->initrtypacl);
+ tyinfo->rolname, &tyinfo->dacl);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
@@ -12219,55 +12010,61 @@ dumpBaseType(Archive *fout, const TypeInfo *tyinfo)
char *typdefault;
bool typdefault_is_literal = false;
- /* Fetch type-specific details */
- appendPQExpBufferStr(query, "SELECT typlen, "
- "typinput, typoutput, typreceive, typsend, "
- "typreceive::pg_catalog.oid AS typreceiveoid, "
- "typsend::pg_catalog.oid AS typsendoid, "
- "typanalyze, "
- "typanalyze::pg_catalog.oid AS typanalyzeoid, "
- "typdelim, typbyval, typalign, typstorage, ");
-
- if (fout->remoteVersion >= 80300)
- appendPQExpBufferStr(query,
- "typmodin, typmodout, "
- "typmodin::pg_catalog.oid AS typmodinoid, "
- "typmodout::pg_catalog.oid AS typmodoutoid, ");
- else
+ if (!fout->is_prepared[PREPQUERY_DUMPBASETYPE])
+ {
+ /* Set up query for type-specific details */
appendPQExpBufferStr(query,
- "'-' AS typmodin, '-' AS typmodout, "
- "0 AS typmodinoid, 0 AS typmodoutoid, ");
+ "PREPARE dumpBaseType(pg_catalog.oid) AS\n");
+
+ appendPQExpBufferStr(query, "SELECT typlen, "
+ "typinput, typoutput, typreceive, typsend, "
+ "typreceive::pg_catalog.oid AS typreceiveoid, "
+ "typsend::pg_catalog.oid AS typsendoid, "
+ "typanalyze, "
+ "typanalyze::pg_catalog.oid AS typanalyzeoid, "
+ "typdelim, typbyval, typalign, typstorage, "
+ "typmodin, typmodout, "
+ "typmodin::pg_catalog.oid AS typmodinoid, "
+ "typmodout::pg_catalog.oid AS typmodoutoid, ");
+
+ if (fout->remoteVersion >= 80400)
+ appendPQExpBufferStr(query,
+ "typcategory, typispreferred, ");
+ else
+ appendPQExpBufferStr(query,
+ "'U' AS typcategory, false AS typispreferred, ");
- if (fout->remoteVersion >= 80400)
- appendPQExpBufferStr(query,
- "typcategory, typispreferred, ");
- else
- appendPQExpBufferStr(query,
- "'U' AS typcategory, false AS typispreferred, ");
+ if (fout->remoteVersion >= 140000)
+ appendPQExpBufferStr(query,
+ "typsubscript, "
+ "typsubscript::pg_catalog.oid AS typsubscriptoid, ");
+ else
+ appendPQExpBufferStr(query,
+ "'-' AS typsubscript, 0 AS typsubscriptoid, ");
+
+ if (fout->remoteVersion >= 90100)
+ appendPQExpBufferStr(query, "(typcollation <> 0) AS typcollatable, ");
+ else
+ appendPQExpBufferStr(query, "false AS typcollatable, ");
- if (fout->remoteVersion >= 90100)
- appendPQExpBufferStr(query, "(typcollation <> 0) AS typcollatable, ");
- else
- appendPQExpBufferStr(query, "false AS typcollatable, ");
+ /* Before 8.4, pg_get_expr does not allow 0 for its second arg */
+ if (fout->remoteVersion >= 80400)
+ appendPQExpBufferStr(query,
+ "pg_catalog.pg_get_expr(typdefaultbin, 0) AS typdefaultbin, typdefault ");
+ else
+ appendPQExpBufferStr(query,
+ "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault ");
- if (fout->remoteVersion >= 140000)
- appendPQExpBufferStr(query,
- "typsubscript, "
- "typsubscript::pg_catalog.oid AS typsubscriptoid, ");
- else
- appendPQExpBufferStr(query,
- "'-' AS typsubscript, 0 AS typsubscriptoid, ");
+ appendPQExpBuffer(query, "FROM pg_catalog.pg_type "
+ "WHERE oid = $1");
- /* Before 8.4, pg_get_expr does not allow 0 for its second arg */
- if (fout->remoteVersion >= 80400)
- appendPQExpBufferStr(query,
- "pg_catalog.pg_get_expr(typdefaultbin, 0) AS typdefaultbin, typdefault ");
- else
- appendPQExpBufferStr(query,
- "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault ");
+ ExecuteSqlStatement(fout, query->data);
- appendPQExpBuffer(query, "FROM pg_catalog.pg_type "
- "WHERE oid = '%u'::pg_catalog.oid",
+ fout->is_prepared[PREPQUERY_DUMPBASETYPE] = true;
+ }
+
+ printfPQExpBuffer(query,
+ "EXECUTE dumpBaseType('%u')",
tyinfo->dobj.catId.oid);
res = ExecuteSqlQueryForSingleRow(fout, query->data);
@@ -12433,8 +12230,7 @@ dumpBaseType(Archive *fout, const TypeInfo *tyinfo)
dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
qtypname, NULL,
tyinfo->dobj.namespace->dobj.name,
- tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
- tyinfo->inittypacl, tyinfo->initrtypacl);
+ tyinfo->rolname, &tyinfo->dacl);
PQclear(res);
destroyPQExpBuffer(q);
@@ -12494,32 +12290,44 @@ dumpDomain(Archive *fout, const TypeInfo *tyinfo)
Oid typcollation;
bool typdefault_is_literal = false;
- /* Fetch domain specific details */
- if (fout->remoteVersion >= 90100)
- {
- /* typcollation is new in 9.1 */
- appendPQExpBuffer(query, "SELECT t.typnotnull, "
- "pg_catalog.format_type(t.typbasetype, t.typtypmod) AS typdefn, "
- "pg_catalog.pg_get_expr(t.typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
- "t.typdefault, "
- "CASE WHEN t.typcollation <> u.typcollation "
- "THEN t.typcollation ELSE 0 END AS typcollation "
- "FROM pg_catalog.pg_type t "
- "LEFT JOIN pg_catalog.pg_type u ON (t.typbasetype = u.oid) "
- "WHERE t.oid = '%u'::pg_catalog.oid",
- tyinfo->dobj.catId.oid);
- }
- else
+ if (!fout->is_prepared[PREPQUERY_DUMPDOMAIN])
{
- appendPQExpBuffer(query, "SELECT typnotnull, "
- "pg_catalog.format_type(typbasetype, typtypmod) AS typdefn, "
- "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
- "typdefault, 0 AS typcollation "
- "FROM pg_catalog.pg_type "
- "WHERE oid = '%u'::pg_catalog.oid",
- tyinfo->dobj.catId.oid);
+ /* Set up query for domain-specific details */
+ appendPQExpBufferStr(query,
+ "PREPARE dumpDomain(pg_catalog.oid) AS\n");
+
+ if (fout->remoteVersion >= 90100)
+ {
+ /* typcollation is new in 9.1 */
+ appendPQExpBufferStr(query, "SELECT t.typnotnull, "
+ "pg_catalog.format_type(t.typbasetype, t.typtypmod) AS typdefn, "
+ "pg_catalog.pg_get_expr(t.typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
+ "t.typdefault, "
+ "CASE WHEN t.typcollation <> u.typcollation "
+ "THEN t.typcollation ELSE 0 END AS typcollation "
+ "FROM pg_catalog.pg_type t "
+ "LEFT JOIN pg_catalog.pg_type u ON (t.typbasetype = u.oid) "
+ "WHERE t.oid = $1");
+ }
+ else
+ {
+ appendPQExpBufferStr(query, "SELECT typnotnull, "
+ "pg_catalog.format_type(typbasetype, typtypmod) AS typdefn, "
+ "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
+ "typdefault, 0 AS typcollation "
+ "FROM pg_catalog.pg_type "
+ "WHERE oid = $1");
+ }
+
+ ExecuteSqlStatement(fout, query->data);
+
+ fout->is_prepared[PREPQUERY_DUMPDOMAIN] = true;
}
+ printfPQExpBuffer(query,
+ "EXECUTE dumpDomain('%u')",
+ tyinfo->dobj.catId.oid);
+
res = ExecuteSqlQueryForSingleRow(fout, query->data);
typnotnull = PQgetvalue(res, 0, PQfnumber(res, "typnotnull"));
@@ -12621,8 +12429,7 @@ dumpDomain(Archive *fout, const TypeInfo *tyinfo)
dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
qtypname, NULL,
tyinfo->dobj.namespace->dobj.name,
- tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
- tyinfo->inittypacl, tyinfo->initrtypacl);
+ tyinfo->rolname, &tyinfo->dacl);
/* Dump any per-constraint comments */
for (i = 0; i < tyinfo->nDomChecks; i++)
@@ -12675,45 +12482,57 @@ dumpCompositeType(Archive *fout, const TypeInfo *tyinfo)
int i;
int actual_atts;
- /* Fetch type specific details */
- if (fout->remoteVersion >= 90100)
- {
- /*
- * attcollation is new in 9.1. Since we only want to dump COLLATE
- * clauses for attributes whose collation is different from their
- * type's default, we use a CASE here to suppress uninteresting
- * attcollations cheaply. atttypid will be 0 for dropped columns;
- * collation does not matter for those.
- */
- appendPQExpBuffer(query, "SELECT a.attname, "
- "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, "
- "a.attlen, a.attalign, a.attisdropped, "
- "CASE WHEN a.attcollation <> at.typcollation "
- "THEN a.attcollation ELSE 0 END AS attcollation "
- "FROM pg_catalog.pg_type ct "
- "JOIN pg_catalog.pg_attribute a ON a.attrelid = ct.typrelid "
- "LEFT JOIN pg_catalog.pg_type at ON at.oid = a.atttypid "
- "WHERE ct.oid = '%u'::pg_catalog.oid "
- "ORDER BY a.attnum ",
- tyinfo->dobj.catId.oid);
- }
- else
+ if (!fout->is_prepared[PREPQUERY_DUMPCOMPOSITETYPE])
{
- /*
- * Since ALTER TYPE could not drop columns until 9.1, attisdropped
- * should always be false.
- */
- appendPQExpBuffer(query, "SELECT a.attname, "
- "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, "
- "a.attlen, a.attalign, a.attisdropped, "
- "0 AS attcollation "
- "FROM pg_catalog.pg_type ct, pg_catalog.pg_attribute a "
- "WHERE ct.oid = '%u'::pg_catalog.oid "
- "AND a.attrelid = ct.typrelid "
- "ORDER BY a.attnum ",
- tyinfo->dobj.catId.oid);
+ /* Set up query for type-specific details */
+ appendPQExpBufferStr(query,
+ "PREPARE dumpCompositeType(pg_catalog.oid) AS\n");
+
+ if (fout->remoteVersion >= 90100)
+ {
+ /*
+ * attcollation is new in 9.1. Since we only want to dump COLLATE
+ * clauses for attributes whose collation is different from their
+ * type's default, we use a CASE here to suppress uninteresting
+ * attcollations cheaply. atttypid will be 0 for dropped columns;
+ * collation does not matter for those.
+ */
+ appendPQExpBufferStr(query, "SELECT a.attname, "
+ "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, "
+ "a.attlen, a.attalign, a.attisdropped, "
+ "CASE WHEN a.attcollation <> at.typcollation "
+ "THEN a.attcollation ELSE 0 END AS attcollation "
+ "FROM pg_catalog.pg_type ct "
+ "JOIN pg_catalog.pg_attribute a ON a.attrelid = ct.typrelid "
+ "LEFT JOIN pg_catalog.pg_type at ON at.oid = a.atttypid "
+ "WHERE ct.oid = $1 "
+ "ORDER BY a.attnum");
+ }
+ else
+ {
+ /*
+ * Since ALTER TYPE could not drop columns until 9.1, attisdropped
+ * should always be false.
+ */
+ appendPQExpBufferStr(query, "SELECT a.attname, "
+ "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, "
+ "a.attlen, a.attalign, a.attisdropped, "
+ "0 AS attcollation "
+ "FROM pg_catalog.pg_type ct, pg_catalog.pg_attribute a "
+ "WHERE ct.oid = $1 "
+ "AND a.attrelid = ct.typrelid "
+ "ORDER BY a.attnum");
+ }
+
+ ExecuteSqlStatement(fout, query->data);
+
+ fout->is_prepared[PREPQUERY_DUMPCOMPOSITETYPE] = true;
}
+ printfPQExpBuffer(query,
+ "EXECUTE dumpCompositeType('%u')",
+ tyinfo->dobj.catId.oid);
+
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
@@ -12847,8 +12666,7 @@ dumpCompositeType(Archive *fout, const TypeInfo *tyinfo)
dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
qtypname, NULL,
tyinfo->dobj.namespace->dobj.name,
- tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
- tyinfo->inittypacl, tyinfo->initrtypacl);
+ tyinfo->rolname, &tyinfo->dacl);
PQclear(res);
destroyPQExpBuffer(q);
@@ -12989,8 +12807,8 @@ dumpShellType(Archive *fout, const ShellTypeInfo *stinfo)
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
- /* Skip if not to be dumped */
- if (!stinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
@@ -13043,8 +12861,8 @@ dumpProcLang(Archive *fout, const ProcLangInfo *plang)
FuncInfo *inlineInfo = NULL;
FuncInfo *validatorInfo = NULL;
- /* Skip if not to be dumped */
- if (!plang->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/*
@@ -13148,8 +12966,7 @@ dumpProcLang(Archive *fout, const ProcLangInfo *plang)
if (plang->lanpltrusted && plang->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, plang->dobj.dumpId, InvalidDumpId, "LANGUAGE",
qlanname, NULL, NULL,
- plang->lanowner, plang->lanacl, plang->rlanacl,
- plang->initlanacl, plang->initrlanacl);
+ plang->lanowner, &plang->dacl);
free(qlanname);
@@ -13397,7 +13214,6 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
char **allargtypes = NULL;
char **argmodes = NULL;
char **argnames = NULL;
- bool isGE50 = isGPDB5000OrLater(fout);
char **configitems = NULL;
int nconfigitems = 0;
const char *keyword;
@@ -13427,117 +13243,92 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
delqry = createPQExpBuffer();
asPart = createPQExpBuffer();
- /* Fetch function-specific details */
- appendPQExpBufferStr(query,
- "SELECT\n"
- "proretset,\n"
- "prosrc,\n"
- "probin,\n"
- "provolatile,\n"
- "proisstrict,\n"
- "prosecdef,\n"
- "lanname,\n");
-
- if (fout->remoteVersion >= 80300)
- {
- appendPQExpBufferStr(query,
- "proconfig,\n"
- "procost,\n"
- "prorows,\n");
-
- if (isGE50 && fout->remoteVersion < 90200)
- {
- appendPQExpBufferStr(query,
- "prodataaccess,\n"
- "'a' as proexeclocation,\n"
- "(SELECT procallback FROM pg_catalog.pg_proc_callback WHERE profnoid::pg_catalog.oid = p.oid) as callbackfunc,\n");
- }
- }
- else
+ if (!fout->is_prepared[PREPQUERY_DUMPFUNC])
{
- appendPQExpBufferStr(query,
- "null AS proconfig,\n"
- "0 AS procost,\n"
- "0 AS prorows,\n");
+ /* Set up query for function-specific details */
+ appendPQExpBufferStr(query, "PREPARE dumpFunc(pg_catalog.oid) AS\n");
appendPQExpBuffer(query,
- "%s\n"
- "'a' as proexeclocation,\n"
- "(SELECT procallback FROM pg_catalog.pg_proc_callback WHERE profnoid::pg_catalog.oid = p.oid) as callbackfunc,\n",
- "prodataaccess,");
- }
+ "SELECT\n"
+ "proretset,\n"
+ "prosrc,\n"
+ "probin,\n"
+ "provolatile,\n"
+ "proisstrict,\n"
+ "prosecdef,\n"
+ "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname,\n "
+ "proconfig,\n"
+ "procost,\n"
+ "prorows,\n"
+ "prodataaccess,\n"
+ "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs,\n"
+ "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs,\n"
+ "pg_catalog.pg_get_function_result(p.oid) AS funcresult,\n"
+ "(SELECT procallback FROM pg_catalog.pg_proc_callback WHERE profnoid::pg_catalog.oid = p.oid) as callbackfunc,\n");
- if (fout->remoteVersion >= 80400)
- {
- /*
- * In GPDB 5.0 and up we rely on pg_get_function_arguments and
- * pg_get_function_result instead of examining proallargtypes etc.
- */
- appendPQExpBufferStr(query,
- "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs,\n"
- "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs,\n"
- "pg_catalog.pg_get_function_result(p.oid) AS funcresult,\n");
- }
- else if (fout->remoteVersion >= 80100)
- appendPQExpBufferStr(query,
- "proallargtypes,\n"
- "proargmodes,\n"
- "proargnames,\n");
- else
- appendPQExpBufferStr(query,
- "null AS proallargtypes,\n"
- "null AS proargmodes,\n"
- "proargnames,\n");
+ if (fout->remoteVersion >= 90200)
+ appendPQExpBuffer(query,
+ "proleakproof,\n");
+ else
+ appendPQExpBuffer(query,
+ "false AS proleakproof,\n");
- if (fout->remoteVersion >= 90200)
- appendPQExpBufferStr(query,
- "prodataaccess,\n"
- "proexeclocation,\n"
- "(SELECT procallback FROM pg_catalog.pg_proc_callback WHERE profnoid::pg_catalog.oid = p.oid) as callbackfunc,\n"
- "proleakproof,\n");
- else
- appendPQExpBufferStr(query,
- "false AS proleakproof,\n");
+ /* GPDB6 added proexeclocation */
+ if (fout->remoteVersion >= GPDB6_MAJOR_PGVERSION)
+ appendPQExpBuffer(query,
+ "proexeclocation,\n");
+ else
+ appendPQExpBuffer(query,
+ "'a' as proexeclocation,\n");
- if (fout->remoteVersion >= 90500)
- appendPQExpBufferStr(query,
- "array_to_string(protrftypes, ' ') AS protrftypes,\n");
+ if (fout->remoteVersion >= 90500)
+ appendPQExpBuffer(query,
+ "array_to_string(protrftypes, ' ') AS protrftypes,\n");
- if (fout->remoteVersion >= 90600)
- appendPQExpBufferStr(query,
- "proparallel,\n");
- else
- appendPQExpBufferStr(query,
- "'u' AS proparallel,\n");
+ if (fout->remoteVersion >= 90600)
+ appendPQExpBuffer(query,
+ "proparallel,\n");
+ else
+ appendPQExpBuffer(query,
+ "'u' AS proparallel,\n");
- if (fout->remoteVersion >= 110000)
- appendPQExpBufferStr(query,
- "prokind,\n");
- else if (fout->remoteVersion >= 80400)
- appendPQExpBufferStr(query,
- "CASE WHEN proiswindow THEN 'w' ELSE 'f' END AS prokind,\n");
- else
- appendPQExpBufferStr(query,
- "'f' AS prokind,\n");
+ if (fout->remoteVersion >= 110000)
+ appendPQExpBuffer(query,
+ "prokind,\n");
+ else if (fout->remoteVersion >= 80400)
+ appendPQExpBuffer(query,
+ "CASE WHEN proiswindow THEN 'w' ELSE 'f' END AS prokind,\n");
+ else
+ appendPQExpBuffer(query,
+ "CASE WHEN proiswin THEN 'w' ELSE 'f' END AS prokind,\n");
- if (fout->remoteVersion >= 120000)
- appendPQExpBufferStr(query,
- "prosupport,\n");
- else
- appendPQExpBufferStr(query,
- "'-' AS prosupport,\n");
+ if (fout->remoteVersion >= 120000)
+ appendPQExpBuffer(query,
+ "prosupport,\n");
+ else
+ appendPQExpBuffer(query,
+ "'-' AS prosupport,\n");
- if (fout->remoteVersion >= 140000)
- appendPQExpBufferStr(query,
- "pg_get_function_sqlbody(p.oid) AS prosqlbody\n");
- else
- appendPQExpBufferStr(query,
- "NULL AS prosqlbody\n");
+ if (fout->remoteVersion >= 140000)
+ appendPQExpBufferStr(query,
+ "pg_get_function_sqlbody(p.oid) AS prosqlbody\n");
+ else
+ appendPQExpBufferStr(query,
+ "NULL AS prosqlbody\n");
- appendPQExpBuffer(query,
- "FROM pg_catalog.pg_proc p, pg_catalog.pg_language l\n"
- "WHERE p.oid = '%u'::pg_catalog.oid "
- "AND l.oid = p.prolang",
+ appendPQExpBuffer(query,
+ "FROM pg_catalog.pg_proc p, pg_catalog.pg_language l\n"
+ "WHERE p.oid = $1 "
+ "AND l.oid = p.prolang");
+
+ ExecuteSqlStatement(fout, query->data);
+
+ fout->is_prepared[PREPQUERY_DUMPFUNC] = true;
+
+ }
+
+ printfPQExpBuffer(query,
+ "EXECUTE dumpFunc('%u')",
finfo->dobj.catId.oid);
res = ExecuteSqlQueryForSingleRow(fout, query->data);
@@ -13555,12 +13346,8 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
probin = NULL;
prosqlbody = PQgetvalue(res, 0, PQfnumber(res, "prosqlbody"));
}
- /*
- * GPDB_14_MERGE_FIXME:
- * isGE50 is >= 80300 but upstream is (fout->remoteVersion >= 80400)
- * Need to check.
- */
- if (isGE50)
+
+ if (fout->remoteVersion >= GPDB5_MAJOR_PGVERSION)
{
funcargs = PQgetvalue(res, 0, PQfnumber(res, "funcargs"));
funciargs = PQgetvalue(res, 0, PQfnumber(res, "funciargs"));
@@ -13717,17 +13504,11 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
nconfigitems = 0;
}
- if (funcargs)
- {
- /* 8.4 or later; we rely on server-side code for most of the work */
- funcfullsig = format_function_arguments(finfo, funcargs, false);
- funcsig = format_function_arguments(finfo, funciargs, false);
- }
- else
- /* pre-8.4, do it ourselves */
- funcsig = format_function_arguments_old(fout,
- finfo, nallargs, allargtypes,
- argmodes, argnames);
+
+ /* 8.4 or later; we rely on server-side code for most of the work */
+ funcfullsig = format_function_arguments(finfo, funcargs, false);
+ funcsig = format_function_arguments(finfo, funciargs, false);
+
funcsig_tag = format_function_signature(fout, finfo, false);
@@ -13971,8 +13752,7 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
dumpACL(fout, finfo->dobj.dumpId, InvalidDumpId, keyword,
funcsig, NULL,
finfo->dobj.namespace->dobj.name,
- finfo->rolname, finfo->proacl, finfo->rproacl,
- finfo->initproacl, finfo->initrproacl);
+ finfo->rolname, &finfo->dacl);
PQclear(res);
@@ -13996,6 +13776,7 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
}
+
/*
* Dump a user-defined cast
*/
@@ -14011,8 +13792,8 @@ dumpCast(Archive *fout, const CastInfo *cast)
const char *sourceType;
const char *targetType;
- /* Skip if not to be dumped */
- if (!cast->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/* Cannot dump if we don't have the cast function's info */
@@ -14117,8 +13898,8 @@ dumpTransform(Archive *fout, const TransformInfo *transform)
char *lanname;
const char *transformType;
- /* Skip if not to be dumped */
- if (!transform->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/* Cannot dump if we don't have the transform functions' info */
@@ -14266,8 +14047,8 @@ dumpOpr(Archive *fout, const OprInfo *oprinfo)
char *oprregproc;
char *oprref;
- /* Skip if not to be dumped */
- if (!oprinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/*
@@ -14283,19 +14064,32 @@ dumpOpr(Archive *fout, const OprInfo *oprinfo)
oprid = createPQExpBuffer();
details = createPQExpBuffer();
+ if (!fout->is_prepared[PREPQUERY_DUMPOPR])
+ {
+ /* Set up query for operator-specific details */
+ appendPQExpBufferStr(query,
+ "PREPARE dumpOpr(pg_catalog.oid) AS\n");
+
+ appendPQExpBuffer(query, "SELECT oprkind, "
+ "oprcode::pg_catalog.regprocedure, "
+ "oprleft::pg_catalog.regtype, "
+ "oprright::pg_catalog.regtype, "
+ "oprcom, "
+ "oprnegate, "
+ "oprrest::pg_catalog.regprocedure, "
+ "oprjoin::pg_catalog.regprocedure, "
+ "oprcanmerge, oprcanhash "
+ "FROM pg_catalog.pg_operator "
+ "WHERE oid = $1");
+
+ ExecuteSqlStatement(fout, query->data);
+
+ fout->is_prepared[PREPQUERY_DUMPOPR] = true;
+ }
- appendPQExpBuffer(query, "SELECT oprkind, "
- "oprcode::pg_catalog.regprocedure, "
- "oprleft::pg_catalog.regtype, "
- "oprright::pg_catalog.regtype, "
- "oprcom, "
- "oprnegate, "
- "oprrest::pg_catalog.regprocedure, "
- "oprjoin::pg_catalog.regprocedure, "
- "oprcanmerge, oprcanhash "
- "FROM pg_catalog.pg_operator "
- "WHERE oid = '%u'::pg_catalog.oid",
- oprinfo->dobj.catId.oid);
+ printfPQExpBuffer(query,
+ "EXECUTE dumpOpr('%u')",
+ oprinfo->dobj.catId.oid);
res = ExecuteSqlQueryForSingleRow(fout, query->data);
@@ -14541,8 +14335,8 @@ dumpAccessMethod(Archive *fout, const AccessMethodInfo *aminfo)
PQExpBuffer delq;
char *qamname;
- /* Skip if not to be dumped */
- if (!aminfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
@@ -14646,8 +14440,8 @@ dumpOpclass(Archive *fout, const OpclassInfo *opcinfo)
bool needComma;
int i;
- /* Skip if not to be dumped */
- if (!opcinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
@@ -14656,32 +14450,17 @@ dumpOpclass(Archive *fout, const OpclassInfo *opcinfo)
nameusing = createPQExpBuffer();
/* Get additional fields from the pg_opclass row */
- if (fout->remoteVersion >= 80300)
- {
- appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
- "opckeytype::pg_catalog.regtype, "
- "opcdefault, opcfamily, "
- "opfname AS opcfamilyname, "
- "nspname AS opcfamilynsp, "
- "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
- "FROM pg_catalog.pg_opclass c "
- "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = opcfamily "
- "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
- "WHERE c.oid = '%u'::pg_catalog.oid",
- opcinfo->dobj.catId.oid);
- }
- else
- {
- appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
- "opckeytype::pg_catalog.regtype, "
- "opcdefault, NULL AS opcfamily, "
- "NULL AS opcfamilyname, "
- "NULL AS opcfamilynsp, "
- "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
- "FROM pg_catalog.pg_opclass "
- "WHERE oid = '%u'::pg_catalog.oid",
- opcinfo->dobj.catId.oid);
- }
+ appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
+ "opckeytype::pg_catalog.regtype, "
+ "opcdefault, opcfamily, "
+ "opfname AS opcfamilyname, "
+ "nspname AS opcfamilynsp, "
+ "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
+ "FROM pg_catalog.pg_opclass c "
+ "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = opcfamily "
+ "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
+ "WHERE c.oid = '%u'::pg_catalog.oid",
+ opcinfo->dobj.catId.oid);
res = ExecuteSqlQueryForSingleRow(fout, query->data);
@@ -14781,7 +14560,7 @@ dumpOpclass(Archive *fout, const OpclassInfo *opcinfo)
"ORDER BY amopstrategy",
opcinfo->dobj.catId.oid);
}
- else if (fout->remoteVersion >= 80300)
+ else
{
appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
"amopopr::pg_catalog.regoperator, "
@@ -14791,22 +14570,7 @@ dumpOpclass(Archive *fout, const OpclassInfo *opcinfo)
"WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
"AND refobjid = '%u'::pg_catalog.oid "
"AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
- "AND objid = ao.oid "
- "ORDER BY amopstrategy",
- opcinfo->dobj.catId.oid);
- }
- else
- {
- /*
- * Here, we print all entries since there are no opfamilies and hence
- * no loose operators to worry about.
- */
- appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
- "amopopr::pg_catalog.regoperator, "
- "NULL AS sortfamily, "
- "NULL AS sortfamilynsp "
- "FROM pg_catalog.pg_amop "
- "WHERE amopclaid = '%u'::pg_catalog.oid "
+ "AND objid = ao.oid "
"ORDER BY amopstrategy",
opcinfo->dobj.catId.oid);
}
@@ -14864,31 +14628,17 @@ dumpOpclass(Archive *fout, const OpclassInfo *opcinfo)
*/
resetPQExpBuffer(query);
- if (fout->remoteVersion >= 80300)
- {
- appendPQExpBuffer(query, "SELECT amprocnum, "
- "amproc::pg_catalog.regprocedure, "
- "amproclefttype::pg_catalog.regtype, "
- "amprocrighttype::pg_catalog.regtype "
- "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
- "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
- "AND refobjid = '%u'::pg_catalog.oid "
- "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
- "AND objid = ap.oid "
- "ORDER BY amprocnum",
- opcinfo->dobj.catId.oid);
- }
- else
- {
- appendPQExpBuffer(query, "SELECT amprocnum, "
- "amproc::pg_catalog.regprocedure, "
- "'' AS amproclefttype, "
- "'' AS amprocrighttype "
- "FROM pg_catalog.pg_amproc "
- "WHERE amopclaid = '%u'::pg_catalog.oid "
- "ORDER BY amprocnum",
- opcinfo->dobj.catId.oid);
- }
+ appendPQExpBuffer(query, "SELECT amprocnum, "
+ "amproc::pg_catalog.regprocedure, "
+ "amproclefttype::pg_catalog.regtype, "
+ "amprocrighttype::pg_catalog.regtype "
+ "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
+ "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
+ "AND refobjid = '%u'::pg_catalog.oid "
+ "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
+ "AND objid = ap.oid "
+ "ORDER BY amprocnum",
+ opcinfo->dobj.catId.oid);
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -15008,8 +14758,8 @@ dumpOpfamily(Archive *fout, const OpfamilyInfo *opfinfo)
bool needComma;
int i;
- /* Skip if not to be dumped */
- if (!opfinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
@@ -15253,8 +15003,8 @@ dumpCollation(Archive *fout, const CollInfo *collinfo)
const char *collcollate;
const char *collctype;
- /* Skip if not to be dumped */
- if (!collinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
@@ -15405,8 +15155,8 @@ dumpConversion(Archive *fout, const ConvInfo *convinfo)
const char *conproc;
bool condefault;
- /* Skip if not to be dumped */
- if (!convinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
@@ -15554,8 +15304,8 @@ dumpAgg(Archive *fout, const AggInfo *agginfo)
const char *proparallel;
char defaultfinalmodify;
- /* Skip if not to be dumped */
- if (!agginfo->aggfn.dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
@@ -15563,97 +15313,97 @@ dumpAgg(Archive *fout, const AggInfo *agginfo)
delq = createPQExpBuffer();
details = createPQExpBuffer();
+ if (!fout->is_prepared[PREPQUERY_DUMPAGG])
+ {
+ /* Set up query for aggregate-specific details */
+ appendPQExpBufferStr(query,
+ "PREPARE dumpAgg(pg_catalog.oid) AS\n");
- /*
- * GPDB_14_MERGE_FIXME:
- * Some fields:
- * aggcombinefn, aggserialfn,
- * aggdeserialfn, aggmtransfn,
- * aggminvtransfn, aggmfinalfn,
- * aggmtranstype::pg_catalog.regtype, aggfinalextra,
- * aggmfinalextra,
- * diffs from upsreaam in certain versions between [80100, 90600].
- * But others versions are same.
- * I think we should keep the same with upsream here, special
- * handles are not need in such versions.
- * Need to recheck.
- */
+ appendPQExpBufferStr(query,
+ "SELECT "
+ "aggtransfn,\n"
+ "aggfinalfn,\n"
+ "aggtranstype::pg_catalog.regtype,\n"
+ "agginitval,\n");
- /* Get aggregate-specific details */
- appendPQExpBufferStr(query,
- "SELECT\n"
- "aggtransfn,\n"
- "aggfinalfn,\n"
- "aggtranstype::pg_catalog.regtype,\n"
- "agginitval,\n");
+ if (fout->remoteVersion >= 80100)
+ appendPQExpBufferStr(query,
+ "aggsortop,\n");
+ else
+ appendPQExpBufferStr(query,
+ "0 AS aggsortop,\n");
- if (fout->remoteVersion >= 80100)
- appendPQExpBufferStr(query,
- "aggsortop,\n");
+ if (fout->remoteVersion >= 80400)
+ appendPQExpBufferStr(query,
+ "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs,\n"
+ "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs,\n");
- if (fout->remoteVersion >= 80400)
- appendPQExpBufferStr(query,
- "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs,\n"
- "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs,\n");
+ if (fout->remoteVersion >= 90400)
+ appendPQExpBufferStr(query,
+ "aggkind,\n"
+ "aggmtransfn,\n"
+ "aggminvtransfn,\n"
+ "aggmfinalfn,\n"
+ "aggmtranstype::pg_catalog.regtype,\n"
+ "aggfinalextra,\n"
+ "aggmfinalextra,\n"
+ "aggtransspace,\n"
+ "aggmtransspace,\n"
+ "aggminitval,\n");
+ else
+ appendPQExpBufferStr(query,
+ "'n' AS aggkind,\n"
+ "'-' AS aggmtransfn,\n"
+ "'-' AS aggminvtransfn,\n"
+ "'-' AS aggmfinalfn,\n"
+ "0 AS aggmtranstype,\n"
+ "false AS aggfinalextra,\n"
+ "false AS aggmfinalextra,\n"
+ "0 AS aggtransspace,\n"
+ "0 AS aggmtransspace,\n"
+ "NULL AS aggminitval,\n");
- if (fout->remoteVersion >= 90400)
- appendPQExpBufferStr(query,
- "aggkind,\n"
- "aggmtransfn,\n"
- "aggminvtransfn,\n"
- "aggmfinalfn,\n"
- "aggmtranstype::pg_catalog.regtype,\n"
- "aggfinalextra,\n"
- "aggmfinalextra,\n"
- "aggtransspace,\n"
- "aggmtransspace,\n"
- "aggminitval,\n");
- else
- appendPQExpBufferStr(query,
- "'n' AS aggkind,\n"
- "'-' AS aggmtransfn,\n"
- "'-' AS aggminvtransfn,\n"
- "'-' AS aggmfinalfn,\n"
- "0 AS aggmtranstype,\n"
- "false AS aggfinalextra,\n"
- "false AS aggmfinalextra,\n"
- "0 AS aggtransspace,\n"
- "0 AS aggmtransspace,\n"
- "NULL AS aggminitval,\n");
+ if (fout->remoteVersion >= 90600)
+ appendPQExpBufferStr(query,
+ "aggcombinefn,\n"
+ "aggserialfn,\n"
+ "aggdeserialfn,\n"
+ "proparallel,\n");
+ else
+ appendPQExpBufferStr(query,
+ "'-' AS aggcombinefn,\n"
+ "'-' AS aggserialfn,\n"
+ "'-' AS aggdeserialfn,\n"
+ "'u' AS proparallel,\n");
- if (fout->remoteVersion >= 90600)
- appendPQExpBufferStr(query,
- "aggcombinefn,\n"
- "aggserialfn,\n"
- "aggdeserialfn,\n"
- "proparallel,\n");
- else
- appendPQExpBufferStr(query,
- "'-' AS aggcombinefn,\n"
- "'-' AS aggserialfn,\n"
- "'-' AS aggdeserialfn,\n"
- "'u' AS proparallel,\n");
+ if (fout->remoteVersion >= 110000)
+ appendPQExpBufferStr(query,
+ "aggfinalmodify,\n"
+ "aggmfinalmodify\n");
+ else
+ appendPQExpBufferStr(query,
+ "'0' AS aggfinalmodify,\n"
+ "'0' AS aggmfinalmodify\n");
+
+ if (fout->remoteVersion >= 140000 && fout->version.type == Cloudberry && fout->version.version >= 2)
+ appendPQExpBufferStr(query,
+ "aggrepsafeexec\n");
+ else
+ appendPQExpBufferStr(query,
+ "false AS aggrepsafeexec\n");
- if (fout->remoteVersion >= 110000)
- appendPQExpBufferStr(query,
- "aggfinalmodify,\n"
- "aggmfinalmodify,\n");
- else
appendPQExpBufferStr(query,
- "'0' AS aggfinalmodify,\n"
- "'0' AS aggmfinalmodify,\n");
+ "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
+ "WHERE a.aggfnoid = p.oid "
+ "AND p.oid = $1");
- if (fout->remoteVersion >= 140000 && fout->version.type == Cloudberry && fout->version.version >= 2)
- appendPQExpBufferStr(query,
- "aggrepsafeexec\n");
- else
- appendPQExpBufferStr(query,
- "false AS aggrepsafeexec\n");
+ ExecuteSqlStatement(fout, query->data);
- appendPQExpBuffer(query,
- "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
- "WHERE a.aggfnoid = p.oid "
- "AND p.oid = '%u'::pg_catalog.oid",
+ fout->is_prepared[PREPQUERY_DUMPAGG] = true;
+ }
+
+ printfPQExpBuffer(query,
+ "EXECUTE dumpAgg('%u')",
agginfo->aggfn.dobj.catId.oid);
res = ExecuteSqlQueryForSingleRow(fout, query->data);
@@ -15883,9 +15633,7 @@ dumpAgg(Archive *fout, const AggInfo *agginfo)
dumpACL(fout, agginfo->aggfn.dobj.dumpId, InvalidDumpId,
"FUNCTION", aggsig, NULL,
agginfo->aggfn.dobj.namespace->dobj.name,
- agginfo->aggfn.rolname, agginfo->aggfn.proacl,
- agginfo->aggfn.rproacl,
- agginfo->aggfn.initproacl, agginfo->aggfn.initrproacl);
+ agginfo->aggfn.rolname, &agginfo->aggfn.dacl);
free(aggsig);
if (aggfullsig)
@@ -15963,7 +15711,7 @@ dumpExtProtocol(Archive *fout, const ExtProtInfo *ptcinfo)
} ProtoFunc;
ProtoFunc protoFuncs[FCOUNT];
-
+ DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
PQExpBuffer delq;
PQExpBuffer nsq;
@@ -15972,8 +15720,8 @@ dumpExtProtocol(Archive *fout, const ExtProtInfo *ptcinfo)
int i;
bool has_internal = false;
- /* Skip if not to be dumped */
- if (!ptcinfo->dobj.dump || fout->dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/* init and fill the protoFuncs array */
@@ -16033,10 +15781,7 @@ dumpExtProtocol(Archive *fout, const ExtProtInfo *ptcinfo)
* qualified with namespace, we must ensure that we have the search_path
* set with the namespaces of the referenced functions. We only need the
* dump file to have the search_path so inject a SET search_path = .. ;
- * into the output stream instead of calling selectSourceSchema().
- *
- * GPDB_96_MERGE_FIXME: update the above comment because selectSourceSchema
- * has been removed in upstream 9f6e5296a Security: CVE-2018-1058
+ * into the output stream.
*/
prev_ns = NULL;
for (i = 0; i < FCOUNT; i++)
@@ -16096,7 +15841,7 @@ dumpExtProtocol(Archive *fout, const ExtProtInfo *ptcinfo)
ArchiveEntry(fout, ptcinfo->dobj.catId, ptcinfo->dobj.dumpId,
ARCHIVE_OPTS(.tag = ptcinfo->dobj.name,
- .owner = ptcinfo->ptcowner,
+ .owner = ptcinfo->rolname,
.description = "PROTOCOL",
.section = SECTION_PRE_DATA,
.createStmt = q->data,
@@ -16109,9 +15854,7 @@ dumpExtProtocol(Archive *fout, const ExtProtInfo *ptcinfo)
dumpACL(fout, ptcinfo->dobj.dumpId, InvalidDumpId,
"PROTOCOL",
namecopy, NULL,
- NULL, ptcinfo->ptcowner,
- ptcinfo->ptcacl, ptcinfo->rproacl,
- ptcinfo->initproacl, ptcinfo->initrproacl);
+ NULL, ptcinfo->rolname, &ptcinfo->dacl);
free(namecopy);
destroyPQExpBuffer(q);
@@ -16136,8 +15879,8 @@ dumpTSParser(Archive *fout, const TSParserInfo *prsinfo)
PQExpBuffer delq;
char *qprsname;
- /* Skip if not to be dumped */
- if (!prsinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
@@ -16280,8 +16023,8 @@ dumpTSTemplate(Archive *fout, const TSTemplateInfo *tmplinfo)
PQExpBuffer delq;
char *qtmplname;
- /* Skip if not to be dumped */
- if (!tmplinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
@@ -16346,8 +16089,8 @@ dumpTSConfig(Archive *fout, const TSConfigInfo *cfginfo)
int i_tokenname;
int i_dictname;
- /* Skip if not to be dumped */
- if (!cfginfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
@@ -16458,8 +16201,8 @@ dumpForeignDataWrapper(Archive *fout, const FdwInfo *fdwinfo)
PQExpBuffer delq;
char *qfdwname;
- /* Skip if not to be dumped */
- if (!fdwinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
@@ -16508,9 +16251,7 @@ dumpForeignDataWrapper(Archive *fout, const FdwInfo *fdwinfo)
if (fdwinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, fdwinfo->dobj.dumpId, InvalidDumpId,
"FOREIGN DATA WRAPPER", qfdwname, NULL,
- NULL, fdwinfo->rolname,
- fdwinfo->fdwacl, fdwinfo->rfdwacl,
- fdwinfo->initfdwacl, fdwinfo->initrfdwacl);
+ NULL, fdwinfo->rolname, &fdwinfo->dacl);
free(qfdwname);
@@ -16533,8 +16274,8 @@ dumpForeignServer(Archive *fout, const ForeignServerInfo *srvinfo)
char *qsrvname;
char *fdwname;
- /* Skip if not to be dumped */
- if (!srvinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
@@ -16597,9 +16338,7 @@ dumpForeignServer(Archive *fout, const ForeignServerInfo *srvinfo)
if (srvinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, srvinfo->dobj.dumpId, InvalidDumpId,
"FOREIGN SERVER", qsrvname, NULL,
- NULL, srvinfo->rolname,
- srvinfo->srvacl, srvinfo->rsrvacl,
- srvinfo->initsrvacl, srvinfo->initrsrvacl);
+ NULL, srvinfo->rolname, &srvinfo->dacl);
/* Dump user mappings */
if (srvinfo->dobj.dump & DUMP_COMPONENT_USERMAP)
@@ -16726,8 +16465,8 @@ dumpDefaultACL(Archive *fout, const DefaultACLInfo *daclinfo)
PQExpBuffer tag;
const char *type;
- /* Skip if not to be dumped */
- if (!daclinfo->dobj.dump || dopt->dataOnly || dopt->aclsSkip)
+ /* Do nothing in data-only dump, or if we're skipping ACLs */
+ if (dopt->dataOnly || dopt->aclsSkip)
return;
q = createPQExpBuffer();
@@ -16763,15 +16502,13 @@ dumpDefaultACL(Archive *fout, const DefaultACLInfo *daclinfo)
if (!buildDefaultACLCommands(type,
daclinfo->dobj.namespace != NULL ?
daclinfo->dobj.namespace->dobj.name : NULL,
- daclinfo->defaclacl,
- daclinfo->rdefaclacl,
- daclinfo->initdefaclacl,
- daclinfo->initrdefaclacl,
+ daclinfo->dacl.acl,
+ daclinfo->dacl.acldefault,
daclinfo->defaclrole,
fout->remoteVersion,
q))
fatal("could not parse default ACL list (%s)",
- daclinfo->defaclacl);
+ daclinfo->dacl.acl);
if (daclinfo->dobj.dump & DUMP_COMPONENT_ACL)
ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId,
@@ -16801,20 +16538,7 @@ dumpDefaultACL(Archive *fout, const DefaultACLInfo *daclinfo)
* (Currently we assume that subname is only provided for table columns.)
* 'nspname' is the namespace the object is in (NULL if none).
* 'owner' is the owner, NULL if there is no owner (for languages).
- * 'acls' contains the ACL string of the object from the appropriate system
- * catalog field; it will be passed to buildACLCommands for building the
- * appropriate GRANT commands.
- * 'racls' contains the ACL string of any initial-but-now-revoked ACLs of the
- * object; it will be passed to buildACLCommands for building the
- * appropriate REVOKE commands.
- * 'initacls' In binary-upgrade mode, ACL string of the object's initial
- * privileges, to be recorded into pg_init_privs
- * 'initracls' In binary-upgrade mode, ACL string of the object's
- * revoked-from-default privileges, to be recorded into pg_init_privs
- *
- * NB: initacls/initracls are needed because extensions can set privileges on
- * an object during the extension's script file and we record those into
- * pg_init_privs as that object's initial privileges.
+ * 'dacl' is the DumpableAcl struct fpr the object.
*
* Returns the dump ID assigned to the ACL TocEntry, or InvalidDumpId if
* no ACL entry was created.
@@ -16824,11 +16548,15 @@ static DumpId
dumpACL(Archive *fout, DumpId objDumpId, DumpId altDumpId,
const char *type, const char *name, const char *subname,
const char *nspname, const char *owner,
- const char *acls, const char *racls,
- const char *initacls, const char *initracls)
+ const DumpableAcl *dacl)
{
DumpId aclDumpId = InvalidDumpId;
DumpOptions *dopt = fout->dopt;
+ const char *acls = dacl->acl;
+ const char *acldefault = dacl->acldefault;
+ char privtype = dacl->privtype;
+ const char *initprivs = dacl->initprivs;
+ const char *baseacls;
PQExpBuffer sql;
/* Do nothing if ACL dump is not enabled */
@@ -16842,29 +16570,52 @@ dumpACL(Archive *fout, DumpId objDumpId, DumpId altDumpId,
sql = createPQExpBuffer();
/*
- * Check to see if this object has had any initial ACLs included for it.
- * If so, we are in binary upgrade mode and these are the ACLs to turn
- * into GRANT and REVOKE statements to set and record the initial
- * privileges for an extension object. Let the backend know that these
- * are to be recorded by calling binary_upgrade_set_record_init_privs()
- * before and after.
+ * In binary upgrade mode, we don't run an extension's script but instead
+ * dump out the objects independently and then recreate them. To preserve
+ * any initial privileges which were set on extension objects, we need to
+ * compute the set of GRANT and REVOKE commands necessary to get from the
+ * default privileges of an object to its initial privileges as recorded
+ * in pg_init_privs.
+ *
+ * At restore time, we apply these commands after having called
+ * binary_upgrade_set_record_init_privs(true). That tells the backend to
+ * copy the results into pg_init_privs. This is how we preserve the
+ * contents of that catalog across binary upgrades.
*/
- if (strlen(initacls) != 0 || strlen(initracls) != 0)
+ if (dopt->binary_upgrade && privtype == 'e' &&
+ initprivs && *initprivs != '\0')
{
appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
if (!buildACLCommands(name, subname, nspname, type,
- initacls, initracls, owner,
+ initprivs, acldefault, owner,
"", fout->remoteVersion, sql))
- fatal("could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)",
- initacls, initracls, name, type);
+ fatal("could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)",
+ initprivs, acldefault, name, type);
appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
}
+ /*
+ * Now figure the GRANT and REVOKE commands needed to get to the object's
+ * actual current ACL, starting from the initprivs if given, else from the
+ * object-type-specific default. Also, while buildACLCommands will assume
+ * that a NULL/empty acls string means it needn't do anything, what that
+ * actually represents is the object-type-specific default; so we need to
+ * substitute the acldefault string to get the right results in that case.
+ */
+ if (initprivs && *initprivs != '\0')
+ {
+ baseacls = initprivs;
+ if (acls == NULL || *acls == '\0')
+ acls = acldefault;
+ }
+ else
+ baseacls = acldefault;
+
if (!buildACLCommands(name, subname, nspname, type,
- acls, racls, owner,
+ acls, baseacls, owner,
"", fout->remoteVersion, sql))
- fatal("could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)",
- acls, racls, name, type);
+ fatal("could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)",
+ acls, baseacls, name, type);
if (sql->len > 0)
{
@@ -17082,20 +16833,12 @@ dumpTableSecLabel(Archive *fout, const TableInfo *tbinfo, const char *reltypenam
static int
findSecLabels(Archive *fout, Oid classoid, Oid objoid, SecLabelItem **items)
{
- /* static storage for table of security labels */
- static SecLabelItem *labels = NULL;
- static int nlabels = -1;
-
SecLabelItem *middle = NULL;
SecLabelItem *low;
SecLabelItem *high;
int nmatch;
- /* Get security labels if we didn't already */
- if (nlabels < 0)
- nlabels = collectSecLabels(fout, &labels);
-
- if (nlabels <= 0) /* no labels, so no match is possible */
+ if (nseclabels <= 0) /* no labels, so no match is possible */
{
*items = NULL;
return 0;
@@ -17104,8 +16847,8 @@ findSecLabels(Archive *fout, Oid classoid, Oid objoid, SecLabelItem **items)
/*
* Do binary search to find some item matching the object.
*/
- low = &labels[0];
- high = &labels[nlabels - 1];
+ low = &seclabels[0];
+ high = &seclabels[nseclabels - 1];
while (low <= high)
{
middle = low + (high - low) / 2;
@@ -17161,13 +16904,13 @@ findSecLabels(Archive *fout, Oid classoid, Oid objoid, SecLabelItem **items)
/*
* collectSecLabels
*
- * Construct a table of all security labels available for database objects.
- * It's much faster to pull them all at once.
+ * Construct a table of all security labels available for database objects;
+ * also set the has-seclabel component flag for each relevant object.
*
* The table is sorted by classoid/objid/objsubid for speed in lookup.
*/
-static int
-collectSecLabels(Archive *fout, SecLabelItem **items)
+static void
+collectSecLabels(Archive *fout)
{
PGresult *res;
PQExpBuffer query;
@@ -17178,7 +16921,7 @@ collectSecLabels(Archive *fout, SecLabelItem **items)
int i_objsubid;
int ntups;
int i;
- SecLabelItem *labels;
+ DumpableObject *dobj;
query = createPQExpBuffer();
@@ -17198,22 +16941,54 @@ collectSecLabels(Archive *fout, SecLabelItem **items)
ntups = PQntuples(res);
- labels = (SecLabelItem *) pg_malloc(ntups * sizeof(SecLabelItem));
+ seclabels = (SecLabelItem *) pg_malloc(ntups * sizeof(SecLabelItem));
+ nseclabels = 0;
+ dobj = NULL;
for (i = 0; i < ntups; i++)
{
- labels[i].label = PQgetvalue(res, i, i_label);
- labels[i].provider = PQgetvalue(res, i, i_provider);
- labels[i].classoid = atooid(PQgetvalue(res, i, i_classoid));
- labels[i].objoid = atooid(PQgetvalue(res, i, i_objoid));
- labels[i].objsubid = atoi(PQgetvalue(res, i, i_objsubid));
+ CatalogId objId;
+ int subid;
+
+ objId.tableoid = atooid(PQgetvalue(res, i, i_classoid));
+ objId.oid = atooid(PQgetvalue(res, i, i_objoid));
+ subid = atoi(PQgetvalue(res, i, i_objsubid));
+
+ /* We needn't remember labels that don't match any dumpable object */
+ if (dobj == NULL ||
+ dobj->catId.tableoid != objId.tableoid ||
+ dobj->catId.oid != objId.oid)
+ dobj = findObjectByCatalogId(objId);
+ if (dobj == NULL)
+ continue;
+
+ /*
+ * Labels on columns of composite types are linked to the type's
+ * pg_class entry, but we need to set the DUMP_COMPONENT_SECLABEL flag
+ * in the type's own DumpableObject.
+ */
+ if (subid != 0 && dobj->objType == DO_TABLE &&
+ ((TableInfo *) dobj)->relkind == RELKIND_COMPOSITE_TYPE)
+ {
+ TypeInfo *cTypeInfo;
+
+ cTypeInfo = findTypeByOid(((TableInfo *) dobj)->reltype);
+ if (cTypeInfo)
+ cTypeInfo->dobj.components |= DUMP_COMPONENT_SECLABEL;
+ }
+ else
+ dobj->components |= DUMP_COMPONENT_SECLABEL;
+
+ seclabels[nseclabels].label = pg_strdup(PQgetvalue(res, i, i_label));
+ seclabels[nseclabels].provider = pg_strdup(PQgetvalue(res, i, i_provider));
+ seclabels[nseclabels].classoid = objId.tableoid;
+ seclabels[nseclabels].objoid = objId.oid;
+ seclabels[nseclabels].objsubid = subid;
+ nseclabels++;
}
- /* Do NOT free the PGresult since we are keeping pointers into it */
+ PQclear(res);
destroyPQExpBuffer(query);
-
- *items = labels;
- return ntups;
}
/*
@@ -17227,17 +17002,17 @@ dumpTable(Archive *fout, const TableInfo *tbinfo)
DumpId tableAclDumpId = InvalidDumpId;
char *namecopy;
- /*
- * noop if we are not dumping anything about this table, or if we are
- * doing a data-only dump
- */
- if (!tbinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
- if (tbinfo->relkind == RELKIND_SEQUENCE)
- dumpSequence(fout, tbinfo);
- else
- dumpTableSchema(fout, tbinfo);
+ if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
+ {
+ if (tbinfo->relkind == RELKIND_SEQUENCE)
+ dumpSequence(fout, tbinfo);
+ else
+ dumpTableSchema(fout, tbinfo);
+ }
/* Handle the ACL here */
namecopy = pg_strdup(fmtId(tbinfo->dobj.name));
@@ -17250,90 +17025,90 @@ dumpTable(Archive *fout, const TableInfo *tbinfo)
dumpACL(fout, tbinfo->dobj.dumpId, InvalidDumpId,
objtype, namecopy, NULL,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
- tbinfo->relacl, tbinfo->rrelacl,
- tbinfo->initrelacl, tbinfo->initrrelacl);
+ &tbinfo->dacl);
}
/*
* Handle column ACLs, if any. Note: we pull these with a separate query
* rather than trying to fetch them during getTableAttrs, so that we won't
- * miss ACLs on system columns.
+ * miss ACLs on system columns. Doing it this way also allows us to dump
+ * ACLs for catalogs that we didn't mark "interesting" back in getTables.
*/
- if (fout->remoteVersion >= 80400 && tbinfo->dobj.dump & DUMP_COMPONENT_ACL)
+ if ((tbinfo->dobj.dump & DUMP_COMPONENT_ACL) && tbinfo->hascolumnACLs)
{
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
int i;
- if (fout->remoteVersion >= 90600)
+ if (!fout->is_prepared[PREPQUERY_GETCOLUMNACLS])
{
- PQExpBuffer acl_subquery = createPQExpBuffer();
- PQExpBuffer racl_subquery = createPQExpBuffer();
- PQExpBuffer initacl_subquery = createPQExpBuffer();
- PQExpBuffer initracl_subquery = createPQExpBuffer();
+ /* Set up query for column ACLs */
+ appendPQExpBufferStr(query,
+ "PREPARE getColumnACLs(pg_catalog.oid) AS\n");
- buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
- initracl_subquery, "at.attacl", "c.relowner", "'c'",
- dopt->binary_upgrade);
+ if (fout->remoteVersion >= 90600)
+ {
+ /*
+ * In principle we should call acldefault('c', relowner) to
+ * get the default ACL for a column. However, we don't
+ * currently store the numeric OID of the relowner in
+ * TableInfo. We could convert the owner name using regrole,
+ * but that creates a risk of failure due to concurrent role
+ * renames. Given that the default ACL for columns is empty
+ * and is likely to stay that way, it's not worth extra cycles
+ * and risk to avoid hard-wiring that knowledge here.
+ */
+ appendPQExpBufferStr(query,
+ "SELECT at.attname, "
+ "at.attacl, "
+ "'{}' AS acldefault, "
+ "pip.privtype, pip.initprivs "
+ "FROM pg_catalog.pg_attribute at "
+ "LEFT JOIN pg_catalog.pg_init_privs pip ON "
+ "(at.attrelid = pip.objoid "
+ "AND pip.classoid = 'pg_catalog.pg_class'::pg_catalog.regclass "
+ "AND at.attnum = pip.objsubid) "
+ "WHERE at.attrelid = $1 AND "
+ "NOT at.attisdropped "
+ "AND (at.attacl IS NOT NULL OR pip.initprivs IS NOT NULL) "
+ "ORDER BY at.attnum");
+ }
+ else
+ {
+ appendPQExpBufferStr(query,
+ "SELECT attname, attacl, '{}' AS acldefault, "
+ "NULL AS privtype, NULL AS initprivs "
+ "FROM pg_catalog.pg_attribute "
+ "WHERE attrelid = $1 AND NOT attisdropped "
+ "AND attacl IS NOT NULL "
+ "ORDER BY attnum");
+ }
- appendPQExpBuffer(query,
- "SELECT at.attname, "
- "%s AS attacl, "
- "%s AS rattacl, "
- "%s AS initattacl, "
- "%s AS initrattacl "
- "FROM pg_catalog.pg_attribute at "
- "JOIN pg_catalog.pg_class c ON (at.attrelid = c.oid) "
- "LEFT JOIN pg_catalog.pg_init_privs pip ON "
- "(at.attrelid = pip.objoid "
- "AND pip.classoid = 'pg_catalog.pg_class'::pg_catalog.regclass "
- "AND at.attnum = pip.objsubid) "
- "WHERE at.attrelid = '%u'::pg_catalog.oid AND "
- "NOT at.attisdropped "
- "AND ("
- "%s IS NOT NULL OR "
- "%s IS NOT NULL OR "
- "%s IS NOT NULL OR "
- "%s IS NOT NULL)"
- "ORDER BY at.attnum",
- acl_subquery->data,
- racl_subquery->data,
- initacl_subquery->data,
- initracl_subquery->data,
- tbinfo->dobj.catId.oid,
- acl_subquery->data,
- racl_subquery->data,
- initacl_subquery->data,
- initracl_subquery->data);
-
- destroyPQExpBuffer(acl_subquery);
- destroyPQExpBuffer(racl_subquery);
- destroyPQExpBuffer(initacl_subquery);
- destroyPQExpBuffer(initracl_subquery);
- }
- else
- {
- appendPQExpBuffer(query,
- "SELECT attname, attacl, NULL as rattacl, "
- "NULL AS initattacl, NULL AS initrattacl "
- "FROM pg_catalog.pg_attribute "
- "WHERE attrelid = '%u'::pg_catalog.oid AND NOT attisdropped "
- "AND attacl IS NOT NULL "
- "ORDER BY attnum",
- tbinfo->dobj.catId.oid);
+ ExecuteSqlStatement(fout, query->data);
+
+ fout->is_prepared[PREPQUERY_GETCOLUMNACLS] = true;
}
+ printfPQExpBuffer(query,
+ "EXECUTE getColumnACLs('%u')",
+ tbinfo->dobj.catId.oid);
+
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
for (i = 0; i < PQntuples(res); i++)
{
char *attname = PQgetvalue(res, i, 0);
char *attacl = PQgetvalue(res, i, 1);
- char *rattacl = PQgetvalue(res, i, 2);
- char *initattacl = PQgetvalue(res, i, 3);
- char *initrattacl = PQgetvalue(res, i, 4);
+ char *acldefault = PQgetvalue(res, i, 2);
+ char privtype = *(PQgetvalue(res, i, 3));
+ char *initprivs = PQgetvalue(res, i, 4);
+ DumpableAcl coldacl;
char *attnamecopy;
+ coldacl.acl = attacl;
+ coldacl.acldefault = acldefault;
+ coldacl.privtype = privtype;
+ coldacl.initprivs = initprivs;
attnamecopy = pg_strdup(fmtId(attname));
/*
@@ -17344,7 +17119,7 @@ dumpTable(Archive *fout, const TableInfo *tbinfo)
dumpACL(fout, tbinfo->dobj.dumpId, tableAclDumpId,
"TABLE", namecopy, attnamecopy,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
- attacl, rattacl, initattacl, initrattacl);
+ &coldacl);
free(attnamecopy);
}
PQclear(res);
@@ -17375,7 +17150,6 @@ dumpExternal(Archive *fout, const TableInfo *tbinfo, PQExpBuffer q, PQExpBuffer
bool isweb = false;
bool iswritable = false;
char *options;
- bool gpdb6OrLater = isGPDB6000OrLater(fout);
char *logerrors = NULL;
char *on_clause;
char *qualrelname;
@@ -17391,7 +17165,7 @@ dumpExternal(Archive *fout, const TableInfo *tbinfo, PQExpBuffer q, PQExpBuffer
qualrelname);
/* Now get required information from pg_exttable */
- if (gpdb6OrLater)
+ if (fout->remoteVersion >= GPDB6_MAJOR_PGVERSION)
{
appendPQExpBuffer(query,
"SELECT x.urilocation, x.execlocation, x.fmttype, x.fmtopts, x.command, "
@@ -17777,7 +17551,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
char *ftoptions = NULL;
char *srvname = NULL;
char *foreign = "";
-
+ char *partkeydef = NULL;
/* We had better have loaded per-column details about this table */
Assert(tbinfo->interesting);
@@ -17790,8 +17564,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
qrelname);
if (dopt->binary_upgrade)
- binary_upgrade_set_type_oids_by_rel_oid(fout, q,
- tbinfo->dobj.catId.oid);
+ binary_upgrade_set_type_oids_by_rel_oid(fout, q, tbinfo->dobj.catId.oid);
/* Is it a table or a view? */
if (tbinfo->relkind == RELKIND_VIEW)
@@ -17833,8 +17606,29 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
}
else
{
+ /*
+ * Set reltypename, and collect any relkind-specific data that we
+ * didn't fetch during getTables().
+ */
switch (tbinfo->relkind)
{
+ case RELKIND_PARTITIONED_TABLE:
+ {
+ PQExpBuffer query = createPQExpBuffer();
+ PGresult *res;
+
+ reltypename = "TABLE";
+
+ /* retrieve partition key definition */
+ appendPQExpBuffer(query,
+ "SELECT pg_get_partkeydef('%u')",
+ tbinfo->dobj.catId.oid);
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
+ partkeydef = pg_strdup(PQgetvalue(res, 0, 0));
+ PQclear(res);
+ destroyPQExpBuffer(query);
+ break;
+ }
case RELKIND_FOREIGN_TABLE:
{
PQExpBuffer query = createPQExpBuffer();
@@ -17877,10 +17671,10 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
break;
default:
reltypename = "TABLE";
-
/* Is it an external table (server GPDB 6.x and below.) */
if (tbinfo->relstorage == RELSTORAGE_EXTERNAL)
reltypename = "EXTERNAL TABLE";
+ break;
}
}
@@ -17936,6 +17730,9 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
{
Oid part_oid = atooid(PQgetvalue(partres, i, 0));
+ if (tbinfo->relstorage == 'x')
+ hasExternalPartitions = true;
+
binary_upgrade_set_pg_class_oids(fout, q, part_oid, false);
binary_upgrade_set_type_oids_by_rel_oid(fout, q, part_oid);
}
@@ -17967,8 +17764,10 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
* Attach to type, if reloftype; except in case of a binary upgrade,
* we dump the table normally and attach it to the type afterward.
*/
- if (tbinfo->reloftype && !dopt->binary_upgrade)
- appendPQExpBuffer(q, " OF %s", tbinfo->reloftype);
+ if (OidIsValid(tbinfo->reloftype) && !dopt->binary_upgrade)
+ appendPQExpBuffer(q, " OF %s",
+ getFormattedTypeName(fout, tbinfo->reloftype,
+ zeroIsError));
if (tbinfo->relkind != RELKIND_MATVIEW)
{
@@ -18006,7 +17805,8 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
* Skip column if fully defined by reloftype, except in
* binary upgrade
*/
- if (tbinfo->reloftype && !print_default && !print_notnull &&
+ if (OidIsValid(tbinfo->reloftype) &&
+ !print_default && !print_notnull &&
!dopt->binary_upgrade)
continue;
@@ -18047,7 +17847,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
* table ('OF type_name'), but in binary-upgrade mode,
* print it in that case too.
*/
- if (dopt->binary_upgrade || !tbinfo->reloftype)
+ if (dopt->binary_upgrade || !OidIsValid(tbinfo->reloftype))
{
appendPQExpBuffer(q, " %s",
tbinfo->atttypnames[j]);
@@ -18137,7 +17937,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
if (actual_atts)
appendPQExpBufferStr(q, "\n)");
- else if (!(tbinfo->reloftype && !dopt->binary_upgrade))
+ else if (!(OidIsValid(tbinfo->reloftype) && !dopt->binary_upgrade))
{
/*
* No attributes? we must have a parenthesized attribute list,
@@ -18166,7 +17966,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
}
if (tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
- appendPQExpBuffer(q, "\nPARTITION BY %s", tbinfo->partkeydef);
+ appendPQExpBuffer(q, "\nPARTITION BY %s", partkeydef);
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
appendPQExpBuffer(q, "\nSERVER %s", fmtId(srvname));
@@ -18232,125 +18032,29 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
/*
* Dump distributed by clause.
*/
- if (dumpGpPolicy && tbinfo->relkind != RELKIND_FOREIGN_TABLE)
+ if (dopt->dumpGpPolicy && tbinfo->relkind != RELKIND_FOREIGN_TABLE)
addDistributedBy(fout, q, tbinfo, actual_atts);
/*
- * If GP partitioning is supported add the partitioning constraints to
- * the table definition.
+ * Add the GPDB partitioning constraints to the table definition.
+ * These do not exist on GPDB7, so first check if we are dumping
+ * from <= GPDB6.
*/
- if (gp_partitioning_available)
+ if (fout->remoteVersion < GPDB7_MAJOR_PGVERSION &&
+ (tbinfo->partclause && *tbinfo->partclause != '\0'))
{
- bool isTemplatesSupported = fout->remoteVersion >= 80214;
- bool isPartitioned = false;
- PQExpBuffer query = createPQExpBuffer();
- PGresult *res;
-
- /* does support GP partitioning. */
- resetPQExpBuffer(query);
- /* MPP-6297: dump by tablename */
- if (isTemplatesSupported)
- /* use 4.x version of function */
- appendPQExpBuffer(query, "SELECT "
- "pg_get_partition_def('%u'::pg_catalog.oid, true, true) ",
- tbinfo->dobj.catId.oid);
- else /* use 3.x version of function */
- appendPQExpBuffer(query, "SELECT "
- "pg_get_partition_def('%u'::pg_catalog.oid, true) ",
- tbinfo->dobj.catId.oid);
-
- res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
-
- if (PQntuples(res) != 1)
- {
- if (PQntuples(res) < 1)
- pg_log_warning("query to obtain definition of table \"%s\" returned no data",
- tbinfo->dobj.name);
- else
- pg_log_warning("query to obtain definition of table \"%s\" returned more than one definition",
- tbinfo->dobj.name);
- exit_nicely(1);
- }
- isPartitioned = !PQgetisnull(res, 0, 0);
- if (isPartitioned)
- appendPQExpBuffer(q, " %s", PQgetvalue(res, 0, 0));
-
- PQclear(res);
-
- /*
- * MPP-6095: dump ALTER TABLE statements for subpartition
- * templates
- */
- if (isTemplatesSupported)
- {
- resetPQExpBuffer(query);
-
- appendPQExpBuffer(
- query, "SELECT "
- "pg_get_partition_template_def('%u'::pg_catalog.oid, true, true) ",
- tbinfo->dobj.catId.oid);
-
- res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
-
- if (PQntuples(res) != 1)
- {
- if (PQntuples(res) < 1)
- pg_log_warning("query to obtain definition of table \"%s\" returned no data",
- tbinfo->dobj.name);
- else
- pg_log_warning("query to obtain definition of table \"%s\" returned more than one definition",
- tbinfo->dobj.name);
- exit_nicely(1);
- }
-
- /*
- * MPP-9537: terminate (with semicolon) the previous
- * statement, and dump the template definitions
- */
- if (!PQgetisnull(res, 0, 0) &&
- PQgetlength(res, 0, 0))
- appendPQExpBuffer(q, ";\n %s", PQgetvalue(res, 0, 0));
-
- PQclear(res);
- }
-
- if (isPartitioned)
- {
- /*
- * Find out if there are any external partitions.
- *
- * In GPDB 6.X and below, external tables have
- * relkind=RELKIND_RELATION and relstorage=RELSTORAGE_EXTERNAL.
- * In later versions, they are just foreign tables. This query
- * works on all server versions.
- */
- resetPQExpBuffer(query);
- appendPQExpBuffer(query, "SELECT EXISTS (SELECT 1 "
- " FROM pg_class part "
- " JOIN pg_partition_rule pr ON (part.oid = pr.parchildrelid) "
- " JOIN pg_partition p ON (pr.paroid = p.oid) "
- "WHERE p.parrelid = '%u'::pg_catalog.oid "
- " AND (part.relstorage = '%c' OR part.relkind = '%c')) "
- "AS has_external_partitions;",
- tbinfo->dobj.catId.oid,
- RELSTORAGE_EXTERNAL,
- RELKIND_FOREIGN_TABLE);
-
- res = ExecuteSqlQueryForSingleRow(fout, query->data);
- hasExternalPartitions = (PQgetvalue(res, 0, 0)[0] == 't');
- PQclear(res);
- }
-
- destroyPQExpBuffer(query);
- }
-
- /* END MPP ADDITION */
+ /* partition by clause */
+ appendPQExpBuffer(q, " %s", tbinfo->partclause);
+ /* subpartition template */
+ if (tbinfo->parttemplate)
+ appendPQExpBuffer(q, ";\n %s", tbinfo->parttemplate);
+ } /* END MPP ADDITION */
/* Dump generic options if any */
if (ftoptions && ftoptions[0])
appendPQExpBuffer(q, "\nOPTIONS (\n %s\n)", ftoptions);
- if (dumpGpPolicy && tbinfo->relkind == RELKIND_FOREIGN_TABLE && strcmp(srvname, GP_EXTTABLE_SERVER_NAME) == 0)
+ if (dopt->dumpGpPolicy && tbinfo->relkind == RELKIND_FOREIGN_TABLE && strcmp(srvname, GP_EXTTABLE_SERVER_NAME) == 0)
addDistributedBy(fout, q, tbinfo, actual_atts);
appendPQExpBufferStr(q, ";\n");
@@ -18516,7 +18220,8 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
tbinfo->attalign[j]);
appendStringLiteralAH(q, tbinfo->attnames[j], fout);
- if (gp_partitioning_available)
+ /* GPDB partitioning */
+ if (fout->remoteVersion < GPDB7_MAJOR_PGVERSION)
{
/*
* Do for all descendants of a partition table.
@@ -18618,12 +18323,13 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
}
}
- if (tbinfo->reloftype)
+ if (OidIsValid(tbinfo->reloftype))
{
appendPQExpBufferStr(q, "\n-- For binary upgrade, set up typed tables this way.\n");
appendPQExpBuffer(q, "ALTER TABLE ONLY %s OF %s;\n",
qualrelname,
- tbinfo->reloftype);
+ getFormattedTypeName(fout, tbinfo->reloftype,
+ zeroIsError));
}
appendPQExpBuffer(q, "RESET allow_system_table_mods;\n");
}
@@ -18812,6 +18518,8 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
tbinfo->attfdwoptions[j]);
} /* end loop over columns */
+ if (partkeydef)
+ free(partkeydef);
if (ftoptions)
free(ftoptions);
if (srvname)
@@ -18919,7 +18627,10 @@ dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo)
{
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
+ PGresult *res;
+ char *partbound;
+ /* Do nothing in data-only dump */
if (dopt->dataOnly)
return;
@@ -18928,14 +18639,23 @@ dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo)
q = createPQExpBuffer();
- /* Perform ALTER TABLE on the parent */
+ /* Fetch the partition's partbound */
appendPQExpBuffer(q,
+ "SELECT pg_get_expr(c.relpartbound, c.oid) "
+ "FROM pg_class c "
+ "WHERE c.oid = '%u'",
+ attachinfo->partitionTbl->dobj.catId.oid);
+ res = ExecuteSqlQueryForSingleRow(fout, q->data);
+ partbound = PQgetvalue(res, 0, 0);
+
+ /* Perform ALTER TABLE on the parent */
+ printfPQExpBuffer(q,
"ALTER TABLE ONLY %s ",
fmtQualifiedDumpable(attachinfo->parentTbl));
appendPQExpBuffer(q,
"ATTACH PARTITION %s %s;\n",
fmtQualifiedDumpable(attachinfo->partitionTbl),
- attachinfo->partitionTbl->partbound);
+ partbound);
/*
* There is no point in creating a drop query as the drop is done by table
@@ -18952,6 +18672,7 @@ dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo)
.section = SECTION_PRE_DATA,
.createStmt = q->data));
+ PQclear(res);
destroyPQExpBuffer(q);
}
@@ -18970,8 +18691,8 @@ dumpAttrDef(Archive *fout, const AttrDefInfo *adinfo)
char *tag;
char *foreign;
- /* Skip if table definition not to be dumped */
- if (!tbinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/* Skip if not "separate"; it was dumped in the table's definition */
@@ -19067,6 +18788,7 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo)
char *qindxname;
char *qqindxname;
+ /* Do nothing in data-only dump */
if (dopt->dataOnly)
return;
@@ -19200,6 +18922,7 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo)
static void
dumpIndexAttach(Archive *fout, const IndexAttachInfo *attachinfo)
{
+ /* Do nothing in data-only dump */
if (fout->dopt->dataOnly)
return;
@@ -19246,8 +18969,8 @@ dumpStatisticsExt(Archive *fout, const StatsExtInfo *statsextinfo)
PGresult *res;
char *stxdef;
- /* Skip if not to be dumped */
- if (!statsextinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
@@ -19323,8 +19046,8 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo)
char *tag = NULL;
char *foreign;
- /* Skip if not to be dumped */
- if (!coninfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
@@ -19612,29 +19335,6 @@ dumpTableConstraintComment(Archive *fout, const ConstraintInfo *coninfo)
free(qtabname);
}
-/*
- * findLastBuiltinOid_V71 -
- *
- * find the last built in oid
- *
- * For 7.1 through 8.0, we do this by retrieving datlastsysoid from the
- * pg_database entry for the current database. (Note: current_database()
- * requires 7.3; pg_dump requires 8.0 now.)
- */
-static Oid
-findLastBuiltinOid_V71(Archive *fout)
-{
- PGresult *res;
- Oid last_oid;
-
- res = ExecuteSqlQueryForSingleRow(fout,
- "SELECT datlastsysoid FROM pg_database WHERE datname = current_database()");
- last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "datlastsysoid")));
- PQclear(res);
-
- return last_oid;
-}
-
/*
* dumpSequence
* write the declaration (not data) of one user-defined sequence
@@ -19975,10 +19675,7 @@ dumpTrigger(Archive *fout, const TriggerInfo *tginfo)
int findx;
char *tag;
- /*
- * we needn't check dobj.dump because TriggerInfo wouldn't have been
- * created in the first place for non-dumpable triggers
- */
+ /* Do nothing in data-only dump */
if (dopt->dataOnly)
return;
@@ -20214,8 +19911,8 @@ dumpEventTrigger(Archive *fout, const EventTriggerInfo *evtinfo)
PQExpBuffer delqry;
char *qevtname;
- /* Skip if not to be dumped */
- if (!evtinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
@@ -20305,8 +20002,8 @@ dumpRule(Archive *fout, const RuleInfo *rinfo)
PGresult *res;
char *tag;
- /* Skip if not to be dumped */
- if (!rinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/*
@@ -21153,50 +20850,22 @@ findDumpableDependencies(ArchiveHandle *AH, const DumpableObject *dobj,
/*
* isGPbackend - returns true if the connected backend is a GreenPlum DB backend.
*/
-static bool
+static void
testGPbackend(Archive *fout)
{
- PQExpBuffer query;
- PGresult *res;
- bool isGPbackend;
-
- query = createPQExpBuffer();
-
- appendPQExpBuffer(query, "SELECT current_setting('gp_role');");
- ArchiveHandle *AH = (ArchiveHandle *) fout;
- res = PQexec(AH->connection, query->data);
-
- isGPbackend = (PQresultStatus(res) == PGRES_TUPLES_OK);
-
- PQclear(res);
- destroyPQExpBuffer(query);
-
- return isGPbackend;
-}
-
-/*
- * testPartitioningSupport - tests whether or not the current GP
- * database includes support for partitioning.
- */
-static bool
-testPartitioningSupport(Archive *fout)
-{
- PQExpBuffer query;
+ DumpOptions *dopt = fout->dopt;
+ PQExpBuffer query = createPQExpBuffer();
PGresult *res;
- bool isSupported;
- query = createPQExpBuffer();
-
- appendPQExpBuffer(query, "SELECT 1 FROM pg_class WHERE relname = 'pg_partition' and relnamespace = 11;");
+ appendPQExpBuffer(query, "SELECT 1 FROM current_setting('gp_role');");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
- isSupported = (PQntuples(res) == 1);
+ dopt->isGPbackend = (PQntuples(res) == 1);
PQclear(res);
destroyPQExpBuffer(query);
-
- return isSupported;
}
+
/*
* addSchedule
*
@@ -21233,7 +20902,7 @@ addSchedule(Archive *fout, PQExpBuffer q, const TableInfo *tbinfo)
static void
addDistributedBy(Archive *fout, PQExpBuffer q, const TableInfo *tbinfo, int actual_atts)
{
- if (isGPDB6000OrLater(fout))
+ if (fout->remoteVersion >= GPDB6_MAJOR_PGVERSION)
{
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 81fa36289b3..d53d2ab623e 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -88,8 +88,13 @@ typedef enum
DO_SUBSCRIPTION
} DumpableObjectType;
-/* component types of an object which can be selected for dumping */
-typedef uint32 DumpComponents; /* a bitmask of dump object components */
+/*
+ * DumpComponents is a bitmask of the potentially dumpable components of
+ * a database object: its core definition, plus optional attributes such
+ * as ACL, comments, etc. The NONE and ALL symbols are convenient
+ * shorthands.
+ */
+typedef uint32 DumpComponents;
#define DUMP_COMPONENT_NONE (0)
#define DUMP_COMPONENT_DEFINITION (1 << 0)
#define DUMP_COMPONENT_DATA (1 << 1)
@@ -134,8 +139,9 @@ typedef struct _dumpableObject
DumpId dumpId; /* assigned by AssignDumpId() */
char *name; /* object name (should never be NULL) */
struct _namespaceInfo *namespace; /* containing namespace, or NULL */
- DumpComponents dump; /* bitmask of components to dump */
+ DumpComponents dump; /* bitmask of components requested to dump */
DumpComponents dump_contains; /* as above, but for contained objects */
+ DumpComponents components; /* bitmask of components available to dump */
bool ext_member; /* true if object is member of extension */
bool depends_on_ext; /* true if object depends on an extension */
DumpId *dependencies; /* dumpIds of objects this one depends on */
@@ -148,14 +154,34 @@ typedef struct _binaryupgradeinfo
DumpableObject dobj;
} BinaryUpgradeInfo;
+/*
+ * Object types that have ACLs must store them in a DumpableAcl sub-struct,
+ * which must immediately follow the DumpableObject base struct.
+ *
+ * Note: when dumping from a pre-9.2 server, which lacks the acldefault()
+ * function, acldefault will be NULL or empty.
+ */
+typedef struct _dumpableAcl
+{
+ char *acl; /* the object's actual ACL string */
+ char *acldefault; /* default ACL for the object's type & owner */
+ /* these fields come from the object's pg_init_privs entry, if any: */
+ char privtype; /* entry type, 'i' or 'e'; 0 if no entry */
+ char *initprivs; /* the object's initial ACL string, or NULL */
+} DumpableAcl;
+
+/* Generic struct that can be used to access any object type having an ACL */
+typedef struct _dumpableObjectWithAcl
+{
+ DumpableObject dobj;
+ DumpableAcl dacl;
+} DumpableObjectWithAcl;
typedef struct _namespaceInfo
{
DumpableObject dobj;
- char *rolname; /* name of owner, or empty string */
- char *nspacl;
- char *rnspacl;
- char *initnspacl;
- char *initrnspacl;
+ DumpableAcl dacl;
+ Oid nspowner; /* OID of owner */
+ const char *rolname; /* name of owner */
} NamespaceInfo;
typedef struct _extensionInfo
@@ -171,6 +197,7 @@ typedef struct _extensionInfo
typedef struct _typeInfo
{
DumpableObject dobj;
+ DumpableAcl dacl;
/*
* Note: dobj.name is the raw pg_type.typname entry. ftypname is the
@@ -178,7 +205,7 @@ typedef struct _typeInfo
* schema-qualified too.
*/
char *ftypname;
- char *rolname; /* name of owner, or empty string */
+ const char *rolname; /* name of owner, or empty string */
char *typacl;
char *rtypacl;
char *inittypacl;
@@ -209,15 +236,12 @@ typedef struct _shellTypeInfo
typedef struct _funcInfo
{
DumpableObject dobj;
- char *rolname; /* name of owner, or empty string */
+ DumpableAcl dacl;
+ const char *rolname;
Oid lang;
int nargs;
Oid *argtypes;
Oid prorettype;
- char *proacl;
- char *rproacl;
- char *initproacl;
- char *initrproacl;
} FuncInfo;
/* AggInfo is a superset of FuncInfo */
@@ -230,13 +254,11 @@ typedef struct _aggInfo
typedef struct _ptcInfo
{
DumpableObject dobj;
+ DumpableAcl dacl;
char *ptcreadfn;
char *ptcwritefn;
- char *ptcowner;
+ const char *rolname;
char *ptcacl;
- char *rproacl;
- char *initproacl;
- char *initrproacl;
bool ptctrusted;
Oid ptcreadid;
Oid ptcwriteid;
@@ -246,7 +268,7 @@ typedef struct _ptcInfo
typedef struct _oprInfo
{
DumpableObject dobj;
- char *rolname;
+ const char *rolname;
char oprkind;
Oid oprcode;
} OprInfo;
@@ -261,25 +283,25 @@ typedef struct _accessMethodInfo
typedef struct _opclassInfo
{
DumpableObject dobj;
- char *rolname;
+ const char *rolname;
} OpclassInfo;
typedef struct _opfamilyInfo
{
DumpableObject dobj;
- char *rolname;
+ const char *rolname;
} OpfamilyInfo;
typedef struct _collInfo
{
DumpableObject dobj;
- char *rolname;
+ const char *rolname;
} CollInfo;
typedef struct _convInfo
{
DumpableObject dobj;
- char *rolname;
+ const char *rolname;
} ConvInfo;
typedef struct _tableInfo
@@ -288,11 +310,8 @@ typedef struct _tableInfo
* These fields are collected for every table in the database.
*/
DumpableObject dobj;
- char *rolname; /* name of owner, or empty string */
- char *relacl;
- char *rrelacl;
- char *initrelacl;
- char *initrrelacl;
+ DumpableAcl dacl;
+ const char *rolname;
char relkind;
char relstorage;
char relpersistence; /* relation persistence */
@@ -305,6 +324,7 @@ typedef struct _tableInfo
bool hasindex; /* does it have any indexes? */
bool hasrules; /* does it have any rules? */
bool hastriggers; /* does it have any triggers? */
+ bool hascolumnACLs; /* do any columns have non-default ACLs? */
bool rowsec; /* is row security enabled? */
bool forcerowsec; /* is row security forced? */
bool hasoids; /* does it have OIDs? */
@@ -314,7 +334,8 @@ typedef struct _tableInfo
uint32 toast_frozenxid; /* toast table's relfrozenxid, if any */
uint32 toast_minmxid; /* toast table's relminmxid */
int ncheck; /* # of CHECK expressions */
- char *reloftype; /* underlying type for typed table */
+ Oid reltype; /* OID of table's composite type, if any */
+ Oid reloftype; /* underlying type for typed table */
Oid foreign_server; /* foreign server oid, if applicable */
/* these two are set only if table is a sequence owned by a column: */
Oid owning_tab; /* OID of table owning sequence */
@@ -355,8 +376,6 @@ typedef struct _tableInfo
char **attencoding; /* the attribute encoding values */
struct _attrDefInfo **attrdefs; /* DEFAULT expressions */
struct _constraintInfo *checkexprs; /* CHECK constraints */
- char *partkeydef; /* partition key definition */
- char *partbound; /* partition bound definition */
bool needs_override; /* has GENERATED ALWAYS AS IDENTITY */
char *amname; /* relation access method */
Oid amoid; /* relation access method oid */
@@ -366,15 +385,19 @@ typedef struct _tableInfo
*/
int numParents; /* number of (immediate) parent tables */
struct _tableInfo **parents; /* TableInfos of immediate parents */
- Oid parrelid; /* external partition's parent oid */
+ Oid parrelid; /* partition's parent oid */
bool parparent; /* true if the table is partition parent */
int numIndexes; /* number of indexes */
struct _indxInfo *indexes; /* indexes */
struct _tableDataInfo *dataObj; /* TableDataInfo, if dumping its data */
int numTriggers; /* number of triggers for table */
struct _triggerInfo *triggers; /* array of TriggerInfo structs */
- bool isivm; /* is incrementally maintainable materialized view? */
- bool isdynamic; /* is dynamic table? */
+
+ /* GPDB */
+ bool isivm; /* is incrementally maintainable materialized view? */
+ bool isdynamic; /* is dynamic table? */
+ char *partclause; /* partition definition, if table is partition parent */
+ char *parttemplate; /* subpartition template */
} TableInfo;
typedef struct _tableAttachInfo
@@ -432,7 +455,7 @@ typedef struct _indexAttachInfo
typedef struct _statsExtInfo
{
DumpableObject dobj;
- char *rolname; /* name of owner, or empty string */
+ const char *rolname; /* name of owner, or empty string */
int stattarget; /* statistics target */
} StatsExtInfo;
@@ -471,7 +494,7 @@ typedef struct _evttriggerInfo
DumpableObject dobj;
char *evtname;
char *evtevent;
- char *evtowner;
+ const char *evtowner;
char *evttags;
char *evtfname;
char evtenabled;
@@ -503,15 +526,12 @@ typedef struct _constraintInfo
typedef struct _procLangInfo
{
DumpableObject dobj;
+ DumpableAcl dacl;
bool lanpltrusted;
Oid lanplcallfoid;
Oid laninline;
Oid lanvalidator;
- char *lanacl;
- char *rlanacl;
- char *initlanacl;
- char *initrlanacl;
- char *lanowner; /* name of owner, or empty string */
+ const char *lanowner;
} ProcLangInfo;
typedef struct _castInfo
@@ -553,7 +573,7 @@ typedef struct _prsInfo
typedef struct _dictInfo
{
DumpableObject dobj;
- char *rolname;
+ const char *rolname;
Oid dicttemplate;
char *dictinitoption;
} TSDictInfo;
@@ -568,56 +588,44 @@ typedef struct _tmplInfo
typedef struct _cfgInfo
{
DumpableObject dobj;
- char *rolname;
+ const char *rolname;
Oid cfgparser;
} TSConfigInfo;
typedef struct _fdwInfo
{
DumpableObject dobj;
- char *rolname;
+ DumpableAcl dacl;
+ const char *rolname;
char *fdwhandler;
char *fdwvalidator;
char *fdwoptions;
- char *fdwacl;
- char *rfdwacl;
- char *initfdwacl;
- char *initrfdwacl;
} FdwInfo;
typedef struct _foreignServerInfo
{
DumpableObject dobj;
- char *rolname;
+ DumpableAcl dacl;
+ const char *rolname;
Oid srvfdw;
char *srvtype;
char *srvversion;
- char *srvacl;
- char *rsrvacl;
- char *initsrvacl;
- char *initrsrvacl;
char *srvoptions;
} ForeignServerInfo;
typedef struct _defaultACLInfo
{
DumpableObject dobj;
- char *defaclrole;
+ DumpableAcl dacl;
+ const char *defaclrole;
char defaclobjtype;
- char *defaclacl;
- char *rdefaclacl;
- char *initdefaclacl;
- char *initrdefaclacl;
} DefaultACLInfo;
typedef struct _blobInfo
{
DumpableObject dobj;
- char *rolname;
- char *blobacl;
- char *rblobacl;
- char *initblobacl;
- char *initrblobacl;
+ DumpableAcl dacl;
+ const char *rolname;
} BlobInfo;
/*
@@ -644,7 +652,7 @@ typedef struct _policyInfo
typedef struct _PublicationInfo
{
DumpableObject dobj;
- char *rolname;
+ const char *rolname;
bool puballtables;
bool pubinsert;
bool pubupdate;
@@ -670,7 +678,7 @@ typedef struct _PublicationRelInfo
typedef struct _SubscriptionInfo
{
DumpableObject dobj;
- char *rolname;
+ const char *rolname;
char *subconninfo;
char *subslotname;
char *subbinary;
@@ -766,8 +774,7 @@ extern void getSubscriptions(Archive *fout);
/* START MPP ADDITION */
extern ExtProtInfo *getExtProtocols(Archive *fout, int *numExtProtocols);
extern BinaryUpgradeInfo *getBinaryUpgradeObjects(void);
-
-extern bool testExtProtocolSupport(Archive *fout);
+extern void getPartitionDefs(Archive *fout, TableInfo tblinfo[], int numTables);
/* END MPP ADDITION */
#endif /* PG_DUMP_H */
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 1684a2b87ca..73a898fb220 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -615,7 +615,7 @@ main(int argc, char *argv[])
}
/* Force quoting of all identifiers if requested. */
- if (quote_all_identifiers && server_version >= 80300)
+ if (quote_all_identifiers)
executeCommand(conn, "SET quote_all_identifiers = true");
fprintf(OPF,"--\n-- Apache Cloudberry cluster dump\n--\n\n");
@@ -845,16 +845,31 @@ dumpResGroups(PGconn *conn)
i_cpu_weight,
i_cpuset;
- printfPQExpBuffer(buf, "SELECT g.rsgname AS groupname, "
- "t1.value AS concurrency, "
- "t2.value AS cpu_max_percent, "
- "t3.value AS cpu_weight, "
- "t4.value AS cpuset "
- "FROM pg_resgroup g "
- " JOIN pg_resgroupcapability t1 ON g.oid = t1.resgroupid AND t1.reslimittype = 1 "
- " JOIN pg_resgroupcapability t2 ON g.oid = t2.resgroupid AND t2.reslimittype = 2 "
- " JOIN pg_resgroupcapability t3 ON g.oid = t3.resgroupid AND t3.reslimittype = 3 "
- "LEFT JOIN pg_resgroupcapability t4 ON g.oid = t4.resgroupid AND t4.reslimittype = 4;");
+ if (server_version >= GPDB7_MAJOR_PGVERSION)
+ {
+ printfPQExpBuffer(buf, "SELECT g.rsgname AS groupname, "
+ "t1.value AS concurrency, "
+ "t2.value AS cpu_max_percent, "
+ "t3.value AS cpu_weight, "
+ "t4.value AS cpuset "
+ "FROM pg_resgroup g "
+ " JOIN pg_resgroupcapability t1 ON g.oid = t1.resgroupid AND t1.reslimittype = 1 "
+ " JOIN pg_resgroupcapability t2 ON g.oid = t2.resgroupid AND t2.reslimittype = 2 "
+ " JOIN pg_resgroupcapability t3 ON g.oid = t3.resgroupid AND t3.reslimittype = 3 "
+ "LEFT JOIN pg_resgroupcapability t4 ON g.oid = t4.resgroupid AND t4.reslimittype = 4;");
+ }
+ else
+ {
+ printfPQExpBuffer(buf, "SELECT g.rsgname AS groupname, "
+ "t1.value AS concurrency, "
+ "t2.value AS cpu_max_percent, "
+ " 100 AS cpu_weight, "
+ "t7.value AS cpuset "
+ "FROM pg_resgroup g "
+ " JOIN pg_resgroupcapability t1 ON g.oid = t1.resgroupid AND t1.reslimittype = 1 "
+ " JOIN pg_resgroupcapability t2 ON g.oid = t2.resgroupid AND t2.reslimittype = 2 "
+ "LEFT JOIN pg_resgroupcapability t7 ON g.oid = t7.resgroupid AND t7.reslimittype = 7;");
+ }
res = executeQuery(conn, buf->data);
@@ -917,7 +932,7 @@ dumpResGroups(PGconn *conn)
else
{
printfPQExpBuffer(buf, "CREATE RESOURCE GROUP %s WITH ("
- "concurrency=%s, cpu_set=%s);\n",
+ "concurrency=%s, cpuset=%s);\n",
fmtId(groupname), concurrency, cpuset);
}
@@ -1395,10 +1410,13 @@ dumpRoles(PGconn *conn)
else
appendPQExpBufferStr(buf, " NOREPLICATION");
- if (strcmp(PQgetvalue(res, i, i_rolbypassrls), "t") == 0)
- appendPQExpBufferStr(buf, " BYPASSRLS");
- else
- appendPQExpBufferStr(buf, " NOBYPASSRLS");
+ if (server_version >= 90600)
+ {
+ if (strcmp(PQgetvalue(res, i, i_rolbypassrls), "t") == 0)
+ appendPQExpBufferStr(buf, " BYPASSRLS");
+ else
+ appendPQExpBufferStr(buf, " NOBYPASSRLS");
+ }
if (strcmp(PQgetvalue(res, i, i_rolconnlimit), "-1") != 0)
appendPQExpBuffer(buf, " CONNECTION LIMIT %s",
@@ -1673,89 +1691,12 @@ dumpTablespaces(PGconn *conn)
* [FIXME] the queries need to be slightly different if the backend isn't
* Cloudberry, and the dump format should vary depending on if the dump is
* --gp-syntax or --no-gp-syntax.
- *
- * For the tablespace ACLs, as of 9.6, we extract both the positive (as
- * spcacl) and negative (as rspcacl) ACLs, relative to the default ACL for
- * tablespaces, which are then passed to buildACLCommands() below.
- *
- * See buildACLQueries() and buildACLCommands().
- *
- * The order in which privileges are in the ACL string (the order they
- * have been GRANT'd in, which the backend maintains) must be preserved to
- * ensure that GRANTs WITH GRANT OPTION and subsequent GRANTs based on
- * those are dumped in the correct order.
- *
- * Note that we do not support initial privileges (pg_init_privs) on
- * tablespaces, so this logic cannot make use of buildACLQueries().
*/
-
- if (server_version >= 140000)
- {
- res = executeQuery(conn, "SELECT oid, spcname, "
- "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
- "pg_catalog.pg_tablespace_location(oid), "
- "(SELECT array_agg(acl ORDER BY row_n) FROM "
- " (SELECT acl, row_n FROM "
- " unnest(coalesce(spcacl,acldefault('t',spcowner))) "
- " WITH ORDINALITY AS perm(acl,row_n) "
- " WHERE NOT EXISTS ( "
- " SELECT 1 "
- " FROM unnest(acldefault('t',spcowner)) "
- " AS init(init_acl) "
- " WHERE acl = init_acl)) AS spcacls) "
- " AS spcacl, "
- "(SELECT array_agg(acl ORDER BY row_n) FROM "
- " (SELECT acl, row_n FROM "
- " unnest(acldefault('t',spcowner)) "
- " WITH ORDINALITY AS initp(acl,row_n) "
- " WHERE NOT EXISTS ( "
- " SELECT 1 "
- " FROM unnest(coalesce(spcacl,acldefault('t',spcowner))) "
- " AS permp(orig_acl) "
- " WHERE acl = orig_acl)) AS rspcacls) "
- " AS rspcacl, "
- "array_to_string(spcoptions, ', '),"
- "pg_catalog.shobj_description(oid, 'pg_tablespace'), "
- "spcfilehandlersrc AS spchandlersrc, "
- "spcfilehandlerbin AS spchandlerbin "
- "FROM pg_catalog.pg_tablespace "
- "WHERE spcname !~ '^pg_' "
- "ORDER BY 1");
- }
- else if (server_version >= 90600)
- res = executeQuery(conn, "SELECT oid, spcname, "
- "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
- "pg_catalog.pg_tablespace_location(oid), "
- "(SELECT array_agg(acl ORDER BY row_n) FROM "
- " (SELECT acl, row_n FROM "
- " unnest(coalesce(spcacl,acldefault('t',spcowner))) "
- " WITH ORDINALITY AS perm(acl,row_n) "
- " WHERE NOT EXISTS ( "
- " SELECT 1 "
- " FROM unnest(acldefault('t',spcowner)) "
- " AS init(init_acl) "
- " WHERE acl = init_acl)) AS spcacls) "
- " AS spcacl, "
- "(SELECT array_agg(acl ORDER BY row_n) FROM "
- " (SELECT acl, row_n FROM "
- " unnest(acldefault('t',spcowner)) "
- " WITH ORDINALITY AS initp(acl,row_n) "
- " WHERE NOT EXISTS ( "
- " SELECT 1 "
- " FROM unnest(coalesce(spcacl,acldefault('t',spcowner))) "
- " AS permp(orig_acl) "
- " WHERE acl = orig_acl)) AS rspcacls) "
- " AS rspcacl, "
- "array_to_string(spcoptions, ', '),"
- "pg_catalog.shobj_description(oid, 'pg_tablespace'), null "
- "FROM pg_catalog.pg_tablespace "
- "WHERE spcname !~ '^pg_' "
- "ORDER BY 1");
- else if (server_version >= 90200)
+ if (server_version >= 90200)
res = executeQuery(conn, "SELECT oid, spcname, "
"pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
"pg_catalog.pg_tablespace_location(oid), "
- "spcacl, '' as rspcacl, "
+ "spcacl, acldefault('t', spcowner) AS acldefault, "
"array_to_string(spcoptions, ', '),"
"pg_catalog.shobj_description(oid, 'pg_tablespace'), null "
"FROM pg_catalog.pg_tablespace "
@@ -1764,7 +1705,7 @@ dumpTablespaces(PGconn *conn)
else if (server_version >= 90000)
res = executeQuery(conn, "SELECT oid, spcname, "
"pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
- "spclocation, spcacl, '' as rspcacl, "
+ "spclocation, spcacl, NULL AS acldefault, "
"array_to_string(spcoptions, ', '),"
"pg_catalog.shobj_description(oid, 'pg_tablespace'), null "
"FROM pg_catalog.pg_tablespace "
@@ -1773,8 +1714,8 @@ dumpTablespaces(PGconn *conn)
else
res = executeQuery(conn, "SELECT oid, spcname, "
"pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
- "spclocation, spcacl, '' as rspcacl, null, "
- "pg_catalog.shobj_description(oid, 'pg_tablespace'), null "
+ "spclocation, spcacl, NULL AS acldefault, null, "
+ "pg_catalog.shobj_description(oid, 'pg_tablespace') "
"FROM pg_catalog.pg_tablespace "
"WHERE spcname !~ '^pg_' "
"ORDER BY 1");
@@ -1790,7 +1731,7 @@ dumpTablespaces(PGconn *conn)
char *spcowner = PQgetvalue(res, i, 2);
char *spclocation = PQgetvalue(res, i, 3);
char *spcacl = PQgetvalue(res, i, 4);
- char *rspcacl = PQgetvalue(res, i, 5);
+ char *acldefault = PQgetvalue(res, i, 5);
char *spcoptions = PQgetvalue(res, i, 6);
char *spccomment = PQgetvalue(res, i, 7);
char *spchandlersrc = PQgetvalue(res, i, 8);
@@ -1824,9 +1765,11 @@ dumpTablespaces(PGconn *conn)
appendPQExpBuffer(buf, "ALTER TABLESPACE %s SET (%s);\n",
fspcname, spcoptions);
+ /* tablespaces can't have initprivs */
+
if (!skip_acls &&
!buildACLCommands(fspcname, NULL, NULL, "TABLESPACE",
- spcacl, rspcacl,
+ spcacl, acldefault,
spcowner, "", server_version, buf))
{
pg_log_error("could not parse ACL list (%s) for tablespace \"%s\"",
@@ -2710,7 +2653,7 @@ connectDatabase(const char *dbname, const char *connection_string,
* our own major version. (See also version check in pg_dump.c.)
*/
if (my_version != server_version
- && (server_version < 80300 || /* we can handle back to 8.3 */
+ && (server_version < GPDB5_MAJOR_PGVERSION || /* we can handle back to 8.3 */
(server_version / 100) > (my_version / 100)))
{
pg_log_error("server version: %s; %s version: %s",
diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl
index 1a6ab11a3ed..5ec7e3f2b20 100644
--- a/src/bin/pg_dump/t/002_pg_dump.pl
+++ b/src/bin/pg_dump/t/002_pg_dump.pl
@@ -198,6 +198,24 @@
'--exclude-table=dump_test.test_table', 'postgres',
],
},
+ exclude_measurement => {
+ dump_cmd => [
+ 'pg_dump', '--no-sync',
+ "--file=$tempdir/exclude_measurement.sql",
+ '--exclude-table-and-children=dump_test.measurement',
+ 'postgres',
+ ],
+ },
+ exclude_measurement_data => {
+ dump_cmd => [
+ 'pg_dump',
+ '--no-sync',
+ "--file=$tempdir/exclude_measurement_data.sql",
+ '--exclude-table-data-and-children=dump_test.measurement',
+ '--no-unlogged-table-data',
+ 'postgres',
+ ],
+ },
exclude_test_table_data => {
dump_cmd => [
'pg_dump',
@@ -285,6 +303,17 @@
'postgres',
],
},
+ only_dump_measurement => {
+ dump_cmd => [
+ 'pg_dump',
+ '--no-sync',
+ "--file=$tempdir/only_dump_measurement.sql",
+ '--table-and-children=dump_test.measurement',
+ '--lock-wait-timeout='
+ . (1000 * $TestLib::timeout_default),
+ 'postgres',
+ ],
+ },
role => {
dump_cmd => [
'pg_dump',
@@ -402,7 +431,8 @@
# Tests which target the 'dump_test' schema, specifically.
my %dump_test_schema_runs = (
only_dump_test_schema => 1,
- test_schema_plus_blobs => 1,);
+ test_schema_plus_blobs => 1,
+ only_dump_measurement => 1);
# Tests which are considered 'full' dumps by pg_dump, but there
# are flags used to exclude specific items (ACLs, blobs, etc).
@@ -417,6 +447,8 @@
exclude_test_table_data => 1,
no_toast_compression => 1,
no_blobs => 1,
+ exclude_measurement => 1,
+ exclude_measurement_data => 1,
no_owner => 1,
no_privs => 1,
pg_dumpall_dbprivs => 1,
@@ -450,6 +482,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_privs => 1,
+ only_dump_measurement => 1,
},
},
@@ -469,6 +502,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_privs => 1,
+ only_dump_measurement => 1,
},
},
@@ -547,6 +581,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_owner => 1,
+ only_dump_measurement => 1,
},
},
@@ -560,6 +595,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_owner => 1,
+ only_dump_measurement => 1,
},
},
@@ -592,7 +628,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'ALTER OPERATOR CLASS dump_test.op_class OWNER TO' => {
@@ -605,6 +644,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_owner => 1,
+ only_dump_measurement => 1,
},
},
@@ -645,6 +685,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_owner => 1,
+ only_dump_measurement => 1,
},
},
@@ -671,6 +712,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -688,6 +730,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -707,6 +750,7 @@
},
unlike => {
exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
},
},
@@ -726,6 +770,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -745,6 +790,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -764,6 +810,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -783,6 +830,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -797,6 +845,10 @@
role => 1,
section_pre_data => 1,
binary_upgrade => 1,
+ only_dump_measurement => 1,
+ },
+ unlike => {
+ exclude_measurement => 1,
},
},
@@ -816,6 +868,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -837,7 +890,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'ALTER TABLE test_table OWNER TO' => {
@@ -851,6 +907,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
no_owner => 1,
},
},
@@ -870,6 +927,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -881,16 +939,22 @@
unlike => {
exclude_dump_test_schema => 1,
no_owner => 1,
+ only_dump_measurement => 1,
},
},
'ALTER TABLE measurement OWNER TO' => {
regexp => qr/^\QALTER TABLE dump_test.measurement OWNER TO \E.+;/m,
- like =>
- { %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
+ like => {
+ %full_runs,
+ %dump_test_schema_runs,
+ section_pre_data => 1,
+ only_dump_measurement => 1,
+ },
unlike => {
exclude_dump_test_schema => 1,
no_owner => 1,
+ exclude_measurement => 1,
},
},
@@ -901,8 +965,12 @@
%full_runs,
role => 1,
section_pre_data => 1,
+ only_dump_measurement => 1,
+ },
+ unlike => {
+ no_owner => 1,
+ exclude_measurement => 1,
},
- unlike => { no_owner => 1, },
},
'ALTER FOREIGN TABLE foreign_table OWNER TO' => {
@@ -913,6 +981,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_owner => 1,
+ only_dump_measurement => 1,
},
},
@@ -924,6 +993,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_owner => 1,
+ only_dump_measurement => 1,
},
},
@@ -937,6 +1007,7 @@
only_dump_test_table => 1,
no_owner => 1,
role => 1,
+ only_dump_measurement => 1,
},
},
@@ -1010,6 +1081,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -1029,6 +1101,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -1041,7 +1114,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'COMMENT ON COLUMN dump_test.test_second_table.col1' => {
@@ -1053,7 +1129,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'COMMENT ON COLUMN dump_test.test_second_table.col2' => {
@@ -1065,7 +1144,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'COMMENT ON CONVERSION dump_test.test_conversion' => {
@@ -1076,7 +1158,10 @@
qr/^\QCOMMENT ON CONVERSION dump_test.test_conversion IS 'comment on test conversion';\E/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'COMMENT ON COLLATION test0' => {
@@ -1143,7 +1228,10 @@
qr/^\QCOMMENT ON TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1 IS 'comment on text search configuration';\E/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'COMMENT ON TEXT SEARCH DICTIONARY dump_test.alt_ts_dict1' => {
@@ -1155,7 +1243,10 @@
qr/^\QCOMMENT ON TEXT SEARCH DICTIONARY dump_test.alt_ts_dict1 IS 'comment on text search dictionary';\E/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'COMMENT ON TEXT SEARCH PARSER dump_test.alt_ts_prs1' => {
@@ -1166,7 +1257,10 @@
qr/^\QCOMMENT ON TEXT SEARCH PARSER dump_test.alt_ts_prs1 IS 'comment on text search parser';\E/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'COMMENT ON TEXT SEARCH TEMPLATE dump_test.alt_ts_temp1' => {
@@ -1177,7 +1271,10 @@
qr/^\QCOMMENT ON TEXT SEARCH TEMPLATE dump_test.alt_ts_temp1 IS 'comment on text search template';\E/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'COMMENT ON TYPE dump_test.planets - ENUM' => {
@@ -1188,7 +1285,10 @@
qr/^\QCOMMENT ON TYPE dump_test.planets IS 'comment on enum type';\E/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'COMMENT ON TYPE dump_test.textrange - RANGE' => {
@@ -1199,7 +1299,10 @@
qr/^\QCOMMENT ON TYPE dump_test.textrange IS 'comment on range type';\E/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'COMMENT ON TYPE dump_test.int42 - Regular' => {
@@ -1210,7 +1313,10 @@
qr/^\QCOMMENT ON TYPE dump_test.int42 IS 'comment on regular type';\E/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'COMMENT ON TYPE dump_test.undefined - Undefined' => {
@@ -1221,7 +1327,10 @@
qr/^\QCOMMENT ON TYPE dump_test.undefined IS 'comment on undefined type';\E/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'COPY test_table' => {
@@ -1245,6 +1354,7 @@
exclude_test_table => 1,
exclude_test_table_data => 1,
schema_only => 1,
+ only_dump_measurement => 1,
},
},
@@ -1268,6 +1378,7 @@
binary_upgrade => 1,
exclude_dump_test_schema => 1,
schema_only => 1,
+ only_dump_measurement => 1,
},
},
@@ -1303,6 +1414,7 @@
binary_upgrade => 1,
exclude_dump_test_schema => 1,
schema_only => 1,
+ only_dump_measurement => 1,
},
},
@@ -1324,6 +1436,7 @@
binary_upgrade => 1,
exclude_dump_test_schema => 1,
schema_only => 1,
+ only_dump_measurement => 1,
},
},
@@ -1346,6 +1459,7 @@
binary_upgrade => 1,
exclude_dump_test_schema => 1,
schema_only => 1,
+ only_dump_measurement => 1,
},
},
@@ -1367,6 +1481,7 @@
binary_upgrade => 1,
exclude_dump_test_schema => 1,
schema_only => 1,
+ only_dump_measurement => 1,
},
},
@@ -1388,6 +1503,7 @@
binary_upgrade => 1,
exclude_dump_test_schema => 1,
schema_only => 1,
+ only_dump_measurement => 1,
},
},
@@ -1567,7 +1683,10 @@
exclude_test_table => 1,
section_pre_data => 1,
},
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE CONVERSION dump_test.test_conversion' => {
@@ -1578,7 +1697,10 @@
qr/^\QCREATE DEFAULT CONVERSION dump_test.test_conversion FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;\E/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE DOMAIN dump_test.us_postal_code' => {
@@ -1597,7 +1719,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE FUNCTION dump_test.pltestlang_call_handler' => {
@@ -1614,7 +1739,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE FUNCTION dump_test.trigger_func' => {
@@ -1630,7 +1758,10 @@
\$\$;/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE FUNCTION dump_test.event_trigger_func' => {
@@ -1646,7 +1777,10 @@
\$\$;/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE OPERATOR FAMILY dump_test.op_family' => {
@@ -1658,7 +1792,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE OPERATOR CLASS dump_test.op_class' => {
@@ -1688,7 +1825,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
# verify that a custom operator/opclass/range type is dumped in right order
@@ -1718,7 +1858,10 @@
/xms,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE OPERATOR CLASS dump_test.op_class_empty' => {
@@ -1733,7 +1876,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE EVENT TRIGGER test_event_trigger' => {
@@ -1769,6 +1915,7 @@
unlike => {
exclude_test_table => 1,
exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
},
},
@@ -1787,6 +1934,7 @@
unlike => {
binary_upgrade => 1,
exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
},
},
@@ -1815,7 +1963,10 @@
\n\);/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TYPE dump_test.int42' => {
@@ -1824,7 +1975,10 @@
regexp => qr/^\QCREATE TYPE dump_test.int42;\E/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1' => {
@@ -1836,7 +1990,10 @@
\s+\QPARSER = pg_catalog."default" );\E/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'ALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1 ...' => {
@@ -1901,7 +2058,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TEXT SEARCH TEMPLATE dump_test.alt_ts_temp1' => {
@@ -1913,7 +2073,10 @@
\s+\QLEXIZE = dsimple_lexize );\E/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TEXT SEARCH PARSER dump_test.alt_ts_prs1' => {
@@ -1929,7 +2092,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TEXT SEARCH DICTIONARY dump_test.alt_ts_dict1' => {
@@ -1942,7 +2108,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE FUNCTION dump_test.int42_in' => {
@@ -1957,7 +2126,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE FUNCTION dump_test.int42_out' => {
@@ -1972,7 +2144,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE FUNCTION ... SUPPORT' => {
@@ -1986,7 +2161,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE PROCEDURE dump_test.ptest1' => {
@@ -2000,7 +2178,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TYPE dump_test.int42 populated' => {
@@ -2024,7 +2205,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TYPE dump_test.composite' => {
@@ -2041,7 +2225,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TYPE dump_test.undefined' => {
@@ -2050,7 +2237,10 @@
regexp => qr/^\QCREATE TYPE dump_test.undefined;\E/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'ALTER TYPE dump_test.int42 SET DEFAULT ENCODING' => {
@@ -2060,7 +2250,10 @@
regexp => qr/^\QALTER TYPE dump_test.int42 SET DEFAULT ENCODING (compresstype=rle_type, blocksize=8192, compresslevel=4);\E/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE FOREIGN DATA WRAPPER dummy' => {
@@ -2093,7 +2286,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE USER MAPPING FOR regress_dump_test_role SERVER s1' => {
@@ -2138,7 +2334,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE MATERIALIZED VIEW matview_second' => {
@@ -2154,7 +2353,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE MATERIALIZED VIEW matview_third' => {
@@ -2170,7 +2372,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE MATERIALIZED VIEW matview_fourth' => {
@@ -2186,7 +2391,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE MATERIALIZED VIEW matview_compression' => {
@@ -2282,6 +2490,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -2302,6 +2511,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -2322,6 +2532,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -2342,6 +2553,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -2362,6 +2574,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -2382,6 +2595,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -2457,7 +2671,10 @@
regexp => qr/^CREATE SCHEMA dump_test;/m,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE SCHEMA dump_test_second_schema' => {
@@ -2498,6 +2715,7 @@
unlike => {
exclude_dump_test_schema => 1,
exclude_test_table => 1,
+ only_dump_measurement => 1,
},
},
@@ -2513,7 +2731,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TABLE test_second_table' => {
@@ -2530,7 +2751,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TABLE test_compression' => {
@@ -2574,11 +2798,16 @@
\)\n
\QPARTITION BY RANGE (logdate);\E\n
/xm,
- like =>
- { %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
+ like => {
+ %full_runs,
+ %dump_test_schema_runs,
+ section_pre_data => 1,
+ only_dump_measurement => 1,
+ },
unlike => {
binary_upgrade => 1,
exclude_dump_test_schema => 1,
+ exclude_measurement => 1,
},
},
@@ -2605,6 +2834,10 @@
section_pre_data => 1,
role => 1,
binary_upgrade => 1,
+ only_dump_measurement => 1,
+ },
+ unlike => {
+ exclude_measurement => 1,
},
},
@@ -2620,9 +2853,40 @@
/xm,
like => {
%full_runs, %dump_test_schema_runs, section_post_data => 1,
+ only_dump_measurement => 1,
},
unlike => {
exclude_dump_test_schema => 1,
+ exclude_measurement => 1,
+ },
+ },
+
+ 'COPY measurement' => {
+ create_order => 93,
+ create_sql => 'INSERT INTO dump_test.measurement (city_id, logdate, peaktemp, unitsales) '
+ . "VALUES (1, '2006-02-12', 35, 1);",
+ regexp => qr/^
+ \QCOPY dump_test_second_schema.measurement_y2006m2 (city_id, logdate, peaktemp, unitsales) FROM stdin;\E
+ \n(?:1\t2006-02-12\t35\t1\n)\\\.\n
+ /xm,
+ like => {
+ %full_runs,
+ %dump_test_schema_runs,
+ data_only => 1,
+ only_dump_measurement => 1,
+ section_data => 1,
+ only_dump_test_schema => 1,
+ role_parallel => 1,
+ role => 1,
+ },
+ unlike => {
+ binary_upgrade => 1,
+ schema_only => 1,
+ exclude_measurement => 1,
+ only_dump_test_schema => 1,
+ test_schema_plus_blobs => 1,
+ exclude_measurement => 1,
+ exclude_measurement_data => 1,
},
},
@@ -2650,6 +2914,10 @@
section_post_data => 1,
role => 1,
binary_upgrade => 1,
+ only_dump_measurement => 1,
+ },
+ unlike => {
+ exclude_measurement => 1,
},
},
@@ -2662,6 +2930,10 @@
section_post_data => 1,
role => 1,
binary_upgrade => 1,
+ only_dump_measurement => 1,
+ },
+ unlike => {
+ exclude_measurement => 1,
},
},
@@ -2674,6 +2946,10 @@
section_post_data => 1,
role => 1,
binary_upgrade => 1,
+ only_dump_measurement => 1,
+ },
+ unlike => {
+ exclude_measurement => 1,
},
},
@@ -2709,7 +2985,11 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { binary_upgrade => 1, exclude_dump_test_schema => 1, },
+ unlike => {
+ binary_upgrade => 1,
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TABLE test_fourth_table_zero_col' => {
@@ -2722,7 +3002,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TABLE test_fifth_table' => {
@@ -2745,7 +3028,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TABLE test_table_identity' => {
@@ -2771,7 +3057,10 @@
/xms,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TABLE test_table_generated' => {
@@ -2788,7 +3077,10 @@
/xms,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TABLE test_table_generated_child1 (without local columns)' => {
@@ -2805,6 +3097,7 @@
unlike => {
binary_upgrade => 1,
exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
},
},
@@ -2834,6 +3127,7 @@
unlike => {
binary_upgrade => 1,
exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
},
},
@@ -2856,7 +3150,10 @@
/xms,
like =>
{ %full_runs, %dump_test_schema_runs, section_post_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TABLE test_inheritance_parent' => {
@@ -2874,7 +3171,10 @@
/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE TABLE test_inheritance_child' => {
@@ -2896,6 +3196,7 @@
unlike => {
binary_upgrade => 1,
exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
},
},
@@ -2908,7 +3209,10 @@
/xms,
like =>
{ %full_runs, %dump_test_schema_runs, section_post_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE STATISTICS extended_stats_options' => {
@@ -2920,7 +3224,10 @@
/xms,
like =>
{ %full_runs, %dump_test_schema_runs, section_post_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'ALTER STATISTICS extended_stats_options' => {
@@ -2963,7 +3270,10 @@
only_dump_test_table => 1,
section_pre_data => 1,
},
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE INDEX ON ONLY measurement' => {
@@ -2991,6 +3301,8 @@
schema_only => 1,
section_post_data => 1,
test_schema_plus_blobs => 1,
+ only_dump_measurement => 1,
+ exclude_measurement_data => 1,
},
unlike => {
exclude_dump_test_schema => 1,
@@ -2999,6 +3311,7 @@
pg_dumpall_globals_clean => 1,
role => 1,
section_pre_data => 1,
+ exclude_measurement => 1,
},
},
@@ -3011,9 +3324,16 @@
\QALTER TABLE ONLY dump_test.measurement\E \n^\s+
\QADD CONSTRAINT measurement_pkey PRIMARY KEY (city_id, logdate);\E
/xm,
- like =>
- { %full_runs, %dump_test_schema_runs, section_post_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ like => {
+ %full_runs,
+ %dump_test_schema_runs,
+ section_post_data => 1,
+ only_dump_measurement => 1,
+ },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ exclude_measurement => 1,
+ },
},
'CREATE INDEX ... ON measurement_y2006_m2' => {
@@ -3024,6 +3344,10 @@
%full_runs,
role => 1,
section_post_data => 1,
+ only_dump_measurement => 1,
+ },
+ unlike => {
+ exclude_measurement => 1,
},
},
@@ -3035,6 +3359,11 @@
%full_runs,
role => 1,
section_post_data => 1,
+ only_dump_measurement => 1,
+ exclude_measurement_data => 1,
+ },
+ unlike => {
+ exclude_measurement => 1,
},
},
@@ -3061,6 +3390,8 @@
role => 1,
schema_only => 1,
section_post_data => 1,
+ only_dump_measurement => 1,
+ exclude_measurement_data => 1,
},
unlike => {
only_dump_test_schema => 1,
@@ -3069,6 +3400,7 @@
pg_dumpall_globals_clean => 1,
section_pre_data => 1,
test_schema_plus_blobs => 1,
+ exclude_measurement => 1,
},
},
@@ -3084,7 +3416,10 @@
\n\s+\QWITH LOCAL CHECK OPTION;\E/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'ALTER VIEW test_view SET DEFAULT' => {
@@ -3095,7 +3430,10 @@
\QALTER TABLE dump_test.test_view ALTER COLUMN col1 SET DEFAULT 1;\E/xm,
like =>
{ %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
- unlike => { exclude_dump_test_schema => 1, },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
# FIXME
@@ -3270,6 +3608,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_privs => 1,
+ only_dump_measurement => 1,
},
},
@@ -3285,6 +3624,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_privs => 1,
+ only_dump_measurement => 1,
},
},
@@ -3300,6 +3640,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_privs => 1,
+ only_dump_measurement => 1,
},
},
@@ -3315,6 +3656,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_privs => 1,
+ only_dump_measurement => 1,
},
},
@@ -3344,6 +3686,7 @@
exclude_dump_test_schema => 1,
exclude_test_table => 1,
no_privs => 1,
+ only_dump_measurement => 1,
},
},
@@ -3354,11 +3697,16 @@
TO regress_dump_test_role;',
regexp =>
qr/^\QGRANT SELECT ON TABLE dump_test.measurement TO regress_dump_test_role;\E/m,
- like =>
- { %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
+ like => {
+ %full_runs,
+ %dump_test_schema_runs,
+ section_pre_data => 1,
+ only_dump_measurement => 1,
+ },
unlike => {
exclude_dump_test_schema => 1,
no_privs => 1,
+ exclude_measurement => 1,
},
},
@@ -3376,8 +3724,12 @@
%full_runs,
role => 1,
section_pre_data => 1,
+ only_dump_measurement => 1,
+ },
+ unlike => {
+ no_privs => 1,
+ exclude_measurement => 1,
},
- unlike => { no_privs => 1, },
},
# Disabled, because GPDB doesn't support large objects
@@ -3421,6 +3773,7 @@
unlike => {
exclude_dump_test_schema => 1,
no_privs => 1,
+ only_dump_measurement => 1,
},
},
@@ -3522,6 +3875,7 @@
binary_upgrade => 1,
exclude_dump_test_schema => 1,
schema_only => 1,
+ only_dump_measurement => 1,
},
},
@@ -3537,6 +3891,7 @@
binary_upgrade => 1,
exclude_dump_test_schema => 1,
schema_only => 1,
+ only_dump_measurement => 1,
},
},
@@ -3608,6 +3963,7 @@
only_dump_test_table => 1,
role => 1,
section_pre_data => 1,
+ only_dump_measurement => 1,
},
unlike => { no_privs => 1, },
},
@@ -3646,7 +4002,10 @@
like => {
%full_runs, %dump_test_schema_runs, section_pre_data => 1,
},
- unlike => { exclude_dump_test_schema => 1 },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
},
'CREATE MATERIALIZED VIEW regress_pg_dump_matview_am' => {
@@ -3666,7 +4025,10 @@
like => {
%full_runs, %dump_test_schema_runs, section_pre_data => 1,
},
- unlike => { exclude_dump_test_schema => 1 },
+ unlike => {
+ exclude_dump_test_schema => 1,
+ only_dump_measurement => 1,
+ },
});
#########################################
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 90c8bb777fa..7423459e690 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -52,7 +52,7 @@ static bool describeOneTSConfig(const char *oid, const char *nspname,
static void printACLColumn(PQExpBuffer buf, const char *colname);
static bool listOneExtensionContents(const char *extname, const char *oid);
-static bool isGPDB(void);
+static bool isMPP(void);
static bool isGPDB4200OrLater(void);
static bool isGPDB5000OrLater(void);
static bool isGPDB6000OrLater(void);
@@ -64,7 +64,7 @@ static bool validateSQLNamePattern(PQExpBuffer buf, const char *pattern,
const char *visibilityrule,
bool *added_clause, int maxparts);
-static bool isGPDB(void)
+static bool isMPP(void)
{
static enum
{
@@ -86,7 +86,7 @@ static bool isGPDB(void)
return false;
ver = PQgetvalue(res, 0, 0);
- if (strstr(ver, "Cloudberry") != NULL)
+ if (strstr(ver, "Cloudberry") != NULL || strstr(ver, "Greenplum") != NULL)
{
PQclear(res);
talking_to_gpdb = gpdb_yes;
@@ -113,7 +113,7 @@ static bool isGPDB4200OrLater(void)
{
bool retValue = false;
- if (isGPDB() == true)
+ if (isMPP() == true)
{
PGresult *result;
@@ -134,7 +134,7 @@ isGPDB4300OrLater(void)
{
bool retValue = false;
- if (isGPDB() == true)
+ if (isMPP() == true)
{
PGresult *result;
@@ -157,7 +157,7 @@ static bool isGPDB5000OrLater(void)
{
bool retValue = false;
- if (isGPDB() == true)
+ if (isMPP() == true)
{
PGresult *res;
@@ -171,8 +171,8 @@ static bool isGPDB5000OrLater(void)
static bool
isGPDB6000OrLater(void)
{
- if (!isGPDB())
- return false; /* Not Cloudberry at all. */
+ if (!isMPP())
+ return false; /* Not GP-based at all. */
/* GPDB 6 is based on PostgreSQL 9.4 */
return pset.sversion >= 90400;
@@ -181,8 +181,8 @@ isGPDB6000OrLater(void)
static bool
isGPDB6000OrBelow(void)
{
- if (!isGPDB())
- return false; /* Not Cloudberry at all. */
+ if (!isMPP())
+ return false; /* Not GP-based at all. */
/* GPDB 6 is based on PostgreSQL 9.4 */
return pset.sversion <= 90400;
@@ -191,8 +191,8 @@ isGPDB6000OrBelow(void)
static bool
isGPDB7000OrLater(void)
{
- if (!isGPDB())
- return false; /* Not Cloudberry at all. */
+ if (!isMPP())
+ return false; /* Not GP-based at all. */
/* GPDB 7 is based on PostgreSQL v12 */
return pset.sversion >= 120000;
@@ -2007,7 +2007,7 @@ describeOneTableDetails(const char *schemaname,
"array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
: "''"),
/* GPDB Only: relstorage */
- (isGPDB() ? "c.relstorage" : "'h'"),
+ (isMPP() ? "c.relstorage" : "'h'"),
oid);
}
else if (pset.sversion >= 90400)
@@ -2027,7 +2027,7 @@ describeOneTableDetails(const char *schemaname,
"array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
: "''"),
/* GPDB Only: relstorage */
- (isGPDB() ? "c.relstorage" : "'h'"),
+ (isMPP() ? "c.relstorage" : "'h'"),
oid);
}
else if (pset.sversion >= 90100)
@@ -2047,7 +2047,7 @@ describeOneTableDetails(const char *schemaname,
"array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
: "''"),
/* GPDB Only: relstorage */
- (isGPDB() ? "c.relstorage" : "'h'"),
+ (isMPP() ? "c.relstorage" : "'h'"),
oid);
}
else if (pset.sversion >= 90000)
@@ -2066,7 +2066,7 @@ describeOneTableDetails(const char *schemaname,
"array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
: "''"),
/* GPDB Only: relstorage */
- (isGPDB() ? "c.relstorage" : "'h'"),
+ (isMPP() ? "c.relstorage" : "'h'"),
oid);
}
else if (pset.sversion >= 80400)
@@ -2084,7 +2084,7 @@ describeOneTableDetails(const char *schemaname,
"array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
: "''"),
/* GPDB Only: relstorage */
- (isGPDB() ? "c.relstorage" : "'h'"),
+ (isMPP() ? "c.relstorage" : "'h'"),
oid);
}
else if (pset.sversion >= 80200)
@@ -2098,7 +2098,7 @@ describeOneTableDetails(const char *schemaname,
(verbose ?
"pg_catalog.array_to_string(reloptions, E', ')" : "''"),
/* GPDB Only: relstorage */
- (isGPDB() ? "relstorage" : "'h'"),
+ (isMPP() ? "relstorage" : "'h'"),
oid);
}
else if (pset.sversion >= 80000)
@@ -2161,7 +2161,7 @@ describeOneTableDetails(const char *schemaname,
tableinfo.isdynamic = strcmp(PQgetvalue(res, 0, 16), "t") == 0;
/* GPDB Only: relstorage */
- if (pset.sversion < 120000 && isGPDB())
+ if (pset.sversion < 120000 && isMPP())
tableinfo.relstorage = *(PQgetvalue(res, 0, PQfnumber(res, "relstorage")));
else
tableinfo.relstorage = 'h';
@@ -3840,7 +3840,7 @@ describeOneTableDetails(const char *schemaname,
* listing them.
*/
tgdef = PQgetvalue(result, i, 1);
- if (isGPDB() && strstr(tgdef, "RI_FKey_") != NULL)
+ if (isMPP() && strstr(tgdef, "RI_FKey_") != NULL)
list_trigger = false;
break;
@@ -5145,7 +5145,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
cols_so_far = 4;
/* Show Storage type for tables */
- if (showTables && isGPDB())
+ if (showTables && isMPP())
{
if (isGPDB7000OrLater())
{
diff --git a/src/fe_utils/string_utils.c b/src/fe_utils/string_utils.c
index ba409e63879..462c5bc8cea 100644
--- a/src/fe_utils/string_utils.c
+++ b/src/fe_utils/string_utils.c
@@ -909,6 +909,69 @@ parsePGArray(const char *atext, char ***itemarray, int *nitems)
}
+/*
+ * Append one element to the text representation of a 1-dimensional Postgres
+ * array.
+ *
+ * The caller must provide the initial '{' and closing '}' of the array.
+ * This function handles all else, including insertion of commas and
+ * quoting of values.
+ *
+ * We assume that typdelim is ','.
+ */
+void
+appendPGArray(PQExpBuffer buffer, const char *value)
+{
+ bool needquote;
+ const char *tmp;
+
+ if (buffer->data[buffer->len - 1] != '{')
+ appendPQExpBufferChar(buffer, ',');
+
+ /* Decide if we need quotes; this should match array_out()'s choices. */
+ if (value[0] == '\0')
+ needquote = true; /* force quotes for empty string */
+ else if (pg_strcasecmp(value, "NULL") == 0)
+ needquote = true; /* force quotes for literal NULL */
+ else
+ needquote = false;
+
+ if (!needquote)
+ {
+ for (tmp = value; *tmp; tmp++)
+ {
+ char ch = *tmp;
+
+ if (ch == '"' || ch == '\\' ||
+ ch == '{' || ch == '}' || ch == ',' ||
+ /* these match array_isspace(): */
+ ch == ' ' || ch == '\t' || ch == '\n' ||
+ ch == '\r' || ch == '\v' || ch == '\f')
+ {
+ needquote = true;
+ break;
+ }
+ }
+ }
+
+ if (needquote)
+ {
+ appendPQExpBufferChar(buffer, '"');
+ for (tmp = value; *tmp; tmp++)
+ {
+ char ch = *tmp;
+
+ if (ch == '"' || ch == '\\')
+ appendPQExpBufferChar(buffer, '\\');
+ appendPQExpBufferChar(buffer, ch);
+ }
+ appendPQExpBufferChar(buffer, '"');
+ }
+ else
+ appendPQExpBufferStr(buffer, value);
+}
+
+
/*
* Format a reloptions array and append it to the given buffer.
*
diff --git a/src/include/fe_utils/string_utils.h b/src/include/fe_utils/string_utils.h
index 3bd6f26dcd4..4a25a959f00 100644
--- a/src/include/fe_utils/string_utils.h
+++ b/src/include/fe_utils/string_utils.h
@@ -52,6 +52,7 @@ extern void appendConnStrVal(PQExpBuffer buf, const char *str);
extern void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname);
extern bool parsePGArray(const char *atext, char ***itemarray, int *nitems);
+extern void appendPGArray(PQExpBuffer buffer, const char *value);
extern bool appendReloptionsArray(PQExpBuffer buffer, const char *reloptions,
const char *prefix, int encoding, bool std_strings);
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index 33c929e9082..c7c534417a2 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -47,6 +47,12 @@ typedef enum
extern PGDLLIMPORT int log_statement;
+/* Flags for restrict_nonsystem_relation_kind value */
+#define RESTRICT_RELKIND_VIEW 0x01
+#define RESTRICT_RELKIND_FOREIGN_TABLE 0x02
+
+extern PGDLLIMPORT int restrict_nonsystem_relation_kind;
+
extern List *pg_parse_query(const char *query_string);
extern List *pg_rewrite_query(Query *query);
extern List *pg_analyze_and_rewrite(RawStmt *parsetree,
@@ -67,6 +73,9 @@ extern List *pg_plan_queries(List *querytrees, const char *query_string,
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
extern void assign_max_stack_depth(int newval, void *extra);
+extern bool check_restrict_nonsystem_relation_kind(char **newval, void **extra,
+ GucSource source);
+extern void assign_restrict_nonsystem_relation_kind(const char *newval, void *extra);
extern void die(SIGNAL_ARGS);
extern void quickdie(SIGNAL_ARGS) pg_attribute_noreturn();
diff --git a/src/include/utils/unsync_guc_name.h b/src/include/utils/unsync_guc_name.h
index cba11770a81..55a81df5bae 100644
--- a/src/include/utils/unsync_guc_name.h
+++ b/src/include/utils/unsync_guc_name.h
@@ -537,6 +537,7 @@
"resource_select_only",
"restart_after_crash",
"restore_command",
+ "restrict_nonsystem_relation_kind",
"role",
"runaway_detector_activation_percent",
"segment_size",
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
index ac88c92f398..2a1fdca3562 100644
--- a/src/test/regress/expected/create_view.out
+++ b/src/test/regress/expected/create_view.out
@@ -1999,6 +1999,44 @@ select pg_get_viewdef('tt26v', true);
FROM ( VALUES (1,2,3)) v(x, y, z);
(1 row)
+-- Test that changing the relkind of a relcache entry doesn't cause
+-- trouble. Prior instances of where it did:
+-- CALDaNm2yXz+zOtv7y5zBd5WKT8O0Ld3YxikuU3dcyCvxF7gypA@mail.gmail.com
+-- CALDaNm3oZA-8Wbps2Jd1g5_Gjrr-x3YWrJPek-mF5Asrrvz2Dg@mail.gmail.com
+CREATE TABLE tt26(c int);
+BEGIN;
+CREATE TABLE tt27(c int);
+SAVEPOINT q;
+CREATE RULE "_RETURN" AS ON SELECT TO tt27 DO INSTEAD SELECT * FROM tt26;
+SELECT * FROM tt27;
+ c
+---
+(0 rows)
+
+ROLLBACK TO q;
+CREATE RULE "_RETURN" AS ON SELECT TO tt27 DO INSTEAD SELECT * FROM tt26;
+ROLLBACK;
+BEGIN;
+CREATE TABLE tt28(c int);
+CREATE RULE "_RETURN" AS ON SELECT TO tt28 DO INSTEAD SELECT * FROM tt26;
+CREATE RULE "_RETURN" AS ON SELECT TO tt28 DO INSTEAD SELECT * FROM tt26;
+ERROR: "tt28" is already a view
+ROLLBACK;
+-- test restriction on non-system view expansion.
+create table tt27v_tbl (a int);
+create view tt27v as select a from tt27v_tbl;
+set restrict_nonsystem_relation_kind to 'view';
+select a from tt27v where a > 0; -- Error
+ERROR: access to non-system view "tt27v" is restricted
+insert into tt27v values (1); -- Error
+ERROR: access to non-system view "tt27v" is restricted
+select viewname from pg_views where viewname = 'tt27v'; -- Ok to access a system view.
+ viewname
+----------
+ tt27v
+(1 row)
+
+reset restrict_nonsystem_relation_kind;
-- test display negative operator of const-folder expression
create table tdis(a int, b int, c int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Greenplum Database data distribution key for this table.
@@ -2046,7 +2084,7 @@ drop cascades to view aliased_view_2
drop cascades to view aliased_view_3
drop cascades to view aliased_view_4
DROP SCHEMA testviewschm2 CASCADE;
-NOTICE: drop cascades to 76 other objects
+NOTICE: drop cascades to 79 other objects
DETAIL: drop cascades to table t1
drop cascades to view temporal1
drop cascades to view temporal2
@@ -2121,5 +2159,8 @@ drop cascades to view tt23v
drop cascades to view tt24v
drop cascades to view tt25v
drop cascades to view tt26v
+drop cascades to table tt26
+drop cascades to table tt27v_tbl
+drop cascades to view tt27v
drop cascades to table tdis
drop cascades to view tdis_v1
diff --git a/src/test/regress/expected/create_view_optimizer.out b/src/test/regress/expected/create_view_optimizer.out
index ece2034d92d..c17ae313cac 100755
--- a/src/test/regress/expected/create_view_optimizer.out
+++ b/src/test/regress/expected/create_view_optimizer.out
@@ -1997,6 +1997,44 @@ select pg_get_viewdef('tt26v', true);
FROM ( VALUES (1,2,3)) v(x, y, z);
(1 row)
+-- Test that changing the relkind of a relcache entry doesn't cause
+-- trouble. Prior instances of where it did:
+-- CALDaNm2yXz+zOtv7y5zBd5WKT8O0Ld3YxikuU3dcyCvxF7gypA@mail.gmail.com
+-- CALDaNm3oZA-8Wbps2Jd1g5_Gjrr-x3YWrJPek-mF5Asrrvz2Dg@mail.gmail.com
+CREATE TABLE tt26(c int);
+BEGIN;
+CREATE TABLE tt27(c int);
+SAVEPOINT q;
+CREATE RULE "_RETURN" AS ON SELECT TO tt27 DO INSTEAD SELECT * FROM tt26;
+SELECT * FROM tt27;
+ c
+---
+(0 rows)
+
+ROLLBACK TO q;
+CREATE RULE "_RETURN" AS ON SELECT TO tt27 DO INSTEAD SELECT * FROM tt26;
+ROLLBACK;
+BEGIN;
+CREATE TABLE tt28(c int);
+CREATE RULE "_RETURN" AS ON SELECT TO tt28 DO INSTEAD SELECT * FROM tt26;
+CREATE RULE "_RETURN" AS ON SELECT TO tt28 DO INSTEAD SELECT * FROM tt26;
+ERROR: "tt28" is already a view
+ROLLBACK;
+-- test restriction on non-system view expansion.
+create table tt27v_tbl (a int);
+create view tt27v as select a from tt27v_tbl;
+set restrict_nonsystem_relation_kind to 'view';
+select a from tt27v where a > 0; -- Error
+ERROR: access to non-system view "tt27v" is restricted
+insert into tt27v values (1); -- Error
+ERROR: access to non-system view "tt27v" is restricted
+select viewname from pg_views where viewname = 'tt27v'; -- Ok to access a system view.
+ viewname
+----------
+ tt27v
+(1 row)
+
+reset restrict_nonsystem_relation_kind;
-- test display negative operator of const-folder expression
create table tdis(a int, b int, c int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
@@ -2044,7 +2082,7 @@ drop cascades to view aliased_view_2
drop cascades to view aliased_view_3
drop cascades to view aliased_view_4
DROP SCHEMA testviewschm2 CASCADE;
-NOTICE: drop cascades to 76 other objects
+NOTICE: drop cascades to 79 other objects
DETAIL: drop cascades to table t1
drop cascades to view temporal1
drop cascades to view temporal2
@@ -2119,5 +2157,8 @@ drop cascades to view tt23v
drop cascades to view tt24v
drop cascades to view tt25v
drop cascades to view tt26v
+drop cascades to table tt26
+drop cascades to table tt27v_tbl
+drop cascades to view tt27v
drop cascades to table tdis
drop cascades to view tdis_v1
diff --git a/src/test/regress/sql/create_view.sql b/src/test/regress/sql/create_view.sql
index f35364b8a23..4605fdb71b1 100644
--- a/src/test/regress/sql/create_view.sql
+++ b/src/test/regress/sql/create_view.sql
@@ -693,6 +693,38 @@ select x + y + z as c1,
from (values(1,2,3)) v(x,y,z);
select pg_get_viewdef('tt26v', true);
+
+-- Test that changing the relkind of a relcache entry doesn't cause
+-- trouble. Prior instances of where it did:
+-- CALDaNm2yXz+zOtv7y5zBd5WKT8O0Ld3YxikuU3dcyCvxF7gypA@mail.gmail.com
+-- CALDaNm3oZA-8Wbps2Jd1g5_Gjrr-x3YWrJPek-mF5Asrrvz2Dg@mail.gmail.com
+CREATE TABLE tt26(c int);
+
+BEGIN;
+CREATE TABLE tt27(c int);
+SAVEPOINT q;
+CREATE RULE "_RETURN" AS ON SELECT TO tt27 DO INSTEAD SELECT * FROM tt26;
+SELECT * FROM tt27;
+ROLLBACK TO q;
+CREATE RULE "_RETURN" AS ON SELECT TO tt27 DO INSTEAD SELECT * FROM tt26;
+ROLLBACK;
+
+BEGIN;
+CREATE TABLE tt28(c int);
+CREATE RULE "_RETURN" AS ON SELECT TO tt28 DO INSTEAD SELECT * FROM tt26;
+CREATE RULE "_RETURN" AS ON SELECT TO tt28 DO INSTEAD SELECT * FROM tt26;
+ROLLBACK;
+
+
+-- test restriction on non-system view expansion.
+create table tt27v_tbl (a int);
+create view tt27v as select a from tt27v_tbl;
+set restrict_nonsystem_relation_kind to 'view';
+select a from tt27v where a > 0; -- Error
+insert into tt27v values (1); -- Error
+select viewname from pg_views where viewname = 'tt27v'; -- Ok to access a system view.
+reset restrict_nonsystem_relation_kind;
+
-- test display negative operator of const-folder expression
create table tdis(a int, b int, c int);
create view tdis_v1 as select a,b,c, -1::int from tdis group by 1,2,3,4;