/[pgswish]/trunk/pgswish.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/pgswish.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 9 by dpavlin, Sat Feb 19 00:59:08 2005 UTC revision 20 by dpavlin, Sun May 29 20:30:18 2005 UTC
# Line 6  Line 6 
6   * TODO:   * TODO:
7   * - check null input using PG_ARGISNULL before using PG_GETARG_xxxx   * - check null input using PG_ARGISNULL before using PG_GETARG_xxxx
8   * - support composite type arguments   * - support composite type arguments
9     * - split error_or_abort
10     * - use getResultPropValue not SwishResultPropertyStr
11   *   *
12   * NOTES:   * NOTES:
13   * - clear structures with memset to support hash indexes (who whould like   * - clear structures with memset to support hash indexes (who whould like
14   *   to create hash index on table returned from function?)   *   to create hash index on table returned from function?)
15     * - number of returned rows is set by PostgreSQL evaluator, see:
16     *   http://archives.postgresql.org/pgsql-hackers/2005-02/msg00546.php
17   *   *
18   * Based on:   * Based on:
19   * - C example from PostgreSQL documentation (BSD licence)   * - C example from PostgreSQL documentation (BSD licence)
# Line 23  Line 27 
27  #include "fmgr.h"  #include "fmgr.h"
28  #include "funcapi.h"  #include "funcapi.h"
29  #include "utils/builtins.h"  #include "utils/builtins.h"
30    #include "utils/array.h"
31    #include "miscadmin.h"
32  #include <swish-e.h>  #include <swish-e.h>
33    
34  #define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str))  #define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str))
35  #define _textout(str) DatumGetPointer(DirectFunctionCall1(textout, PointerGetDatum(str)))  #define _textout(str) DatumGetPointer(DirectFunctionCall1(textout, PointerGetDatum(str)))
36    #define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
37    #define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))
38    
39    /* Globals */
40  SW_HANDLE   swish_handle = NULL;/* Database handle */  static SW_HANDLE   swish_handle = NULL; /* Database handle */
41  SW_SEARCH   search = NULL;      /* search handle -- holds search parameters */  static SW_SEARCH   search = NULL;       /* search handle -- search parameters */
42  SW_RESULTS  results = NULL;     /* results handle -- holds list of results */  static SW_RESULTS  swish_results = NULL; /* results handle -- list of results */
43    static SW_RESULT   *sw_res = NULL;      /* one row from swish-e results */
44    
45  /* define PostgreSQL v1 function */  /* define PostgreSQL v1 function */
46  PG_FUNCTION_INFO_V1(pgswish);  PG_FUNCTION_INFO_V1(pgswish);
# Line 43  Datum pgswish(PG_FUNCTION_ARGS) { Line 52  Datum pgswish(PG_FUNCTION_ARGS) {
52          TupleDesc       tupdesc;          TupleDesc       tupdesc;
53          TupleTableSlot  *slot;          TupleTableSlot  *slot;
54          AttInMetadata   *attinmeta;          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 */  
55          char            *index_path;          char            *index_path;
56          char            *query;          char            *query;
57            FILE            *logfh;
58    
59          /* stuff done only on the first call of the function */          /* stuff done only on the first call of the function */
60          if (SRF_IS_FIRSTCALL()) {          if (SRF_IS_FIRSTCALL()) {
# Line 65  Datum pgswish(PG_FUNCTION_ARGS) { Line 72  Datum pgswish(PG_FUNCTION_ARGS) {
72                  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);                  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
73    
74                                    
75                  /* Send any errors or warnings to stderr (default is stdout) */                  /* Send any errors or warnings to log, as well as
76                  SwishErrorsToStderr();                   * STDOUT and STDERR (just to be sure) */
77                    if ( logfh = fopen("/tmp/pgswish.log", "a") ) {
78                            set_error_handle( logfh );
79                            elog(INFO, "loggin swish-e errors to /tmp/pgswish.log");
80                            /* redirect STDOUT and STDERR to log */
81                            dup2(1, logfh);
82                            dup2(2, logfh);
83                    } else {
84                            elog(INFO, "can't open /tmp/pgswish.log -- errors from swish-e won't be cought and may result in back-end crashes!");
85                    }
86    
87                  elog(INFO, "pgswish: SwishInit(%s)", index_path);                  elog(INFO, "pgswish: SwishInit(%s)", index_path);
88                    
89                  swish_handle = SwishInit( index_path );                  swish_handle = SwishInit( index_path );
90    
91                    if ( SwishError( swish_handle ) )
92                            elog(INFO, "pgswish: SwishInit(%s) failed: %s", index_path, SwishErrorString( swish_handle ));
93                    
94                    elog(INFO, "handle: %08x", swish_handle);
95    
96                  if (! swish_handle) {                  if (! swish_handle) {
97                          elog(ERROR, "pgswish: can't open %s", index_path);                          elog(ERROR, "pgswish: can't open %s", index_path);
98                          SRF_RETURN_DONE(funcctx);                          SRF_RETURN_DONE(funcctx);
99                  }                  }
100                                    
101                  if ( SwishError( swish_handle ) ) error_or_abort( swish_handle );                  if (error_or_abort( swish_handle )) SRF_RETURN_DONE(funcctx);
102                  /* set ranking scheme. default is 0 */                  /* set ranking scheme. default is 0 */
103                  SwishRankScheme( swish_handle, 1 );                  SwishRankScheme( swish_handle, 0 );
104                    if (error_or_abort( swish_handle )) SRF_RETURN_DONE(funcctx);
                 /* Check for errors after every call */  
                 if ( SwishError( swish_handle ) )  
                         error_or_abort( swish_handle );  /* print an error or abort -- see below */  
105    
106                  elog(INFO, "pgswish: SwishQuery(%s)", query);                  elog(INFO, "pgswish: SwishQuery(%s)", query);
107                  /* Here's a short-cut to searching that creates a search object and searches at the same time */                  /* Here's a short-cut to searching that creates a search object and searches at the same time */
108  elog(INFO,"## FIXME: SwishQuery kills back-end?");                  swish_results = SwishQuery( swish_handle, query);
109                  results = SwishQuery( swish_handle, query);                  if (error_or_abort( swish_handle )) SRF_RETURN_DONE(funcctx);
 elog(INFO,"## FIXME: no...");  
                 if ( SwishError( swish_handle ) ) error_or_abort( swish_handle );  
110    
111                  /* total number of tuples to be returned */                  /* total number of tuples to be returned */
112                  funcctx->max_calls = SwishHits( results );                  funcctx->max_calls = SwishHits( swish_results );
113    
114                  /* check if results exists */                  /* check if results exists */
115                  if ( 0 == funcctx->max_calls )                  if ( 0 == funcctx->max_calls )
# Line 118  elog(INFO,"## FIXME: no..."); Line 134  elog(INFO,"## FIXME: no...");
134                  funcctx->attinmeta = attinmeta;                  funcctx->attinmeta = attinmeta;
135    
136                  MemoryContextSwitchTo(oldcontext);                  MemoryContextSwitchTo(oldcontext);
137    
138                    elog(INFO, "SRF_IS_FIRSTCALL done");
139          }          }
140    
141          /* stuff done on every call of the function */          /* stuff done on every call of the function */
# Line 133  elog(INFO,"## FIXME: no..."); Line 151  elog(INFO,"## FIXME: no...");
151                  HeapTuple       tuple;                  HeapTuple       tuple;
152                  Datum           result;                  Datum           result;
153    
154  if (0) {                  elog(INFO, "pgswish: loop count %d", call_cntr);
155    
156                    if (! swish_results) {
157                            elog(ERROR, "pgswish: no swish-e results");
158                            SRF_RETURN_DONE(funcctx);
159                    }
160                    
161                    elog(DEBUG1, "pgswish: check for swish-e error");
162                    if (error_or_abort( swish_handle )) SRF_RETURN_DONE(funcctx);
163    
164                  /*                  /*
165                   * Prepare a values array for storage in our slot.                   * Prepare a values array for storage in our slot.
166                   * This should be an array of C strings which will                   * This should be an array of C strings which will
167                   * be processed later by the type input functions.                   * be processed later by the type input functions.
168                   */                   */
169                  values = (char **) palloc(5 * sizeof(char *));  
170                  values[0] = _textout( SwishResultPropertyULong ( result, "swishrank" ) );                  sw_res = SwishNextResult( swish_results );
171                  values[1] = _textout( SwishResultPropertyStr   ( result, "swishdocpath" ) );                  if (! sw_res) {
172                  values[2] = _textout( SwishResultPropertyStr   ( result, "swishtitle" ) );                          elog(ERROR, "pgswish: swish-e sort result list: %d rows expected %d", call_cntr, max_calls - 1);
173                  values[3] = _textout( SwishResultPropertyStr   ( result, "swishdocsize" ) );                          Free_Results_Object( swish_results );
174                  values[4] = _textout( SwishResultPropertyStr   ( result, "swishdbfile" ) );                          Free_Search_Object( search );
175                            SRF_RETURN_DONE(funcctx);
176                    }
177                    
178                    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",
179                            SwishResultPropertyStr   ( sw_res, "swishdocpath" ),
180                            SwishResultPropertyULong ( sw_res, "swishrank" ),
181                            SwishResultPropertyULong ( sw_res, "swishdocsize" ),
182                            SwishResultPropertyStr   ( sw_res, "swishtitle"),
183                            SwishResultPropertyStr   ( sw_res, "swishdbfile" ),
184                            SwishResultPropertyStr   ( sw_res, "swishlastmodified" ),
185                            SwishResultPropertyULong ( sw_res, "swishreccount" ),  /* can figure this out in loop, of course */
186                            SwishResultPropertyULong ( sw_res, "swishfilenum" )
187                    );
188    
189                    values = (char **) palloc(4 * sizeof(char *));
190    
191                    values[0] = prop2int( sw_res, "swishrank" );
192                    values[1] = prop2text( sw_res, "swishdocpath" );
193                    values[2] = prop2text( sw_res, "swishtitle" );
194                    values[3] = prop2int( sw_res, "swishdocsize" );
195    
196    /*
197                    values[0] = (char *) palloc(16 * sizeof(char));
198                    snprintf(values[0], 16, "%d", 1);
199                    values[1] = (char *) palloc(16 * sizeof(char));
200                    snprintf(values[1], 16, "%d", 2);
201                    values[2] = (char *) palloc(16 * sizeof(char));
202                    snprintf(values[2], 16, "%d", 3);
203                    values[3] = (char *) palloc(16 * sizeof(char));
204                    snprintf(values[3], 16, "%d", 4);
205    */
206    
207                  /* build a tuple */                  /* build a tuple */
208                  tuple = BuildTupleFromCStrings(attinmeta, values);                  tuple = BuildTupleFromCStrings(attinmeta, values);
# Line 152  if (0) { Line 210  if (0) {
210                  /* make the tuple into a datum */                  /* make the tuple into a datum */
211                  result = TupleGetDatum(slot, tuple);                  result = TupleGetDatum(slot, tuple);
212    
213  }                  /* clean up ? */
214                  /* clean up (this is not really necessary) */                  pfree(values[0]);
215                    pfree(values[1]);
216                    pfree(values[2]);
217                    pfree(values[3]);
218                    pfree(values);
219                    
220                    elog(DEBUG1, "row: %s|%s|%s|%s",values[0],values[1],values[2],values[3]);
221            
222                  SRF_RETURN_NEXT(funcctx, result);                  SRF_RETURN_NEXT(funcctx, result);
223          } else {          } else {
224                    elog(INFO, "loop over");
225    
226                  /* free swish object and close */                  /* free swish object and close */
227                  Free_Search_Object( search );                  Free_Search_Object( search );
228                  SwishClose( swish_handle );                  SwishClose( swish_handle );
# Line 166  if (0) { Line 232  if (0) {
232          }          }
233  }  }
234    
235    
236    /* make text var from property */
237    char *prop2text(SW_RESULT sw_res, char *propname) {
238            char *val;
239            char *prop;
240            int len;
241    
242            elog(DEBUG2, "prop2text(%s)", propname);
243    
244            prop = SwishResultPropertyStr( sw_res, propname );
245            if (error_or_abort( swish_handle )) return NULL;
246    
247            len = strlen(prop);
248            elog(DEBUG1, "prop2text(%s) = '%s' %d bytes", propname, prop, len);
249    
250            len++;
251            len *= sizeof(char);
252    
253            elog(DEBUG2, "palloc(%d)", len);
254    
255            val = palloc(len);
256    
257            memset(val, 0, len);
258            strncpy(val, prop, len);
259    
260            elog(DEBUG2, "val=%s", val);
261    
262            return val;
263    }
264    
265    /* make integer variable from property */
266    char *prop2int(SW_RESULT sw_res, char *propname) {
267            char *val;
268            unsigned long prop;
269            int len;
270    
271            elog(DEBUG2, "prop2int(%s)", propname);
272    
273            prop = SwishResultPropertyULong( sw_res, propname );
274            if (error_or_abort( swish_handle )) return NULL;
275    
276            elog(DEBUG1, "prop2int(%s) = %lu", propname, prop);
277    
278            len = 128 * sizeof(char);
279            elog(DEBUG2, "palloc(%d)", len);
280    
281            val = palloc(len);
282            memset(val, 0, len);
283    
284            snprintf(val, len, "%lu", prop);
285    
286            elog(DEBUG2, "val=%s", val);
287    
288            return val;
289    }
290    
291    
292  /*  /*
293   * elog errors   * check if swish has returned error, and elog it.
  *  
294   */   */
295    static int error_or_abort( SW_HANDLE swish_handle ) {
 static void error_or_abort( SW_HANDLE swish_handle ) {  
296          if ( !SwishError( swish_handle ) )          if ( !SwishError( swish_handle ) )
297                  return;                  return 0;
298    
299          /* print a message */          /* print a message */
300          elog(ERROR,          elog(ERROR,
# Line 182  static void error_or_abort( SW_HANDLE sw Line 303  static void error_or_abort( SW_HANDLE sw
303                          SwishErrorString( swish_handle ),                          SwishErrorString( swish_handle ),
304                          SwishLastErrorMsg( swish_handle )                          SwishLastErrorMsg( swish_handle )
305          );          );
306            if ( swish_results ) Free_Results_Object( swish_results );
307          if ( search ) Free_Search_Object( search );          if ( search ) Free_Search_Object( search );
308          SwishClose( swish_handle );          SwishClose( swish_handle );
309    
310          /* do when there is no more left */          return 1;
311  }  }
312    

Legend:
Removed from v.9  
changed lines
  Added in v.20

  ViewVC Help
Powered by ViewVC 1.1.26