Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0a2e5cd

Browse files
committed
Allow index use with OR clauses.
1 parent 0668aa8 commit 0a2e5cd

File tree

9 files changed

+287
-316
lines changed

9 files changed

+287
-316
lines changed

src/backend/executor/execQual.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.33 1998/06/15 19:28:19 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.34 1998/08/01 22:12:02 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -1349,8 +1349,6 @@ ExecQual(List *qual, ExprContext *econtext)
13491349

13501350
foreach(clause, qual)
13511351
{
1352-
1353-
13541352
result = ExecQualClause((Node *) lfirst(clause), econtext);
13551353
if (result == true)
13561354
break;

src/backend/executor/nodeIndexscan.c

Lines changed: 118 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.19 1998/07/27 19:37:57 vadim Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.20 1998/08/01 22:12:04 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -87,15 +87,15 @@ IndexNext(IndexScan *node)
8787
IndexScanState *indexstate;
8888
ScanDirection direction;
8989
Snapshot snapshot;
90-
int indexPtr;
9190
IndexScanDescPtr scanDescs;
9291
IndexScanDesc scandesc;
9392
Relation heapRelation;
9493
RetrieveIndexResult result;
9594
HeapTuple tuple;
9695
TupleTableSlot *slot;
9796
Buffer buffer = InvalidBuffer;
98-
97+
int numIndices;
98+
9999
/* ----------------
100100
* extract necessary information from index scan node
101101
* ----------------
@@ -105,54 +105,66 @@ IndexNext(IndexScan *node)
105105
snapshot = estate->es_snapshot;
106106
scanstate = node->scan.scanstate;
107107
indexstate = node->indxstate;
108-
indexPtr = indexstate->iss_IndexPtr;
109108
scanDescs = indexstate->iss_ScanDescs;
110-
scandesc = scanDescs[indexPtr];
111109
heapRelation = scanstate->css_currentRelation;
112-
110+
numIndices = indexstate->iss_NumIndices;
113111
slot = scanstate->css_ScanTupleSlot;
114112

115113
/* ----------------
116114
* ok, now that we have what we need, fetch an index tuple.
117-
* ----------------
118-
*/
119-
120-
/* ----------------
121115
* if scanning this index succeeded then return the
122116
* appropriate heap tuple.. else return NULL.
123117
* ----------------
124118
*/
125-
while ((result = index_getnext(scandesc, direction)) != NULL)
119+
while (indexstate->iss_IndexPtr < numIndices)
126120
{
127-
tuple = heap_fetch(heapRelation, snapshot,
128-
&result->heap_iptr, &buffer);
129-
/* be tidy */
130-
pfree(result);
131-
132-
if (tuple != NULL)
133-
{
134-
/* ----------------
135-
* store the scanned tuple in the scan tuple slot of
136-
* the scan state. Eventually we will only do this and not
137-
* return a tuple. Note: we pass 'false' because tuples
138-
* returned by amgetnext are pointers onto disk pages and
139-
* were not created with palloc() and so should not be pfree()'d.
140-
* ----------------
141-
*/
142-
ExecStoreTuple(tuple, /* tuple to store */
143-
slot, /* slot to store in */
144-
buffer, /* buffer associated with tuple */
145-
false); /* don't pfree */
146-
147-
return slot;
148-
}
149-
else
121+
scandesc = scanDescs[indexstate->iss_IndexPtr];
122+
while ((result = index_getnext(scandesc, direction)) != NULL)
150123
{
124+
tuple = heap_fetch(heapRelation, snapshot,
125+
&result->heap_iptr, &buffer);
126+
/* be tidy */
127+
pfree(result);
128+
129+
if (tuple != NULL)
130+
{
131+
bool prev_matches = false;
132+
int prev_index;
133+
134+
/* ----------------
135+
* store the scanned tuple in the scan tuple slot of
136+
* the scan state. Eventually we will only do this and not
137+
* return a tuple. Note: we pass 'false' because tuples
138+
* returned by amgetnext are pointers onto disk pages and
139+
* were not created with palloc() and so should not be pfree()'d.
140+
* ----------------
141+
*/
142+
ExecStoreTuple(tuple, /* tuple to store */
143+
slot, /* slot to store in */
144+
buffer, /* buffer associated with tuple */
145+
false); /* don't pfree */
146+
147+
for (prev_index = 0; prev_index < indexstate->iss_IndexPtr;
148+
prev_index++)
149+
{
150+
if (ExecQual(nth(prev_index, node->indxqual),
151+
scanstate->cstate.cs_ExprContext))
152+
{
153+
prev_matches = true;
154+
break;
155+
}
156+
}
157+
if (!prev_matches)
158+
return slot;
159+
else
160+
ExecClearTuple(slot);
161+
}
151162
if (BufferIsValid(buffer))
152163
ReleaseBuffer(buffer);
153164
}
165+
if (indexstate->iss_IndexPtr < numIndices)
166+
indexstate->iss_IndexPtr++;
154167
}
155-
156168
/* ----------------
157169
* if we get here it means the index scan failed so we
158170
* are at the end of the scan..
@@ -218,7 +230,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
218230
int i;
219231

220232
Pointer *runtimeKeyInfo;
221-
int indexPtr;
222233
int *numScanKeys;
223234
List *indxqual;
224235
List *qual;
@@ -238,69 +249,62 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
238249
numIndices = indexstate->iss_NumIndices;
239250
scanDescs = indexstate->iss_ScanDescs;
240251
scanKeys = indexstate->iss_ScanKeys;
241-
242252
runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
253+
indxqual = node->indxqual;
254+
numScanKeys = indexstate->iss_NumScanKeys;
255+
indexstate->iss_IndexPtr = 0;
256+
257+
/* it's possible in subselects */
258+
if (exprCtxt == NULL)
259+
exprCtxt = node->scan.scanstate->cstate.cs_ExprContext;
243260

244-
if (runtimeKeyInfo != NULL)
245-
{
246-
247-
/*
248-
* get the index qualifications and recalculate the appropriate
249-
* values
250-
*/
251-
indexPtr = indexstate->iss_IndexPtr;
252-
indxqual = node->indxqual;
253-
qual = nth(indexPtr, indxqual);
254-
numScanKeys = indexstate->iss_NumScanKeys;
255-
n_keys = numScanKeys[indexPtr];
256-
run_keys = (int *) runtimeKeyInfo[indexPtr];
257-
scan_keys = (ScanKey) scanKeys[indexPtr];
261+
if (exprCtxt != NULL)
262+
node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple =
263+
exprCtxt->ecxt_outertuple;
258264

259-
/* it's possible in subselects */
260-
if (exprCtxt == NULL)
261-
exprCtxt = node->scan.scanstate->cstate.cs_ExprContext;
262-
263-
for (j = 0; j < n_keys; j++)
265+
/*
266+
* get the index qualifications and recalculate the appropriate
267+
* values
268+
*/
269+
for (i = 0; i < numIndices; i++)
270+
{
271+
if (runtimeKeyInfo && runtimeKeyInfo[i] != NULL)
264272
{
265-
266-
/*
267-
* If we have a run-time key, then extract the run-time
268-
* expression and evaluate it with respect to the current
269-
* outer tuple. We then stick the result into the scan key.
270-
*/
271-
if (run_keys[j] != NO_OP)
273+
qual = nth(i, indxqual);
274+
n_keys = numScanKeys[i];
275+
run_keys = (int *) runtimeKeyInfo[i];
276+
scan_keys = (ScanKey) scanKeys[i];
277+
278+
for (j = 0; j < n_keys; j++)
272279
{
273-
clause = nth(j, qual);
274-
scanexpr = (run_keys[j] == RIGHT_OP) ?
275-
(Node *) get_rightop(clause) : (Node *) get_leftop(clause);
276-
277280
/*
278-
* pass in isDone but ignore it. We don't iterate in
279-
* quals
281+
* If we have a run-time key, then extract the run-time
282+
* expression and evaluate it with respect to the current
283+
* outer tuple. We then stick the result into the scan key.
280284
*/
281-
scanvalue = (Datum)
282-
ExecEvalExpr(scanexpr, exprCtxt, &isNull, &isDone);
283-
scan_keys[j].sk_argument = scanvalue;
284-
if (isNull)
285-
scan_keys[j].sk_flags |= SK_ISNULL;
286-
else
287-
scan_keys[j].sk_flags &= ~SK_ISNULL;
285+
if (run_keys[j] != NO_OP)
286+
{
287+
clause = nth(j, qual);
288+
scanexpr = (run_keys[j] == RIGHT_OP) ?
289+
(Node *) get_rightop(clause) : (Node *) get_leftop(clause);
290+
291+
/*
292+
* pass in isDone but ignore it. We don't iterate in
293+
* quals
294+
*/
295+
scanvalue = (Datum)
296+
ExecEvalExpr(scanexpr, exprCtxt, &isNull, &isDone);
297+
scan_keys[j].sk_argument = scanvalue;
298+
if (isNull)
299+
scan_keys[j].sk_flags |= SK_ISNULL;
300+
else
301+
scan_keys[j].sk_flags &= ~SK_ISNULL;
302+
}
288303
}
304+
sdesc = scanDescs[i];
305+
skey = scanKeys[i];
306+
index_rescan(sdesc, direction, skey);
289307
}
290-
}
291-
292-
/*
293-
* rescans all indices
294-
*
295-
* note: AMrescan assumes only one scan key. This may have to change if
296-
* we ever decide to support multiple keys.
297-
*/
298-
for (i = 0; i < numIndices; i++)
299-
{
300-
sdesc = scanDescs[i];
301-
skey = scanKeys[i];
302-
index_rescan(sdesc, direction, skey);
303-
}
304308

305309
/* ----------------
306310
* perhaps return something meaningful
@@ -322,19 +326,23 @@ ExecEndIndexScan(IndexScan *node)
322326
{
323327
CommonScanState *scanstate;
324328
IndexScanState *indexstate;
329+
Pointer *runtimeKeyInfo;
325330
ScanKey *scanKeys;
331+
int *numScanKeys;
326332
int numIndices;
327333
int i;
328334

329335
scanstate = node->scan.scanstate;
330336
indexstate = node->indxstate;
331-
337+
runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
338+
332339
/* ----------------
333340
* extract information from the node
334341
* ----------------
335342
*/
336343
numIndices = indexstate->iss_NumIndices;
337344
scanKeys = indexstate->iss_ScanKeys;
345+
numScanKeys = indexstate->iss_NumScanKeys;
338346

339347
/* ----------------
340348
* Free the projection info and the scan attribute info
@@ -362,7 +370,24 @@ ExecEndIndexScan(IndexScan *node)
362370
if (scanKeys[i] != NULL)
363371
pfree(scanKeys[i]);
364372
}
373+
pfree(scanKeys);
374+
pfree(numScanKeys);
375+
376+
if (runtimeKeyInfo)
377+
{
378+
for (i = 0; i < numIndices; i++)
379+
{
380+
List *qual;
381+
int n_keys;
365382

383+
qual = nth(i, indxqual);
384+
n_keys = length(qual);
385+
if (n_keys > 0)
386+
pfree(runtimeKeyInfo[i]);
387+
}
388+
pfree(runtimeKeyInfo);
389+
}
390+
366391
/* ----------------
367392
* clear out tuple table slots
368393
* ----------------
@@ -430,7 +455,7 @@ ExecIndexRestrPos(IndexScan *node)
430455

431456
/* ----------------------------------------------------------------
432457
* ExecInitIndexScan
433-
*
458+
*
434459
* Initializes the index scan's state information, creates
435460
* scan keys, and opens the base and index relations.
436461
*
@@ -886,20 +911,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
886911
if (have_runtime_keys)
887912
indexstate->iss_RuntimeKeyInfo = (Pointer) runtimeKeyInfo;
888913
else
889-
{
890914
indexstate->iss_RuntimeKeyInfo = NULL;
891-
for (i = 0; i < numIndices; i++)
892-
{
893-
List *qual;
894-
int n_keys;
895-
896-
qual = nth(i, indxqual);
897-
n_keys = length(qual);
898-
if (n_keys > 0)
899-
pfree(runtimeKeyInfo[i]);
900-
}
901-
pfree(runtimeKeyInfo);
902-
}
903915

904916
/* ----------------
905917
* get the range table and direction information
@@ -991,6 +1003,5 @@ int
9911003
ExecCountSlotsIndexScan(IndexScan *node)
9921004
{
9931005
return ExecCountSlotsNode(outerPlan((Plan *) node)) +
994-
ExecCountSlotsNode(innerPlan((Plan *) node)) +
995-
INDEXSCAN_NSLOTS;
1006+
ExecCountSlotsNode(innerPlan((Plan *) node)) + INDEXSCAN_NSLOTS;
9961007
}

0 commit comments

Comments
 (0)