Thread: Problem with heap_form_tuple error

Problem with heap_form_tuple error

From
Stephen Woodbridge
Date:
Hi all,

I'm have a problem with heap_form_tuple error
    ERROR:  invalid memory alloc request size 1149502660

I've read through a ton of examples and read through the code and the
docs and I'm sure I'm doing something stupid but I'm not seeing it. I
have included a very reduced sample of the code below trying to focus on
the relevant parts.

1. how I get my return tuple_desc
2. how I prepare my values and nulls arrays

I am totally stuck on this! So I really need some help to point out the
error of my ways here.

Thanks,
   -Steve

     if (SRF_IS_FIRSTCALL()) {
         MemoryContext   oldcontext;

         /* create a function context for cross-call persistence */
         funcctx = SRF_FIRSTCALL_INIT();

         /* create a function context for cross-call persistence */
         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

         ...

         if (get_call_result_type( fcinfo, NULL, &tuple_desc ) !=
TYPEFUNC_COMPOSITE ) {
             elog(ERROR, "function returning record called in context"
                 " that cannot accept type record");
             std_free(std);
             return finish(-1);
         }
         /* since this is a defined composite type,
            I probably do not need to bless it,
            but the example in the docs said to */
         BlessTupleDesc(tuple_desc);
         /* save this for later usage also */
         funcctx->tuple_desc = tuple_desc;

         MemoryContextSwitchTo(oldcontext);

         DBG("finished first call setup");
     }

     funcctx = SRF_PERCALL_SETUP();

     call_cntr  = funcctx->call_cntr;
     max_calls  = funcctx->max_calls;
     tuple_desc = funcctx->tuple_desc;  /* the result record description */
     fctx       = (std_fctx *) funcctx->user_fctx;
     std        = fctx->std;

     ...

     if (call_cntr < max_calls) { /* do while there are more to send */
         Datum *values;
         bool *nulls;
         int id;
         int k;

         HeapTuple addr_tuple = spi_tuptable->vals[call_cntr];

         ...

         values = (Datum *) palloc(17 * sizeof(Datum));
         nulls = (bool *) palloc(17 * sizeof(bool));
         for (k=0; k<17; k++) {
             values[k] = (Datum) 0;
             nulls[k] = true;
         }
         values[0] = Int32GetDatum(id);
         nulls[0] = false;
         if (stdaddr->building) {
             DBG("building %d", strlen(stdaddr->building));
             values[1] = CStringGetDatum(pstrdup(stdaddr->building));
             nulls[1] = false;
         }
         ... more if blocks for values[2..15] ...
         if (stdaddr->unit) {
             DBG("unit %d", strlen(stdaddr->unit));
             values[16] = CStringGetDatum(pstrdup(stdaddr->unit));
             nulls[16] = false;
         }
         HeapTuple tuple = heap_form_tuple(tuple_desc, values, nulls);
         result = HeapTupleGetDatum(tuple);
         SRF_RETURN_NEXT(funcctx, result);
     }
     ...

when this runs DBG logs the following:

NOTICE:  city='NORTH CHELMSFORD', state='MASSACHUSETTS', postcode='01863'
NOTICE:  setup values and nulls array for natts=17
NOTICE:  house_num 2
NOTICE:  name 8
NOTICE:  suftype 4
NOTICE:  city 16
NOTICE:  state 13
NOTICE:  postcode 5
NOTICE:  calling heap_form_tuple
ERROR:  invalid memory alloc request size 1149502660

the stdaddr fields all have reasonable null terminated CStrings in them.


Re: Problem with heap_form_tuple error

From
Tom Lane
Date:
Stephen Woodbridge <woodbri@swoodbridge.com> writes:
> I'm have a problem with heap_form_tuple error
>     ERROR:  invalid memory alloc request size 1149502660
> I've read through a ton of examples and read through the code and the
> docs and I'm sure I'm doing something stupid but I'm not seeing it.

Hm ... you're setting up arguments to heap_form_tuple like this:

>              values[1] = CStringGetDatum(pstrdup(stdaddr->building));

This is only correct if the corresponding column of the tupledesc is
declared as being type "cstring", which I'm willing to bet it isn't.
heap_form_tuple does not do any type conversion --- the datums provided
have to be of the right types already.

You could feed the string through the input function for the column's
type, but perhaps what you really ought to do is use
BuildTupleFromCStrings rather than using heap_form_tuple directly.

            regards, tom lane


Re: Problem with heap_form_tuple error

From
Stephen Woodbridge
Date:
On 11/5/2012 10:34 AM, Tom Lane wrote:
> Stephen Woodbridge <woodbri@swoodbridge.com> writes:
>> I'm have a problem with heap_form_tuple error
>>      ERROR:  invalid memory alloc request size 1149502660
>> I've read through a ton of examples and read through the code and the
>> docs and I'm sure I'm doing something stupid but I'm not seeing it.
>
> Hm ... you're setting up arguments to heap_form_tuple like this:
>
>>               values[1] = CStringGetDatum(pstrdup(stdaddr->building));
>
> This is only correct if the corresponding column of the tupledesc is
> declared as being type "cstring", which I'm willing to bet it isn't.
> heap_form_tuple does not do any type conversion --- the datums provided
> have to be of the right types already.
>
> You could feed the string through the input function for the column's
> type, but perhaps what you really ought to do is use
> BuildTupleFromCStrings rather than using heap_form_tuple directly.
>
>             regards, tom lane
>
>
Hi Tom,

Thanks, changing my code to use BuildTupleFromCStrings did the trick. So
if I wanted to do some like my code was doing what is the proper way to
convert a CString into varchar and then that into Datum?

I tried to follow the source code for BuildTupleFromCStrings but it
rapidly got convoluted and was not easy to follow.

Thanks again for the help,
   -Steve


Re: Problem with heap_form_tuple error

From
Tom Lane
Date:
Stephen Woodbridge <woodbri@swoodbridge.com> writes:
> Thanks, changing my code to use BuildTupleFromCStrings did the trick. So
> if I wanted to do some like my code was doing what is the proper way to
> convert a CString into varchar and then that into Datum?

Personally I'd use cstring_to_text (relying on the knowledge that text
and varchar are binary-equivalent types).

            regards, tom lane