diff options
-rw-r--r-- | doc/src/sgml/release-11.sgml | 23 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 123 | ||||
-rw-r--r-- | src/bin/pg_dump/t/002_pg_dump.pl | 12 |
3 files changed, 75 insertions, 83 deletions
diff --git a/doc/src/sgml/release-11.sgml b/doc/src/sgml/release-11.sgml index 373b8de09ac..e9ce1ee9253 100644 --- a/doc/src/sgml/release-11.sgml +++ b/doc/src/sgml/release-11.sgml @@ -1053,29 +1053,6 @@ Branch: REL9_4_STABLE [12c42a543] 2019-04-11 21:06:21 +0200 <listitem> <!-- -Author: Alvaro Herrera <alvherre@alvh.no-ip.org> -Branch: master [3b23552ad] 2019-04-24 15:30:37 -0400 -Branch: REL_11_STABLE [a98c48deb] 2019-04-24 15:30:37 -0400 -Branch: REL_10_STABLE [5a191f697] 2019-04-24 15:30:37 -0400 ---> - <para> - Make <application>pg_dump</application> recreate table partitions - using <command>ATTACH PARTITION</command> instead - of <command>CREATE TABLE ... PARTITION OF</command> (David Rowley) - </para> - - <para> - This avoids various corner-case problems, notably that dump and - restore might unexpectedly alter a partition's column ordering. - It also means that a selective restore of the partition can succeed - even if its parent partitioned table isn't restored. - (The <command>ATTACH PARTITION</command> will fail of course, but - the partition table itself can be created and populated.) - </para> - </listitem> - - <listitem> -<!-- Author: Michael Paquier <michael@paquier.xyz> Branch: master [a7eadaaaa] 2019-03-18 10:34:45 +0900 Branch: REL_11_STABLE [dcf2a0db8] 2019-03-18 10:35:01 +0900 diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index e6a116cefff..c79ac0b18ee 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -8617,12 +8617,9 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) * Normally this is always true, but it's false for dropped columns, as well * as those that were inherited without any local definition. (If we print * such a column it will mistakenly get pg_attribute.attislocal set to true.) - * For partitions, it's always true, because we want the partitions to be - * created independently and ATTACH PARTITION used afterwards. - * - * In binary_upgrade mode, we must print all columns and fix the attislocal/ - * attisdropped state later, so as to keep control of the physical column - * order. + * However, in binary_upgrade mode, we must print all such columns anyway and + * fix the attislocal/attisdropped state later, so as to keep control of the + * physical column order. * * This function exists because there are scattered nonobvious places that * must be kept in sync with this decision. @@ -8632,9 +8629,7 @@ shouldPrintColumn(DumpOptions *dopt, TableInfo *tbinfo, int colno) { if (dopt->binary_upgrade) return true; - if (tbinfo->attisdropped[colno]) - return false; - return (tbinfo->attislocal[colno] || tbinfo->ispartition); + return (tbinfo->attislocal[colno] && !tbinfo->attisdropped[colno]); } @@ -15543,6 +15538,27 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) if (tbinfo->reloftype && !dopt->binary_upgrade) appendPQExpBuffer(q, " OF %s", tbinfo->reloftype); + /* + * If the table is a partition, dump it as such; except in the case of + * a binary upgrade, we dump the table normally and attach it to the + * parent afterward. + */ + if (tbinfo->ispartition && !dopt->binary_upgrade) + { + TableInfo *parentRel = tbinfo->parents[0]; + + /* + * With partitions, unlike inheritance, there can only be one + * parent. + */ + if (tbinfo->numParents != 1) + exit_horribly(NULL, "invalid number of parents %d for table \"%s\"\n", + tbinfo->numParents, tbinfo->dobj.name); + + appendPQExpBuffer(q, " PARTITION OF %s", + fmtQualifiedDumpable(parentRel)); + } + if (tbinfo->relkind != RELKIND_MATVIEW) { /* Dump the attributes */ @@ -15571,9 +15587,12 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) (!tbinfo->inhNotNull[j] || dopt->binary_upgrade)); - /* Skip column if fully defined by reloftype */ - if (tbinfo->reloftype && !has_default && !has_notnull && - !dopt->binary_upgrade) + /* + * Skip column if fully defined by reloftype or the + * partition parent. + */ + if ((tbinfo->reloftype || tbinfo->ispartition) && + !has_default && !has_notnull && !dopt->binary_upgrade) continue; /* Format properly if not first attr */ @@ -15596,16 +15615,20 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) * clean things up later. */ appendPQExpBufferStr(q, " INTEGER /* dummy */"); - /* and skip to the next column */ + /* Skip all the rest, too */ continue; } /* - * Attribute type; print it except when creating a typed - * table ('OF type_name'), but in binary-upgrade mode, - * print it in that case too. + * Attribute type + * + * In binary-upgrade mode, we always include the type. If + * we aren't in binary-upgrade mode, then we skip the type + * when creating a typed table ('OF type_name') or a + * partition ('PARTITION OF'), since the type comes from + * the parent/partitioned table. */ - if (dopt->binary_upgrade || !tbinfo->reloftype) + if (dopt->binary_upgrade || (!tbinfo->reloftype && !tbinfo->ispartition)) { appendPQExpBuffer(q, " %s", tbinfo->atttypnames[j]); @@ -15655,20 +15678,25 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) if (actual_atts) appendPQExpBufferStr(q, "\n)"); - else if (!(tbinfo->reloftype && !dopt->binary_upgrade)) + else if (!((tbinfo->reloftype || tbinfo->ispartition) && + !dopt->binary_upgrade)) { /* - * No attributes? we must have a parenthesized attribute list, - * even though empty, when not using the OF TYPE syntax. + * We must have a parenthesized attribute list, even though + * empty, when not using the OF TYPE or PARTITION OF syntax. */ appendPQExpBufferStr(q, " (\n)"); } - /* - * Emit the INHERITS clause (not for partitions), except in - * binary-upgrade mode. - */ - if (numParents > 0 && !tbinfo->ispartition && + if (tbinfo->ispartition && !dopt->binary_upgrade) + { + appendPQExpBufferChar(q, '\n'); + appendPQExpBufferStr(q, tbinfo->partbound); + } + + /* Emit the INHERITS clause, except if this is a partition. */ + if (numParents > 0 && + !tbinfo->ispartition && !dopt->binary_upgrade) { appendPQExpBufferStr(q, "\nINHERITS ("); @@ -15841,16 +15869,30 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); } - if (numParents > 0 && !tbinfo->ispartition) + if (numParents > 0) { - appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inheritance this way.\n"); + appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inheritance and partitioning this way.\n"); for (k = 0; k < numParents; k++) { TableInfo *parentRel = parents[k]; - appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT %s;\n", - qualrelname, - fmtQualifiedDumpable(parentRel)); + /* In the partitioning case, we alter the parent */ + if (tbinfo->ispartition) + appendPQExpBuffer(q, + "ALTER TABLE ONLY %s ATTACH PARTITION ", + fmtQualifiedDumpable(parentRel)); + else + appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT ", + qualrelname); + + /* Partition needs specifying the bounds */ + if (tbinfo->ispartition) + appendPQExpBuffer(q, "%s %s;\n", + qualrelname, + tbinfo->partbound); + else + appendPQExpBuffer(q, "%s;\n", + fmtQualifiedDumpable(parentRel)); } } @@ -15864,27 +15906,6 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) } /* - * For partitioned tables, emit the ATTACH PARTITION clause. Note - * that we always want to create partitions this way instead of using - * CREATE TABLE .. PARTITION OF, mainly to preserve a possible column - * layout discrepancy with the parent, but also to ensure it gets the - * correct tablespace setting if it differs from the parent's. - */ - if (tbinfo->ispartition) - { - /* With partitions there can only be one parent */ - if (tbinfo->numParents != 1) - exit_horribly(NULL, "invalid number of parents %d for table \"%s\"\n", - tbinfo->numParents, tbinfo->dobj.name); - - /* Perform ALTER TABLE on the parent */ - appendPQExpBuffer(q, - "ALTER TABLE ONLY %s ATTACH PARTITION %s %s;\n", - fmtQualifiedDumpable(parents[0]), - qualrelname, tbinfo->partbound); - } - - /* * In binary_upgrade mode, arrange to restore the old relfrozenxid and * relminmxid of all vacuumable relations. (While vacuum.c processes * TOAST tables semi-independently, here we see them only as children diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl index 6cd3a36d4ab..f7cdf046834 100644 --- a/src/bin/pg_dump/t/002_pg_dump.pl +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -732,12 +732,7 @@ my %tests = ( \QALTER TABLE ONLY dump_test.measurement ATTACH PARTITION dump_test_second_schema.measurement_y2006m2 \E \QFOR VALUES FROM ('2006-02-01') TO ('2006-03-01');\E\n /xm, - like => { - %full_runs, - role => 1, - section_pre_data => 1, - binary_upgrade => 1, - }, + like => { binary_upgrade => 1, }, }, 'ALTER TABLE test_table CLUSTER ON test_table_pkey' => { @@ -2355,13 +2350,12 @@ my %tests = ( \QCREATE TABLE dump_test_second_schema.measurement_y2006m2 PARTITION OF dump_test.measurement\E\n \QFOR VALUES FROM ('2006-02-01') TO ('2006-03-01');\E\n /xm, - like => {}, - unlike => { + like => { %full_runs, role => 1, section_pre_data => 1, - binary_upgrade => 1, }, + unlike => { binary_upgrade => 1, }, }, 'CREATE TABLE test_fourth_table_zero_col' => { |