/[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 48 by dpavlin, Thu Oct 20 16:24:26 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    /* SortMem got renamed in PostgreSQL 8.0 */
39    #ifndef SortMem
40     #define SortMem 16 * 1024
41    #endif
42    
43    #define ATTR_DELIMITER "{{!}}"
44    
45    /* prototype */
46    char *attr2text(ESTDOC *doc, char *attr);
47    char *node_attr2text(ESTRESDOC *rdoc, char *attr);
48    
49  ESTDB *db;  
50  ESTCOND *cond;  /* work in progress */
51  ESTDOC *doc;  PG_FUNCTION_INFO_V1(pgest_attr);
52  const CBLIST *texts;  Datum pgest_attr(PG_FUNCTION_ARGS)
53  int ecode, *est_result, resnum, i, j;  {
54            ArrayType       *attr_arr = PG_GETARG_ARRAYTYPE_P(6);
55  /* define PostgreSQL v1 function */          Oid             attr_element_type = ARR_ELEMTYPE(attr_arr);
56  PG_FUNCTION_INFO_V1(pgest);          int             attr_ndims = ARR_NDIM(attr_arr);
57  Datum pgest(PG_FUNCTION_ARGS) {          int             *attr_dim_counts = ARR_DIMS(attr_arr);
58            int             *attr_dim_lower_bounds = ARR_LBOUND(attr_arr);
59          FuncCallContext *funcctx;          int             ncols = 0;
60          int             call_cntr;          int             nrows = 0;
61          int             max_calls;          int             indx[MAXDIM];
62          TupleDesc       tupdesc;          int16           attr_len;
63          TupleTableSlot  *slot;          bool            attr_byval;
64            char            attr_align;
65            ReturnSetInfo   *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
66          AttInMetadata   *attinmeta;          AttInMetadata   *attinmeta;
67            TupleDesc       tupdesc;
68            Tuplestorestate *tupstore = NULL;
69            HeapTuple       tuple;
70            MemoryContext   per_query_ctx;
71            MemoryContext   oldcontext;
72            Datum           dvalue;
73            char            **values;
74            int             rsinfo_ncols;
75            int             i, j;
76            /* 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;
88            char            *order;
89    
         /* 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));  
90    
91                  /* create a function context for cross-call persistence */          /* only allow 1D input array */
92                  funcctx = SRF_FIRSTCALL_INIT();          if (attr_ndims == 1)
93            {
94                    ncols = attr_dim_counts[0];
95            }
96            else
97                    ereport(ERROR,
98                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
99                                     errmsg("invalid input array"),
100                                     errdetail("Input array must have 1 dimension")));
101                    
102            /* check to see if caller supports us returning a tuplestore */
103            if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
104                    ereport(ERROR,
105                                    (errcode(ERRCODE_SYNTAX_ERROR),
106                                     errmsg("materialize mode required, but it is not " \
107                                                    "allowed in this context")));
108    
109                  /* switch to memory context appropriate for multiple function calls */          /* get info about element type needed to construct the array */
110                  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);          get_typlenbyvalalign(attr_element_type, &attr_len, &attr_byval, &attr_align);
111    
112                  /* open the database */          /* get the requested return tuple description */
113                  elog(DEBUG1, "pgest: est_db_open(%s)", index_path);          tupdesc = rsinfo->expectedDesc;
114                            rsinfo_ncols = tupdesc->natts;
                 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);  
115    
116                  /* get the result of search */          /*
117                  est_result = est_db_search(db, cond, &resnum, NULL);           * The requested tuple description better match up with the array
118                             * we were given.
119                  /* total number of tuples to be returned */           */
120                  funcctx->max_calls = resnum;          if (rsinfo_ncols != ncols)
121                    ereport(ERROR,
122                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
123                                     errmsg("invalid input array"),
124                                     errdetail("Number of elements in array must match number of query specified columns.")));
125    
126                  /* check if results exists */          /* OK, use it */
127                  if ( 0 == funcctx->max_calls )          attinmeta = TupleDescGetAttInMetadata(tupdesc);
                         elog(INFO, "pgest: no results for: %s", query );  
128    
129                  elog(INFO, "pgest: found %d hits for %s", funcctx->max_calls, query);          /* Now go to work */
130            rsinfo->returnMode = SFRM_Materialize;
131    
132                  /* Build a tuple description for a __pgest tuple */          per_query_ctx = fcinfo->flinfo->fn_mcxt;
133                  tupdesc = RelationNameGetTupleDesc("__pgest");          oldcontext = MemoryContextSwitchTo(per_query_ctx);
134    
135                  /* allocate a slot for a tuple with this tupdesc */          /* initialize our tuplestore */
136                  slot = TupleDescGetSlot(tupdesc);          tupstore = tuplestore_begin_heap(true, false, SortMem);
137    
                 /* assign slot to function context */  
                 funcctx->slot = slot;  
138    
139                  /*          /* take rest of arguments from function */
                  * generate attribute metadata needed later to produce tuples from raw  
                  * C strings  
                  */  
                 attinmeta = TupleDescGetAttInMetadata(tupdesc);  
                 funcctx->attinmeta = attinmeta;  
140    
141                  MemoryContextSwitchTo(oldcontext);          /* index path */
142            if (PG_ARGISNULL(0)) {
143                    ereport(ERROR,
144                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
145                                     errmsg("index path can't be null"),
146                                     errdetail("Index path must be valid full path to HyperEstraier index")));
147            }
148            index_path = _textout(PG_GETARG_TEXT_P(0));
149    
150                  elog(INFO, "SRF_IS_FIRSTCALL done");          /* query string */
151            if (PG_ARGISNULL(1)) {
152                    query = "";
153            } else {
154                    query = _textout(PG_GETARG_TEXT_P(1));
155          }          }
156    
157          /* stuff done on every call of the function */          /* atribute filter */
158          funcctx = SRF_PERCALL_SETUP();          if (PG_ARGISNULL(2)) {
159                    attr = "";
160            } else {
161                    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    
         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;  
171    
172                  elog(INFO, "pgest: loop count %d", call_cntr);          /* limit */
173            if (PG_ARGISNULL(4)) {
174                    limit = 0;
175            } else {
176                    limit = PG_GETARG_INT32(4);
177            }
178    
179            /* offset */
180            if (PG_ARGISNULL(5)) {
181                    offset = 0;
182            } else {
183                    offset = PG_GETARG_INT32(5);
184            }
185    
                 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.  
                  */  
186    
187                  if (doc = est_db_get_doc(db, est_result[call_cntr], 0)) {          /* open the database */
188            elog(DEBUG1, "pgest_attr: est_db_open(%s)", index_path);
189                                    
190                          elog(INFO, "URI: %s\n Title: %s\n",          if(!(db = est_db_open(index_path, ESTDBREADER, &ecode))){
191                    ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
192                            errmsg("est_db_open: can't open %s: %d", index_path, ecode),
193                            errdetail(est_err_msg(ecode))));
194            }
195                    
196            elog(DEBUG1, "pgest_attr: query[%s] attr[%s] limit %d offset %d", query, (PG_ARGISNULL(2) ? "NULL" : attr), limit, offset);
197            
198            /* create a search condition object */
199            if (!(cond = est_cond_new())) {
200                    ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED),
201                            errmsg("pgest_attr: est_cond_new failed")));
202            }
203            
204            /* set the search phrase to the search condition object */
205            if (! PG_ARGISNULL(1) && strlen(query) > 0)
206                    est_cond_set_phrase(cond, query);
207    
208            /* minimum valid attribute length is 10: @a STREQ a */
209            if (! PG_ARGISNULL(2) && strlen(attr) >= 10) {
210                    elog(DEBUG1,"attributes: %s", attr);
211                    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 */
232            est_result = est_db_search(db, cond, &resnum, NULL);
233    
234            /* check if results exists */
235            if ( 0 == resnum ) {
236                    elog(INFO, "pgest_attr: no results for: %s", query );
237            }
238    
239            /* total number of tuples to be returned */
240            if (limit && limit < resnum) {
241                    nrows = limit;
242            } else {
243                    nrows = resnum - offset;
244            }
245    
246    
247            elog(DEBUG1, "pgest_attr: found %d hits for %s", resnum, query);
248    
249            values = (char **) palloc(ncols * sizeof(char *));
250    
251            for (i = 0; i < nrows; i++)
252            {
253    
254                    /* get result from estraier */
255                    if (! ( doc = est_db_get_doc(db, est_result[i + offset], 0)) ) {
256                            elog(INFO, "pgest_attr: can't find result %d", i + offset);
257                    } else {
258                            elog(DEBUG1, "URI: %s\n Title: %s\n",
259                                  est_doc_attr(doc, "@uri"),                                  est_doc_attr(doc, "@uri"),
260                                  est_doc_attr(doc, "@title")                                  est_doc_attr(doc, "@title")
261                          );                          );
262                    }
263    
264                          values = (char **) palloc(4 * sizeof(char *));                  /* iterate over results */
265                    for (j = 0; j < ncols; j++)
266                    {
267                            bool    isnull;
268    
269  //                      values[0] = (char *) palloc(strlen(_estval) * sizeof(char));                          /* array value of this position */
270                            indx[0] = j + attr_dim_lower_bounds[0];
271    
272                          values[0] = attr2text(doc,"@id");                          dvalue = array_ref(attr_arr, attr_ndims, indx, -1, attr_len, attr_byval, attr_align, &isnull);
273                          values[1] = attr2text(doc,"@uri");  
274                          values[2] = attr2text(doc,"@title");                          if (!isnull && doc)
275                          values[3] = attr2text(doc,"@type");                                  values[j] = DatumGetCString(
276                                            attr2text(doc,
277                          /* destloy the document object */                                                  (char *)DirectFunctionCall1(textout, dvalue)
278                          elog(DEBUG2, "est_doc_delete");                                          ));
279                          est_doc_delete(doc);                          else
280                  } else {                                  values[j] = NULL;
                         elog(INFO, "no result from estraier");  
                         values[0] = NULL;  
                         values[1] = NULL;  
                         values[2] = NULL;  
                         values[3] = NULL;  
281                  }                  }
282                    /* construct the tuple */
283                    tuple = BuildTupleFromCStrings(attinmeta, values);
284    
285                    /* now store it */
286                    tuplestore_puttuple(tupstore, tuple);
287    
288                  elog(DEBUG2, "build tuple");                  /* delete estraier document object */
289                  /* build a tuple */                  if (doc) est_doc_delete(doc);
290                  tuple = BuildTupleFromCStrings(attinmeta, values);          }
291    
292                  elog(DEBUG2, "make tuple into datum");          tuplestore_donestoring(tupstore);
293                  /* make the tuple into a datum */          rsinfo->setResult = tupstore;
                 result = TupleGetDatum(slot, tuple);  
294    
295                  elog(DEBUG2, "cleanup");          /*
296                  /* clean up ? */           * SFRM_Materialize mode expects us to return a NULL Datum. The actual
297  /*           * tuples are in our tuplestore and passed back through
298                  pfree(values[0]);           * rsinfo->setResult. rsinfo->setDesc is set to the tuple description
299                  pfree(values[1]);           * that we actually used to build our tuples with, so the caller can
300                  pfree(values[2]);           * verify we did what it was expecting.
301                  pfree(values[3]);           */
302                  pfree(values);          rsinfo->setDesc = tupdesc;
303  */          MemoryContextSwitchTo(oldcontext);
                   
                 elog(DEBUG2, "cleanup over");  
           
                 SRF_RETURN_NEXT(funcctx, result);  
         } else {  
                 elog(INFO, "loop over");  
304    
305                  if(!est_db_close(db, &ecode)){          est_cond_delete(cond);
                         elog(INFO, "est_db_close error: %s", est_err_msg(ecode));  
                 }  
306    
307                  /* do when there is no more left */          if(!est_db_close(db, &ecode)){
308                  SRF_RETURN_DONE(funcctx);                  ereport(ERROR, (errcode(ERRCODE_IO_ERROR),
309                            errmsg("est_db_close: %d", ecode),
310                            errdetail(est_err_msg(ecode))));
311          }          }
312    
313            return (Datum) 0;
314  }  }
315    
316  /* work in progress */  
317  PG_FUNCTION_INFO_V1(pgest2);  /* make text var from attr */
318  Datum pgest2(PG_FUNCTION_ARGS)  char *attr2text(ESTDOC *doc, char *attr) {
319            char *val;
320            const char *attrval;
321            int len;
322            int attrlen;
323    
324            if (! doc) return (Datum) NULL;
325    
326            elog(DEBUG1, "doc: %08x, attr: %s", doc, attr);
327    
328            if ( (attrval = est_doc_attr(doc, attr)) && (attrlen = strlen(attrval)) ) {
329                    val = (char *) palloc(attrlen * sizeof(char));
330            } else {
331                    return (Datum) NULL;
332            }
333    
334            len = strlen(attrval);
335            elog(DEBUG1, "attr2text(%s) = '%s' %d bytes", attr, attrval, len);
336    
337            len++;
338            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    /* select * from pgest( */
359    #define _arg_node_uri 0
360    #define _arg_login 1
361    #define _arg_passwd 2
362    #define _arg_query 3
363    #define _arg_attr 4
364    #define _arg_order 5
365    #define _arg_limit 6
366    #define _arg_offset 7
367    #define _arg_attr_array 8
368    /* as (foo text, ... ); */
369    
370    
371    PG_FUNCTION_INFO_V1(pgest_node);
372    Datum pgest_node(PG_FUNCTION_ARGS)
373  {  {
374          int             nrows = 3;          ArrayType       *attr_arr = PG_GETARG_ARRAYTYPE_P(_arg_attr_array);
375          int16           typlen;          Oid             attr_element_type = ARR_ELEMTYPE(attr_arr);
376          bool            typbyval;          int             attr_ndims = ARR_NDIM(attr_arr);
377          char            typalign;          int             *attr_dim_counts = ARR_DIMS(attr_arr);
378            int             *attr_dim_lower_bounds = ARR_LBOUND(attr_arr);
379            int             ncols = 0;
380            int             nrows = 0;
381            int             indx[MAXDIM];
382            int16           attr_len;
383            bool            attr_byval;
384            char            attr_align;
385          ReturnSetInfo   *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;          ReturnSetInfo   *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
386          AttInMetadata   *attinmeta;          AttInMetadata   *attinmeta;
387          TupleDesc       tupdesc;          TupleDesc       tupdesc;
388          Tuplestorestate *tupstore = NULL;          Tuplestorestate *tupstore = NULL;
389          HeapTuple       tuple;          HeapTuple       tuple;
390          MemoryContext   per_query_ctx;          MemoryContext   per_query_ctx;
391          MemoryContext   oldcontext;          MemoryContext   oldcontext;
392          Datum           dvalue;          Datum           dvalue;
393          char            **values;          char            **values;
394          int             ncols;          int             rsinfo_ncols;
395          int             i, j;          int             i, j;
396            /* estvars */
397            ESTNODE *node;
398            ESTCOND *cond;
399            ESTNODERES *nres;
400            ESTRESDOC *rdoc;
401            const CBLIST *texts;
402            int resnum = 0;
403            int limit = 0;
404            int offset = 0;
405    
406            char            *node_url;
407            char            *user, *passwd;
408            char            *query;
409            char            *attr;
410            char            *order;
411    
412    
413            /* only allow 1D input array */
414            if (attr_ndims == 1)
415            {
416                    ncols = attr_dim_counts[0];
417            }
418            else
419                    ereport(ERROR,
420                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
421                                     errmsg("invalid input array"),
422                                     errdetail("Input array must have 1 dimension")));
423                    
424          /* check to see if caller supports us returning a tuplestore */          /* check to see if caller supports us returning a tuplestore */
425          if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))          if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
426                  ereport(ERROR,                  ereport(ERROR,
# Line 235  Datum pgest2(PG_FUNCTION_ARGS) Line 428  Datum pgest2(PG_FUNCTION_ARGS)
428                                   errmsg("materialize mode required, but it is not " \                                   errmsg("materialize mode required, but it is not " \
429                                                  "allowed in this context")));                                                  "allowed in this context")));
430    
431            /* get info about element type needed to construct the array */
432            get_typlenbyvalalign(attr_element_type, &attr_len, &attr_byval, &attr_align);
433    
434          /* get the requested return tuple description */          /* get the requested return tuple description */
435          tupdesc = rsinfo->expectedDesc;          tupdesc = rsinfo->expectedDesc;
436          ncols = tupdesc->natts;          rsinfo_ncols = tupdesc->natts;
437    
438          /*          /*
439           * The requested tuple description better match up with the array           * The requested tuple description better match up with the array
440           * we were given.           * we were given.
441           */           */
442            if (rsinfo_ncols != ncols)
443                    ereport(ERROR,
444                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
445                                     errmsg("invalid input array"),
446                                     errdetail("Number of elements in array must match number of query specified columns.")));
447    
448          /* OK, use it */          /* OK, use it */
449          attinmeta = TupleDescGetAttInMetadata(tupdesc);          attinmeta = TupleDescGetAttInMetadata(tupdesc);
450    
# Line 255  Datum pgest2(PG_FUNCTION_ARGS) Line 457  Datum pgest2(PG_FUNCTION_ARGS)
457          /* initialize our tuplestore */          /* initialize our tuplestore */
458          tupstore = tuplestore_begin_heap(true, false, SortMem);          tupstore = tuplestore_begin_heap(true, false, SortMem);
459    
460    
461            /* take rest of arguments from function */
462    
463            /* node URL */
464            if (PG_ARGISNULL(_arg_node_uri)) {
465                    ereport(ERROR,
466                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
467                                     errmsg("node URL can't be null"),
468                                     errdetail("Node URL must be valid URL to HyperEstraier node")));
469            }
470            node_url = _textout(PG_GETARG_TEXT_P(_arg_node_uri));
471    
472            /* login and password */
473            if (PG_ARGISNULL(_arg_login) || PG_ARGISNULL(_arg_passwd)) {
474                    ereport(ERROR,
475                                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
476                                     errmsg("username and password can't be NULL"),
477                                     errdetail("You must specify valid username and password to HyperEstraier node")));
478            }
479            user = _textout(PG_GETARG_TEXT_P(_arg_login));
480            passwd = _textout(PG_GETARG_TEXT_P(_arg_passwd));
481    
482            /* query string */
483            if (PG_ARGISNULL(_arg_query)) {
484                    query = "";
485            } else {
486                    query = _textout(PG_GETARG_TEXT_P(_arg_query));
487            }
488    
489            /* atribute filter */
490            if (PG_ARGISNULL(_arg_attr)) {
491                    attr = "";
492            } else {
493                    attr = _textout(PG_GETARG_TEXT_P(_arg_attr));
494            }
495            
496            /* sort order */
497            if (PG_ARGISNULL(_arg_order)) {
498                    order = "";
499            } else {
500                    order = _textout(PG_GETARG_TEXT_P(_arg_order));
501            }
502    
503    
504            /* limit */
505            if (PG_ARGISNULL(_arg_limit)) {
506                    limit = 0;
507            } else {
508                    limit = PG_GETARG_INT32(_arg_limit);
509            }
510    
511            /* offset */
512            if (PG_ARGISNULL(_arg_offset)) {
513                    offset = 0;
514            } else {
515                    offset = PG_GETARG_INT32(_arg_offset);
516            }
517    
518            /* initialize the network environment */
519            if(!est_init_net_env()){
520                    ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED),
521                            errmsg("pgest_node: can't create network enviroment")));
522            }
523    
524            /* create the node connection object */
525            elog(DEBUG1, "pgest_node: est_node_new(%s) as %s", node_url, user);
526            node = est_node_new(node_url);
527            est_node_set_auth(node, user, passwd);
528    
529            elog(DEBUG1, "pgest_node: query[%s] attr[%s] limit %d offset %d", query, (PG_ARGISNULL(_arg_attr) ? "NULL" : attr), limit, offset);
530            
531            /* create a search condition object */
532            if (!(cond = est_cond_new())) {
533                    ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED),
534                            errmsg("pgest_node: est_cond_new failed")));
535            }
536            
537            /* set the search phrase to the search condition object */
538            if (! PG_ARGISNULL(_arg_query) && strlen(query) > 0)
539                    est_cond_set_phrase(cond, query);
540    
541            /* minimum valid attribute length is 10: @a STREQ a */
542            if (! PG_ARGISNULL(_arg_attr) && strlen(attr) >= 10) {
543                    elog(DEBUG1,"attributes: %s", attr);
544                    char *curr_attr;
545                    curr_attr = strtok(attr, ATTR_DELIMITER);
546                    while (curr_attr) {
547                            elog(DEBUG1,"est_cond_add_attr(%s)", curr_attr);
548                            est_cond_add_attr(cond, curr_attr);
549                            curr_attr = strtok(NULL, ATTR_DELIMITER);
550                    }
551            }
552    
553            /* set the search phrase to the search condition object */
554            if (! PG_ARGISNULL(_arg_order) && strlen(order) > 0) {
555                    elog(DEBUG1,"est_cond_set_order(%s)", order);
556                    est_cond_set_order(cond, order);
557            }
558    
559            if (limit) {
560                    elog(DEBUG1,"est_cond_set_max(%d)", limit + offset);
561                    est_cond_set_max(cond, limit + offset);
562            }
563    
564            /* get the result of search */
565            /* FIXME: allow user to specify depath of search */
566            nres = est_node_search(node, cond, 0);
567    
568            if (! nres) {
569                    int status = est_node_status(node);
570                    est_cond_delete(cond);
571                    est_node_delete(node);
572                    est_free_net_env();
573                    ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED),
574                            errmsg("pgest_node: search failed, node status %d", status)));
575            }
576    
577            /* get number of results */
578            resnum = est_noderes_doc_num(nres);
579    
580            /* check if results exists */
581            if ( 0 == resnum ) {
582                    elog(INFO, "pgest_node: no results for: %s", query );
583            }
584    
585            /* total number of tuples to be returned */
586            if (limit && limit < resnum) {
587                    nrows = limit;
588            } else {
589                    nrows = resnum - offset;
590            }
591    
592    
593            elog(DEBUG1, "pgest_node: found %d hits for %s", resnum, query);
594    
595    
596          values = (char **) palloc(ncols * sizeof(char *));          values = (char **) palloc(ncols * sizeof(char *));
597    
598          for (i = 0; i < nrows; i++)          for (i = 0; i < nrows; i++)
599          {          {
600    
601                    /* get result from estraier */
602                    if (! ( rdoc = est_noderes_get_doc(nres, i + offset) )) {
603                            elog(INFO, "pgest_node: can't find result %d", i + offset);
604                    } else {
605                            elog(DEBUG1, "URI: %s\n Title: %s\n",
606                                    est_resdoc_attr(rdoc, "@uri"),
607                                    est_resdoc_attr(rdoc, "@title")
608                            );
609                    }
610    
611                    /* iterate over results */
612                  for (j = 0; j < ncols; j++)                  for (j = 0; j < ncols; j++)
613                  {                  {
614                          values[j] = DatumGetCString( "foo" );                          bool    isnull;
615    
616                            /* array value of this position */
617                            indx[0] = j + attr_dim_lower_bounds[0];
618    
619                            dvalue = array_ref(attr_arr, attr_ndims, indx, -1, attr_len, attr_byval, attr_align, &isnull);
620    
621                            if (!isnull && rdoc)
622                                    values[j] = DatumGetCString(
623                                            node_attr2text(rdoc,
624                                                    (char *)DirectFunctionCall1(textout, dvalue)
625                                            ));
626                            else
627                                    values[j] = NULL;
628                  }                  }
629                  /* construct the tuple */                  /* construct the tuple */
630                  tuple = BuildTupleFromCStrings(attinmeta, values);                  tuple = BuildTupleFromCStrings(attinmeta, values);
631    
632                  /* now store it */                  /* now store it */
633                  tuplestore_puttuple(tupstore, tuple);                  tuplestore_puttuple(tupstore, tuple);
634    
635          }          }
636    
637          tuplestore_donestoring(tupstore);          tuplestore_donestoring(tupstore);
# Line 283  Datum pgest2(PG_FUNCTION_ARGS) Line 647  Datum pgest2(PG_FUNCTION_ARGS)
647          rsinfo->setDesc = tupdesc;          rsinfo->setDesc = tupdesc;
648          MemoryContextSwitchTo(oldcontext);          MemoryContextSwitchTo(oldcontext);
649    
650            /* delete the node result object */
651            est_noderes_delete(nres);
652    
653            /* destroy the search condition object */                          
654            est_cond_delete(cond);
655    
656            /* destroy the node object */
657            est_node_delete(node);
658    
659            /* free the networking environment */
660            est_free_net_env();
661    
662          return (Datum) 0;          return (Datum) 0;
663  }  }
664    
665    /* make text var from node attr */
666  /* make text var from attr */  char *node_attr2text(ESTRESDOC *rdoc, char *attr) {
 char *attr2text(ESTDOC *doc, char *attr) {  
667          char *val;          char *val;
668          const char *attrval;          const char *attrval;
669          int len;          int len;
670            int attrlen;
671    
672            if (! rdoc) return (Datum) NULL;
673    
674          elog(INFO, "doc: %08x, attr: %s", doc, attr);          elog(DEBUG1, "doc: %08x, attr: %s", rdoc, attr);
675    
676          if (attrval = est_doc_attr(doc, attr)) {          if ( (attrval = est_resdoc_attr(rdoc, attr)) && (attrlen = strlen(attrval)) ) {
677                  val = (char *) palloc(strlen(attrval) * sizeof(char));                  val = (char *) palloc(attrlen * sizeof(char));
678          } else {          } else {
679                  return (Datum) NULL;                  return (Datum) NULL;
680          }          }
681    
682          len = strlen(attrval);          len = strlen(attrval);
683          elog(INFO, "attr2text(%s) = '%s' %d bytes", attr, attrval, len);          elog(DEBUG1, "node_attr2text(%s) = '%s' %d bytes", attr, attrval, len);
684    
685          len++;          len++;
686          len *= sizeof(char);          len *= sizeof(char);
# Line 319  char *attr2text(ESTDOC *doc, char *attr) Line 697  char *attr2text(ESTDOC *doc, char *attr)
697          return val;          return val;
698  }  }
699    
 /* 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.48

  ViewVC Help
Powered by ViewVC 1.1.26