PostGIS  2.5.7dev-r@@SVN_REVISION@@
geography_inout.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 Paul Ramsey <pramsey@cleverelephant.ca>
22  *
23  **********************************************************************/
24 
25 
26 #include "postgres.h"
27 
28 #include "../postgis_config.h"
29 
30 #include <math.h>
31 #include <float.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <errno.h>
35 
36 #include "utils/elog.h"
37 #include "utils/array.h"
38 #include "utils/builtins.h" /* for pg_atoi */
39 #include "lib/stringinfo.h" /* For binary input */
40 #include "catalog/pg_type.h" /* for CSTRINGOID */
41 
42 #include "liblwgeom.h" /* For standard geometry types. */
43 #include "lwgeom_pg.h" /* For debugging macros. */
44 #include "geography.h" /* For utility functions. */
45 #include "lwgeom_export.h" /* For export functions. */
46 #include "lwgeom_transform.h"
47 
48 Datum geography_in(PG_FUNCTION_ARGS);
49 Datum geography_out(PG_FUNCTION_ARGS);
50 
51 Datum geography_as_text(PG_FUNCTION_ARGS);
52 Datum geography_from_text(PG_FUNCTION_ARGS);
53 Datum geography_as_geojson(PG_FUNCTION_ARGS);
54 Datum geography_as_gml(PG_FUNCTION_ARGS);
55 Datum geography_as_kml(PG_FUNCTION_ARGS);
56 Datum geography_as_svg(PG_FUNCTION_ARGS);
57 Datum geography_from_binary(PG_FUNCTION_ARGS);
58 Datum geography_from_geometry(PG_FUNCTION_ARGS);
59 Datum geometry_from_geography(PG_FUNCTION_ARGS);
60 Datum geography_send(PG_FUNCTION_ARGS);
61 Datum geography_recv(PG_FUNCTION_ARGS);
62 
64 
71 {
72  if ( ! (
73  type == POINTTYPE ||
74  type == LINETYPE ||
75  type == POLYGONTYPE ||
76  type == MULTIPOINTTYPE ||
77  type == MULTILINETYPE ||
80  ) )
81  {
82  ereport(ERROR, (
83  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
84  errmsg("Geography type does not support %s", lwtype_name(type) )));
85 
86  }
87 }
88 
90 {
91  GSERIALIZED *g_ser = NULL;
92 
93  /* Set geodetic flag */
94  lwgeom_set_geodetic(lwgeom, true);
95 
96  /* Check that this is a type we can handle */
97  geography_valid_type(lwgeom->type);
98 
99  /* Force the geometry to have valid geodetic coordinate range. */
100  lwgeom_nudge_geodetic(lwgeom);
101  if ( lwgeom_force_geodetic(lwgeom) == LW_TRUE )
102  {
103  ereport(NOTICE, (
104  errmsg_internal("Coordinate values were coerced into range [-180 -90, 180 90] for GEOGRAPHY" ))
105  );
106  }
107 
108  /* Force default SRID to the default */
109  if ( (int)lwgeom->srid <= 0 )
110  lwgeom->srid = SRID_DEFAULT;
111 
112  /*
113  ** Serialize our lwgeom and set the geodetic flag so subsequent
114  ** functions do the right thing.
115  */
116  g_ser = geography_serialize(lwgeom);
117 
118  /* Check for typmod agreement */
119  if ( geog_typmod >= 0 )
120  {
121  g_ser = postgis_valid_typmod(g_ser, geog_typmod);
122  POSTGIS_DEBUG(3, "typmod and geometry were consistent");
123  }
124  else
125  {
126  POSTGIS_DEBUG(3, "typmod was -1");
127  }
128 
129  return g_ser;
130 }
131 
132 
133 /*
134 ** geography_in(cstring) returns *GSERIALIZED
135 */
137 Datum geography_in(PG_FUNCTION_ARGS)
138 {
139  char *str = PG_GETARG_CSTRING(0);
140  /* Datum geog_oid = PG_GETARG_OID(1); Not needed. */
141  int32 geog_typmod = -1;
142  LWGEOM_PARSER_RESULT lwg_parser_result;
143  LWGEOM *lwgeom = NULL;
144  GSERIALIZED *g_ser = NULL;
145 
146  if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) {
147  geog_typmod = PG_GETARG_INT32(2);
148  }
149 
150  lwgeom_parser_result_init(&lwg_parser_result);
151 
152  /* Empty string. */
153  if ( str[0] == '\0' )
154  ereport(ERROR,(errmsg("parse error - invalid geometry")));
155 
156  /* WKB? Let's find out. */
157  if ( str[0] == '0' )
158  {
159  /* TODO: 20101206: No parser checks! This is inline with current 1.5 behavior, but needs discussion */
161  /* Error out if something went sideways */
162  if ( ! lwgeom )
163  ereport(ERROR,(errmsg("parse error - invalid geometry")));
164  }
165  /* WKT then. */
166  else
167  {
168  if ( lwgeom_parse_wkt(&lwg_parser_result, str, LW_PARSER_CHECK_ALL) == LW_FAILURE )
169  PG_PARSER_ERROR(lwg_parser_result);
170 
171  lwgeom = lwg_parser_result.geom;
172  }
173 
174  /* Error on any SRID != default */
175  srid_is_latlong(fcinfo, lwgeom->srid);
176 
177  /* Convert to gserialized */
178  g_ser = gserialized_geography_from_lwgeom(lwgeom, geog_typmod);
179 
180  /* Clean up temporary object */
181  lwgeom_free(lwgeom);
182 
183 
184  PG_RETURN_POINTER(g_ser);
185 }
186 
187 /*
188 ** geography_out(*GSERIALIZED) returns cstring
189 */
191 Datum geography_out(PG_FUNCTION_ARGS)
192 {
193  LWGEOM *lwgeom = NULL;
194  GSERIALIZED *g = NULL;
195  char *hexwkb;
196 
197  g = PG_GETARG_GSERIALIZED_P(0);
198  lwgeom = lwgeom_from_gserialized(g);
199  hexwkb = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, 0);
200  lwgeom_free(lwgeom);
201 
202  PG_RETURN_CSTRING(hexwkb);
203 }
204 
205 
206 /*
207 ** geography_as_gml(*GSERIALIZED) returns text
208 */
210 Datum geography_as_gml(PG_FUNCTION_ARGS)
211 {
212  LWGEOM *lwgeom = NULL;
213  GSERIALIZED *g = NULL;
214  char *gml;
215  text *result;
216  int version;
217  char *srs;
218  int srid = SRID_DEFAULT;
219  int precision = DBL_DIG;
220  int option = 0;
221  int lwopts = LW_GML_IS_DIMS;
222  static const char *default_prefix = "gml:";
223  const char *prefix = default_prefix;
224  char *prefix_buf = "";
225  text *prefix_text, *id_text = NULL;
226  const char *id=NULL;
227  char *id_buf;
228 
229 
230  /* Get the version */
231  version = PG_GETARG_INT32(0);
232  if ( version != 2 && version != 3 )
233  {
234  elog(ERROR, "Only GML 2 and GML 3 are supported");
235  PG_RETURN_NULL();
236  }
237 
238  /* Get the geography */
239  if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
240  g = PG_GETARG_GSERIALIZED_P(1);
241 
242  /* Convert to lwgeom so we can run the old functions */
243  lwgeom = lwgeom_from_gserialized(g);
244 
245  /* Retrieve precision if any (default is max) */
246  if (PG_NARGS() >2 && !PG_ARGISNULL(2))
247  {
248  precision = PG_GETARG_INT32(2);
249  /* TODO: leave this to liblwgeom */
250  if ( precision > DBL_DIG )
251  precision = DBL_DIG;
252  else if ( precision < 0 ) precision = 0;
253  }
254 
255  /* retrieve option */
256  if (PG_NARGS() >3 && !PG_ARGISNULL(3))
257  option = PG_GETARG_INT32(3);
258 
259 
260  /* retrieve prefix */
261  if (PG_NARGS() >4 && !PG_ARGISNULL(4))
262  {
263  prefix_text = PG_GETARG_TEXT_P(4);
264  if ( VARSIZE(prefix_text)-VARHDRSZ == 0 )
265  {
266  prefix = "";
267  }
268  else
269  {
270  /* +2 is one for the ':' and one for term null */
271  prefix_buf = palloc(VARSIZE(prefix_text)-VARHDRSZ+2);
272  memcpy(prefix_buf, VARDATA(prefix_text),
273  VARSIZE(prefix_text)-VARHDRSZ);
274  /* add colon and null terminate */
275  prefix_buf[VARSIZE(prefix_text)-VARHDRSZ] = ':';
276  prefix_buf[VARSIZE(prefix_text)-VARHDRSZ+1] = '\0';
277  prefix = prefix_buf;
278  }
279  }
280 
281  /* retrieve id */
282  if (PG_NARGS() >5 && !PG_ARGISNULL(5))
283  {
284  id_text = PG_GETARG_TEXT_P(5);
285  if ( VARSIZE(id_text)-VARHDRSZ == 0 )
286  {
287  id = "";
288  }
289  else
290  {
291  id_buf = palloc(VARSIZE(id_text)-VARHDRSZ+1);
292  memcpy(id_buf, VARDATA(id_text), VARSIZE(id_text)-VARHDRSZ);
293  prefix_buf[VARSIZE(id_text)-VARHDRSZ+1] = '\0';
294  id = id_buf;
295  }
296  }
297 
298  if (option & 1)
299  srs = getSRSbySRID(fcinfo, srid, false);
300  else
301  srs = getSRSbySRID(fcinfo, srid, true);
302  if (!srs)
303  {
304  elog(ERROR, "SRID %d unknown in spatial_ref_sys table", SRID_DEFAULT);
305  PG_RETURN_NULL();
306  }
307 
308  /* Revert lat/lon only with long SRS */
309  if (option & 1) lwopts |= LW_GML_IS_DEGREE;
310  if (option & 2) lwopts &= ~LW_GML_IS_DIMS;
311  if (option & 8)
312  {
313  elog(ERROR,
314  "Options %d passed to ST_AsGML(geography) sets "
315  "unsupported value 8",
316  option);
317  PG_RETURN_NULL();
318  }
319  if ((option & 4) || (option & 16) || (option & 32))
320  {
321  elog(ERROR,
322  "Options %d passed to ST_AsGML(geography) but are only "
323  "applicable to ST_AsGML(geometry)",
324  option);
325  PG_RETURN_NULL();
326  }
327 
328  if (version == 2)
329  gml = lwgeom_to_gml2(lwgeom, srs, precision, prefix);
330  else
331  gml = lwgeom_to_gml3(lwgeom, srs, precision, lwopts, prefix, id);
332 
333  lwgeom_free(lwgeom);
334  PG_FREE_IF_COPY(g, 1);
335 
336  /* Return null on null */
337  if ( ! gml )
338  PG_RETURN_NULL();
339 
340  /* Turn string result into text for return */
341  result = cstring_to_text(gml);
342  lwfree(gml);
343 
344  PG_RETURN_TEXT_P(result);
345 }
346 
347 
348 /*
349 ** geography_as_kml(*GSERIALIZED) returns text
350 */
352 Datum geography_as_kml(PG_FUNCTION_ARGS)
353 {
354  GSERIALIZED *g = NULL;
355  LWGEOM *lwgeom = NULL;
356  char *kml;
357  text *result;
358  int version;
359  int precision = DBL_DIG;
360  static const char *default_prefix = "";
361  char *prefixbuf;
362  const char* prefix = default_prefix;
363  text *prefix_text;
364 
365 
366  /* Get the version */
367  version = PG_GETARG_INT32(0);
368  if ( version != 2)
369  {
370  elog(ERROR, "Only KML 2 is supported");
371  PG_RETURN_NULL();
372  }
373 
374  /* Get the geometry */
375  if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
376  g = PG_GETARG_GSERIALIZED_P(1);
377 
378  /* Convert to lwgeom so we can run the old functions */
379  lwgeom = lwgeom_from_gserialized(g);
380 
381  /* Retrieve precision if any (default is max) */
382  if (PG_NARGS() >2 && !PG_ARGISNULL(2))
383  {
384  precision = PG_GETARG_INT32(2);
385  /* TODO: leave this to liblwgeom */
386  if ( precision > DBL_DIG )
387  precision = DBL_DIG;
388  else if ( precision < 0 ) precision = 0;
389  }
390 
391  /* retrieve prefix */
392  if (PG_NARGS() >3 && !PG_ARGISNULL(3))
393  {
394  prefix_text = PG_GETARG_TEXT_P(3);
395  if ( VARSIZE(prefix_text)-VARHDRSZ == 0 )
396  {
397  prefix = "";
398  }
399  else
400  {
401  /* +2 is one for the ':' and one for term null */
402  prefixbuf = palloc(VARSIZE(prefix_text)-VARHDRSZ+2);
403  memcpy(prefixbuf, VARDATA(prefix_text),
404  VARSIZE(prefix_text)-VARHDRSZ);
405  /* add colon and null terminate */
406  prefixbuf[VARSIZE(prefix_text)-VARHDRSZ] = ':';
407  prefixbuf[VARSIZE(prefix_text)-VARHDRSZ+1] = '\0';
408  prefix = prefixbuf;
409  }
410  }
411 
412  kml = lwgeom_to_kml2(lwgeom, precision, prefix);
413 
414  lwgeom_free(lwgeom);
415  PG_FREE_IF_COPY(g, 1);
416 
417  if ( ! kml )
418  PG_RETURN_NULL();
419 
420  result = cstring_to_text(kml);
421  lwfree(kml);
422 
423  PG_RETURN_TEXT_P(result);
424 }
425 
426 
427 /*
428 ** geography_as_svg(*GSERIALIZED) returns text
429 */
431 Datum geography_as_svg(PG_FUNCTION_ARGS)
432 {
433  GSERIALIZED *g = NULL;
434  LWGEOM *lwgeom = NULL;
435  char *svg;
436  text *result;
437  int relative = 0;
438  int precision=DBL_DIG;
439 
440  if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
441 
442  g = PG_GETARG_GSERIALIZED_P(0);
443 
444  /* Convert to lwgeom so we can run the old functions */
445  lwgeom = lwgeom_from_gserialized(g);
446 
447  /* check for relative path notation */
448  if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
449  relative = PG_GETARG_INT32(1) ? 1:0;
450 
451  if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
452  {
453  precision = PG_GETARG_INT32(2);
454  /* TODO: leave this to liblwgeom */
455  if ( precision > DBL_DIG )
456  precision = DBL_DIG;
457  else if ( precision < 0 ) precision = 0;
458  }
459 
460  svg = lwgeom_to_svg(lwgeom, precision, relative);
461 
462  lwgeom_free(lwgeom);
463  PG_FREE_IF_COPY(g, 0);
464 
465  result = cstring_to_text(svg);
466  lwfree(svg);
467 
468  PG_RETURN_TEXT_P(result);
469 }
470 
471 
472 /*
473 ** geography_as_geojson(*GSERIALIZED) returns text
474 */
476 Datum geography_as_geojson(PG_FUNCTION_ARGS)
477 {
478  LWGEOM *lwgeom = NULL;
479  GSERIALIZED *g = NULL;
480  char *geojson;
481  text *result;
482  int version;
483  int option = 0;
484  int has_bbox = 0;
485  int precision = DBL_DIG;
486  char * srs = NULL;
487 
488  /* Get the version */
489  version = PG_GETARG_INT32(0);
490  if ( version != 1)
491  {
492  elog(ERROR, "Only GeoJSON 1 is supported");
493  PG_RETURN_NULL();
494  }
495 
496  /* Get the geography */
497  if (PG_ARGISNULL(1) ) PG_RETURN_NULL();
498  g = PG_GETARG_GSERIALIZED_P(1);
499 
500  /* Convert to lwgeom so we can run the old functions */
501  lwgeom = lwgeom_from_gserialized(g);
502 
503  /* Retrieve precision if any (default is max) */
504  if (PG_NARGS() >2 && !PG_ARGISNULL(2))
505  {
506  precision = PG_GETARG_INT32(2);
507  /* TODO: leave this to liblwgeom */
508  if ( precision > DBL_DIG )
509  precision = DBL_DIG;
510  else if ( precision < 0 ) precision = 0;
511  }
512 
513  /* Retrieve output option
514  * 0 = without option (default)
515  * 1 = bbox
516  * 2 = short crs
517  * 4 = long crs
518  */
519  if (PG_NARGS() >3 && !PG_ARGISNULL(3))
520  option = PG_GETARG_INT32(3);
521 
522  if (option & 2 || option & 4)
523  {
524  /* Geography only handle srid SRID_DEFAULT */
525  if (option & 2)
526  srs = getSRSbySRID(fcinfo, SRID_DEFAULT, true);
527  if (option & 4)
528  srs = getSRSbySRID(fcinfo, SRID_DEFAULT, false);
529 
530  if (!srs)
531  {
532  elog(ERROR, "SRID SRID_DEFAULT unknown in spatial_ref_sys table");
533  PG_RETURN_NULL();
534  }
535  }
536 
537  if (option & 1) has_bbox = 1;
538 
539  geojson = lwgeom_to_geojson(lwgeom, srs, precision, has_bbox);
540  lwgeom_free(lwgeom);
541  PG_FREE_IF_COPY(g, 1);
542  if (srs) pfree(srs);
543 
544  result = cstring_to_text(geojson);
545  lwfree(geojson);
546 
547  PG_RETURN_TEXT_P(result);
548 }
549 
550 
551 /*
552 ** geography_from_text(*char) returns *GSERIALIZED
553 **
554 ** Convert text (varlena) to cstring and then call geography_in().
555 */
557 Datum geography_from_text(PG_FUNCTION_ARGS)
558 {
559  LWGEOM_PARSER_RESULT lwg_parser_result;
560  GSERIALIZED *g_ser = NULL;
561  text *wkt_text = PG_GETARG_TEXT_P(0);
562 
563  /* Extract the cstring from the varlena */
564  char *wkt = text_to_cstring(wkt_text);
565 
566  /* Pass the cstring to the input parser, and magic occurs! */
567  if ( lwgeom_parse_wkt(&lwg_parser_result, wkt, LW_PARSER_CHECK_ALL) == LW_FAILURE )
568  PG_PARSER_ERROR(lwg_parser_result);
569 
570  /* Error on any SRID != default */
571  srid_is_latlong(fcinfo, lwg_parser_result.geom->srid);
572 
573  /* Clean up string */
574  pfree(wkt);
575  g_ser = gserialized_geography_from_lwgeom(lwg_parser_result.geom, -1);
576 
577  /* Clean up temporary object */
578  lwgeom_free(lwg_parser_result.geom);
579 
580  PG_RETURN_POINTER(g_ser);
581 }
582 
583 /*
584 ** geography_from_binary(*char) returns *GSERIALIZED
585 */
587 Datum geography_from_binary(PG_FUNCTION_ARGS)
588 {
589  char *wkb_bytea = (char*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
590  GSERIALIZED *gser = NULL;
591  size_t wkb_size = VARSIZE(wkb_bytea);
592  uint8_t *wkb = (uint8_t*)VARDATA(wkb_bytea);
593  LWGEOM *lwgeom = lwgeom_from_wkb(wkb, wkb_size, LW_PARSER_CHECK_NONE);
594 
595  if ( ! lwgeom )
596  lwpgerror("Unable to parse WKB");
597 
598  /* Error on any SRID != default */
599  srid_is_latlong(fcinfo, lwgeom->srid);
600 
601  gser = gserialized_geography_from_lwgeom(lwgeom, -1);
602  lwgeom_free(lwgeom);
603  PG_RETURN_POINTER(gser);
604 }
605 
606 
608 Datum geography_from_geometry(PG_FUNCTION_ARGS)
609 {
610  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P_COPY(0);
611  LWGEOM *lwgeom = NULL;
612  GSERIALIZED *g_ser = NULL;
613 
615 
616  lwgeom = lwgeom_from_gserialized(geom);
617 
618  /* Force default SRID */
619  if ( (int)lwgeom->srid <= 0 )
620  {
621  lwgeom->srid = SRID_DEFAULT;
622  }
623 
624  /* Error on any SRID != default */
625  srid_is_latlong(fcinfo, lwgeom->srid);
626 
627  /* Force the geometry to have valid geodetic coordinate range. */
628  lwgeom_nudge_geodetic(lwgeom);
629  if ( lwgeom_force_geodetic(lwgeom) == LW_TRUE )
630  {
631  ereport(NOTICE, (
632  errmsg_internal("Coordinate values were coerced into range [-180 -90, 180 90] for GEOGRAPHY" ))
633  );
634  }
635 
636  /* force recalculate of box by dropping */
637  lwgeom_drop_bbox(lwgeom);
638 
639  lwgeom_set_geodetic(lwgeom, true);
640  /* We are trusting geography_serialize will add a box if needed */
641  g_ser = geography_serialize(lwgeom);
642 
643 
644  lwgeom_free(lwgeom);
645 
646  PG_FREE_IF_COPY(geom, 0);
647  PG_RETURN_POINTER(g_ser);
648 }
649 
651 Datum geometry_from_geography(PG_FUNCTION_ARGS)
652 {
653  LWGEOM *lwgeom = NULL;
654  GSERIALIZED *ret = NULL;
655  GSERIALIZED *g_ser = PG_GETARG_GSERIALIZED_P(0);
656 
657  lwgeom = lwgeom_from_gserialized(g_ser);
658 
659  /* Recalculate the boxes after re-setting the geodetic bit */
660  lwgeom_set_geodetic(lwgeom, false);
661  lwgeom_refresh_bbox(lwgeom);
662 
663  /* We want "geometry" to think all our "geography" has an SRID, and the
664  implied SRID is the default, so we fill that in if our SRID is actually unknown. */
665  if ( (int)lwgeom->srid <= 0 )
666  lwgeom->srid = SRID_DEFAULT;
667 
668  ret = geometry_serialize(lwgeom);
669  lwgeom_free(lwgeom);
670 
671  PG_RETURN_POINTER(ret);
672 }
673 
675 Datum geography_recv(PG_FUNCTION_ARGS)
676 {
677  StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
678  int32 geog_typmod = -1;
679  LWGEOM *lwgeom = NULL;
680  GSERIALIZED *g_ser = NULL;
681 
682  if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) {
683  geog_typmod = PG_GETARG_INT32(2);
684  }
685 
686  lwgeom = lwgeom_from_wkb((uint8_t*)buf->data, buf->len, LW_PARSER_CHECK_ALL);
687 
688  /* Error on any SRID != default */
689  srid_is_latlong(fcinfo, lwgeom->srid);
690 
691  g_ser = gserialized_geography_from_lwgeom(lwgeom, geog_typmod);
692 
693  /* Clean up temporary object */
694  lwgeom_free(lwgeom);
695 
696  /* Set cursor to the end of buffer (so the backend is happy) */
697  buf->cursor = buf->len;
698 
699  PG_RETURN_POINTER(g_ser);
700 }
701 
702 
704 Datum geography_send(PG_FUNCTION_ARGS)
705 {
706  LWGEOM *lwgeom = NULL;
707  GSERIALIZED *g = NULL;
708  size_t size_result;
709  uint8_t *wkb;
710  bytea *result;
711 
712  g = PG_GETARG_GSERIALIZED_P(0);
713  lwgeom = lwgeom_from_gserialized(g);
714  wkb = lwgeom_to_wkb(lwgeom, WKB_EXTENDED, &size_result);
715  lwgeom_free(lwgeom);
716 
717  result = palloc(size_result + VARHDRSZ);
718  SET_VARSIZE(result, size_result + VARHDRSZ);
719  memcpy(VARDATA(result), wkb, size_result);
720  pfree(wkb);
721 
722  PG_RETURN_POINTER(result);
723 }
static uint8_t precision
Definition: cu_in_twkb.c:25
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
Definition: g_serialized.c:86
GSERIALIZED * postgis_valid_typmod(GSERIALIZED *gser, int32_t typmod)
Check the consistency of the metadata we want to enforce in the typmod: srid, type and dimensionality...
Datum geography_as_kml(PG_FUNCTION_ARGS)
Datum geography_from_geometry(PG_FUNCTION_ARGS)
Datum geometry_from_geography(PG_FUNCTION_ARGS)
GSERIALIZED * gserialized_geography_from_lwgeom(LWGEOM *lwgeom, int32 geog_typmod)
Datum geography_in(PG_FUNCTION_ARGS)
Datum geography_recv(PG_FUNCTION_ARGS)
Datum geography_send(PG_FUNCTION_ARGS)
Datum geography_from_text(PG_FUNCTION_ARGS)
Datum geography_as_text(PG_FUNCTION_ARGS)
Datum geography_out(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(geography_in)
void geography_valid_type(uint8_t type)
The geography type only support POINT, LINESTRING, POLYGON, MULTI* variants of same,...
Datum geography_from_binary(PG_FUNCTION_ARGS)
Datum geography_as_gml(PG_FUNCTION_ARGS)
Datum geography_as_geojson(PG_FUNCTION_ARGS)
Datum geography_as_svg(PG_FUNCTION_ARGS)
void lwgeom_refresh_bbox(LWGEOM *lwgeom)
Drop current bbox and calculate a fresh one.
Definition: lwgeom.c:698
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_PARSER_CHECK_ALL
Definition: liblwgeom.h:2006
void lwgeom_set_geodetic(LWGEOM *geom, int value)
Set the FLAGS geodetic bit on geometry an all sub-geometries and pointlists.
Definition: lwgeom.c:952
#define COLLECTIONTYPE
Definition: liblwgeom.h:91
#define LW_GML_IS_DEGREE
For GML3 only, declare that datas are lat/lon.
Definition: liblwgeom.h:1544
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:809
#define LW_FAILURE
Definition: liblwgeom.h:79
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1144
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:2005
#define MULTILINETYPE
Definition: liblwgeom.h:89
#define LINETYPE
Definition: liblwgeom.h:86
void lwgeom_parser_result_init(LWGEOM_PARSER_RESULT *parser_result)
Definition: lwin_wkt.c:879
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
int lwgeom_parse_wkt(LWGEOM_PARSER_RESULT *parser_result, char *wktstr, int parse_flags)
Parse a WKT geometry string into an LWGEOM structure.
char * lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix)
Definition: lwout_kml.c:43
uint8_t * lwgeom_to_wkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
Convert LWGEOM to a char* in WKB format.
Definition: lwout_wkb.c:764
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
void lwgeom_drop_bbox(LWGEOM *lwgeom)
Call this function to drop BBOX and SRID from LWGEOM.
Definition: lwgeom.c:673
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
char * lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:717
void lwfree(void *mem)
Definition: lwutil.c:244
#define SRID_DEFAULT
Definition: liblwgeom.h:198
#define POLYGONTYPE
Definition: liblwgeom.h:87
#define WKB_EXTENDED
Definition: liblwgeom.h:2068
char * lwgeom_to_hexwkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
Definition: lwout_wkb.c:848
int lwgeom_force_geodetic(LWGEOM *geom)
Force coordinates of LWGEOM into geodetic range (-180, -90, 180, 90)
Definition: lwgeodetic.c:3222
#define LW_GML_IS_DIMS
Macros for specifying GML options.
Definition: liblwgeom.h:1542
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
int lwgeom_nudge_geodetic(LWGEOM *geom)
Gently move coordinates of LWGEOM if they are close enough into geodetic range.
Definition: lwgeodetic.c:3404
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:76
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_geojson(const LWGEOM *geo, char *srs, int precision, int has_bbox)
Takes a GEOMETRY and returns a GeoJson representation.
Definition: lwout_geojson.c:48
LWGEOM * lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
WKB inputs must have a declared size, to prevent malformed WKB from reading off the end of the memory...
Definition: lwin_wkb.c:789
This library is the generic geometry handling section of PostGIS.
char * getSRSbySRID(FunctionCallInfo fcinfo, int srid, bool short_crs)
Definition: lwgeom_export.c:60
type
Definition: ovdump.py:41
char * text_to_cstring(const text *textptr)
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
unsigned int int32
Definition: shpopen.c:273
uint8_t type
Definition: liblwgeom.h:399
int32_t srid
Definition: liblwgeom.h:402
Parser result structure: returns the result of attempting to convert (E)WKT/(E)WKB to LWGEOM.
Definition: liblwgeom.h:2013
unsigned char uint8_t
Definition: uthash.h:79