--- trunk/pgswish.c 2005/02/19 00:59:08 9 +++ trunk/pgswish.c 2005/02/19 20:59:17 14 @@ -10,6 +10,8 @@ * NOTES: * - clear structures with memset to support hash indexes (who whould like * to create hash index on table returned from function?) + * - number of returned rows is set by PostgreSQL evaluator, see: + * http://archives.postgresql.org/pgsql-hackers/2005-02/msg00546.php * * Based on: * - C example from PostgreSQL documentation (BSD licence) @@ -27,11 +29,14 @@ #define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str)) #define _textout(str) DatumGetPointer(DirectFunctionCall1(textout, PointerGetDatum(str))) +#define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp))) +#define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp))) SW_HANDLE swish_handle = NULL;/* Database handle */ SW_SEARCH search = NULL; /* search handle -- holds search parameters */ -SW_RESULTS results = NULL; /* results handle -- holds list of results */ +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); @@ -43,9 +48,6 @@ TupleDesc tupdesc; TupleTableSlot *slot; AttInMetadata *attinmeta; - SW_HANDLE swish_handle = NULL; /* Database handle */ - SW_SEARCH search = NULL; /* search handle -- holds search parameters */ - SW_RESULTS results = NULL; /* results handle -- holds list of results */ char *index_path; char *query; @@ -77,23 +79,18 @@ SRF_RETURN_DONE(funcctx); } - if ( SwishError( swish_handle ) ) error_or_abort( swish_handle ); + error_or_abort( swish_handle ); /* set ranking scheme. default is 0 */ - SwishRankScheme( swish_handle, 1 ); - - /* Check for errors after every call */ - if ( SwishError( swish_handle ) ) - error_or_abort( swish_handle ); /* print an error or abort -- see below */ + SwishRankScheme( swish_handle, 0 ); + error_or_abort( swish_handle ); elog(INFO, "pgswish: SwishQuery(%s)", query); /* Here's a short-cut to searching that creates a search object and searches at the same time */ -elog(INFO,"## FIXME: SwishQuery kills back-end?"); - results = SwishQuery( swish_handle, query); -elog(INFO,"## FIXME: no..."); - if ( SwishError( swish_handle ) ) error_or_abort( swish_handle ); + swish_results = SwishQuery( swish_handle, query); + error_or_abort( swish_handle ); /* total number of tuples to be returned */ - funcctx->max_calls = SwishHits( results ); + funcctx->max_calls = SwishHits( swish_results ); /* check if results exists */ if ( 0 == funcctx->max_calls ) @@ -118,6 +115,8 @@ funcctx->attinmeta = attinmeta; MemoryContextSwitchTo(oldcontext); + + elog(INFO, "SRF_IS_FIRSTCALL done"); } /* stuff done on every call of the function */ @@ -133,30 +132,76 @@ HeapTuple tuple; Datum result; -if (0) { + elog(INFO, "pgswish: loop count %d", call_cntr); + + if (! swish_results) { + elog(ERROR, "pgswish: no swish-e results"); + SRF_RETURN_DONE(funcctx); + } + + elog(DEBUG1, "pgswish: check for swish-e error"); + error_or_abort( swish_handle ); + /* * Prepare a values array for storage in our slot. * This should be an array of C strings which will * be processed later by the type input functions. */ - values = (char **) palloc(5 * sizeof(char *)); - values[0] = _textout( SwishResultPropertyULong ( result, "swishrank" ) ); - values[1] = _textout( SwishResultPropertyStr ( result, "swishdocpath" ) ); - values[2] = _textout( SwishResultPropertyStr ( result, "swishtitle" ) ); - values[3] = _textout( SwishResultPropertyStr ( result, "swishdocsize" ) ); - values[4] = _textout( SwishResultPropertyStr ( result, "swishdbfile" ) ); + sw_res = SwishNextResult( swish_results ); + if (! sw_res) { + elog(ERROR, "pgswish: swish-e sort result list: %d rows expected %d", call_cntr, max_calls - 1); + SRF_RETURN_DONE(funcctx); + } + + elog(INFO, "Path: %s\n Rank: %lu\n Size: %lu\n Title: %s\n Index: %s\n Modified: %s\n Record #: %lu\n File #: %lu\n\n", + SwishResultPropertyStr ( sw_res, "swishdocpath" ), + SwishResultPropertyULong ( sw_res, "swishrank" ), + SwishResultPropertyULong ( sw_res, "swishdocsize" ), + SwishResultPropertyStr ( sw_res, "swishtitle"), + SwishResultPropertyStr ( sw_res, "swishdbfile" ), + SwishResultPropertyStr ( sw_res, "swishlastmodified" ), + SwishResultPropertyULong ( sw_res, "swishreccount" ), /* can figure this out in loop, of course */ + SwishResultPropertyULong ( sw_res, "swishfilenum" ) + ); + + values = (char **) palloc(4 * sizeof(char *)); + + values[0] = prop2int( sw_res, "swishrank" ); + values[1] = prop2text( sw_res, "swishdocpath" ); + values[2] = prop2text( sw_res, "swishtitle" ); + values[3] = prop2int( sw_res, "swishdocsize" ); + +/* + values[0] = (char *) palloc(16 * sizeof(char)); + snprintf(values[0], 16, "%d", 1); + values[1] = (char *) palloc(16 * sizeof(char)); + snprintf(values[1], 16, "%d", 2); + values[2] = (char *) palloc(16 * sizeof(char)); + snprintf(values[2], 16, "%d", 3); + values[3] = (char *) palloc(16 * sizeof(char)); + snprintf(values[3], 16, "%d", 4); +*/ + /* build a tuple */ tuple = BuildTupleFromCStrings(attinmeta, values); /* make the tuple into a datum */ result = TupleGetDatum(slot, tuple); -} - /* clean up (this is not really necessary) */ - + /* clean up ? */ + pfree(values[0]); + pfree(values[1]); + pfree(values[2]); + pfree(values[3]); + pfree(values); + + elog(INFO, "row: %s|%s|%s|%s",values[0],values[1],values[2],values[3]); + SRF_RETURN_NEXT(funcctx, result); } else { + elog(INFO, "loop over"); + /* free swish object and close */ Free_Search_Object( search ); SwishClose( swish_handle ); @@ -166,11 +211,81 @@ } } +Datum swtextprop(PG_FUNCTION_ARGS) { + char *prop; + char *val; + + prop = _textout(PG_GETARG_TEXT_P(0)); + elog(INFO, "pgswish: swextprop(%s)", prop); + + val = prop2int( sw_res, prop ); + error_or_abort( swish_handle ); + + elog(INFO, "pgswish: swextprop(%s) = '%s'", prop, val ); + + PG_FREE_IF_COPY(prop, 0); + PG_RETURN_TEXT_P( _textin(val) ); +} + +/* make text var prom property */ +char *prop2text(SW_RESULT sw_res, char *propname) { + char *val; + char *prop; + int len; + + elog(DEBUG1, "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); + + len++; + len *= sizeof(char); + + elog(DEBUG1, "palloc(%d)", len); + + val = palloc(len); + + memset(val, 0, len); + strncpy(val, prop, len); + + elog(DEBUG1, "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(DEBUG1, "prop2int(%s)", propname); + + prop = SwishResultPropertyULong( sw_res, propname ); + error_or_abort( swish_handle ); + + elog(INFO, "prop2int(%s) = %lu", propname, prop); + + len = 128 * sizeof(char); + elog(DEBUG1, "palloc(%d)", len); + + val = palloc(len); + memset(val, 0, len); + + snprintf(val, len, "%lu", prop); + + elog(DEBUG1, "val=%s", val); + + return val; +} + + /* - * elog errors - * + * check if swish has returned error, and elog it. */ - static void error_or_abort( SW_HANDLE swish_handle ) { if ( !SwishError( swish_handle ) ) return; @@ -184,7 +299,5 @@ ); if ( search ) Free_Search_Object( search ); SwishClose( swish_handle ); - - /* do when there is no more left */ }