7
7
*
8
8
*
9
9
* 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 $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -87,15 +87,15 @@ IndexNext(IndexScan *node)
87
87
IndexScanState * indexstate ;
88
88
ScanDirection direction ;
89
89
Snapshot snapshot ;
90
- int indexPtr ;
91
90
IndexScanDescPtr scanDescs ;
92
91
IndexScanDesc scandesc ;
93
92
Relation heapRelation ;
94
93
RetrieveIndexResult result ;
95
94
HeapTuple tuple ;
96
95
TupleTableSlot * slot ;
97
96
Buffer buffer = InvalidBuffer ;
98
-
97
+ int numIndices ;
98
+
99
99
/* ----------------
100
100
* extract necessary information from index scan node
101
101
* ----------------
@@ -105,54 +105,66 @@ IndexNext(IndexScan *node)
105
105
snapshot = estate -> es_snapshot ;
106
106
scanstate = node -> scan .scanstate ;
107
107
indexstate = node -> indxstate ;
108
- indexPtr = indexstate -> iss_IndexPtr ;
109
108
scanDescs = indexstate -> iss_ScanDescs ;
110
- scandesc = scanDescs [indexPtr ];
111
109
heapRelation = scanstate -> css_currentRelation ;
112
-
110
+ numIndices = indexstate -> iss_NumIndices ;
113
111
slot = scanstate -> css_ScanTupleSlot ;
114
112
115
113
/* ----------------
116
114
* ok, now that we have what we need, fetch an index tuple.
117
- * ----------------
118
- */
119
-
120
- /* ----------------
121
115
* if scanning this index succeeded then return the
122
116
* appropriate heap tuple.. else return NULL.
123
117
* ----------------
124
118
*/
125
- while (( result = index_getnext ( scandesc , direction )) != NULL )
119
+ while (indexstate -> iss_IndexPtr < numIndices )
126
120
{
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 )
150
123
{
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
+ }
151
162
if (BufferIsValid (buffer ))
152
163
ReleaseBuffer (buffer );
153
164
}
165
+ if (indexstate -> iss_IndexPtr < numIndices )
166
+ indexstate -> iss_IndexPtr ++ ;
154
167
}
155
-
156
168
/* ----------------
157
169
* if we get here it means the index scan failed so we
158
170
* are at the end of the scan..
@@ -218,7 +230,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
218
230
int i ;
219
231
220
232
Pointer * runtimeKeyInfo ;
221
- int indexPtr ;
222
233
int * numScanKeys ;
223
234
List * indxqual ;
224
235
List * qual ;
@@ -238,69 +249,62 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
238
249
numIndices = indexstate -> iss_NumIndices ;
239
250
scanDescs = indexstate -> iss_ScanDescs ;
240
251
scanKeys = indexstate -> iss_ScanKeys ;
241
-
242
252
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 ;
243
260
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 ;
258
264
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 )
264
272
{
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 ++ )
272
279
{
273
- clause = nth (j , qual );
274
- scanexpr = (run_keys [j ] == RIGHT_OP ) ?
275
- (Node * ) get_rightop (clause ) : (Node * ) get_leftop (clause );
276
-
277
280
/*
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.
280
284
*/
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
+ }
288
303
}
304
+ sdesc = scanDescs [i ];
305
+ skey = scanKeys [i ];
306
+ index_rescan (sdesc , direction , skey );
289
307
}
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
- }
304
308
305
309
/* ----------------
306
310
* perhaps return something meaningful
@@ -322,19 +326,23 @@ ExecEndIndexScan(IndexScan *node)
322
326
{
323
327
CommonScanState * scanstate ;
324
328
IndexScanState * indexstate ;
329
+ Pointer * runtimeKeyInfo ;
325
330
ScanKey * scanKeys ;
331
+ int * numScanKeys ;
326
332
int numIndices ;
327
333
int i ;
328
334
329
335
scanstate = node -> scan .scanstate ;
330
336
indexstate = node -> indxstate ;
331
-
337
+ runtimeKeyInfo = (Pointer * ) indexstate -> iss_RuntimeKeyInfo ;
338
+
332
339
/* ----------------
333
340
* extract information from the node
334
341
* ----------------
335
342
*/
336
343
numIndices = indexstate -> iss_NumIndices ;
337
344
scanKeys = indexstate -> iss_ScanKeys ;
345
+ numScanKeys = indexstate -> iss_NumScanKeys ;
338
346
339
347
/* ----------------
340
348
* Free the projection info and the scan attribute info
@@ -362,7 +370,24 @@ ExecEndIndexScan(IndexScan *node)
362
370
if (scanKeys [i ] != NULL )
363
371
pfree (scanKeys [i ]);
364
372
}
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 ;
365
382
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
+
366
391
/* ----------------
367
392
* clear out tuple table slots
368
393
* ----------------
@@ -430,7 +455,7 @@ ExecIndexRestrPos(IndexScan *node)
430
455
431
456
/* ----------------------------------------------------------------
432
457
* ExecInitIndexScan
433
- *
458
+ *
434
459
* Initializes the index scan's state information, creates
435
460
* scan keys, and opens the base and index relations.
436
461
*
@@ -886,20 +911,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
886
911
if (have_runtime_keys )
887
912
indexstate -> iss_RuntimeKeyInfo = (Pointer ) runtimeKeyInfo ;
888
913
else
889
- {
890
914
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
- }
903
915
904
916
/* ----------------
905
917
* get the range table and direction information
991
1003
ExecCountSlotsIndexScan (IndexScan * node )
992
1004
{
993
1005
return ExecCountSlotsNode (outerPlan ((Plan * ) node )) +
994
- ExecCountSlotsNode (innerPlan ((Plan * ) node )) +
995
- INDEXSCAN_NSLOTS ;
1006
+ ExecCountSlotsNode (innerPlan ((Plan * ) node )) + INDEXSCAN_NSLOTS ;
996
1007
}
0 commit comments