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

Reply via email to