--- trunk/pgswish.c 2005/02/19 16:01:46 13 +++ trunk/pgswish.c 2005/02/20 22:58:25 18 @@ -25,6 +25,8 @@ #include "fmgr.h" #include "funcapi.h" #include "utils/builtins.h" +#include "utils/array.h" +#include "miscadmin.h" #include #define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str)) @@ -36,6 +38,7 @@ SW_HANDLE swish_handle = NULL;/* Database handle */ SW_SEARCH search = NULL; /* search handle -- holds search parameters */ SW_RESULTS swish_results = NULL; /* results handle -- holds list of results */ +SW_RESULT *sw_res = NULL; /* one row from swish-e results */ /* define PostgreSQL v1 function */ PG_FUNCTION_INFO_V1(pgswish); @@ -130,7 +133,6 @@ char **values; HeapTuple tuple; Datum result; - SW_RESULT *sw_res; /* one row from swish-e results */ elog(INFO, "pgswish: loop count %d", call_cntr); @@ -139,7 +141,7 @@ SRF_RETURN_DONE(funcctx); } - elog(INFO, "pgswish: check for swish-e error"); + elog(DEBUG1, "pgswish: check for swish-e error"); error_or_abort( swish_handle ); /* @@ -182,7 +184,7 @@ values[3] = (char *) palloc(16 * sizeof(char)); snprintf(values[3], 16, "%d", 4); */ - + /* build a tuple */ tuple = BuildTupleFromCStrings(attinmeta, values); @@ -196,7 +198,7 @@ pfree(values[3]); pfree(values); - elog(INFO, "row: %s|%s|%s|%s",values[0],values[1],values[2],values[3]); + elog(DEBUG1, "row: %s|%s|%s|%s",values[0],values[1],values[2],values[3]); SRF_RETURN_NEXT(funcctx, result); } else { @@ -211,65 +213,144 @@ } } -/* - * elog errors - * - */ +/* work in progress */ +PG_FUNCTION_INFO_V1(pgswish2); +Datum pgswish2(PG_FUNCTION_ARGS) +{ + int nrows = 3; + int16 typlen; + bool typbyval; + char typalign; + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + AttInMetadata *attinmeta; + TupleDesc tupdesc; + Tuplestorestate *tupstore = NULL; + HeapTuple tuple; + MemoryContext per_query_ctx; + MemoryContext oldcontext; + Datum dvalue; + char **values; + int ncols; + int i, j; + + /* 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"))); + + /* get the requested return tuple description */ + tupdesc = rsinfo->expectedDesc; + ncols = tupdesc->natts; + + /* + * The requested tuple description better match up with the array + * we were given. + */ + /* OK, use it */ + attinmeta = TupleDescGetAttInMetadata(tupdesc); + + /* Now go to work */ + rsinfo->returnMode = SFRM_Materialize; + + per_query_ctx = fcinfo->flinfo->fn_mcxt; + oldcontext = MemoryContextSwitchTo(per_query_ctx); + + /* initialize our tuplestore */ + tupstore = tuplestore_begin_heap(true, false, SortMem); + + values = (char **) palloc(ncols * sizeof(char *)); + + for (i = 0; i < nrows; i++) + { + for (j = 0; j < ncols; j++) + { + values[j] = DatumGetCString( "foo" ); + } + /* construct the tuple */ + tuple = BuildTupleFromCStrings(attinmeta, values); + + /* now store it */ + tuplestore_puttuple(tupstore, tuple); + } + + tuplestore_donestoring(tupstore); + 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; +} + +/* make text var prom property */ char *prop2text(SW_RESULT sw_res, char *propname) { char *val; char *prop; int len; - elog(INFO, "prop2text(%s)", propname); + elog(DEBUG2, "prop2text(%s)", propname); prop = SwishResultPropertyStr( sw_res, propname ); error_or_abort( swish_handle ); len = strlen(prop); - elog(INFO, "prop2text(%s) = '%s' %d bytes", propname, prop, len); + elog(DEBUG1, "prop2text(%s) = '%s' %d bytes", propname, prop, len); len++; len *= sizeof(char); - elog(INFO, "palloc(%d)", len); + elog(DEBUG2, "palloc(%d)", len); val = palloc(len); memset(val, 0, len); strncpy(val, prop, len); - elog(INFO, "val=%s", val); + elog(DEBUG2, "val=%s", val); return val; } +/* make integer variable from property */ char *prop2int(SW_RESULT sw_res, char *propname) { char *val; unsigned long prop; int len; - elog(INFO, "prop2int(%s)", propname); + elog(DEBUG2, "prop2int(%s)", propname); prop = SwishResultPropertyULong( sw_res, propname ); error_or_abort( swish_handle ); - elog(INFO, "prop2int(%s) = %lu", propname, prop); + elog(DEBUG1, "prop2int(%s) = %lu", propname, prop); len = 128 * sizeof(char); - elog(INFO, "palloc(%d)", len); + elog(DEBUG2, "palloc(%d)", len); val = palloc(len); memset(val, 0, len); snprintf(val, len, "%lu", prop); - elog(INFO, "val=%s", val); + elog(DEBUG2, "val=%s", val); return val; } +/* + * check if swish has returned error, and elog it. + */ static void error_or_abort( SW_HANDLE swish_handle ) { if ( !SwishError( swish_handle ) ) return; @@ -283,7 +364,5 @@ ); if ( search ) Free_Search_Object( search ); SwishClose( swish_handle ); - - /* do when there is no more left */ }