Skip to content

Commit 70bc583

Browse files
committed
Fix btmarkpos/btrestrpos to handle array keys.
This fixes another error in commit 9e8da0f. I neglected to make the mark/restore functionality save and restore the current set of array key values, which led to strange behavior if an IndexScan with ScalarArrayOpExpr quals was used as the inner side of a mergejoin. Per bug #7570 from Melese Tesfaye.
1 parent ae90ffa commit 70bc583

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

src/backend/access/nbtree/nbtree.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,10 @@ btmarkpos(PG_FUNCTION_ARGS)
584584
else
585585
so->markItemIndex = -1;
586586

587+
/* Also record the current positions of any array keys */
588+
if (so->numArrayKeys)
589+
_bt_mark_array_keys(scan);
590+
587591
PG_RETURN_VOID();
588592
}
589593

@@ -596,6 +600,10 @@ btrestrpos(PG_FUNCTION_ARGS)
596600
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
597601
BTScanOpaque so = (BTScanOpaque) scan->opaque;
598602

603+
/* Restore the marked positions of any array keys */
604+
if (so->numArrayKeys)
605+
_bt_restore_array_keys(scan);
606+
599607
if (so->markItemIndex >= 0)
600608
{
601609
/*

src/backend/access/nbtree/nbtutils.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,65 @@ _bt_advance_array_keys(IndexScanDesc scan, ScanDirection dir)
595595
return found;
596596
}
597597

598+
/*
599+
* _bt_mark_array_keys() -- Handle array keys during btmarkpos
600+
*
601+
* Save the current state of the array keys as the "mark" position.
602+
*/
603+
void
604+
_bt_mark_array_keys(IndexScanDesc scan)
605+
{
606+
BTScanOpaque so = (BTScanOpaque) scan->opaque;
607+
int i;
608+
609+
for (i = 0; i < so->numArrayKeys; i++)
610+
{
611+
BTArrayKeyInfo *curArrayKey = &so->arrayKeys[i];
612+
613+
curArrayKey->mark_elem = curArrayKey->cur_elem;
614+
}
615+
}
616+
617+
/*
618+
* _bt_restore_array_keys() -- Handle array keys during btrestrpos
619+
*
620+
* Restore the array keys to where they were when the mark was set.
621+
*/
622+
void
623+
_bt_restore_array_keys(IndexScanDesc scan)
624+
{
625+
BTScanOpaque so = (BTScanOpaque) scan->opaque;
626+
bool changed = false;
627+
int i;
628+
629+
/* Restore each array key to its position when the mark was set */
630+
for (i = 0; i < so->numArrayKeys; i++)
631+
{
632+
BTArrayKeyInfo *curArrayKey = &so->arrayKeys[i];
633+
ScanKey skey = &so->arrayKeyData[curArrayKey->scan_key];
634+
int mark_elem = curArrayKey->mark_elem;
635+
636+
if (curArrayKey->cur_elem != mark_elem)
637+
{
638+
curArrayKey->cur_elem = mark_elem;
639+
skey->sk_argument = curArrayKey->elem_values[mark_elem];
640+
changed = true;
641+
}
642+
}
643+
644+
/*
645+
* If we changed any keys, we must redo _bt_preprocess_keys. That might
646+
* sound like overkill, but in cases with multiple keys per index column
647+
* it seems necessary to do the full set of pushups.
648+
*/
649+
if (changed)
650+
{
651+
_bt_preprocess_keys(scan);
652+
/* The mark should have been set on a consistent set of keys... */
653+
Assert(so->qual_ok);
654+
}
655+
}
656+
598657

599658
/*
600659
* _bt_preprocess_keys() -- Preprocess scan keys

src/include/access/nbtree.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ typedef struct BTArrayKeyInfo
535535
{
536536
int scan_key; /* index of associated key in arrayKeyData */
537537
int cur_elem; /* index of current element in elem_values */
538+
int mark_elem; /* index of marked element in elem_values */
538539
int num_elems; /* number of elems in current array value */
539540
Datum *elem_values; /* array of num_elems Datums */
540541
} BTArrayKeyInfo;
@@ -665,6 +666,8 @@ extern void _bt_freestack(BTStack stack);
665666
extern void _bt_preprocess_array_keys(IndexScanDesc scan);
666667
extern void _bt_start_array_keys(IndexScanDesc scan, ScanDirection dir);
667668
extern bool _bt_advance_array_keys(IndexScanDesc scan, ScanDirection dir);
669+
extern void _bt_mark_array_keys(IndexScanDesc scan);
670+
extern void _bt_restore_array_keys(IndexScanDesc scan);
668671
extern void _bt_preprocess_keys(IndexScanDesc scan);
669672
extern IndexTuple _bt_checkkeys(IndexScanDesc scan,
670673
Page page, OffsetNumber offnum,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy