/[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 51 by dpavlin, Tue May 9 22:55:42 2006 UTC revision 80 by dpavlin, Tue Aug 8 12:15:55 2006 UTC
# Line 25  Line 25 
25  #include "funcapi.h"  #include "funcapi.h"
26  #include "utils/builtins.h"  #include "utils/builtins.h"
27  #include "utils/array.h"  #include "utils/array.h"
28    #include "utils/lsyscache.h"
29  #include "miscadmin.h"  #include "miscadmin.h"
30    #include "commands/trigger.h"
31    #include "executor/spi.h"
32    
33  #include <estraier.h>  #include <estraier.h>
34  #include <cabin.h>  #include <cabin.h>
35  #include <estnode.h>  #include <estnode.h>
# Line 41  Line 45 
45  #endif  #endif
46    
47  #define ATTR_DELIMITER "{{!}}"  #define ATTR_DELIMITER "{{!}}"
48    #define HINTS_PREFIX "HINTS."
49    
50  /* prototype */  /* prototype */
51  char *attr2text(ESTDOC *doc, char *attr);  char *attr2text(ESTDOC *doc, char *attr);
52  char *node_attr2text(ESTRESDOC *rdoc, char *attr);  char *node_attr2text(ESTRESDOC *rdoc, char *attr);
53    void cond_add_attr(ESTCOND *cond, char *attr);
54    
55    
56  /* work in progress */  /* work in progress */
# Line 77  Datum pgest_attr(PG_FUNCTION_ARGS) Line 83  Datum pgest_attr(PG_FUNCTION_ARGS)
83          ESTDB *db;          ESTDB *db;
84          ESTCOND *cond;          ESTCOND *cond;
85          ESTDOC *doc;          ESTDOC *doc;
         const CBLIST *texts;  
86          int ecode, *est_result, resnum;          int ecode, *est_result, resnum;
87          int limit = 0;          int limit = 0;
88          int offset = 0;          int offset = 0;
# Line 208  Datum pgest_attr(PG_FUNCTION_ARGS) Line 213  Datum pgest_attr(PG_FUNCTION_ARGS)
213          /* minimum valid attribute length is 10: @a STREQ a */          /* minimum valid attribute length is 10: @a STREQ a */
214          if (! PG_ARGISNULL(2) && strlen(attr) >= 10) {          if (! PG_ARGISNULL(2) && strlen(attr) >= 10) {
215                  elog(DEBUG1,"attributes: %s", attr);                  elog(DEBUG1,"attributes: %s", attr);
216                  char *curr_attr;                  cond_add_attr(cond, attr);
                 curr_attr = strtok(attr, ATTR_DELIMITER);  
                 while (curr_attr) {  
                         elog(DEBUG1,"est_cond_add_attr(%s)", curr_attr);  
                         est_cond_add_attr(cond, curr_attr);  
                         curr_attr = strtok(NULL, ATTR_DELIMITER);  
                 }  
217          }          }
218    
219          /* set the search phrase to the search condition object */          /* set the search phrase to the search condition object */
# Line 323  char *attr2text(ESTDOC *doc, char *attr) Line 322  char *attr2text(ESTDOC *doc, char *attr)
322    
323          if (! doc) return (Datum) NULL;          if (! doc) return (Datum) NULL;
324    
325          elog(DEBUG1, "doc: %08x, attr: %s", doc, attr);          elog(DEBUG1, "doc: %p, attr: %s", doc, attr);
326    
327          if ( (attrval = est_doc_attr(doc, attr)) && (attrlen = strlen(attrval)) ) {          if ( (attrval = est_doc_attr(doc, attr)) && (attrlen = strlen(attrval)) ) {
328                  val = (char *) palloc(attrlen * sizeof(char));                  val = (char *) palloc(attrlen * sizeof(char));
# Line 399  Datum pgest_node(PG_FUNCTION_ARGS) Line 398  Datum pgest_node(PG_FUNCTION_ARGS)
398          ESTCOND *cond;          ESTCOND *cond;
399          ESTNODERES *nres;          ESTNODERES *nres;
400          ESTRESDOC *rdoc;          ESTRESDOC *rdoc;
401          const CBLIST *texts;          CBMAP *hints;
402          int resnum = 0;          int resnum = 0;
403          int limit = 0;          int limit = 0;
404          int offset = 0;          int offset = 0;
# Line 550  Datum pgest_node(PG_FUNCTION_ARGS) Line 549  Datum pgest_node(PG_FUNCTION_ARGS)
549          /* minimum valid attribute length is 10: @a STREQ a */          /* minimum valid attribute length is 10: @a STREQ a */
550          if (! PG_ARGISNULL(_arg_attr) && strlen(attr) >= 10) {          if (! PG_ARGISNULL(_arg_attr) && strlen(attr) >= 10) {
551                  elog(DEBUG1,"attributes: %s", attr);                  elog(DEBUG1,"attributes: %s", attr);
552                  char *curr_attr;                  cond_add_attr(cond, attr);
                 curr_attr = strtok(attr, ATTR_DELIMITER);  
                 while (curr_attr) {  
                         elog(DEBUG1,"est_cond_add_attr(%s)", curr_attr);  
                         est_cond_add_attr(cond, curr_attr);  
                         curr_attr = strtok(NULL, ATTR_DELIMITER);  
                 }  
553          }          }
554    
555          /* set the search phrase to the search condition object */          /* set the search phrase to the search condition object */
# Line 599  Datum pgest_node(PG_FUNCTION_ARGS) Line 592  Datum pgest_node(PG_FUNCTION_ARGS)
592          if (limit && limit < resnum) {          if (limit && limit < resnum) {
593                  nrows = limit;                  nrows = limit;
594          } else {          } else {
595                  nrows = resnum - offset;                  nrows = resnum;
596          }          }
597    
598            /* get hints */
599            hints = est_noderes_hints(nres);
600    
601          elog(DEBUG1, "pgest_node: found %d hits for %s", resnum, query);          elog(DEBUG1, "pgest_node: found %d hits for %s", resnum, query);
602    
603    
# Line 624  Datum pgest_node(PG_FUNCTION_ARGS) Line 620  Datum pgest_node(PG_FUNCTION_ARGS)
620                  for (j = 0; j < ncols; j++)                  for (j = 0; j < ncols; j++)
621                  {                  {
622                          bool    isnull;                          bool    isnull;
623                            char    *attr;  /* current attribute name */
624                            char    *hint;  /* position of current hint in attribute */
625                            char    *hint_val;
626    
627                          /* array value of this position */                          /* array value of this position */
628                          indx[0] = j + attr_dim_lower_bounds[0];                          indx[0] = j + attr_dim_lower_bounds[0];
629    
630                          dvalue = array_ref(attr_arr, attr_ndims, indx, -1, attr_len, attr_byval, attr_align, &isnull);                          dvalue = array_ref(attr_arr, attr_ndims, indx, -1, attr_len, attr_byval, attr_align, &isnull);
631                            attr = (char *)DirectFunctionCall1(textout, dvalue);
632    
633                          if (!isnull && rdoc)                          if (!isnull && (hint = strstr(attr, HINTS_PREFIX)) != NULL) {
634                                  values[j] = DatumGetCString(                                  /* skip HINTS. prefix */
635                                          node_attr2text(rdoc,                                  hint += strlen(HINTS_PREFIX);
636                                                  (char *)DirectFunctionCall1(textout, dvalue)  
637                                          ));                                  hint_val = (char *)cbmapget(hints, hint, -1, NULL);
638                                    elog(DEBUG2, "hint %s = %s", hint, hint_val);
639    
640                                    if (hint_val != NULL) {
641                                            values[j] = DatumGetCString( hint_val );
642                                    } else {
643                                            elog(INFO, "can't get hint in results: %s", hint);
644                                            values[j] = NULL;
645                                    }
646                            } else if (!isnull && rdoc)
647                                    values[j] = DatumGetCString( node_attr2text(rdoc, attr) );
648                          else                          else
649                                  values[j] = NULL;                                  values[j] = NULL;
650                  }                  }
# Line 683  char *node_attr2text(ESTRESDOC *rdoc, ch Line 693  char *node_attr2text(ESTRESDOC *rdoc, ch
693    
694          if (! rdoc) return (Datum) NULL;          if (! rdoc) return (Datum) NULL;
695    
696          elog(DEBUG1, "doc: %08x, attr: %s", rdoc, attr);          elog(DEBUG1, "doc: %p, attr: %s", rdoc, attr);
697    
698          if ( (attrval = est_resdoc_attr(rdoc, attr)) && (attrlen = strlen(attrval)) ) {          if ( (attrval = est_resdoc_attr(rdoc, attr)) && (attrlen = strlen(attrval)) ) {
699                  val = (char *) palloc(attrlen * sizeof(char));                  val = (char *) palloc(attrlen * sizeof(char));
# Line 709  char *node_attr2text(ESTRESDOC *rdoc, ch Line 719  char *node_attr2text(ESTRESDOC *rdoc, ch
719          return val;          return val;
720  }  }
721    
722    /* parse attributes and add them to confition */
723    void cond_add_attr(ESTCOND *cond, char *attr) {
724            char *next;
725            char *curr_attr;
726            while ( strlen(attr) > 0 ) {
727                    printf("len [%s] = %zd\n", attr, strlen(attr));
728                    if ((next = strstr(attr, ATTR_DELIMITER)) != NULL) {
729                            curr_attr = palloc( next - attr + 1 );
730                            memcpy(curr_attr, attr, next-attr);
731                            curr_attr[next-attr] = '\0';
732                            next += strlen(ATTR_DELIMITER);
733                    } else {
734                            next = "";
735                            curr_attr = attr;
736                    }
737                    elog(DEBUG1, "est_cond_add_attr(%s)", curr_attr);
738                    est_cond_add_attr(cond, curr_attr);
739                    attr = next;
740            }
741    }
742    
743    /* trigger to keep data in Hyper Estraier index up-to-date */
744    /* CREATE FUNCTION pgest_trigger() RETURNS TRIGGER AS ... */
745    
746    /*
747     * UPDATE, INSERT and DELETE triggers are like this:
748    
749    CREATE TRIGGER pgest_trigger_update AFTER UPDATE
750            ON table_name FOR EACH ROW
751            EXECUTE PROCEDURE pgest_trigger('http://localhost:1978/node/trivia','admin','admin',
752                    'name_of_pk', 'column', 'another_column', 'and_so_on'
753            )
754    
755    */
756    
757    PG_FUNCTION_INFO_V1(pgest_trigger);
758    Datum pgest_trigger(PG_FUNCTION_ARGS) {
759    
760            TriggerData *data;
761            TupleDesc   tupdesc;
762            HeapTuple   ret;
763    
764            char **args;
765            char *keycol  = NULL;
766            char *key     = NULL;
767            char *col_data = NULL;
768            int   knumber;
769            int   i;
770            int   create_doc = 0;
771            int   edit_doc = 0;
772    
773            ESTNODE *node;
774            ESTDOC *doc;
775    
776    
777    
778            if (! CALLED_AS_TRIGGER(fcinfo)) {
779                    elog(ERROR, "pgest_trigger() must be called as a trigger");
780            }
781    
782            data = (TriggerData *) fcinfo->context;
783    
784            if (data->tg_trigger->tgnargs < 5)
785                    elog(ERROR, "pgest_trigger() requires at least 5 parameters ('http://localhost:1978/node/trivia', 'user', 'passwd', 'pk_column', 'column', ... )");
786    
787            args       = data->tg_trigger->tgargs;
788            keycol     = args[3];
789    
790            tupdesc = data->tg_relation->rd_att;
791    
792            knumber = SPI_fnumber(tupdesc, keycol);
793            key = SPI_getvalue(data->tg_trigtuple, tupdesc, knumber);
794    
795    
796            /* initialize the network environment */
797            if( ! est_init_net_env() )
798                    elog(ERROR, "pgest_trigger: network is unavailable\n");
799    
800            /* create and configure the node connection object */
801            node = est_node_new( args[0] );
802            est_node_set_auth(node, args[1], args[2]);
803    
804    
805            if (TRIGGER_FIRED_BY_INSERT(data->tg_event)) {
806                    /* There is no old data */
807                    ret = data->tg_trigtuple;
808    
809                    create_doc++;
810    
811            } else if (TRIGGER_FIRED_BY_UPDATE(data->tg_event)) {
812                    ret = data->tg_newtuple;
813    
814                    edit_doc++;
815    
816            } else if (TRIGGER_FIRED_BY_DELETE(data->tg_event)) {
817                    /* There is no new data */
818                    ret = data->tg_trigtuple;
819    
820                    if (! est_node_out_doc_by_uri(node, key) )
821                            elog(ERROR, "est_node_doc_by_uri(%s): %d\n", key, est_node_status(node));
822    
823            } else {
824                    elog(ERROR, "pgest_trigger() not called from INSERT/UPDATE/DELETE");
825            }
826    
827            if ( create_doc || edit_doc ) {
828    
829                    if ( create_doc ) {
830                            /* create a document object */
831                            doc = est_doc_new();
832                            est_doc_add_attr(doc, "@uri", key);
833    
834                            elog(DEBUG1, "est_doc_new @uri=%s", key);
835                    } else {
836                            /* edit existing document */
837                            doc = est_node_get_doc_by_uri(node, key);
838                            if (doc == NULL)
839                                    elog(ERROR, "est_node_get_doc_by_uri(%s): %d\n", key, est_node_status(node));
840                            elog(DEBUG1, "est_node_get_doc_by_uri(%s)", key);
841                    }
842    
843                    for( i = 4; i < data->tg_trigger->tgnargs; i++ ) {
844    
845                            col_data = SPI_getvalue(ret, tupdesc, SPI_fnumber(tupdesc, args[i]));
846    
847                            if (data) {
848                                    elog(DEBUG1, " + %s = %s", args[i], col_data);
849                                    est_doc_add_attr(doc, args[i], col_data);
850                                    est_doc_add_text(doc, col_data);
851                            }
852    
853                    }
854    
855                    if ( edit_doc ) {
856                            /* update existing document */
857                            if( ! est_node_edit_doc(node, doc) )
858                                    elog(ERROR, "est_node_edit_doc: %d\n", est_node_status(node));
859                    } else {
860                            /* register the document object to the node */
861                            if( ! est_node_put_doc(node, doc) )
862                                    elog(ERROR, "est_node_put_doc: %d\n", est_node_status(node));
863                    }
864    
865                    /* destroy the document object */
866                    est_doc_delete(doc);
867    
868            }
869    
870            /* destroy the node object */
871            est_node_delete(node);
872            /* free the networking environment */
873            est_free_net_env();
874    
875    
876            return PointerGetDatum(ret);
877    }
878    

Legend:
Removed from v.51  
changed lines
  Added in v.80

  ViewVC Help
Powered by ViewVC 1.1.26