27 #include "../postgis_config.h"
35 #include "access/gist.h"
36 #include "access/itup.h"
39 #include "utils/elog.h"
40 #include "mb/pg_wchar.h"
41 #include "lib/stringinfo.h"
42 #include "utils/array.h"
43 #include "utils/builtins.h"
44 #include "utils/lsyscache.h"
48 #include "lwgeom_pg.h"
50 #include "lwgeom_transform.h"
53 #include "access/htup_details.h"
86 char *input = PG_GETARG_CSTRING(0);
87 int32 geom_typmod = -1;
94 if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) {
95 geom_typmod = PG_GETARG_INT32(2);
101 if (
str[0] ==
'\0' ) {
102 ereport(ERROR,(errmsg(
"parse error - invalid geometry")));
107 if( strncasecmp(
str,
"SRID=",5) == 0 )
111 while ( tmp && *tmp !=
';' )
115 if ( tmp && *(tmp+1) ==
'0' )
131 size_t hexsize = strlen(
str);
136 if ( !lwgeom ) PG_RETURN_NULL();
150 PG_PARSER_ERROR(lwg_parser_result);
153 lwgeom = lwg_parser_result.
geom;
160 if ( geom_typmod >= 0 )
163 POSTGIS_DEBUG(3,
"typmod and geometry were consistent");
167 POSTGIS_DEBUG(3,
"typmod was -1");
173 PG_RETURN_POINTER(ret);
203 GSERIALIZED *pg_lwgeom = PG_GETARG_GSERIALIZED_P(0);
204 text *format_text = PG_GETARG_TEXT_P(1);
207 char *format_str = NULL;
209 char * formatted_str;
210 text * formatted_text;
217 lwpgerror(
"Only points are supported, you tried type %s.",
lwtype_name(geom_type));
222 if (format_text == NULL) {
223 lwpgerror(
"ST_AsLatLonText: invalid format string (null");
228 lwpgerror(
"ST_AsLatLonText: invalid coordinate");
233 assert(format_str != NULL);
237 tmp = (
char *)pg_do_encoding_conversion(
238 (uint8_t *)format_str, strlen(format_str), GetDatabaseEncoding(), PG_UTF8);
240 if ( tmp != format_str ) {
247 assert(formatted_str != NULL);
251 tmp = (
char *)pg_do_encoding_conversion(
252 (uint8_t *)formatted_str, strlen(formatted_str),
253 PG_UTF8, GetDatabaseEncoding());
255 if ( tmp != formatted_str) {
256 pfree(formatted_str);
261 formatted_text = cstring_to_text(formatted_str);
262 pfree(formatted_str);
264 PG_RETURN_POINTER(formatted_text);
286 PG_RETURN_CSTRING(hexwkb);
305 if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) )
307 type = PG_GETARG_TEXT_P(1);
309 if ( ! strncmp(VARDATA(
type),
"xdr", 3) ||
310 ! strncmp(VARDATA(
type),
"XDR", 3) )
326 text_size = hexwkb_size - 1 + VARHDRSZ;
327 result = palloc(text_size);
328 memcpy(VARDATA(result), hexwkb, hexwkb_size - 1);
329 SET_VARSIZE(result, text_size);
333 PG_FREE_IF_COPY(geom, 0);
334 PG_RETURN_TEXT_P(result);
360 result = cstring_to_text(hexwkb);
364 PG_FREE_IF_COPY(geom, 0);
365 PG_RETURN_TEXT_P(result);
378 bytea *bytea_wkb = PG_GETARG_BYTEA_P(0);
381 uint8_t *wkb = (uint8_t*)VARDATA(bytea_wkb);
385 lwpgerror(
"Unable to parse WKB");
387 if ((PG_NARGS() > 1) && (!PG_ARGISNULL(1)))
389 int32 srid = PG_GETARG_INT32(1);
398 PG_FREE_IF_COPY(bytea_wkb, 0);
399 PG_RETURN_POINTER(geom);
409 bytea *bytea_twkb = PG_GETARG_BYTEA_P(0);
412 uint8_t *twkb = (uint8_t*)VARDATA(bytea_twkb);
421 PG_FREE_IF_COPY(bytea_twkb, 0);
422 PG_RETURN_POINTER(geom);
440 if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) )
442 type = PG_GETARG_TEXT_P(1);
444 if ( ! strncmp(VARDATA(
type),
"xdr", 3) ||
445 ! strncmp(VARDATA(
type),
"XDR", 3) )
454 wkb_size= VARSIZE_ANY_EXHDR(geom);
462 result = palloc(wkb_size + VARHDRSZ);
463 memcpy(VARDATA(result), wkb, wkb_size);
464 SET_VARSIZE(result, wkb_size+VARHDRSZ);
468 PG_FREE_IF_COPY(geom, 0);
469 PG_RETURN_BYTEA_P(result);
485 if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
487 geom = PG_GETARG_GSERIALIZED_P(0);
493 if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
494 sp.precision_xy = PG_GETARG_INT32(1);
497 if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
498 sp.precision_z = PG_GETARG_INT32(2);
501 if ( PG_NARGS() > 3 && ! PG_ARGISNULL(3) )
502 sp.precision_m = PG_GETARG_INT32(3);
508 if ( PG_NARGS() > 4 && ! PG_ARGISNULL(4) && PG_GETARG_BOOL(4) )
512 if ( PG_NARGS() > 5 && ! PG_ARGISNULL(5) && PG_GETARG_BOOL(5) )
520 result = palloc(twkb_size + VARHDRSZ);
521 memcpy(VARDATA(result), twkb, twkb_size);
522 SET_VARSIZE(result, twkb_size + VARHDRSZ);
524 PG_RETURN_BYTEA_P(result);
531 ArrayType *arr_geoms = NULL;
532 ArrayType *arr_ids = NULL;
533 int num_geoms, num_ids, i = 0;
535 ArrayIterator iter_geoms, iter_ids;
536 bool null_geom, null_id;
537 Datum val_geom, val_id;
539 int is_homogeneous =
true;
540 uint32_t subtype = 0;
544 int64_t *idlist = NULL;
553 if ( PG_NARGS() < 2 || PG_ARGISNULL(0) || PG_ARGISNULL(1) )
556 arr_geoms = PG_GETARG_ARRAYTYPE_P(0);
557 arr_ids = PG_GETARG_ARRAYTYPE_P(1);
559 num_geoms = ArrayGetNItems(ARR_NDIM(arr_geoms), ARR_DIMS(arr_geoms));
560 num_ids = ArrayGetNItems(ARR_NDIM(arr_ids), ARR_DIMS(arr_ids));
562 if ( num_geoms != num_ids )
564 elog(ERROR,
"size of geometry[] and integer[] arrays must match");
571 iter_geoms = array_create_iterator(arr_geoms, 0, NULL);
572 iter_ids = array_create_iterator(arr_ids, 0, NULL);
574 while( array_iterate(iter_geoms, &val_geom, &null_geom) &&
575 array_iterate(iter_ids, &val_id, &null_id) )
580 if ( null_geom || null_id )
582 elog(NOTICE,
"ST_AsTWKB skipping NULL entry at position %d", i);
587 uid = DatumGetInt64(val_id);
597 idlist = palloc0(num_geoms *
sizeof(int64_t));
603 elog(ERROR,
"Geometries have different dimensionality");
604 PG_FREE_IF_COPY(arr_geoms, 0);
605 PG_FREE_IF_COPY(arr_ids, 1);
616 is_homogeneous =
false;
624 array_free_iterator(iter_geoms);
625 array_free_iterator(iter_ids);
629 elog(NOTICE,
"No valid geometry - id pairs found");
630 PG_FREE_IF_COPY(arr_geoms, 0);
631 PG_FREE_IF_COPY(arr_ids, 1);
634 if ( is_homogeneous )
643 if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
644 sp.precision_xy = PG_GETARG_INT32(2);
647 if ( PG_NARGS() > 3 && ! PG_ARGISNULL(3) )
648 sp.precision_z = PG_GETARG_INT32(3);
651 if ( PG_NARGS() > 4 && ! PG_ARGISNULL(4) )
652 sp.precision_m = PG_GETARG_INT32(4);
658 if ( PG_NARGS() > 5 && ! PG_ARGISNULL(5) && PG_GETARG_BOOL(5) )
662 if ( PG_NARGS() > 6 && ! PG_ARGISNULL(6) && PG_GETARG_BOOL(6) )
668 sp.precision_xy, sp.precision_z, sp.precision_m,
672 result = palloc(twkb_size + VARHDRSZ);
673 memcpy(VARDATA(result), twkb, twkb_size);
674 SET_VARSIZE(result, twkb_size + VARHDRSZ);
680 PG_FREE_IF_COPY(arr_geoms, 0);
681 PG_FREE_IF_COPY(arr_ids, 1);
683 PG_RETURN_BYTEA_P(result);
699 PG_FREE_IF_COPY(geom, 0);
700 PG_RETURN_POINTER(result);
711 PG_RETURN_POINTER(geom);
720 elog(ERROR,
"%s",
string);
732 text *wkt_text = PG_GETARG_TEXT_P(0);
740 result = DirectFunctionCall1(
LWGEOM_in, CStringGetDatum(wkt));
746 PG_RETURN_DATUM(result);
760 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
761 int32 geom_typmod = -1;
765 if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) {
766 geom_typmod = PG_GETARG_INT32(2);
772 ereport(ERROR,(errmsg(
"recv error - invalid geometry")));
780 buf->cursor = buf->len;
785 if ( geom_typmod >= 0 )
788 POSTGIS_DEBUG(3,
"typmod and geometry were consistent");
792 POSTGIS_DEBUG(3,
"typmod was -1");
796 PG_RETURN_POINTER(geom);
804 POSTGIS_DEBUG(2,
"LWGEOM_send called");
817 POSTGIS_DEBUG(2,
"LWGEOM_to_bytea called");
832 POSTGIS_DEBUG(2,
"LWGEOM_from_bytea start");
834 result = (
GSERIALIZED *)DatumGetPointer(DirectFunctionCall1(
837 PG_RETURN_POINTER(result);
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...
int gserialized_has_bbox(const GSERIALIZED *g)
Check if a GSERIALIZED has a bounding box without deserializing first.
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.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
GSERIALIZED * gserialized_drop_gbox(GSERIALIZED *g)
Remove the bounding box from a GSERIALIZED.
#define LW_PARSER_CHECK_ALL
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
uint32_t lwtype_get_collectiontype(uint8_t type)
Given an lwtype number, what homogeneous collection can hold it?
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
uint8_t * lwgeom_to_twkb_with_idlist(const LWGEOM *geom, int64_t *idlist, uint8_t variant, int8_t precision_xy, int8_t precision_z, int8_t precision_m, size_t *twkb_size)
Convert LWGEOM to a char* in TWKB format.
void lwgeom_set_srid(LWGEOM *geom, int32_t srid)
Set the SRID on an LWGEOM For collections, only the parent gets an SRID, all the children get SRID_UN...
void lwgeom_free(LWGEOM *geom)
#define LW_PARSER_CHECK_NONE
LWGEOM * lwgeom_from_twkb(const uint8_t *twkb, size_t twkb_size, char check)
WKB inputs must have a declared size, to prevent malformed WKB from reading off the end of the memory...
void lwgeom_parser_result_init(LWGEOM_PARSER_RESULT *parser_result)
int lwgeom_parse_wkt(LWGEOM_PARSER_RESULT *parser_result, char *wktstr, int parse_flags)
Parse a WKT geometry string into an LWGEOM structure.
uint8_t * lwgeom_to_wkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
Convert LWGEOM to a char* in WKB format.
uint8_t * bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
int lwgeom_needs_bbox(const LWGEOM *geom)
Check whether or not a lwgeom is big enough to warrant a bounding box.
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
int lwgeom_isfinite(const LWGEOM *lwgeom)
Check if a LWGEOM has any non-finite (NaN or Inf) coordinates.
char * lwgeom_to_hexwkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
char * lwpoint_to_latlon(const LWPOINT *p, const char *format)
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
void lwcollection_free(LWCOLLECTION *col)
#define TWKB_DEFAULT_PRECISION
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
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...
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
void lwgeom_parser_result_free(LWGEOM_PARSER_RESULT *parser_result)
uint8_t * lwgeom_to_twkb(const LWGEOM *geom, uint8_t variant, int8_t precision_xy, int8_t precision_z, int8_t precision_m, size_t *twkb_size)
This library is the generic geometry handling section of PostGIS.
Datum WKBFromLWGEOM(PG_FUNCTION_ARGS)
Datum parse_WKT_lwgeom(PG_FUNCTION_ARGS)
Datum TWKBFromLWGEOM(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(LWGEOM_in)
Datum LWGEOM_in(PG_FUNCTION_ARGS)
Datum LWGEOM_to_latlon(PG_FUNCTION_ARGS)
Datum LWGEOM_out(PG_FUNCTION_ARGS)
Datum LWGEOM_to_bytea(PG_FUNCTION_ARGS)
Datum LWGEOMFromTWKB(PG_FUNCTION_ARGS)
Datum LWGEOM_from_bytea(PG_FUNCTION_ARGS)
Datum TWKBFromLWGEOMArray(PG_FUNCTION_ARGS)
Datum LWGEOM_send(PG_FUNCTION_ARGS)
Datum LWGEOM_dropBBOX(PG_FUNCTION_ARGS)
Datum LWGEOM_to_text(PG_FUNCTION_ARGS)
Datum LWGEOMFromEWKB(PG_FUNCTION_ARGS)
Datum LWGEOM_addBBOX(PG_FUNCTION_ARGS)
void elog_ERROR(const char *string)
Datum LWGEOM_asHEXEWKB(PG_FUNCTION_ARGS)
Datum LWGEOM_recv(PG_FUNCTION_ARGS)
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
char * text_to_cstring(const text *textptr)
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
Parser result structure: returns the result of attempting to convert (E)WKT/(E)WKB to LWGEOM.