/[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 20 by dpavlin, Thu May 26 19:42:36 2005 UTC revision 41 by dpavlin, Sat Sep 10 20:35:09 2005 UTC
# Line 14  Line 14 
14   *   *
15   * Based on:   * Based on:
16   * - C example from PostgreSQL documentation (BSD licence)   * - C example from PostgreSQL documentation (BSD licence)
17   * - example002.c from Hyper Estraier (GPL)   * - coreexample002.c and nodeexample002.c from Hyper Estraier (GPL)
18   * - _textin/_textout from pgcurl.c (LGPL)   * - _textin/_textout from pgcurl.c (LGPL)
19   *   *
20   * This code is licenced under GPL   * This code is licenced under GPL
# Line 28  Line 28 
28  #include "miscadmin.h"  #include "miscadmin.h"
29  #include <estraier.h>  #include <estraier.h>
30  #include <cabin.h>  #include <cabin.h>
31    #include <estnode.h>
32    
33  #define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str))  #define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str))
34  #define _textout(str) DatumGetPointer(DirectFunctionCall1(textout, PointerGetDatum(str)))  #define _textout(str) DatumGetPointer(DirectFunctionCall1(textout, PointerGetDatum(str)))
35  #define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))  #define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
36  #define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))  #define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))
37    
38  /* prototype */  /* SortMem got renamed in PostgreSQL 8.0 */
39  char *attr2text(ESTDOC *doc, char *attr);  #ifndef SortMem
40     #define SortMem 16 * 1024
41  ESTDB *db;  #endif
 ESTCOND *cond;  
 ESTDOC *doc;  
 const CBLIST *texts;  
 int ecode, *est_result, resnum, i, j;  
 int limit = 0;  
 int offset = 0;  
   
 /* 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;  
         char            *attr;  
   
         /* stuff done only on the first call of the function */  
         if (SRF_IS_FIRSTCALL()) {  
                 MemoryContext   oldcontext;  
   
                 /* 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);  
                 /* take arguments from function */  
   
                 /* index path */  
                 if (PG_ARGISNULL(0)) {  
                         elog(ERROR, "index path can't be null");  
                         SRF_RETURN_DONE(funcctx);  
                 }  
                 index_path = _textout(PG_GETARG_TEXT_P(0));  
   
                 /* query string */  
                 if (PG_ARGISNULL(0)) {  
                         query = "";  
                 } else {  
                         query = _textout(PG_GETARG_TEXT_P(1));  
                 }  
   
                 /* atribute filter */  
                 if (PG_ARGISNULL(2)) {  
                         attr = "";  
                 } else {  
                         attr = _textout(PG_GETARG_TEXT_P(2));  
                 }  
   
                 /* limit */  
                 if (PG_ARGISNULL(3)) {  
                         limit = 0;  
                 } else {  
                         limit = PG_GETARG_INT32(3);  
                 }  
   
                 /* offset */  
                 if (PG_ARGISNULL(4)) {  
                         offset = 0;  
                 } else {  
                         offset = PG_GETARG_INT32(4);  
                 }  
   
   
                 /* 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(DEBUG1, "pgest: query[%s] attr[%s] limit %d offset %d", query, (PG_ARGISNULL(2) ? "NULL" : attr), limit, offset);  
                   
                 /* 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 */  
                 if (! PG_ARGISNULL(1) && strlen(query) > 0)  
                         est_cond_set_phrase(cond, query);  
   
                 /* minimum valid attribute length is 10: @a STREQ a */  
                 if (! PG_ARGISNULL(2) && strlen(attr) >= 10) {  
                         elog(DEBUG1,"est_cond_add_attr(%s)", attr);  
                         est_cond_add_attr(cond, attr);  
                 }  
   
                 /* get the result of search */  
                 est_result = est_db_search(db, cond, &resnum, NULL);  
                   
                 /* total number of tuples to be returned */  
                 if (limit && limit < resnum) {  
                         funcctx->max_calls = limit - offset;  
                 } else {  
                         funcctx->max_calls = resnum - offset;  
                 }  
   
                 /* check if results exists */  
                 if ( 0 == funcctx->max_calls )  
                         elog(INFO, "pgest: no results for: %s", query );  
   
                 elog(DEBUG1, "pgest: found %d hits for %s", resnum, 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;  
42    
43                  /*  #define ATTR_DELIMITER "{{!}}"
                  * generate attribute metadata needed later to produce tuples from raw  
                  * C strings  
                  */  
                 attinmeta = TupleDescGetAttInMetadata(tupdesc);  
                 funcctx->attinmeta = attinmeta;  
44    
45                  MemoryContextSwitchTo(oldcontext);  /* prototype */
46    char *attr2text(ESTDOC *doc, char *attr);
47                  elog(DEBUG1, "SRF_IS_FIRSTCALL done");  char *node_attr2text(ESTRESDOC *rdoc, char *attr);
         }  
   
         /* 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 (limit && call_cntr > limit - 1) {  
                 elog(DEBUG1, "call_cntr: %d limit: %d", call_cntr, limit);  
                 SRF_RETURN_DONE(funcctx);  
         }  
   
         if (call_cntr < max_calls) {  
                 char            **values;  
                 HeapTuple       tuple;  
                 Datum           result;  
   
                 elog(DEBUG1, "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 + offset], 0)) {  
                   
                         elog(DEBUG1, "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] = (char *) attr2text(doc,"@id");  
                         values[1] = (char *) attr2text(doc,"@uri");  
                         values[2] = (char *) attr2text(doc,"@title");  
                         values[3] = (char *) attr2text(doc,"@size");  
   
                         /* destloy the document object */  
                         elog(DEBUG2, "est_doc_delete");  
                         est_doc_delete(doc);  
                 } else {  
                         elog(INFO, "no result from estraier");  
                         values[0] = DatumGetCString( "" );  
                         values[1] = DatumGetCString( "" );  
                         values[2] = DatumGetCString( "" );  
                         values[3] = DatumGetCString( "" );  
                 }  
   
   
                 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(DEBUG1, "loop over");  
48    
                 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);  
         }  
 }  
49    
50  /* work in progress */  /* work in progress */
51  PG_FUNCTION_INFO_V1(pgest_attr);  PG_FUNCTION_INFO_V1(pgest_attr);
52  Datum pgest_attr(PG_FUNCTION_ARGS)  Datum pgest_attr(PG_FUNCTION_ARGS)
53  {  {
54          ArrayType       *attr_arr = PG_GETARG_ARRAYTYPE_P(5);          ArrayType       *attr_arr = PG_GETARG_ARRAYTYPE_P(6);
55          Oid             element_type = ARR_ELEMTYPE(attr_arr);          Oid             attr_element_type = ARR_ELEMTYPE(attr_arr);
56          int             ndims = ARR_NDIM(attr_arr);          int             attr_ndims = ARR_NDIM(attr_arr);
57          int             *dim_counts = ARR_DIMS(attr_arr);          int             *attr_dim_counts = ARR_DIMS(attr_arr);
58          int             *dim_lower_bounds = ARR_LBOUND(attr_arr);          int             *attr_dim_lower_bounds = ARR_LBOUND(attr_arr);
59          int             ncols = 0;          int             ncols = 0;
60          int             nrows = 0;          int             nrows = 0;
61          int             indx[MAXDIM];          int             indx[MAXDIM];
62          int16           typlen;          int16           attr_len;
63          bool            typbyval;          bool            attr_byval;
64          char            typalign;          char            attr_align;
65          ReturnSetInfo   *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;          ReturnSetInfo   *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
66          AttInMetadata   *attinmeta;          AttInMetadata   *attinmeta;
67          TupleDesc       tupdesc;          TupleDesc       tupdesc;
# Line 288  Datum pgest_attr(PG_FUNCTION_ARGS) Line 74  Datum pgest_attr(PG_FUNCTION_ARGS)
74          int             rsinfo_ncols;          int             rsinfo_ncols;
75          int             i, j;          int             i, j;
76          /* estvars */          /* estvars */
77            ESTDB *db;
78            ESTCOND *cond;
79            ESTDOC *doc;
80            const CBLIST *texts;
81            int ecode, *est_result, resnum;
82            int limit = 0;
83            int offset = 0;
84    
85          char            *index_path;          char            *index_path;
86          char            *query;          char            *query;
87          char            *attr;          char            *attr;
88            char            *order;
89    
90    
91          /* only allow 1D input array */          /* only allow 1D input array */
92          if (ndims == 1)          if (attr_ndims == 1)
93          {          {
94                  ncols = dim_counts[0];                  ncols = attr_dim_counts[0];
95          }          }
96          else          else
97                  ereport(ERROR,                  ereport(ERROR,
# Line 312  Datum pgest_attr(PG_FUNCTION_ARGS) Line 107  Datum pgest_attr(PG_FUNCTION_ARGS)
107                                                  "allowed in this context")));                                                  "allowed in this context")));
108    
109          /* get info about element type needed to construct the array */          /* get info about element type needed to construct the array */
110          get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);          get_typlenbyvalalign(attr_element_type, &attr_len, &attr_byval, &attr_align);
111    
112          /* get the requested return tuple description */          /* get the requested return tuple description */
113          tupdesc = rsinfo->expectedDesc;          tupdesc = rsinfo->expectedDesc;
# Line 353  Datum pgest_attr(PG_FUNCTION_ARGS) Line 148  Datum pgest_attr(PG_FUNCTION_ARGS)
148          index_path = _textout(PG_GETARG_TEXT_P(0));          index_path = _textout(PG_GETARG_TEXT_P(0));
149    
150          /* query string */          /* query string */
151          if (PG_ARGISNULL(0)) {          if (PG_ARGISNULL(1)) {
152                  query = "";                  query = "";
153          } else {          } else {
154                  query = _textout(PG_GETARG_TEXT_P(1));                  query = _textout(PG_GETARG_TEXT_P(1));
# Line 365  Datum pgest_attr(PG_FUNCTION_ARGS) Line 160  Datum pgest_attr(PG_FUNCTION_ARGS)
160          } else {          } else {
161                  attr = _textout(PG_GETARG_TEXT_P(2));                  attr = _textout(PG_GETARG_TEXT_P(2));
162          }          }
163            
164            /* sort order */
165            if (PG_ARGISNULL(3)) {
166                    order = "";
167            } else {
168                    order = _textout(PG_GETARG_TEXT_P(3));
169            }
170    
171    
172          /* limit */          /* limit */
173          if (PG_ARGISNULL(3)) {          if (PG_ARGISNULL(4)) {
174                  limit = 0;                  limit = 0;
175          } else {          } else {
176                  limit = PG_GETARG_INT32(3);                  limit = PG_GETARG_INT32(4);
177          }          }
178    
179          /* offset */          /* offset */
180          if (PG_ARGISNULL(4)) {          if (PG_ARGISNULL(5)) {
181                  offset = 0;                  offset = 0;
182          } else {          } else {
183                  offset = PG_GETARG_INT32(4);                  offset = PG_GETARG_INT32(5);
184          }          }
185    
186    
# Line 404  Datum pgest_attr(PG_FUNCTION_ARGS) Line 207  Datum pgest_attr(PG_FUNCTION_ARGS)
207    
208          /* minimum valid attribute length is 10: @a STREQ a */          /* minimum valid attribute length is 10: @a STREQ a */
209          if (! PG_ARGISNULL(2) && strlen(attr) >= 10) {          if (! PG_ARGISNULL(2) && strlen(attr) >= 10) {
210                  elog(DEBUG1,"est_cond_add_attr(%s)", attr);                  elog(DEBUG1,"attributes: %s", attr);
211                  est_cond_add_attr(cond, attr);                  char *curr_attr;
212                    curr_attr = strtok(attr, ATTR_DELIMITER);
213                    while (curr_attr) {
214                            elog(DEBUG1,"est_cond_add_attr(%s)", curr_attr);
215                            est_cond_add_attr(cond, curr_attr);
216                            curr_attr = strtok(NULL, ATTR_DELIMITER);
217                    }
218            }
219    
220            /* set the search phrase to the search condition object */
221            if (! PG_ARGISNULL(3) && strlen(order) > 0) {
222                    elog(DEBUG1,"est_cond_set_order(%s)", order);
223                    est_cond_set_order(cond, order);
224            }
225    
226            if (limit) {
227                    elog(DEBUG1,"est_cond_set_max(%d)", limit + offset);
228                    est_cond_set_max(cond, limit + offset);
229          }          }
230    
231          /* get the result of search */          /* get the result of search */
# Line 418  Datum pgest_attr(PG_FUNCTION_ARGS) Line 238  Datum pgest_attr(PG_FUNCTION_ARGS)
238    
239          /* total number of tuples to be returned */          /* total number of tuples to be returned */
240          if (limit && limit < resnum) {          if (limit && limit < resnum) {
241                  nrows = limit - offset;                  nrows = limit;
242          } else {          } else {
243                  nrows = resnum - offset;                  nrows = resnum - offset;
244          }          }
# Line 448  Datum pgest_attr(PG_FUNCTION_ARGS) Line 268  Datum pgest_attr(PG_FUNCTION_ARGS)
268                          bool    isnull;                          bool    isnull;
269    
270                          /* array value of this position */                          /* array value of this position */
271                          indx[0] = j + dim_lower_bounds[0];                          indx[0] = j + attr_dim_lower_bounds[0];
272    
273                          dvalue = array_ref(attr_arr, ndims, indx, -1, typlen, typbyval, typalign, &isnull);                          dvalue = array_ref(attr_arr, attr_ndims, indx, -1, attr_len, attr_byval, attr_align, &isnull);
274    
275                          if (!isnull && doc)                          if (!isnull && doc)
276                                  values[j] = DatumGetCString(                                  values[j] = DatumGetCString(
# Line 484  Datum pgest_attr(PG_FUNCTION_ARGS) Line 304  Datum pgest_attr(PG_FUNCTION_ARGS)
304          rsinfo->setDesc = tupdesc;          rsinfo->setDesc = tupdesc;
305          MemoryContextSwitchTo(oldcontext);          MemoryContextSwitchTo(oldcontext);
306    
307            est_cond_delete(cond);
308    
309          if(!est_db_close(db, &ecode)){          if(!est_db_close(db, &ecode)){
310                  ereport(ERROR, (errcode(ERRCODE_IO_ERROR),                  ereport(ERROR, (errcode(ERRCODE_IO_ERROR),
311                          errmsg("est_db_close: %d", ecode),                          errmsg("est_db_close: %d", ecode),
# Line 514  char *attr2text(ESTDOC *doc, char *attr) Line 336  char *attr2text(ESTDOC *doc, char *attr)
336    
337          len++;          len++;
338          len *= sizeof(char);          len *= sizeof(char);
339    
340            elog(DEBUG2, "palloc(%d)", len);
341    
342            val = palloc(len);
343    
344            memset(val, 0, len);
345            strncpy(val, attrval, len);
346    
347            elog(DEBUG2, "val=%s", val);
348    
349            return val;
350    }
351    
352    /*
353     * variation on theme: use node API which doesn't open index on
354     * every query which is much faster for large indexes
355     *
356     */
357    
358    PG_FUNCTION_INFO_V1(pgest_node);
359    Datum pgest_node(PG_FUNCTION_ARGS)
360    {
361            ArrayType       *attr_arr = PG_GETARG_ARRAYTYPE_P(8);
362            Oid             attr_element_type = ARR_ELEMTYPE(attr_arr);
363            int             attr_ndims = ARR_NDIM(attr_arr);
364            int             *attr_dim_counts = ARR_DIMS(attr_arr);
365            int             *attr_dim_lower_bounds = ARR_LBOUND(attr_arr);
366            int             ncols = 0;
367            int             nrows = 0;
368            int             indx[MAXDIM];
369            int16           attr_len;
370            bool            attr_byval;
371            char            attr_align;
372            ReturnSetInfo   *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
373            AttInMetadata   *attinmeta;
374            TupleDesc       tupdesc;
375            Tuplestorestate *tupstore = NULL;
376            HeapTuple       tuple;
377            MemoryContext   per_query_ctx;
378            MemoryContext   oldcontext;
379            Datum           dvalue;
380            char            **values;
381            int             rsinfo_ncols;
382            int             i, j;
383            /* estvars */
384            ESTNODE *node;
385            ESTCOND *cond;
386            ESTNODERES *nres;
387            ESTRESDOC *rdoc;
388            const CBLIST *texts;
389            int resnum = 0;
390            int limit = 0;
391            int offset = 0;
392    
393            char            *node_url;
394            char            *user, *passwd;
395            char            *query;
396            char            *attr;
397            char            *order;
398    
399    
400            /* only allow 1D input array */
401            if (attr_ndims == 1)
402            {
403                    ncols = attr_dim_counts[0];
404            }
405            else
406                    ereport(ERROR,
407                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
408                                     errmsg("invalid input array"),
409                                     errdetail("Input array must have 1 dimension")));
410                    
411            /* check to see if caller supports us returning a tuplestore */
412            if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
413                    ereport(ERROR,
414                                    (errcode(ERRCODE_SYNTAX_ERROR),
415                                     errmsg("materialize mode required, but it is not " \
416                                                    "allowed in this context")));
417    
418            /* get info about element type needed to construct the array */
419            get_typlenbyvalalign(attr_element_type, &attr_len, &attr_byval, &attr_align);
420    
421            /* get the requested return tuple description */
422            tupdesc = rsinfo->expectedDesc;
423            rsinfo_ncols = tupdesc->natts;
424    
425            /*
426             * The requested tuple description better match up with the array
427             * we were given.
428             */
429            if (rsinfo_ncols != ncols)
430                    ereport(ERROR,
431                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
432                                     errmsg("invalid input array"),
433                                     errdetail("Number of elements in array must match number of query specified columns.")));
434    
435            /* OK, use it */
436            attinmeta = TupleDescGetAttInMetadata(tupdesc);
437    
438            /* Now go to work */
439            rsinfo->returnMode = SFRM_Materialize;
440    
441            per_query_ctx = fcinfo->flinfo->fn_mcxt;
442            oldcontext = MemoryContextSwitchTo(per_query_ctx);
443    
444            /* initialize our tuplestore */
445            tupstore = tuplestore_begin_heap(true, false, SortMem);
446    
447    
448            /* take rest of arguments from function */
449    
450            /* node URL */
451            if (PG_ARGISNULL(0)) {
452                    ereport(ERROR,
453                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
454                                     errmsg("node URL can't be null"),
455                                     errdetail("Node URL must be valid URL to HyperEstraier node")));
456            }
457            node_url = _textout(PG_GETARG_TEXT_P(0));
458    
459            /* login and password */
460            if (PG_ARGISNULL(1) || PG_ARGISNULL(2)) {
461                    ereport(ERROR,
462                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
463                                     errmsg("username and password can't be NULL"),
464                                     errdetail("You must specify valid username and password to HyperEstraier node")));
465            }
466            user = _textout(PG_GETARG_TEXT_P(1));
467            passwd = _textout(PG_GETARG_TEXT_P(2));
468    
469            /* query string */
470            if (PG_ARGISNULL(3)) {
471                    query = "";
472            } else {
473                    query = _textout(PG_GETARG_TEXT_P(3));
474            }
475    
476            /* atribute filter */
477            if (PG_ARGISNULL(4)) {
478                    attr = "";
479            } else {
480                    attr = _textout(PG_GETARG_TEXT_P(4));
481            }
482            
483            /* sort order */
484            if (PG_ARGISNULL(5)) {
485                    order = "";
486            } else {
487                    order = _textout(PG_GETARG_TEXT_P(5));
488            }
489    
490    
491            /* limit */
492            if (PG_ARGISNULL(6)) {
493                    limit = 0;
494            } else {
495                    limit = PG_GETARG_INT32(6);
496            }
497    
498            /* offset */
499            if (PG_ARGISNULL(7)) {
500                    offset = 0;
501            } else {
502                    offset = PG_GETARG_INT32(7);
503            }
504    
505            /* initialize the network environment */
506            if(!est_init_net_env()){
507                    ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED),
508                            errmsg("pgest_node: can't create network enviroment")));
509            }
510    
511            /* create the node connection object */
512            elog(DEBUG1, "pgest_node: est_node_new(%s) as %s", node_url, user);
513            node = est_node_new(node_url);
514            est_node_set_auth(node, user, passwd);
515    
516            elog(DEBUG1, "pgest_node: query[%s] attr[%s] limit %d offset %d", query, (PG_ARGISNULL(4) ? "NULL" : attr), limit, offset);
517            
518            /* create a search condition object */
519            if (!(cond = est_cond_new())) {
520                    ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED),
521                            errmsg("pgest_node: est_cond_new failed")));
522            }
523            
524            /* set the search phrase to the search condition object */
525            if (! PG_ARGISNULL(3) && strlen(query) > 0)
526                    est_cond_set_phrase(cond, query);
527    
528            /* minimum valid attribute length is 10: @a STREQ a */
529            if (! PG_ARGISNULL(4) && strlen(attr) >= 10) {
530                    elog(DEBUG1,"attributes: %s", attr);
531                    char *curr_attr;
532                    curr_attr = strtok(attr, ATTR_DELIMITER);
533                    while (curr_attr) {
534                            elog(DEBUG1,"est_cond_add_attr(%s)", curr_attr);
535                            est_cond_add_attr(cond, curr_attr);
536                            curr_attr = strtok(NULL, ATTR_DELIMITER);
537                    }
538            }
539    
540            /* set the search phrase to the search condition object */
541            if (! PG_ARGISNULL(5) && strlen(order) > 0) {
542                    elog(DEBUG1,"est_cond_set_order(%s)", order);
543                    est_cond_set_order(cond, order);
544            }
545    
546            if (limit) {
547                    elog(DEBUG1,"est_cond_set_max(%d)", limit + offset);
548                    est_cond_set_max(cond, limit + offset);
549            }
550    
551            /* get the result of search */
552            /* FIXME: allow user to specify depath of search */
553            nres = est_node_search(node, cond, 0);
554    
555            /* get number of results */
556            resnum = est_noderes_doc_num(nres);
557    
558            /* check if results exists */
559            if ( 0 == resnum ) {
560                    elog(INFO, "pgest_node: no results for: %s", query );
561            }
562    
563            /* total number of tuples to be returned */
564            if (limit && limit < resnum) {
565                    nrows = limit;
566            } else {
567                    nrows = resnum - offset;
568            }
569    
570    
571            elog(DEBUG1, "pgest_node: found %d hits for %s", resnum, query);
572    
573    
574            values = (char **) palloc(ncols * sizeof(char *));
575    
576            for (i = 0; i < nrows; i++)
577            {
578    
579                    /* get result from estraier */
580                    if (! ( rdoc = est_noderes_get_doc(nres, i + offset) )) {
581                            elog(INFO, "can't find result %d", i + offset);
582                    } else {
583                            elog(DEBUG1, "URI: %s\n Title: %s\n",
584                                    est_resdoc_attr(rdoc, "@uri"),
585                                    est_resdoc_attr(rdoc, "@title")
586                            );
587                    }
588    
589                    /* iterate over results */
590                    for (j = 0; j < ncols; j++)
591                    {
592                            bool    isnull;
593    
594                            /* array value of this position */
595                            indx[0] = j + attr_dim_lower_bounds[0];
596    
597                            dvalue = array_ref(attr_arr, attr_ndims, indx, -1, attr_len, attr_byval, attr_align, &isnull);
598    
599                            if (!isnull && rdoc)
600                                    values[j] = DatumGetCString(
601                                            node_attr2text(rdoc,
602                                                    (char *)DirectFunctionCall1(textout, dvalue)
603                                            ));
604                            else
605                                    values[j] = NULL;
606                    }
607                    /* construct the tuple */
608                    tuple = BuildTupleFromCStrings(attinmeta, values);
609    
610                    /* now store it */
611                    tuplestore_puttuple(tupstore, tuple);
612    
613            }
614    
615            tuplestore_donestoring(tupstore);
616            rsinfo->setResult = tupstore;
617    
618            /*
619             * SFRM_Materialize mode expects us to return a NULL Datum. The actual
620             * tuples are in our tuplestore and passed back through
621             * rsinfo->setResult. rsinfo->setDesc is set to the tuple description
622             * that we actually used to build our tuples with, so the caller can
623             * verify we did what it was expecting.
624             */
625            rsinfo->setDesc = tupdesc;
626            MemoryContextSwitchTo(oldcontext);
627    
628            /* delete the node result object */
629            est_noderes_delete(nres);
630    
631            /* destroy the search condition object */                          
632            est_cond_delete(cond);
633    
634            /* destroy the node object */
635            est_node_delete(node);
636    
637            /* free the networking environment */
638            est_free_net_env();
639    
640            return (Datum) 0;
641    }
642    
643    /* make text var from node attr */
644    char *node_attr2text(ESTRESDOC *rdoc, char *attr) {
645            char *val;
646            const char *attrval;
647            int len;
648            int attrlen;
649    
650            elog(DEBUG1, "doc: %08x, attr: %s", rdoc, attr);
651    
652            if ( (attrval = est_resdoc_attr(rdoc, attr)) && (attrlen = strlen(attrval)) ) {
653                    val = (char *) palloc(attrlen * sizeof(char));
654            } else {
655                    return (Datum) NULL;
656            }
657    
658            len = strlen(attrval);
659            elog(DEBUG1, "node_attr2text(%s) = '%s' %d bytes", attr, attrval, len);
660    
661            len++;
662            len *= sizeof(char);
663    
664          elog(DEBUG2, "palloc(%d)", len);          elog(DEBUG2, "palloc(%d)", len);
665    

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

  ViewVC Help
Powered by ViewVC 1.1.26