aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorPeter Eisentraut <peter@eisentraut.org>2019-04-12 08:36:05 +0200
committerPeter Eisentraut <peter@eisentraut.org>2019-04-12 08:36:05 +0200
commitef6f30fe77af69a8c775cca82bf993b10c9889ee (patch)
tree318e3cc237fc57035c4d63ee766e110845b01d75 /src/backend
parentf7feb020c3d8d5aff24204af28359b99ee65bf8f (diff)
downloadpostgresql-ef6f30fe77af69a8c775cca82bf993b10c9889ee.tar.gz
postgresql-ef6f30fe77af69a8c775cca82bf993b10c9889ee.zip
Fix REINDEX CONCURRENTLY of partitions
In case of a partition index, when swapping the old and new index, we also need to attach the new index as a partition and detach the old one. Also, to handle partition indexes, we not only need to change dependencies referencing the index, but also dependencies of the index referencing something else. The previous code did this only specifically for a constraint, but we also need to do this for partitioned indexes. So instead write a generic function that does it for all dependencies. Author: Michael Paquier <michael@paquier.xyz> Author: Peter Eisentraut <peter.eisentraut@2ndquadrant.com> Discussion: https://www.postgresql.org/message-id/flat/DF4PR8401MB11964EDB77C860078C343BEBEE5A0%40DF4PR8401MB1196.NAMPRD84.PROD.OUTLOOK.COM#154df1fedb735190a773481765f7b874
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/index.c40
-rw-r--r--src/backend/catalog/pg_depend.c56
2 files changed, 78 insertions, 18 deletions
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 9b1d5467917..e9399bef14c 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -39,6 +39,7 @@
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/objectaccess.h"
+#include "catalog/partition.h"
#include "catalog/pg_am.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
@@ -1263,7 +1264,13 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, const char
indexColNames = lappend(indexColNames, NameStr(att->attname));
}
- /* Now create the new index */
+ /*
+ * Now create the new index.
+ *
+ * For a partition index, we adjust the partition dependency later, to
+ * ensure a consistent state at all times. That is why parentIndexRelid
+ * is not set here.
+ */
newIndexId = index_create(heapRelation,
newName,
InvalidOid, /* indexRelationId */
@@ -1395,6 +1402,9 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
namestrcpy(&newClassForm->relname, NameStr(oldClassForm->relname));
namestrcpy(&oldClassForm->relname, oldName);
+ /* Copy partition flag to track inheritance properly */
+ newClassForm->relispartition = oldClassForm->relispartition;
+
CatalogTupleUpdate(pg_class, &oldClassTuple->t_self, oldClassTuple);
CatalogTupleUpdate(pg_class, &newClassTuple->t_self, newClassTuple);
@@ -1555,29 +1565,23 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
}
/*
- * Move all dependencies on the old index to the new one
+ * Swap inheritance relationship with parent index
*/
-
- if (OidIsValid(indexConstraintOid))
+ if (get_rel_relispartition(oldIndexId))
{
- ObjectAddress myself,
- referenced;
-
- /* Change to having the new index depend on the constraint */
- deleteDependencyRecordsForClass(RelationRelationId, oldIndexId,
- ConstraintRelationId, DEPENDENCY_INTERNAL);
+ List *ancestors = get_partition_ancestors(oldIndexId);
+ Oid parentIndexRelid = linitial_oid(ancestors);
- myself.classId = RelationRelationId;
- myself.objectId = newIndexId;
- myself.objectSubId = 0;
+ DeleteInheritsTuple(oldIndexId, parentIndexRelid);
+ StoreSingleInheritance(newIndexId, parentIndexRelid, 1);
- referenced.classId = ConstraintRelationId;
- referenced.objectId = indexConstraintOid;
- referenced.objectSubId = 0;
-
- recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+ list_free(ancestors);
}
+ /*
+ * Move all dependencies of and on the old index to the new one
+ */
+ changeDependenciesOf(RelationRelationId, oldIndexId, newIndexId);
changeDependenciesOn(RelationRelationId, oldIndexId, newIndexId);
/*
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index d63bf5e56d9..f7caedcc02c 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -396,6 +396,62 @@ changeDependencyFor(Oid classId, Oid objectId,
}
/*
+ * Adjust all dependency records to come from a different object of the same type
+ *
+ * classId/oldObjectId specify the old referencing object.
+ * newObjectId is the new referencing object (must be of class classId).
+ *
+ * Returns the number of records updated.
+ */
+long
+changeDependenciesOf(Oid classId, Oid oldObjectId,
+ Oid newObjectId)
+{
+ long count = 0;
+ Relation depRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ depRel = table_open(DependRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(oldObjectId));
+
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ NULL, 2, key);
+
+ while (HeapTupleIsValid((tup = systable_getnext(scan))))
+ {
+ Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ /* make a modifiable copy */
+ tup = heap_copytuple(tup);
+ depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ depform->objid = newObjectId;
+
+ CatalogTupleUpdate(depRel, &tup->t_self, tup);
+
+ heap_freetuple(tup);
+
+ count++;
+ }
+
+ systable_endscan(scan);
+
+ table_close(depRel, RowExclusiveLock);
+
+ return count;
+}
+
+/*
* Adjust all dependency records to point to a different object of the same type
*
* refClassId/oldRefObjectId specify the old referenced object.