2
#include "executor/spi.h" /* this is what you need to work with SPI */
3
#include "commands/trigger.h" /* ... and triggers */
6
Datum cache_bbox(PG_FUNCTION_ARGS);
9
* The intended use for this trigger function is making
10
* a geometry field cache it's bbox. Use like this:
12
* CREATE TRIGGER <name> BEFORE INSERT OR UPDATE
13
* ON <table> FOR EACH ROW EXECUTE PROCEDURE
14
* cache_bbox(<field>);
17
PG_FUNCTION_INFO_V1(cache_bbox);
18
Datum cache_bbox(PG_FUNCTION_ARGS)
20
TriggerData *trigdata = (TriggerData *) fcinfo->context;
28
/* make sure it's called as a trigger at all */
29
if (!CALLED_AS_TRIGGER(fcinfo))
30
elog(ERROR, "cache_bbox: not called by trigger manager");
33
* make sure it's called with at least one argument
34
* (the geometry fields)
36
if ( trigdata->tg_trigger->tgnargs != 1 )
37
elog(ERROR, "trigger 'cache_bbox' must be called with one argument");
39
trigger = trigdata->tg_trigger;
41
/* tuple to return to executor */
42
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
43
rettuple = trigdata->tg_newtuple;
45
rettuple = trigdata->tg_trigtuple;
47
/* Do nothing when fired by delete, after or for statement */
48
if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
50
elog(NOTICE, "Useless cache_box trigger fired by DELETE");
51
return PointerGetDatum(rettuple);
53
if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
55
elog(NOTICE, "Useless cache_box trigger fired AFTER");
56
return PointerGetDatum(rettuple);
58
if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
60
elog(NOTICE, "Useless cache_box trigger fired for STATEMENT");
61
return PointerGetDatum(rettuple);
64
tupdesc = trigdata->tg_relation->rd_att;
66
/* Connect to SPI manager */
67
if ((ret = SPI_connect()) < 0)
68
elog(ERROR, "cache_bbox: SPI_connect returned %d", ret);
70
/* Find number of requested argument */
71
attno = SPI_fnumber(tupdesc, trigger->tgargs[0]);
72
if ( attno == SPI_ERROR_NOATTRIBUTE )
73
elog(ERROR, "trigger %s can't find attribute %s",
74
trigger->tgname, trigger->tgargs[0]);
76
/* Find number of requested argument */
77
if ( strcmp(SPI_gettype(tupdesc, attno), "geometry") )
78
elog(ERROR, "trigger %s requested to apply to a non-geometry field (%s)", trigger->tgname, trigger->tgargs[0]);
80
/* Get input lwgeom */
81
in = SPI_getbinval(rettuple, tupdesc, attno, &isnull);
85
out = PointerGetDatum(DirectFunctionCall1(LWGEOM_addBBOX, in));
87
rettuple = SPI_modifytuple(trigdata->tg_relation, rettuple,
88
1, &attno, &out, NULL);
91
/* Disconnect from SPI */
94
return PointerGetDatum(rettuple);