PostGIS  2.5.0beta2dev-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 ||
78  type == MULTIPOLYGONTYPE ||
79  type == COLLECTIONTYPE
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) srs = getSRSbySRID(srid, false);
299  else srs = getSRSbySRID(srid, true);
300  if (!srs)
301  {
302  elog(ERROR, "SRID %d unknown in spatial_ref_sys table", SRID_DEFAULT);
303  PG_RETURN_NULL();
304  }
305 
306  /* Revert lat/lon only with long SRS */
307  if (option & 1) lwopts |= LW_GML_IS_DEGREE;
308  if (option & 2) lwopts &= ~LW_GML_IS_DIMS;
309  if (option & 8)
310  {
311  elog(ERROR,
312  "Options %d passed to ST_AsGML(geography) sets "
313  "unsupported value 8",
314  option);
315  PG_RETURN_NULL();
316  }
317  if ((option & 4) || (option & 16) || (option & 32))
318  {
319  elog(ERROR,
320  "Options %d passed to ST_AsGML(geography) but are only "
321  "applicable to ST_AsGML(geometry)",
322  option);
323  PG_RETURN_NULL();
324  }
325 
326  if (version == 2)
327  gml = lwgeom_to_gml2(lwgeom, srs, precision, prefix);
328  else
329  gml = lwgeom_to_gml3(lwgeom, srs, precision, lwopts, prefix, id);
330 
331  lwgeom_free(lwgeom);
332  PG_FREE_IF_COPY(g, 1);
333 
334  /* Return null on null */
335  if ( ! gml )
336  PG_RETURN_NULL();
337 
338  /* Turn string result into text for return */
339  result = cstring_to_text(gml);
340  lwfree(gml);
341 
342  PG_RETURN_TEXT_P(result);
343 }
344 
345 
346 /*
347 ** geography_as_kml(*GSERIALIZED) returns text
348 */
350 Datum geography_as_kml(PG_FUNCTION_ARGS)
351 {
352  GSERIALIZED *g = NULL;
353  LWGEOM *lwgeom = NULL;
354  char *kml;
355  text *result;
356  int version;
357  int precision = DBL_DIG;
358  static const char *default_prefix = "";
359  char *prefixbuf;
360  const char* prefix = default_prefix;
361  text *prefix_text;
362 
363 
364  /* Get the version */
365  version = PG_GETARG_INT32(0);
366  if ( version != 2)
367  {
368  elog(ERROR, "Only KML 2 is supported");
369  PG_RETURN_NULL();
370  }
371 
372  /* Get the geometry */
373  if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
374  g = PG_GETARG_GSERIALIZED_P(1);
375 
376  /* Convert to lwgeom so we can run the old functions */
377  lwgeom = lwgeom_from_gserialized(g);
378 
379  /* Retrieve precision if any (default is max) */
380  if (PG_NARGS() >2 && !PG_ARGISNULL(2))
381  {
382  precision = PG_GETARG_INT32(2);
383  /* TODO: leave this to liblwgeom */
384  if ( precision > DBL_DIG )
385  precision = DBL_DIG;
386  else if ( precision < 0 ) precision = 0;
387  }
388 
389  /* retrieve prefix */
390  if (PG_NARGS() >3 && !PG_ARGISNULL(3))
391  {
392  prefix_text = PG_GETARG_TEXT_P(3);
393  if ( VARSIZE(prefix_text)-VARHDRSZ == 0 )
394  {
395  prefix = "";
396  }
397  else
398  {
399  /* +2 is one for the ':' and one for term null */
400  prefixbuf = palloc(VARSIZE(prefix_text)-VARHDRSZ+2);
401  memcpy(prefixbuf, VARDATA(prefix_text),
402  VARSIZE(prefix_text)-VARHDRSZ);
403  /* add colon and null terminate */
404  prefixbuf[VARSIZE(prefix_text)-VARHDRSZ] = ':';
405  prefixbuf[VARSIZE(prefix_text)-VARHDRSZ+1] = '\0';
406  prefix = prefixbuf;
407  }
408  }
409 
410  kml = lwgeom_to_kml2(lwgeom, precision, prefix);
411 
412  lwgeom_free(lwgeom);
413  PG_FREE_IF_COPY(g, 1);
414 
415  if ( ! kml )
416  PG_RETURN_NULL();
417 
418  result = cstring_to_text(kml);
419  lwfree(kml);
420 
421  PG_RETURN_TEXT_P(result);
422 }
423 
424 
425 /*
426 ** geography_as_svg(*GSERIALIZED) returns text
427 */
429 Datum geography_as_svg(PG_FUNCTION_ARGS)
430 {
431  GSERIALIZED *g = NULL;
432  LWGEOM *lwgeom = NULL;
433  char *svg;
434  text *result;
435  int relative = 0;
436  int precision=DBL_DIG;
437 
438  if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
439 
440  g = PG_GETARG_GSERIALIZED_P(0);
441 
442  /* Convert to lwgeom so we can run the old functions */
443  lwgeom = lwgeom_from_gserialized(g);
444 
445  /* check for relative path notation */
446  if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
447  relative = PG_GETARG_INT32(1) ? 1:0;
448 
449  if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
450  {
451  precision = PG_GETARG_INT32(2);
452  /* TODO: leave this to liblwgeom */
453  if ( precision > DBL_DIG )
454  precision = DBL_DIG;
455  else if ( precision < 0 ) precision = 0;
456  }
457 
458  svg = lwgeom_to_svg(lwgeom, precision, relative);
459 
460  lwgeom_free(lwgeom);
461  PG_FREE_IF_COPY(g, 0);
462 
463  result = cstring_to_text(svg);
464  lwfree(svg);
465 
466  PG_RETURN_TEXT_P(result);
467 }
468 
469 
470 /*
471 ** geography_as_geojson(*GSERIALIZED) returns text
472 */
474 Datum geography_as_geojson(PG_FUNCTION_ARGS)
475 {
476  LWGEOM *lwgeom = NULL;
477  GSERIALIZED *g = NULL;
478  char *geojson;
479  text *result;
480  int version;
481  int option = 0;
482  int has_bbox = 0;
483  int precision = DBL_DIG;
484  char * srs = NULL;
485 
486  /* Get the version */
487  version = PG_GETARG_INT32(0);
488  if ( version != 1)
489  {
490  elog(ERROR, "Only GeoJSON 1 is supported");
491  PG_RETURN_NULL();
492  }
493 
494  /* Get the geography */
495  if (PG_ARGISNULL(1) ) PG_RETURN_NULL();
496  g = PG_GETARG_GSERIALIZED_P(1);
497 
498  /* Convert to lwgeom so we can run the old functions */
499  lwgeom = lwgeom_from_gserialized(g);
500 
501  /* Retrieve precision if any (default is max) */
502  if (PG_NARGS() >2 && !PG_ARGISNULL(2))
503  {
504  precision = PG_GETARG_INT32(2);
505  /* TODO: leave this to liblwgeom */
506  if ( precision > DBL_DIG )
507  precision = DBL_DIG;
508  else if ( precision < 0 ) precision = 0;
509  }
510 
511  /* Retrieve output option
512  * 0 = without option (default)
513  * 1 = bbox
514  * 2 = short crs
515  * 4 = long crs
516  */
517  if (PG_NARGS() >3 && !PG_ARGISNULL(3))
518  option = PG_GETARG_INT32(3);
519 
520  if (option & 2 || option & 4)
521  {
522  /* Geography only handle srid SRID_DEFAULT */
523  if (option & 2) srs = getSRSbySRID(SRID_DEFAULT, true);
524  if (option & 4) srs = getSRSbySRID(SRID_DEFAULT, false);
525 
526  if (!srs)
527  {
528  elog(ERROR, "SRID SRID_DEFAULT unknown in spatial_ref_sys table");
529  PG_RETURN_NULL();
530  }
531  }
532 
533  if (option & 1) has_bbox = 1;
534 
535  geojson = lwgeom_to_geojson(lwgeom, srs, precision, has_bbox);
536  lwgeom_free(lwgeom);
537  PG_FREE_IF_COPY(g, 1);
538  if (srs) pfree(srs);
539 
540  result = cstring_to_text(geojson);
541  lwfree(geojson);
542 
543  PG_RETURN_TEXT_P(result);
544 }
545 
546 
547 /*
548 ** geography_from_text(*char) returns *GSERIALIZED
549 **
550 ** Convert text (varlena) to cstring and then call geography_in().
551 */
553 Datum geography_from_text(PG_FUNCTION_ARGS)
554 {
555  LWGEOM_PARSER_RESULT lwg_parser_result;
556  GSERIALIZED *g_ser = NULL;
557  text *wkt_text = PG_GETARG_TEXT_P(0);
558 
559  /* Extract the cstring from the varlena */
560  char *wkt = text_to_cstring(wkt_text);
561 
562  /* Pass the cstring to the input parser, and magic occurs! */
563  if ( lwgeom_parse_wkt(&lwg_parser_result, wkt, LW_PARSER_CHECK_ALL) == LW_FAILURE )
564  PG_PARSER_ERROR(lwg_parser_result);
565 
566  /* Error on any SRID != default */
567  srid_is_latlong(fcinfo, lwg_parser_result.geom->srid);
568 
569  /* Clean up string */
570  pfree(wkt);
571  g_ser = gserialized_geography_from_lwgeom(lwg_parser_result.geom, -1);
572 
573  /* Clean up temporary object */
574  lwgeom_free(lwg_parser_result.geom);
575 
576  PG_RETURN_POINTER(g_ser);
577 }
578 
579 /*
580 ** geography_from_binary(*char) returns *GSERIALIZED
581 */
583 Datum geography_from_binary(PG_FUNCTION_ARGS)
584 {
585  char *wkb_bytea = (char*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
586  GSERIALIZED *gser = NULL;
587  size_t wkb_size = VARSIZE(wkb_bytea);
588  uint8_t *wkb = (uint8_t*)VARDATA(wkb_bytea);
589  LWGEOM *lwgeom = lwgeom_from_wkb(wkb, wkb_size, LW_PARSER_CHECK_NONE);
590 
591  if ( ! lwgeom )
592  lwpgerror("Unable to parse WKB");
593 
594  /* Error on any SRID != default */
595  srid_is_latlong(fcinfo, lwgeom->srid);
596 
597  gser = gserialized_geography_from_lwgeom(lwgeom, -1);
598  lwgeom_free(lwgeom);
599  PG_RETURN_POINTER(gser);
600 }
601 
602 
604 Datum geography_from_geometry(PG_FUNCTION_ARGS)
605 {
606  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P_COPY(0);
607  LWGEOM *lwgeom = NULL;
608  GSERIALIZED *g_ser = NULL;
609 
611 
612  lwgeom = lwgeom_from_gserialized(geom);
613 
614  /* Force default SRID */
615  if ( (int)lwgeom->srid <= 0 )
616  {
617  lwgeom->srid = SRID_DEFAULT;
618  }
619 
620  /* Error on any SRID != default */
621  srid_is_latlong(fcinfo, lwgeom->srid);
622 
623  /* Force the geometry to have valid geodetic coordinate range. */
624  lwgeom_nudge_geodetic(lwgeom);
625  if ( lwgeom_force_geodetic(lwgeom) == LW_TRUE )
626  {
627  ereport(NOTICE, (
628  errmsg_internal("Coordinate values were coerced into range [-180 -90, 180 90] for GEOGRAPHY" ))
629  );
630  }
631 
632  /* force recalculate of box by dropping */
633  lwgeom_drop_bbox(lwgeom);
634 
635  lwgeom_set_geodetic(lwgeom, true);
636  /* We are trusting geography_serialize will add a box if needed */
637  g_ser = geography_serialize(lwgeom);
638 
639 
640  lwgeom_free(lwgeom);
641 
642  PG_FREE_IF_COPY(geom, 0);
643  PG_RETURN_POINTER(g_ser);
644 }
645 
647 Datum geometry_from_geography(PG_FUNCTION_ARGS)
648 {
649  LWGEOM *lwgeom = NULL;
650  GSERIALIZED *ret = NULL;
651  GSERIALIZED *g_ser = PG_GETARG_GSERIALIZED_P(0);
652 
653  lwgeom = lwgeom_from_gserialized(g_ser);
654 
655  /* Recalculate the boxes after re-setting the geodetic bit */
656  lwgeom_set_geodetic(lwgeom, false);
657  lwgeom_refresh_bbox(lwgeom);
658 
659  /* We want "geometry" to think all our "geography" has an SRID, and the
660  implied SRID is the default, so we fill that in if our SRID is actually unknown. */
661  if ( (int)lwgeom->srid <= 0 )
662  lwgeom->srid = SRID_DEFAULT;
663 
664  ret = geometry_serialize(lwgeom);
665  lwgeom_free(lwgeom);
666 
667  PG_RETURN_POINTER(ret);
668 }
669 
671 Datum geography_recv(PG_FUNCTION_ARGS)
672 {
673  StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
674  int32 geog_typmod = -1;
675  LWGEOM *lwgeom = NULL;
676  GSERIALIZED *g_ser = NULL;
677 
678  if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) {
679  geog_typmod = PG_GETARG_INT32(2);
680  }
681 
682  lwgeom = lwgeom_from_wkb((uint8_t*)buf->data, buf->len, LW_PARSER_CHECK_ALL);
683 
684  /* Error on any SRID != default */
685  srid_is_latlong(fcinfo, lwgeom->srid);
686 
687  g_ser = gserialized_geography_from_lwgeom(lwgeom, geog_typmod);
688 
689  /* Clean up temporary object */
690  lwgeom_free(lwgeom);
691 
692  /* Set cursor to the end of buffer (so the backend is happy) */
693  buf->cursor = buf->len;
694 
695  PG_RETURN_POINTER(g_ser);
696 }
697 
698 
700 Datum geography_send(PG_FUNCTION_ARGS)
701 {
702  LWGEOM *lwgeom = NULL;
703  GSERIALIZED *g = NULL;
704  size_t size_result;
705  uint8_t *wkb;
706  bytea *result;
707 
708  g = PG_GETARG_GSERIALIZED_P(0);
709  lwgeom = lwgeom_from_gserialized(g);
710  wkb = lwgeom_to_wkb(lwgeom, WKB_EXTENDED, &size_result);
711  lwgeom_free(lwgeom);
712 
713  result = palloc(size_result + VARHDRSZ);
714  SET_VARSIZE(result, size_result + VARHDRSZ);
715  memcpy(VARDATA(result), wkb, size_result);
716  pfree(wkb);
717 
718  PG_RETURN_POINTER(result);
719 }
#define LINETYPE
Definition: liblwgeom.h:85
char * text_to_cstring(const text *textptr)
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
char * lwgeom_to_hexwkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
Definition: lwout_wkb.c:848
void lwgeom_refresh_bbox(LWGEOM *lwgeom)
Drop current bbox and calculate a fresh one.
Definition: lwgeom.c:698
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
unsigned int int32
Definition: shpopen.c:273
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...
void lwfree(void *mem)
Definition: lwutil.c:244
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
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 POLYGONTYPE
Definition: liblwgeom.h:86
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1144
#define MULTIPOINTTYPE
Definition: liblwgeom.h:87
#define SRID_DEFAULT
Definition: liblwgeom.h:197
Datum geography_as_geojson(PG_FUNCTION_ARGS)
Datum geography_recv(PG_FUNCTION_ARGS)
int lwgeom_nudge_geodetic(LWGEOM *geom)
Gently move coordinates of LWGEOM if they are close enough into geodetic range.
Definition: lwgeodetic.c:3316
PG_FUNCTION_INFO_V1(geography_in)
void lwgeom_drop_bbox(LWGEOM *lwgeom)
Call this function to drop BBOX and SRID from LWGEOM.
Definition: lwgeom.c:673
int32_t srid
Definition: liblwgeom.h:401
#define LW_FAILURE
Definition: liblwgeom.h:78
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:2004
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
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
int lwgeom_parse_wkt(LWGEOM_PARSER_RESULT *parser_result, char *wktstr, int parse_flags)
Parse a WKT geometry string into an LWGEOM structure.
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:75
Parser result structure: returns the result of attempting to convert (E)WKT/(E)WKB to LWGEOM...
Definition: liblwgeom.h:2011
int lwgeom_force_geodetic(LWGEOM *geom)
Force coordinates of LWGEOM into geodetic range (-180, -90, 180, 90)
Definition: lwgeodetic.c:3134
Datum geography_in(PG_FUNCTION_ARGS)
Datum geography_as_text(PG_FUNCTION_ARGS)
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
uint8_t precision
Definition: cu_in_twkb.c:25
Datum geography_as_gml(PG_FUNCTION_ARGS)
Datum geometry_from_geography(PG_FUNCTION_ARGS)
Datum geography_as_svg(PG_FUNCTION_ARGS)
#define WKB_EXTENDED
Definition: liblwgeom.h:2067
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
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:789
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:89
char * getSRSbySRID(int srid, bool short_crs)
Definition: lwgeom_export.c:56
Datum geography_from_geometry(PG_FUNCTION_ARGS)
#define LW_GML_IS_DIMS
Macros for specifying GML options.
Definition: liblwgeom.h:1541
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
Datum geography_out(PG_FUNCTION_ARGS)
void lwgeom_parser_result_init(LWGEOM_PARSER_RESULT *parser_result)
Definition: lwin_wkt.c:879
void geography_valid_type(uint8_t type)
The geography type only support POINT, LINESTRING, POLYGON, MULTI* variants of same, and GEOMETRYCOLLECTION.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:84
Datum geography_from_text(PG_FUNCTION_ARGS)
Datum geography_send(PG_FUNCTION_ARGS)
uint8_t type
Definition: liblwgeom.h:398
GSERIALIZED * gserialized_geography_from_lwgeom(LWGEOM *lwgeom, int32 geog_typmod)
type
Definition: ovdump.py:41
Datum geography_from_binary(PG_FUNCTION_ARGS)
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
#define LW_PARSER_CHECK_ALL
Definition: liblwgeom.h:2005
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:770
#define MULTILINETYPE
Definition: liblwgeom.h:88
unsigned char uint8_t
Definition: uthash.h:79
#define COLLECTIONTYPE
Definition: liblwgeom.h:90
This library is the generic geometry handling section of PostGIS.
char * lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix)
Definition: lwout_kml.c:43
#define LW_GML_IS_DEGREE
For GML3 only, declare that datas are lat/lon.
Definition: liblwgeom.h:1543
Datum geography_as_kml(PG_FUNCTION_ARGS)