On Fri, Nov 06, 2020 at 11:18:35PM -0300, Alvaro Herrera wrote: > On 2020-Oct-24, Justin Pryzby wrote: > > > On Fri, Oct 23, 2020 at 12:29:40AM -0500, Justin Pryzby wrote: > > > > Now that I look, it seems like this is calling PQexec(), which sends a > > > single, > > > "simple" libpq message with: > > > |CREATE TABLE ..; ALTER TABLE .. ATTACH PARTITION; > > > ..which is transactional, so when the 2nd command fails, the CREATE is > > > rolled back. > > > https://www.postgresql.org/docs/9.5/libpq-exec.html#LIBPQ-EXEC-MAIN > > > > The easy fix is to add an explicit begin/commit. > > Hmm, I think this throws a warning when used with "pg_restore -1", > right? I don't think that's sufficient reason to discard the idea, but > it be better to find some other way.
Worse, right ? It'd commit in the middle and then continue outside of a txn. I guess there's no test case for this :( > I have no ideas ATM :-( 1. Maybe pg_restore ExecuteSqlCommandBuf() should (always?) call ExecuteSimpleCommands() instead of ExecuteSqlCommand(). It doesn't seem to break anything (although that surprised me). 2. Otherwise, the createStmt would need to be split into a createStmt2 or a char *createStmt[], which I think would then require changing the output format. It seems clearly better to keep the sql commands split up initially than to reverse engineer them during restore. I tried using \x01 to separate commands, and strtok to split them to run them individually. But that breaks the pg_dumpall tests. As an experiment, I used \x00, which is somewhat invasive but actually works. Obviously patching pg_dump will affect only future backups, and the pg_restore patch allows independently restoring parent tables in existing dumps. -- Justin
>From f1ce24cb79dd4cdcd93d602ddede711efff8227e Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryz...@telsasoft.com> Date: Thu, 19 Nov 2020 19:10:02 -0600 Subject: [PATCH v2 1/2] pg_restore: parse and run separately SQL commands If pg_dump emits multiple DDL commands, run them in separate transactions, to avoid failures in the 2ndary (ALTER) commands from rolling back the first, primary (CREATE) command. XXX: is there any performance benefit possible if can we call ExecuteSqlCommand() in some cases? I don't think it matters much for DDL. --- src/bin/pg_dump/pg_backup_db.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c index 5ba43441f5..1565155e20 100644 --- a/src/bin/pg_dump/pg_backup_db.c +++ b/src/bin/pg_dump/pg_backup_db.c @@ -477,21 +477,20 @@ ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen) else { /* - * General SQL commands; we assume that commands will not be split - * across calls. + * General SQL commands * * In most cases the data passed to us will be a null-terminated * string, but if it's not, we have to add a trailing null. */ if (buf[bufLen] == '\0') - ExecuteSqlCommand(AH, buf, "could not execute query"); + ExecuteSimpleCommands(AH, buf, bufLen); else { char *str = (char *) pg_malloc(bufLen + 1); memcpy(str, buf, bufLen); str[bufLen] = '\0'; - ExecuteSqlCommand(AH, str, "could not execute query"); + ExecuteSimpleCommands(AH, buf, bufLen); free(str); } } -- 2.17.0
>From c6ec806b245a08c47f6e1d7c4909a532f49e69e1 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryz...@telsasoft.com> Date: Sat, 24 Oct 2020 14:51:18 -0500 Subject: [PATCH v2 2/2] pg_dump: Allow child partitions to be independently restored ..even if the parent doesn't exist, or has missing/incompatible columns This seems to have been intended by commit 33a53130a --- src/bin/pg_dump/pg_backup_archiver.c | 50 +++++++++++++++++-- src/bin/pg_dump/pg_dump.c | 72 ++++++++++++++++++++++++++-- src/bin/pg_dump/t/002_pg_dump.pl | 2 +- 3 files changed, 117 insertions(+), 7 deletions(-) diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index b961a24b36..becf9ec34d 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -143,6 +143,8 @@ static void inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te); static void StrictNamesCheck(RestoreOptions *ropt); +static size_t WriteStrs(ArchiveHandle *AH, const char *c); + /* * Allocate a new DumpOptions block containing all default values. @@ -1081,9 +1083,20 @@ ArchiveEntry(Archive *AHX, CatalogId catalogId, DumpId dumpId, newToc->tableam = opts->tableam ? pg_strdup(opts->tableam) : NULL; newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL; newToc->desc = pg_strdup(opts->description); - newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL; newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL; newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL; + if (opts->createStmt == NULL) + newToc->defn = NULL; + else + { + const char *p = opts->createStmt; + size_t len; + for (; *p != 0;) + p += 1 + strlen(p); + len = p - opts->createStmt + 1; + newToc->defn = palloc(len); + memcpy(newToc->defn, opts->createStmt, len); + } if (opts->nDeps > 0) { @@ -2037,6 +2050,29 @@ WriteStr(ArchiveHandle *AH, const char *c) return res; } +size_t +WriteStrs(ArchiveHandle *AH, const char *c) +{ + size_t res; + + if (c) + { + int len; + const char *s = c; + for ( ; *s; ) + s += 1 + strlen(s); + len = s - c + 1; + + res = WriteInt(AH, len); + AH->WriteBufPtr(AH, c, len); + res += len; + } + else + res = WriteInt(AH, -1); + + return res; +} + char * ReadStr(ArchiveHandle *AH) { @@ -2522,7 +2558,7 @@ WriteToc(ArchiveHandle *AH) WriteStr(AH, te->tag); WriteStr(AH, te->desc); WriteInt(AH, te->section); - WriteStr(AH, te->defn); + WriteStrs(AH, te->defn); WriteStr(AH, te->dropStmt); WriteStr(AH, te->copyStmt); WriteStr(AH, te->namespace); @@ -3607,7 +3643,15 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData) else { if (te->defn && strlen(te->defn) > 0) - ahprintf(AH, "%s\n\n", te->defn); + { + char *p = te->defn; + for (; *p;) + { + ahprintf(AH, "%s\n", p); + p += 1 + strlen(p); + } + ahprintf(AH, "\n"); + } } /* diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index dc1d41dd8d..7c8af9b19d 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -2362,6 +2362,7 @@ refreshMatViewData(Archive *fout, TableDataInfo *tdinfo) appendPQExpBuffer(q, "REFRESH MATERIALIZED VIEW %s;\n", fmtQualifiedDumpable(tbinfo)); + appendPQExpBufferChar(q, '\x00'); if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA) ArchiveEntry(fout, @@ -2925,6 +2926,7 @@ dumpDatabase(Archive *fout) appendPQExpBuffer(creaQry, " TABLESPACE = %s", fmtId(tablespace)); appendPQExpBufferStr(creaQry, ";\n"); + appendPQExpBufferChar(creaQry, '\x00'); appendPQExpBuffer(delQry, "DROP DATABASE %s;\n", qdatname); @@ -2965,6 +2967,7 @@ dumpDatabase(Archive *fout) appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", qdatname); appendStringLiteralAH(dbQry, comment, fout); appendPQExpBufferStr(dbQry, ";\n"); + appendPQExpBufferChar(dbQry, '\x00'); ArchiveEntry(fout, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = labelq->data, @@ -2994,6 +2997,7 @@ dumpDatabase(Archive *fout) shres = ExecuteSqlQuery(fout, seclabelQry->data, PGRES_TUPLES_OK); resetPQExpBuffer(seclabelQry); emitShSecLabels(conn, shres, seclabelQry, "DATABASE", datname); + appendPQExpBufferChar(seclabelQry, '\x00'); if (seclabelQry->len > 0) ArchiveEntry(fout, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = labelq->data, @@ -3064,6 +3068,7 @@ dumpDatabase(Archive *fout) frozenxid, minmxid); appendStringLiteralAH(creaQry, datname, fout); appendPQExpBufferStr(creaQry, ";\n"); + appendPQExpBufferChar(creaQry, '\x00'); } if (creaQry->len > 0) @@ -3114,6 +3119,7 @@ dumpDatabase(Archive *fout) atooid(PQgetvalue(lo_res, 0, i_relfrozenxid)), atooid(PQgetvalue(lo_res, 0, i_relminmxid)), LargeObjectRelationId); + appendPQExpBufferChar(loOutQry, '\x00'); ArchiveEntry(fout, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = "pg_largeobject", .description = "pg_largeobject", @@ -3221,6 +3227,7 @@ dumpEncoding(Archive *AH) appendPQExpBufferStr(qry, "SET client_encoding = "); appendStringLiteralAH(qry, encname, AH); appendPQExpBufferStr(qry, ";\n"); + appendPQExpBufferChar(qry, '\x00'); ArchiveEntry(AH, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = "ENCODING", @@ -3246,6 +3253,7 @@ dumpStdStrings(Archive *AH) appendPQExpBuffer(qry, "SET standard_conforming_strings = '%s';\n", stdstrings); + appendPQExpBufferChar(qry, '\x00'); ArchiveEntry(AH, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = "STDSTRINGS", @@ -3298,6 +3306,7 @@ dumpSearchPath(Archive *AH) appendPQExpBufferStr(qry, "SELECT pg_catalog.set_config('search_path', "); appendStringLiteralAH(qry, path->data, AH); appendPQExpBufferStr(qry, ", false);\n"); + appendPQExpBufferChar(qry, '\x00'); pg_log_info("saving search_path = %s", path->data); @@ -3468,6 +3477,7 @@ dumpBlob(Archive *fout, BlobInfo *binfo) appendPQExpBuffer(cquery, "SELECT pg_catalog.lo_create('%s');\n", binfo->dobj.name); + appendPQExpBufferChar(cquery, '\x00'); appendPQExpBuffer(dquery, "SELECT pg_catalog.lo_unlink('%s');\n", @@ -3769,6 +3779,7 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo) appendPQExpBuffer(query, "ALTER TABLE %s ENABLE ROW LEVEL SECURITY;", fmtQualifiedDumpable(tbinfo)); + appendPQExpBufferChar(query, '\x00'); /* * We must emit the ROW SECURITY object's dependency on its table @@ -3828,6 +3839,7 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo) appendPQExpBuffer(query, " WITH CHECK (%s)", polinfo->polwithcheck); appendPQExpBufferStr(query, ";\n"); + appendPQExpBufferChar(query, '\x00'); appendPQExpBuffer(delqry, "DROP POLICY %s", fmtId(polinfo->polname)); appendPQExpBuffer(delqry, " ON %s;\n", fmtQualifiedDumpable(tbinfo)); @@ -4033,6 +4045,7 @@ dumpPublication(Archive *fout, PublicationInfo *pubinfo) appendPQExpBufferStr(query, ", publish_via_partition_root = true"); appendPQExpBufferStr(query, ");\n"); + appendPQExpBufferChar(query, '\x00'); ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = pubinfo->dobj.name, @@ -4172,6 +4185,7 @@ dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo) fmtId(pubrinfo->pubname)); appendPQExpBuffer(query, " %s;\n", fmtQualifiedDumpable(tbinfo)); + appendPQExpBufferChar(query, '\x00'); /* * There is no point in creating drop query as the drop is done by table @@ -4384,6 +4398,7 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo) appendPQExpBuffer(query, ", synchronous_commit = %s", fmtId(subinfo->subsynccommit)); appendPQExpBufferStr(query, ");\n"); + appendPQExpBufferChar(query, '\x00'); ArchiveEntry(fout, subinfo->dobj.catId, subinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = subinfo->dobj.name, @@ -9801,6 +9816,7 @@ dumpComment(Archive *fout, const char *type, const char *name, appendPQExpBuffer(query, "%s IS ", name); appendStringLiteralAH(query, comments->descr, fout); appendPQExpBufferStr(query, ";\n"); + appendPQExpBufferChar(query, '\x00'); appendPQExpBuffer(tag, "%s %s", type, name); @@ -9877,6 +9893,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo, fmtQualifiedDumpable(tbinfo)); appendStringLiteralAH(query, descr, fout); appendPQExpBufferStr(query, ";\n"); + appendPQExpBufferChar(query, '\x00'); ArchiveEntry(fout, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = tag->data, @@ -9902,6 +9919,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo, fmtId(tbinfo->attnames[objsubid - 1])); appendStringLiteralAH(query, descr, fout); appendPQExpBufferStr(query, ";\n"); + appendPQExpBufferChar(query, '\x00'); ArchiveEntry(fout, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = tag->data, @@ -10252,6 +10270,7 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo) appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname); appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname); + appendPQExpBufferChar(q, '\x00'); if (dopt->binary_upgrade) binary_upgrade_extension_member(q, &nspinfo->dobj, @@ -10392,6 +10411,7 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo) appendPQExpBufferStr(q, ");\n"); } + appendPQExpBufferChar(q, '\x00'); if (extinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, extinfo->dobj.catId, extinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = extinfo->dobj.name, @@ -10540,6 +10560,7 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo) "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tyinfo->dobj.name, @@ -10666,6 +10687,7 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo) "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tyinfo->dobj.name, @@ -10738,6 +10760,7 @@ dumpUndefinedType(Archive *fout, TypeInfo *tyinfo) "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tyinfo->dobj.name, @@ -11019,6 +11042,7 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo) "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tyinfo->dobj.name, @@ -11175,6 +11199,7 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo) "DOMAIN", qtypname, tyinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tyinfo->dobj.name, @@ -11396,6 +11421,7 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) "TYPE", qtypname, tyinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tyinfo->dobj.name, @@ -11531,6 +11557,7 @@ dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo) appendPQExpBuffer(query, "%s IS ", fmtId(attname)); appendStringLiteralAH(query, descr, fout); appendPQExpBufferStr(query, ";\n"); + appendPQExpBufferChar(query, '\x00'); ArchiveEntry(fout, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = target->data, @@ -11587,6 +11614,7 @@ dumpShellType(Archive *fout, ShellTypeInfo *stinfo) appendPQExpBuffer(q, "CREATE TYPE %s;\n", fmtQualifiedDumpable(stinfo)); + appendPQExpBufferChar(q, '\x00'); if (stinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = stinfo->dobj.name, @@ -11697,6 +11725,7 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) binary_upgrade_extension_member(defqry, &plang->dobj, "LANGUAGE", qlanname, NULL); + appendPQExpBufferChar(defqry, '\x00'); if (plang->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId, ARCHIVE_OPTS(.tag = plang->dobj.name, @@ -12318,6 +12347,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo) keyword, funcsig, finfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (finfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId, ARCHIVE_OPTS(.tag = funcsig_tag, @@ -12452,6 +12482,7 @@ dumpCast(Archive *fout, CastInfo *cast) binary_upgrade_extension_member(defqry, &cast->dobj, "CAST", castargs->data, NULL); + appendPQExpBufferChar(defqry, '\x00'); if (cast->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId, ARCHIVE_OPTS(.tag = labelq->data, @@ -12579,6 +12610,7 @@ dumpTransform(Archive *fout, TransformInfo *transform) binary_upgrade_extension_member(defqry, &transform->dobj, "TRANSFORM", transformargs->data, NULL); + appendPQExpBufferChar(defqry, '\x00'); if (transform->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, transform->dobj.catId, transform->dobj.dumpId, ARCHIVE_OPTS(.tag = labelq->data, @@ -12799,6 +12831,7 @@ dumpOpr(Archive *fout, OprInfo *oprinfo) "OPERATOR", oprid->data, oprinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (oprinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = oprinfo->dobj.name, @@ -12971,6 +13004,7 @@ dumpAccessMethod(Archive *fout, AccessMethodInfo *aminfo) binary_upgrade_extension_member(q, &aminfo->dobj, "ACCESS METHOD", qamname, NULL); + appendPQExpBufferChar(q, '\x00'); if (aminfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, aminfo->dobj.catId, aminfo->dobj.dumpId, ARCHIVE_OPTS(.tag = aminfo->dobj.name, @@ -13334,6 +13368,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo) "OPERATOR CLASS", nameusing->data, opcinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (opcinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = opcinfo->dobj.name, @@ -13600,6 +13635,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo) "OPERATOR FAMILY", nameusing->data, opfinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (opfinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = opfinfo->dobj.name, @@ -13732,6 +13768,7 @@ dumpCollation(Archive *fout, CollInfo *collinfo) "COLLATION", qcollname, collinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (collinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, collinfo->dobj.catId, collinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = collinfo->dobj.name, @@ -13826,6 +13863,7 @@ dumpConversion(Archive *fout, ConvInfo *convinfo) "CONVERSION", qconvname, convinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (convinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = convinfo->dobj.name, @@ -14200,6 +14238,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) "AGGREGATE", aggsig, agginfo->aggfn.dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId, @@ -14298,6 +14337,7 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo) "TEXT SEARCH PARSER", qprsname, prsinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (prsinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = prsinfo->dobj.name, @@ -14376,6 +14416,7 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo) "TEXT SEARCH DICTIONARY", qdictname, dictinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (dictinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = dictinfo->dobj.name, @@ -14436,6 +14477,7 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo) "TEXT SEARCH TEMPLATE", qtmplname, tmplinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (tmplinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tmplinfo->dobj.name, @@ -14554,6 +14596,7 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo) "TEXT SEARCH CONFIGURATION", qcfgname, cfginfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (cfginfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId, ARCHIVE_OPTS(.tag = cfginfo->dobj.name, @@ -14619,6 +14662,7 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo) "FOREIGN DATA WRAPPER", qfdwname, NULL); + appendPQExpBufferChar(q, '\x00'); if (fdwinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = fdwinfo->dobj.name, @@ -14708,6 +14752,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo) binary_upgrade_extension_member(q, &srvinfo->dobj, "SERVER", qsrvname, NULL); + appendPQExpBufferChar(q, '\x00'); if (srvinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = srvinfo->dobj.name, @@ -14825,6 +14870,7 @@ dumpUserMappings(Archive *fout, appendPQExpBuffer(tag, "USER MAPPING %s SERVER %s", usename, servername); + appendPQExpBufferChar(q, '\x00'); ArchiveEntry(fout, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = tag->data, .namespace = namespace, @@ -14901,6 +14947,7 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo) fatal("could not parse default ACL list (%s)", daclinfo->defaclacl); + appendPQExpBufferChar(q, '\x00'); if (daclinfo->dobj.dump & DUMP_COMPONENT_ACL) ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tag->data, @@ -15011,6 +15058,7 @@ dumpACL(Archive *fout, DumpId objDumpId, DumpId altDumpId, aclDumpId = createDumpId(); + appendPQExpBufferChar(sql, '\x00'); ArchiveEntry(fout, nilCatalogId, aclDumpId, ARCHIVE_OPTS(.tag = tag->data, .namespace = nspname, @@ -15103,6 +15151,7 @@ dumpSecLabel(Archive *fout, const char *type, const char *name, PQExpBuffer tag = createPQExpBuffer(); appendPQExpBuffer(tag, "%s %s", type, name); + appendPQExpBufferChar(query, '\x00'); ArchiveEntry(fout, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = tag->data, .namespace = namespace, @@ -15186,6 +15235,7 @@ dumpTableSecLabel(Archive *fout, TableInfo *tbinfo, const char *reltypename) resetPQExpBuffer(target); appendPQExpBuffer(target, "%s %s", reltypename, fmtId(tbinfo->dobj.name)); + appendPQExpBufferChar(query, '\x00'); ArchiveEntry(fout, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = target->data, .namespace = tbinfo->dobj.namespace->dobj.name, @@ -15917,12 +15967,12 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) PQExpBuffer result; result = createViewAsClause(fout, tbinfo); - appendPQExpBuffer(q, " AS\n%s\n WITH NO DATA;\n", - result->data); + appendPQExpBuffer(q, " AS\n%s\n WITH NO DATA;%c\n", + result->data, '\x00'); destroyPQExpBuffer(result); } else - appendPQExpBufferStr(q, ";\n"); + appendPQExpBuffer(q, ";%c\n", '\x00'); /* Materialized views can depend on extensions */ if (tbinfo->relkind == RELKIND_MATVIEW) @@ -16279,6 +16329,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) tbinfo->relkind == RELKIND_MATVIEW) tableam = tbinfo->amname; + appendPQExpBufferChar(q, '\x00'); ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tbinfo->dobj.name, .namespace = tbinfo->dobj.namespace->dobj.name, @@ -16360,6 +16411,7 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo) tag = psprintf("%s %s", tbinfo->dobj.name, tbinfo->attnames[adnum - 1]); + appendPQExpBufferChar(q, '\x00'); if (adinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, adinfo->dobj.catId, adinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tag, @@ -16523,6 +16575,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo) appendPQExpBuffer(delq, "DROP INDEX %s;\n", qqindxname); + appendPQExpBufferChar(q, '\x00'); if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = indxinfo->dobj.name, @@ -16544,6 +16597,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo) appendIndexCollationVersion(q, indxinfo, fout->encoding, dopt->coll_unknown, fout); + appendPQExpBufferChar(q, '\x00'); if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = indxinfo->dobj.name, @@ -16589,6 +16643,7 @@ dumpIndexAttach(Archive *fout, IndexAttachInfo *attachinfo) appendPQExpBuffer(q, "ATTACH PARTITION %s;\n", fmtQualifiedDumpable(attachinfo->partitionIdx)); + appendPQExpBufferChar(q, '\x00'); ArchiveEntry(fout, attachinfo->dobj.catId, attachinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = attachinfo->dobj.name, .namespace = attachinfo->dobj.namespace->dobj.name, @@ -16652,6 +16707,7 @@ dumpStatisticsExt(Archive *fout, StatsExtInfo *statsextinfo) appendPQExpBuffer(delq, "DROP STATISTICS %s;\n", fmtQualifiedDumpable(statsextinfo)); + appendPQExpBufferChar(q, '\x00'); if (statsextinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, statsextinfo->dobj.catId, statsextinfo->dobj.dumpId, @@ -16822,6 +16878,7 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo) tag = psprintf("%s %s", tbinfo->dobj.name, coninfo->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tag, @@ -16862,6 +16919,7 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo) tag = psprintf("%s %s", tbinfo->dobj.name, coninfo->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tag, @@ -16893,6 +16951,7 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo) tag = psprintf("%s %s", tbinfo->dobj.name, coninfo->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tag, @@ -16925,6 +16984,7 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo) tag = psprintf("%s %s", tyinfo->dobj.name, coninfo->dobj.name); + appendPQExpBufferChar(q, '\x00'); if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tag, @@ -17201,6 +17261,7 @@ dumpSequence(Archive *fout, TableInfo *tbinfo) "SEQUENCE", qseqname, tbinfo->dobj.namespace->dobj.name); + appendPQExpBufferChar(query, '\x00'); if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tbinfo->dobj.name, @@ -17241,6 +17302,7 @@ dumpSequence(Archive *fout, TableInfo *tbinfo) appendPQExpBuffer(query, ".%s;\n", fmtId(owning_tab->attnames[tbinfo->owning_col - 1])); + appendPQExpBufferChar(query, '\x00'); if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = tbinfo->dobj.name, @@ -17309,6 +17371,7 @@ dumpSequenceData(Archive *fout, TableDataInfo *tdinfo) appendPQExpBuffer(query, ", %s, %s);\n", last, (called ? "true" : "false")); + appendPQExpBufferChar(query, '\x00'); if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA) ArchiveEntry(fout, nilCatalogId, createDumpId(), ARCHIVE_OPTS(.tag = tbinfo->dobj.name, @@ -17516,6 +17579,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo) tag = psprintf("%s %s", tbinfo->dobj.name, tginfo->dobj.name); + appendPQExpBufferChar(query, '\x00'); if (tginfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tag, @@ -17605,6 +17669,7 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo) binary_upgrade_extension_member(query, &evtinfo->dobj, "EVENT TRIGGER", qevtname, NULL); + appendPQExpBufferChar(query, '\x00'); if (evtinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, evtinfo->dobj.catId, evtinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = evtinfo->dobj.name, @@ -17763,6 +17828,7 @@ dumpRule(Archive *fout, RuleInfo *rinfo) tag = psprintf("%s %s", tbinfo->dobj.name, rinfo->dobj.name); + appendPQExpBufferChar(cmd, '\x00'); if (rinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tag, diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl index ec63662060..9eab65e4f3 100644 --- a/src/bin/pg_dump/t/002_pg_dump.pl +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -2351,7 +2351,7 @@ my %tests = ( \s+\QCONSTRAINT measurement_peaktemp_check CHECK ((peaktemp >= '-460'::integer))\E\n \)\n \QPARTITION BY RANGE (logdate);\E\n - /xm, + /xm, # XXX: how to test that it's in a separate txn ? like => { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, unlike => { -- 2.17.0