Skip to content

Commit 290166f

Browse files
committed
Teach planner and executor to handle ScalarArrayOpExpr as an indexable
qualification when the underlying operator is indexable and useOr is true. That is, indexkey op ANY (ARRAY[...]) is effectively translated into an OR combination of one indexscan for each array element. This only works for bitmap index scans, of course, since regular indexscans no longer support OR'ing of scans. There are still some loose ends to clean up before changing 'x IN (list)' to translate as a ScalarArrayOpExpr; for instance predtest.c ought to be taught about it. But this gets the basic functionality in place.
1 parent dab52ab commit 290166f

File tree

12 files changed

+942
-318
lines changed

12 files changed

+942
-318
lines changed

src/backend/executor/nodeBitmapIndexscan.c

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.11 2005/11/22 18:17:10 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.12 2005/11/25 19:47:49 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -43,6 +43,7 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node)
4343
ItemPointerData tids[MAX_TIDS];
4444
int32 ntids;
4545
double nTuples = 0;
46+
bool doscan;
4647

4748
/* must provide our own instrumentation support */
4849
if (node->ss.ps.instrument)
@@ -55,9 +56,18 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node)
5556

5657
/*
5758
* If we have runtime keys and they've not already been set up, do it now.
59+
* Array keys are also treated as runtime keys; note that if ExecReScan
60+
* returns with biss_RuntimeKeysReady still false, then there is an
61+
* empty array key so we should do nothing.
5862
*/
59-
if (node->biss_RuntimeKeyInfo && !node->biss_RuntimeKeysReady)
63+
if (!node->biss_RuntimeKeysReady &&
64+
(node->biss_NumRuntimeKeys != 0 || node->biss_NumArrayKeys != 0))
65+
{
6066
ExecReScan((PlanState *) node, NULL);
67+
doscan = node->biss_RuntimeKeysReady;
68+
}
69+
else
70+
doscan = true;
6171

6272
/*
6373
* Prepare the result bitmap. Normally we just create a new one to pass
@@ -79,7 +89,7 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node)
7989
/*
8090
* Get TIDs from index and insert into bitmap
8191
*/
82-
for (;;)
92+
while (doscan)
8393
{
8494
bool more = index_getmulti(scandesc, tids, MAX_TIDS, &ntids);
8595

@@ -89,10 +99,15 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node)
8999
nTuples += ntids;
90100
}
91101

92-
if (!more)
93-
break;
94-
95102
CHECK_FOR_INTERRUPTS();
103+
104+
if (!more)
105+
{
106+
doscan = ExecIndexAdvanceArrayKeys(node->biss_ArrayKeys,
107+
node->biss_NumArrayKeys);
108+
if (doscan) /* reset index scan */
109+
index_rescan(node->biss_ScanDesc, node->biss_ScanKeys);
110+
}
96111
}
97112

98113
/* must provide our own instrumentation support */
@@ -113,10 +128,8 @@ void
113128
ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt)
114129
{
115130
ExprContext *econtext;
116-
ExprState **runtimeKeyInfo;
117131

118132
econtext = node->biss_RuntimeContext; /* context for runtime keys */
119-
runtimeKeyInfo = node->biss_RuntimeKeyInfo;
120133

121134
if (econtext)
122135
{
@@ -137,19 +150,27 @@ ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt)
137150

138151
/*
139152
* If we are doing runtime key calculations (ie, the index keys depend on
140-
* data from an outer scan), compute the new key values
153+
* data from an outer scan), compute the new key values.
154+
*
155+
* Array keys are also treated as runtime keys; note that if we
156+
* return with biss_RuntimeKeysReady still false, then there is an
157+
* empty array key so no index scan is needed.
141158
*/
142-
if (runtimeKeyInfo)
143-
{
159+
if (node->biss_NumRuntimeKeys != 0)
144160
ExecIndexEvalRuntimeKeys(econtext,
145-
runtimeKeyInfo,
146-
node->biss_ScanKeys,
147-
node->biss_NumScanKeys);
161+
node->biss_RuntimeKeys,
162+
node->biss_NumRuntimeKeys);
163+
if (node->biss_NumArrayKeys != 0)
164+
node->biss_RuntimeKeysReady =
165+
ExecIndexEvalArrayKeys(econtext,
166+
node->biss_ArrayKeys,
167+
node->biss_NumArrayKeys);
168+
else
148169
node->biss_RuntimeKeysReady = true;
149-
}
150170

151171
/* reset index scan */
152-
index_rescan(node->biss_ScanDesc, node->biss_ScanKeys);
172+
if (node->biss_RuntimeKeysReady)
173+
index_rescan(node->biss_ScanDesc, node->biss_ScanKeys);
153174
}
154175

155176
/* ----------------------------------------------------------------
@@ -193,10 +214,6 @@ BitmapIndexScanState *
193214
ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate)
194215
{
195216
BitmapIndexScanState *indexstate;
196-
ScanKey scanKeys;
197-
int numScanKeys;
198-
ExprState **runtimeKeyInfo;
199-
bool have_runtime_keys;
200217

201218
/*
202219
* create state structure
@@ -236,26 +253,25 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate)
236253
/*
237254
* build the index scan keys from the index qualification
238255
*/
239-
have_runtime_keys =
240-
ExecIndexBuildScanKeys((PlanState *) indexstate,
241-
node->indexqual,
242-
node->indexstrategy,
243-
node->indexsubtype,
244-
&runtimeKeyInfo,
245-
&scanKeys,
246-
&numScanKeys);
247-
248-
indexstate->biss_RuntimeKeyInfo = runtimeKeyInfo;
249-
indexstate->biss_ScanKeys = scanKeys;
250-
indexstate->biss_NumScanKeys = numScanKeys;
256+
ExecIndexBuildScanKeys((PlanState *) indexstate,
257+
node->indexqual,
258+
node->indexstrategy,
259+
node->indexsubtype,
260+
&indexstate->biss_ScanKeys,
261+
&indexstate->biss_NumScanKeys,
262+
&indexstate->biss_RuntimeKeys,
263+
&indexstate->biss_NumRuntimeKeys,
264+
&indexstate->biss_ArrayKeys,
265+
&indexstate->biss_NumArrayKeys);
251266

252267
/*
253-
* If we have runtime keys, we need an ExprContext to evaluate them. We
254-
* could just create a "standard" plan node exprcontext, but to keep the
255-
* code looking similar to nodeIndexscan.c, it seems better to stick with
256-
* the approach of using a separate ExprContext.
268+
* If we have runtime keys or array keys, we need an ExprContext to
269+
* evaluate them. We could just create a "standard" plan node exprcontext,
270+
* but to keep the code looking similar to nodeIndexscan.c, it seems
271+
* better to stick with the approach of using a separate ExprContext.
257272
*/
258-
if (have_runtime_keys)
273+
if (indexstate->biss_NumRuntimeKeys != 0 ||
274+
indexstate->biss_NumArrayKeys != 0)
259275
{
260276
ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
261277

@@ -286,8 +302,8 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate)
286302
indexstate->biss_ScanDesc =
287303
index_beginscan_multi(indexstate->biss_RelationDesc,
288304
estate->es_snapshot,
289-
numScanKeys,
290-
scanKeys);
305+
indexstate->biss_NumScanKeys,
306+
indexstate->biss_ScanKeys);
291307

292308
/*
293309
* all done.

0 commit comments

Comments
 (0)