/[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

Annotation of /trunk/pgswish.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8 - (hide annotations)
Fri Feb 18 23:34:31 2005 UTC (19 years, 2 months ago) by dpavlin
File MIME type: text/plain
File size: 4946 byte(s)
first, not-yet working C version

1 dpavlin 8 /*
2     * integrate swish-e into PostgreSQL
3     *
4     * Dobrica Pavlinusic <dpavlin@rot13.org> 2005-02-18
5     *
6     * TODO:
7     * - check null input using PG_ARGISNULL before using PG_GETARG_xxxx
8     * - support composite type arguments
9     *
10     * NOTES:
11     * - clear structures with memset to support hash indexes (who whould like
12     * to create hash index on table returned from function?)
13     *
14     * Based on C example from PostgreSQL documentation and swish-e
15     * src/libtest.c, so licence is GPL
16     */
17    
18     #include "postgres.h"
19     #include "fmgr.h"
20     #include "funcapi.h"
21     #include <swish-e.h>
22    
23    
24     SW_HANDLE swish_handle = NULL;/* Database handle */
25     SW_SEARCH search = NULL; /* search handle -- holds search parameters */
26     SW_RESULTS results = NULL; /* results handle -- holds list of results */
27    
28     /* define PostgreSQL v1 function */
29     PG_FUNCTION_INFO_V1(pgswish);
30     Datum pgswish(PG_FUNCTION_ARGS) {
31    
32     FuncCallContext *funcctx;
33     int call_cntr;
34     int max_calls;
35     TupleDesc tupdesc;
36     TupleTableSlot *slot;
37     AttInMetadata *attinmeta;
38     SW_HANDLE swish_handle = NULL; /* Database handle */
39     SW_SEARCH search = NULL; /* search handle -- holds search parameters */
40     SW_RESULTS results = NULL; /* results handle -- holds list of results */
41    
42     /* stuff done only on the first call of the function */
43     if (SRF_IS_FIRSTCALL()) {
44     MemoryContext oldcontext;
45    
46     /* create a function context for cross-call persistence */
47     funcctx = SRF_FIRSTCALL_INIT();
48    
49     /* switch to memory context appropriate for multiple function calls */
50     oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
51    
52     /* Send any errors or warnings to stderr (default is stdout) */
53     SwishErrorsToStderr();
54    
55     elog(INFO, "pgswish opening %s, query %s",
56     PG_GETARG_TEXT_P(0),
57     PG_GETARG_TEXT_P(1)
58     );
59    
60     swish_handle = SwishInit( (char *)PG_GETARG_TEXT_P(0) );
61    
62     if (! swish_handle) {
63     elog(ERROR, "pgswish: can't open %s", PG_GETARG_TEXT_P(0));
64     SRF_RETURN_DONE(funcctx);
65     }
66    
67     if ( SwishError( swish_handle ) ) error_or_abort( swish_handle );
68     /* set ranking scheme. default is 0 */
69     SwishRankScheme( swish_handle, 1 );
70    
71     /* Check for errors after every call */
72     if ( SwishError( swish_handle ) )
73     error_or_abort( swish_handle ); /* print an error or abort -- see below */
74    
75     /* Here's a short-cut to searching that creates a search object and searches at the same time */
76     results = SwishQuery( swish_handle, (char *)PG_GETARG_TEXT_P(1) );
77    
78     if ( SwishError( swish_handle ) ) error_or_abort( swish_handle );
79    
80     /* total number of tuples to be returned */
81     funcctx->max_calls = SwishHits( results );
82    
83     /* check if results exists */
84     if ( 0 == funcctx->max_calls )
85     elog(INFO, "no results for: %s", PG_GETARG_TEXT_P(1) );
86    
87     /* Build a tuple description for a __pgswish tuple */
88     tupdesc = RelationNameGetTupleDesc("__pgswish");
89    
90     /* allocate a slot for a tuple with this tupdesc */
91     slot = TupleDescGetSlot(tupdesc);
92    
93     /* assign slot to function context */
94     funcctx->slot = slot;
95    
96     /*
97     * generate attribute metadata needed later to produce tuples from raw
98     * C strings
99     */
100     attinmeta = TupleDescGetAttInMetadata(tupdesc);
101     funcctx->attinmeta = attinmeta;
102    
103     MemoryContextSwitchTo(oldcontext);
104     }
105    
106     /* stuff done on every call of the function */
107     funcctx = SRF_PERCALL_SETUP();
108    
109     call_cntr = funcctx->call_cntr;
110     max_calls = funcctx->max_calls;
111     slot = funcctx->slot;
112     attinmeta = funcctx->attinmeta;
113    
114     if (call_cntr < max_calls) {
115     char **values;
116     HeapTuple tuple;
117     Datum result;
118    
119     if (0) {
120     /*
121     * Prepare a values array for storage in our slot.
122     * This should be an array of C strings which will
123     * be processed later by the type input functions.
124     */
125     values = (void **) palloc(5 * sizeof(void *));
126     values[0] = (long *) SwishResultPropertyULong ( result, "swishrank" ),
127     values[1] = (char *) SwishResultPropertyStr ( result, "swishdocpath" ),
128     values[2] = (char *) SwishResultPropertyStr ( result, "swishtitle" ),
129     values[3] = (long *) SwishResultPropertyStr ( result, "swishdocsize" ),
130     values[4] = (char *) SwishResultPropertyStr ( result, "swishdbfile" ),
131    
132     /* build a tuple */
133     tuple = BuildTupleFromCStrings(attinmeta, values);
134    
135     /* make the tuple into a datum */
136     result = TupleGetDatum(slot, tuple);
137    
138     }
139     /* clean up (this is not really necessary) */
140    
141     SRF_RETURN_NEXT(funcctx, result);
142     } else {
143     /* free swish object and close */
144     Free_Search_Object( search );
145     SwishClose( swish_handle );
146    
147     /* do when there is no more left */
148     SRF_RETURN_DONE(funcctx);
149     }
150     }
151    
152     /*
153     * elog errors
154     *
155     */
156    
157     static void error_or_abort( SW_HANDLE swish_handle ) {
158     if ( !SwishError( swish_handle ) )
159     return;
160    
161     /* print a message */
162     elog(ERROR,
163     "pgswish error: Number [%d], Type [%s], Optional Message: [%s]\n",
164     SwishError( swish_handle ),
165     SwishErrorString( swish_handle ),
166     SwishLastErrorMsg( swish_handle )
167     );
168     if ( search ) Free_Search_Object( search );
169     SwishClose( swish_handle );
170    
171     /* do when there is no more left */
172     }
173    

  ViewVC Help
Powered by ViewVC 1.1.26