How to write a c-function to return multiple bytea rows - Mailing list pgsql-hackers
From | Billow Gao |
---|---|
Subject | How to write a c-function to return multiple bytea rows |
Date | |
Msg-id | 677a32120711281743t336b82d5i722001ae9e3e6bda@mail.gmail.com Whole thread Raw |
Responses |
Re: How to write a c-function to return multiple bytea rows
Re: How to write a c-function to return multiple bytea rows |
List | pgsql-hackers |
I can return multiple strings w/o problem.<br /><br />But if I tried to return multiple bytea rows. It only return 10 rowswith empty data.<br />Please see the code below.<br /><br />Also, when I compile it, I had warning:<br />test.c :121:warning: assignment makes pointer from integer without a cast <br />The line is: <br />tuple = heap_form_tuple( tupdesc,&dtvalues, &isNull );<br /><br />Strange.. compiled in a linux box. <br /><br /><br />If I use: tuple = BuildTupleFromCStrings(attinmeta,values); <br />it can work but it's string and I want to use bytea.<br /><br />Also, doI need to free char** values or let postgresql do the job?<br /><br />Thanks<br /><br />Billow<br /><br /><br />============================================================================================<br />/************************************************************<br/>-- select * from test(1,2,'asdfdsaf') as (id bytea);<br/>CREATE OR REPLACE FUNCTION test(int,int,text)<br /> RETURNS setof record<br /> AS 'gr_indexsearch.so','test' <br /> LANGUAGE 'C' IMMUTABLE CALLED ON NULL INPUT;<br />*************************************************************/<br/><br />// PostgreSQL includes<br />#include "postgres.h"<br/>#include "fmgr.h" <br /><br />// Tuple building functions and macros<br />#include "funcapi.h"<br /><br/>#include "utils/builtins.h"<br /><br /><br />#include <string.h><br /><br />#define _textout(str) DatumGetPointer(DirectFunctionCall1(textout,PointerGetDatum(str))) <br /><br />#ifndef SET_VARSIZE<br />#define SET_VARSIZE(v,l)(VARATT_SIZEP(v) = (l))<br />#endif<br /><br />/* SortMem got renamed in PostgreSQL 8.0 */<br />#ifndef SortMem<br/> #define SortMem 16 * 1024<br />#endif<br /><br />#ifdef PG_MODULE_MAGIC <br />PG_MODULE_MAGIC;<br />#endif<br/><br /><br />// forward declaration to keep compiler happy<br />Datum c_complex_add( PG_FUNCTION_ARGS );<br /><br/>PG_FUNCTION_INFO_V1( test );<br />Datum test( PG_FUNCTION_ARGS )<br />{<br /> // things we need to deal with constructingour composite type <br /> TupleDesc tupdesc;<br /> HeapTuple tuple;<br /> Tuplestorestate *tupstore = NULL;<br /> ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;<br /> <br/> MemoryContext per_query_ctx; <br /> MemoryContext oldcontext;<br /> <br /> // Get arguments. If we declareour function as STRICT, then<br /> // this check is superfluous.<br /> if( PG_ARGISNULL(0) ||<br /> PG_ARGISNULL(1)|| <br /> PG_ARGISNULL(2)) <br /> {<br /> PG_RETURN_NULL();<br /> }<br /><br /> // Get arguments:TimeStart and TimeEnd<br /> int32 TimeStart = PG_GETARG_INT32(0);<br /> int32 TimeEnd = PG_GETARG_INT32(1);<br/><br /> // Get Search query<br /> char *query = _textout(PG_GETARG_TEXT_P(2)); <br /> <br/> <br /> /* check to see if caller supports us returning a tuplestore */<br /> if (!rsinfo || !(rsinfo->allowedModes& SFRM_Materialize))<br /> ereport(ERROR,<br /> (errcode(ERRCODE_SYNTAX_ERROR),<br /> errmsg("materialize mode required, but it is not " \<br /> "allowed in this context")));<br /><br /> /* let the caller know we're sending back a tuplestore */ <br/> rsinfo->returnMode = SFRM_Materialize;<br /> <br /> per_query_ctx = fcinfo->flinfo->fn_mcxt;<br /> oldcontext = MemoryContextSwitchTo(per_query_ctx);<br /><br /> /* get the requested return tuple description */ <br/> tupdesc = rsinfo->expectedDesc;<br /> <br /> /* OK, use it */<br /> AttInMetadata *attinmeta = TupleDescGetAttInMetadata(tupdesc);<br/> <br /> /* initialize our tuplestore */<br /> tupstore = tuplestore_begin_heap(true,false, SortMem); <br /> <br /> char strtest[] = "This is a test!";<br /> int strleng= strlen(strtest);<br /> <br /> int rows = 10;<br /> //char** values = (char **) palloc(rows * sizeof(char*));<br /> <br /> bytea** values = (bytea **) palloc(rows * sizeof(bytea *)); <br /> Datum dtvalues;<br/> bool isNull;<br /> <br /> int i;<br /> for(i=0; i<rows; i++)<br /> {<br /> //values[i]= palloc(strleng * sizeof(char));<br /> //strncpy(values[i], strtest, strleng); <br /> /* construct the tuple */<br /> //tuple = BuildTupleFromCStrings(attinmeta, values);<br /> /* nowstore it */<br /> //tuplestore_puttuple(tupstore, tuple);<br /> <br /> values[i] = (bytea *)palloc( strleng + VARHDRSZ ); <br /> SET_VARSIZE(values[i], strleng + VARHDRSZ);<br /> memcpy( VARDATA(values[i]),strtest, strleng );<br /> dtvalues = PointerGetDatum(values[i]);<br /><br /> tuple= heap_form_tuple( tupdesc, &dtvalues, &isNull ); <br /><br /> /* now store it */<br /> oldcontext = MemoryContextSwitchTo(per_query_ctx);<br /> tuplestore_puttuple(tupstore, tuple);<br /> MemoryContextSwitchTo(oldcontext);<br /><br /> heap_freetuple(tuple); <br /> }<br /> <br /> tuplestore_donestoring(tupstore);<br/> <br /> /* now go build it */<br /> rsinfo->setResult = tupstore;<br /><br/> /*<br /> * SFRM_Materialize mode expects us to return a NULL Datum. The actual <br /> * tuples are inour tuplestore and passed back through rsinfo->setResult.<br /> * rsinfo->setDesc is set to the tuple descriptionthat we actually used<br /> * to build our tuples with, so the caller can verify we did what it was <br /> * expecting.<br /> */<br /> rsinfo->setDesc = tupdesc;<br /> MemoryContextSwitchTo(oldcontext);<br /><br/> return (Datum) 0;<br />}<br />
pgsql-hackers by date: