diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2019-10-17 09:58:01 +0200 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2019-10-17 09:58:01 +0200 |
commit | b304b2b65fde057a35286adf3ea69f5e154d1878 (patch) | |
tree | 9d1d433d9f27d6ed13f7eb13914d792aab4d672f /src/bin/pg_dump/pg_dump.c | |
parent | 3af7c64fe70c0b9d1072c660ddb1cb87dbe0a9d3 (diff) |
Fix parallel restore of FKs to partitioned tables
When an FK constraint is created, it needs the index on the referenced
table to exist and be valid. When doing parallel pg_restore and the
referenced table was partitioned, this condition can sometimes not be
met, because pg_dump didn't emit sufficient object dependencies to
ensure so; this means that parallel pg_restore would fail in certain
conditions. Fix by having pg_dump make the FK constraint object
dependent on the partition attachment objects for the constraint's
referenced index.
This has been broken since f56f8f8da6af, so backpatch to Postgres 12.
Discussion: https://postgr.es/m/20191005224333.GA9738@alvherre.pgsql
Diffstat (limited to 'src/bin/pg_dump/pg_dump.c')
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index a9c868b9aff..33e58fa287e 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -7109,6 +7109,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) indxinfo[j].indisclustered = (PQgetvalue(res, j, i_indisclustered)[0] == 't'); indxinfo[j].indisreplident = (PQgetvalue(res, j, i_indisreplident)[0] == 't'); indxinfo[j].parentidx = atooid(PQgetvalue(res, j, i_parentidx)); + indxinfo[j].partattaches = (SimplePtrList) { NULL, NULL }; contype = *(PQgetvalue(res, j, i_contype)); if (contype == 'p' || contype == 'u' || contype == 'x') @@ -7241,6 +7242,7 @@ getConstraints(Archive *fout, TableInfo tblinfo[], int numTables) i_conoid, i_conname, i_confrelid, + i_conindid, i_condef; int ntups; @@ -7266,7 +7268,7 @@ getConstraints(Archive *fout, TableInfo tblinfo[], int numTables) resetPQExpBuffer(query); if (fout->remoteVersion >= 110000) appendPQExpBuffer(query, - "SELECT tableoid, oid, conname, confrelid, " + "SELECT tableoid, oid, conname, confrelid, conindid, " "pg_catalog.pg_get_constraintdef(oid) AS condef " "FROM pg_catalog.pg_constraint " "WHERE conrelid = '%u'::pg_catalog.oid " @@ -7275,7 +7277,7 @@ getConstraints(Archive *fout, TableInfo tblinfo[], int numTables) tbinfo->dobj.catId.oid); else appendPQExpBuffer(query, - "SELECT tableoid, oid, conname, confrelid, " + "SELECT tableoid, oid, conname, confrelid, 0 as conindid, " "pg_catalog.pg_get_constraintdef(oid) AS condef " "FROM pg_catalog.pg_constraint " "WHERE conrelid = '%u'::pg_catalog.oid " @@ -7289,12 +7291,15 @@ getConstraints(Archive *fout, TableInfo tblinfo[], int numTables) i_conoid = PQfnumber(res, "oid"); i_conname = PQfnumber(res, "conname"); i_confrelid = PQfnumber(res, "confrelid"); + i_conindid = PQfnumber(res, "conindid"); i_condef = PQfnumber(res, "condef"); constrinfo = (ConstraintInfo *) pg_malloc(ntups * sizeof(ConstraintInfo)); for (j = 0; j < ntups; j++) { + TableInfo *reftable; + constrinfo[j].dobj.objType = DO_FK_CONSTRAINT; constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid)); constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid)); @@ -7311,6 +7316,39 @@ getConstraints(Archive *fout, TableInfo tblinfo[], int numTables) constrinfo[j].condeferred = false; constrinfo[j].conislocal = true; constrinfo[j].separate = true; + + /* + * Restoring an FK that points to a partitioned table requires + * that all partition indexes have been attached beforehand. + * Ensure that happens by making the constraint depend on each + * index partition attach object. + */ + reftable = findTableByOid(constrinfo[j].confrelid); + if (reftable && reftable->relkind == RELKIND_PARTITIONED_TABLE) + { + IndxInfo *refidx; + Oid indexOid = atooid(PQgetvalue(res, j, i_conindid)); + + if (indexOid != InvalidOid) + { + for (int k = 0; k < reftable->numIndexes; k++) + { + SimplePtrListCell *cell; + + /* not our index? */ + if (reftable->indexes[k].dobj.catId.oid != indexOid) + continue; + + refidx = &reftable->indexes[k]; + for (cell = refidx->partattaches.head; cell; + cell = cell->next) + addObjectDependency(&constrinfo[j].dobj, + ((DumpableObject *) + cell->ptr)->dumpId); + break; + } + } + } } PQclear(res); |