mirror of
https://git.osgeo.org/gitea/postgis/postgis
synced 2024-10-25 17:42:38 +00:00
d7f25db65d
git-svn-id: http://svn.osgeo.org/postgis/trunk@1190 b70326c6-7e19-0410-871a-916f4a2858ee
96 lines
2.7 KiB
C
96 lines
2.7 KiB
C
#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);
|
|
}
|