@@ -6272,20 +6272,23 @@ getTables(Archive *fout, int *numTables)
62726272 int i_is_identity_sequence;
62736273 int i_relacl;
62746274 int i_acldefault;
6275- int i_partkeydef;
62766275 int i_ispartition;
6277- int i_partbound;
62786276
62796277 /*
62806278 * Find all the tables and table-like objects.
62816279 *
6280+ * We must fetch all tables in this phase because otherwise we cannot
6281+ * correctly identify inherited columns, owned sequences, etc.
6282+ *
62826283 * We include system catalogs, so that we can work if a user table is
62836284 * defined to inherit from a system catalog (pretty weird, but...)
62846285 *
62856286 * Note: in this phase we should collect only a minimal amount of
62866287 * information about each table, basically just enough to decide if it is
6287- * interesting. We must fetch all tables in this phase because otherwise
6288- * we cannot correctly identify inherited columns, owned sequences, etc.
6288+ * interesting. In particular, since we do not yet have lock on any user
6289+ * table, we MUST NOT invoke any server-side data collection functions
6290+ * (for instance, pg_get_partkeydef()). Those are likely to fail or give
6291+ * wrong answers if any concurrent DDL is happening.
62896292 */
62906293
62916294 appendPQExpBuffer(query,
@@ -6379,10 +6382,10 @@ getTables(Archive *fout, int *numTables)
63796382
63806383 if (fout->remoteVersion >= 90000)
63816384 appendPQExpBufferStr(query,
6382- "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, ");
6385+ "c. reloftype, ");
63836386 else
63846387 appendPQExpBufferStr(query,
6385- "NULL AS reloftype, ");
6388+ "0 AS reloftype, ");
63866389
63876390 if (fout->remoteVersion >= 90100)
63886391 appendPQExpBufferStr(query,
@@ -6423,14 +6426,10 @@ getTables(Archive *fout, int *numTables)
64236426
64246427 if (fout->remoteVersion >= 100000)
64256428 appendPQExpBufferStr(query,
6426- "pg_get_partkeydef(c.oid) AS partkeydef, "
6427- "c.relispartition AS ispartition, "
6428- "pg_get_expr(c.relpartbound, c.oid) AS partbound ");
6429+ "c.relispartition AS ispartition ");
64296430 else
64306431 appendPQExpBufferStr(query,
6431- "NULL AS partkeydef, "
6432- "false AS ispartition, "
6433- "NULL AS partbound ");
6432+ "false AS ispartition ");
64346433
64356434 /*
64366435 * Left join to pg_depend to pick up dependency info linking sequences to
@@ -6539,9 +6538,7 @@ getTables(Archive *fout, int *numTables)
65396538 i_is_identity_sequence = PQfnumber(res, "is_identity_sequence");
65406539 i_relacl = PQfnumber(res, "relacl");
65416540 i_acldefault = PQfnumber(res, "acldefault");
6542- i_partkeydef = PQfnumber(res, "partkeydef");
65436541 i_ispartition = PQfnumber(res, "ispartition");
6544- i_partbound = PQfnumber(res, "partbound");
65456542
65466543 if (dopt->lockWaitTimeout)
65476544 {
@@ -6607,19 +6604,14 @@ getTables(Archive *fout, int *numTables)
66076604 else
66086605 tblinfo[i].checkoption = pg_strdup(PQgetvalue(res, i, i_checkoption));
66096606 tblinfo[i].toast_reloptions = pg_strdup(PQgetvalue(res, i, i_toastreloptions));
6610- if (PQgetisnull(res, i, i_reloftype))
6611- tblinfo[i].reloftype = NULL;
6612- else
6613- tblinfo[i].reloftype = pg_strdup(PQgetvalue(res, i, i_reloftype));
6607+ tblinfo[i].reloftype = atooid(PQgetvalue(res, i, i_reloftype));
66146608 tblinfo[i].foreign_server = atooid(PQgetvalue(res, i, i_foreignserver));
66156609 if (PQgetisnull(res, i, i_amname))
66166610 tblinfo[i].amname = NULL;
66176611 else
66186612 tblinfo[i].amname = pg_strdup(PQgetvalue(res, i, i_amname));
66196613 tblinfo[i].is_identity_sequence = (strcmp(PQgetvalue(res, i, i_is_identity_sequence), "t") == 0);
6620- tblinfo[i].partkeydef = pg_strdup(PQgetvalue(res, i, i_partkeydef));
66216614 tblinfo[i].ispartition = (strcmp(PQgetvalue(res, i, i_ispartition), "t") == 0);
6622- tblinfo[i].partbound = pg_strdup(PQgetvalue(res, i, i_partbound));
66236615
66246616 /* other fields were zeroed above */
66256617
@@ -15651,12 +15643,34 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
1565115643 }
1565215644 else
1565315645 {
15646+ char *partkeydef = NULL;
1565415647 char *ftoptions = NULL;
1565515648 char *srvname = NULL;
1565615649 char *foreign = "";
1565715650
15651+ /*
15652+ * Set reltypename, and collect any relkind-specific data that we
15653+ * didn't fetch during getTables().
15654+ */
1565815655 switch (tbinfo->relkind)
1565915656 {
15657+ case RELKIND_PARTITIONED_TABLE:
15658+ {
15659+ PQExpBuffer query = createPQExpBuffer();
15660+ PGresult *res;
15661+
15662+ reltypename = "TABLE";
15663+
15664+ /* retrieve partition key definition */
15665+ appendPQExpBuffer(query,
15666+ "SELECT pg_get_partkeydef('%u')",
15667+ tbinfo->dobj.catId.oid);
15668+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
15669+ partkeydef = pg_strdup(PQgetvalue(res, 0, 0));
15670+ PQclear(res);
15671+ destroyPQExpBuffer(query);
15672+ break;
15673+ }
1566015674 case RELKIND_FOREIGN_TABLE:
1566115675 {
1566215676 PQExpBuffer query = createPQExpBuffer();
@@ -15696,6 +15710,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
1569615710 break;
1569715711 default:
1569815712 reltypename = "TABLE";
15713+ break;
1569915714 }
1570015715
1570115716 numParents = tbinfo->numParents;
@@ -15717,8 +15732,10 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
1571715732 * Attach to type, if reloftype; except in case of a binary upgrade,
1571815733 * we dump the table normally and attach it to the type afterward.
1571915734 */
15720- if (tbinfo->reloftype && !dopt->binary_upgrade)
15721- appendPQExpBuffer(q, " OF %s", tbinfo->reloftype);
15735+ if (OidIsValid(tbinfo->reloftype) && !dopt->binary_upgrade)
15736+ appendPQExpBuffer(q, " OF %s",
15737+ getFormattedTypeName(fout, tbinfo->reloftype,
15738+ zeroIsError));
1572215739
1572315740 if (tbinfo->relkind != RELKIND_MATVIEW)
1572415741 {
@@ -15756,7 +15773,8 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
1575615773 * Skip column if fully defined by reloftype, except in
1575715774 * binary upgrade
1575815775 */
15759- if (tbinfo->reloftype && !print_default && !print_notnull &&
15776+ if (OidIsValid(tbinfo->reloftype) &&
15777+ !print_default && !print_notnull &&
1576015778 !dopt->binary_upgrade)
1576115779 continue;
1576215780
@@ -15789,7 +15807,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
1578915807 * table ('OF type_name'), but in binary-upgrade mode,
1579015808 * print it in that case too.
1579115809 */
15792- if (dopt->binary_upgrade || !tbinfo->reloftype)
15810+ if (dopt->binary_upgrade || !OidIsValid( tbinfo->reloftype) )
1579315811 {
1579415812 appendPQExpBuffer(q, " %s",
1579515813 tbinfo->atttypnames[j]);
@@ -15852,7 +15870,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
1585215870
1585315871 if (actual_atts)
1585415872 appendPQExpBufferStr(q, "\n)");
15855- else if (!(tbinfo->reloftype && !dopt->binary_upgrade))
15873+ else if (!(OidIsValid( tbinfo->reloftype) && !dopt->binary_upgrade))
1585615874 {
1585715875 /*
1585815876 * No attributes? we must have a parenthesized attribute list,
@@ -15881,7 +15899,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
1588115899 }
1588215900
1588315901 if (tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
15884- appendPQExpBuffer(q, "\nPARTITION BY %s", tbinfo-> partkeydef);
15902+ appendPQExpBuffer(q, "\nPARTITION BY %s", partkeydef);
1588515903
1588615904 if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
1588715905 appendPQExpBuffer(q, "\nSERVER %s", fmtId(srvname));
@@ -16064,12 +16082,13 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
1606416082 }
1606516083 }
1606616084
16067- if (tbinfo->reloftype)
16085+ if (OidIsValid( tbinfo->reloftype) )
1606816086 {
1606916087 appendPQExpBufferStr(q, "\n-- For binary upgrade, set up typed tables this way.\n");
1607016088 appendPQExpBuffer(q, "ALTER TABLE ONLY %s OF %s;\n",
1607116089 qualrelname,
16072- tbinfo->reloftype);
16090+ getFormattedTypeName(fout, tbinfo->reloftype,
16091+ zeroIsError));
1607316092 }
1607416093 }
1607516094
@@ -16242,6 +16261,8 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
1624216261 tbinfo->attfdwoptions[j]);
1624316262 } /* end loop over columns */
1624416263
16264+ if (partkeydef)
16265+ free(partkeydef);
1624516266 if (ftoptions)
1624616267 free(ftoptions);
1624716268 if (srvname)
@@ -16358,6 +16379,8 @@ dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo)
1635816379{
1635916380 DumpOptions *dopt = fout->dopt;
1636016381 PQExpBuffer q;
16382+ PGresult *res;
16383+ char *partbound;
1636116384
1636216385 /* Do nothing in data-only dump */
1636316386 if (dopt->dataOnly)
@@ -16368,14 +16391,23 @@ dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo)
1636816391
1636916392 q = createPQExpBuffer();
1637016393
16371- /* Perform ALTER TABLE on the parent */
16394+ /* Fetch the partition's partbound */
1637216395 appendPQExpBuffer(q,
16396+ "SELECT pg_get_expr(c.relpartbound, c.oid) "
16397+ "FROM pg_class c "
16398+ "WHERE c.oid = '%u'",
16399+ attachinfo->partitionTbl->dobj.catId.oid);
16400+ res = ExecuteSqlQueryForSingleRow(fout, q->data);
16401+ partbound = PQgetvalue(res, 0, 0);
16402+
16403+ /* Perform ALTER TABLE on the parent */
16404+ printfPQExpBuffer(q,
1637316405 "ALTER TABLE ONLY %s ",
1637416406 fmtQualifiedDumpable(attachinfo->parentTbl));
1637516407 appendPQExpBuffer(q,
1637616408 "ATTACH PARTITION %s %s;\n",
1637716409 fmtQualifiedDumpable(attachinfo->partitionTbl),
16378- attachinfo->partitionTbl-> partbound);
16410+ partbound);
1637916411
1638016412 /*
1638116413 * There is no point in creating a drop query as the drop is done by table
@@ -16392,6 +16424,7 @@ dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo)
1639216424 .section = SECTION_PRE_DATA,
1639316425 .createStmt = q->data));
1639416426
16427+ PQclear(res);
1639516428 destroyPQExpBuffer(q);
1639616429}
1639716430
0 commit comments