Re: How to return a large String with C

From: Stefan Niantschur <sniantschur(at)web(dot)de>
To:
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: How to return a large String with C
Date: 2008-02-18 19:46:48
Message-ID: 20080218204648.00a9b51b@trabant.niantschur.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Am Mon, 18 Feb 2008 14:15:14 -0500
schrieb Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>:

> Stefan Niantschur <sniantschur(at)web(dot)de> writes:
> > Please find below the most recent code snippet. It is mainly based
> > on examples from the pg documentation:
> > -------8< -------
> > #define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin,
> > CStringGetDatum(cstrp)))
> > (...)
> > char *cres;
> > int ret;
> > (...)
> > if ((ret = SPI_connect()) < 0)
> > {
> > elog(ERROR, "get_info: SPI_connect returned %d", ret);
> > }
>
> > proc = SPI_processed;
>
> > initStringInfo(&result_buf);
> > if (ret > 0 && SPI_tuptable != NULL)
> > {
> > TupleDesc tupdesc = SPI_tuptable->tupdesc;
> > SPITupleTable *tuptable = SPI_tuptable;
> > int i,k;
> > for (i = 0; i < proc; i++)
> > {
> > HeapTuple tuple = tuptable->vals[i];
> > for (k = 1; k <= tupdesc->natts; k++)
> > {
> > cres = SPI_getvalue(tuple, tupdesc, k);
> > appendStringInfo(&result_buf, SPI_getvalue(tuple, tupdesc, k));
> > elog(INFO, "info: %s", cres);
> > }
> > }
> > }
> > SPI_finish();
> > elog(INFO, "---");
> > PG_RETURN_TEXT_P(GET_TEXT(result_buf.data));
> > ------->8 -------
>
> > I still have the problem that I can use the C function via
> > select from within psql if the result is not too long.
>
> I don't think length has anything to do with it; rather the problem is
> that you're trying to return data that's already been pfree'd when you
> did SPI_finish().
>
> Probably the simplest fix for this case is to put the initStringInfo
> call before SPI_connect, so that the result_buf.data buffer exists
> in the outer function context and not in the temporary SPI context.
>
> BTW, it is strongly advisable to do development/testing of C code
> in a backend that's been built with --enable-cassert. Had you done
> so, this mistake would have been much more obvious.
>
> regards, tom lane

That was also one of my attempts. I even changed my code from calling
initStringInfo to initialise the buffer with
StringInfo result_buf = makeStringInfo();
just at the beginning fo my function before anything happened.

Regarding the documentation this should palloc the buffer. However,
reproducably I ended up in crashes when the string length exceeded a
certain size.

So SPI_palloc() helped me to solve the problem.

Regards,
Stefan

In response to

Browse pgsql-general by date

  From Date Subject
Next Message Tom Lane 2008-02-18 19:56:39 Re: deadlock with truncate and foreing keys
Previous Message Scott Marlowe 2008-02-18 19:45:04 Re: Initdb failed in PostgreSQL 7.3.21