PostGIS  2.4.9dev-r@@SVN_REVISION@@
lwgeom_triggers.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * PostGIS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * PostGIS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18  *
19  **********************************************************************
20  *
21  * Copyright (C) 2004 Refractions Research Inc.
22  *
23  **********************************************************************/
24 
25 
26 #include "postgres.h"
27 #include "executor/spi.h" /* this is what you need to work with SPI */
28 #include "commands/trigger.h" /* ... and triggers */
29 
30 #include "../postgis_config.h"
31 #include "lwgeom_pg.h"
32 #include "utils/rel.h"
33 
34 Datum cache_bbox(PG_FUNCTION_ARGS);
35 
46 Datum cache_bbox(PG_FUNCTION_ARGS)
47 {
48  TriggerData *trigdata = (TriggerData *) fcinfo->context;
49  Trigger *trigger;
50  TupleDesc tupdesc;
51  HeapTuple rettuple;
52  bool isnull;
53  Datum in, out;
54  int attno, ret;
55 
56  /* make sure it's called as a trigger at all */
57  if (!CALLED_AS_TRIGGER(fcinfo))
58  elog(ERROR, "cache_bbox: not called by trigger manager");
59 
60  /*
61  * make sure it's called with at least one argument
62  * (the geometry fields)
63  */
64  if ( trigdata->tg_trigger->tgnargs != 1 )
65  elog(ERROR, "trigger 'cache_bbox' must be called with one argument");
66 
67  trigger = trigdata->tg_trigger;
68 
69  /* tuple to return to executor */
70  if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
71  rettuple = trigdata->tg_newtuple;
72  else
73  rettuple = trigdata->tg_trigtuple;
74 
75  /* Do nothing when fired by delete, after or for statement */
76  if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
77  {
78  elog(NOTICE, "Useless cache_box trigger fired by DELETE");
79  return PointerGetDatum(rettuple);
80  }
81  if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
82  {
83  elog(NOTICE, "Useless cache_box trigger fired AFTER");
84  return PointerGetDatum(rettuple);
85  }
86  if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
87  {
88  elog(NOTICE, "Useless cache_box trigger fired for STATEMENT");
89  return PointerGetDatum(rettuple);
90  }
91 
92  tupdesc = trigdata->tg_relation->rd_att;
93 
94  /* Connect to SPI manager */
95  if ((ret = SPI_connect()) < 0)
96  elog(ERROR, "cache_bbox: SPI_connect returned %d", ret);
97 
98  /* Find number of requested argument */
99  attno = SPI_fnumber(tupdesc, trigger->tgargs[0]);
100  if ( attno == SPI_ERROR_NOATTRIBUTE )
101  elog(ERROR, "trigger %s can't find attribute %s",
102  trigger->tgname, trigger->tgargs[0]);
103 
104  /* Find number of requested argument */
105  if ( strcmp(SPI_gettype(tupdesc, attno), "geometry") )
106  elog(ERROR, "trigger %s requested to apply to a non-geometry field (%s)", trigger->tgname, trigger->tgargs[0]);
107 
108  /* Get input lwgeom */
109  in = SPI_getbinval(rettuple, tupdesc, attno, &isnull);
110 
111  if ( ! isnull )
112  {
113  out = PointerGetDatum(DirectFunctionCall1(LWGEOM_addBBOX, in));
114 
115  rettuple = SPI_modifytuple(trigdata->tg_relation, rettuple,
116  1, &attno, &out, NULL);
117  }
118 
119  /* Disconnect from SPI */
120  SPI_finish();
121 
122  return PointerGetDatum(rettuple);
123 }
PG_FUNCTION_INFO_V1(cache_bbox)
Datum LWGEOM_addBBOX(PG_FUNCTION_ARGS)
Definition: lwgeom_inout.c:686
Datum cache_bbox(PG_FUNCTION_ARGS)
if(!(yy_init))