Datum geography_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); int32 geog_typmod = -1; LWGEOM *lwgeom = NULL; GSERIALIZED *g_ser = NULL; if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) { geog_typmod = PG_GETARG_INT32(2); } lwgeom = lwgeom_from_wkb((uint8_t*)buf->data, buf->len, LW_PARSER_CHECK_ALL); /* Error on any SRID != default */ srid_is_latlong(fcinfo, lwgeom->srid); g_ser = gserialized_geography_from_lwgeom(lwgeom, geog_typmod); /* Clean up temporary object */ lwgeom_free(lwgeom); /* Set cursor to the end of buffer (so the backend is happy) */ buf->cursor = buf->len; PG_RETURN_POINTER(g_ser); }
Datum geography_typmod_in(PG_FUNCTION_ARGS) { ArrayType *arr = (ArrayType *) DatumGetPointer(PG_GETARG_DATUM(0)); uint32 typmod = gserialized_typmod_in(arr, LW_TRUE); int srid = TYPMOD_GET_SRID(typmod); /* Check the SRID is legal (geographic coordinates) */ srid_is_latlong(fcinfo, srid); PG_RETURN_INT32(typmod); }
Datum geography_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); /* Datum geog_oid = PG_GETARG_OID(1); Not needed. */ int32 geog_typmod = -1; LWGEOM_PARSER_RESULT lwg_parser_result; LWGEOM *lwgeom = NULL; GSERIALIZED *g_ser = NULL; if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) { geog_typmod = PG_GETARG_INT32(2); } lwgeom_parser_result_init(&lwg_parser_result); /* Empty string. */ if ( str[0] == '\0' ) ereport(ERROR,(errmsg("parse error - invalid geometry"))); /* WKB? Let's find out. */ if ( str[0] == '0' ) { /* TODO: 20101206: No parser checks! This is inline with current 1.5 behavior, but needs discussion */ lwgeom = lwgeom_from_hexwkb(str, LW_PARSER_CHECK_NONE); /* Error out if something went sideways */ if ( ! lwgeom ) ereport(ERROR,(errmsg("parse error - invalid geometry"))); } /* WKT then. */ else { if ( lwgeom_parse_wkt(&lwg_parser_result, str, LW_PARSER_CHECK_ALL) == LW_FAILURE ) PG_PARSER_ERROR(lwg_parser_result); lwgeom = lwg_parser_result.geom; } /* Error on any SRID != default */ srid_is_latlong(fcinfo, lwgeom->srid); /* Convert to gserialized */ g_ser = gserialized_geography_from_lwgeom(lwgeom, geog_typmod); /* Clean up temporary object */ lwgeom_free(lwgeom); PG_RETURN_POINTER(g_ser); }
Datum geography_from_geometry(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); LWGEOM *lwgeom = NULL; GSERIALIZED *g_ser = NULL; geography_valid_type(gserialized_get_type(geom)); lwgeom = lwgeom_from_gserialized(geom); /* Force default SRID */ if ( (int)lwgeom->srid <= 0 ) { lwgeom->srid = SRID_DEFAULT; } /* Error on any SRID != default */ srid_is_latlong(fcinfo, lwgeom->srid); /* Check if the geography has valid coordinate range. */ if ( lwgeom_check_geodetic(lwgeom) == LW_FALSE ) { if ( (! lwgeom_nudge_geodetic(lwgeom)) || lwgeom_check_geodetic(lwgeom) == LW_FALSE ) { ereport(ERROR, ( errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Coordinate values are out of range [-180 -90, 180 90] for GEOGRAPHY type" ))); } } /* ** Serialize our lwgeom and set the geodetic flag so subsequent ** functions do the right thing. */ lwgeom_set_geodetic(lwgeom, true); /* Recalculate the boxes after re-setting the geodetic bit */ lwgeom_drop_bbox(lwgeom); lwgeom_add_bbox(lwgeom); g_ser = geography_serialize(lwgeom); /* ** Replace the unaligned lwgeom with a new aligned one based on GSERIALIZED. */ lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(g_ser); }
Datum geography_from_geometry(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)); LWGEOM *lwgeom = NULL; GSERIALIZED *g_ser = NULL; geography_valid_type(gserialized_get_type(geom)); lwgeom = lwgeom_from_gserialized(geom); /* Force default SRID */ if ( (int)lwgeom->srid <= 0 ) { lwgeom->srid = SRID_DEFAULT; } /* Error on any SRID != default */ srid_is_latlong(fcinfo, lwgeom->srid); /* Force the geometry to have valid geodetic coordinate range. */ lwgeom_nudge_geodetic(lwgeom); if ( lwgeom_force_geodetic(lwgeom) == LW_TRUE ) { ereport(NOTICE, ( errmsg_internal("Coordinate values were coerced into range [-180 -90, 180 90] for GEOGRAPHY" )) ); } /* ** Serialize our lwgeom and set the geodetic flag so subsequent ** functions do the right thing. */ lwgeom_set_geodetic(lwgeom, true); /* Recalculate the boxes after re-setting the geodetic bit */ lwgeom_drop_bbox(lwgeom); lwgeom_add_bbox(lwgeom); g_ser = geography_serialize(lwgeom); /* ** Replace the unaligned lwgeom with a new aligned one based on GSERIALIZED. */ lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(g_ser); }