Thread: BUG #3264: SPI: int64's sometimes returned by value sometimes by reference

The following bug has been logged online:

Bug reference:      3264
Logged by:          Adam Kunen
Email address:      adam.kunen@gmail.com
PostgreSQL version: 8.2.4
Operating system:   Ubuntu 7.04 - AMD64
Description:        SPI:  int64's sometimes returned by value sometimes by
reference
Details:

I have the ubuntu standard install of postgresql (including devel headers,
etc) for the 64-bit platform.

I have noticed some discrepencies with 64-bit values in tuples.
For a given row with multiple int8's I have noticed sometimes the value will
be passed by value and sometime by reference.

On my platform a int is 32-bit, long is 64-bit.

The DatumGetInt64 breaks for this because it seems to just be
dereferencing/casting a pointer, as defined as:

#define DatumGetInt64(X) (* ((int64 *) DatumGetPointer(X)))

So in my C trigger code I have been forced to make a wrapper around
SPI_getbinval to get my int64's that looks at the
TupleDesc->attrs[x]->attrbyval to determine which course of actions..
this is my wrapper:

int64 wrapper_get_int64(HeapTuple tup, TupleDesc desc, int colnum, bool
*isnull)
{
    // get the value or pointer
    Datum tmp = SPI_getbinval(tup, desc, colnum, isnull);

    // if its null, return 0
    if(*isnull)return 0;

    // if its pass by value, return the int64
    if(desc->attrs[colnum-1]->attbyval)return (int64)tmp;

    // if its pass by reference, deref and return
    else return DatumGetInt64(tmp);

}


This works great for me.

In all of the examples and contrib code i don't see anyone checking this,
all I see are examples like:

DatumGetInt64(SPI_getbinval(tup, desc, colnum, isnull));

So maybee this is not a bug... maybe a nice note about this in the docs
would be good.  But it seems to me that some of the contrib code could fail
on a 64-bit platform when 64-bits can be passed by value.

If i'm missing something here, let me know :)

thanks
-Adam Kunen
"Adam Kunen" <adam.kunen@gmail.com> writes:
> I have noticed some discrepencies with 64-bit values in tuples.
> For a given row with multiple int8's I have noticed sometimes the value will
> be passed by value and sometime by reference.

No, int8 datums are always passed by reference.  If you have a
counterexample then let's see it.

Whether they *could* be passed by value on some platforms is a
different issue.  One of the reasons for having macros like
DatumGetInt64 is to make such a thing transparent to source code
when/if we get around to doing it.  IMHO, if your code assumes
either convention explicitly then it's broken.

A possible reading of your report is that you've failed to distinguish
int4 and int8 datums in places ... but with so few details, it's
impossible to be sure of that diagnosis.

            regards, tom lane
"Adam Kunen" <adam.kunen@gmail.com> writes:
> > I have noticed some discrepencies with 64-bit values in tuples.
> > For a given row with multiple int8's I have noticed sometimes the value
> will
> > be passed by value and sometime by reference.
>
> No, int8 datums are always passed by reference.  If you have a
> counterexample then let's see it.
>
> Whether they *could* be passed by value on some platforms is a
> different issue.  One of the reasons for having macros like
> DatumGetInt64 is to make such a thing transparent to source code
> when/if we get around to doing it.  IMHO, if your code assumes
> either convention explicitly then it's broken.
>
> A possible reading of your report is that you've failed to distinguish
> int4 and int8 datums in places ... but with so few details, it's
> impossible to be sure of that diagnosis.
>
>                         regards, tom lane
>

Ah, you are right.  My apologies,  someone switched a serial8 to a serial on
me, and never let me know!

I didn't post my example because it would have been too long, instead I went
thru making a test case for you, only to find out what you already knew!

Thanks anyways,
sorry for wasting your time!

-Adam Kunen