@@ -6272,20 +6272,23 @@ getTables(Archive *fout, int *numTables)
6272
6272
int i_is_identity_sequence;
6273
6273
int i_relacl;
6274
6274
int i_acldefault;
6275
- int i_partkeydef;
6276
6275
int i_ispartition;
6277
- int i_partbound;
6278
6276
6279
6277
/*
6280
6278
* Find all the tables and table-like objects.
6281
6279
*
6280
+ * We must fetch all tables in this phase because otherwise we cannot
6281
+ * correctly identify inherited columns, owned sequences, etc.
6282
+ *
6282
6283
* We include system catalogs, so that we can work if a user table is
6283
6284
* defined to inherit from a system catalog (pretty weird, but...)
6284
6285
*
6285
6286
* Note: in this phase we should collect only a minimal amount of
6286
6287
* 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.
6289
6292
*/
6290
6293
6291
6294
appendPQExpBuffer(query,
@@ -6379,10 +6382,10 @@ getTables(Archive *fout, int *numTables)
6379
6382
6380
6383
if (fout->remoteVersion >= 90000)
6381
6384
appendPQExpBufferStr(query,
6382
- "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, ");
6385
+ "c. reloftype, ");
6383
6386
else
6384
6387
appendPQExpBufferStr(query,
6385
- "NULL AS reloftype, ");
6388
+ "0 AS reloftype, ");
6386
6389
6387
6390
if (fout->remoteVersion >= 90100)
6388
6391
appendPQExpBufferStr(query,
@@ -6423,14 +6426,10 @@ getTables(Archive *fout, int *numTables)
6423
6426
6424
6427
if (fout->remoteVersion >= 100000)
6425
6428
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 ");
6429
6430
else
6430
6431
appendPQExpBufferStr(query,
6431
- "NULL AS partkeydef, "
6432
- "false AS ispartition, "
6433
- "NULL AS partbound ");
6432
+ "false AS ispartition ");
6434
6433
6435
6434
/*
6436
6435
* Left join to pg_depend to pick up dependency info linking sequences to
@@ -6539,9 +6538,7 @@ getTables(Archive *fout, int *numTables)
6539
6538
i_is_identity_sequence = PQfnumber(res, "is_identity_sequence");
6540
6539
i_relacl = PQfnumber(res, "relacl");
6541
6540
i_acldefault = PQfnumber(res, "acldefault");
6542
- i_partkeydef = PQfnumber(res, "partkeydef");
6543
6541
i_ispartition = PQfnumber(res, "ispartition");
6544
- i_partbound = PQfnumber(res, "partbound");
6545
6542
6546
6543
if (dopt->lockWaitTimeout)
6547
6544
{
@@ -6607,19 +6604,14 @@ getTables(Archive *fout, int *numTables)
6607
6604
else
6608
6605
tblinfo[i].checkoption = pg_strdup(PQgetvalue(res, i, i_checkoption));
6609
6606
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));
6614
6608
tblinfo[i].foreign_server = atooid(PQgetvalue(res, i, i_foreignserver));
6615
6609
if (PQgetisnull(res, i, i_amname))
6616
6610
tblinfo[i].amname = NULL;
6617
6611
else
6618
6612
tblinfo[i].amname = pg_strdup(PQgetvalue(res, i, i_amname));
6619
6613
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));
6621
6614
tblinfo[i].ispartition = (strcmp(PQgetvalue(res, i, i_ispartition), "t") == 0);
6622
- tblinfo[i].partbound = pg_strdup(PQgetvalue(res, i, i_partbound));
6623
6615
6624
6616
/* other fields were zeroed above */
6625
6617
@@ -15651,12 +15643,34 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
15651
15643
}
15652
15644
else
15653
15645
{
15646
+ char *partkeydef = NULL;
15654
15647
char *ftoptions = NULL;
15655
15648
char *srvname = NULL;
15656
15649
char *foreign = "";
15657
15650
15651
+ /*
15652
+ * Set reltypename, and collect any relkind-specific data that we
15653
+ * didn't fetch during getTables().
15654
+ */
15658
15655
switch (tbinfo->relkind)
15659
15656
{
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
+ }
15660
15674
case RELKIND_FOREIGN_TABLE:
15661
15675
{
15662
15676
PQExpBuffer query = createPQExpBuffer();
@@ -15696,6 +15710,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
15696
15710
break;
15697
15711
default:
15698
15712
reltypename = "TABLE";
15713
+ break;
15699
15714
}
15700
15715
15701
15716
numParents = tbinfo->numParents;
@@ -15717,8 +15732,10 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
15717
15732
* Attach to type, if reloftype; except in case of a binary upgrade,
15718
15733
* we dump the table normally and attach it to the type afterward.
15719
15734
*/
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));
15722
15739
15723
15740
if (tbinfo->relkind != RELKIND_MATVIEW)
15724
15741
{
@@ -15756,7 +15773,8 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
15756
15773
* Skip column if fully defined by reloftype, except in
15757
15774
* binary upgrade
15758
15775
*/
15759
- if (tbinfo->reloftype && !print_default && !print_notnull &&
15776
+ if (OidIsValid(tbinfo->reloftype) &&
15777
+ !print_default && !print_notnull &&
15760
15778
!dopt->binary_upgrade)
15761
15779
continue;
15762
15780
@@ -15789,7 +15807,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
15789
15807
* table ('OF type_name'), but in binary-upgrade mode,
15790
15808
* print it in that case too.
15791
15809
*/
15792
- if (dopt->binary_upgrade || !tbinfo->reloftype)
15810
+ if (dopt->binary_upgrade || !OidIsValid( tbinfo->reloftype) )
15793
15811
{
15794
15812
appendPQExpBuffer(q, " %s",
15795
15813
tbinfo->atttypnames[j]);
@@ -15852,7 +15870,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
15852
15870
15853
15871
if (actual_atts)
15854
15872
appendPQExpBufferStr(q, "\n)");
15855
- else if (!(tbinfo->reloftype && !dopt->binary_upgrade))
15873
+ else if (!(OidIsValid( tbinfo->reloftype) && !dopt->binary_upgrade))
15856
15874
{
15857
15875
/*
15858
15876
* No attributes? we must have a parenthesized attribute list,
@@ -15881,7 +15899,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
15881
15899
}
15882
15900
15883
15901
if (tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
15884
- appendPQExpBuffer(q, "\nPARTITION BY %s", tbinfo-> partkeydef);
15902
+ appendPQExpBuffer(q, "\nPARTITION BY %s", partkeydef);
15885
15903
15886
15904
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
15887
15905
appendPQExpBuffer(q, "\nSERVER %s", fmtId(srvname));
@@ -16064,12 +16082,13 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
16064
16082
}
16065
16083
}
16066
16084
16067
- if (tbinfo->reloftype)
16085
+ if (OidIsValid( tbinfo->reloftype) )
16068
16086
{
16069
16087
appendPQExpBufferStr(q, "\n-- For binary upgrade, set up typed tables this way.\n");
16070
16088
appendPQExpBuffer(q, "ALTER TABLE ONLY %s OF %s;\n",
16071
16089
qualrelname,
16072
- tbinfo->reloftype);
16090
+ getFormattedTypeName(fout, tbinfo->reloftype,
16091
+ zeroIsError));
16073
16092
}
16074
16093
}
16075
16094
@@ -16242,6 +16261,8 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
16242
16261
tbinfo->attfdwoptions[j]);
16243
16262
} /* end loop over columns */
16244
16263
16264
+ if (partkeydef)
16265
+ free(partkeydef);
16245
16266
if (ftoptions)
16246
16267
free(ftoptions);
16247
16268
if (srvname)
@@ -16358,6 +16379,8 @@ dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo)
16358
16379
{
16359
16380
DumpOptions *dopt = fout->dopt;
16360
16381
PQExpBuffer q;
16382
+ PGresult *res;
16383
+ char *partbound;
16361
16384
16362
16385
/* Do nothing in data-only dump */
16363
16386
if (dopt->dataOnly)
@@ -16368,14 +16391,23 @@ dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo)
16368
16391
16369
16392
q = createPQExpBuffer();
16370
16393
16371
- /* Perform ALTER TABLE on the parent */
16394
+ /* Fetch the partition's partbound */
16372
16395
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,
16373
16405
"ALTER TABLE ONLY %s ",
16374
16406
fmtQualifiedDumpable(attachinfo->parentTbl));
16375
16407
appendPQExpBuffer(q,
16376
16408
"ATTACH PARTITION %s %s;\n",
16377
16409
fmtQualifiedDumpable(attachinfo->partitionTbl),
16378
- attachinfo->partitionTbl-> partbound);
16410
+ partbound);
16379
16411
16380
16412
/*
16381
16413
* 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)
16392
16424
.section = SECTION_PRE_DATA,
16393
16425
.createStmt = q->data));
16394
16426
16427
+ PQclear(res);
16395
16428
destroyPQExpBuffer(q);
16396
16429
}
16397
16430
0 commit comments