diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 94aee0b746e..a3c5ff418ff 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -77,15 +77,17 @@ #define PRETTYINDENT_LIMIT 40 /* wrap limit */ /* Pretty flags */ -#define PRETTYFLAG_PAREN 1 -#define PRETTYFLAG_INDENT 2 +#define PRETTYFLAG_PAREN 0x0001 +#define PRETTYFLAG_INDENT 0x0002 +#define PRETTYFLAG_SCHEMA 0x0004 /* Default line length for pretty-print wrapping: 0 means wrap always */ #define WRAP_COLUMN_DEFAULT 0 -/* macro to test if pretty action needed */ +/* macros to test if pretty action needed */ #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN) #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT) +#define PRETTY_SCHEMA(context) ((context)->prettyFlags & PRETTYFLAG_SCHEMA) /* ---------- @@ -458,7 +460,8 @@ pg_get_ruledef_ext(PG_FUNCTION_ARGS) bool pretty = PG_GETARG_BOOL(1); int prettyFlags; - prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT; + prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; + PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, prettyFlags))); } @@ -557,7 +560,8 @@ pg_get_viewdef_ext(PG_FUNCTION_ARGS) bool pretty = PG_GETARG_BOOL(1); int prettyFlags; - prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT; + prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; + PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT))); } @@ -570,7 +574,8 @@ pg_get_viewdef_wrap(PG_FUNCTION_ARGS) int prettyFlags; /* calling this implies we want pretty printing */ - prettyFlags = PRETTYFLAG_PAREN | PRETTYFLAG_INDENT; + prettyFlags = PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA; + PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags, wrap))); } @@ -603,7 +608,7 @@ pg_get_viewdef_name_ext(PG_FUNCTION_ARGS) RangeVar *viewrel; Oid viewoid; - prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT; + prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; /* Look up view name. Can't lock it - we might not have privileges. */ viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname)); @@ -807,8 +812,15 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty) appendStringInfoString(&buf, " TRUNCATE"); findx++; } + + /* + * In non-pretty mode, always schema-qualify the target table name for + * safety. In pretty mode, schema-qualify only if not visible. + */ appendStringInfo(&buf, " ON %s ", - generate_relation_name(trigrec->tgrelid, NIL)); + pretty ? + generate_relation_name(trigrec->tgrelid, NIL) : + generate_qualified_relation_name(trigrec->tgrelid)); if (OidIsValid(trigrec->tgconstraint)) { @@ -881,7 +893,7 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty) context.windowClause = NIL; context.windowTList = NIL; context.varprefix = true; - context.prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT; + context.prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; context.wrapColumn = WRAP_COLUMN_DEFAULT; context.indentLevel = PRETTYINDENT_STD; @@ -961,7 +973,8 @@ pg_get_indexdef_ext(PG_FUNCTION_ARGS) bool pretty = PG_GETARG_BOOL(2); int prettyFlags; - prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT; + prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; + PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno, NULL, colno != 0, @@ -986,7 +999,8 @@ pg_get_indexdef_columns(Oid indexrelid, bool pretty) { int prettyFlags; - prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT; + prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; + return pg_get_indexdef_worker(indexrelid, 0, NULL, true, false, prettyFlags); } @@ -1107,7 +1121,9 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (", idxrec->indisunique ? "UNIQUE " : "", quote_identifier(NameStr(idxrelrec->relname)), - generate_relation_name(indrelid, NIL), + (prettyFlags & PRETTYFLAG_SCHEMA) ? + generate_relation_name(indrelid, NIL) : + generate_qualified_relation_name(indrelid), quote_identifier(NameStr(amrec->amname))); else /* currently, must be EXCLUDE constraint */ appendStringInfo(&buf, "EXCLUDE USING %s (", @@ -1299,7 +1315,8 @@ pg_get_constraintdef_ext(PG_FUNCTION_ARGS) bool pretty = PG_GETARG_BOOL(1); int prettyFlags; - prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT; + prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; + PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId, false, prettyFlags))); @@ -1728,7 +1745,7 @@ pg_get_expr_ext(PG_FUNCTION_ARGS) int prettyFlags; char *relname; - prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT; + prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; if (OidIsValid(relid)) { @@ -4113,7 +4130,10 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, } /* The relation the rule is fired on */ - appendStringInfo(buf, " TO %s", generate_relation_name(ev_class, NIL)); + appendStringInfo(buf, " TO %s", + (prettyFlags & PRETTYFLAG_SCHEMA) ? + generate_relation_name(ev_class, NIL) : + generate_qualified_relation_name(ev_class)); /* If the rule has an event qualification, add it */ if (ev_qual == NULL) diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index 1f883ed593b..fdf9d47b644 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -718,6 +718,7 @@ parsePGArray(const char *atext, char ***itemarray, int *nitems) * * name: the object name, in the form to use in the commands (already quoted) * subname: the sub-object name, if any (already quoted); NULL if none + * nspname: the namespace the object is in (NULL if none); not pre-quoted * type: the object type (as seen in GRANT command: must be one of * TABLE, SEQUENCE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, TABLESPACE, * FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT) @@ -737,7 +738,7 @@ parsePGArray(const char *atext, char ***itemarray, int *nitems) * since this routine uses fmtId() internally. */ bool -buildACLCommands(const char *name, const char *subname, +buildACLCommands(const char *name, const char *subname, const char *nspname, const char *type, const char *acls, const char *owner, const char *prefix, int remoteVersion, PQExpBuffer sql) @@ -791,7 +792,10 @@ buildACLCommands(const char *name, const char *subname, appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix); if (subname) appendPQExpBuffer(firstsql, "(%s)", subname); - appendPQExpBuffer(firstsql, " ON %s %s FROM PUBLIC;\n", type, name); + appendPQExpBuffer(firstsql, " ON %s ", type); + if (nspname && *nspname) + appendPQExpBuffer(firstsql, "%s.", fmtId(nspname)); + appendPQExpBuffer(firstsql, "%s FROM PUBLIC;\n", name); /* * We still need some hacking though to cover the case where new default @@ -839,18 +843,33 @@ buildACLCommands(const char *name, const char *subname, appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix); if (subname) appendPQExpBuffer(firstsql, "(%s)", subname); - appendPQExpBuffer(firstsql, " ON %s %s FROM %s;\n", - type, name, fmtId(grantee->data)); + 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 %s TO %s;\n", - prefix, privs->data, type, name, - fmtId(grantee->data)); + "%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 %s TO %s WITH GRANT OPTION;\n", - prefix, privswgo->data, type, name, - fmtId(grantee->data)); + "%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 @@ -865,8 +884,11 @@ buildACLCommands(const char *name, const char *subname, if (privs->len > 0) { - appendPQExpBuffer(secondsql, "%sGRANT %s ON %s %s TO ", - prefix, privs->data, type, name); + appendPQExpBuffer(secondsql, "%sGRANT %s ON %s ", + prefix, privs->data, type); + if (nspname && *nspname) + appendPQExpBuffer(secondsql, "%s.", fmtId(nspname)); + appendPQExpBuffer(secondsql, "%s TO ", name); if (grantee->len == 0) appendPQExpBufferStr(secondsql, "PUBLIC;\n"); else if (strncmp(grantee->data, "group ", @@ -878,8 +900,11 @@ buildACLCommands(const char *name, const char *subname, } if (privswgo->len > 0) { - appendPQExpBuffer(secondsql, "%sGRANT %s ON %s %s TO ", - prefix, privswgo->data, type, name); + appendPQExpBuffer(secondsql, "%sGRANT %s ON %s ", + prefix, privswgo->data, type); + if (nspname && *nspname) + appendPQExpBuffer(secondsql, "%s.", fmtId(nspname)); + appendPQExpBuffer(secondsql, "%s TO ", name); if (grantee->len == 0) appendPQExpBufferStr(secondsql, "PUBLIC"); else if (strncmp(grantee->data, "group ", @@ -906,8 +931,11 @@ buildACLCommands(const char *name, const char *subname, appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix); if (subname) appendPQExpBuffer(firstsql, "(%s)", subname); - appendPQExpBuffer(firstsql, " ON %s %s FROM %s;\n", - type, name, fmtId(owner)); + appendPQExpBuffer(firstsql, " ON %s ", type); + if (nspname && *nspname) + appendPQExpBuffer(firstsql, "%s.", fmtId(nspname)); + appendPQExpBuffer(firstsql, "%s FROM %s;\n", + name, fmtId(owner)); } destroyPQExpBuffer(grantee); @@ -958,7 +986,7 @@ buildDefaultACLCommands(const char *type, const char *nspname, if (nspname) appendPQExpBuffer(prefix, "IN SCHEMA %s ", fmtId(nspname)); - result = buildACLCommands("", NULL, + result = buildACLCommands("", NULL, NULL, type, acls, owner, prefix->data, remoteVersion, sql); @@ -1412,26 +1440,32 @@ processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, * buildShSecLabelQuery * * Build a query to retrieve security labels for a shared object. + * The object is identified by its OID plus the name of the catalog + * it can be found in (e.g., "pg_database" for database names). + * The query is appended to "sql". (We don't execute it here so as to + * keep this file free of assumptions about how to deal with SQL errors.) */ void -buildShSecLabelQuery(PGconn *conn, const char *catalog_name, uint32 objectId, +buildShSecLabelQuery(PGconn *conn, const char *catalog_name, Oid objectId, PQExpBuffer sql) { appendPQExpBuffer(sql, "SELECT provider, label FROM pg_catalog.pg_shseclabel " - "WHERE classoid = '%s'::pg_catalog.regclass AND " - "objoid = %u", catalog_name, objectId); + "WHERE classoid = 'pg_catalog.%s'::pg_catalog.regclass " + "AND objoid = '%u'", catalog_name, objectId); } /* * emitShSecLabels * - * Format security label data retrieved by the query generated in - * buildShSecLabelQuery. + * Construct SECURITY LABEL commands using the data retrieved by the query + * generated by buildShSecLabelQuery, and append them to "buffer". + * Here, the target object is identified by its type name (e.g. "DATABASE") + * and its name (not pre-quoted). */ void emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer, - const char *target, const char *objname) + const char *objtype, const char *objname) { int i; @@ -1443,7 +1477,7 @@ emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer, /* must use fmtId result before calling it again */ appendPQExpBuffer(buffer, "SECURITY LABEL FOR %s ON %s", - fmtId(provider), target); + fmtId(provider), objtype); appendPQExpBuffer(buffer, " %s IS ", fmtId(objname)); diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h index f8ecd6008ae..24dc404ed1f 100644 --- a/src/bin/pg_dump/dumputils.h +++ b/src/bin/pg_dump/dumputils.h @@ -53,7 +53,7 @@ extern void appendShellString(PQExpBuffer buf, const char *str); 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 bool buildACLCommands(const char *name, const char *subname, +extern bool buildACLCommands(const char *name, const char *subname, const char *nspname, const char *type, const char *acls, const char *owner, const char *prefix, int remoteVersion, PQExpBuffer sql); @@ -67,9 +67,9 @@ extern bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule); extern void buildShSecLabelQuery(PGconn *conn, const char *catalog_name, - uint32 objectId, PQExpBuffer sql); + Oid objectId, PQExpBuffer sql); extern void emitShSecLabels(PGconn *conn, PGresult *res, - PQExpBuffer buffer, const char *target, const char *objname); + PQExpBuffer buffer, const char *objtype, const char *objname); extern void set_dump_section(const char *arg, int *dumpSections); extern void simple_string_list_append(SimpleStringList *list, const char *val); diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index 643b4fb3a7a..c090ca0c9ef 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -89,6 +89,9 @@ struct Archive /* info needed for string escaping */ int encoding; /* libpq code for client_encoding */ bool std_strings; /* standard_conforming_strings */ + + /* other important stuff */ + char *searchpath; /* search_path to set during restore */ char *use_role; /* Issue SET ROLE to this */ /* error handling */ diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 27632326fd0..afde17f0d92 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -67,6 +67,7 @@ static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName); static void _selectTablespace(ArchiveHandle *AH, const char *tablespace); static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te); static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te); +static void processSearchPathEntry(ArchiveHandle *AH, TocEntry *te); static teReqs _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt); static RestorePass _tocEntryRestorePass(TocEntry *te); static bool _tocEntryIsACL(TocEntry *te); @@ -806,7 +807,9 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, ahprintf(AH, "TRUNCATE TABLE %s%s;\n\n", (PQserverVersion(AH->connection) >= 80400 ? "ONLY " : ""), - fmtId(te->tag)); + fmtQualifiedId(PQserverVersion(AH->connection), + te->namespace, + te->tag)); } /* @@ -891,10 +894,10 @@ _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *rop /* * Disable them. */ - _selectOutputSchema(AH, te->namespace); - ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n", - fmtId(te->tag)); + fmtQualifiedId(PQserverVersion(AH->connection), + te->namespace, + te->tag)); } static void @@ -917,10 +920,10 @@ _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt /* * Enable them. */ - _selectOutputSchema(AH, te->namespace); - ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n", - fmtId(te->tag)); + fmtQualifiedId(PQserverVersion(AH->connection), + te->namespace, + te->tag)); } /* @@ -2573,6 +2576,8 @@ ReadToc(ArchiveHandle *AH) processEncodingEntry(AH, te); else if (strcmp(te->desc, "STDSTRINGS") == 0) processStdStringsEntry(AH, te); + else if (strcmp(te->desc, "SEARCHPATH") == 0) + processSearchPathEntry(AH, te); } } @@ -2620,14 +2625,25 @@ processStdStringsEntry(ArchiveHandle *AH, TocEntry *te) te->defn); } +static void +processSearchPathEntry(ArchiveHandle *AH, TocEntry *te) +{ + /* + * te->defn should contain a command to set search_path. We just copy it + * verbatim for use later. + */ + AH->public.searchpath = pg_strdup(te->defn); +} + static teReqs _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt) { teReqs res = REQ_SCHEMA | REQ_DATA; - /* ENCODING and STDSTRINGS items are treated specially */ + /* These items are treated specially */ if (strcmp(te->desc, "ENCODING") == 0 || - strcmp(te->desc, "STDSTRINGS") == 0) + strcmp(te->desc, "STDSTRINGS") == 0 || + strcmp(te->desc, "SEARCHPATH") == 0) return REQ_SPECIAL; /* If it's an ACL, maybe ignore it */ @@ -2831,6 +2847,10 @@ _doSetFixedOutputState(ArchiveHandle *AH) if (AH->ropt && AH->ropt->use_role) ahprintf(AH, "SET ROLE %s;\n", fmtId(AH->ropt->use_role)); + /* Select the dump-time search_path */ + if (AH->public.searchpath) + ahprintf(AH, "%s", AH->public.searchpath); + /* Make sure function checking is disabled */ ahprintf(AH, "SET check_function_bodies = false;\n"); @@ -3027,6 +3047,15 @@ _selectOutputSchema(ArchiveHandle *AH, const char *schemaName) { PQExpBuffer qry; + /* + * If there was a SEARCHPATH TOC entry, we're supposed to just stay with + * that search_path rather than switching to entry-specific paths. + * Otherwise, it's an old archive that will not restore correctly unless + * we set the search_path as it's expecting. + */ + if (AH->public.searchpath) + return; + if (!schemaName || *schemaName == '\0' || (AH->currSchema && strcmp(AH->currSchema, schemaName) == 0)) return; /* no need to do anything */ @@ -3155,8 +3184,10 @@ _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH) strcmp(type, "SERVER") == 0 || strcmp(type, "USER MAPPING") == 0) { - /* We already know that search_path was set properly */ - appendPQExpBuffer(buf, "%s %s", type, fmtId(te->tag)); + appendPQExpBuffer(buf, "%s ", type); + if (te->namespace && *te->namespace) + appendPQExpBuffer(buf, "%s.", fmtId(te->namespace)); + appendPQExpBufferStr(buf, fmtId(te->tag)); return; } diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index dc61d610fc6..ff93e79ff2e 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -66,7 +66,7 @@ typedef z_stream *z_streamp; /* Current archive version number (the format we can output) */ #define K_VERS_MAJOR 1 -#define K_VERS_MINOR 12 +#define K_VERS_MINOR 13 #define K_VERS_REV 0 /* Data block types */ @@ -92,9 +92,11 @@ typedef z_stream *z_streamp; * indicator */ #define K_VERS_1_12 (( (1 * 256 + 12) * 256 + 0) * 256 + 0) /* add separate BLOB * entries */ +#define K_VERS_1_13 (( (1 * 256 + 13) * 256 + 0) * 256 + 0) /* change search_path + * behavior */ /* Newest format we can read */ -#define K_VERS_MAX (( (1 * 256 + 12) * 256 + 255) * 256 + 0) +#define K_VERS_MAX (( (1 * 256 + 13) * 256 + 255) * 256 + 0) /* Flags to indicate disposition of offsets stored in files */ diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 6f8ef709215..7fd3ff300b8 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -142,6 +142,15 @@ static int no_unlogged_table_data = 0; static int serializable_deferrable = 0; +/* + * Macro for producing quoted, schema-qualified name of a dumpable object. + * Note implicit dependence on "fout"; we should get rid of that argument. + */ +#define fmtQualifiedDumpable(obj) \ + fmtQualifiedId(fout->remoteVersion, \ + (obj)->dobj.namespace->dobj.name, \ + (obj)->dobj.name) + static void help(const char *progname); static void setup_connection(Archive *AH, const char *dumpencoding, char *use_role); @@ -156,13 +165,13 @@ static NamespaceInfo *findNamespace(Archive *fout, Oid nsoid, Oid objoid); static void dumpTableData(Archive *fout, TableDataInfo *tdinfo); static void refreshMatViewData(Archive *fout, TableDataInfo *tdinfo); static void guessConstraintInheritance(TableInfo *tblinfo, int numTables); -static void dumpComment(Archive *fout, const char *target, +static void dumpComment(Archive *fout, const char *type, const char *name, const char *namespace, const char *owner, CatalogId catalogId, int subid, DumpId dumpId); static int findComments(Archive *fout, Oid classoid, Oid objoid, CommentItem **items); static int collectComments(Archive *fout, CommentItem **items); -static void dumpSecLabel(Archive *fout, const char *target, +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, @@ -213,7 +222,7 @@ static void dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo); static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId, const char *type, const char *name, const char *subname, - const char *tag, const char *nspname, const char *owner, + const char *nspname, const char *owner, const char *acls); static void getDependencies(Archive *fout); @@ -241,11 +250,10 @@ static char *format_function_signature(Archive *fout, FuncInfo *finfo, bool honor_quotes); static char *convertRegProcReference(Archive *fout, const char *proc); -static char *convertOperatorReference(Archive *fout, const char *opr); +static char *getFormattedOperatorName(Archive *fout, const char *oproid); static const char *convertTSFunction(Archive *fout, Oid funcOid); static Oid findLastBuiltinOid_V71(Archive *fout, const char *); static Oid findLastBuiltinOid_V70(Archive *fout); -static void selectSourceSchema(Archive *fout, const char *schemaName); static char *getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts); static char *myFormatType(const char *typname, int32 typmod); static void getBlobs(Archive *fout); @@ -254,6 +262,7 @@ static int dumpBlobs(Archive *fout, void *arg); static void dumpDatabase(Archive *AH); static void dumpEncoding(Archive *AH); static void dumpStdStrings(Archive *AH); +static void dumpSearchPath(Archive *AH); static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout, PQExpBuffer upgrade_buffer, Oid pg_type_oid); static bool binary_upgrade_set_type_oids_by_rel_oid(Archive *fout, @@ -263,7 +272,9 @@ static void binary_upgrade_set_pg_class_oids(Archive *fout, Oid pg_class_oid, bool is_index); static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer, DumpableObject *dobj, - const char *objlabel); + const char *objtype, + const char *objname, + const char *objnamespace); static const char *getAttrName(int attrnum, TableInfo *tblInfo); static const char *fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer); static bool nonemptyReloptions(const char *reloptions); @@ -832,9 +843,10 @@ main(int argc, char **argv) * order. */ - /* First the special ENCODING and STDSTRINGS entries. */ + /* First the special ENCODING, STDSTRINGS, and SEARCHPATH entries. */ dumpEncoding(fout); dumpStdStrings(fout); + dumpSearchPath(fout); /* The database item is always next, unless we don't want it at all */ if (include_everything && !dataOnly) @@ -1545,14 +1557,6 @@ dumpTableData_copy(Archive *fout, void *dcontext) if (g_verbose) write_msg(NULL, "dumping contents of table %s\n", classname); - /* - * Make sure we are in proper schema. We will qualify the table name - * below anyway (in case its name conflicts with a pg_catalog table); but - * this ensures reproducible results in case the table contains regproc, - * regclass, etc columns. - */ - selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name); - /* * If possible, specify the column list explicitly so that we have no * possibility of retrieving data in the wrong column order. (The default @@ -1567,9 +1571,7 @@ dumpTableData_copy(Archive *fout, void *dcontext) if (oids && hasoids) { appendPQExpBuffer(q, "COPY %s %s WITH OIDS TO stdout;", - fmtQualifiedId(fout->remoteVersion, - tbinfo->dobj.namespace->dobj.name, - classname), + fmtQualifiedDumpable(tbinfo), column_list); } else if (tdinfo->filtercond) @@ -1585,17 +1587,13 @@ dumpTableData_copy(Archive *fout, void *dcontext) else appendPQExpBufferStr(q, "* "); appendPQExpBuffer(q, "FROM %s %s) TO stdout;", - fmtQualifiedId(fout->remoteVersion, - tbinfo->dobj.namespace->dobj.name, - classname), + fmtQualifiedDumpable(tbinfo), tdinfo->filtercond); } else { appendPQExpBuffer(q, "COPY %s %s TO stdout;", - fmtQualifiedId(fout->remoteVersion, - tbinfo->dobj.namespace->dobj.name, - classname), + fmtQualifiedDumpable(tbinfo), column_list); } res = ExecuteSqlQuery(fout, q->data, PGRES_COPY_OUT); @@ -1705,7 +1703,6 @@ dumpTableData_insert(Archive *fout, void *dcontext) { TableDataInfo *tdinfo = (TableDataInfo *) dcontext; TableInfo *tbinfo = tdinfo->tdtable; - const char *classname = tbinfo->dobj.name; PQExpBuffer q = createPQExpBuffer(); PQExpBuffer insertStmt = NULL; PGresult *res; @@ -1713,29 +1710,17 @@ dumpTableData_insert(Archive *fout, void *dcontext) int nfields; int field; - /* - * Make sure we are in proper schema. We will qualify the table name - * below anyway (in case its name conflicts with a pg_catalog table); but - * this ensures reproducible results in case the table contains regproc, - * regclass, etc columns. - */ - selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name); - if (fout->remoteVersion >= 70100) { appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR " "SELECT * FROM ONLY %s", - fmtQualifiedId(fout->remoteVersion, - tbinfo->dobj.namespace->dobj.name, - classname)); + fmtQualifiedDumpable(tbinfo)); } else { appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR " "SELECT * FROM %s", - fmtQualifiedId(fout->remoteVersion, - tbinfo->dobj.namespace->dobj.name, - classname)); + fmtQualifiedDumpable(tbinfo)); } if (tdinfo->filtercond) appendPQExpBuffer(q, " %s", tdinfo->filtercond); @@ -1760,7 +1745,7 @@ dumpTableData_insert(Archive *fout, void *dcontext) { insertStmt = createPQExpBuffer(); appendPQExpBuffer(insertStmt, "INSERT INTO %s ", - fmtId(classname)); + fmtQualifiedDumpable(tbinfo)); /* corner case for zero-column table */ if (nfields == 0) @@ -1901,7 +1886,7 @@ dumpTableData(Archive *fout, TableDataInfo *tdinfo) dumpFn = dumpTableData_copy; /* must use 2 steps here 'cause fmtId is nonreentrant */ appendPQExpBuffer(copyBuf, "COPY %s ", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); appendPQExpBuffer(copyBuf, "%s %sFROM stdin;\n", fmtCopyColumnList(tbinfo, clistBuf), (tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : ""); @@ -1951,7 +1936,7 @@ refreshMatViewData(Archive *fout, TableDataInfo *tdinfo) q = createPQExpBuffer(); appendPQExpBuffer(q, "REFRESH MATERIALIZED VIEW %s;\n", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); ArchiveEntry(fout, tdinfo->dobj.catId, /* catalog ID */ @@ -2072,9 +2057,6 @@ buildMatViewRefreshDependencies(Archive *fout) if (fout->remoteVersion < 90300) return; - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - query = createPQExpBuffer(); appendPQExpBufferStr(query, "WITH RECURSIVE w AS " @@ -2315,16 +2297,16 @@ dumpDatabase(Archive *fout) *collate, *ctype, *tablespace; - uint32 frozenxid, minmxid; + uint32 frozenxid, + minmxid; + char *qdatname; datname = PQdb(conn); + qdatname = pg_strdup(fmtId(datname)); if (g_verbose) write_msg(NULL, "saving database definition\n"); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - /* Get the database owner and parameters from pg_database */ if (fout->remoteVersion >= 90300) { @@ -2432,7 +2414,7 @@ dumpDatabase(Archive *fout) tablespace = PQgetvalue(res, 0, i_tablespace); appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0", - fmtId(datname)); + qdatname); if (strlen(encoding) > 0) { appendPQExpBufferStr(creaQry, " ENCODING = "); @@ -2462,11 +2444,10 @@ dumpDatabase(Archive *fout) frozenxid, minmxid); appendStringLiteralAH(creaQry, datname, fout); appendPQExpBufferStr(creaQry, ";\n"); - } appendPQExpBuffer(delQry, "DROP DATABASE %s;\n", - fmtId(datname)); + qdatname); dbDumpId = createDumpId(); @@ -2579,8 +2560,8 @@ dumpDatabase(Archive *fout) destroyPQExpBuffer(loOutQry); } - /* Compute correct tag for comments etc */ - appendPQExpBuffer(labelq, "DATABASE %s", fmtId(datname)); + /* Compute correct tag for archive entry */ + appendPQExpBuffer(labelq, "DATABASE %s", qdatname); /* Dump DB comment if any */ if (fout->remoteVersion >= 80200) @@ -2600,7 +2581,7 @@ dumpDatabase(Archive *fout) * Generates warning when loaded into a differently-named * database. */ - appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname)); + appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", qdatname); appendStringLiteralAH(dbQry, comment, fout); appendPQExpBufferStr(dbQry, ";\n"); @@ -2614,7 +2595,7 @@ dumpDatabase(Archive *fout) } else { - dumpComment(fout, labelq->data, NULL, dba, + dumpComment(fout, "DATABASE", qdatname, NULL, dba, dbCatId, 0, dbDumpId); } @@ -2643,6 +2624,7 @@ dumpDatabase(Archive *fout) PQclear(res); + free(qdatname); destroyPQExpBuffer(dbQry); destroyPQExpBuffer(delQry); destroyPQExpBuffer(creaQry); @@ -2703,6 +2685,84 @@ dumpStdStrings(Archive *AH) destroyPQExpBuffer(qry); } +/* + * dumpSearchPath: record the active search_path in the archive + */ +static void +dumpSearchPath(Archive *AH) +{ + PQExpBuffer qry = createPQExpBuffer(); + PQExpBuffer path = createPQExpBuffer(); + PGresult *res; + char **schemanames = NULL; + int nschemanames = 0; + int i; + + if (AH->remoteVersion >= 70300) + { + /* + * We use the result of current_schemas(), not the search_path GUC, + * because that might contain wildcards such as "$user", which won't + * necessarily have the same value during restore. Also, this way + * avoids listing schemas that may appear in search_path but not + * actually exist, which seems like a prudent exclusion. + */ + res = ExecuteSqlQueryForSingleRow(AH, + "SELECT pg_catalog.current_schemas(false)"); + + if (!parsePGArray(PQgetvalue(res, 0, 0), &schemanames, &nschemanames)) + exit_horribly(NULL, "could not parse result of current_schemas()\n"); + + /* + * We use set_config(), not a simple "SET search_path" command, + * because the latter has less-clean behavior if the search path is + * empty. While that's likely to get fixed at some point, it seems + * like a good idea to be as backwards-compatible as possible in what + * we put into archives. + */ + for (i = 0; i < nschemanames; i++) + { + if (i > 0) + appendPQExpBufferStr(path, ", "); + appendPQExpBufferStr(path, fmtId(schemanames[i])); + } + + PQclear(res); + } + else + { + /* + * For pre-schema servers, we must force the output search path to be + * "public", because the source server's ruleutils functions will not + * schema-qualify anything. Thus, for example, references to user + * tables in view definitions won't work otherwise. + */ + appendPQExpBufferStr(path, "public"); + } + + appendPQExpBufferStr(qry, "SELECT pg_catalog.set_config('search_path', "); + appendStringLiteralAH(qry, path->data, AH); + appendPQExpBufferStr(qry, ", false);\n"); + + if (g_verbose) + write_msg(NULL, "saving search_path = %s\n", path->data); + + ArchiveEntry(AH, nilCatalogId, createDumpId(), + "SEARCHPATH", NULL, NULL, "", + false, "SEARCHPATH", SECTION_PRE_DATA, + qry->data, "", NULL, + NULL, 0, + NULL, NULL); + + /* Also save it in AH->searchpath, in case we're doing plain text dump */ + AH->searchpath = pg_strdup(qry->data); + + if (schemanames) + free(schemanames); + destroyPQExpBuffer(qry); + destroyPQExpBuffer(path); +} + /* * getBlobs: @@ -2722,9 +2782,6 @@ getBlobs(Archive *fout) if (g_verbose) write_msg(NULL, "reading large objects\n"); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - /* Fetch BLOB OIDs, and owner/ACL data if >= 9.0 */ if (fout->remoteVersion >= 90000) appendPQExpBuffer(blobQry, @@ -2811,17 +2868,13 @@ dumpBlob(Archive *fout, BlobInfo *binfo) NULL, 0, NULL, NULL); - /* set up tag for comment and/or ACL */ - resetPQExpBuffer(cquery); - appendPQExpBuffer(cquery, "LARGE OBJECT %s", binfo->dobj.name); - /* Dump comment if any */ - dumpComment(fout, cquery->data, + dumpComment(fout, "LARGE OBJECT", binfo->dobj.name, NULL, binfo->rolname, binfo->dobj.catId, 0, binfo->dobj.dumpId); /* Dump security label if any */ - dumpSecLabel(fout, cquery->data, + dumpSecLabel(fout, "LARGE OBJECT", binfo->dobj.name, NULL, binfo->rolname, binfo->dobj.catId, 0, binfo->dobj.dumpId); @@ -2834,7 +2887,7 @@ dumpBlob(Archive *fout, BlobInfo *binfo) */ if (binfo->blobacl && !binary_upgrade) dumpACL(fout, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT", - binfo->dobj.name, NULL, cquery->data, + binfo->dobj.name, NULL, NULL, binfo->rolname, binfo->blobacl); destroyPQExpBuffer(cquery); @@ -2867,9 +2920,6 @@ dumpBlobs(Archive *fout, void *arg) if (g_verbose) write_msg(NULL, "saving large objects\n"); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - /* * Currently, we re-fetch all BLOB OIDs using a cursor. Consider scanning * the already-in-memory dumpable objects instead... @@ -3079,11 +3129,16 @@ binary_upgrade_set_pg_class_oids(Archive *fout, /* * If the DumpableObject is a member of an extension, add a suitable * ALTER EXTENSION ADD command to the creation commands in upgrade_buffer. + * + * For somewhat historical reasons, objname should already be quoted, + * but not objnamespace (if any). */ static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer, DumpableObject *dobj, - const char *objlabel) + const char *objtype, + const char *objname, + const char *objnamespace) { DumpableObject *extobj = NULL; int i; @@ -3105,13 +3160,17 @@ binary_upgrade_extension_member(PQExpBuffer upgrade_buffer, extobj = NULL; } if (extobj == NULL) - exit_horribly(NULL, "could not find parent extension for %s\n", objlabel); + exit_horribly(NULL, "could not find parent extension for %s %s\n", + objtype, objname); appendPQExpBufferStr(upgrade_buffer, "\n-- For binary upgrade, handle extension membership the hard way\n"); - appendPQExpBuffer(upgrade_buffer, "ALTER EXTENSION %s ADD %s;\n", + appendPQExpBuffer(upgrade_buffer, "ALTER EXTENSION %s ADD %s ", fmtId(extobj->name), - objlabel); + objtype); + if (objnamespace && *objnamespace) + appendPQExpBuffer(upgrade_buffer, "%s.", fmtId(objnamespace)); + appendPQExpBuffer(upgrade_buffer, "%s;\n", objname); } /* @@ -3170,9 +3229,6 @@ getNamespaces(Archive *fout, int *numNamespaces) query = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - /* * we fetch all namespaces including system ones, so that every object we * read in can be linked to a containing namespace. @@ -3291,9 +3347,6 @@ getExtensions(Archive *fout, int *numExtensions) query = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - appendPQExpBufferStr(query, "SELECT x.tableoid, x.oid, " "x.extname, n.nspname, x.extrelocatable, x.extversion, x.extconfig, x.extcondition " "FROM pg_extension x " @@ -3389,9 +3442,6 @@ getTypes(Archive *fout, int *numTypes) * be revisited if the backend ever allows renaming of array types. */ - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - if (fout->remoteVersion >= 90200) { appendPQExpBuffer(query, "SELECT tableoid, oid, typname, " @@ -3642,9 +3692,6 @@ getOperators(Archive *fout, int *numOprs) * system-defined operators at dump-out time. */ - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - if (fout->remoteVersion >= 70300) { appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, " @@ -3758,9 +3805,6 @@ getCollations(Archive *fout, int *numCollations) * system-defined collations at dump-out time. */ - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - appendPQExpBuffer(query, "SELECT tableoid, oid, collname, " "collnamespace, " "(%s collowner) AS rolname " @@ -3839,9 +3883,6 @@ getConversions(Archive *fout, int *numConversions) * system-defined conversions at dump-out time. */ - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - appendPQExpBuffer(query, "SELECT tableoid, oid, conname, " "connamespace, " "(%s conowner) AS rolname " @@ -3911,9 +3952,6 @@ getOpclasses(Archive *fout, int *numOpclasses) * system-defined opclasses at dump-out time. */ - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - if (fout->remoteVersion >= 70300) { appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, " @@ -4018,9 +4056,6 @@ getOpfamilies(Archive *fout, int *numOpfamilies) * system-defined opfamilies at dump-out time. */ - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - appendPQExpBuffer(query, "SELECT tableoid, oid, opfname, " "opfnamespace, " "(%s opfowner) AS rolname " @@ -4095,9 +4130,6 @@ getAggregates(Archive *fout, int *numAggs) int i_rolname; int i_aggacl; - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - /* * Find all user-defined aggregates. See comment in getFuncs() for the * rationale behind the filtering logic. @@ -4254,9 +4286,6 @@ getFuncs(Archive *fout, int *numFuncs) int i_prorettype; int i_proacl; - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - /* * Find all interesting functions. This is a bit complicated: * @@ -4445,9 +4474,6 @@ getTables(Archive *fout, int *numTables) int i_reloftype; int i_relpages; - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - /* * Find all the tables and table-like objects. * @@ -5000,9 +5026,7 @@ getTables(Archive *fout, int *numTables) resetPQExpBuffer(query); appendPQExpBuffer(query, "LOCK TABLE %s IN ACCESS SHARE MODE", - fmtQualifiedId(fout->remoteVersion, - tblinfo[i].dobj.namespace->dobj.name, - tblinfo[i].dobj.name)); + fmtQualifiedDumpable(&tblinfo[i])); ExecuteSqlStatement(fout, query->data); } @@ -5073,13 +5097,9 @@ getInherits(Archive *fout, int *numInherits) int i; PQExpBuffer query = createPQExpBuffer(); InhInfo *inhinfo; - int i_inhrelid; int i_inhparent; - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - /* find all the inheritance information */ appendPQExpBufferStr(query, "SELECT inhrelid, inhparent FROM pg_inherits"); @@ -5163,9 +5183,6 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) write_msg(NULL, "reading indexes for table \"%s\"\n", tbinfo->dobj.name); - /* Make sure we are in proper schema so indexdef is right */ - selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name); - /* * 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 @@ -5529,12 +5546,6 @@ getConstraints(Archive *fout, TableInfo tblinfo[], int numTables) write_msg(NULL, "reading foreign key constraints for table \"%s\"\n", tbinfo->dobj.name); - /* - * select table schema to ensure constraint expr is qualified if - * needed - */ - selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name); - resetPQExpBuffer(query); appendPQExpBuffer(query, "SELECT tableoid, oid, conname, confrelid, " @@ -5603,12 +5614,6 @@ getDomainConstraints(Archive *fout, TypeInfo *tyinfo) if (fout->remoteVersion < 70300) return; - /* - * select appropriate schema to ensure names in constraint are properly - * qualified - */ - selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name); - query = createPQExpBuffer(); if (fout->remoteVersion >= 90100) @@ -5711,9 +5716,6 @@ getRules(Archive *fout, int *numRules) int i_is_instead; int i_ev_enabled; - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - if (fout->remoteVersion >= 80300) { appendPQExpBufferStr(query, "SELECT " @@ -5867,11 +5869,6 @@ getTriggers(Archive *fout, TableInfo tblinfo[], int numTables) write_msg(NULL, "reading triggers for table \"%s\"\n", tbinfo->dobj.name); - /* - * select table schema to ensure regproc name is qualified if needed - */ - selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name); - resetPQExpBuffer(query); if (fout->remoteVersion >= 90000) { @@ -6082,9 +6079,6 @@ getEventTriggers(Archive *fout, int *numEventTriggers) query = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - appendPQExpBuffer(query, "SELECT e.tableoid, e.oid, evtname, evtenabled, " "evtevent, (%s evtowner) AS evtowner, " @@ -6165,9 +6159,6 @@ getProcLangs(Archive *fout, int *numProcLangs) int i_lanacl; int i_lanowner; - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - if (fout->remoteVersion >= 90000) { /* pg_language has a laninline column */ @@ -6330,9 +6321,6 @@ getCasts(Archive *fout, int *numCasts) int i_castcontext; int i_castmethod; - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - if (fout->remoteVersion >= 80400) { appendPQExpBufferStr(query, "SELECT tableoid, oid, " @@ -6483,12 +6471,6 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) if (!tbinfo->interesting) continue; - /* - * Make sure we are in proper schema for this table; this allows - * correct retrieval of formatted type names and default exprs - */ - selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name); - /* find all the user attributes and their types */ /* @@ -7058,9 +7040,6 @@ getTSParsers(Archive *fout, int *numTSParsers) * system-defined objects at dump-out time. */ - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - appendPQExpBufferStr(query, "SELECT tableoid, oid, prsname, prsnamespace, " "prsstart::oid, prstoken::oid, " "prsend::oid, prsheadline::oid, prslextype::oid " @@ -7143,9 +7122,6 @@ getTSDictionaries(Archive *fout, int *numTSDicts) query = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - appendPQExpBuffer(query, "SELECT tableoid, oid, dictname, " "dictnamespace, (%s dictowner) AS rolname, " "dicttemplate, dictinitoption " @@ -7227,9 +7203,6 @@ getTSTemplates(Archive *fout, int *numTSTemplates) query = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - appendPQExpBufferStr(query, "SELECT tableoid, oid, tmplname, " "tmplnamespace, tmplinit::oid, tmpllexize::oid " "FROM pg_ts_template"); @@ -7304,9 +7277,6 @@ getTSConfigurations(Archive *fout, int *numTSConfigs) query = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - appendPQExpBuffer(query, "SELECT tableoid, oid, cfgname, " "cfgnamespace, (%s cfgowner) AS rolname, cfgparser " "FROM pg_ts_config", @@ -7384,9 +7354,6 @@ getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers) query = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - if (fout->remoteVersion >= 90100) { appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, " @@ -7493,9 +7460,6 @@ getForeignServers(Archive *fout, int *numForeignServers) query = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - appendPQExpBuffer(query, "SELECT tableoid, oid, srvname, " "(%s srvowner) AS rolname, " "srvfdw, srvtype, srvversion, srvacl," @@ -7581,9 +7545,6 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs) query = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - appendPQExpBuffer(query, "SELECT oid, tableoid, " "(%s defaclrole) AS defaclrole, " "defaclnamespace, " @@ -7642,13 +7603,18 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs) * dumpComment -- * * This routine is used to dump any comments associated with the - * object handed to this routine. The routine takes a constant character - * string for the target part of the comment-creation command, plus + * object handed to this routine. The routine takes the object type + * and object name (ready to print, except for schema decoration), plus * the namespace and owner of the object (for labeling the ArchiveEntry), * plus catalog ID and subid which are the lookup key for pg_description, * plus the dump ID for the object (for setting a dependency). * If a matching pg_description entry is found, it is dumped. * + * Note: in some cases, such as comments for triggers and rules, the "type" + * string really looks like, e.g., "TRIGGER name ON". This is a bit of a hack + * but it doesn't seem worth complicating the API for all callers to make + * it cleaner. + * * Note: although this routine takes a dumpId for dependency purposes, * that purpose is just to mark the dependency in the emitted dump file * for possible future use by pg_restore. We do NOT use it for determining @@ -7657,7 +7623,7 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs) * calling ArchiveEntry() for the specified object. */ static void -dumpComment(Archive *fout, const char *target, +dumpComment(Archive *fout, const char *type, const char *name, const char *namespace, const char *owner, CatalogId catalogId, int subid, DumpId dumpId) { @@ -7665,7 +7631,7 @@ dumpComment(Archive *fout, const char *target, int ncomments; /* Comments are schema not data ... except blob comments are data */ - if (strncmp(target, "LARGE OBJECT ", 13) != 0) + if (strcmp(type, "LARGE OBJECT") != 0) { if (dataOnly) return; @@ -7694,24 +7660,31 @@ dumpComment(Archive *fout, const char *target, if (ncomments > 0) { PQExpBuffer query = createPQExpBuffer(); + PQExpBuffer tag = createPQExpBuffer(); - appendPQExpBuffer(query, "COMMENT ON %s IS ", target); + appendPQExpBuffer(query, "COMMENT ON %s ", type); + if (namespace && *namespace) + appendPQExpBuffer(query, "%s.", fmtId(namespace)); + appendPQExpBuffer(query, "%s IS ", name); appendStringLiteralAH(query, comments->descr, fout); appendPQExpBufferStr(query, ";\n"); + appendPQExpBuffer(tag, "%s %s", type, name); + /* * We mark comments as SECTION_NONE because they really belong in the * same section as their parent, whether that is pre-data or * post-data. */ ArchiveEntry(fout, nilCatalogId, createDumpId(), - target, namespace, NULL, owner, + tag->data, namespace, NULL, owner, false, "COMMENT", SECTION_NONE, query->data, "", NULL, &(dumpId), 1, NULL, NULL); destroyPQExpBuffer(query); + destroyPQExpBuffer(tag); } } @@ -7728,7 +7701,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo, CommentItem *comments; int ncomments; PQExpBuffer query; - PQExpBuffer target; + PQExpBuffer tag; /* Comments are SCHEMA not data */ if (dataOnly) @@ -7745,7 +7718,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo, return; query = createPQExpBuffer(); - target = createPQExpBuffer(); + tag = createPQExpBuffer(); while (ncomments > 0) { @@ -7754,17 +7727,18 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo, if (objsubid == 0) { - resetPQExpBuffer(target); - appendPQExpBuffer(target, "%s %s", reltypename, + resetPQExpBuffer(tag); + appendPQExpBuffer(tag, "%s %s", reltypename, fmtId(tbinfo->dobj.name)); resetPQExpBuffer(query); - appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data); + appendPQExpBuffer(query, "COMMENT ON %s %s IS ", reltypename, + fmtQualifiedDumpable(tbinfo)); appendStringLiteralAH(query, descr, fout); appendPQExpBufferStr(query, ";\n"); ArchiveEntry(fout, nilCatalogId, createDumpId(), - target->data, + tag->data, tbinfo->dobj.namespace->dobj.name, NULL, tbinfo->rolname, false, "COMMENT", SECTION_NONE, @@ -7774,18 +7748,21 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo, } else if (objsubid > 0 && objsubid <= tbinfo->numatts) { - resetPQExpBuffer(target); - appendPQExpBuffer(target, "COLUMN %s.", + resetPQExpBuffer(tag); + appendPQExpBuffer(tag, "COLUMN %s.", fmtId(tbinfo->dobj.name)); - appendPQExpBufferStr(target, fmtId(tbinfo->attnames[objsubid - 1])); + appendPQExpBufferStr(tag, fmtId(tbinfo->attnames[objsubid - 1])); resetPQExpBuffer(query); - appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data); + appendPQExpBuffer(query, "COMMENT ON COLUMN %s.", + fmtQualifiedDumpable(tbinfo)); + appendPQExpBuffer(query, "%s IS ", + fmtId(tbinfo->attnames[objsubid - 1])); appendStringLiteralAH(query, descr, fout); appendPQExpBufferStr(query, ";\n"); ArchiveEntry(fout, nilCatalogId, createDumpId(), - target->data, + tag->data, tbinfo->dobj.namespace->dobj.name, NULL, tbinfo->rolname, false, "COMMENT", SECTION_NONE, @@ -7799,7 +7776,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo, } destroyPQExpBuffer(query); - destroyPQExpBuffer(target); + destroyPQExpBuffer(tag); } /* @@ -7914,11 +7891,6 @@ collectComments(Archive *fout, CommentItem **items) int i; CommentItem *comments; - /* - * Note we do NOT change source schema here; preserve the caller's - * setting, instead. - */ - query = createPQExpBuffer(); if (fout->remoteVersion >= 70300) @@ -8103,7 +8075,6 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo) { PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; char *qnspname; /* Skip if not to be dumped */ @@ -8116,7 +8087,6 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo) q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); qnspname = pg_strdup(fmtId(nspinfo->dobj.name)); @@ -8124,10 +8094,9 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo) appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname); - appendPQExpBuffer(labelq, "SCHEMA %s", qnspname); - if (binary_upgrade) - binary_upgrade_extension_member(q, &nspinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &nspinfo->dobj, + "SCHEMA", qnspname, NULL); ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, nspinfo->dobj.name, @@ -8139,22 +8108,21 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo) NULL, NULL); /* Dump Schema Comments and Security Labels */ - dumpComment(fout, labelq->data, + dumpComment(fout, "SCHEMA", qnspname, NULL, nspinfo->rolname, nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId); - dumpSecLabel(fout, labelq->data, + dumpSecLabel(fout, "SCHEMA", qnspname, NULL, nspinfo->rolname, nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId); dumpACL(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, "SCHEMA", - qnspname, NULL, labelq->data, NULL, + qnspname, NULL, NULL, nspinfo->rolname, nspinfo->nspacl); free(qnspname); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); } /* @@ -8166,7 +8134,6 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo) { PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; char *qextname; /* Skip if not to be dumped */ @@ -8175,7 +8142,6 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo) q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); qextname = pg_strdup(fmtId(extinfo->dobj.name)); @@ -8255,8 +8221,6 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo) appendPQExpBufferStr(q, ");\n"); } - appendPQExpBuffer(labelq, "EXTENSION %s", qextname); - ArchiveEntry(fout, extinfo->dobj.catId, extinfo->dobj.dumpId, extinfo->dobj.name, NULL, NULL, @@ -8267,10 +8231,10 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo) NULL, NULL); /* Dump Extension Comments and Security Labels */ - dumpComment(fout, labelq->data, + dumpComment(fout, "EXTENSION", qextname, NULL, "", extinfo->dobj.catId, 0, extinfo->dobj.dumpId); - dumpSecLabel(fout, labelq->data, + dumpSecLabel(fout, "EXTENSION", qextname, NULL, "", extinfo->dobj.catId, 0, extinfo->dobj.dumpId); @@ -8278,7 +8242,6 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo) destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); } /* @@ -8319,18 +8282,15 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo) { PQExpBuffer q = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer(); - PQExpBuffer labelq = createPQExpBuffer(); PQExpBuffer query = createPQExpBuffer(); PGresult *res; int num, i; Oid enum_oid; char *qtypname; + char *qualtypname; char *label; - /* Set proper schema search path */ - selectSourceSchema(fout, "pg_catalog"); - if (fout->remoteVersion >= 90100) appendPQExpBuffer(query, "SELECT oid, enumlabel " "FROM pg_catalog.pg_enum " @@ -8349,23 +8309,20 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo) num = PQntuples(res); qtypname = pg_strdup(fmtId(tyinfo->dobj.name)); + qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo)); /* - * DROP must be fully qualified in case same name appears in pg_catalog. * CASCADE shouldn't be required here as for normal types since the I/O * functions are generic and do not get dropped. */ - appendPQExpBuffer(delq, "DROP TYPE %s.", - fmtId(tyinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s;\n", - qtypname); + appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname); if (binary_upgrade) binary_upgrade_set_type_oids_by_type_oid(fout, q, tyinfo->dobj.catId.oid); appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (", - qtypname); + qualtypname); if (!binary_upgrade) { @@ -8395,19 +8352,16 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo) appendPQExpBuffer(q, "SELECT binary_upgrade.set_next_pg_enum_oid('%u'::pg_catalog.oid);\n", enum_oid); - appendPQExpBuffer(q, "ALTER TYPE %s.", - fmtId(tyinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(q, "%s ADD VALUE ", - qtypname); + appendPQExpBuffer(q, "ALTER TYPE %s ADD VALUE ", qualtypname); appendStringLiteralAH(q, label, fout); appendPQExpBufferStr(q, ";\n\n"); } } - appendPQExpBuffer(labelq, "TYPE %s", qtypname); - if (binary_upgrade) - binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &tyinfo->dobj, + "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, tyinfo->dobj.name, @@ -8420,23 +8374,24 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo) NULL, NULL); /* Dump Type Comments and Security Labels */ - dumpComment(fout, labelq->data, + dumpComment(fout, "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); - dumpSecLabel(fout, labelq->data, + dumpSecLabel(fout, "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE", - qtypname, NULL, labelq->data, + qtypname, NULL, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->typacl); PQclear(res); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); destroyPQExpBuffer(query); + free(qtypname); + free(qualtypname); } /* @@ -8448,19 +8403,13 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo) { PQExpBuffer q = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer(); - PQExpBuffer labelq = createPQExpBuffer(); PQExpBuffer query = createPQExpBuffer(); PGresult *res; Oid collationOid; char *qtypname; + char *qualtypname; char *procname; - /* - * select appropriate schema to ensure names in CREATE are properly - * qualified - */ - selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name); - appendPQExpBuffer(query, "SELECT pg_catalog.format_type(rngsubtype, NULL) AS rngsubtype, " "opc.opcname AS opcname, " @@ -8479,23 +8428,20 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo) res = ExecuteSqlQueryForSingleRow(fout, query->data); qtypname = pg_strdup(fmtId(tyinfo->dobj.name)); + qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo)); /* - * DROP must be fully qualified in case same name appears in pg_catalog. * CASCADE shouldn't be required here as for normal types since the I/O * functions are generic and do not get dropped. */ - appendPQExpBuffer(delq, "DROP TYPE %s.", - fmtId(tyinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s;\n", - qtypname); + appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname); if (binary_upgrade) binary_upgrade_set_type_oids_by_type_oid(fout, q, tyinfo->dobj.catId.oid); appendPQExpBuffer(q, "CREATE TYPE %s AS RANGE (", - qtypname); + qualtypname); appendPQExpBuffer(q, "\n subtype = %s", PQgetvalue(res, 0, PQfnumber(res, "rngsubtype"))); @@ -8506,7 +8452,6 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo) char *opcname = PQgetvalue(res, 0, PQfnumber(res, "opcname")); char *nspname = PQgetvalue(res, 0, PQfnumber(res, "opcnsp")); - /* always schema-qualify, don't try to be smart */ appendPQExpBuffer(q, ",\n subtype_opclass = %s.", fmtId(nspname)); appendPQExpBufferStr(q, fmtId(opcname)); @@ -8518,12 +8463,8 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo) CollInfo *coll = findCollationByOid(collationOid); if (coll) - { - /* always schema-qualify, don't try to be smart */ - appendPQExpBuffer(q, ",\n collation = %s.", - fmtId(coll->dobj.namespace->dobj.name)); - appendPQExpBufferStr(q, fmtId(coll->dobj.name)); - } + appendPQExpBuffer(q, ",\n collation = %s", + fmtQualifiedDumpable(coll)); } procname = PQgetvalue(res, 0, PQfnumber(res, "rngcanonical")); @@ -8536,10 +8477,10 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo) appendPQExpBufferStr(q, "\n);\n"); - appendPQExpBuffer(labelq, "TYPE %s", qtypname); - if (binary_upgrade) - binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &tyinfo->dobj, + "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, tyinfo->dobj.name, @@ -8552,23 +8493,24 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo) NULL, NULL); /* Dump Type Comments and Security Labels */ - dumpComment(fout, labelq->data, + dumpComment(fout, "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); - dumpSecLabel(fout, labelq->data, + dumpSecLabel(fout, "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE", - qtypname, NULL, labelq->data, + qtypname, NULL, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->typacl); PQclear(res); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); destroyPQExpBuffer(query); + free(qtypname); + free(qualtypname); } /* @@ -8585,30 +8527,25 @@ dumpUndefinedType(Archive *fout, TypeInfo *tyinfo) { PQExpBuffer q = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer(); - PQExpBuffer labelq = createPQExpBuffer(); char *qtypname; + char *qualtypname; qtypname = pg_strdup(fmtId(tyinfo->dobj.name)); + qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo)); - /* - * DROP must be fully qualified in case same name appears in pg_catalog. - */ - appendPQExpBuffer(delq, "DROP TYPE %s.", - fmtId(tyinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s;\n", - qtypname); + appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname); if (binary_upgrade) binary_upgrade_set_type_oids_by_type_oid(fout, q, tyinfo->dobj.catId.oid); appendPQExpBuffer(q, "CREATE TYPE %s;\n", - qtypname); - - appendPQExpBuffer(labelq, "TYPE %s", qtypname); + qualtypname); if (binary_upgrade) - binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &tyinfo->dobj, + "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, tyinfo->dobj.name, @@ -8621,21 +8558,22 @@ dumpUndefinedType(Archive *fout, TypeInfo *tyinfo) NULL, NULL); /* Dump Type Comments and Security Labels */ - dumpComment(fout, labelq->data, + dumpComment(fout, "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); - dumpSecLabel(fout, labelq->data, + dumpSecLabel(fout, "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE", - qtypname, NULL, labelq->data, + qtypname, NULL, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->typacl); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); + free(qtypname); + free(qualtypname); } /* @@ -8647,10 +8585,10 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo) { PQExpBuffer q = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer(); - PQExpBuffer labelq = createPQExpBuffer(); PQExpBuffer query = createPQExpBuffer(); PGresult *res; char *qtypname; + char *qualtypname; char *typlen; char *typinput; char *typoutput; @@ -8674,9 +8612,6 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo) char *typdefault; bool typdefault_is_literal = false; - /* Set proper schema search path so regproc references list correctly */ - selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name); - /* Fetch type-specific details */ if (fout->remoteVersion >= 90100) { @@ -8884,17 +8819,14 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo) typdefault = NULL; qtypname = pg_strdup(fmtId(tyinfo->dobj.name)); + qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo)); /* - * DROP must be fully qualified in case same name appears in pg_catalog. * The reason we include CASCADE is that the circular dependency between * the type and its I/O functions makes it impossible to drop the type any * other way. */ - appendPQExpBuffer(delq, "DROP TYPE %s.", - fmtId(tyinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s CASCADE;\n", - qtypname); + appendPQExpBuffer(delq, "DROP TYPE %s CASCADE;\n", qualtypname); /* We might already have a shell type, but setting pg_type_oid is harmless */ if (binary_upgrade) @@ -8904,7 +8836,7 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo) appendPQExpBuffer(q, "CREATE TYPE %s (\n" " INTERNALLENGTH = %s", - qtypname, + qualtypname, (strcmp(typlen, "-1") == 0) ? "variable" : typlen); if (fout->remoteVersion >= 70300) @@ -8948,8 +8880,6 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo) { char *elemType; - /* reselect schema in case changed by function dump */ - selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name); elemType = getFormattedTypeName(fout, tyinfo->typelem, zeroAsOpaque); appendPQExpBuffer(q, ",\n ELEMENT = %s", elemType); free(elemType); @@ -8993,10 +8923,10 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo) appendPQExpBufferStr(q, "\n);\n"); - appendPQExpBuffer(labelq, "TYPE %s", qtypname); - if (binary_upgrade) - binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &tyinfo->dobj, + "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, tyinfo->dobj.name, @@ -9009,23 +8939,24 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo) NULL, NULL); /* Dump Type Comments and Security Labels */ - dumpComment(fout, labelq->data, + dumpComment(fout, "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); - dumpSecLabel(fout, labelq->data, + dumpSecLabel(fout, "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE", - qtypname, NULL, labelq->data, + qtypname, NULL, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->typacl); PQclear(res); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); destroyPQExpBuffer(query); + free(qtypname); + free(qualtypname); } /* @@ -9037,20 +8968,17 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo) { PQExpBuffer q = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer(); - PQExpBuffer labelq = createPQExpBuffer(); PQExpBuffer query = createPQExpBuffer(); PGresult *res; int i; char *qtypname; + char *qualtypname; char *typnotnull; char *typdefn; char *typdefault; Oid typcollation; bool typdefault_is_literal = false; - /* Set proper schema search path so type references list correctly */ - selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name); - /* Fetch domain specific details */ if (fout->remoteVersion >= 90100) { @@ -9098,10 +9026,11 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo) tyinfo->dobj.catId.oid); qtypname = pg_strdup(fmtId(tyinfo->dobj.name)); + qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo)); appendPQExpBuffer(q, "CREATE DOMAIN %s AS %s", - qtypname, + qualtypname, typdefn); /* Print collation only if different from base type's collation */ @@ -9111,12 +9040,7 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo) coll = findCollationByOid(typcollation); if (coll) - { - /* always schema-qualify, don't try to be smart */ - appendPQExpBuffer(q, " COLLATE %s.", - fmtId(coll->dobj.namespace->dobj.name)); - appendPQExpBufferStr(q, fmtId(coll->dobj.name)); - } + appendPQExpBuffer(q, " COLLATE %s", fmtQualifiedDumpable(coll)); } if (typnotnull[0] == 't') @@ -9147,18 +9071,12 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo) appendPQExpBufferStr(q, ";\n"); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ - appendPQExpBuffer(delq, "DROP DOMAIN %s.", - fmtId(tyinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s;\n", - qtypname); - - appendPQExpBuffer(labelq, "DOMAIN %s", qtypname); + appendPQExpBuffer(delq, "DROP DOMAIN %s;\n", qualtypname); if (binary_upgrade) - binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &tyinfo->dobj, + "DOMAIN", qtypname, + tyinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, tyinfo->dobj.name, @@ -9171,22 +9089,23 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo) NULL, NULL); /* Dump Domain Comments and Security Labels */ - dumpComment(fout, labelq->data, + dumpComment(fout, "DOMAIN", qtypname, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); - dumpSecLabel(fout, labelq->data, + dumpSecLabel(fout, "DOMAIN", qtypname, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE", - qtypname, NULL, labelq->data, + qtypname, NULL, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->typacl); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); destroyPQExpBuffer(query); + free(qtypname); + free(qualtypname); } /* @@ -9200,10 +9119,10 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) PQExpBuffer q = createPQExpBuffer(); PQExpBuffer dropped = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer(); - PQExpBuffer labelq = createPQExpBuffer(); PQExpBuffer query = createPQExpBuffer(); PGresult *res; char *qtypname; + char *qualtypname; int ntups; int i_attname; int i_atttypdefn; @@ -9214,9 +9133,6 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) int i; int actual_atts; - /* Set proper schema search path so type references list correctly */ - selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name); - /* Fetch type specific details */ if (fout->remoteVersion >= 90100) { @@ -9276,9 +9192,10 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) } qtypname = pg_strdup(fmtId(tyinfo->dobj.name)); + qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo)); appendPQExpBuffer(q, "CREATE TYPE %s AS (", - qtypname); + qualtypname); actual_atts = 0; for (i = 0; i < ntups; i++) @@ -9316,12 +9233,8 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) coll = findCollationByOid(attcollation); if (coll) - { - /* always schema-qualify, don't try to be smart */ - appendPQExpBuffer(q, " COLLATE %s.", - fmtId(coll->dobj.namespace->dobj.name)); - appendPQExpBufferStr(q, fmtId(coll->dobj.name)); - } + appendPQExpBuffer(q, " COLLATE %s", + fmtQualifiedDumpable(coll)); } } else @@ -9343,11 +9256,11 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) "WHERE attname = ", attlen, attalign); appendStringLiteralAH(dropped, attname, fout); appendPQExpBufferStr(dropped, "\n AND attrelid = "); - appendStringLiteralAH(dropped, qtypname, fout); + appendStringLiteralAH(dropped, qualtypname, fout); appendPQExpBufferStr(dropped, "::pg_catalog.regclass;\n"); appendPQExpBuffer(dropped, "ALTER TYPE %s ", - qtypname); + qualtypname); appendPQExpBuffer(dropped, "DROP ATTRIBUTE %s;\n", fmtId(attname)); } @@ -9355,18 +9268,12 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) appendPQExpBufferStr(q, "\n);\n"); appendPQExpBufferStr(q, dropped->data); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ - appendPQExpBuffer(delq, "DROP TYPE %s.", - fmtId(tyinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s;\n", - qtypname); - - appendPQExpBuffer(labelq, "TYPE %s", qtypname); + appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname); if (binary_upgrade) - binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &tyinfo->dobj, + "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, tyinfo->dobj.name, @@ -9380,15 +9287,15 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) /* Dump Type Comments and Security Labels */ - dumpComment(fout, labelq->data, + dumpComment(fout, "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); - dumpSecLabel(fout, labelq->data, + dumpSecLabel(fout, "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE", - qtypname, NULL, labelq->data, + qtypname, NULL, tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, tyinfo->typacl); @@ -9396,8 +9303,9 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) destroyPQExpBuffer(q); destroyPQExpBuffer(dropped); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); destroyPQExpBuffer(query); + free(qtypname); + free(qualtypname); /* Dump any per-column comments */ dumpCompositeTypeColComments(fout, tyinfo); @@ -9488,7 +9396,9 @@ dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo) appendPQExpBufferStr(target, fmtId(attname)); resetPQExpBuffer(query); - appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data); + appendPQExpBuffer(query, "COMMENT ON COLUMN %s.", + fmtQualifiedDumpable(tyinfo)); + appendPQExpBuffer(query, "%s IS ", fmtId(attname)); appendStringLiteralAH(query, descr, fout); appendPQExpBufferStr(query, ";\n"); @@ -9542,7 +9452,7 @@ dumpShellType(Archive *fout, ShellTypeInfo *stinfo) stinfo->baseType->dobj.catId.oid); appendPQExpBuffer(q, "CREATE TYPE %s;\n", - fmtId(stinfo->dobj.name)); + fmtQualifiedDumpable(stinfo)); ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId, stinfo->dobj.name, @@ -9567,10 +9477,8 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) { PQExpBuffer defqry; PQExpBuffer delqry; - PQExpBuffer labelq; bool useParams; char *qlanname; - char *lanschema; FuncInfo *funcInfo; FuncInfo *inlineInfo = NULL; FuncInfo *validatorInfo = NULL; @@ -9616,20 +9524,9 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) defqry = createPQExpBuffer(); delqry = createPQExpBuffer(); - labelq = createPQExpBuffer(); qlanname = pg_strdup(fmtId(plang->dobj.name)); - /* - * If dumping a HANDLER clause, treat the language as being in the handler - * function's schema; this avoids cluttering the HANDLER clause. Otherwise - * it doesn't really have a schema. - */ - if (useParams) - lanschema = funcInfo->dobj.namespace->dobj.name; - else - lanschema = NULL; - appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n", qlanname); @@ -9639,25 +9536,13 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) plang->lanpltrusted ? "TRUSTED " : "", qlanname); appendPQExpBuffer(defqry, " HANDLER %s", - fmtId(funcInfo->dobj.name)); + fmtQualifiedDumpable(funcInfo)); if (OidIsValid(plang->laninline)) - { - appendPQExpBufferStr(defqry, " INLINE "); - /* Cope with possibility that inline is in different schema */ - if (inlineInfo->dobj.namespace != funcInfo->dobj.namespace) - appendPQExpBuffer(defqry, "%s.", - fmtId(inlineInfo->dobj.namespace->dobj.name)); - appendPQExpBufferStr(defqry, fmtId(inlineInfo->dobj.name)); - } + appendPQExpBuffer(defqry, " INLINE %s", + fmtQualifiedDumpable(inlineInfo)); if (OidIsValid(plang->lanvalidator)) - { - appendPQExpBufferStr(defqry, " VALIDATOR "); - /* Cope with possibility that validator is in different schema */ - if (validatorInfo->dobj.namespace != funcInfo->dobj.namespace) - appendPQExpBuffer(defqry, "%s.", - fmtId(validatorInfo->dobj.namespace->dobj.name)); - appendPQExpBufferStr(defqry, fmtId(validatorInfo->dobj.name)); - } + appendPQExpBuffer(defqry, " VALIDATOR %s", + fmtQualifiedDumpable(validatorInfo)); } else { @@ -9675,38 +9560,35 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) } appendPQExpBufferStr(defqry, ";\n"); - appendPQExpBuffer(labelq, "LANGUAGE %s", qlanname); - if (binary_upgrade) - binary_upgrade_extension_member(defqry, &plang->dobj, labelq->data); + binary_upgrade_extension_member(defqry, &plang->dobj, + "LANGUAGE", qlanname, NULL); ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId, plang->dobj.name, - lanschema, NULL, plang->lanowner, + NULL, NULL, plang->lanowner, false, "PROCEDURAL LANGUAGE", SECTION_PRE_DATA, defqry->data, delqry->data, NULL, NULL, 0, NULL, NULL); /* Dump Proc Lang Comments and Security Labels */ - dumpComment(fout, labelq->data, - lanschema, plang->lanowner, + dumpComment(fout, "LANGUAGE", qlanname, + NULL, plang->lanowner, plang->dobj.catId, 0, plang->dobj.dumpId); - dumpSecLabel(fout, labelq->data, - lanschema, plang->lanowner, + dumpSecLabel(fout, "LANGUAGE", qlanname, + NULL, plang->lanowner, plang->dobj.catId, 0, plang->dobj.dumpId); if (plang->lanpltrusted) dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE", - qlanname, NULL, labelq->data, - lanschema, + qlanname, NULL, NULL, plang->lanowner, plang->lanacl); free(qlanname); destroyPQExpBuffer(defqry); destroyPQExpBuffer(delqry); - destroyPQExpBuffer(labelq); } /* @@ -9849,7 +9731,6 @@ dumpFunc(Archive *fout, FuncInfo *finfo) PQExpBuffer query; PQExpBuffer q; PQExpBuffer delqry; - PQExpBuffer labelq; PQExpBuffer asPart; PGresult *res; char *funcsig; /* identity signature */ @@ -9889,12 +9770,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo) query = createPQExpBuffer(); q = createPQExpBuffer(); delqry = createPQExpBuffer(); - labelq = createPQExpBuffer(); asPart = createPQExpBuffer(); - /* Set proper schema search path so type references list correctly */ - selectSourceSchema(fout, finfo->dobj.namespace->dobj.name); - /* Fetch function-specific details */ if (fout->remoteVersion >= 90200) { @@ -10058,6 +9935,15 @@ dumpFunc(Archive *fout, FuncInfo *finfo) prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows")); lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname")); + /* + * Before 7.3, the "C" language name was actually upper case in the + * pg_language catalog. If we don't down-case it, we'll get a lookup + * failure at restore. + */ + if (fout->remoteVersion < 70300 && + strcmp(lanname, "C") == 0) + lanname = "c"; + /* * See backend/commands/functioncmds.c for details of how the 'AS' clause * is used. In 8.4 and up, an unused probin is NULL (here ""); previous @@ -10168,15 +10054,15 @@ dumpFunc(Archive *fout, FuncInfo *finfo) funcsig_tag = format_function_signature(fout, finfo, false); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ appendPQExpBuffer(delqry, "DROP FUNCTION %s.%s;\n", fmtId(finfo->dobj.namespace->dobj.name), funcsig); - appendPQExpBuffer(q, "CREATE FUNCTION %s ", funcfullsig ? funcfullsig : + appendPQExpBuffer(q, "CREATE FUNCTION %s.%s ", + fmtId(finfo->dobj.namespace->dobj.name), + funcfullsig ? funcfullsig : funcsig); + if (funcresult) appendPQExpBuffer(q, "RETURNS %s", funcresult); else @@ -10263,10 +10149,10 @@ dumpFunc(Archive *fout, FuncInfo *finfo) appendPQExpBuffer(q, "\n %s;\n", asPart->data); - appendPQExpBuffer(labelq, "FUNCTION %s", funcsig); - if (binary_upgrade) - binary_upgrade_extension_member(q, &finfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &finfo->dobj, + "FUNCTION", funcsig, + finfo->dobj.namespace->dobj.name); ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId, funcsig_tag, @@ -10279,15 +10165,15 @@ dumpFunc(Archive *fout, FuncInfo *finfo) NULL, NULL); /* Dump Function Comments and Security Labels */ - dumpComment(fout, labelq->data, + dumpComment(fout, "FUNCTION", funcsig, finfo->dobj.namespace->dobj.name, finfo->rolname, finfo->dobj.catId, 0, finfo->dobj.dumpId); - dumpSecLabel(fout, labelq->data, + dumpSecLabel(fout, "FUNCTION", funcsig, finfo->dobj.namespace->dobj.name, finfo->rolname, finfo->dobj.catId, 0, finfo->dobj.dumpId); dumpACL(fout, finfo->dobj.catId, finfo->dobj.dumpId, "FUNCTION", - funcsig, NULL, labelq->data, + funcsig, NULL, finfo->dobj.namespace->dobj.name, finfo->rolname, finfo->proacl); @@ -10296,7 +10182,6 @@ dumpFunc(Archive *fout, FuncInfo *finfo) destroyPQExpBuffer(query); destroyPQExpBuffer(q); destroyPQExpBuffer(delqry); - destroyPQExpBuffer(labelq); destroyPQExpBuffer(asPart); free(funcsig); if (funcfullsig) @@ -10322,7 +10207,10 @@ dumpCast(Archive *fout, CastInfo *cast) PQExpBuffer defqry; PQExpBuffer delqry; PQExpBuffer labelq; + PQExpBuffer castargs; FuncInfo *funcInfo = NULL; + char *sourceType; + char *targetType; /* Skip if not to be dumped */ if (!cast->dobj.dump || dataOnly) @@ -10337,23 +10225,18 @@ dumpCast(Archive *fout, CastInfo *cast) cast->castfunc); } - /* - * Make sure we are in proper schema (needed for getFormattedTypeName). - * Casts don't have a schema of their own, so use pg_catalog. - */ - selectSourceSchema(fout, "pg_catalog"); - defqry = createPQExpBuffer(); delqry = createPQExpBuffer(); labelq = createPQExpBuffer(); + castargs = createPQExpBuffer(); + sourceType = getFormattedTypeName(fout, cast->castsource, zeroAsNone); + targetType = getFormattedTypeName(fout, cast->casttarget, zeroAsNone); appendPQExpBuffer(delqry, "DROP CAST (%s AS %s);\n", - getFormattedTypeName(fout, cast->castsource, zeroAsNone), - getFormattedTypeName(fout, cast->casttarget, zeroAsNone)); + sourceType, targetType); appendPQExpBuffer(defqry, "CREATE CAST (%s AS %s) ", - getFormattedTypeName(fout, cast->castsource, zeroAsNone), - getFormattedTypeName(fout, cast->casttarget, zeroAsNone)); + sourceType, targetType); switch (cast->castmethod) { @@ -10369,9 +10252,8 @@ dumpCast(Archive *fout, CastInfo *cast) char *fsig = format_function_signature(fout, funcInfo, true); /* - * Always qualify the function name, in case it is not in - * pg_catalog schema (format_function_signature won't qualify - * it). + * Always qualify the function name (format_function_signature + * won't qualify it). */ appendPQExpBuffer(defqry, "WITH FUNCTION %s.%s", fmtId(funcInfo->dobj.namespace->dobj.name), fsig); @@ -10391,28 +10273,35 @@ dumpCast(Archive *fout, CastInfo *cast) appendPQExpBufferStr(defqry, ";\n"); appendPQExpBuffer(labelq, "CAST (%s AS %s)", - getFormattedTypeName(fout, cast->castsource, zeroAsNone), - getFormattedTypeName(fout, cast->casttarget, zeroAsNone)); + sourceType, targetType); + + appendPQExpBuffer(castargs, "(%s AS %s)", + sourceType, targetType); if (binary_upgrade) - binary_upgrade_extension_member(defqry, &cast->dobj, labelq->data); + binary_upgrade_extension_member(defqry, &cast->dobj, + "CAST", castargs->data, NULL); ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId, labelq->data, - "pg_catalog", NULL, "", + NULL, NULL, "", false, "CAST", SECTION_PRE_DATA, defqry->data, delqry->data, NULL, NULL, 0, NULL, NULL); /* Dump Cast Comments */ - dumpComment(fout, labelq->data, - "pg_catalog", "", + dumpComment(fout, "CAST", castargs->data, + NULL, "", cast->dobj.catId, 0, cast->dobj.dumpId); + free(sourceType); + free(targetType); + destroyPQExpBuffer(defqry); destroyPQExpBuffer(delqry); destroyPQExpBuffer(labelq); + destroyPQExpBuffer(castargs); } /* @@ -10425,7 +10314,6 @@ dumpOpr(Archive *fout, OprInfo *oprinfo) PQExpBuffer query; PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; PQExpBuffer oprid; PQExpBuffer details; const char *name; @@ -10467,21 +10355,17 @@ dumpOpr(Archive *fout, OprInfo *oprinfo) query = createPQExpBuffer(); q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); oprid = createPQExpBuffer(); details = createPQExpBuffer(); - /* Make sure we are in proper schema so regoperator works correctly */ - selectSourceSchema(fout, oprinfo->dobj.namespace->dobj.name); - if (fout->remoteVersion >= 80300) { appendPQExpBuffer(query, "SELECT oprkind, " "oprcode::pg_catalog.regprocedure, " "oprleft::pg_catalog.regtype, " "oprright::pg_catalog.regtype, " - "oprcom::pg_catalog.regoperator, " - "oprnegate::pg_catalog.regoperator, " + "oprcom, " + "oprnegate, " "oprrest::pg_catalog.regprocedure, " "oprjoin::pg_catalog.regprocedure, " "oprcanmerge, oprcanhash " @@ -10495,8 +10379,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo) "oprcode::pg_catalog.regprocedure, " "oprleft::pg_catalog.regtype, " "oprright::pg_catalog.regtype, " - "oprcom::pg_catalog.regoperator, " - "oprnegate::pg_catalog.regoperator, " + "oprcom, " + "oprnegate, " "oprrest::pg_catalog.regprocedure, " "oprjoin::pg_catalog.regprocedure, " "(oprlsortop != 0) AS oprcanmerge, " @@ -10598,14 +10482,14 @@ dumpOpr(Archive *fout, OprInfo *oprinfo) else appendPQExpBufferStr(oprid, ", NONE)"); - oprref = convertOperatorReference(fout, oprcom); + oprref = getFormattedOperatorName(fout, oprcom); if (oprref) { appendPQExpBuffer(details, ",\n COMMUTATOR = %s", oprref); free(oprref); } - oprref = convertOperatorReference(fout, oprnegate); + oprref = getFormattedOperatorName(fout, oprnegate); if (oprref) { appendPQExpBuffer(details, ",\n NEGATOR = %s", oprref); @@ -10632,20 +10516,18 @@ dumpOpr(Archive *fout, OprInfo *oprinfo) free(oprregproc); } - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ appendPQExpBuffer(delq, "DROP OPERATOR %s.%s;\n", fmtId(oprinfo->dobj.namespace->dobj.name), oprid->data); - appendPQExpBuffer(q, "CREATE OPERATOR %s (\n%s\n);\n", + appendPQExpBuffer(q, "CREATE OPERATOR %s.%s (\n%s\n);\n", + fmtId(oprinfo->dobj.namespace->dobj.name), oprinfo->dobj.name, details->data); - appendPQExpBuffer(labelq, "OPERATOR %s", oprid->data); - if (binary_upgrade) - binary_upgrade_extension_member(q, &oprinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &oprinfo->dobj, + "OPERATOR", oprid->data, + oprinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId, oprinfo->dobj.name, @@ -10658,7 +10540,7 @@ dumpOpr(Archive *fout, OprInfo *oprinfo) NULL, NULL); /* Dump Operator Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "OPERATOR", oprid->data, oprinfo->dobj.namespace->dobj.name, oprinfo->rolname, oprinfo->dobj.catId, 0, oprinfo->dobj.dumpId); @@ -10667,7 +10549,6 @@ dumpOpr(Archive *fout, OprInfo *oprinfo) destroyPQExpBuffer(query); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); destroyPQExpBuffer(oprid); destroyPQExpBuffer(details); } @@ -10715,65 +10596,39 @@ convertRegProcReference(Archive *fout, const char *proc) } /* - * Convert an operator cross-reference obtained from pg_operator + * getFormattedOperatorName - retrieve the operator name for the + * given operator OID (presented in string form). * - * Returns an allocated string of what to print, or NULL to print nothing. + * Returns an allocated string, or NULL if the given OID is InvalidOid. * Caller is responsible for free'ing result string. * - * In 7.3 and up the input is a REGOPERATOR display; we have to strip the - * argument-types part, and add OPERATOR() decoration if the name is - * schema-qualified. In older versions, the input is just a numeric OID, - * which we search our operator list for. + * What we produce has the format "OPERATOR(schema.oprname)". This is only + * useful in commands where the operator's argument types can be inferred from + * context. We always schema-qualify the name, though. The predecessor to + * this code tried to skip the schema qualification if possible, but that led + * to wrong results in corner cases, such as if an operator and its negator + * are in different schemas. */ static char * -convertOperatorReference(Archive *fout, const char *opr) +getFormattedOperatorName(Archive *fout, const char *oproid) { OprInfo *oprInfo; /* In all cases "0" means a null reference */ - if (strcmp(opr, "0") == 0) + if (strcmp(oproid, "0") == 0) return NULL; - if (fout->remoteVersion >= 70300) - { - char *name; - char *oname; - char *ptr; - bool inquote; - bool sawdot; - - name = pg_strdup(opr); - /* find non-double-quoted left paren, and check for non-quoted dot */ - inquote = false; - sawdot = false; - for (ptr = name; *ptr; ptr++) - { - if (*ptr == '"') - inquote = !inquote; - else if (*ptr == '.' && !inquote) - sawdot = true; - else if (*ptr == '(' && !inquote) - { - *ptr = '\0'; - break; - } - } - /* If not schema-qualified, don't need to add OPERATOR() */ - if (!sawdot) - return name; - oname = psprintf("OPERATOR(%s)", name); - free(name); - return oname; - } - - oprInfo = findOprByOid(atooid(opr)); + oprInfo = findOprByOid(atooid(oproid)); if (oprInfo == NULL) { write_msg(NULL, "WARNING: could not find operator with OID %s\n", - opr); + oproid); return NULL; } - return pg_strdup(oprInfo->dobj.name); + + return psprintf("OPERATOR(%s.%s)", + fmtId(oprInfo->dobj.namespace->dobj.name), + oprInfo->dobj.name); } /* @@ -10813,7 +10668,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo) PQExpBuffer query; PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; + PQExpBuffer nameusing; PGresult *res; int ntups; int i_opcintype; @@ -10866,10 +10721,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo) query = createPQExpBuffer(); q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); - - /* Make sure we are in proper schema so regoperator works correctly */ - selectSourceSchema(fout, opcinfo->dobj.namespace->dobj.name); + nameusing = createPQExpBuffer(); /* Get additional fields from the pg_opclass row */ if (fout->remoteVersion >= 80300) @@ -10920,19 +10772,14 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo) /* amname will still be needed after we PQclear res */ amname = pg_strdup(PQgetvalue(res, 0, i_amname)); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ appendPQExpBuffer(delq, "DROP OPERATOR CLASS %s", - fmtId(opcinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, ".%s", - fmtId(opcinfo->dobj.name)); + fmtQualifiedDumpable(opcinfo)); appendPQExpBuffer(delq, " USING %s;\n", fmtId(amname)); /* Build the fixed portion of the CREATE command */ appendPQExpBuffer(q, "CREATE OPERATOR CLASS %s\n ", - fmtId(opcinfo->dobj.name)); + fmtQualifiedDumpable(opcinfo)); if (strcmp(opcdefault, "t") == 0) appendPQExpBufferStr(q, "DEFAULT "); appendPQExpBuffer(q, "FOR TYPE %s USING %s", @@ -10941,8 +10788,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo) if (strlen(opcfamilyname) > 0) { appendPQExpBufferStr(q, " FAMILY "); - if (strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0) - appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp)); + appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp)); appendPQExpBuffer(q, "%s", fmtId(opcfamilyname)); } appendPQExpBufferStr(q, " AS\n "); @@ -11060,8 +10906,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo) if (strlen(sortfamily) > 0) { appendPQExpBufferStr(q, " FOR ORDER BY "); - if (strcmp(sortfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0) - appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp)); + appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp)); appendPQExpBufferStr(q, fmtId(sortfamily)); } @@ -11155,13 +11000,14 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo) appendPQExpBufferStr(q, ";\n"); - appendPQExpBuffer(labelq, "OPERATOR CLASS %s", - fmtId(opcinfo->dobj.name)); - appendPQExpBuffer(labelq, " USING %s", + appendPQExpBufferStr(nameusing, fmtId(opcinfo->dobj.name)); + appendPQExpBuffer(nameusing, " USING %s", fmtId(amname)); if (binary_upgrade) - binary_upgrade_extension_member(q, &opcinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &opcinfo->dobj, + "OPERATOR CLASS", nameusing->data, + opcinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId, opcinfo->dobj.name, @@ -11174,7 +11020,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo) NULL, NULL); /* Dump Operator Class Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "OPERATOR CLASS", nameusing->data, opcinfo->dobj.namespace->dobj.name, opcinfo->rolname, opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId); @@ -11184,7 +11030,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo) destroyPQExpBuffer(query); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); + destroyPQExpBuffer(nameusing); } /* @@ -11200,7 +11046,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo) PQExpBuffer query; PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; + PQExpBuffer nameusing; PGresult *res; PGresult *res_ops; PGresult *res_procs; @@ -11235,10 +11081,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo) query = createPQExpBuffer(); q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); - - /* Make sure we are in proper schema so regoperator works correctly */ - selectSourceSchema(fout, opfinfo->dobj.namespace->dobj.name); + nameusing = createPQExpBuffer(); /* * Fetch only those opfamily members that are tied directly to the @@ -11330,19 +11173,14 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo) /* amname will still be needed after we PQclear res */ amname = pg_strdup(PQgetvalue(res, 0, i_amname)); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ appendPQExpBuffer(delq, "DROP OPERATOR FAMILY %s", - fmtId(opfinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, ".%s", - fmtId(opfinfo->dobj.name)); + fmtQualifiedDumpable(opfinfo)); appendPQExpBuffer(delq, " USING %s;\n", fmtId(amname)); /* Build the fixed portion of the CREATE command */ appendPQExpBuffer(q, "CREATE OPERATOR FAMILY %s", - fmtId(opfinfo->dobj.name)); + fmtQualifiedDumpable(opfinfo)); appendPQExpBuffer(q, " USING %s;\n", fmtId(amname)); @@ -11352,7 +11190,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo) if (PQntuples(res_ops) > 0 || PQntuples(res_procs) > 0) { appendPQExpBuffer(q, "ALTER OPERATOR FAMILY %s", - fmtId(opfinfo->dobj.name)); + fmtQualifiedDumpable(opfinfo)); appendPQExpBuffer(q, " USING %s ADD\n ", fmtId(amname)); @@ -11386,8 +11224,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo) if (strlen(sortfamily) > 0) { appendPQExpBufferStr(q, " FOR ORDER BY "); - if (strcmp(sortfamilynsp, opfinfo->dobj.namespace->dobj.name) != 0) - appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp)); + appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp)); appendPQExpBufferStr(q, fmtId(sortfamily)); } @@ -11427,13 +11264,14 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo) appendPQExpBufferStr(q, ";\n"); } - appendPQExpBuffer(labelq, "OPERATOR FAMILY %s", - fmtId(opfinfo->dobj.name)); - appendPQExpBuffer(labelq, " USING %s", + appendPQExpBufferStr(nameusing, fmtId(opfinfo->dobj.name)); + appendPQExpBuffer(nameusing, " USING %s", fmtId(amname)); if (binary_upgrade) - binary_upgrade_extension_member(q, &opfinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &opfinfo->dobj, + "OPERATOR FAMILY", nameusing->data, + opfinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId, opfinfo->dobj.name, @@ -11446,7 +11284,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo) NULL, NULL); /* Dump Operator Family Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "OPERATOR FAMILY", nameusing->data, opfinfo->dobj.namespace->dobj.name, opfinfo->rolname, opfinfo->dobj.catId, 0, opfinfo->dobj.dumpId); @@ -11456,7 +11294,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo) destroyPQExpBuffer(query); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); + destroyPQExpBuffer(nameusing); } /* @@ -11469,7 +11307,7 @@ dumpCollation(Archive *fout, CollInfo *collinfo) PQExpBuffer query; PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; + char *qcollname; PGresult *res; int i_collcollate; int i_collctype; @@ -11483,10 +11321,8 @@ dumpCollation(Archive *fout, CollInfo *collinfo) query = createPQExpBuffer(); q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, collinfo->dobj.namespace->dobj.name); + qcollname = pg_strdup(fmtId(collinfo->dobj.name)); /* Get conversion-specific details */ appendPQExpBuffer(query, "SELECT " @@ -11504,25 +11340,20 @@ dumpCollation(Archive *fout, CollInfo *collinfo) collcollate = PQgetvalue(res, 0, i_collcollate); collctype = PQgetvalue(res, 0, i_collctype); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ - appendPQExpBuffer(delq, "DROP COLLATION %s", - fmtId(collinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, ".%s;\n", - fmtId(collinfo->dobj.name)); + appendPQExpBuffer(delq, "DROP COLLATION %s;\n", + fmtQualifiedDumpable(collinfo)); appendPQExpBuffer(q, "CREATE COLLATION %s (lc_collate = ", - fmtId(collinfo->dobj.name)); + fmtQualifiedDumpable(collinfo)); appendStringLiteralAH(q, collcollate, fout); appendPQExpBufferStr(q, ", lc_ctype = "); appendStringLiteralAH(q, collctype, fout); appendPQExpBufferStr(q, ");\n"); - appendPQExpBuffer(labelq, "COLLATION %s", fmtId(collinfo->dobj.name)); - if (binary_upgrade) - binary_upgrade_extension_member(q, &collinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &collinfo->dobj, + "COLLATION", qcollname, + collinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, collinfo->dobj.catId, collinfo->dobj.dumpId, collinfo->dobj.name, @@ -11535,7 +11366,7 @@ dumpCollation(Archive *fout, CollInfo *collinfo) NULL, NULL); /* Dump Collation Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "COLLATION", qcollname, collinfo->dobj.namespace->dobj.name, collinfo->rolname, collinfo->dobj.catId, 0, collinfo->dobj.dumpId); @@ -11544,7 +11375,7 @@ dumpCollation(Archive *fout, CollInfo *collinfo) destroyPQExpBuffer(query); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); + free(qcollname); } /* @@ -11557,7 +11388,7 @@ dumpConversion(Archive *fout, ConvInfo *convinfo) PQExpBuffer query; PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; + char *qconvname; PGresult *res; int i_conforencoding; int i_contoencoding; @@ -11575,10 +11406,8 @@ dumpConversion(Archive *fout, ConvInfo *convinfo) query = createPQExpBuffer(); q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, convinfo->dobj.namespace->dobj.name); + qconvname = pg_strdup(fmtId(convinfo->dobj.name)); /* Get conversion-specific details */ appendPQExpBuffer(query, "SELECT " @@ -11601,27 +11430,22 @@ dumpConversion(Archive *fout, ConvInfo *convinfo) conproc = PQgetvalue(res, 0, i_conproc); condefault = (PQgetvalue(res, 0, i_condefault)[0] == 't'); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ - appendPQExpBuffer(delq, "DROP CONVERSION %s", - fmtId(convinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, ".%s;\n", - fmtId(convinfo->dobj.name)); + appendPQExpBuffer(delq, "DROP CONVERSION %s;\n", + fmtQualifiedDumpable(convinfo)); appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ", (condefault) ? "DEFAULT " : "", - fmtId(convinfo->dobj.name)); + fmtQualifiedDumpable(convinfo)); appendStringLiteralAH(q, conforencoding, fout); appendPQExpBufferStr(q, " TO "); appendStringLiteralAH(q, contoencoding, fout); /* regproc is automatically quoted in 7.3 and above */ appendPQExpBuffer(q, " FROM %s;\n", conproc); - appendPQExpBuffer(labelq, "CONVERSION %s", fmtId(convinfo->dobj.name)); - if (binary_upgrade) - binary_upgrade_extension_member(q, &convinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &convinfo->dobj, + "CONVERSION", qconvname, + convinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId, convinfo->dobj.name, @@ -11634,7 +11458,7 @@ dumpConversion(Archive *fout, ConvInfo *convinfo) NULL, NULL); /* Dump Conversion Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "CONVERSION", qconvname, convinfo->dobj.namespace->dobj.name, convinfo->rolname, convinfo->dobj.catId, 0, convinfo->dobj.dumpId); @@ -11643,7 +11467,7 @@ dumpConversion(Archive *fout, ConvInfo *convinfo) destroyPQExpBuffer(query); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); + free(qconvname); } /* @@ -11696,7 +11520,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) PQExpBuffer query; PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; PQExpBuffer details; char *aggsig; /* identity signature */ char *aggfullsig = NULL; /* full signature */ @@ -11743,12 +11566,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo) query = createPQExpBuffer(); q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); details = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, agginfo->aggfn.dobj.namespace->dobj.name); - /* Get aggregate-specific details */ if (fout->remoteVersion >= 90400) { @@ -11757,7 +11576,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) "aggmtransfn, aggminvtransfn, aggmfinalfn, " "aggmtranstype::pg_catalog.regtype, " "aggfinalextra, aggmfinalextra, " - "aggsortop::pg_catalog.regoperator, " + "aggsortop, " "(aggkind = 'h') AS hypothetical, " "aggtransspace, agginitval, " "aggmtransspace, aggminitval, " @@ -11776,7 +11595,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) "'-' AS aggmtransfn, '-' AS aggminvtransfn, " "'-' AS aggmfinalfn, 0 AS aggmtranstype, " "false AS aggfinalextra, false AS aggmfinalextra, " - "aggsortop::pg_catalog.regoperator, " + "aggsortop, " "false AS hypothetical, " "0 AS aggtransspace, agginitval, " "0 AS aggmtransspace, NULL AS aggminitval, " @@ -11795,7 +11614,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) "'-' AS aggmtransfn, '-' AS aggminvtransfn, " "'-' AS aggmfinalfn, 0 AS aggmtranstype, " "false AS aggfinalextra, false AS aggmfinalextra, " - "aggsortop::pg_catalog.regoperator, " + "aggsortop, " "false AS hypothetical, " "0 AS aggtransspace, agginitval, " "0 AS aggmtransspace, NULL AS aggminitval, " @@ -11993,7 +11812,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) appendPQExpBufferStr(details, ",\n MFINALFUNC_EXTRA"); } - aggsortconvop = convertOperatorReference(fout, aggsortop); + aggsortconvop = getFormattedOperatorName(fout, aggsortop); if (aggsortconvop) { appendPQExpBuffer(details, ",\n SORTOP = %s", @@ -12004,20 +11823,18 @@ dumpAgg(Archive *fout, AggInfo *agginfo) if (hypothetical) appendPQExpBufferStr(details, ",\n HYPOTHETICAL"); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ appendPQExpBuffer(delq, "DROP AGGREGATE %s.%s;\n", fmtId(agginfo->aggfn.dobj.namespace->dobj.name), aggsig); - appendPQExpBuffer(q, "CREATE AGGREGATE %s (\n%s\n);\n", + appendPQExpBuffer(q, "CREATE AGGREGATE %s.%s (\n%s\n);\n", + fmtId(agginfo->aggfn.dobj.namespace->dobj.name), aggfullsig ? aggfullsig : aggsig, details->data); - appendPQExpBuffer(labelq, "AGGREGATE %s", aggsig); - if (binary_upgrade) - binary_upgrade_extension_member(q, &agginfo->aggfn.dobj, labelq->data); + binary_upgrade_extension_member(q, &agginfo->aggfn.dobj, + "AGGREGATE", aggsig, + agginfo->aggfn.dobj.namespace->dobj.name); ArchiveEntry(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId, aggsig_tag, @@ -12030,10 +11847,10 @@ dumpAgg(Archive *fout, AggInfo *agginfo) NULL, NULL); /* Dump Aggregate Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "AGGREGATE", aggsig, agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname, agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId); - dumpSecLabel(fout, labelq->data, + dumpSecLabel(fout, "AGGREGATE", aggsig, agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname, agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId); @@ -12047,8 +11864,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) aggsig = format_function_signature(fout, &agginfo->aggfn, true); dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId, - "FUNCTION", - aggsig, NULL, labelq->data, + "FUNCTION", aggsig, NULL, agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname, agginfo->aggfn.proacl); @@ -12062,7 +11878,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo) destroyPQExpBuffer(query); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); destroyPQExpBuffer(details); } @@ -12075,7 +11890,7 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo) { PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; + char *qprsname; /* Skip if not to be dumped */ if (!prsinfo->dobj.dump || dataOnly) @@ -12083,13 +11898,11 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo) q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, prsinfo->dobj.namespace->dobj.name); + qprsname = pg_strdup(fmtId(prsinfo->dobj.name)); appendPQExpBuffer(q, "CREATE TEXT SEARCH PARSER %s (\n", - fmtId(prsinfo->dobj.name)); + fmtQualifiedDumpable(prsinfo)); appendPQExpBuffer(q, " START = %s,\n", convertTSFunction(fout, prsinfo->prsstart)); @@ -12103,19 +11916,13 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo) appendPQExpBuffer(q, " LEXTYPES = %s );\n", convertTSFunction(fout, prsinfo->prslextype)); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ - appendPQExpBuffer(delq, "DROP TEXT SEARCH PARSER %s", - fmtId(prsinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, ".%s;\n", - fmtId(prsinfo->dobj.name)); - - appendPQExpBuffer(labelq, "TEXT SEARCH PARSER %s", - fmtId(prsinfo->dobj.name)); + appendPQExpBuffer(delq, "DROP TEXT SEARCH PARSER %s;\n", + fmtQualifiedDumpable(prsinfo)); if (binary_upgrade) - binary_upgrade_extension_member(q, &prsinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &prsinfo->dobj, + "TEXT SEARCH PARSER", qprsname, + prsinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId, prsinfo->dobj.name, @@ -12128,13 +11935,13 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo) NULL, NULL); /* Dump Parser Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "TEXT SEARCH PARSER", qprsname, prsinfo->dobj.namespace->dobj.name, "", prsinfo->dobj.catId, 0, prsinfo->dobj.dumpId); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); + free(qprsname); } /* @@ -12146,8 +11953,8 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo) { PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; PQExpBuffer query; + char *qdictname; PGresult *res; char *nspname; char *tmplname; @@ -12158,11 +11965,11 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo) q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); query = createPQExpBuffer(); + qdictname = pg_strdup(fmtId(dictinfo->dobj.name)); + /* Fetch name and namespace of the dictionary's template */ - selectSourceSchema(fout, "pg_catalog"); appendPQExpBuffer(query, "SELECT nspname, tmplname " "FROM pg_ts_template p, pg_namespace n " "WHERE p.oid = '%u' AND n.oid = tmplnamespace", @@ -12171,15 +11978,11 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo) nspname = PQgetvalue(res, 0, 0); tmplname = PQgetvalue(res, 0, 1); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, dictinfo->dobj.namespace->dobj.name); - appendPQExpBuffer(q, "CREATE TEXT SEARCH DICTIONARY %s (\n", - fmtId(dictinfo->dobj.name)); + fmtQualifiedDumpable(dictinfo)); appendPQExpBufferStr(q, " TEMPLATE = "); - if (strcmp(nspname, dictinfo->dobj.namespace->dobj.name) != 0) - appendPQExpBuffer(q, "%s.", fmtId(nspname)); + appendPQExpBuffer(q, "%s.", fmtId(nspname)); appendPQExpBufferStr(q, fmtId(tmplname)); PQclear(res); @@ -12190,19 +11993,13 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo) appendPQExpBufferStr(q, " );\n"); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ - appendPQExpBuffer(delq, "DROP TEXT SEARCH DICTIONARY %s", - fmtId(dictinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, ".%s;\n", - fmtId(dictinfo->dobj.name)); - - appendPQExpBuffer(labelq, "TEXT SEARCH DICTIONARY %s", - fmtId(dictinfo->dobj.name)); + appendPQExpBuffer(delq, "DROP TEXT SEARCH DICTIONARY %s;\n", + fmtQualifiedDumpable(dictinfo)); if (binary_upgrade) - binary_upgrade_extension_member(q, &dictinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &dictinfo->dobj, + "TEXT SEARCH DICTIONARY", qdictname, + dictinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId, dictinfo->dobj.name, @@ -12215,14 +12012,14 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo) NULL, NULL); /* Dump Dictionary Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "TEXT SEARCH DICTIONARY", qdictname, dictinfo->dobj.namespace->dobj.name, dictinfo->rolname, dictinfo->dobj.catId, 0, dictinfo->dobj.dumpId); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); destroyPQExpBuffer(query); + free(qdictname); } /* @@ -12234,7 +12031,7 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo) { PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; + char *qtmplname; /* Skip if not to be dumped */ if (!tmplinfo->dobj.dump || dataOnly) @@ -12242,13 +12039,11 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo) q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, tmplinfo->dobj.namespace->dobj.name); + qtmplname = pg_strdup(fmtId(tmplinfo->dobj.name)); appendPQExpBuffer(q, "CREATE TEXT SEARCH TEMPLATE %s (\n", - fmtId(tmplinfo->dobj.name)); + fmtQualifiedDumpable(tmplinfo)); if (tmplinfo->tmplinit != InvalidOid) appendPQExpBuffer(q, " INIT = %s,\n", @@ -12256,19 +12051,13 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo) appendPQExpBuffer(q, " LEXIZE = %s );\n", convertTSFunction(fout, tmplinfo->tmpllexize)); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ - appendPQExpBuffer(delq, "DROP TEXT SEARCH TEMPLATE %s", - fmtId(tmplinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, ".%s;\n", - fmtId(tmplinfo->dobj.name)); - - appendPQExpBuffer(labelq, "TEXT SEARCH TEMPLATE %s", - fmtId(tmplinfo->dobj.name)); + appendPQExpBuffer(delq, "DROP TEXT SEARCH TEMPLATE %s;\n", + fmtQualifiedDumpable(tmplinfo)); if (binary_upgrade) - binary_upgrade_extension_member(q, &tmplinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &tmplinfo->dobj, + "TEXT SEARCH TEMPLATE", qtmplname, + tmplinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId, tmplinfo->dobj.name, @@ -12281,13 +12070,13 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo) NULL, NULL); /* Dump Template Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "TEXT SEARCH TEMPLATE", qtmplname, tmplinfo->dobj.namespace->dobj.name, "", tmplinfo->dobj.catId, 0, tmplinfo->dobj.dumpId); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); + free(qtmplname); } /* @@ -12299,8 +12088,8 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo) { PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; PQExpBuffer query; + char *qcfgname; PGresult *res; char *nspname; char *prsname; @@ -12315,11 +12104,11 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo) q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); query = createPQExpBuffer(); + qcfgname = pg_strdup(fmtId(cfginfo->dobj.name)); + /* Fetch name and namespace of the config's parser */ - selectSourceSchema(fout, "pg_catalog"); appendPQExpBuffer(query, "SELECT nspname, prsname " "FROM pg_ts_parser p, pg_namespace n " "WHERE p.oid = '%u' AND n.oid = prsnamespace", @@ -12328,15 +12117,10 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo) nspname = PQgetvalue(res, 0, 0); prsname = PQgetvalue(res, 0, 1); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, cfginfo->dobj.namespace->dobj.name); - appendPQExpBuffer(q, "CREATE TEXT SEARCH CONFIGURATION %s (\n", - fmtId(cfginfo->dobj.name)); + fmtQualifiedDumpable(cfginfo)); - appendPQExpBufferStr(q, " PARSER = "); - if (strcmp(nspname, cfginfo->dobj.namespace->dobj.name) != 0) - appendPQExpBuffer(q, "%s.", fmtId(nspname)); + appendPQExpBuffer(q, " PARSER = %s.", fmtId(nspname)); appendPQExpBuffer(q, "%s );\n", fmtId(prsname)); PQclear(res); @@ -12370,7 +12154,7 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo) if (i > 0) appendPQExpBufferStr(q, ";\n"); appendPQExpBuffer(q, "\nALTER TEXT SEARCH CONFIGURATION %s\n", - fmtId(cfginfo->dobj.name)); + fmtQualifiedDumpable(cfginfo)); /* tokenname needs quoting, dictname does NOT */ appendPQExpBuffer(q, " ADD MAPPING FOR %s WITH %s", fmtId(tokenname), dictname); @@ -12384,19 +12168,13 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo) PQclear(res); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ - appendPQExpBuffer(delq, "DROP TEXT SEARCH CONFIGURATION %s", - fmtId(cfginfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, ".%s;\n", - fmtId(cfginfo->dobj.name)); - - appendPQExpBuffer(labelq, "TEXT SEARCH CONFIGURATION %s", - fmtId(cfginfo->dobj.name)); + appendPQExpBuffer(delq, "DROP TEXT SEARCH CONFIGURATION %s;\n", + fmtQualifiedDumpable(cfginfo)); if (binary_upgrade) - binary_upgrade_extension_member(q, &cfginfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &cfginfo->dobj, + "TEXT SEARCH CONFIGURATION", qcfgname, + cfginfo->dobj.namespace->dobj.name); ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId, cfginfo->dobj.name, @@ -12409,14 +12187,14 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo) NULL, NULL); /* Dump Configuration Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "TEXT SEARCH CONFIGURATION", qcfgname, cfginfo->dobj.namespace->dobj.name, cfginfo->rolname, cfginfo->dobj.catId, 0, cfginfo->dobj.dumpId); destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); destroyPQExpBuffer(query); + free(qcfgname); } /* @@ -12428,7 +12206,6 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo) { PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; char *qfdwname; /* Skip if not to be dumped */ @@ -12437,7 +12214,6 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo) q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); qfdwname = pg_strdup(fmtId(fdwinfo->dobj.name)); @@ -12458,11 +12234,10 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo) appendPQExpBuffer(delq, "DROP FOREIGN DATA WRAPPER %s;\n", qfdwname); - appendPQExpBuffer(labelq, "FOREIGN DATA WRAPPER %s", - qfdwname); - if (binary_upgrade) - binary_upgrade_extension_member(q, &fdwinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &fdwinfo->dobj, + "FOREIGN DATA WRAPPER", qfdwname, + NULL); ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId, fdwinfo->dobj.name, @@ -12476,13 +12251,12 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo) /* Handle the ACL */ dumpACL(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId, - "FOREIGN DATA WRAPPER", - qfdwname, NULL, labelq->data, + "FOREIGN DATA WRAPPER", qfdwname, NULL, NULL, fdwinfo->rolname, fdwinfo->fdwacl); /* Dump Foreign Data Wrapper Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "FOREIGN DATA WRAPPER", qfdwname, NULL, fdwinfo->rolname, fdwinfo->dobj.catId, 0, fdwinfo->dobj.dumpId); @@ -12490,7 +12264,6 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo) destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); } /* @@ -12502,7 +12275,6 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo) { PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; PQExpBuffer query; PGresult *res; char *qsrvname; @@ -12514,13 +12286,11 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo) q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); query = createPQExpBuffer(); qsrvname = pg_strdup(fmtId(srvinfo->dobj.name)); /* look up the foreign-data wrapper */ - selectSourceSchema(fout, "pg_catalog"); appendPQExpBuffer(query, "SELECT fdwname " "FROM pg_foreign_data_wrapper w " "WHERE w.oid = '%u'", @@ -12551,10 +12321,9 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo) appendPQExpBuffer(delq, "DROP SERVER %s;\n", qsrvname); - appendPQExpBuffer(labelq, "SERVER %s", qsrvname); - if (binary_upgrade) - binary_upgrade_extension_member(q, &srvinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &srvinfo->dobj, + "SERVER", qsrvname, NULL); ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId, srvinfo->dobj.name, @@ -12568,8 +12337,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo) /* Handle the ACL */ dumpACL(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId, - "FOREIGN SERVER", - qsrvname, NULL, labelq->data, + "FOREIGN SERVER", qsrvname, NULL, NULL, srvinfo->rolname, srvinfo->srvacl); @@ -12580,7 +12348,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo) srvinfo->dobj.catId, srvinfo->dobj.dumpId); /* Dump Foreign Server Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "SERVER", qsrvname, NULL, srvinfo->rolname, srvinfo->dobj.catId, 0, srvinfo->dobj.dumpId); @@ -12588,7 +12356,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo) destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); + destroyPQExpBuffer(query); } /* @@ -12627,8 +12395,6 @@ dumpUserMappings(Archive *fout, * OPTIONS clause. A possible alternative is to skip such mappings * altogether, but it's not clear that that's an improvement. */ - selectSourceSchema(fout, "pg_catalog"); - appendPQExpBuffer(query, "SELECT usename, " "array_to_string(ARRAY(" @@ -12768,8 +12534,7 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo) * FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT. * 'name' is the formatted name of the object. Must be quoted etc. already. * 'subname' is the formatted name of the sub-object, if any. Must be quoted. - * 'tag' is the tag for the archive entry (should be the same tag as would be - * used for comments etc; for example "TABLE foo"). + * (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' is the string read out of the fooacl system catalog field; @@ -12779,7 +12544,7 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo) static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId, const char *type, const char *name, const char *subname, - const char *tag, const char *nspname, const char *owner, + const char *nspname, const char *owner, const char *acls) { PQExpBuffer sql; @@ -12794,21 +12559,31 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId, sql = createPQExpBuffer(); - if (!buildACLCommands(name, subname, type, acls, owner, + if (!buildACLCommands(name, subname, nspname, type, acls, owner, "", fout->remoteVersion, sql)) exit_horribly(NULL, "could not parse ACL list (%s) for object \"%s\" (%s)\n", acls, name, type); if (sql->len > 0) + { + PQExpBuffer tag = createPQExpBuffer(); + + if (subname) + appendPQExpBuffer(tag, "COLUMN %s.%s", name, subname); + else + appendPQExpBuffer(tag, "%s %s", type, name); + ArchiveEntry(fout, nilCatalogId, createDumpId(), - tag, nspname, + tag->data, nspname, NULL, owner ? owner : "", false, "ACL", SECTION_NONE, sql->data, "", NULL, &(objDumpId), 1, NULL, NULL); + destroyPQExpBuffer(tag); + } destroyPQExpBuffer(sql); } @@ -12817,8 +12592,8 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId, * dumpSecLabel * * This routine is used to dump any security labels associated with the - * object handed to this routine. The routine takes a constant character - * string for the target part of the security-label command, plus + * object handed to this routine. The routine takes the object type + * and object name (ready to print, except for schema decoration), plus * the namespace and owner of the object (for labeling the ArchiveEntry), * plus catalog ID and subid which are the lookup key for pg_seclabel, * plus the dump ID for the object (for setting a dependency). @@ -12832,7 +12607,7 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId, * calling ArchiveEntry() for the specified object. */ static void -dumpSecLabel(Archive *fout, const char *target, +dumpSecLabel(Archive *fout, const char *type, const char *name, const char *namespace, const char *owner, CatalogId catalogId, int subid, DumpId dumpId) { @@ -12846,7 +12621,7 @@ dumpSecLabel(Archive *fout, const char *target, return; /* Security labels are schema not data ... except blob labels are data */ - if (strncmp(target, "LARGE OBJECT ", 13) != 0) + if (strcmp(type, "LARGE OBJECT") != 0) { if (dataOnly) return; @@ -12872,21 +12647,29 @@ dumpSecLabel(Archive *fout, const char *target, continue; appendPQExpBuffer(query, - "SECURITY LABEL FOR %s ON %s IS ", - fmtId(labels[i].provider), target); + "SECURITY LABEL FOR %s ON %s ", + fmtId(labels[i].provider), type); + if (namespace && *namespace) + appendPQExpBuffer(query, "%s.", fmtId(namespace)); + appendPQExpBuffer(query, "%s IS ", name); appendStringLiteralAH(query, labels[i].label, fout); appendPQExpBufferStr(query, ";\n"); } if (query->len > 0) { + PQExpBuffer tag = createPQExpBuffer(); + + appendPQExpBuffer(tag, "%s %s", type, name); ArchiveEntry(fout, nilCatalogId, createDumpId(), - target, namespace, NULL, owner, + tag->data, namespace, NULL, owner, false, "SECURITY LABEL", SECTION_NONE, query->data, "", NULL, &(dumpId), 1, NULL, NULL); + destroyPQExpBuffer(tag); } + destroyPQExpBuffer(query); } @@ -12937,13 +12720,14 @@ dumpTableSecLabel(Archive *fout, TableInfo *tbinfo, const char *reltypename) if (objsubid == 0) { appendPQExpBuffer(target, "%s %s", reltypename, - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); } else { colname = getAttrName(objsubid, tbinfo); - /* first fmtId result must be consumed before calling it again */ - appendPQExpBuffer(target, "COLUMN %s", fmtId(tbinfo->dobj.name)); + /* first fmtXXX result must be consumed before calling again */ + appendPQExpBuffer(target, "COLUMN %s", + fmtQualifiedDumpable(tbinfo)); appendPQExpBuffer(target, ".%s", fmtId(colname)); } appendPQExpBuffer(query, "SECURITY LABEL FOR %s ON %s IS ", @@ -13124,7 +12908,6 @@ dumpTable(Archive *fout, TableInfo *tbinfo) { char *namecopy; const char *objtype; - char *acltag; if (tbinfo->relkind == RELKIND_SEQUENCE) dumpSequence(fout, tbinfo); @@ -13134,12 +12917,10 @@ dumpTable(Archive *fout, TableInfo *tbinfo) /* Handle the ACL here */ namecopy = pg_strdup(fmtId(tbinfo->dobj.name)); objtype = (tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" : "TABLE"; - acltag = psprintf("%s %s", objtype, namecopy); dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, - objtype, namecopy, NULL, acltag, + objtype, namecopy, NULL, tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, tbinfo->relacl); - free(acltag); /* * Handle column ACLs, if any. Note: we pull these with a separate @@ -13166,14 +12947,12 @@ dumpTable(Archive *fout, TableInfo *tbinfo) char *attnamecopy; attnamecopy = pg_strdup(fmtId(attname)); - acltag = psprintf("COLUMN %s.%s", namecopy, attnamecopy); /* Column's GRANT type is always TABLE */ - dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE", - namecopy, attnamecopy, acltag, + dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, + "TABLE", namecopy, attnamecopy, tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, attacl); free(attnamecopy); - free(acltag); } PQclear(res); destroyPQExpBuffer(query); @@ -13249,7 +13028,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) { PQExpBuffer q = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer(); - PQExpBuffer labelq = createPQExpBuffer(); + char *qrelname; + char *qualrelname; int numParents; TableInfo **parents; int actual_atts; /* number of attrs in this CREATE statement */ @@ -13260,8 +13040,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) int j, k; - /* Make sure we are in proper schema */ - selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name); + qrelname = pg_strdup(fmtId(tbinfo->dobj.name)); + qualrelname = pg_strdup(fmtQualifiedDumpable(tbinfo)); if (binary_upgrade) binary_upgrade_set_type_oids_by_rel_oid(fout, q, @@ -13274,20 +13054,14 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) reltypename = "VIEW"; - /* - * DROP must be fully qualified in case same name appears in - * pg_catalog - */ - appendPQExpBuffer(delq, "DROP VIEW %s.", - fmtId(tbinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s;\n", - fmtId(tbinfo->dobj.name)); + appendPQExpBuffer(delq, "DROP VIEW %s;\n", qualrelname); if (binary_upgrade) binary_upgrade_set_pg_class_oids(fout, q, tbinfo->dobj.catId.oid, false); - appendPQExpBuffer(q, "CREATE VIEW %s", fmtId(tbinfo->dobj.name)); + appendPQExpBuffer(q, "CREATE VIEW %s", qualrelname); + if (nonemptyReloptions(tbinfo->reloptions)) { appendPQExpBufferStr(q, " WITH ("); @@ -13301,9 +13075,6 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) if (tbinfo->checkoption != NULL) appendPQExpBuffer(q, "\n WITH %s CHECK OPTION", tbinfo->checkoption); appendPQExpBufferStr(q, ";\n"); - - appendPQExpBuffer(labelq, "VIEW %s", - fmtId(tbinfo->dobj.name)); } else { @@ -13355,17 +13126,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) numParents = tbinfo->numParents; parents = tbinfo->parents; - /* - * DROP must be fully qualified in case same name appears in - * pg_catalog - */ - appendPQExpBuffer(delq, "DROP %s %s.", reltypename, - fmtId(tbinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s;\n", - fmtId(tbinfo->dobj.name)); - - appendPQExpBuffer(labelq, "%s %s", reltypename, - fmtId(tbinfo->dobj.name)); + appendPQExpBuffer(delq, "DROP %s %s;\n", reltypename, qualrelname); if (binary_upgrade) binary_upgrade_set_pg_class_oids(fout, q, @@ -13375,7 +13136,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ? "UNLOGGED " : "", reltypename, - fmtId(tbinfo->dobj.name)); + qualrelname); /* * Attach to type, if reloftype; except in case of a binary upgrade, @@ -13466,12 +13227,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) coll = findCollationByOid(tbinfo->attcollation[j]); if (coll) - { - /* always schema-qualify, don't try to be smart */ - appendPQExpBuffer(q, " COLLATE %s.", - fmtId(coll->dobj.namespace->dobj.name)); - appendPQExpBufferStr(q, fmtId(coll->dobj.name)); - } + appendPQExpBuffer(q, " COLLATE %s", + fmtQualifiedDumpable(coll)); } if (has_default) @@ -13525,10 +13282,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) if (k > 0) appendPQExpBufferStr(q, ", "); - if (parentRel->dobj.namespace != tbinfo->dobj.namespace) - appendPQExpBuffer(q, "%s.", - fmtId(parentRel->dobj.namespace->dobj.name)); - appendPQExpBufferStr(q, fmtId(parentRel->dobj.name)); + appendPQExpBufferStr(q, fmtQualifiedDumpable(parentRel)); } appendPQExpBufferChar(q, ')'); } @@ -13613,15 +13367,15 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) tbinfo->attalign[j]); appendStringLiteralAH(q, tbinfo->attnames[j], fout); appendPQExpBufferStr(q, "\n AND attrelid = "); - appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout); + appendStringLiteralAH(q, qualrelname, fout); appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); if (tbinfo->relkind == RELKIND_RELATION) appendPQExpBuffer(q, "ALTER TABLE ONLY %s ", - fmtId(tbinfo->dobj.name)); + qualrelname); else appendPQExpBuffer(q, "ALTER FOREIGN TABLE %s ", - fmtId(tbinfo->dobj.name)); + qualrelname); appendPQExpBuffer(q, "DROP COLUMN %s;\n", fmtId(tbinfo->attnames[j])); @@ -13635,7 +13389,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) "WHERE attname = "); appendStringLiteralAH(q, tbinfo->attnames[j], fout); appendPQExpBufferStr(q, "\n AND attrelid = "); - appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout); + appendStringLiteralAH(q, qualrelname, fout); appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); } } @@ -13649,7 +13403,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inherited constraint.\n"); appendPQExpBuffer(q, "ALTER TABLE ONLY %s ", - fmtId(tbinfo->dobj.name)); + qualrelname); appendPQExpBuffer(q, " ADD CONSTRAINT %s ", fmtId(constr->dobj.name)); appendPQExpBuffer(q, "%s;\n", constr->condef); @@ -13658,7 +13412,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) "WHERE contype = 'c' AND conname = "); appendStringLiteralAH(q, constr->dobj.name, fout); appendPQExpBufferStr(q, "\n AND conrelid = "); - appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout); + appendStringLiteralAH(q, qualrelname, fout); appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); } @@ -13670,12 +13424,9 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) TableInfo *parentRel = parents[k]; appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT ", - fmtId(tbinfo->dobj.name)); - if (parentRel->dobj.namespace != tbinfo->dobj.namespace) - appendPQExpBuffer(q, "%s.", - fmtId(parentRel->dobj.namespace->dobj.name)); + qualrelname); appendPQExpBuffer(q, "%s;\n", - fmtId(parentRel->dobj.name)); + fmtQualifiedDumpable(parentRel)); } } @@ -13683,7 +13434,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) { appendPQExpBufferStr(q, "\n-- For binary upgrade, set up typed tables this way.\n"); appendPQExpBuffer(q, "ALTER TABLE ONLY %s OF %s;\n", - fmtId(tbinfo->dobj.name), + qualrelname, tbinfo->reloftype); } } @@ -13704,7 +13455,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) "SET relfrozenxid = '%u', relminmxid = '%u'\n" "WHERE oid = ", tbinfo->frozenxid, tbinfo->minmxid); - appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout); + appendStringLiteralAH(q, qualrelname, fout); appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); if (tbinfo->toast_oid) @@ -13736,7 +13487,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_class\n" "SET relispopulated = 't'\n" "WHERE oid = "); - appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout); + appendStringLiteralAH(q, qualrelname, fout); appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); } @@ -13759,7 +13510,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) tbinfo->notnull[j] && !tbinfo->inhNotNull[j]) { appendPQExpBuffer(q, "ALTER TABLE ONLY %s ", - fmtId(tbinfo->dobj.name)); + qualrelname); appendPQExpBuffer(q, "ALTER COLUMN %s SET NOT NULL;\n", fmtId(tbinfo->attnames[j])); } @@ -13772,7 +13523,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) if (tbinfo->attstattarget[j] >= 0) { appendPQExpBuffer(q, "ALTER TABLE ONLY %s ", - fmtId(tbinfo->dobj.name)); + qualrelname); appendPQExpBuffer(q, "ALTER COLUMN %s ", fmtId(tbinfo->attnames[j])); appendPQExpBuffer(q, "SET STATISTICS %d;\n", @@ -13809,7 +13560,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) if (storage != NULL) { appendPQExpBuffer(q, "ALTER TABLE ONLY %s ", - fmtId(tbinfo->dobj.name)); + qualrelname); appendPQExpBuffer(q, "ALTER COLUMN %s ", fmtId(tbinfo->attnames[j])); appendPQExpBuffer(q, "SET STORAGE %s;\n", @@ -13823,7 +13574,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) if (tbinfo->attoptions[j] && tbinfo->attoptions[j][0] != '\0') { appendPQExpBuffer(q, "ALTER TABLE ONLY %s ", - fmtId(tbinfo->dobj.name)); + qualrelname); appendPQExpBuffer(q, "ALTER COLUMN %s ", fmtId(tbinfo->attnames[j])); appendPQExpBuffer(q, "SET (%s);\n", @@ -13838,7 +13589,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) tbinfo->attfdwoptions[j][0] != '\0') { appendPQExpBuffer(q, "ALTER FOREIGN TABLE %s ", - fmtId(tbinfo->dobj.name)); + qualrelname); appendPQExpBuffer(q, "ALTER COLUMN %s ", fmtId(tbinfo->attnames[j])); appendPQExpBuffer(q, "OPTIONS (\n %s\n);\n", @@ -13860,17 +13611,19 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) else if (tbinfo->relreplident == REPLICA_IDENTITY_NOTHING) { appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY NOTHING;\n", - fmtId(tbinfo->dobj.name)); + qualrelname); } else if (tbinfo->relreplident == REPLICA_IDENTITY_FULL) { appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY FULL;\n", - fmtId(tbinfo->dobj.name)); + qualrelname); } } if (binary_upgrade) - binary_upgrade_extension_member(q, &tbinfo->dobj, labelq->data); + binary_upgrade_extension_member(q, &tbinfo->dobj, + reltypename, qrelname, + tbinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, tbinfo->dobj.name, @@ -13904,7 +13657,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); + free(qrelname); + free(qualrelname); } /* @@ -13917,6 +13671,7 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo) int adnum = adinfo->adnum; PQExpBuffer q; PQExpBuffer delq; + char *qualrelname; /* Skip if table definition not to be dumped */ if (!tbinfo->dobj.dump || dataOnly) @@ -13929,19 +13684,16 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo) q = createPQExpBuffer(); delq = createPQExpBuffer(); + qualrelname = pg_strdup(fmtQualifiedDumpable(tbinfo)); + appendPQExpBuffer(q, "ALTER TABLE ONLY %s ", - fmtId(tbinfo->dobj.name)); + qualrelname); appendPQExpBuffer(q, "ALTER COLUMN %s SET DEFAULT %s;\n", fmtId(tbinfo->attnames[adnum - 1]), adinfo->adef_expr); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ - appendPQExpBuffer(delq, "ALTER TABLE %s.", - fmtId(tbinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s ", - fmtId(tbinfo->dobj.name)); + appendPQExpBuffer(delq, "ALTER TABLE %s ", + qualrelname); appendPQExpBuffer(delq, "ALTER COLUMN %s DROP DEFAULT;\n", fmtId(tbinfo->attnames[adnum - 1])); @@ -13957,6 +13709,7 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo) destroyPQExpBuffer(q); destroyPQExpBuffer(delq); + free(qualrelname); } /* @@ -14004,17 +13757,15 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo) bool is_constraint = (indxinfo->indexconstraint != 0); PQExpBuffer q; PQExpBuffer delq; - PQExpBuffer labelq; + char *qindxname; if (dataOnly) return; q = createPQExpBuffer(); delq = createPQExpBuffer(); - labelq = createPQExpBuffer(); - appendPQExpBuffer(labelq, "INDEX %s", - fmtId(indxinfo->dobj.name)); + qindxname = pg_strdup(fmtId(indxinfo->dobj.name)); /* * If there's an associated constraint, don't dump the index per se, but @@ -14036,28 +13787,24 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo) if (indxinfo->indisclustered) { appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); + /* index name is not qualified in this syntax */ appendPQExpBuffer(q, " ON %s;\n", - fmtId(indxinfo->dobj.name)); + qindxname); } /* If the index defines identity, we need to record that. */ if (indxinfo->indisreplident) { appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY USING", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); + /* index name is not qualified in this syntax */ appendPQExpBuffer(q, " INDEX %s;\n", - fmtId(indxinfo->dobj.name)); + qindxname); } - /* - * DROP must be fully qualified in case same name appears in - * pg_catalog - */ - appendPQExpBuffer(delq, "DROP INDEX %s.", - fmtId(tbinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s;\n", - fmtId(indxinfo->dobj.name)); + appendPQExpBuffer(delq, "DROP INDEX %s;\n", + fmtQualifiedDumpable(indxinfo)); ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId, indxinfo->dobj.name, @@ -14071,7 +13818,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo) } /* Dump Index Comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, "INDEX", qindxname, tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, indxinfo->dobj.catId, 0, @@ -14080,7 +13827,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo) destroyPQExpBuffer(q); destroyPQExpBuffer(delq); - destroyPQExpBuffer(labelq); + free(qindxname); } /* @@ -14120,7 +13867,7 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo) indxinfo->dobj.catId.oid, true); appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); appendPQExpBuffer(q, " ADD CONSTRAINT %s ", fmtId(coninfo->dobj.name)); @@ -14170,19 +13917,14 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo) if (indxinfo->indisclustered) { appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); + /* index name is not qualified in this syntax */ appendPQExpBuffer(q, " ON %s;\n", fmtId(indxinfo->dobj.name)); } - /* - * DROP must be fully qualified in case same name appears in - * pg_catalog - */ - appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.", - fmtId(tbinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s ", - fmtId(tbinfo->dobj.name)); + appendPQExpBuffer(delq, "ALTER TABLE ONLY %s ", + fmtQualifiedDumpable(tbinfo)); appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n", fmtId(coninfo->dobj.name)); @@ -14203,19 +13945,13 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo) * current table data is not processed */ appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n", fmtId(coninfo->dobj.name), coninfo->condef); - /* - * DROP must be fully qualified in case same name appears in - * pg_catalog - */ - appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.", - fmtId(tbinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s ", - fmtId(tbinfo->dobj.name)); + appendPQExpBuffer(delq, "ALTER TABLE ONLY %s ", + fmtQualifiedDumpable(tbinfo)); appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n", fmtId(coninfo->dobj.name)); @@ -14238,19 +13974,13 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo) { /* not ONLY since we want it to propagate to children */ appendPQExpBuffer(q, "ALTER TABLE %s\n", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n", fmtId(coninfo->dobj.name), coninfo->condef); - /* - * DROP must be fully qualified in case same name appears in - * pg_catalog - */ - appendPQExpBuffer(delq, "ALTER TABLE %s.", - fmtId(tbinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s ", - fmtId(tbinfo->dobj.name)); + appendPQExpBuffer(delq, "ALTER TABLE %s ", + fmtQualifiedDumpable(tbinfo)); appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n", fmtId(coninfo->dobj.name)); @@ -14274,19 +14004,13 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo) if (coninfo->separate) { appendPQExpBuffer(q, "ALTER DOMAIN %s\n", - fmtId(tyinfo->dobj.name)); + fmtQualifiedDumpable(tyinfo)); appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n", fmtId(coninfo->dobj.name), coninfo->condef); - /* - * DROP must be fully qualified in case same name appears in - * pg_catalog - */ - appendPQExpBuffer(delq, "ALTER DOMAIN %s.", - fmtId(tyinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delq, "%s ", - fmtId(tyinfo->dobj.name)); + appendPQExpBuffer(delq, "ALTER DOMAIN %s ", + fmtQualifiedDumpable(tyinfo)); appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n", fmtId(coninfo->dobj.name)); @@ -14326,19 +14050,22 @@ static void dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo) { TableInfo *tbinfo = coninfo->contable; - PQExpBuffer labelq = createPQExpBuffer(); + PQExpBuffer conprefix = createPQExpBuffer(); + char *qtabname; - appendPQExpBuffer(labelq, "CONSTRAINT %s ", + qtabname = pg_strdup(fmtId(tbinfo->dobj.name)); + + appendPQExpBuffer(conprefix, "CONSTRAINT %s ON", fmtId(coninfo->dobj.name)); - appendPQExpBuffer(labelq, "ON %s", - fmtId(tbinfo->dobj.name)); - dumpComment(fout, labelq->data, + + dumpComment(fout, conprefix->data, qtabname, tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, coninfo->dobj.catId, 0, coninfo->separate ? coninfo->dobj.dumpId : tbinfo->dobj.dumpId); - destroyPQExpBuffer(labelq); + destroyPQExpBuffer(conprefix); + free(qtabname); } /* @@ -14405,10 +14132,9 @@ dumpSequence(Archive *fout, TableInfo *tbinfo) bool cycled; PQExpBuffer query = createPQExpBuffer(); PQExpBuffer delqry = createPQExpBuffer(); - PQExpBuffer labelq = createPQExpBuffer(); + char *qseqname; - /* Make sure we are in proper schema */ - selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name); + qseqname = pg_strdup(fmtId(tbinfo->dobj.name)); snprintf(bufm, sizeof(bufm), INT64_FORMAT, SEQ_MINVALUE); snprintf(bufx, sizeof(bufx), INT64_FORMAT, SEQ_MAXVALUE); @@ -14428,7 +14154,7 @@ dumpSequence(Archive *fout, TableInfo *tbinfo) "END AS min_value, " "cache_value, is_cycled FROM %s", bufx, bufm, - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); } else { @@ -14445,7 +14171,7 @@ dumpSequence(Archive *fout, TableInfo *tbinfo) "END AS min_value, " "cache_value, is_cycled FROM %s", bufx, bufm, - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); } res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); @@ -14478,13 +14204,8 @@ dumpSequence(Archive *fout, TableInfo *tbinfo) cache = PQgetvalue(res, 0, 5); cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ - appendPQExpBuffer(delqry, "DROP SEQUENCE %s.", - fmtId(tbinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delqry, "%s;\n", - fmtId(tbinfo->dobj.name)); + appendPQExpBuffer(delqry, "DROP SEQUENCE %s;\n", + fmtQualifiedDumpable(tbinfo)); resetPQExpBuffer(query); @@ -14498,7 +14219,7 @@ dumpSequence(Archive *fout, TableInfo *tbinfo) appendPQExpBuffer(query, "CREATE SEQUENCE %s\n", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); if (fout->remoteVersion >= 80400) appendPQExpBuffer(query, " START WITH %s\n", startv); @@ -14521,13 +14242,12 @@ dumpSequence(Archive *fout, TableInfo *tbinfo) appendPQExpBufferStr(query, ";\n"); - appendPQExpBuffer(labelq, "SEQUENCE %s", fmtId(tbinfo->dobj.name)); - /* binary_upgrade: no need to clear TOAST table oid */ if (binary_upgrade) binary_upgrade_extension_member(query, &tbinfo->dobj, - labelq->data); + "SEQUENCE", qseqname, + tbinfo->dobj.namespace->dobj.name); ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, tbinfo->dobj.name, @@ -14559,9 +14279,9 @@ dumpSequence(Archive *fout, TableInfo *tbinfo) { resetPQExpBuffer(query); appendPQExpBuffer(query, "ALTER SEQUENCE %s", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); appendPQExpBuffer(query, " OWNED BY %s", - fmtId(owning_tab->dobj.name)); + fmtQualifiedDumpable(owning_tab)); appendPQExpBuffer(query, ".%s;\n", fmtId(owning_tab->attnames[tbinfo->owning_col - 1])); @@ -14578,10 +14298,10 @@ dumpSequence(Archive *fout, TableInfo *tbinfo) } /* Dump Sequence Comments and Security Labels */ - dumpComment(fout, labelq->data, + dumpComment(fout, "SEQUENCE", qseqname, tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId); - dumpSecLabel(fout, labelq->data, + dumpSecLabel(fout, "SEQUENCE", qseqname, tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId); @@ -14589,7 +14309,7 @@ dumpSequence(Archive *fout, TableInfo *tbinfo) destroyPQExpBuffer(query); destroyPQExpBuffer(delqry); - destroyPQExpBuffer(labelq); + free(qseqname); } /* @@ -14605,12 +14325,9 @@ dumpSequenceData(Archive *fout, TableDataInfo *tdinfo) bool called; PQExpBuffer query = createPQExpBuffer(); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name); - appendPQExpBuffer(query, "SELECT last_value, is_called FROM %s", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); @@ -14628,7 +14345,7 @@ dumpSequenceData(Archive *fout, TableDataInfo *tdinfo) resetPQExpBuffer(query); appendPQExpBufferStr(query, "SELECT pg_catalog.setval("); - appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout); + appendStringLiteralAH(query, fmtQualifiedDumpable(tbinfo), fout); appendPQExpBuffer(query, ", %s, %s);\n", last, (called ? "true" : "false")); @@ -14657,7 +14374,8 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo) TableInfo *tbinfo = tginfo->tgtable; PQExpBuffer query; PQExpBuffer delqry; - PQExpBuffer labelq; + PQExpBuffer trigprefix; + char *qtabname; char *tgargs; size_t lentgargs; const char *p; @@ -14672,17 +14390,14 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo) query = createPQExpBuffer(); delqry = createPQExpBuffer(); - labelq = createPQExpBuffer(); + trigprefix = createPQExpBuffer(); + + qtabname = pg_strdup(fmtId(tbinfo->dobj.name)); - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ appendPQExpBuffer(delqry, "DROP TRIGGER %s ", fmtId(tginfo->dobj.name)); - appendPQExpBuffer(delqry, "ON %s.", - fmtId(tbinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delqry, "%s;\n", - fmtId(tbinfo->dobj.name)); + appendPQExpBuffer(delqry, "ON %s;\n", + fmtQualifiedDumpable(tbinfo)); if (tginfo->tgdef) { @@ -14746,7 +14461,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo) findx++; } appendPQExpBuffer(query, " ON %s\n", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); if (tginfo->tgisconstraint) { @@ -14812,7 +14527,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo) if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O') { appendPQExpBuffer(query, "\nALTER TABLE %s ", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); switch (tginfo->tgenabled) { case 'D': @@ -14833,10 +14548,8 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo) fmtId(tginfo->dobj.name)); } - appendPQExpBuffer(labelq, "TRIGGER %s ", + appendPQExpBuffer(trigprefix, "TRIGGER %s ON", fmtId(tginfo->dobj.name)); - appendPQExpBuffer(labelq, "ON %s", - fmtId(tbinfo->dobj.name)); ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId, tginfo->dobj.name, @@ -14848,13 +14561,14 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo) NULL, 0, NULL, NULL); - dumpComment(fout, labelq->data, + dumpComment(fout, trigprefix->data, qtabname, tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, tginfo->dobj.catId, 0, tginfo->dobj.dumpId); destroyPQExpBuffer(query); destroyPQExpBuffer(delqry); - destroyPQExpBuffer(labelq); + destroyPQExpBuffer(trigprefix); + free(qtabname); } /* @@ -14866,7 +14580,7 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo) { PQExpBuffer query; PQExpBuffer delqry; - PQExpBuffer labelq; + char *qevtname; /* Skip if not to be dumped */ if (!evtinfo->dobj.dump || dataOnly) @@ -14874,10 +14588,11 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo) query = createPQExpBuffer(); delqry = createPQExpBuffer(); - labelq = createPQExpBuffer(); + + qevtname = pg_strdup(fmtId(evtinfo->dobj.name)); appendPQExpBufferStr(query, "CREATE EVENT TRIGGER "); - appendPQExpBufferStr(query, fmtId(evtinfo->dobj.name)); + appendPQExpBufferStr(query, qevtname); appendPQExpBufferStr(query, " ON "); appendPQExpBufferStr(query, fmtId(evtinfo->evtevent)); @@ -14895,7 +14610,7 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo) if (evtinfo->evtenabled != 'O') { appendPQExpBuffer(query, "\nALTER EVENT TRIGGER %s ", - fmtId(evtinfo->dobj.name)); + qevtname); switch (evtinfo->evtenabled) { case 'D': @@ -14915,10 +14630,7 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo) } appendPQExpBuffer(delqry, "DROP EVENT TRIGGER %s;\n", - fmtId(evtinfo->dobj.name)); - - appendPQExpBuffer(labelq, "EVENT TRIGGER %s", - fmtId(evtinfo->dobj.name)); + qevtname); ArchiveEntry(fout, evtinfo->dobj.catId, evtinfo->dobj.dumpId, evtinfo->dobj.name, NULL, NULL, @@ -14928,13 +14640,13 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo) NULL, 0, NULL, NULL); - dumpComment(fout, labelq->data, + dumpComment(fout, "EVENT TRIGGER", qevtname, NULL, evtinfo->evtowner, evtinfo->dobj.catId, 0, evtinfo->dobj.dumpId); destroyPQExpBuffer(query); destroyPQExpBuffer(delqry); - destroyPQExpBuffer(labelq); + free(qevtname); } /* @@ -14948,8 +14660,10 @@ dumpRule(Archive *fout, RuleInfo *rinfo) PQExpBuffer query; PQExpBuffer cmd; PQExpBuffer delcmd; - PQExpBuffer labelq; + PQExpBuffer ruleprefix; + char *qtabname; PGresult *res; + char *tag; /* Skip if not to be dumped */ if (!rinfo->dobj.dump || dataOnly) @@ -14962,15 +14676,12 @@ dumpRule(Archive *fout, RuleInfo *rinfo) if (!rinfo->separate) return; - /* - * Make sure we are in proper schema. - */ - selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name); - query = createPQExpBuffer(); cmd = createPQExpBuffer(); delcmd = createPQExpBuffer(); - labelq = createPQExpBuffer(); + ruleprefix = createPQExpBuffer(); + + qtabname = pg_strdup(fmtId(tbinfo->dobj.name)); if (fout->remoteVersion >= 70300) { @@ -15003,7 +14714,7 @@ dumpRule(Archive *fout, RuleInfo *rinfo) */ if (rinfo->ev_enabled != 'O') { - appendPQExpBuffer(cmd, "ALTER TABLE %s ", fmtId(tbinfo->dobj.name)); + appendPQExpBuffer(cmd, "ALTER TABLE %s ", fmtQualifiedDumpable(tbinfo)); switch (rinfo->ev_enabled) { case 'A': @@ -15027,28 +14738,23 @@ dumpRule(Archive *fout, RuleInfo *rinfo) if (nonemptyReloptions(rinfo->reloptions)) { appendPQExpBuffer(cmd, "ALTER VIEW %s SET (", - fmtId(tbinfo->dobj.name)); + fmtQualifiedDumpable(tbinfo)); fmtReloptionsArray(fout, cmd, rinfo->reloptions, ""); appendPQExpBufferStr(cmd, ");\n"); } - /* - * DROP must be fully qualified in case same name appears in pg_catalog - */ appendPQExpBuffer(delcmd, "DROP RULE %s ", fmtId(rinfo->dobj.name)); - appendPQExpBuffer(delcmd, "ON %s.", - fmtId(tbinfo->dobj.namespace->dobj.name)); - appendPQExpBuffer(delcmd, "%s;\n", - fmtId(tbinfo->dobj.name)); + appendPQExpBuffer(delcmd, "ON %s;\n", + fmtQualifiedDumpable(tbinfo)); - appendPQExpBuffer(labelq, "RULE %s", + appendPQExpBuffer(ruleprefix, "RULE %s ON", fmtId(rinfo->dobj.name)); - appendPQExpBuffer(labelq, " ON %s", - fmtId(tbinfo->dobj.name)); + + tag = psprintf("%s %s", tbinfo->dobj.name, rinfo->dobj.name); ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId, - rinfo->dobj.name, + tag, tbinfo->dobj.namespace->dobj.name, NULL, tbinfo->rolname, false, @@ -15058,17 +14764,19 @@ dumpRule(Archive *fout, RuleInfo *rinfo) NULL, NULL); /* Dump rule comments */ - dumpComment(fout, labelq->data, + dumpComment(fout, ruleprefix->data, qtabname, tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, rinfo->dobj.catId, 0, rinfo->dobj.dumpId); PQclear(res); + free(tag); destroyPQExpBuffer(query); destroyPQExpBuffer(cmd); destroyPQExpBuffer(delcmd); - destroyPQExpBuffer(labelq); + destroyPQExpBuffer(ruleprefix); + free(qtabname); } /* @@ -15100,9 +14808,6 @@ getExtensionMembership(Archive *fout, ExtensionInfo extinfo[], if (numExtensions == 0) return; - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - query = createPQExpBuffer(); /* refclassid constraint is redundant but may speed the search */ @@ -15299,9 +15004,6 @@ processExtensionTables(Archive *fout, ExtensionInfo extinfo[], * recreated after the data has been loaded. */ - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - query = createPQExpBuffer(); printfPQExpBuffer(query, @@ -15371,9 +15073,6 @@ getDependencies(Archive *fout) if (g_verbose) write_msg(NULL, "reading dependency data\n"); - /* Make sure we are in proper schema */ - selectSourceSchema(fout, "pg_catalog"); - query = createPQExpBuffer(); /* @@ -15693,50 +15392,14 @@ findDumpableDependencies(ArchiveHandle *AH, DumpableObject *dobj, } -/* - * selectSourceSchema - make the specified schema the active search path - * in the source database. - * - * NB: pg_catalog is explicitly searched after the specified schema; - * so user names are only qualified if they are cross-schema references, - * and system names are only qualified if they conflict with a user name - * in the current schema. - * - * Whenever the selected schema is not pg_catalog, be careful to qualify - * references to system catalogs and types in our emitted commands! - * - * This function is called only from selectSourceSchemaOnAH and - * selectSourceSchema. - */ -static void -selectSourceSchema(Archive *fout, const char *schemaName) -{ - PQExpBuffer query; - - /* This is checked by the callers already */ - Assert(schemaName != NULL && *schemaName != '\0'); - - /* Not relevant if fetching from pre-7.3 DB */ - if (fout->remoteVersion < 70300) - return; - - query = createPQExpBuffer(); - appendPQExpBuffer(query, "SET search_path = %s", - fmtId(schemaName)); - if (strcmp(schemaName, "pg_catalog") != 0) - appendPQExpBufferStr(query, ", pg_catalog"); - - ExecuteSqlStatement(fout, query->data); - - destroyPQExpBuffer(query); -} - /* * getFormattedTypeName - retrieve a nicely-formatted type name for the - * given type name. + * given type OID. * - * NB: in 7.3 and up the result may depend on the currently-selected - * schema; this is why we don't try to cache the names. + * This does not guarantee to schema-qualify the output, so it should not + * be used to create the target object name for CREATE or ALTER commands. + * + * TODO: there might be some value in caching the results. */ static char * getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts) diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index f0408db00d7..99d10f0c059 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -51,9 +51,10 @@ static void dumpDatabases(PGconn *conn); static void dumpTimestamp(char *msg); static int runPgDump(const char *dbname); -static void buildShSecLabels(PGconn *conn, const char *catalog_name, - uint32 objectId, PQExpBuffer buffer, - const char *target, const char *objname); +static void buildShSecLabels(PGconn *conn, + const char *catalog_name, Oid objectId, + const char *objtype, const char *objname, + PQExpBuffer buffer); static PGconn *connectDatabase(const char *dbname, const char *connstr, const char *pghost, const char *pgport, const char *pguser, enum trivalue prompt_password, bool fail_on_error); static char *constructConnStr(const char **keywords, const char **values); @@ -835,7 +836,8 @@ dumpRoles(PGconn *conn) if (!no_security_labels && server_version >= 90200) buildShSecLabels(conn, "pg_authid", auth_oid, - buf, "ROLE", rolename); + "ROLE", rolename, + buf); fprintf(OPF, "%s", buf->data); } @@ -1070,7 +1072,7 @@ dumpTablespaces(PGconn *conn) for (i = 0; i < PQntuples(res); i++) { PQExpBuffer buf = createPQExpBuffer(); - uint32 spcoid = atooid(PQgetvalue(res, i, 0)); + Oid spcoid = atooid(PQgetvalue(res, i, 0)); char *spcname = PQgetvalue(res, i, 1); char *spcowner = PQgetvalue(res, i, 2); char *spclocation = PQgetvalue(res, i, 3); @@ -1094,11 +1096,12 @@ dumpTablespaces(PGconn *conn) fspcname, spcoptions); if (!skip_acls && - !buildACLCommands(fspcname, NULL, "TABLESPACE", spcacl, spcowner, + !buildACLCommands(fspcname, NULL, NULL, "TABLESPACE", + spcacl, spcowner, "", server_version, buf)) { fprintf(stderr, _("%s: could not parse ACL list (%s) for tablespace \"%s\"\n"), - progname, spcacl, fspcname); + progname, spcacl, spcname); PQfinish(conn); exit_nicely(1); } @@ -1112,7 +1115,8 @@ dumpTablespaces(PGconn *conn) if (!no_security_labels && server_version >= 90200) buildShSecLabels(conn, "pg_tablespace", spcoid, - buf, "TABLESPACE", fspcname); + "TABLESPACE", spcname, + buf); fprintf(OPF, "%s", buf->data); @@ -1429,7 +1433,7 @@ dumpCreateDB(PGconn *conn) } if (!skip_acls && - !buildACLCommands(fdbname, NULL, "DATABASE", dbacl, dbowner, + !buildACLCommands(fdbname, NULL, NULL, "DATABASE", dbacl, dbowner, "", server_version, buf)) { fprintf(stderr, _("%s: could not parse ACL list (%s) for database \"%s\"\n"), @@ -1739,19 +1743,23 @@ runPgDump(const char *dbname) * * Build SECURITY LABEL command(s) for an shared object * - * The caller has to provide object type and identifier to select security - * labels from pg_seclabels system view. + * The caller has to provide object type and identity in two separate formats: + * catalog_name (e.g., "pg_database") and object OID, as well as + * type name (e.g., "DATABASE") and object name (not pre-quoted). + * + * The command(s) are appended to "buffer". */ static void -buildShSecLabels(PGconn *conn, const char *catalog_name, uint32 objectId, - PQExpBuffer buffer, const char *target, const char *objname) +buildShSecLabels(PGconn *conn, const char *catalog_name, Oid objectId, + const char *objtype, const char *objname, + PQExpBuffer buffer) { PQExpBuffer sql = createPQExpBuffer(); PGresult *res; buildShSecLabelQuery(conn, catalog_name, objectId, sql); res = executeQuery(conn, sql->data); - emitShSecLabels(conn, res, buffer, target, objname); + emitShSecLabels(conn, res, buffer, objtype, objname); PQclear(res); destroyPQExpBuffer(sql); diff --git a/src/test/regress/expected/collate.linux.utf8.out b/src/test/regress/expected/collate.linux.utf8.out index 495e4ad4488..1e435ce44a0 100644 --- a/src/test/regress/expected/collate.linux.utf8.out +++ b/src/test/regress/expected/collate.linux.utf8.out @@ -943,12 +943,12 @@ ERROR: collations are not supported by type integer LINE 1: ...ATE INDEX collate_test1_idx6 ON collate_test1 ((a COLLATE "C... ^ SELECT relname, pg_get_indexdef(oid) FROM pg_class WHERE relname LIKE 'collate_test%_idx%' ORDER BY 1; - relname | pg_get_indexdef ---------------------+----------------------------------------------------------------------------------------------------- - collate_test1_idx1 | CREATE INDEX collate_test1_idx1 ON collate_test1 USING btree (b) - collate_test1_idx2 | CREATE INDEX collate_test1_idx2 ON collate_test1 USING btree (b COLLATE "C") - collate_test1_idx3 | CREATE INDEX collate_test1_idx3 ON collate_test1 USING btree (b COLLATE "C") - collate_test1_idx4 | CREATE INDEX collate_test1_idx4 ON collate_test1 USING btree (((b || 'foo'::text)) COLLATE "POSIX") + relname | pg_get_indexdef +--------------------+------------------------------------------------------------------------------------------------------------ + collate_test1_idx1 | CREATE INDEX collate_test1_idx1 ON public.collate_test1 USING btree (b) + collate_test1_idx2 | CREATE INDEX collate_test1_idx2 ON public.collate_test1 USING btree (b COLLATE "C") + collate_test1_idx3 | CREATE INDEX collate_test1_idx3 ON public.collate_test1 USING btree (b COLLATE "C") + collate_test1_idx4 | CREATE INDEX collate_test1_idx4 ON public.collate_test1 USING btree (((b || 'foo'::text)) COLLATE "POSIX") (4 rows) -- schema manipulation commands diff --git a/src/test/regress/expected/collate.out b/src/test/regress/expected/collate.out index 91d574dbe4c..49a8561e17c 100644 --- a/src/test/regress/expected/collate.out +++ b/src/test/regress/expected/collate.out @@ -572,12 +572,12 @@ ERROR: collations are not supported by type integer LINE 1: ...ATE INDEX collate_test1_idx6 ON collate_test1 ((a COLLATE "P... ^ SELECT relname, pg_get_indexdef(oid) FROM pg_class WHERE relname LIKE 'collate_test%_idx%' ORDER BY 1; - relname | pg_get_indexdef ---------------------+----------------------------------------------------------------------------------------------------- - collate_test1_idx1 | CREATE INDEX collate_test1_idx1 ON collate_test1 USING btree (b) - collate_test1_idx2 | CREATE INDEX collate_test1_idx2 ON collate_test1 USING btree (b COLLATE "POSIX") - collate_test1_idx3 | CREATE INDEX collate_test1_idx3 ON collate_test1 USING btree (b COLLATE "POSIX") - collate_test1_idx4 | CREATE INDEX collate_test1_idx4 ON collate_test1 USING btree (((b || 'foo'::text)) COLLATE "POSIX") + relname | pg_get_indexdef +--------------------+------------------------------------------------------------------------------------------------------------------- + collate_test1_idx1 | CREATE INDEX collate_test1_idx1 ON collate_tests.collate_test1 USING btree (b) + collate_test1_idx2 | CREATE INDEX collate_test1_idx2 ON collate_tests.collate_test1 USING btree (b COLLATE "POSIX") + collate_test1_idx3 | CREATE INDEX collate_test1_idx3 ON collate_tests.collate_test1 USING btree (b COLLATE "POSIX") + collate_test1_idx4 | CREATE INDEX collate_test1_idx4 ON collate_tests.collate_test1 USING btree (((b || 'foo'::text)) COLLATE "POSIX") (4 rows) -- foreign keys diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 0885e1c3560..78435fe9fa8 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -2169,103 +2169,103 @@ tvvmv| SELECT tvvm.grandtot SELECT tablename, rulename, definition FROM pg_rules ORDER BY tablename, rulename; pg_settings|pg_settings_n|CREATE RULE pg_settings_n AS - ON UPDATE TO pg_settings DO INSTEAD NOTHING; + ON UPDATE TO pg_catalog.pg_settings DO INSTEAD NOTHING; pg_settings|pg_settings_u|CREATE RULE pg_settings_u AS - ON UPDATE TO pg_settings + ON UPDATE TO pg_catalog.pg_settings WHERE (new.name = old.name) DO SELECT set_config(old.name, new.setting, false) AS set_config; rtest_emp|rtest_emp_del|CREATE RULE rtest_emp_del AS - ON DELETE TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, action, newsal, oldsal) + ON DELETE TO public.rtest_emp DO INSERT INTO rtest_emplog (ename, who, action, newsal, oldsal) VALUES (old.ename, "current_user"(), 'fired'::bpchar, '$0.00'::money, old.salary); rtest_emp|rtest_emp_ins|CREATE RULE rtest_emp_ins AS - ON INSERT TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, action, newsal, oldsal) + ON INSERT TO public.rtest_emp DO INSERT INTO rtest_emplog (ename, who, action, newsal, oldsal) VALUES (new.ename, "current_user"(), 'hired'::bpchar, new.salary, '$0.00'::money); rtest_emp|rtest_emp_upd|CREATE RULE rtest_emp_upd AS - ON UPDATE TO rtest_emp + ON UPDATE TO public.rtest_emp WHERE (new.salary <> old.salary) DO INSERT INTO rtest_emplog (ename, who, action, newsal, oldsal) VALUES (new.ename, "current_user"(), 'honored'::bpchar, new.salary, old.salary); rtest_nothn1|rtest_nothn_r1|CREATE RULE rtest_nothn_r1 AS - ON INSERT TO rtest_nothn1 + ON INSERT TO public.rtest_nothn1 WHERE ((new.a >= 10) AND (new.a < 20)) DO INSTEAD NOTHING; rtest_nothn1|rtest_nothn_r2|CREATE RULE rtest_nothn_r2 AS - ON INSERT TO rtest_nothn1 + ON INSERT TO public.rtest_nothn1 WHERE ((new.a >= 30) AND (new.a < 40)) DO INSTEAD NOTHING; rtest_nothn2|rtest_nothn_r3|CREATE RULE rtest_nothn_r3 AS - ON INSERT TO rtest_nothn2 + ON INSERT TO public.rtest_nothn2 WHERE (new.a >= 100) DO INSTEAD INSERT INTO rtest_nothn3 (a, b) VALUES (new.a, new.b); rtest_nothn2|rtest_nothn_r4|CREATE RULE rtest_nothn_r4 AS - ON INSERT TO rtest_nothn2 DO INSTEAD NOTHING; + ON INSERT TO public.rtest_nothn2 DO INSTEAD NOTHING; rtest_order1|rtest_order_r1|CREATE RULE rtest_order_r1 AS - ON INSERT TO rtest_order1 DO INSTEAD INSERT INTO rtest_order2 (a, b, c) + ON INSERT TO public.rtest_order1 DO INSTEAD INSERT INTO rtest_order2 (a, b, c) VALUES (new.a, nextval('rtest_seq'::regclass), 'rule 1 - this should run 1st'::text); rtest_order1|rtest_order_r2|CREATE RULE rtest_order_r2 AS - ON INSERT TO rtest_order1 DO INSERT INTO rtest_order2 (a, b, c) + ON INSERT TO public.rtest_order1 DO INSERT INTO rtest_order2 (a, b, c) VALUES (new.a, nextval('rtest_seq'::regclass), 'rule 2 - this should run 2nd'::text); rtest_order1|rtest_order_r3|CREATE RULE rtest_order_r3 AS - ON INSERT TO rtest_order1 DO INSTEAD INSERT INTO rtest_order2 (a, b, c) + ON INSERT TO public.rtest_order1 DO INSTEAD INSERT INTO rtest_order2 (a, b, c) VALUES (new.a, nextval('rtest_seq'::regclass), 'rule 3 - this should run 3rd'::text); rtest_order1|rtest_order_r4|CREATE RULE rtest_order_r4 AS - ON INSERT TO rtest_order1 + ON INSERT TO public.rtest_order1 WHERE (new.a < 100) DO INSTEAD INSERT INTO rtest_order2 (a, b, c) VALUES (new.a, nextval('rtest_seq'::regclass), 'rule 4 - this should run 4th'::text); rtest_person|rtest_pers_del|CREATE RULE rtest_pers_del AS - ON DELETE TO rtest_person DO DELETE FROM rtest_admin + ON DELETE TO public.rtest_person DO DELETE FROM rtest_admin WHERE (rtest_admin.pname = old.pname); rtest_person|rtest_pers_upd|CREATE RULE rtest_pers_upd AS - ON UPDATE TO rtest_person DO UPDATE rtest_admin SET pname = new.pname + ON UPDATE TO public.rtest_person DO UPDATE rtest_admin SET pname = new.pname WHERE (rtest_admin.pname = old.pname); rtest_system|rtest_sys_del|CREATE RULE rtest_sys_del AS - ON DELETE TO rtest_system DO ( DELETE FROM rtest_interface + ON DELETE TO public.rtest_system DO ( DELETE FROM rtest_interface WHERE (rtest_interface.sysname = old.sysname); DELETE FROM rtest_admin WHERE (rtest_admin.sysname = old.sysname); ); rtest_system|rtest_sys_upd|CREATE RULE rtest_sys_upd AS - ON UPDATE TO rtest_system DO ( UPDATE rtest_interface SET sysname = new.sysname + ON UPDATE TO public.rtest_system DO ( UPDATE rtest_interface SET sysname = new.sysname WHERE (rtest_interface.sysname = old.sysname); UPDATE rtest_admin SET sysname = new.sysname WHERE (rtest_admin.sysname = old.sysname); ); rtest_t4|rtest_t4_ins1|CREATE RULE rtest_t4_ins1 AS - ON INSERT TO rtest_t4 + ON INSERT TO public.rtest_t4 WHERE ((new.a >= 10) AND (new.a < 20)) DO INSTEAD INSERT INTO rtest_t5 (a, b) VALUES (new.a, new.b); rtest_t4|rtest_t4_ins2|CREATE RULE rtest_t4_ins2 AS - ON INSERT TO rtest_t4 + ON INSERT TO public.rtest_t4 WHERE ((new.a >= 20) AND (new.a < 30)) DO INSERT INTO rtest_t6 (a, b) VALUES (new.a, new.b); rtest_t5|rtest_t5_ins|CREATE RULE rtest_t5_ins AS - ON INSERT TO rtest_t5 + ON INSERT TO public.rtest_t5 WHERE (new.a > 15) DO INSERT INTO rtest_t7 (a, b) VALUES (new.a, new.b); rtest_t6|rtest_t6_ins|CREATE RULE rtest_t6_ins AS - ON INSERT TO rtest_t6 + ON INSERT TO public.rtest_t6 WHERE (new.a > 25) DO INSTEAD INSERT INTO rtest_t8 (a, b) VALUES (new.a, new.b); rtest_v1|rtest_v1_del|CREATE RULE rtest_v1_del AS - ON DELETE TO rtest_v1 DO INSTEAD DELETE FROM rtest_t1 + ON DELETE TO public.rtest_v1 DO INSTEAD DELETE FROM rtest_t1 WHERE (rtest_t1.a = old.a); rtest_v1|rtest_v1_ins|CREATE RULE rtest_v1_ins AS - ON INSERT TO rtest_v1 DO INSTEAD INSERT INTO rtest_t1 (a, b) + ON INSERT TO public.rtest_v1 DO INSTEAD INSERT INTO rtest_t1 (a, b) VALUES (new.a, new.b); rtest_v1|rtest_v1_upd|CREATE RULE rtest_v1_upd AS - ON UPDATE TO rtest_v1 DO INSTEAD UPDATE rtest_t1 SET a = new.a, b = new.b + ON UPDATE TO public.rtest_v1 DO INSTEAD UPDATE rtest_t1 SET a = new.a, b = new.b WHERE (rtest_t1.a = old.a); shoelace|shoelace_del|CREATE RULE shoelace_del AS - ON DELETE TO shoelace DO INSTEAD DELETE FROM shoelace_data + ON DELETE TO public.shoelace DO INSTEAD DELETE FROM shoelace_data WHERE (shoelace_data.sl_name = old.sl_name); shoelace|shoelace_ins|CREATE RULE shoelace_ins AS - ON INSERT TO shoelace DO INSTEAD INSERT INTO shoelace_data (sl_name, sl_avail, sl_color, sl_len, sl_unit) + ON INSERT TO public.shoelace DO INSTEAD INSERT INTO shoelace_data (sl_name, sl_avail, sl_color, sl_len, sl_unit) VALUES (new.sl_name, new.sl_avail, new.sl_color, new.sl_len, new.sl_unit); shoelace|shoelace_upd|CREATE RULE shoelace_upd AS - ON UPDATE TO shoelace DO INSTEAD UPDATE shoelace_data SET sl_name = new.sl_name, sl_avail = new.sl_avail, sl_color = new.sl_color, sl_len = new.sl_len, sl_unit = new.sl_unit + ON UPDATE TO public.shoelace DO INSTEAD UPDATE shoelace_data SET sl_name = new.sl_name, sl_avail = new.sl_avail, sl_color = new.sl_color, sl_len = new.sl_len, sl_unit = new.sl_unit WHERE (shoelace_data.sl_name = old.sl_name); shoelace_data|log_shoelace|CREATE RULE log_shoelace AS - ON UPDATE TO shoelace_data + ON UPDATE TO public.shoelace_data WHERE (new.sl_avail <> old.sl_avail) DO INSERT INTO shoelace_log (sl_name, sl_avail, log_who, log_when) VALUES (new.sl_name, new.sl_avail, 'Al Bundy'::name, 'Thu Jan 01 00:00:00 1970'::timestamp without time zone); shoelace_ok|shoelace_ok_ins|CREATE RULE shoelace_ok_ins AS - ON INSERT TO shoelace_ok DO INSTEAD UPDATE shoelace SET sl_avail = (shoelace.sl_avail + new.ok_quant) + ON INSERT TO public.shoelace_ok DO INSTEAD UPDATE shoelace SET sl_avail = (shoelace.sl_avail + new.ok_quant) WHERE (shoelace.sl_name = new.ok_name); -- restore normal output mode \a\t diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out index f1a5fde107d..6706021051a 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -381,9 +381,9 @@ SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'main_table' (1 row) SELECT pg_get_triggerdef(oid, false) FROM pg_trigger WHERE tgrelid = 'main_table'::regclass AND tgname = 'modified_a'; - pg_get_triggerdef ----------------------------------------------------------------------------------------------------------------------------------------------- - CREATE TRIGGER modified_a BEFORE UPDATE OF a ON main_table FOR EACH ROW WHEN ((old.a <> new.a)) EXECUTE PROCEDURE trigger_func('modified_a') + pg_get_triggerdef +----------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE TRIGGER modified_a BEFORE UPDATE OF a ON public.main_table FOR EACH ROW WHEN ((old.a <> new.a)) EXECUTE PROCEDURE trigger_func('modified_a') (1 row) SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'main_table'::regclass AND tgname = 'modified_any'; @@ -411,9 +411,9 @@ FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('before_upd_a_stmt'); CREATE TRIGGER after_upd_b_stmt_trig AFTER UPDATE OF b ON main_table FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('after_upd_b_stmt'); SELECT pg_get_triggerdef(oid) FROM pg_trigger WHERE tgrelid = 'main_table'::regclass AND tgname = 'after_upd_a_b_row_trig'; - pg_get_triggerdef -------------------------------------------------------------------------------------------------------------------------------------------- - CREATE TRIGGER after_upd_a_b_row_trig AFTER UPDATE OF a, b ON main_table FOR EACH ROW EXECUTE PROCEDURE trigger_func('after_upd_a_b_row') + pg_get_triggerdef +-------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE TRIGGER after_upd_a_b_row_trig AFTER UPDATE OF a, b ON public.main_table FOR EACH ROW EXECUTE PROCEDURE trigger_func('after_upd_a_b_row') (1 row) UPDATE main_table SET a = 50;