Re: How to return a large String with C

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

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

> Stefan Niantschur <sniantschur(at)web(dot)de> writes:
> > Am Sun, 17 Feb 2008 09:17:08 -0500
> > schrieb Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>:
> >> Hardly surprising when you're printing the string into a fixed-size
> >> 8K buffer. The buffer overflow is smashing the stack, in particular
> >> the function's return address.
>
> > Yes, I know, but the backend does not allow for a bigger buffer.
> > Trying to use a 80K (char[81920])buffer did not work and returns:
>
> So you've got some other bug in code you didn't show us. It's highly
> unlikely that you wouldn't be able to allocate an 80K buffer.
> (Whether that's big enough for your data even yet is a separate
> question.)
>
> What I was wondering was why you even bothered with the char[] buffer,
> when it looked like the actually useful return value was being
> accumulated in an expansible StringInfo buffer.
>
> regards, tom lane
>

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. If the result is
a really long string, then I see this:
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.

The problem is not the query via SPI (this works and I can see the
result in elog). The issue I have is that I cannot see the string in
psql when it is a long string. For short strings it does the trick.

Even if I use a (char *) and return it this only works for short
strings.

As short strings are not the problem, what do I need to do to get a
long string handed back to my select in psql?

Best Regards,
Stefan

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Tony Caduto 2008-02-18 15:38:33 Re: msvcr80.dll and PostgreSQL 8.3 under Windows XP
Previous Message Magnus Hagander 2008-02-18 15:20:57 Re: msvcr80.dll and PostgreSQL 8.3 under Windows XP