Skip to content

Commit 5a191f6

Browse files
committed
Make pg_dump emit ATTACH PARTITION instead of PARTITION OF
Using PARTITION OF can result in column ordering being changed from the database being dumped, if the partition uses a column layout different from the parent's. It's not pg_dump's job to editorialize on table definitions, so this is not acceptable; back-patch all the way back to pg10, where partitioned tables where introduced. This change also ensures that partitions end up in the correct tablespace, if different from the parent's; this is an oversight in ca41030 (in pg12 only). Partitioned indexes (in pg11) don't have this problem, because they're already created as independent indexes and attached to their parents afterwards. This change also has the advantage that the partition is restorable from the dump (as a standalone table) even if its parent table isn't restored. Author: David Rowley Reviewed-by: Álvaro Herrera Discussion: https://postgr.es/m/CAKJS1f_1c260nOt_vBJ067AZ3JXptXVRohDVMLEBmudX1YEx-A@mail.gmail.com Discussion: https://postgr.es/m/20190423185007.GA27954@alvherre.pgsql
1 parent a0bbd01 commit 5a191f6

File tree

2 files changed

+58
-78
lines changed

2 files changed

+58
-78
lines changed

src/bin/pg_dump/pg_dump.c

Lines changed: 51 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -8188,9 +8188,12 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
81888188
* Normally this is always true, but it's false for dropped columns, as well
81898189
* as those that were inherited without any local definition. (If we print
81908190
* such a column it will mistakenly get pg_attribute.attislocal set to true.)
8191-
* However, in binary_upgrade mode, we must print all such columns anyway and
8192-
* fix the attislocal/attisdropped state later, so as to keep control of the
8193-
* physical column order.
8191+
* For partitions, it's always true, because we want the partitions to be
8192+
* created independently and ATTACH PARTITION used afterwards.
8193+
*
8194+
* In binary_upgrade mode, we must print all columns and fix the attislocal/
8195+
* attisdropped state later, so as to keep control of the physical column
8196+
* order.
81948197
*
81958198
* This function exists because there are scattered nonobvious places that
81968199
* must be kept in sync with this decision.
@@ -8200,7 +8203,9 @@ shouldPrintColumn(DumpOptions *dopt, TableInfo *tbinfo, int colno)
82008203
{
82018204
if (dopt->binary_upgrade)
82028205
return true;
8203-
return (tbinfo->attislocal[colno] && !tbinfo->attisdropped[colno]);
8206+
if (tbinfo->attisdropped[colno])
8207+
return false;
8208+
return (tbinfo->attislocal[colno] || tbinfo->ispartition);
82048209
}
82058210

82068211

@@ -14963,27 +14968,6 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
1496314968
if (tbinfo->reloftype && !dopt->binary_upgrade)
1496414969
appendPQExpBuffer(q, " OF %s", tbinfo->reloftype);
1496514970

14966-
/*
14967-
* If the table is a partition, dump it as such; except in the case of
14968-
* a binary upgrade, we dump the table normally and attach it to the
14969-
* parent afterward.
14970-
*/
14971-
if (tbinfo->ispartition && !dopt->binary_upgrade)
14972-
{
14973-
TableInfo *parentRel = tbinfo->parents[0];
14974-
14975-
/*
14976-
* With partitions, unlike inheritance, there can only be one
14977-
* parent.
14978-
*/
14979-
if (tbinfo->numParents != 1)
14980-
exit_horribly(NULL, "invalid number of parents %d for table \"%s\"\n",
14981-
tbinfo->numParents, tbinfo->dobj.name);
14982-
14983-
appendPQExpBuffer(q, " PARTITION OF %s",
14984-
fmtQualifiedDumpable(parentRel));
14985-
}
14986-
1498714971
if (tbinfo->relkind != RELKIND_MATVIEW)
1498814972
{
1498914973
/* Dump the attributes */
@@ -15012,12 +14996,9 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
1501214996
(!tbinfo->inhNotNull[j] ||
1501314997
dopt->binary_upgrade));
1501414998

15015-
/*
15016-
* Skip column if fully defined by reloftype or the
15017-
* partition parent.
15018-
*/
15019-
if ((tbinfo->reloftype || tbinfo->ispartition) &&
15020-
!has_default && !has_notnull && !dopt->binary_upgrade)
14999+
/* Skip column if fully defined by reloftype */
15000+
if (tbinfo->reloftype && !has_default && !has_notnull &&
15001+
!dopt->binary_upgrade)
1502115002
continue;
1502215003

1502315004
/* Format properly if not first attr */
@@ -15040,20 +15021,16 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
1504015021
* clean things up later.
1504115022
*/
1504215023
appendPQExpBufferStr(q, " INTEGER /* dummy */");
15043-
/* Skip all the rest, too */
15024+
/* and skip to the next column */
1504415025
continue;
1504515026
}
1504615027

1504715028
/*
15048-
* Attribute type
15049-
*
15050-
* In binary-upgrade mode, we always include the type. If
15051-
* we aren't in binary-upgrade mode, then we skip the type
15052-
* when creating a typed table ('OF type_name') or a
15053-
* partition ('PARTITION OF'), since the type comes from
15054-
* the parent/partitioned table.
15029+
* Attribute type; print it except when creating a typed
15030+
* table ('OF type_name'), but in binary-upgrade mode,
15031+
* print it in that case too.
1505515032
*/
15056-
if (dopt->binary_upgrade || (!tbinfo->reloftype && !tbinfo->ispartition))
15033+
if (dopt->binary_upgrade || !tbinfo->reloftype)
1505715034
{
1505815035
appendPQExpBuffer(q, " %s",
1505915036
tbinfo->atttypnames[j]);
@@ -15103,25 +15080,20 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
1510315080

1510415081
if (actual_atts)
1510515082
appendPQExpBufferStr(q, "\n)");
15106-
else if (!((tbinfo->reloftype || tbinfo->ispartition) &&
15107-
!dopt->binary_upgrade))
15083+
else if (!(tbinfo->reloftype && !dopt->binary_upgrade))
1510815084
{
1510915085
/*
15110-
* We must have a parenthesized attribute list, even though
15111-
* empty, when not using the OF TYPE or PARTITION OF syntax.
15086+
* No attributes? we must have a parenthesized attribute list,
15087+
* even though empty, when not using the OF TYPE syntax.
1511215088
*/
1511315089
appendPQExpBufferStr(q, " (\n)");
1511415090
}
1511515091

15116-
if (tbinfo->ispartition && !dopt->binary_upgrade)
15117-
{
15118-
appendPQExpBufferStr(q, "\n");
15119-
appendPQExpBufferStr(q, tbinfo->partbound);
15120-
}
15121-
15122-
/* Emit the INHERITS clause, except if this is a partition. */
15123-
if (numParents > 0 &&
15124-
!tbinfo->ispartition &&
15092+
/*
15093+
* Emit the INHERITS clause (not for partitions), except in
15094+
* binary-upgrade mode.
15095+
*/
15096+
if (numParents > 0 && !tbinfo->ispartition &&
1512515097
!dopt->binary_upgrade)
1512615098
{
1512715099
appendPQExpBufferStr(q, "\nINHERITS (");
@@ -15271,30 +15243,16 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
1527115243
appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
1527215244
}
1527315245

15274-
if (numParents > 0)
15246+
if (numParents > 0 && !tbinfo->ispartition)
1527515247
{
15276-
appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inheritance and partitioning this way.\n");
15248+
appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inheritance this way.\n");
1527715249
for (k = 0; k < numParents; k++)
1527815250
{
1527915251
TableInfo *parentRel = parents[k];
1528015252

15281-
/* In the partitioning case, we alter the parent */
15282-
if (tbinfo->ispartition)
15283-
appendPQExpBuffer(q,
15284-
"ALTER TABLE ONLY %s ATTACH PARTITION ",
15285-
fmtQualifiedDumpable(parentRel));
15286-
else
15287-
appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT ",
15288-
qualrelname);
15289-
15290-
/* Partition needs specifying the bounds */
15291-
if (tbinfo->ispartition)
15292-
appendPQExpBuffer(q, "%s %s;\n",
15293-
qualrelname,
15294-
tbinfo->partbound);
15295-
else
15296-
appendPQExpBuffer(q, "%s;\n",
15297-
fmtQualifiedDumpable(parentRel));
15253+
appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT %s;\n",
15254+
qualrelname,
15255+
fmtQualifiedDumpable(parentRel));
1529815256
}
1529915257
}
1530015258

@@ -15307,6 +15265,27 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
1530715265
}
1530815266
}
1530915267

15268+
/*
15269+
* For partitioned tables, emit the ATTACH PARTITION clause. Note
15270+
* that we always want to create partitions this way instead of using
15271+
* CREATE TABLE .. PARTITION OF, mainly to preserve a possible column
15272+
* layout discrepancy with the parent, but also to ensure it gets the
15273+
* correct tablespace setting if it differs from the parent's.
15274+
*/
15275+
if (tbinfo->ispartition)
15276+
{
15277+
/* With partitions there can only be one parent */
15278+
if (tbinfo->numParents != 1)
15279+
exit_horribly(NULL, "invalid number of parents %d for table \"%s\"",
15280+
tbinfo->numParents, tbinfo->dobj.name);
15281+
15282+
/* Perform ALTER TABLE on the parent */
15283+
appendPQExpBuffer(q,
15284+
"ALTER TABLE ONLY %s ATTACH PARTITION %s %s;\n",
15285+
fmtQualifiedDumpable(parents[0]),
15286+
qualrelname, tbinfo->partbound);
15287+
}
15288+
1531015289
/*
1531115290
* In binary_upgrade mode, arrange to restore the old relfrozenxid and
1531215291
* relminmxid of all vacuumable relations. (While vacuum.c processes

src/bin/pg_dump/t/002_pg_dump.pl

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,8 +1047,8 @@
10471047
\QALTER TABLE ONLY dump_test.measurement ATTACH PARTITION dump_test_second_schema.measurement_y2006m2 \E
10481048
\QFOR VALUES FROM ('2006-02-01') TO ('2006-03-01');\E\n
10491049
/xm,
1050-
like => { binary_upgrade => 1, },
1051-
unlike => {
1050+
like => {
1051+
binary_upgrade => 1,
10521052
clean => 1,
10531053
clean_if_exists => 1,
10541054
createdb => 1,
@@ -1057,13 +1057,14 @@
10571057
exclude_test_table => 1,
10581058
exclude_test_table_data => 1,
10591059
no_blobs => 1,
1060-
no_privs => 1,
10611060
no_owner => 1,
1061+
no_privs => 1,
10621062
pg_dumpall_dbprivs => 1,
10631063
role => 1,
10641064
schema_only => 1,
10651065
section_pre_data => 1,
10661066
with_oids => 1,
1067+
}, unlike => {
10671068
only_dump_test_schema => 1,
10681069
only_dump_test_table => 1,
10691070
pg_dumpall_globals => 1,
@@ -4833,7 +4834,8 @@
48334834
\QCREATE TABLE dump_test_second_schema.measurement_y2006m2 PARTITION OF dump_test.measurement\E\n
48344835
\QFOR VALUES FROM ('2006-02-01') TO ('2006-03-01');\E\n
48354836
/xm,
4836-
like => {
4837+
like => {},
4838+
unlike => {
48374839
clean => 1,
48384840
clean_if_exists => 1,
48394841
createdb => 1,
@@ -4848,8 +4850,7 @@
48484850
role => 1,
48494851
schema_only => 1,
48504852
section_pre_data => 1,
4851-
with_oids => 1, },
4852-
unlike => {
4853+
with_oids => 1,
48534854
binary_upgrade => 1,
48544855
only_dump_test_schema => 1,
48554856
only_dump_test_table => 1,

0 commit comments

Comments
 (0)