summaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeIndexscan.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2017-03-08 08:15:24 -0500
committerRobert Haas <rhaas@postgresql.org>2017-03-08 08:15:24 -0500
commit09529a70bb5a77935d086d651c63396767d240d7 (patch)
tree6413df5b74055c6fd5a0f2ffd1bfce3a09f91b8b /src/backend/executor/nodeIndexscan.c
parent98e6e89040a0534ca26914c66cae9dd49ef62ad9 (diff)
downloadpostgresql-09529a70bb5a77935d086d651c63396767d240d7.tar.gz
Fix parallel index and index-only scans to fall back to serial.
Parallel executor nodes can't assume that parallel execution will happen in every case where the plan calls for it, because it might not work out that way. However, parallel index scan and parallel index-only scan failed to do the right thing here. Repair. Amit Kapila, per a report from me. Discussion: http://postgr.es/m/CAA4eK1Kq5qb_u2AOoda5XBB91vVWz90w=LgtRLgsssriS8pVTw@mail.gmail.com
Diffstat (limited to 'src/backend/executor/nodeIndexscan.c')
-rw-r--r--src/backend/executor/nodeIndexscan.c90
1 files changed, 58 insertions, 32 deletions
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 0a9dfdbaf3..cb6aff9137 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -102,6 +102,30 @@ IndexNext(IndexScanState *node)
econtext = node->ss.ps.ps_ExprContext;
slot = node->ss.ss_ScanTupleSlot;
+ if (scandesc == NULL)
+ {
+ /*
+ * We reach here if the index scan is not parallel, or if we're
+ * executing a index scan that was intended to be parallel serially.
+ */
+ scandesc = index_beginscan(node->ss.ss_currentRelation,
+ node->iss_RelationDesc,
+ estate->es_snapshot,
+ node->iss_NumScanKeys,
+ node->iss_NumOrderByKeys);
+
+ node->iss_ScanDesc = scandesc;
+
+ /*
+ * If no run-time keys to calculate or they are ready, go ahead and
+ * pass the scankeys to the index AM.
+ */
+ if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
+ index_rescan(scandesc,
+ node->iss_ScanKeys, node->iss_NumScanKeys,
+ node->iss_OrderByKeys, node->iss_NumOrderByKeys);
+ }
+
/*
* ok, now that we have what we need, fetch the next tuple.
*/
@@ -154,6 +178,7 @@ IndexNext(IndexScanState *node)
static TupleTableSlot *
IndexNextWithReorder(IndexScanState *node)
{
+ EState *estate;
ExprContext *econtext;
IndexScanDesc scandesc;
HeapTuple tuple;
@@ -164,6 +189,8 @@ IndexNextWithReorder(IndexScanState *node)
bool *lastfetched_nulls;
int cmp;
+ estate = node->ss.ps.state;
+
/*
* Only forward scan is supported with reordering. Note: we can get away
* with just Asserting here because the system will not try to run the
@@ -174,12 +201,36 @@ IndexNextWithReorder(IndexScanState *node)
* explicitly.
*/
Assert(!ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indexorderdir));
- Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction));
+ Assert(ScanDirectionIsForward(estate->es_direction));
scandesc = node->iss_ScanDesc;
econtext = node->ss.ps.ps_ExprContext;
slot = node->ss.ss_ScanTupleSlot;
+ if (scandesc == NULL)
+ {
+ /*
+ * We reach here if the index scan is not parallel, or if we're
+ * executing a index scan that was intended to be parallel serially.
+ */
+ scandesc = index_beginscan(node->ss.ss_currentRelation,
+ node->iss_RelationDesc,
+ estate->es_snapshot,
+ node->iss_NumScanKeys,
+ node->iss_NumOrderByKeys);
+
+ node->iss_ScanDesc = scandesc;
+
+ /*
+ * If no run-time keys to calculate or they are ready, go ahead and
+ * pass the scankeys to the index AM.
+ */
+ if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
+ index_rescan(scandesc,
+ node->iss_ScanKeys, node->iss_NumScanKeys,
+ node->iss_OrderByKeys, node->iss_NumOrderByKeys);
+ }
+
for (;;)
{
/*
@@ -1039,31 +1090,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
}
/*
- * for parallel-aware node, we initialize the scan descriptor after
- * initializing the shared memory for parallel execution.
- */
- if (!node->scan.plan.parallel_aware)
- {
- /*
- * Initialize scan descriptor.
- */
- indexstate->iss_ScanDesc = index_beginscan(currentRelation,
- indexstate->iss_RelationDesc,
- estate->es_snapshot,
- indexstate->iss_NumScanKeys,
- indexstate->iss_NumOrderByKeys);
-
- /*
- * If no run-time keys to calculate, go ahead and pass the scankeys to
- * the index AM.
- */
- if (indexstate->iss_NumRuntimeKeys == 0)
- index_rescan(indexstate->iss_ScanDesc,
- indexstate->iss_ScanKeys, indexstate->iss_NumScanKeys,
- indexstate->iss_OrderByKeys, indexstate->iss_NumOrderByKeys);
- }
-
- /*
* all done.
*/
return indexstate;
@@ -1674,10 +1700,10 @@ ExecIndexScanInitializeDSM(IndexScanState *node,
piscan);
/*
- * If no run-time keys to calculate, go ahead and pass the scankeys to the
- * index AM.
+ * If no run-time keys to calculate or they are ready, go ahead and pass
+ * the scankeys to the index AM.
*/
- if (node->iss_NumRuntimeKeys == 0)
+ if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
index_rescan(node->iss_ScanDesc,
node->iss_ScanKeys, node->iss_NumScanKeys,
node->iss_OrderByKeys, node->iss_NumOrderByKeys);
@@ -1703,10 +1729,10 @@ ExecIndexScanInitializeWorker(IndexScanState *node, shm_toc *toc)
piscan);
/*
- * If no run-time keys to calculate, go ahead and pass the scankeys to the
- * index AM.
+ * If no run-time keys to calculate or they are ready, go ahead and pass
+ * the scankeys to the index AM.
*/
- if (node->iss_NumRuntimeKeys == 0)
+ if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
index_rescan(node->iss_ScanDesc,
node->iss_ScanKeys, node->iss_NumScanKeys,
node->iss_OrderByKeys, node->iss_NumOrderByKeys);