Thread: setting up scan keys

setting up scan keys

From
"Markus Wanner"
Date:
Hi,

I'm currently having difficulties understanding how to setup scan keys
for simple index scans. What I want to achieve is scanning a primary
key index (thus unique constraint - and as far as I know only nbtree
can handle these, right?).

Up until now I've used something along the following lines to setup
the scan keys for a BTGreaterStrategy scan:
        procinfo = index_getprocinfo(index_rel, i + 1, BTORDER_PROC);        ScanKeyEntryInitializeWithInfo(&skeys[i],
                                    SK_ROW_MEMBER,                                       (AttrNumber) (i + 1),
                            strategy,                                       InvalidOid,
     procinfo,                                       value); 

That seems to work for that strategy. However, when using the same for
BTEqualStrategy, the scan doesn't return any tuple (although I'm
pretty sure it should return exactly one).

Reading src/backend/access/nbtree/README and various code in the same
directory, I've learned that these scan keys are used in two different
ways: "search" and "insertion" scan keys. AFAIU, I'm setting up an
insertion scan key, due to using the BTORDER_PROC directly (in my case
that's mostly btint4cmp). But it also looks like that's just an
(nbtree-)internal representation. I don't see
ScanKeyEntryInitializeWithInfo used anywhere outside of that code.

Now I'm trying with something more like:
        get_sort_group_operators(tdesc->attrs[attnum-1]->atttypid,                                 false, true, true,
                             NULL, &eq_func, >_func); 
        if (strategy == BTEqualStrategyNumber)            regproc = get_opcode(eq_func);        else if (strategy ==
BTGreaterStrategyNumber)           regproc = get_opcode(gt_func);        else            Assert(false); 
        ScanKeyEntryInitialize(&skeys[i],                               SK_ROW_MEMBER,
(AttrNumber)(i + 1),                               strategy,                               InvalidOid,
            regproc,                               value); 

That still triggers an assertion for me, not quite sure why. But is
this the preferred way? Or am I better off fiddling with the first
variant and get that to run?

I'm using the scan keys later on with simple index_beginscan(),
index_rescan() and index_getnext(). My goal is to support any kind of
UNIQUE INDEX, always with all attributes of the index.

Any enlightening comments on this duplicate use of ScanKeyData?

Help is greatly appreciated.

Regards

Markus Wanner



Re: setting up scan keys

From
Tom Lane
Date:
"Markus Wanner" <markus@bluegap.ch> writes:
> Up until now I've used something along the following lines to setup  
> the scan keys for a BTGreaterStrategy scan:

>          procinfo = index_getprocinfo(index_rel, i + 1, BTORDER_PROC);
>          ScanKeyEntryInitializeWithInfo(&skeys[i],
>                                         SK_ROW_MEMBER,
>                                         (AttrNumber) (i + 1),
>                                         strategy,
>                                         InvalidOid,
>                                         procinfo,
>                                         value);

Either the SK_ROW_MEMBER flag is entirely wrong, or this is part of
a larger structure that you're not telling us about.  But also,
from anywhere outside the btree index AM itself you should not be
dealing in the support function.  The scankey is supposed to refer
to an operator's underlying function.  Your second try looks a bit
saner, but it's still using SK_ROW_MEMBER ... why?
        regards, tom lane


Re: setting up scan keys

From
"Markus Wanner"
Date:
Hello Tom,

Quoting "Tom Lane" <tgl@sss.pgh.pa.us>:
> Either the SK_ROW_MEMBER flag is entirely wrong..

Uhm.. yes, that's it. I've been under the impression that for an index
scan with multiple attributes, I need to assemble scan keys with
SK_ROW_MEMBER, SK_ROW_END and SK_ROW_HEADER. I now realize that's
plain wrong and I can simply provide as many scan keys as I have
attributes to scan for, without fiddling with any flag or subtype. The
code in question now uses the simpler ScanKeyInit() and looks as
follows:
    for (i = 0; i < numKeys; i++)    {        attnum = idx_info->ii_KeyAttrNumbers[i];
        get_sort_group_operators(tdesc->attrs[attnum - 1]->atttypid,                                 false, true,
false,                                NULL, &eq_func, NULL); 
        ScanKeyInit(&skeys[i], i + 1, BTEqualStrategyNumber,                    get_opcode(eq_func), values[attnum -
1]);   } 

Thank you very much for your help, that quickly got me on track again.

Regards

Markus Wanner