mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Fix btmarkpos/btrestrpos to handle array keys.
This fixes another error in commit 9e8da0f75731aaa7605cf4656c21ea09e84d2eb1. 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.
This commit is contained in:
parent
ae90ffada4
commit
70bc583319
@ -584,6 +584,10 @@ btmarkpos(PG_FUNCTION_ARGS)
|
||||
else
|
||||
so->markItemIndex = -1;
|
||||
|
||||
/* Also record the current positions of any array keys */
|
||||
if (so->numArrayKeys)
|
||||
_bt_mark_array_keys(scan);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
@ -596,6 +600,10 @@ btrestrpos(PG_FUNCTION_ARGS)
|
||||
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
BTScanOpaque so = (BTScanOpaque) scan->opaque;
|
||||
|
||||
/* Restore the marked positions of any array keys */
|
||||
if (so->numArrayKeys)
|
||||
_bt_restore_array_keys(scan);
|
||||
|
||||
if (so->markItemIndex >= 0)
|
||||
{
|
||||
/*
|
||||
|
@ -595,6 +595,65 @@ _bt_advance_array_keys(IndexScanDesc scan, ScanDirection dir)
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
* _bt_mark_array_keys() -- Handle array keys during btmarkpos
|
||||
*
|
||||
* Save the current state of the array keys as the "mark" position.
|
||||
*/
|
||||
void
|
||||
_bt_mark_array_keys(IndexScanDesc scan)
|
||||
{
|
||||
BTScanOpaque so = (BTScanOpaque) scan->opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < so->numArrayKeys; i++)
|
||||
{
|
||||
BTArrayKeyInfo *curArrayKey = &so->arrayKeys[i];
|
||||
|
||||
curArrayKey->mark_elem = curArrayKey->cur_elem;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* _bt_restore_array_keys() -- Handle array keys during btrestrpos
|
||||
*
|
||||
* Restore the array keys to where they were when the mark was set.
|
||||
*/
|
||||
void
|
||||
_bt_restore_array_keys(IndexScanDesc scan)
|
||||
{
|
||||
BTScanOpaque so = (BTScanOpaque) scan->opaque;
|
||||
bool changed = false;
|
||||
int i;
|
||||
|
||||
/* Restore each array key to its position when the mark was set */
|
||||
for (i = 0; i < so->numArrayKeys; i++)
|
||||
{
|
||||
BTArrayKeyInfo *curArrayKey = &so->arrayKeys[i];
|
||||
ScanKey skey = &so->arrayKeyData[curArrayKey->scan_key];
|
||||
int mark_elem = curArrayKey->mark_elem;
|
||||
|
||||
if (curArrayKey->cur_elem != mark_elem)
|
||||
{
|
||||
curArrayKey->cur_elem = mark_elem;
|
||||
skey->sk_argument = curArrayKey->elem_values[mark_elem];
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we changed any keys, we must redo _bt_preprocess_keys. That might
|
||||
* sound like overkill, but in cases with multiple keys per index column
|
||||
* it seems necessary to do the full set of pushups.
|
||||
*/
|
||||
if (changed)
|
||||
{
|
||||
_bt_preprocess_keys(scan);
|
||||
/* The mark should have been set on a consistent set of keys... */
|
||||
Assert(so->qual_ok);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* _bt_preprocess_keys() -- Preprocess scan keys
|
||||
|
@ -535,6 +535,7 @@ typedef struct BTArrayKeyInfo
|
||||
{
|
||||
int scan_key; /* index of associated key in arrayKeyData */
|
||||
int cur_elem; /* index of current element in elem_values */
|
||||
int mark_elem; /* index of marked element in elem_values */
|
||||
int num_elems; /* number of elems in current array value */
|
||||
Datum *elem_values; /* array of num_elems Datums */
|
||||
} BTArrayKeyInfo;
|
||||
@ -665,6 +666,8 @@ extern void _bt_freestack(BTStack stack);
|
||||
extern void _bt_preprocess_array_keys(IndexScanDesc scan);
|
||||
extern void _bt_start_array_keys(IndexScanDesc scan, ScanDirection dir);
|
||||
extern bool _bt_advance_array_keys(IndexScanDesc scan, ScanDirection dir);
|
||||
extern void _bt_mark_array_keys(IndexScanDesc scan);
|
||||
extern void _bt_restore_array_keys(IndexScanDesc scan);
|
||||
extern void _bt_preprocess_keys(IndexScanDesc scan);
|
||||
extern IndexTuple _bt_checkkeys(IndexScanDesc scan,
|
||||
Page page, OffsetNumber offnum,
|
||||
|
Loading…
x
Reference in New Issue
Block a user