From d7f25db65d5f2ebbcf8e777606e2676afdc22c24 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Thu, 30 Dec 2004 10:24:25 +0000 Subject: [PATCH] Added cache_bbox trigger git-svn-id: http://svn.osgeo.org/postgis/trunk@1190 b70326c6-7e19-0410-871a-916f4a2858ee --- lwgeom/Makefile | 2 +- lwgeom/lwgeom_triggers.c | 95 ++++++++++++++++++++++++++++++++++++++++ lwgeom/lwpostgis.sql.in | 5 +++ 3 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 lwgeom/lwgeom_triggers.c diff --git a/lwgeom/Makefile b/lwgeom/Makefile index 945697439..db3c52ecd 100644 --- a/lwgeom/Makefile +++ b/lwgeom/Makefile @@ -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 index 000000000..2a1f0c24e --- /dev/null +++ b/lwgeom/lwgeom_triggers.c @@ -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 BEFORE INSERT OR UPDATE + * ON FOR EACH ROW EXECUTE PROCEDURE + * cache_bbox(); + * + */ +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); +} diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index adfe5a75c..4050f5438 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -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 ------------------------------------------------------------------------ -- 2.40.0