pg.ddx.io pgsql-hackers@postgresql.org mailing list archive
help / color / mirror / Atom feed From: Justin Pryzby <pryzby@telsasoft.com>
To: Alvaro Herrera <alvherre@alvh.no-ip.org>
Cc: David Rowley <drowley@postgresql.org>
Cc: pgsql-hackers@lists.postgresql.org
Subject: Re: pg_dump, ATTACH, and independently restorable child partitions
Date: Fri, 20 Nov 2020 09:20:55 -0600
Message-ID: <20201120152055.GF24784@telsasoft.com> (raw )
In-Reply-To: <20201107021835.GA13348@alvherre.pgsql >
References: <20201024195949.GL9241@telsasoft.com >
<20201107021835.GA13348@alvherre.pgsql >
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
Attachments: download all (2 files, .tar.gz)
v2-0001-pg_restore-parse-and-run-separately-SQL-commands.patch (text/x-diff, 1.5K) download
From f1ce24cb79dd4cdcd93d602ddede711efff8227e Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@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
v2-0002-pg_dump-Allow-child-partitions-to-be-independentl.patch (text/x-diff, 26.4K) download
From c6ec806b245a08c47f6e1d7c4909a532f49e69e1 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@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
view thread (11+ messages) latest in thread
Message-ID: <20201120152055.GF24784@telsasoft.com>
Permalink: ../20201120152055.GF24784@telsasoft.com/
Also on: postgresql.org/message-id/20201120152055.GF24784@telsasoft.com
copy link · copy postgr.es · copy git am
reply Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: pryzby@telsasoft.com, alvherre@alvh.no-ip.org, drowley@postgresql.org, pgsql-hackers@lists.postgresql.org
Subject: Re: pg_dump, ATTACH, and independently restorable child partitions
In-Reply-To: <20201120152055.GF24784@telsasoft.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox