How to write a c-function to return multiple bytea rows

From: "Billow Gao" <billowgy(at)gmail(dot)com>
To: pgsql-hackers(at)postgresql(dot)org
Subject: How to write a c-function to return multiple bytea rows
Date: 2007-11-29 01:43:33
Message-ID: 677a32120711281743t336b82d5i722001ae9e3e6bda@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I can return multiple strings w/o problem.

But if I tried to return multiple bytea rows. It only return 10 rows with
empty data.
Please see the code below.

Also, when I compile it, I had warning:
test.c:121: warning: assignment makes pointer from integer without a cast
The line is:
tuple = heap_form_tuple( tupdesc, &dtvalues, &isNull );

Strange.. compiled in a linux box.

If I use: tuple = BuildTupleFromCStrings(attinmeta, values);
it can work but it's string and I want to use bytea.

Also, do I need to free char** values or let postgresql do the job?

Thanks

Billow

============================================================================================
/************************************************************
-- select * from test(1,2,'asdfdsaf') as (id bytea);
CREATE OR REPLACE FUNCTION test(int,int,text)
RETURNS setof record
AS 'gr_indexsearch.so', 'test'
LANGUAGE 'C' IMMUTABLE CALLED ON NULL INPUT;
*************************************************************/

// PostgreSQL includes
#include "postgres.h"
#include "fmgr.h"

// Tuple building functions and macros
#include "funcapi.h"

#include "utils/builtins.h"

#include <string.h>

#define _textout(str) DatumGetPointer(DirectFunctionCall1(textout,
PointerGetDatum(str)))

#ifndef SET_VARSIZE
#define SET_VARSIZE(v,l) (VARATT_SIZEP(v) = (l))
#endif

/* SortMem got renamed in PostgreSQL 8.0 */
#ifndef SortMem
#define SortMem 16 * 1024
#endif

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

// forward declaration to keep compiler happy
Datum c_complex_add( PG_FUNCTION_ARGS );

PG_FUNCTION_INFO_V1( test );
Datum test( PG_FUNCTION_ARGS )
{
// things we need to deal with constructing our composite type
TupleDesc tupdesc;
HeapTuple tuple;
Tuplestorestate *tupstore = NULL;
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;

MemoryContext per_query_ctx;
MemoryContext oldcontext;

// Get arguments. If we declare our function as STRICT, then
// this check is superfluous.
if( PG_ARGISNULL(0) ||
PG_ARGISNULL(1) ||
PG_ARGISNULL(2))
{
PG_RETURN_NULL();
}

// Get arguments: TimeStart and TimeEnd
int32 TimeStart = PG_GETARG_INT32(0);
int32 TimeEnd = PG_GETARG_INT32(1);

// Get Search query
char *query = _textout(PG_GETARG_TEXT_P(2));

/* check to see if caller supports us returning a tuplestore */
if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("materialize mode required, but it is not " \
"allowed in this context")));

/* let the caller know we're sending back a tuplestore */
rsinfo->returnMode = SFRM_Materialize;

per_query_ctx = fcinfo->flinfo->fn_mcxt;
oldcontext = MemoryContextSwitchTo(per_query_ctx);

/* get the requested return tuple description */
tupdesc = rsinfo->expectedDesc;

/* OK, use it */
AttInMetadata *attinmeta = TupleDescGetAttInMetadata(tupdesc);

/* initialize our tuplestore */
tupstore = tuplestore_begin_heap(true, false, SortMem);

char strtest[] = "This is a test!";
int strleng = strlen(strtest);

int rows = 10;
//char** values = (char **) palloc(rows * sizeof(char *));

bytea** values = (bytea **) palloc(rows * sizeof(bytea *));
Datum dtvalues;
bool isNull;

int i;
for(i=0; i<rows; i++)
{
//values[i] = palloc(strleng * sizeof(char));
//strncpy(values[i], strtest, strleng);
/* construct the tuple */
//tuple = BuildTupleFromCStrings(attinmeta, values);
/* now store it */
//tuplestore_puttuple(tupstore, tuple);

values[i] = (bytea *) palloc( strleng + VARHDRSZ );
SET_VARSIZE(values[i], strleng + VARHDRSZ);
memcpy( VARDATA(values[i]), strtest, strleng );
dtvalues = PointerGetDatum(values[i]);

tuple = heap_form_tuple( tupdesc, &dtvalues, &isNull );

/* now store it */
oldcontext = MemoryContextSwitchTo(per_query_ctx);
tuplestore_puttuple(tupstore, tuple);
MemoryContextSwitchTo(oldcontext);

heap_freetuple(tuple);
}

tuplestore_donestoring(tupstore);

/* now go build it */
rsinfo->setResult = tupstore;

/*
* SFRM_Materialize mode expects us to return a NULL Datum. The actual
* tuples are in our tuplestore and passed back through
rsinfo->setResult.
* rsinfo->setDesc is set to the tuple description that we actually used
* to build our tuples with, so the caller can verify we did what it was
* expecting.
*/
rsinfo->setDesc = tupdesc;
MemoryContextSwitchTo(oldcontext);

return (Datum) 0;
}

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Jonah H. Harris 2007-11-29 02:54:57 Re: quotas once again
Previous Message Alvaro Herrera 2007-11-29 01:09:24 Re: quotas once again