PostGIS  2.1.10dev-r@@SVN_REVISION@@
lwgeom_accum.c
Go to the documentation of this file.
1 /**********************************************************************
2  * $Id: lwgeom_accum.c 13525 2015-05-19 17:38:43Z pramsey $
3  *
4  * PostGIS - Spatial Types for PostgreSQL
5  * http://postgis.net
6  * Copyright 2009 Paul Ramsey <pramsey@opengeo.org>
7  *
8  * This is free software; you can redistribute and/or modify it under
9  * the terms of the GNU General Public Licence. See the COPYING file.
10  *
11  **********************************************************************/
12 
13 #include "postgres.h"
14 #include "fmgr.h"
15 #include "funcapi.h"
16 #include "access/tupmacs.h"
17 #include "utils/array.h"
18 #include "utils/lsyscache.h"
19 
20 #include "../postgis_config.h"
21 
22 #include "liblwgeom.h"
23 #include "lwgeom_pg.h"
24 
25 /* Local prototypes */
26 Datum PGISDirectFunctionCall1(PGFunction func, Datum arg1);
27 Datum pgis_geometry_accum_transfn(PG_FUNCTION_ARGS);
28 Datum pgis_geometry_accum_finalfn(PG_FUNCTION_ARGS);
29 Datum pgis_geometry_union_finalfn(PG_FUNCTION_ARGS);
30 Datum pgis_geometry_collect_finalfn(PG_FUNCTION_ARGS);
31 Datum pgis_geometry_polygonize_finalfn(PG_FUNCTION_ARGS);
32 Datum pgis_geometry_makeline_finalfn(PG_FUNCTION_ARGS);
33 Datum pgis_abs_in(PG_FUNCTION_ARGS);
34 Datum pgis_abs_out(PG_FUNCTION_ARGS);
35 
36 /* External prototypes */
37 Datum pgis_union_geometry_array(PG_FUNCTION_ARGS);
38 Datum LWGEOM_collect_garray(PG_FUNCTION_ARGS);
39 Datum polygonize_garray(PG_FUNCTION_ARGS);
40 Datum LWGEOM_makeline_garray(PG_FUNCTION_ARGS);
41 
42 
61 typedef struct
62 {
63  ArrayBuildState *a;
64 }
65 pgis_abs;
66 
72 Datum
73 pgis_abs_in(PG_FUNCTION_ARGS)
74 {
75  ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
76  errmsg("function pgis_abs_in not implemented")));
77  PG_RETURN_POINTER(NULL);
78 }
80 Datum
81 pgis_abs_out(PG_FUNCTION_ARGS)
82 {
83  ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
84  errmsg("function pgis_abs_out not implemented")));
85  PG_RETURN_POINTER(NULL);
86 }
87 
94 Datum
95 pgis_geometry_accum_transfn(PG_FUNCTION_ARGS)
96 {
97  Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1);
98  MemoryContext aggcontext;
99  ArrayBuildState *state;
100  pgis_abs *p;
101  Datum elem;
102 
103  if (arg1_typeid == InvalidOid)
104  ereport(ERROR,
105  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
106  errmsg("could not determine input data type")));
107 
108  if ( ! AggCheckCallContext(fcinfo, &aggcontext) )
109  {
110  /* cannot be called directly because of dummy-type argument */
111  elog(ERROR, "%s called in non-aggregate context", __func__);
112  aggcontext = NULL; /* keep compiler quiet */
113  }
114 
115  if ( PG_ARGISNULL(0) )
116  {
117  p = (pgis_abs*) palloc(sizeof(pgis_abs));
118  p->a = NULL;
119  }
120  else
121  {
122  p = (pgis_abs*) PG_GETARG_POINTER(0);
123  }
124  state = p->a;
125  elem = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
126  state = accumArrayResult(state,
127  elem,
128  PG_ARGISNULL(1),
129  arg1_typeid,
130  aggcontext);
131  p->a = state;
132 
133  PG_RETURN_POINTER(p);
134 }
135 
136 Datum pgis_accum_finalfn(pgis_abs *p, MemoryContext mctx, FunctionCallInfo fcinfo);
137 
142 Datum
143 pgis_accum_finalfn(pgis_abs *p, MemoryContext mctx, FunctionCallInfo fcinfo)
144 {
145  int dims[1];
146  int lbs[1];
147  ArrayBuildState *state;
148  Datum result;
149 
150  /* cannot be called directly because of internal-type argument */
151  Assert(fcinfo->context &&
152  (IsA(fcinfo->context, AggState) ||
153  IsA(fcinfo->context, WindowAggState))
154  );
155 
156  state = p->a;
157  dims[0] = state->nelems;
158  lbs[0] = 1;
159  result = makeMdArrayResult(state, 1, dims, lbs, mctx, false);
160  return result;
161 }
162 
167 Datum
169 {
170  pgis_abs *p;
171  Datum result = 0;
172 
173  if (PG_ARGISNULL(0))
174  PG_RETURN_NULL(); /* returns null iff no input values */
175 
176  p = (pgis_abs*) PG_GETARG_POINTER(0);
177 
178  result = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
179 
180  PG_RETURN_DATUM(result);
181 
182 }
183 
189 Datum
191 {
192  pgis_abs *p;
193  Datum result = 0;
194  Datum geometry_array = 0;
195 
196  if (PG_ARGISNULL(0))
197  PG_RETURN_NULL(); /* returns null iff no input values */
198 
199  p = (pgis_abs*) PG_GETARG_POINTER(0);
200 
201  geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
202  result = PGISDirectFunctionCall1( pgis_union_geometry_array, geometry_array );
203  if (!result)
204  PG_RETURN_NULL();
205 
206  PG_RETURN_DATUM(result);
207 }
208 
214 Datum
216 {
217  pgis_abs *p;
218  Datum result = 0;
219  Datum geometry_array = 0;
220 
221  if (PG_ARGISNULL(0))
222  PG_RETURN_NULL(); /* returns null iff no input values */
223 
224  p = (pgis_abs*) PG_GETARG_POINTER(0);
225 
226  geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
227  result = PGISDirectFunctionCall1( LWGEOM_collect_garray, geometry_array );
228  if (!result)
229  PG_RETURN_NULL();
230 
231  PG_RETURN_DATUM(result);
232 }
233 
239 Datum
241 {
242  pgis_abs *p;
243  Datum result = 0;
244  Datum geometry_array = 0;
245 
246  if (PG_ARGISNULL(0))
247  PG_RETURN_NULL(); /* returns null iff no input values */
248 
249  p = (pgis_abs*) PG_GETARG_POINTER(0);
250 
251  geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
252  result = DirectFunctionCall1( polygonize_garray, geometry_array );
253 
254  PG_RETURN_DATUM(result);
255 }
256 
262 Datum
264 {
265  pgis_abs *p;
266  Datum result = 0;
267  Datum geometry_array = 0;
268 
269  if (PG_ARGISNULL(0))
270  PG_RETURN_NULL(); /* returns null iff no input values */
271 
272  p = (pgis_abs*) PG_GETARG_POINTER(0);
273 
274  geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
275  result = PGISDirectFunctionCall1( LWGEOM_makeline_garray, geometry_array );
276  if (!result)
277  PG_RETURN_NULL();
278 
279  PG_RETURN_DATUM(result);
280 }
281 
286 Datum
287 PGISDirectFunctionCall1(PGFunction func, Datum arg1)
288 {
289  FunctionCallInfoData fcinfo;
290  Datum result;
291 
292 #if POSTGIS_PGSQL_VERSION > 90
293 
294  InitFunctionCallInfoData(fcinfo, NULL, 1, InvalidOid, NULL, NULL);
295 #else
296 
297  InitFunctionCallInfoData(fcinfo, NULL, 1, NULL, NULL);
298 #endif
299 
300  fcinfo.arg[0] = arg1;
301  fcinfo.argnull[0] = false;
302 
303  result = (*func) (&fcinfo);
304 
305  /* Check for null result, returning a "NULL" Datum if indicated */
306  if (fcinfo.isnull)
307  return (Datum) 0;
308 
309  return result;
310 }
Datum pgis_accum_finalfn(pgis_abs *p, MemoryContext mctx, FunctionCallInfo fcinfo)
The final function rescues the built array from the side memory context using the PostgreSQL built-in...
Definition: lwgeom_accum.c:143
Datum pgis_union_geometry_array(PG_FUNCTION_ARGS)
Datum pgis_geometry_accum_transfn(PG_FUNCTION_ARGS)
Definition: lwgeom_accum.c:95
Datum pgis_geometry_polygonize_finalfn(PG_FUNCTION_ARGS)
Definition: lwgeom_accum.c:240
Datum pgis_abs_in(PG_FUNCTION_ARGS)
Definition: lwgeom_accum.c:73
ArrayBuildState * a
Definition: lwgeom_accum.c:63
Datum pgis_geometry_union_finalfn(PG_FUNCTION_ARGS)
Definition: lwgeom_accum.c:190
Datum LWGEOM_collect_garray(PG_FUNCTION_ARGS)
Datum pgis_geometry_collect_finalfn(PG_FUNCTION_ARGS)
Definition: lwgeom_accum.c:215
Datum LWGEOM_makeline_garray(PG_FUNCTION_ARGS)
Datum pgis_geometry_makeline_finalfn(PG_FUNCTION_ARGS)
Definition: lwgeom_accum.c:263
char ** result
Definition: liblwgeom.h:218
Datum pgis_abs_out(PG_FUNCTION_ARGS)
Definition: lwgeom_accum.c:81
Datum PGISDirectFunctionCall1(PGFunction func, Datum arg1)
A modified version of PostgreSQL's DirectFunctionCall1 which allows NULL results; this is required fo...
Definition: lwgeom_accum.c:287
Datum pgis_geometry_accum_finalfn(PG_FUNCTION_ARGS)
Definition: lwgeom_accum.c:168
PG_FUNCTION_INFO_V1(pgis_abs_in)
We're never going to use this type externally so the in/out functions are dummies.
To pass the internal ArrayBuildState pointer between the transfn and finalfn we need to wrap it into ...
Definition: lwgeom_accum.c:61
This library is the generic geometry handling section of PostGIS.
Datum polygonize_garray(PG_FUNCTION_ARGS)