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;
}
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 |