vBulletin Search Engine Optimization
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| 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; } |
| |||
| I don't know if it's the proximate source of your problem but your MemoryContextSwitchTo() calls are mixed up. You're reusing the same oldcontext variable for both the switch you're doing in the main body and the switch you're doing in the inner loop. At the very least you should use two different oldcontext variables, currently I think you're leaving the memory context set to the per_query_ctx. But I think in this situation you're going to end up just doing the whole thing in per_query_ctx anyways. The only part you can avoid that for is the pallocing of the heap_form_tuple args and the actual heap_form_tuple call. The tuple will be copied when you call tuplestore_puttuple (which should be done in the same context the tuplestore was created in). -- Gregory Stark EnterpriseDB http://www.enterprisedb.com Get trained by Bruce Momjian - ask me about EnterpriseDB's PostgreSQL training! ---------------------------(end of broadcast)--------------------------- TIP 7: You can help support the PostgreSQL project by donating at http://www.postgresql.org/about/donate |
| ||||
| "Billow Gao" <billowgy@gmail.com> writes: > 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 ); That part is because you didn't #include access/heapam.h, where heap_form_tuple is declared. If you didn't get a warning about it not being declared, you do not have warnings turned up high enough. regards, tom lane ---------------------------(end of broadcast)--------------------------- TIP 3: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faq |