diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index fee7055249..13f63303ba 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -16676,6 +16676,12 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo) PQExpBuffer delq; char *qindxname; char *qqindxname; + char *indstatcols = indxinfo->indstatcols; + char *indstatvals = indxinfo->indstatvals; + char **indstatcolsarray = NULL; + char **indstatvalsarray = NULL; + int nstatcols = 0; + int nstatvals = 0; if (dopt->dataOnly) return; @@ -16687,107 +16693,95 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo) qqindxname = pg_strdup(fmtQualifiedDumpable(indxinfo)); /* - * If there's an associated constraint, don't dump the index per se, but - * do dump any comment for it. (This is safe because dependency ordering - * will have ensured the constraint is emitted first.) Note that the - * emitted comment has to be shown as depending on the constraint, not the - * index, in such cases. + * Previously to PG16, we avoided dumping any index that was created by a + * constraint, allowing the constraint definition to re-create the index + * automatically. This was problematic because ALTER TABLE doesn't have all + * the same options as CREATE INDEX and we would have had to deepen the + * connection between CREATE INDEX and ALTER TABLE. Now, these commands are + * separated but with a reference from the ALTER TABLE to the appropriate + * index, which then requires us to have a dependency ordering to ensure we + * create the index first and then the constraint. */ - if (!is_constraint) - { - char *indstatcols = indxinfo->indstatcols; - char *indstatvals = indxinfo->indstatvals; - char **indstatcolsarray = NULL; - char **indstatvalsarray = NULL; - int nstatcols = 0; - int nstatvals = 0; - if (dopt->binary_upgrade) - binary_upgrade_set_pg_class_oids(fout, q, - indxinfo->dobj.catId.oid, true); + if (dopt->binary_upgrade) + binary_upgrade_set_pg_class_oids(fout, q, + indxinfo->dobj.catId.oid, true); - /* Plain secondary index */ - appendPQExpBuffer(q, "%s;\n", indxinfo->indexdef); + /* Plain secondary index */ + appendPQExpBuffer(q, "%s;\n", indxinfo->indexdef); - /* - * Append ALTER TABLE commands as needed to set properties that we - * only have ALTER TABLE syntax for. Keep this in sync with the - * similar code in dumpConstraint! - */ - - /* If the index is clustered, we need to record that. */ - if (indxinfo->indisclustered) - { - appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER", - fmtQualifiedDumpable(tbinfo)); - /* index name is not qualified in this syntax */ - appendPQExpBuffer(q, " ON %s;\n", - qindxname); - } + /* If the index is clustered, we need to record that. */ + if (!is_constraint && indxinfo->indisclustered) + { + appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER", + fmtQualifiedDumpable(tbinfo)); + /* index name is not qualified in this syntax */ + appendPQExpBuffer(q, " ON %s;\n", + qindxname); + } - /* - * If the index has any statistics on some of its columns, generate - * the associated ALTER INDEX queries. - */ - if (strlen(indstatcols) != 0 || strlen(indstatvals) != 0) - { - int j; + /* + * If the index has any statistics on some of its columns, generate + * the associated ALTER INDEX queries. + */ + if (!is_constraint && (strlen(indstatcols) != 0 || strlen(indstatvals) != 0)) + { + int j; - if (!parsePGArray(indstatcols, &indstatcolsarray, &nstatcols)) - fatal("could not parse index statistic columns"); - if (!parsePGArray(indstatvals, &indstatvalsarray, &nstatvals)) - fatal("could not parse index statistic values"); - if (nstatcols != nstatvals) - fatal("mismatched number of columns and values for index statistics"); + if (!parsePGArray(indstatcols, &indstatcolsarray, &nstatcols)) + fatal("could not parse index statistic columns"); + if (!parsePGArray(indstatvals, &indstatvalsarray, &nstatvals)) + fatal("could not parse index statistic values"); + if (nstatcols != nstatvals) + fatal("mismatched number of columns and values for index statistics"); - for (j = 0; j < nstatcols; j++) - { - appendPQExpBuffer(q, "ALTER INDEX %s ", qqindxname); + for (j = 0; j < nstatcols; j++) + { + appendPQExpBuffer(q, "ALTER INDEX %s ", qqindxname); - /* - * Note that this is a column number, so no quotes should be - * used. - */ - appendPQExpBuffer(q, "ALTER COLUMN %s ", - indstatcolsarray[j]); - appendPQExpBuffer(q, "SET STATISTICS %s;\n", - indstatvalsarray[j]); - } + /* + * Note that this is a column number, so no quotes should be + * used. + */ + appendPQExpBuffer(q, "ALTER COLUMN %s ", + indstatcolsarray[j]); + appendPQExpBuffer(q, "SET STATISTICS %s;\n", + indstatvalsarray[j]); } + } - /* Indexes can depend on extensions */ - append_depends_on_extension(fout, q, &indxinfo->dobj, - "pg_catalog.pg_class", - "INDEX", qqindxname); + /* Indexes can depend on extensions */ + append_depends_on_extension(fout, q, &indxinfo->dobj, + "pg_catalog.pg_class", + "INDEX", qqindxname); - /* If the index defines identity, we need to record that. */ - if (indxinfo->indisreplident) - { - appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY USING", - fmtQualifiedDumpable(tbinfo)); - /* index name is not qualified in this syntax */ - appendPQExpBuffer(q, " INDEX %s;\n", - qindxname); - } + /* If the index defines identity, we need to record that. */ + if (!is_constraint && indxinfo->indisreplident) + { + appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY USING", + fmtQualifiedDumpable(tbinfo)); + /* index name is not qualified in this syntax */ + appendPQExpBuffer(q, " INDEX %s;\n", + qindxname); + } - appendPQExpBuffer(delq, "DROP INDEX %s;\n", qqindxname); + appendPQExpBuffer(delq, "DROP INDEX %s;\n", qqindxname); - if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) - ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId, - ARCHIVE_OPTS(.tag = indxinfo->dobj.name, - .namespace = tbinfo->dobj.namespace->dobj.name, - .tablespace = indxinfo->tablespace, - .owner = tbinfo->rolname, - .description = "INDEX", - .section = SECTION_POST_DATA, - .createStmt = q->data, - .dropStmt = delq->data)); + if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = indxinfo->dobj.name, + .namespace = tbinfo->dobj.namespace->dobj.name, + .tablespace = indxinfo->tablespace, + .owner = tbinfo->rolname, + .description = "INDEX", + .section = SECTION_POST_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); - if (indstatcolsarray) - free(indstatcolsarray); - if (indstatvalsarray) - free(indstatvalsarray); - } + if (indstatcolsarray) + free(indstatcolsarray); + if (indstatvalsarray) + free(indstatvalsarray); /* Dump Index Comments */ if (indxinfo->dobj.dump & DUMP_COMPONENT_COMMENT) @@ -16950,7 +16944,6 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo) { /* Index-related constraint */ IndxInfo *indxinfo; - int k; indxinfo = (IndxInfo *) findObjectByDumpId(coninfo->conindex); @@ -16967,61 +16960,16 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo) appendPQExpBuffer(q, " ADD CONSTRAINT %s ", fmtId(coninfo->dobj.name)); - if (coninfo->condef) + if (coninfo->contype == 'x') { /* pg_get_constraintdef should have provided everything */ appendPQExpBuffer(q, "%s;\n", coninfo->condef); } else { - appendPQExpBuffer(q, "%s (", - coninfo->contype == 'p' ? "PRIMARY KEY" : "UNIQUE"); - for (k = 0; k < indxinfo->indnkeyattrs; k++) - { - int indkey = (int) indxinfo->indkeys[k]; - const char *attname; - - if (indkey == InvalidAttrNumber) - break; - attname = getAttrName(indkey, tbinfo); - - appendPQExpBuffer(q, "%s%s", - (k == 0) ? "" : ", ", - fmtId(attname)); - } - - if (indxinfo->indnkeyattrs < indxinfo->indnattrs) - appendPQExpBufferStr(q, ") INCLUDE ("); - - for (k = indxinfo->indnkeyattrs; k < indxinfo->indnattrs; k++) - { - int indkey = (int) indxinfo->indkeys[k]; - const char *attname; - - if (indkey == InvalidAttrNumber) - break; - attname = getAttrName(indkey, tbinfo); - - appendPQExpBuffer(q, "%s%s", - (k == indxinfo->indnkeyattrs) ? "" : ", ", - fmtId(attname)); - } - - appendPQExpBufferChar(q, ')'); - - if (nonemptyReloptions(indxinfo->indreloptions)) - { - appendPQExpBufferStr(q, " WITH ("); - appendReloptionsArrayAH(q, indxinfo->indreloptions, "", fout); - appendPQExpBufferChar(q, ')'); - } - - if (coninfo->condeferrable) - { - appendPQExpBufferStr(q, " DEFERRABLE"); - if (coninfo->condeferred) - appendPQExpBufferStr(q, " INITIALLY DEFERRED"); - } + appendPQExpBuffer(q, "%s USING INDEX %s", + coninfo->contype == 'p' ? "PRIMARY KEY" : "UNIQUE", + fmtId(indxinfo->dobj.name)); appendPQExpBufferStr(q, ";\n"); } diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c index 46461fb6a1..f4aee4f832 100644 --- a/src/bin/pg_dump/pg_dump_sort.c +++ b/src/bin/pg_dump/pg_dump_sort.c @@ -72,9 +72,9 @@ enum dbObjectTypePriorities PRIO_SEQUENCE_SET, PRIO_BLOB_DATA, PRIO_POST_DATA_BOUNDARY, /* boundary! */ - PRIO_CONSTRAINT, PRIO_INDEX, PRIO_INDEX_ATTACH, + PRIO_CONSTRAINT, PRIO_STATSEXT, PRIO_RULE, PRIO_TRIGGER,