Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9e8da0f

Browse files
committed
Teach btree to handle ScalarArrayOpExpr quals natively.
This allows "indexedcol op ANY(ARRAY[...])" conditions to be used in plainindexscans, and particularly in index-only scans.
1 parent0898d71 commit9e8da0f

File tree

13 files changed

+725
-128
lines changed

13 files changed

+725
-128
lines changed

‎doc/src/sgml/catalogs.sgml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,13 @@
491491
for the first index column?</entry>
492492
</row>
493493

494+
<row>
495+
<entry><structfield>amsearcharray</structfield></entry>
496+
<entry><type>bool</type></entry>
497+
<entry></entry>
498+
<entry>Does the access method support <literal>ScalarArrayOpExpr</> searches?</entry>
499+
</row>
500+
494501
<row>
495502
<entry><structfield>amsearchnulls</structfield></entry>
496503
<entry><type>bool</type></entry>

‎src/backend/access/nbtree/nbtree.c

Lines changed: 100 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -276,39 +276,63 @@ btgettuple(PG_FUNCTION_ARGS)
276276
scan->xs_recheck= false;
277277

278278
/*
279-
* If we've already initialized this scan, we can just advance it in the
280-
*appropriate direction.If we haven'tdone so yet,wecall a routine to
281-
*get the first item in the scan.
279+
* If we have any array keys, initialize them during first call for a
280+
*scan.We can'tdo this in btrescan becausewedon't know the scan
281+
*direction at that time.
282282
*/
283-
if (BTScanPosIsValid(so->currPos))
283+
if (so->numArrayKeys&& !BTScanPosIsValid(so->currPos))
284+
{
285+
/* punt if we have any unsatisfiable array keys */
286+
if (so->numArrayKeys<0)
287+
PG_RETURN_BOOL(false);
288+
289+
_bt_start_array_keys(scan,dir);
290+
}
291+
292+
/* This loop handles advancing to the next array elements, if any */
293+
do
284294
{
285295
/*
286-
* Check to see if we should kill the previously-fetched tuple.
296+
* If we've already initialized this scan, we can just advance it in
297+
* the appropriate direction. If we haven't done so yet, we call
298+
* _bt_first() to get the first item in the scan.
287299
*/
288-
if (scan->kill_prior_tuple)
300+
if (!BTScanPosIsValid(so->currPos))
301+
res=_bt_first(scan,dir);
302+
else
289303
{
290304
/*
291-
* Yes, remember it for later.(We'll deal with all such tuples
292-
* at once right before leaving the index page.) The test for
293-
* numKilled overrun is not just paranoia: if the caller reverses
294-
* direction in the indexscan then the same item might get entered
295-
* multiple times.It's not worth trying to optimize that, so we
296-
* don't detect it, but instead just forget any excess entries.
305+
* Check to see if we should kill the previously-fetched tuple.
297306
*/
298-
if (so->killedItems==NULL)
299-
so->killedItems= (int*)
300-
palloc(MaxIndexTuplesPerPage*sizeof(int));
301-
if (so->numKilled<MaxIndexTuplesPerPage)
302-
so->killedItems[so->numKilled++]=so->currPos.itemIndex;
307+
if (scan->kill_prior_tuple)
308+
{
309+
/*
310+
* Yes, remember it for later. (We'll deal with all such
311+
* tuples at once right before leaving the index page.) The
312+
* test for numKilled overrun is not just paranoia: if the
313+
* caller reverses direction in the indexscan then the same
314+
* item might get entered multiple times. It's not worth
315+
* trying to optimize that, so we don't detect it, but instead
316+
* just forget any excess entries.
317+
*/
318+
if (so->killedItems==NULL)
319+
so->killedItems= (int*)
320+
palloc(MaxIndexTuplesPerPage*sizeof(int));
321+
if (so->numKilled<MaxIndexTuplesPerPage)
322+
so->killedItems[so->numKilled++]=so->currPos.itemIndex;
323+
}
324+
325+
/*
326+
* Now continue the scan.
327+
*/
328+
res=_bt_next(scan,dir);
303329
}
304330

305-
/*
306-
* Now continue the scan.
307-
*/
308-
res=_bt_next(scan,dir);
309-
}
310-
else
311-
res=_bt_first(scan,dir);
331+
/* If we have a tuple, return it ... */
332+
if (res)
333+
break;
334+
/* ... otherwise see if we have more array keys to deal with */
335+
}while (so->numArrayKeys&&_bt_advance_array_keys(scan,dir));
312336

313337
PG_RETURN_BOOL(res);
314338
}
@@ -325,35 +349,50 @@ btgetbitmap(PG_FUNCTION_ARGS)
325349
int64ntids=0;
326350
ItemPointerheapTid;
327351

328-
/* Fetch the first page & tuple. */
329-
if (!_bt_first(scan,ForwardScanDirection))
352+
/*
353+
* If we have any array keys, initialize them.
354+
*/
355+
if (so->numArrayKeys)
330356
{
331-
/* empty scan */
332-
PG_RETURN_INT64(0);
357+
/* punt if we have any unsatisfiable array keys */
358+
if (so->numArrayKeys<0)
359+
PG_RETURN_INT64(ntids);
360+
361+
_bt_start_array_keys(scan,ForwardScanDirection);
333362
}
334-
/* Save tuple ID, and continue scanning */
335-
heapTid=&scan->xs_ctup.t_self;
336-
tbm_add_tuples(tbm,heapTid,1, false);
337-
ntids++;
338363

339-
for (;;)
364+
/* This loop handles advancing to the next array elements, if any */
365+
do
340366
{
341-
/*
342-
* Advance to next tuple within page. This is the same as the easy
343-
* case in _bt_next().
344-
*/
345-
if (++so->currPos.itemIndex>so->currPos.lastItem)
367+
/* Fetch the first page & tuple */
368+
if (_bt_first(scan,ForwardScanDirection))
346369
{
347-
/*let _bt_next do the heavy lifting */
348-
if (!_bt_next(scan,ForwardScanDirection))
349-
break;
350-
}
370+
/*Save tuple ID, and continue scanning */
371+
heapTid=&scan->xs_ctup.t_self;
372+
tbm_add_tuples(tbm,heapTid,1, false);
373+
ntids++;
351374

352-
/* Save tuple ID, and continue scanning */
353-
heapTid=&so->currPos.items[so->currPos.itemIndex].heapTid;
354-
tbm_add_tuples(tbm,heapTid,1, false);
355-
ntids++;
356-
}
375+
for (;;)
376+
{
377+
/*
378+
* Advance to next tuple within page. This is the same as the
379+
* easy case in _bt_next().
380+
*/
381+
if (++so->currPos.itemIndex>so->currPos.lastItem)
382+
{
383+
/* let _bt_next do the heavy lifting */
384+
if (!_bt_next(scan,ForwardScanDirection))
385+
break;
386+
}
387+
388+
/* Save tuple ID, and continue scanning */
389+
heapTid=&so->currPos.items[so->currPos.itemIndex].heapTid;
390+
tbm_add_tuples(tbm,heapTid,1, false);
391+
ntids++;
392+
}
393+
}
394+
/* Now see if we have more array keys to deal with */
395+
}while (so->numArrayKeys&&_bt_advance_array_keys(scan,ForwardScanDirection));
357396

358397
PG_RETURN_INT64(ntids);
359398
}
@@ -383,6 +422,12 @@ btbeginscan(PG_FUNCTION_ARGS)
383422
so->keyData= (ScanKey)palloc(scan->numberOfKeys*sizeof(ScanKeyData));
384423
else
385424
so->keyData=NULL;
425+
426+
so->arrayKeyData=NULL;/* assume no array keys for now */
427+
so->numArrayKeys=0;
428+
so->arrayKeys=NULL;
429+
so->arrayContext=NULL;
430+
386431
so->killedItems=NULL;/* until needed */
387432
so->numKilled=0;
388433

@@ -460,6 +505,9 @@ btrescan(PG_FUNCTION_ARGS)
460505
scan->numberOfKeys*sizeof(ScanKeyData));
461506
so->numberOfKeys=0;/* until _bt_preprocess_keys sets it */
462507

508+
/* If any keys are SK_SEARCHARRAY type, set up array-key info */
509+
_bt_preprocess_array_keys(scan);
510+
463511
PG_RETURN_VOID();
464512
}
465513

@@ -490,10 +538,13 @@ btendscan(PG_FUNCTION_ARGS)
490538
so->markItemIndex=-1;
491539

492540
/* Release storage */
493-
if (so->killedItems!=NULL)
494-
pfree(so->killedItems);
495541
if (so->keyData!=NULL)
496542
pfree(so->keyData);
543+
/* so->arrayKeyData and so->arrayKeys are in arrayContext */
544+
if (so->arrayContext!=NULL)
545+
MemoryContextDelete(so->arrayContext);
546+
if (so->killedItems!=NULL)
547+
pfree(so->killedItems);
497548
if (so->currTuples!=NULL)
498549
pfree(so->currTuples);
499550
/* so->markTuples should not be pfree'd, see btrescan */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp