]> granicus.if.org Git - postgis/commitdiff
Added cache_bbox trigger
authorSandro Santilli <strk@keybit.net>
Thu, 30 Dec 2004 10:24:25 +0000 (10:24 +0000)
committerSandro Santilli <strk@keybit.net>
Thu, 30 Dec 2004 10:24:25 +0000 (10:24 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@1190 b70326c6-7e19-0410-871a-916f4a2858ee

lwgeom/Makefile
lwgeom/lwgeom_triggers.c [new file with mode: 0644]
lwgeom/lwpostgis.sql.in

index 945697439827fe6840c7986e65f093f21d342012..db3c52ecd2186bbce6d7497f20e4635b0995086f 100644 (file)
@@ -75,7 +75,7 @@ ifeq ($(USE_STATS),1)
 endif
  
 SA_OBJS=misures.o box2d.o ptarray.o lwgeom_api.o lwgeom.o lwpoint.o lwline.o lwpoly.o lwmpoint.o lwmline.o lwmpoly.o lwcollection.o $(GEOS_WRAPPER) wktunparse.o lwgparse.o wktparse.tab.o lex.yy.o vsprintf.o
-OBJS=$(SA_OBJS) liblwgeom.o lwgeom_pg.o lwgeom_debug.o lwgeom_spheroid.o lwgeom_ogc.o lwgeom_functions_analytic.o lwgeom_geos.o lwgeom_inout.o lwgeom_estimate.o lwgeom_functions_basic.o lwgeom_gist.o lwgeom_btree.o lwgeom_transform.o stringBuffer.o lwgeom_box.o lwgeom_box3d.o lwgeom_box2dfloat4.o lwgeom_chip.o lwgeom_svg.o lwgeom_gml.o 
+OBJS=$(SA_OBJS) liblwgeom.o lwgeom_pg.o lwgeom_debug.o lwgeom_spheroid.o lwgeom_ogc.o lwgeom_functions_analytic.o lwgeom_geos.o lwgeom_inout.o lwgeom_estimate.o lwgeom_functions_basic.o lwgeom_gist.o lwgeom_btree.o lwgeom_transform.o stringBuffer.o lwgeom_box.o lwgeom_box3d.o lwgeom_box2dfloat4.o lwgeom_chip.o lwgeom_svg.o lwgeom_gml.o lwgeom_triggers.o
 
 OTHERS=y.output lex.yy.c wktparse.tab.c wktparse.tab.h lwpostgis.sql
 
diff --git a/lwgeom/lwgeom_triggers.c b/lwgeom/lwgeom_triggers.c
new file mode 100644 (file)
index 0000000..2a1f0c2
--- /dev/null
@@ -0,0 +1,95 @@
+#include "postgres.h"
+#include "executor/spi.h"       /* this is what you need to work with SPI */
+#include "commands/trigger.h"   /* ... and triggers */
+#include "lwgeom_pg.h"
+
+Datum cache_bbox(PG_FUNCTION_ARGS);
+
+/*
+ * The intended use for this trigger function is making
+ * a geometry field cache it's bbox. Use like this:
+ *
+ * CREATE TRIGGER <name> BEFORE INSERT OR UPDATE
+ *     ON <table> FOR EACH ROW EXECUTE PROCEDURE
+ *     cache_bbox(<field>);
+ *
+ */
+PG_FUNCTION_INFO_V1(cache_bbox);
+Datum cache_bbox(PG_FUNCTION_ARGS)
+{
+       TriggerData *trigdata = (TriggerData *) fcinfo->context;
+       Trigger *trigger;
+       TupleDesc   tupdesc;
+       HeapTuple   rettuple;
+       bool        isnull;
+       Datum in, out;
+       int attno, ret;
+
+       /* make sure it's called as a trigger at all */
+       if (!CALLED_AS_TRIGGER(fcinfo))
+               elog(ERROR, "cache_bbox: not called by trigger manager");
+
+       /*
+        * make sure it's called with at least one argument
+        * (the geometry fields)
+        */
+       if ( trigdata->tg_trigger->tgnargs != 1 )
+               elog(ERROR, "trigger 'cache_bbox' must be called with one argument");
+
+       trigger = trigdata->tg_trigger;
+
+       /* tuple to return to executor */
+       if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
+               rettuple = trigdata->tg_newtuple;
+       else
+               rettuple = trigdata->tg_trigtuple;
+
+       /* Do nothing when fired by delete, after or for statement */
+       if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
+       {
+               elog(NOTICE, "Useless cache_box trigger fired by DELETE");
+               return PointerGetDatum(rettuple);
+       }
+       if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
+       {
+               elog(NOTICE, "Useless cache_box trigger fired AFTER");
+               return PointerGetDatum(rettuple);
+       }
+       if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
+       {
+               elog(NOTICE, "Useless cache_box trigger fired for STATEMENT");
+               return PointerGetDatum(rettuple);
+       }
+
+       tupdesc = trigdata->tg_relation->rd_att;
+
+        /* Connect to SPI manager */
+        if ((ret = SPI_connect()) < 0)
+                elog(ERROR, "cache_bbox: SPI_connect returned %d", ret);
+
+       /* Find number of requested argument */
+       attno = SPI_fnumber(tupdesc, trigger->tgargs[0]);
+       if ( attno == SPI_ERROR_NOATTRIBUTE )
+                elog(ERROR, "trigger %s can't find attribute %s",
+                       trigger->tgname, trigger->tgargs[0]);
+
+       /* Find number of requested argument */
+       if ( strcmp(SPI_gettype(tupdesc, attno), "geometry") )
+                elog(ERROR, "trigger %s requested to apply to a non-geometry field (%s)", trigger->tgname, trigger->tgargs[0]);
+       
+       /* Get input lwgeom */
+       in = SPI_getbinval(rettuple, tupdesc, attno, &isnull);
+
+       if ( ! isnull )
+       {
+               out = PointerGetDatum(DirectFunctionCall1(LWGEOM_addBBOX, in));
+
+               rettuple = SPI_modifytuple(trigdata->tg_relation, rettuple,
+                       1, &attno, &out, NULL);
+       }
+
+       /* Disconnect from SPI */
+       SPI_finish();
+
+       return PointerGetDatum(rettuple);
+}
index adfe5a75c25aae0d6c899aca4678ea5c39fab315..4050f5438f57b2dfba13fc8ec7e937ec84c009c9 100644 (file)
@@ -1733,6 +1733,11 @@ CREATEFUNCTION GeomFromEWKT(text)
        AS '@MODULE_FILENAME@','parse_WKT_lwgeom'
        LANGUAGE 'C' WITH (isstrict,iscachable);
 
+CREATEFUNCTION cache_bbox()
+       RETURNS trigger
+       AS '@MODULE_FILENAME@'
+       LANGUAGE 'C';
+
 ------------------------------------------------------------------------
 -- CONSTRUCTORS
 ------------------------------------------------------------------------