Re: How to compare different datums within from a tuple?

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));
}

In response to

Browse pgsql-hackers by date

  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