/[pgestraier]/trunk/pgest.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/pgest.c

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

revision 1 by dpavlin, Fri May 20 12:19:05 2005 UTC revision 38 by dpavlin, Fri Jul 8 12:47:49 2005 UTC
# Line 34  Line 34 
34  #define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))  #define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
35  #define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))  #define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))
36    
37    /* SortMem got renamed in PostgreSQL 8.0 */
38    #ifndef SortMem
39     #define SortMem 16 * 1024
40    #endif
41    
42  ESTDB *db;  /* prototype */
43  ESTCOND *cond;  char *attr2text(ESTDOC *doc, char *attr);
 ESTDOC *doc;  
 const CBLIST *texts;  
 int ecode, *est_result, resnum, i, j;  
   
 /* define PostgreSQL v1 function */  
 PG_FUNCTION_INFO_V1(pgest);  
 Datum pgest(PG_FUNCTION_ARGS) {  
   
         FuncCallContext *funcctx;  
         int             call_cntr;  
         int             max_calls;  
         TupleDesc       tupdesc;  
         TupleTableSlot  *slot;  
         AttInMetadata   *attinmeta;  
         char            *index_path;  
         char            *query;  
   
         /* stuff done only on the first call of the function */  
         if (SRF_IS_FIRSTCALL()) {  
                 MemoryContext   oldcontext;  
   
                 /* take arguments from function */  
                 //index_path = _textout(PG_GETARG_TEXT_P(0));  
                 index_path = _textout(PG_GETARG_TEXT_P(0));  
                 query = _textout(PG_GETARG_TEXT_P(1));  
   
                 /* create a function context for cross-call persistence */  
                 funcctx = SRF_FIRSTCALL_INIT();  
   
                 /* switch to memory context appropriate for multiple function calls */  
                 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);  
   
                 /* open the database */  
                 elog(DEBUG1, "pgest: est_db_open(%s)", index_path);  
                   
                 if(!(db = est_db_open(index_path, ESTDBREADER, &ecode))){  
                         elog(ERROR, "est_db_open: can't open %s [%d]: %s", index_path, ecode, est_err_msg(ecode));  
                         SRF_RETURN_DONE(funcctx);  
                 }  
                   
                 elog(DEBUG2, "pgest: query=%s", query);  
                   
                 /* create a search condition object */  
                 if (!(cond = est_cond_new())) {  
                         elog(INFO, "pgest: est_cond_new failed");  
                         SRF_RETURN_DONE(funcctx);  
                 }  
                   
                 /* set the search phrase to the search condition object */  
                 est_cond_set_phrase(cond, query);  
   
                 /* get the result of search */  
                 est_result = est_db_search(db, cond, &resnum, NULL);  
                   
                 /* total number of tuples to be returned */  
                 funcctx->max_calls = resnum;  
44    
                 /* check if results exists */  
                 if ( 0 == funcctx->max_calls )  
                         elog(INFO, "pgest: no results for: %s", query );  
   
                 elog(INFO, "pgest: found %d hits for %s", funcctx->max_calls, query);  
   
                 /* Build a tuple description for a __pgest tuple */  
                 tupdesc = RelationNameGetTupleDesc("__pgest");  
   
                 /* allocate a slot for a tuple with this tupdesc */  
                 slot = TupleDescGetSlot(tupdesc);  
   
                 /* assign slot to function context */  
                 funcctx->slot = slot;  
   
                 /*  
                  * generate attribute metadata needed later to produce tuples from raw  
                  * C strings  
                  */  
                 attinmeta = TupleDescGetAttInMetadata(tupdesc);  
                 funcctx->attinmeta = attinmeta;  
   
                 MemoryContextSwitchTo(oldcontext);  
   
                 elog(INFO, "SRF_IS_FIRSTCALL done");  
         }  
   
         /* stuff done on every call of the function */  
         funcctx = SRF_PERCALL_SETUP();  
   
         call_cntr = funcctx->call_cntr;  
         max_calls = funcctx->max_calls;  
         slot = funcctx->slot;  
         attinmeta = funcctx->attinmeta;  
   
         if (call_cntr < max_calls) {  
                 char            **values;  
                 HeapTuple       tuple;  
                 Datum           result;  
   
                 elog(INFO, "pgest: loop count %d", call_cntr);  
   
                 if (! est_result) {  
                         elog(ERROR, "pgest: no estraier results");  
                         SRF_RETURN_DONE(funcctx);  
                 }  
                   
                 /*  
                  * 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.  
                  */  
   
                 if (doc = est_db_get_doc(db, est_result[call_cntr], 0)) {  
                   
                         elog(INFO, "URI: %s\n Title: %s\n",  
                                 est_doc_attr(doc, "@uri"),  
                                 est_doc_attr(doc, "@title")  
                         );  
   
                         values = (char **) palloc(4 * sizeof(char *));  
   
 //                      values[0] = (char *) palloc(strlen(_estval) * sizeof(char));  
   
                         values[0] = attr2text(doc,"@id");  
                         values[1] = attr2text(doc,"@uri");  
                         values[2] = attr2text(doc,"@title");  
                         values[3] = attr2text(doc,"@type");  
   
                         /* destloy the document object */  
                         elog(DEBUG2, "est_doc_delete");  
                         est_doc_delete(doc);  
                 } else {  
                         elog(INFO, "no result from estraier");  
                         values[0] = NULL;  
                         values[1] = NULL;  
                         values[2] = NULL;  
                         values[3] = NULL;  
                 }  
   
   
                 elog(DEBUG2, "build tuple");  
                 /* build a tuple */  
                 tuple = BuildTupleFromCStrings(attinmeta, values);  
   
                 elog(DEBUG2, "make tuple into datum");  
                 /* make the tuple into a datum */  
                 result = TupleGetDatum(slot, tuple);  
   
                 elog(DEBUG2, "cleanup");  
                 /* clean up ? */  
 /*  
                 pfree(values[0]);  
                 pfree(values[1]);  
                 pfree(values[2]);  
                 pfree(values[3]);  
                 pfree(values);  
 */  
                   
                 elog(DEBUG2, "cleanup over");  
           
                 SRF_RETURN_NEXT(funcctx, result);  
         } else {  
                 elog(INFO, "loop over");  
   
                 if(!est_db_close(db, &ecode)){  
                         elog(INFO, "est_db_close error: %s", est_err_msg(ecode));  
                 }  
   
                 /* do when there is no more left */  
                 SRF_RETURN_DONE(funcctx);  
         }  
 }  
45    
46  /* work in progress */  /* work in progress */
47  PG_FUNCTION_INFO_V1(pgest2);  PG_FUNCTION_INFO_V1(pgest_attr);
48  Datum pgest2(PG_FUNCTION_ARGS)  Datum pgest_attr(PG_FUNCTION_ARGS)
49  {  {
50          int             nrows = 3;          ArrayType       *attr_arr = PG_GETARG_ARRAYTYPE_P(6);
51          int16           typlen;          Oid             attr_element_type = ARR_ELEMTYPE(attr_arr);
52          bool            typbyval;          int             attr_ndims = ARR_NDIM(attr_arr);
53          char            typalign;          int             *attr_dim_counts = ARR_DIMS(attr_arr);
54            int             *attr_dim_lower_bounds = ARR_LBOUND(attr_arr);
55            int             ncols = 0;
56            int             nrows = 0;
57            int             indx[MAXDIM];
58            int16           attr_len;
59            bool            attr_byval;
60            char            attr_align;
61          ReturnSetInfo   *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;          ReturnSetInfo   *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
62          AttInMetadata   *attinmeta;          AttInMetadata   *attinmeta;
63          TupleDesc       tupdesc;          TupleDesc       tupdesc;
64          Tuplestorestate *tupstore = NULL;          Tuplestorestate *tupstore = NULL;
65          HeapTuple       tuple;          HeapTuple       tuple;
66          MemoryContext   per_query_ctx;          MemoryContext   per_query_ctx;
67          MemoryContext   oldcontext;          MemoryContext   oldcontext;
68          Datum           dvalue;          Datum           dvalue;
69          char            **values;          char            **values;
70          int             ncols;          int             rsinfo_ncols;
71          int             i, j;          int             i, j;
72            /* estvars */
73            ESTDB *db;
74            ESTCOND *cond;
75            ESTDOC *doc;
76            const CBLIST *texts;
77            int ecode, *est_result, resnum;
78            int limit = 0;
79            int offset = 0;
80    
81            char            *index_path;
82            char            *query;
83            char            *attr;
84            char            *order;
85    
86    
87            /* only allow 1D input array */
88            if (attr_ndims == 1)
89            {
90                    ncols = attr_dim_counts[0];
91            }
92            else
93                    ereport(ERROR,
94                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
95                                     errmsg("invalid input array"),
96                                     errdetail("Input array must have 1 dimension")));
97                    
98          /* check to see if caller supports us returning a tuplestore */          /* check to see if caller supports us returning a tuplestore */
99          if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))          if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
100                  ereport(ERROR,                  ereport(ERROR,
# Line 235  Datum pgest2(PG_FUNCTION_ARGS) Line 102  Datum pgest2(PG_FUNCTION_ARGS)
102                                   errmsg("materialize mode required, but it is not " \                                   errmsg("materialize mode required, but it is not " \
103                                                  "allowed in this context")));                                                  "allowed in this context")));
104    
105            /* get info about element type needed to construct the array */
106            get_typlenbyvalalign(attr_element_type, &attr_len, &attr_byval, &attr_align);
107    
108          /* get the requested return tuple description */          /* get the requested return tuple description */
109          tupdesc = rsinfo->expectedDesc;          tupdesc = rsinfo->expectedDesc;
110          ncols = tupdesc->natts;          rsinfo_ncols = tupdesc->natts;
111    
112          /*          /*
113           * The requested tuple description better match up with the array           * The requested tuple description better match up with the array
114           * we were given.           * we were given.
115           */           */
116            if (rsinfo_ncols != ncols)
117                    ereport(ERROR,
118                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
119                                     errmsg("invalid input array"),
120                                     errdetail("Number of elements in array must match number of query specified columns.")));
121    
122          /* OK, use it */          /* OK, use it */
123          attinmeta = TupleDescGetAttInMetadata(tupdesc);          attinmeta = TupleDescGetAttInMetadata(tupdesc);
124    
# Line 255  Datum pgest2(PG_FUNCTION_ARGS) Line 131  Datum pgest2(PG_FUNCTION_ARGS)
131          /* initialize our tuplestore */          /* initialize our tuplestore */
132          tupstore = tuplestore_begin_heap(true, false, SortMem);          tupstore = tuplestore_begin_heap(true, false, SortMem);
133    
134    
135            /* take rest of arguments from function */
136    
137            /* index path */
138            if (PG_ARGISNULL(0)) {
139                    ereport(ERROR,
140                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
141                                     errmsg("index path can't be null"),
142                                     errdetail("Index path must be valid full path to HyperEstraier index")));
143            }
144            index_path = _textout(PG_GETARG_TEXT_P(0));
145    
146            /* query string */
147            if (PG_ARGISNULL(1)) {
148                    query = "";
149            } else {
150                    query = _textout(PG_GETARG_TEXT_P(1));
151            }
152    
153            /* atribute filter */
154            if (PG_ARGISNULL(2)) {
155                    attr = "";
156            } else {
157                    attr = _textout(PG_GETARG_TEXT_P(2));
158            }
159            
160            /* sort order */
161            if (PG_ARGISNULL(3)) {
162                    order = "";
163            } else {
164                    order = _textout(PG_GETARG_TEXT_P(3));
165            }
166    
167    
168            /* limit */
169            if (PG_ARGISNULL(4)) {
170                    limit = 0;
171            } else {
172                    limit = PG_GETARG_INT32(4);
173            }
174    
175            /* offset */
176            if (PG_ARGISNULL(5)) {
177                    offset = 0;
178            } else {
179                    offset = PG_GETARG_INT32(5);
180            }
181    
182    
183            /* open the database */
184            elog(DEBUG1, "pgest_attr: est_db_open(%s)", index_path);
185                    
186            if(!(db = est_db_open(index_path, ESTDBREADER, &ecode))){
187                    ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
188                            errmsg("est_db_open: can't open %s: %d", index_path, ecode),
189                            errdetail(est_err_msg(ecode))));
190            }
191                    
192            elog(DEBUG1, "pgest_attr: query[%s] attr[%s] limit %d offset %d", query, (PG_ARGISNULL(2) ? "NULL" : attr), limit, offset);
193            
194            /* create a search condition object */
195            if (!(cond = est_cond_new())) {
196                    ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED),
197                            errmsg("pgest_attr: est_cond_new failed")));
198            }
199            
200            /* set the search phrase to the search condition object */
201            if (! PG_ARGISNULL(1) && strlen(query) > 0)
202                    est_cond_set_phrase(cond, query);
203    
204            /* minimum valid attribute length is 10: @a STREQ a */
205            if (! PG_ARGISNULL(2) && strlen(attr) >= 10) {
206                    elog(DEBUG1,"est_cond_add_attr(%s)", attr);
207                    est_cond_add_attr(cond, attr);
208            }
209    
210            /* set the search phrase to the search condition object */
211            if (! PG_ARGISNULL(3) && strlen(order) > 0) {
212                    elog(DEBUG1,"est_cond_set_order(%s)", order);
213                    est_cond_set_order(cond, order);
214            }
215    
216            if (limit) {
217                    elog(DEBUG1,"est_cond_set_max(%d)", limit + offset);
218                    est_cond_set_max(cond, limit + offset);
219            }
220    
221            /* get the result of search */
222            est_result = est_db_search(db, cond, &resnum, NULL);
223    
224            /* check if results exists */
225            if ( 0 == resnum ) {
226                    elog(INFO, "pgest_attr: no results for: %s", query );
227            }
228    
229            /* total number of tuples to be returned */
230            if (limit && limit < resnum) {
231                    nrows = limit;
232                    elog(INFO, "This is probably a bug in limit implementation. Please report it to dpavlin@rot13.org");
233            } else {
234                    nrows = resnum - offset;
235            }
236    
237    
238            elog(DEBUG1, "pgest_attr: found %d hits for %s", resnum, query);
239    
240    
241          values = (char **) palloc(ncols * sizeof(char *));          values = (char **) palloc(ncols * sizeof(char *));
242    
243          for (i = 0; i < nrows; i++)          for (i = 0; i < nrows; i++)
244          {          {
245    
246                    /* get result from estraier */
247                    if (! ( doc = est_db_get_doc(db, est_result[i + offset], 0)) ) {
248                            elog(INFO, "can't find result %d", i + offset);
249                    } else {
250                            elog(DEBUG1, "URI: %s\n Title: %s\n",
251                                    est_doc_attr(doc, "@uri"),
252                                    est_doc_attr(doc, "@title")
253                            );
254                    }
255    
256                    /* iterate over results */
257                  for (j = 0; j < ncols; j++)                  for (j = 0; j < ncols; j++)
258                  {                  {
259                          values[j] = DatumGetCString( "foo" );                          bool    isnull;
260    
261                            /* array value of this position */
262                            indx[0] = j + attr_dim_lower_bounds[0];
263    
264                            dvalue = array_ref(attr_arr, attr_ndims, indx, -1, attr_len, attr_byval, attr_align, &isnull);
265    
266                            if (!isnull && doc)
267                                    values[j] = DatumGetCString(
268                                            attr2text(doc,
269                                                    (char *)DirectFunctionCall1(textout, dvalue)
270                                            ));
271                            else
272                                    values[j] = NULL;
273                  }                  }
274                  /* construct the tuple */                  /* construct the tuple */
275                  tuple = BuildTupleFromCStrings(attinmeta, values);                  tuple = BuildTupleFromCStrings(attinmeta, values);
276    
277                  /* now store it */                  /* now store it */
278                  tuplestore_puttuple(tupstore, tuple);                  tuplestore_puttuple(tupstore, tuple);
279    
280    
281                    /* delete estraier document object */
282                    est_doc_delete(doc);
283          }          }
284    
285          tuplestore_donestoring(tupstore);          tuplestore_donestoring(tupstore);
# Line 283  Datum pgest2(PG_FUNCTION_ARGS) Line 295  Datum pgest2(PG_FUNCTION_ARGS)
295          rsinfo->setDesc = tupdesc;          rsinfo->setDesc = tupdesc;
296          MemoryContextSwitchTo(oldcontext);          MemoryContextSwitchTo(oldcontext);
297    
298            est_cond_delete(cond);
299    
300            if(!est_db_close(db, &ecode)){
301                    ereport(ERROR, (errcode(ERRCODE_IO_ERROR),
302                            errmsg("est_db_close: %d", ecode),
303                            errdetail(est_err_msg(ecode))));
304            }
305    
306          return (Datum) 0;          return (Datum) 0;
307  }  }
308    
# Line 292  char *attr2text(ESTDOC *doc, char *attr) Line 312  char *attr2text(ESTDOC *doc, char *attr)
312          char *val;          char *val;
313          const char *attrval;          const char *attrval;
314          int len;          int len;
315            int attrlen;
316    
317          elog(INFO, "doc: %08x, attr: %s", doc, attr);          elog(DEBUG1, "doc: %08x, attr: %s", doc, attr);
318    
319          if (attrval = est_doc_attr(doc, attr)) {          if ( (attrval = est_doc_attr(doc, attr)) && (attrlen = strlen(attrval)) ) {
320                  val = (char *) palloc(strlen(attrval) * sizeof(char));                  val = (char *) palloc(attrlen * sizeof(char));
321          } else {          } else {
322                  return (Datum) NULL;                  return (Datum) NULL;
323          }          }
324    
325          len = strlen(attrval);          len = strlen(attrval);
326          elog(INFO, "attr2text(%s) = '%s' %d bytes", attr, attrval, len);          elog(DEBUG1, "attr2text(%s) = '%s' %d bytes", attr, attrval, len);
327    
328          len++;          len++;
329          len *= sizeof(char);          len *= sizeof(char);
# Line 319  char *attr2text(ESTDOC *doc, char *attr) Line 340  char *attr2text(ESTDOC *doc, char *attr)
340          return val;          return val;
341  }  }
342    
 /* make integer variable from property */  
 /*  
 char *prop2int(SW_RESULT sw_res, char *propname) {  
         char *val;  
         unsigned long prop;  
         int len;  
   
         elog(DEBUG2, "prop2int(%s)", propname);  
   
         prop = estResultPropertyULong( sw_res, propname );  
         if (error_or_abort( est_handle )) return NULL;  
   
         elog(DEBUG1, "prop2int(%s) = %lu", propname, prop);  
   
         len = 128 * sizeof(char);  
         elog(DEBUG2, "palloc(%d)", len);  
   
         val = palloc(len);  
         memset(val, 0, len);  
   
         snprintf(val, len, "%lu", prop);  
   
         elog(DEBUG2, "val=%s", val);  
   
         return val;  
 }  
 */  

Legend:
Removed from v.1  
changed lines
  Added in v.38

  ViewVC Help
Powered by ViewVC 1.1.26