--- trunk/pgest.c 2006/05/11 16:19:38 57 +++ trunk/pgest.c 2006/08/08 12:15:55 80 @@ -27,6 +27,9 @@ #include "utils/array.h" #include "utils/lsyscache.h" #include "miscadmin.h" +#include "commands/trigger.h" +#include "executor/spi.h" + #include #include #include @@ -589,7 +592,7 @@ if (limit && limit < resnum) { nrows = limit; } else { - nrows = resnum - offset; + nrows = resnum; } /* get hints */ @@ -631,7 +634,7 @@ /* skip HINTS. prefix */ hint += strlen(HINTS_PREFIX); - hint_val = cbmapget(hints, hint, -1, NULL); + hint_val = (char *)cbmapget(hints, hint, -1, NULL); elog(DEBUG2, "hint %s = %s", hint, hint_val); if (hint_val != NULL) { @@ -721,7 +724,7 @@ char *next; char *curr_attr; while ( strlen(attr) > 0 ) { - printf("len [%s] = %d\n", attr, strlen(attr)); + printf("len [%s] = %zd\n", attr, strlen(attr)); if ((next = strstr(attr, ATTR_DELIMITER)) != NULL) { curr_attr = palloc( next - attr + 1 ); memcpy(curr_attr, attr, next-attr); @@ -736,3 +739,140 @@ attr = next; } } + +/* trigger to keep data in Hyper Estraier index up-to-date */ +/* CREATE FUNCTION pgest_trigger() RETURNS TRIGGER AS ... */ + +/* + * UPDATE, INSERT and DELETE triggers are like this: + +CREATE TRIGGER pgest_trigger_update AFTER UPDATE + ON table_name FOR EACH ROW + EXECUTE PROCEDURE pgest_trigger('http://localhost:1978/node/trivia','admin','admin', + 'name_of_pk', 'column', 'another_column', 'and_so_on' + ) + +*/ + +PG_FUNCTION_INFO_V1(pgest_trigger); +Datum pgest_trigger(PG_FUNCTION_ARGS) { + + TriggerData *data; + TupleDesc tupdesc; + HeapTuple ret; + + char **args; + char *keycol = NULL; + char *key = NULL; + char *col_data = NULL; + int knumber; + int i; + int create_doc = 0; + int edit_doc = 0; + + ESTNODE *node; + ESTDOC *doc; + + + + if (! CALLED_AS_TRIGGER(fcinfo)) { + elog(ERROR, "pgest_trigger() must be called as a trigger"); + } + + data = (TriggerData *) fcinfo->context; + + if (data->tg_trigger->tgnargs < 5) + elog(ERROR, "pgest_trigger() requires at least 5 parameters ('http://localhost:1978/node/trivia', 'user', 'passwd', 'pk_column', 'column', ... )"); + + args = data->tg_trigger->tgargs; + keycol = args[3]; + + tupdesc = data->tg_relation->rd_att; + + knumber = SPI_fnumber(tupdesc, keycol); + key = SPI_getvalue(data->tg_trigtuple, tupdesc, knumber); + + + /* initialize the network environment */ + if( ! est_init_net_env() ) + elog(ERROR, "pgest_trigger: network is unavailable\n"); + + /* create and configure the node connection object */ + node = est_node_new( args[0] ); + est_node_set_auth(node, args[1], args[2]); + + + if (TRIGGER_FIRED_BY_INSERT(data->tg_event)) { + /* There is no old data */ + ret = data->tg_trigtuple; + + create_doc++; + + } else if (TRIGGER_FIRED_BY_UPDATE(data->tg_event)) { + ret = data->tg_newtuple; + + edit_doc++; + + } else if (TRIGGER_FIRED_BY_DELETE(data->tg_event)) { + /* There is no new data */ + ret = data->tg_trigtuple; + + if (! est_node_out_doc_by_uri(node, key) ) + elog(ERROR, "est_node_doc_by_uri(%s): %d\n", key, est_node_status(node)); + + } else { + elog(ERROR, "pgest_trigger() not called from INSERT/UPDATE/DELETE"); + } + + if ( create_doc || edit_doc ) { + + if ( create_doc ) { + /* create a document object */ + doc = est_doc_new(); + est_doc_add_attr(doc, "@uri", key); + + elog(DEBUG1, "est_doc_new @uri=%s", key); + } else { + /* edit existing document */ + doc = est_node_get_doc_by_uri(node, key); + if (doc == NULL) + elog(ERROR, "est_node_get_doc_by_uri(%s): %d\n", key, est_node_status(node)); + elog(DEBUG1, "est_node_get_doc_by_uri(%s)", key); + } + + for( i = 4; i < data->tg_trigger->tgnargs; i++ ) { + + col_data = SPI_getvalue(ret, tupdesc, SPI_fnumber(tupdesc, args[i])); + + if (data) { + elog(DEBUG1, " + %s = %s", args[i], col_data); + est_doc_add_attr(doc, args[i], col_data); + est_doc_add_text(doc, col_data); + } + + } + + if ( edit_doc ) { + /* update existing document */ + if( ! est_node_edit_doc(node, doc) ) + elog(ERROR, "est_node_edit_doc: %d\n", est_node_status(node)); + } else { + /* register the document object to the node */ + if( ! est_node_put_doc(node, doc) ) + elog(ERROR, "est_node_put_doc: %d\n", est_node_status(node)); + } + + /* destroy the document object */ + est_doc_delete(doc); + + } + + /* destroy the node object */ + est_node_delete(node); + /* free the networking environment */ + est_free_net_env(); + + + return PointerGetDatum(ret); +} +