PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwgeom_export.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 2009-2011 Olivier Courtin <olivier.courtin@oslandia.com>
22 *
23 **********************************************************************/
24
25
26
31#include "float.h" /* for DBL_DIG */
32
33#include "postgres.h"
34#include "catalog/pg_type.h" /* for CSTRINGOID */
35#include "executor/spi.h"
36#include "utils/builtins.h"
37
38#if POSTGIS_PGSQL_VERSION > 95
39#include "utils/fmgrprotos.h"
40#else
41#include "utils/jsonb.h"
42#endif
43
44#include "../postgis_config.h"
45#include "lwgeom_pg.h"
46#include "liblwgeom.h"
47#include "lwgeom_export.h"
48
49Datum LWGEOM_asGML(PG_FUNCTION_ARGS);
50Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS);
51Datum LWGEOM_asGeoJson_old(PG_FUNCTION_ARGS);
52Datum LWGEOM_asSVG(PG_FUNCTION_ARGS);
53Datum LWGEOM_asX3D(PG_FUNCTION_ARGS);
54Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS);
55Datum geometry_to_json(PG_FUNCTION_ARGS);
56Datum geometry_to_jsonb(PG_FUNCTION_ARGS);
57
58/*
59 * Retrieve an SRS from a given SRID
60 * Require valid spatial_ref_sys table entry
61 *
62 * Could return SRS as short one (i.e EPSG:4326)
63 * or as long one: (i.e urn:ogc:def:crs:EPSG::4326)
64 */
65char *
66getSRSbySRID(FunctionCallInfo fcinfo, int32_t srid, bool short_crs)
67{
68 static const uint16_t max_query_size = 512;
69 char query[512];
70 char *srs, *srscopy;
71 int size, err;
72 postgis_initialize_cache(fcinfo);
73
74 if (SPI_OK_CONNECT != SPI_connect ())
75 {
76 elog(NOTICE, "getSRSbySRID: could not connect to SPI manager");
77 SPI_finish();
78 return NULL;
79 }
80
81 if (short_crs)
82 snprintf(query,
83 max_query_size,
84 "SELECT auth_name||':'||auth_srid \
85 FROM %s WHERE srid='%d'",
86 postgis_spatial_ref_sys(),
87 srid);
88 else
89 snprintf(query,
90 max_query_size,
91 "SELECT 'urn:ogc:def:crs:'||auth_name||'::'||auth_srid \
92 FROM %s WHERE srid='%d'",
93 postgis_spatial_ref_sys(),
94 srid);
95
96 err = SPI_exec(query, 1);
97 if ( err < 0 )
98 {
99 elog(NOTICE, "getSRSbySRID: error executing query %d", err);
100 SPI_finish();
101 return NULL;
102 }
103
104 /* no entry in spatial_ref_sys */
105 if (SPI_processed <= 0)
106 {
107 SPI_finish();
108 return NULL;
109 }
110
111 /* get result */
112 srs = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
113
114 /* NULL result */
115 if ( ! srs )
116 {
117 SPI_finish();
118 return NULL;
119 }
120
121 /* copy result to upper executor context */
122 size = strlen(srs)+1;
123 srscopy = SPI_palloc(size);
124 memcpy(srscopy, srs, size);
125
126 /* disconnect from SPI */
127 SPI_finish();
128
129 return srscopy;
130}
131
132
133/*
134* Retrieve an SRID from a given SRS
135* Require valid spatial_ref_sys table entry
136*
137*/
138int
139getSRIDbySRS(FunctionCallInfo fcinfo, const char *srs)
140{
141 static const int16_t max_query_size = 512;
142 char query[512];
143 Oid argtypes[] = {CSTRINGOID};
144 Datum values[] = {CStringGetDatum(srs)};
145 int32_t srid, err;
146
147 postgis_initialize_cache(fcinfo);
148 snprintf(query,
149 max_query_size,
150 "SELECT srid "
151 "FROM %s, "
152 "regexp_matches($1::text, E'([a-z]+):([0-9]+)', 'gi') AS re "
153 "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid",
154 postgis_spatial_ref_sys());
155
156 if (!srs) return 0;
157
158 if (SPI_OK_CONNECT != SPI_connect())
159 {
160 elog(NOTICE, "getSRIDbySRS: could not connect to SPI manager");
161 return 0;
162 }
163
164 err = SPI_execute_with_args(query, 1, argtypes, values, NULL, true, 1);
165 if (err < 0)
166 {
167 elog(NOTICE, "getSRIDbySRS: error executing query %d", err);
168 SPI_finish();
169 return 0;
170 }
171
172 /* no entry in spatial_ref_sys */
173 if (SPI_processed <= 0)
174 {
175 snprintf(query,
176 max_query_size,
177 "SELECT srid "
178 "FROM %s, "
179 "regexp_matches($1::text, E'urn:ogc:def:crs:([a-z]+):.*:([0-9]+)', 'gi') AS re "
180 "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid",
181 postgis_spatial_ref_sys());
182
183 err = SPI_execute_with_args(query, 1, argtypes, values, NULL, true, 1);
184 if (err < 0)
185 {
186 elog(NOTICE, "getSRIDbySRS: error executing query %d", err);
187 SPI_finish();
188 return 0;
189 }
190
191 if (SPI_processed <= 0)
192 {
193 SPI_finish();
194 return 0;
195 }
196 }
197
198 srid = atoi(SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1));
199 SPI_finish();
200
201 return srid;
202}
203
204
209Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
210{
211 GSERIALIZED *geom;
212 LWGEOM *lwgeom;
213 char *gml = NULL;
214 text *result;
215 int version;
216 char *srs;
217 int32_t srid;
218 int option = 0;
219 int lwopts = LW_GML_IS_DIMS;
220 int precision = DBL_DIG;
221 static const char* default_prefix = "gml:"; /* default prefix */
222 const char* prefix = default_prefix;
223 const char* gml_id = NULL;
224 size_t len;
225 char *gml_id_buf, *prefix_buf;
226 text *prefix_text, *gml_id_text;
227
228
229 /* Get the version */
230 version = PG_GETARG_INT32(0);
231 if ( version != 2 && version != 3 )
232 {
233 elog(ERROR, "Only GML 2 and GML 3 are supported");
234 PG_RETURN_NULL();
235 }
236
237 /* Get the geometry */
238 if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
239 geom = PG_GETARG_GSERIALIZED_P(1);
240
241 /* Retrieve precision if any (default is max) */
242 if (PG_NARGS() > 2 && !PG_ARGISNULL(2))
243 {
244 precision = PG_GETARG_INT32(2);
245 /* TODO: leave this to liblwgeom ? */
246 if (precision > DBL_DIG)
247 precision = DBL_DIG;
248 else if (precision < 0)
249 precision = 0;
250 }
251
252 /* retrieve option */
253 if (PG_NARGS() > 3 && !PG_ARGISNULL(3)) option = PG_GETARG_INT32(3);
254
255 /* retrieve prefix */
256 if (PG_NARGS() >4 && !PG_ARGISNULL(4))
257 {
258 prefix_text = PG_GETARG_TEXT_P(4);
259 if ( VARSIZE(prefix_text) == VARHDRSZ )
260 {
261 prefix = "";
262 }
263 else
264 {
265 len = VARSIZE_ANY_EXHDR(prefix_text);
266 prefix_buf = palloc(len + 2); /* +2 is one for the ':' and one for term null */
267 memcpy(prefix_buf, VARDATA(prefix_text), len);
268 /* add colon and null terminate */
269 prefix_buf[len] = ':';
270 prefix_buf[len+1] = '\0';
271 prefix = prefix_buf;
272 }
273 }
274
275 if (PG_NARGS() >5 && !PG_ARGISNULL(5))
276 {
277 gml_id_text = PG_GETARG_TEXT_P(5);
278 if ( VARSIZE(gml_id_text) == VARHDRSZ )
279 {
280 gml_id = "";
281 }
282 else
283 {
284 len = VARSIZE_ANY_EXHDR(gml_id_text);
285 gml_id_buf = palloc(len+1);
286 memcpy(gml_id_buf, VARDATA(gml_id_text), len);
287 gml_id_buf[len] = '\0';
288 gml_id = gml_id_buf;
289 }
290 }
291
292 srid = gserialized_get_srid(geom);
293 if (srid == SRID_UNKNOWN) srs = NULL;
294 else if (option & 1)
295 srs = getSRSbySRID(fcinfo, srid, false);
296 else
297 srs = getSRSbySRID(fcinfo, srid, true);
298
299 if (option & 2) lwopts &= ~LW_GML_IS_DIMS;
300 if (option & 4) lwopts |= LW_GML_SHORTLINE;
301 if (option & 8)
302 {
303 elog(ERROR,
304 "Options %d passed to ST_AsGML(geography) sets "
305 "unsupported value 8",
306 option);
307 PG_RETURN_NULL();
308 }
309 if (option & 16) lwopts |= LW_GML_IS_DEGREE;
310 if (option & 32) lwopts |= LW_GML_EXTENT;
311
312 lwgeom = lwgeom_from_gserialized(geom);
313
314 if (version == 2)
315 {
316 if (lwopts & LW_GML_EXTENT)
318 lwgeom, srs, precision, prefix);
319 else
320 gml = lwgeom_to_gml2(lwgeom, srs, precision, prefix);
321 }
322 if (version == 3)
323 {
324 if (lwopts & LW_GML_EXTENT)
326 lwgeom, srs, precision, lwopts, prefix);
327 else
328 gml = lwgeom_to_gml3(
329 lwgeom, srs, precision, lwopts, prefix, gml_id);
330 }
331
332 lwgeom_free(lwgeom);
333 PG_FREE_IF_COPY(geom, 1);
334
335 /* Return null on null */
336 if ( ! gml )
337 PG_RETURN_NULL();
338
339 result = cstring_to_text(gml);
340 lwfree(gml);
341 PG_RETURN_TEXT_P(result);
342}
343
344
345
346
354Datum LWGEOM_asGeoJson_old(PG_FUNCTION_ARGS)
355{
356 switch( PG_NARGS() )
357 {
358 case 2:
359 return DirectFunctionCall1(LWGEOM_asGeoJson, PG_GETARG_DATUM(1));
360 case 3:
361 return DirectFunctionCall2(LWGEOM_asGeoJson, PG_GETARG_DATUM(1), PG_GETARG_DATUM(2));
362 case 4:
363 return DirectFunctionCall3(LWGEOM_asGeoJson, PG_GETARG_DATUM(1), PG_GETARG_DATUM(2), PG_GETARG_DATUM(3));
364 default:
365 elog(ERROR, "bad call in %s", __func__);
366 }
367 PG_RETURN_NULL();
368}
369
374Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
375{
376 GSERIALIZED *geom;
377 LWGEOM *lwgeom;
378 char *geojson;
379 text *result;
380 int precision = DBL_DIG;
381 int output_bbox = LW_FALSE;
382 int output_long_crs = LW_FALSE;
383 int output_short_crs = LW_FALSE;
384 int output_guess_short_srid = LW_FALSE;
385 char *srs = NULL;
386 int32_t srid;
387
388 /* Get the geometry */
389 if (PG_ARGISNULL(0))
390 PG_RETURN_NULL();
391
392 geom = PG_GETARG_GSERIALIZED_P(0);
393 srid = gserialized_get_srid(geom);
394
395 /* Retrieve precision if any (default is max) */
396 if ( PG_NARGS() > 1 && !PG_ARGISNULL(1) )
397 {
398 precision = PG_GETARG_INT32(1);
399 if ( precision > DBL_DIG )
400 precision = DBL_DIG;
401 else if ( precision < 0 )
402 precision = 0;
403 }
404
405 /* Retrieve output option
406 * 0 = without option
407 * 1 = bbox
408 * 2 = short crs
409 * 4 = long crs
410 * 8 = guess if CRS is needed (default)
411 */
412 if (PG_NARGS() > 2 && !PG_ARGISNULL(2))
413 {
414 int option = PG_GETARG_INT32(2);
415 output_guess_short_srid = (option & 8) ? LW_TRUE : LW_FALSE;
416 output_short_crs = (option & 2) ? LW_TRUE : LW_FALSE;
417 output_long_crs = (option & 4) ? LW_TRUE : LW_FALSE;
418 output_bbox = (option & 1) ? LW_TRUE : LW_FALSE;
419 }
420 else
421 output_guess_short_srid = LW_TRUE;
422
423 if (output_guess_short_srid && srid != WGS84_SRID && srid != SRID_UNKNOWN)
424 output_short_crs = LW_TRUE;
425
426 if (srid != SRID_UNKNOWN && (output_short_crs || output_long_crs))
427 {
428 srs = getSRSbySRID(fcinfo, srid, !output_long_crs);
429
430 if (!srs)
431 {
432 elog(ERROR, "SRID %i unknown in spatial_ref_sys table", srid);
433 PG_RETURN_NULL();
434 }
435 }
436
437 lwgeom = lwgeom_from_gserialized(geom);
438 geojson = lwgeom_to_geojson(lwgeom, srs, precision, output_bbox);
439 lwgeom_free(lwgeom);
440
441 if (srs) pfree(srs);
442
443 result = cstring_to_text(geojson);
444 lwfree(geojson);
445
446 PG_FREE_IF_COPY(geom, 0);
447 PG_RETURN_TEXT_P(result);
448}
449
450
455Datum geometry_to_json(PG_FUNCTION_ARGS)
456{
457 GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
458 LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
459 char *geojson = lwgeom_to_geojson(lwgeom, NULL, 15, 0);
460 text *result = cstring_to_text(geojson);
461 lwgeom_free(lwgeom);
462 pfree(geojson);
463 PG_FREE_IF_COPY(geom, 0);
464 PG_RETURN_TEXT_P(result);
465}
466
468Datum geometry_to_jsonb(PG_FUNCTION_ARGS)
469{
470 GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
471 LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
472 char *geojson = lwgeom_to_geojson(lwgeom, NULL, 15, 0);
473 lwgeom_free(lwgeom);
474 PG_RETURN_DATUM(DirectFunctionCall1(jsonb_in, PointerGetDatum(geojson)));
475}
476
477
482Datum LWGEOM_asSVG(PG_FUNCTION_ARGS)
483{
484 GSERIALIZED *geom;
485 LWGEOM *lwgeom;
486 char *svg;
487 text *result;
488 int relative = 0;
489 int precision=DBL_DIG;
490
491 if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
492
493 geom = PG_GETARG_GSERIALIZED_P(0);
494
495 /* check for relative path notation */
496 if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
497 relative = PG_GETARG_INT32(1) ? 1:0;
498
499 if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
500 {
501 precision = PG_GETARG_INT32(2);
502 /* TODO: leave this to liblwgeom ? */
503 if ( precision > DBL_DIG )
504 precision = DBL_DIG;
505 else if ( precision < 0 ) precision = 0;
506 }
507
508 lwgeom = lwgeom_from_gserialized(geom);
509 svg = lwgeom_to_svg(lwgeom, precision, relative);
510 result = cstring_to_text(svg);
511 lwgeom_free(lwgeom);
512 pfree(svg);
513 PG_FREE_IF_COPY(geom, 0);
514
515 PG_RETURN_TEXT_P(result);
516}
517
522Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
523{
524 GSERIALIZED *geom;
525 LWGEOM *lwgeom;
526 char *x3d;
527 text *result;
528 int version;
529 char *srs;
530 int32_t srid;
531 int option = 0;
532 int precision = DBL_DIG;
533 static const char* default_defid = "x3d:"; /* default defid */
534 char *defidbuf;
535 const char* defid = default_defid;
536 text *defid_text;
537
538 /* Get the version */
539 version = PG_GETARG_INT32(0);
540 if ( version != 3 )
541 {
542 elog(ERROR, "Only X3D version 3 are supported");
543 PG_RETURN_NULL();
544 }
545
546 /* Get the geometry */
547 if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
548 geom = PG_GETARG_GSERIALIZED_P(1);
549
550 /* Retrieve precision if any (default is max) */
551 if (PG_NARGS() >2 && !PG_ARGISNULL(2))
552 {
553 precision = PG_GETARG_INT32(2);
554 /* TODO: leave this to liblwgeom ? */
555 if ( precision > DBL_DIG )
556 precision = DBL_DIG;
557 else if ( precision < 0 ) precision = 0;
558 }
559
560 /* retrieve option */
561 if (PG_NARGS() >3 && !PG_ARGISNULL(3))
562 option = PG_GETARG_INT32(3);
563
564
565
566 /* retrieve defid */
567 if (PG_NARGS() >4 && !PG_ARGISNULL(4))
568 {
569 defid_text = PG_GETARG_TEXT_P(4);
570 if ( VARSIZE_ANY_EXHDR(defid_text) == 0 )
571 {
572 defid = "";
573 }
574 else
575 {
576 /* +2 is one for the ':' and one for term null */
577 defidbuf = palloc(VARSIZE_ANY_EXHDR(defid_text)+2);
578 memcpy(defidbuf, VARDATA(defid_text),
579 VARSIZE_ANY_EXHDR(defid_text));
580 /* add colon and null terminate */
581 defidbuf[VARSIZE_ANY_EXHDR(defid_text)] = ':';
582 defidbuf[VARSIZE_ANY_EXHDR(defid_text)+1] = '\0';
583 defid = defidbuf;
584 }
585 }
586
587 lwgeom = lwgeom_from_gserialized(geom);
588 srid = gserialized_get_srid(geom);
589 if (srid == SRID_UNKNOWN) srs = NULL;
590 else if (option & 1)
591 srs = getSRSbySRID(fcinfo, srid, false);
592 else
593 srs = getSRSbySRID(fcinfo, srid, true);
594
595 if (option & LW_X3D_USE_GEOCOORDS) {
596 if (srid != 4326) {
597 PG_FREE_IF_COPY(geom, 0);
600 elog(ERROR, "Only SRID 4326 is supported for geocoordinates.");
601 PG_RETURN_NULL();
602 }
603 }
604
605
606 x3d = lwgeom_to_x3d3(lwgeom, srs, precision,option, defid);
607
608 lwgeom_free(lwgeom);
609 PG_FREE_IF_COPY(geom, 1);
610
611 result = cstring_to_text(x3d);
612 lwfree(x3d);
613
614 PG_RETURN_TEXT_P(result);
615}
616
621Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS)
622{
623 GSERIALIZED *geom;
624 LWGEOM *lwgeom;
625 char *encodedpolyline;
626 int precision = 5;
627 text *result;
628
629 if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
630
631 geom = PG_GETARG_GSERIALIZED_P(0);
632 if (gserialized_get_srid(geom) != 4326) {
633 PG_FREE_IF_COPY(geom, 0);
634 elog(ERROR, "Only SRID 4326 is supported.");
635 PG_RETURN_NULL();
636 }
637 lwgeom = lwgeom_from_gserialized(geom);
638
639 if (PG_NARGS() > 1 && !PG_ARGISNULL(1))
640 {
641 precision = PG_GETARG_INT32(1);
642 if ( precision < 0 ) precision = 5;
643 }
644
645 encodedpolyline = lwgeom_to_encoded_polyline(lwgeom, precision);
646 lwgeom_free(lwgeom);
647 PG_FREE_IF_COPY(geom, 0);
648
649 result = cstring_to_text(encodedpolyline);
650 lwfree(encodedpolyline);
651
652 PG_RETURN_TEXT_P(result);
653}
static uint8_t precision
Definition cu_in_twkb.c:25
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
#define WGS84_SRID
Definition liblwgeom.h:163
char * lwgeom_to_encoded_polyline(const LWGEOM *geom, int precision)
#define LW_FALSE
Definition liblwgeom.h:108
#define LW_GML_IS_DEGREE
For GML3 only, declare that datas are lat/lon.
Definition liblwgeom.h:1650
char * lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid)
Definition lwout_x3d.c:36
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1138
char * lwgeom_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix)
VERSION GML 2 takes a GEOMETRY and returns a GML2 representation.
Definition lwout_gml.c:231
char * lwgeom_to_svg(const LWGEOM *geom, int precision, int relative)
Takes a GEOMETRY and returns a SVG representation.
Definition lwout_svg.c:56
#define LW_GML_SHORTLINE
For GML3, use <LineString> rather than <Curve> for lines.
Definition liblwgeom.h:1652
#define LW_GML_EXTENT
For GML2 and GML3, output only extent of geometry.
Definition liblwgeom.h:1654
char * lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix)
Definition lwout_gml.c:198
void lwfree(void *mem)
Definition lwutil.c:242
#define LW_GML_IS_DIMS
Macros for specifying GML options.
Definition liblwgeom.h:1648
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:107
char * lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition lwout_gml.c:716
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:229
#define LW_X3D_USE_GEOCOORDS
Definition liblwgeom.h:1667
char * lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix)
Definition lwout_gml.c:213
char * lwgeom_to_geojson(const LWGEOM *geo, char *srs, int precision, int has_bbox)
Takes a GEOMETRY and returns a GeoJson representation.
This library is the generic geometry handling section of PostGIS.
Datum geometry_to_json(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(LWGEOM_asGML)
Encode feature in GML.
int getSRIDbySRS(FunctionCallInfo fcinfo, const char *srs)
Datum LWGEOM_asGeoJson_old(PG_FUNCTION_ARGS)
Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS)
Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
Datum LWGEOM_asSVG(PG_FUNCTION_ARGS)
Datum geometry_to_jsonb(PG_FUNCTION_ARGS)
char * getSRSbySRID(FunctionCallInfo fcinfo, int32_t srid, bool short_crs)
Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)