summaryrefslogtreecommitdiff
path: root/src/backend/tcop/utility.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/tcop/utility.c')
-rw-r--r--src/backend/tcop/utility.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index ec98a612ec9..9cccc8d39de 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -23,6 +23,7 @@
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "catalog/namespace.h"
+#include "catalog/pg_inherits_fn.h"
#include "catalog/toasting.h"
#include "commands/alter.h"
#include "commands/async.h"
@@ -1300,6 +1301,7 @@ ProcessUtilitySlow(ParseState *pstate,
IndexStmt *stmt = (IndexStmt *) parsetree;
Oid relid;
LOCKMODE lockmode;
+ List *inheritors = NIL;
if (stmt->concurrent)
PreventTransactionChain(isTopLevel,
@@ -1322,6 +1324,23 @@ ProcessUtilitySlow(ParseState *pstate,
RangeVarCallbackOwnsRelation,
NULL);
+ /*
+ * CREATE INDEX on partitioned tables (but not regular
+ * inherited tables) recurses to partitions, so we must
+ * acquire locks early to avoid deadlocks.
+ */
+ if (stmt->relation->inh)
+ {
+ Relation rel;
+
+ /* already locked by RangeVarGetRelidExtended */
+ rel = heap_open(relid, NoLock);
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ inheritors = find_all_inheritors(relid, lockmode,
+ NULL);
+ heap_close(rel, NoLock);
+ }
+
/* Run parse analysis ... */
stmt = transformIndexStmt(relid, stmt, queryString);
@@ -1331,6 +1350,7 @@ ProcessUtilitySlow(ParseState *pstate,
DefineIndex(relid, /* OID of heap relation */
stmt,
InvalidOid, /* no predefined OID */
+ InvalidOid, /* no parent index */
false, /* is_alter_table */
true, /* check_rights */
true, /* check_not_in_use */
@@ -1346,6 +1366,8 @@ ProcessUtilitySlow(ParseState *pstate,
parsetree);
commandCollected = true;
EventTriggerAlterTableEnd();
+
+ list_free(inheritors);
}
break;