Re: How to compare different datums within from a tuple? - Mailing list pgsql-hackers

From Peter Moser
Subject Re: How to compare different datums within from a tuple?
Date
Msg-id 55CAF5FE.7080701@gmail.com
Whole thread Raw
In response to Re: How to compare different datums within from a tuple?  (Peter Eisentraut <peter_e@gmx.net>)
List 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));
}





pgsql-hackers by date:

Previous
From: Andres Freund
Date:
Subject: Re: Raising our compiler requirements for 9.6
Next
From: Pavel Stehule
Date:
Subject: Re: PL/pgSQL, RAISE and error context