summaryrefslogtreecommitdiff
path: root/src/backend/executor/execUtils.c
diff options
context:
space:
mode:
authorRobert Haas2017-03-21 13:48:04 +0000
committerRobert Haas2017-03-21 13:48:04 +0000
commitd3cc37f1d801a6b5cad9bf179274a8d767f1ee50 (patch)
tree88dd5a0133f46b2eb015b4fd2ce69f1b3c30bb56 /src/backend/executor/execUtils.c
parentd5286aa905c9173b3fc4f911682089149bd3caef (diff)
Don't scan partitioned tables.
Partitioned tables do not contain any data; only their unpartitioned descendents need to be scanned. However, the partitioned tables still need to be locked, even though they're not scanned. To make that work, Append and MergeAppend relations now need to carry a list of (unscanned) partitioned relations that must be locked, and InitPlan must lock all partitioned result relations. Aside from the obvious advantage of avoiding some work at execution time, this has two other advantages. First, it may improve the planner's decision-making in some cases since the empty relation might throw things off. Second, it paves the way to getting rid of the storage for partitioned tables altogether. Amit Langote, reviewed by me. Discussion: http://postgr.es/m/[email protected]
Diffstat (limited to 'src/backend/executor/execUtils.c')
-rw-r--r--src/backend/executor/execUtils.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 3d6a3801c06..a72cffeb6e5 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -43,6 +43,7 @@
#include "executor/executor.h"
#include "nodes/nodeFuncs.h"
#include "parser/parsetree.h"
+#include "storage/lmgr.h"
#include "utils/memutils.h"
#include "utils/rel.h"
@@ -953,3 +954,58 @@ ShutdownExprContext(ExprContext *econtext, bool isCommit)
MemoryContextSwitchTo(oldcontext);
}
+
+/*
+ * ExecLockNonLeafAppendTables
+ *
+ * Locks, if necessary, the tables indicated by the RT indexes contained in
+ * the partitioned_rels list. These are the non-leaf tables in the partition
+ * tree controlled by a given Append or MergeAppend node.
+ */
+void
+ExecLockNonLeafAppendTables(List *partitioned_rels, EState *estate)
+{
+ PlannedStmt *stmt = estate->es_plannedstmt;
+ ListCell *lc;
+
+ foreach(lc, partitioned_rels)
+ {
+ ListCell *l;
+ Index rti = lfirst_int(lc);
+ bool is_result_rel = false;
+ Oid relid = getrelid(rti, estate->es_range_table);
+
+ /* If this is a result relation, already locked in InitPlan */
+ foreach(l, stmt->nonleafResultRelations)
+ {
+ if (rti == lfirst_int(l))
+ {
+ is_result_rel = true;
+ break;
+ }
+ }
+
+ /*
+ * Not a result relation; check if there is a RowMark that requires
+ * taking a RowShareLock on this rel.
+ */
+ if (!is_result_rel)
+ {
+ PlanRowMark *rc = NULL;
+
+ foreach(l, stmt->rowMarks)
+ {
+ if (((PlanRowMark *) lfirst(l))->rti == rti)
+ {
+ rc = lfirst(l);
+ break;
+ }
+ }
+
+ if (rc && RowMarkRequiresRowShareLock(rc->markType))
+ LockRelationOid(relid, RowShareLock);
+ else
+ LockRelationOid(relid, AccessShareLock);
+ }
+ }
+}