From: | Peter Moser <pitiz29a(at)gmail(dot)com> |
---|---|
To: | pgsql-hackers(at)postgresql(dot)org |
Subject: | Re: How to compare different datums within from a tuple? |
Date: | 2015-08-12 07:30:06 |
Message-ID: | 55CAF5FE.7080701@gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Am 11.08.2015 um 21:03 schrieb Peter Eisentraut:
> On 8/10/15 12:36 PM, Peter Moser wrote:
>> Can someone tell me, how I can compare two datum fields, when I do not
>> know the data type in advance inside an executor function?
>>
>> For example, "x less than y" where x and y are of various types that
>> form intervals. I have found the method ExecTuplesMatch, but it is only
>> for equality comparison, I think. Another one is ApplySortComparator...
>> maybe that's the correct way to go?
>>
>> Some code to make things clearer...
>>
>> Datum x = heap_getattr(out->tts_tuple,
>> node->xpos,
>> out->tts_tupleDescriptor,
>> &isNull1);
>> Datum y = slot_getattr(curr, node->ypos, &isNull2);
>>
>> if (compareDatumWithCorrectMethod(x,y) < 0)
>> {
>> /* do something */
>> }
>
> The tuple descriptor will contain the data type of the datum, so you can
> use that to look up the default btree operator class and call the
> respective operators in there. But note that there is no single notion
> of comparison in the system. Comparison depends on operator class,
> access method, possibly collation, null value treatment. Some types
> don't support comparison beyond equality. A robust patch would need to
> take that into account.
>
Ok, thank you.
Now I have a first solution. I am just wondering if this is robust, or
do I miss something? Thanks for any comments...
My executor consumes rows from my own rewritten sub-query. From this
sub-query I extract one sortGroupClause and from that the "eqop" and
"sortop" during planning.
sgc = (SortGroupClause *) llast(sortClause);
node->eqOperator = sgc->eqop;
node->ltOperator = sgc->sortop;
The last sort clause uses the same types as the executor needs to
compare later.
The executor initializes the methods with:
state->ltFunctionInfo = (FmgrInfo *) palloc(sizeof(FmgrInfo));
ltOperatorId = get_opcode(node->ltOperator);
fmgr_info(ltOperatorId, state->ltFunctionInfo);
state->eqFunctionInfo = (FmgrInfo *) palloc(sizeof(FmgrInfo));
eqOperatorId = get_opcode(node->eqOperator);
fmgr_info(eqOperatorId, state->eqFunctionInfo);
Finally I use them in this way...
static bool
isLessThan(Datum a, Datum b, FmgrInfo *ltFunctionInfo)
{
return DatumGetBool(FunctionCall2(ltFunctionInfo, a, b));
}
static bool
isEqual(Datum a, Datum b, FmgrInfo *eqFunctionInfo)
{
return DatumGetBool(FunctionCall2(eqFunctionInfo, a, b));
}
From | Date | Subject | |
---|---|---|---|
Next Message | Pavel Stehule | 2015-08-12 07:36:12 | Re: PL/pgSQL, RAISE and error context |
Previous Message | Andres Freund | 2015-08-12 07:29:21 | Re: Raising our compiler requirements for 9.6 |