Skip site navigation (1) Skip section navigation (2)

Peripheral Links

Header And Logo

PostgreSQL
| The world's most advanced open source database.

Site Navigation

Search for
  Advanced Search

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



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


Home | Main Index | Thread Index

Privacy Policy | PostgreSQL Archives hosted by Command Prompt, Inc. | Designed by tinysofa
Copyright © 1996 – 2008 PostgreSQL Global Development Group