Commit b38079d4 authored by Raúl Marín's avatar Raúl Marín

Cache getSRSbySRID

parent 3ced96fc
......@@ -1699,8 +1699,8 @@ extern lwvarlena_t* lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, i
extern lwvarlena_t* lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix);
extern lwvarlena_t* lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id);
extern lwvarlena_t* lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix);
extern lwvarlena_t* lwgeom_to_geojson(const LWGEOM *geo, char *srs, int precision, int has_bbox);
extern lwvarlena_t* lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid);
extern lwvarlena_t* lwgeom_to_geojson(const LWGEOM *geo, const char *srs, int precision, int has_bbox);
extern lwvarlena_t* lwgeom_to_x3d3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *defid);
extern lwvarlena_t* lwgeom_to_svg(const LWGEOM *geom, int precision, int relative);
extern lwvarlena_t* lwgeom_to_encoded_polyline(const LWGEOM *geom, int precision);
......
This diff is collapsed.
......@@ -34,7 +34,7 @@
*/
/* takes a GEOMETRY and returns a X3D representation */
lwvarlena_t *
lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid)
lwgeom_to_x3d3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *defid)
{
stringbuffer_t *sb;
int rv;
......@@ -63,7 +63,7 @@ lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const cha
}
/* takes a GEOMETRY and appends to string buffer the x3d output */
static int
lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
lwgeom_to_x3d3_sb(const LWGEOM *geom, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
{
int type = geom->type;
......@@ -110,7 +110,7 @@ lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const
}
static int
asx3d3_point_sb(const LWPOINT *point, __attribute__((__unused__)) char *srs, int precision,
asx3d3_point_sb(const LWPOINT *point, __attribute__((__unused__)) const char *srs, int precision,
int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
{
/** for point we just output the coordinates **/
......@@ -215,7 +215,7 @@ asx3d3_mpoly_coordindex_sb(const LWMPOLY *psur, stringbuffer_t *sb)
/** Return the linestring as an X3D LineSet */
static int
asx3d3_line_sb(const LWLINE *line, __attribute__((__unused__)) char *srs, int precision,
asx3d3_line_sb(const LWLINE *line, __attribute__((__unused__)) const char *srs, int precision,
int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
{
......@@ -242,7 +242,7 @@ asx3d3_line_sb(const LWLINE *line, __attribute__((__unused__)) char *srs, int pr
/** Compute the X3D coordinates of the polygon and add to string buffer **/
static int
asx3d3_poly_sb(const LWPOLY *poly, __attribute__((__unused__)) char *srs, int precision,
asx3d3_poly_sb(const LWPOLY *poly, __attribute__((__unused__)) const char *srs, int precision,
int opts, __attribute__((__unused__)) int is_patch, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
{
uint32_t i;
......@@ -255,7 +255,7 @@ asx3d3_poly_sb(const LWPOLY *poly, __attribute__((__unused__)) char *srs, int p
}
static int
asx3d3_triangle_sb(const LWTRIANGLE *triangle, __attribute__((__unused__)) char *srs, int precision,
asx3d3_triangle_sb(const LWTRIANGLE *triangle, __attribute__((__unused__)) const char *srs, int precision,
int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
{
return ptarray_to_x3d3_sb(triangle->points, precision, opts, 1, sb);
......@@ -266,7 +266,7 @@ asx3d3_triangle_sb(const LWTRIANGLE *triangle, __attribute__((__unused__)) char
* Don't call this with single-geoms inspected!
*/
static int
asx3d3_multi_sb(const LWCOLLECTION *col, __attribute__((__unused__)) char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
asx3d3_multi_sb(const LWCOLLECTION *col, __attribute__((__unused__)) const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
{
char *x3dtype;
uint32_t i;
......@@ -345,7 +345,7 @@ asx3d3_multi_sb(const LWCOLLECTION *col, __attribute__((__unused__)) char *srs,
* Don't call this with single-geoms inspected!
*/
static int
asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
asx3d3_psurface_sb(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
{
uint32_t i;
uint32_t j;
......@@ -398,7 +398,7 @@ asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, c
* Computes X3D representation of TIN (as IndexedTriangleSet and adds to string buffer)
*/
static int
asx3d3_tin_sb(const LWTIN *tin, __attribute__((__unused__)) char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
asx3d3_tin_sb(const LWTIN *tin, __attribute__((__unused__)) const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
{
uint32_t i;
uint32_t k;
......@@ -436,7 +436,7 @@ asx3d3_tin_sb(const LWTIN *tin, __attribute__((__unused__)) char *srs, int prec
}
static int
asx3d3_collection_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
asx3d3_collection_sb(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
{
uint32_t i;
LWGEOM *subgeom;
......
......@@ -31,16 +31,16 @@
#include "stringbuffer.h"
/** defid is the id of the coordinate can be used to hold other elements DEF='abc' transform='' etc. **/
static int lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int lwgeom_to_x3d3_sb(const LWGEOM *geom, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_point_sb(const LWPOINT *point, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_line_sb(const LWLINE *line, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_point_sb(const LWPOINT *point, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_line_sb(const LWLINE *line, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_triangle_sb(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_triangle_sb(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_multi_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_tin_sb(const LWTIN *tin, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_multi_sb(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_psurface_sb(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_tin_sb(const LWTIN *tin, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_collection_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int asx3d3_collection_sb(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb);
static int ptarray_to_x3d3_sb(POINTARRAY *pa, int precision, int opts, int is_closed, stringbuffer_t *sb );
......@@ -333,3 +333,109 @@ ToastCacheGetGeometry(FunctionCallInfo fcinfo, uint32_t argnum)
return (GSERIALIZED*)PG_DETOAST_DATUM(datum);
}
}
/*
* Retrieve an SRS from a given SRID
* Require valid spatial_ref_sys table entry
*
* Could return SRS as short one (i.e EPSG:4326)
* or as long one: (i.e urn:ogc:def:crs:EPSG::4326)
*/
static char *
getSRSbySRID(FunctionCallInfo fcinfo, int32_t srid, bool short_crs)
{
static const uint16_t max_query_size = 512;
char query[512];
char *srs, *srscopy;
int size, err;
postgis_initialize_cache(fcinfo);
if (SPI_OK_CONNECT != SPI_connect())
{
elog(NOTICE, "%s: could not connect to SPI manager", __func__);
SPI_finish();
return NULL;
}
if (short_crs)
snprintf(query,
max_query_size,
"SELECT auth_name||':'||auth_srid \
FROM %s WHERE srid='%d'",
postgis_spatial_ref_sys(),
srid);
else
snprintf(query,
max_query_size,
"SELECT 'urn:ogc:def:crs:'||auth_name||'::'||auth_srid \
FROM %s WHERE srid='%d'",
postgis_spatial_ref_sys(),
srid);
err = SPI_exec(query, 1);
if (err < 0)
{
elog(NOTICE, "%s: error executing query %d", __func__, err);
SPI_finish();
return NULL;
}
/* no entry in spatial_ref_sys */
if (SPI_processed <= 0)
{
SPI_finish();
return NULL;
}
/* get result */
srs = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
/* NULL result */
if (!srs)
{
SPI_finish();
return NULL;
}
size = strlen(srs) + 1;
srscopy = MemoryContextAllocZero(PostgisCacheContext(fcinfo), size);
memcpy(srscopy, srs, size);
/* disconnect from SPI */
SPI_finish();
return srscopy;
}
static inline SRSDescCache *
SRSDescCacheGet(FunctionCallInfo fcinfo)
{
const uint32_t entry_number = SRSDESC_CACHE_ENTRY;
GenericCacheCollection *generic_cache = GetGenericCacheCollection(fcinfo);
SRSDescCache *cache = (SRSDescCache *)(generic_cache->entry[entry_number]);
if (!cache)
{
cache = MemoryContextAllocZero(PostgisCacheContext(fcinfo), sizeof(SRSDescCache));
cache->type = entry_number;
generic_cache->entry[entry_number] = (GenericCache *)cache;
}
return cache;
}
const char *
GetSRSCacheBySRID(FunctionCallInfo fcinfo, int32_t srid, bool short_crs)
{
SRSDescCache *cache = SRSDescCacheGet(fcinfo);
SRSDescCacheArgument *arg = &(cache->arg[0]);
if (arg->srid != srid || arg->short_mode != short_crs || !arg->srs)
{
arg->srid = srid;
arg->short_mode = short_crs;
if (arg->srs)
pfree(arg->srs);
arg->srs = getSRSbySRID(fcinfo, srid, short_crs);
}
return arg->srs;
}
\ No newline at end of file
......@@ -27,6 +27,7 @@
#define CIRC_CACHE_ENTRY 3
#define RECT_CACHE_ENTRY 4
#define TOAST_CACHE_ENTRY 5
#define SRSDESC_CACHE_ENTRY 6
#define NUM_CACHE_ENTRIES 8
......@@ -132,5 +133,20 @@ typedef struct
GSERIALIZED* ToastCacheGetGeometry(FunctionCallInfo fcinfo, uint32_t argnum);
/******************************************************************************/
#define SRSDescCacheSize 1
typedef struct {
int32_t srid;
bool short_mode;
char *srs;
} SRSDescCacheArgument;
typedef struct {
int type;
SRSDescCacheArgument arg[SRSDescCacheSize];
} SRSDescCache;
const char *GetSRSCacheBySRID(FunctionCallInfo fcinfo, int32_t srid, bool short_crs);
#endif /* LWGEOM_CACHE_H_ */
......@@ -39,6 +39,7 @@
#include "catalog/pg_type.h" /* for CSTRINGOID */
#include "liblwgeom.h" /* For standard geometry types. */
#include "lwgeom_cache.h"
#include "lwgeom_pg.h" /* For debugging macros. */
#include "geography.h" /* For utility functions. */
#include "lwgeom_export.h" /* For export functions. */
......@@ -206,7 +207,7 @@ Datum geography_as_gml(PG_FUNCTION_ARGS)
GSERIALIZED *g = NULL;
lwvarlena_t *v;
int version;
char *srs;
const char *srs;
int32_t srid = SRID_DEFAULT;
int precision = DBL_DIG;
int option = 0;
......@@ -283,9 +284,9 @@ Datum geography_as_gml(PG_FUNCTION_ARGS)
}
if (option & 1)
srs = getSRSbySRID(fcinfo, srid, false);
srs = GetSRSCacheBySRID(fcinfo, srid, false);
else
srs = getSRSbySRID(fcinfo, srid, true);
srs = GetSRSCacheBySRID(fcinfo, srid, true);
if (!srs)
{
elog(ERROR, "SRID %d unknown in spatial_ref_sys table", SRID_DEFAULT);
......@@ -397,7 +398,7 @@ Datum geography_as_geojson(PG_FUNCTION_ARGS)
{
lwvarlena_t *geojson;
int has_bbox = 0;
char * srs = NULL;
const char *srs = NULL;
GSERIALIZED *g = PG_GETARG_GSERIALIZED_P(0);
int precision = PG_GETARG_INT32(1);
int option = PG_GETARG_INT32(2);
......@@ -419,9 +420,9 @@ Datum geography_as_geojson(PG_FUNCTION_ARGS)
{
/* Geography only handle srid SRID_DEFAULT */
if (option & 2)
srs = getSRSbySRID(fcinfo, SRID_DEFAULT, true);
srs = GetSRSCacheBySRID(fcinfo, SRID_DEFAULT, true);
if (option & 4)
srs = getSRSbySRID(fcinfo, SRID_DEFAULT, false);
srs = GetSRSCacheBySRID(fcinfo, SRID_DEFAULT, false);
if (!srs)
{
......@@ -435,7 +436,6 @@ Datum geography_as_geojson(PG_FUNCTION_ARGS)
geojson = lwgeom_to_geojson(lwgeom, srs, precision, has_bbox);
lwgeom_free(lwgeom);
PG_FREE_IF_COPY(g, 0);
if (srs) pfree(srs);
PG_RETURN_TEXT_P(geojson);
}
......
......@@ -37,6 +37,7 @@
#include "utils/jsonb.h"
#include "../postgis_config.h"
#include "lwgeom_cache.h"
#include "lwgeom_pg.h"
#include "liblwgeom.h"
#include "lwgeom_export.h"
......@@ -50,81 +51,6 @@ Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS);
Datum geometry_to_json(PG_FUNCTION_ARGS);
Datum geometry_to_jsonb(PG_FUNCTION_ARGS);
/*
* Retrieve an SRS from a given SRID
* Require valid spatial_ref_sys table entry
*
* Could return SRS as short one (i.e EPSG:4326)
* or as long one: (i.e urn:ogc:def:crs:EPSG::4326)
*/
char *
getSRSbySRID(FunctionCallInfo fcinfo, int32_t srid, bool short_crs)
{
static const uint16_t max_query_size = 512;
char query[512];
char *srs, *srscopy;
int size, err;
postgis_initialize_cache(fcinfo);
if (SPI_OK_CONNECT != SPI_connect ())
{
elog(NOTICE, "getSRSbySRID: could not connect to SPI manager");
SPI_finish();
return NULL;
}
if (short_crs)
snprintf(query,
max_query_size,
"SELECT auth_name||':'||auth_srid \
FROM %s WHERE srid='%d'",
postgis_spatial_ref_sys(),
srid);
else
snprintf(query,
max_query_size,
"SELECT 'urn:ogc:def:crs:'||auth_name||'::'||auth_srid \
FROM %s WHERE srid='%d'",
postgis_spatial_ref_sys(),
srid);
err = SPI_exec(query, 1);
if ( err < 0 )
{
elog(NOTICE, "getSRSbySRID: error executing query %d", err);
SPI_finish();
return NULL;
}
/* no entry in spatial_ref_sys */
if (SPI_processed <= 0)
{
SPI_finish();
return NULL;
}
/* get result */
srs = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
/* NULL result */
if ( ! srs )
{
SPI_finish();
return NULL;
}
/* copy result to upper executor context */
size = strlen(srs)+1;
srscopy = SPI_palloc(size);
memcpy(srscopy, srs, size);
/* disconnect from SPI */
SPI_finish();
return srscopy;
}
/*
* Retrieve an SRID from a given SRS
* Require valid spatial_ref_sys table entry
......@@ -207,7 +133,7 @@ Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
LWGEOM *lwgeom;
lwvarlena_t *v = NULL;
int version;
char *srs;
const char *srs;
int32_t srid;
int option = 0;
int lwopts = LW_GML_IS_DIMS;
......@@ -286,9 +212,9 @@ Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
srid = gserialized_get_srid(geom);
if (srid == SRID_UNKNOWN) srs = NULL;
else if (option & 1)
srs = getSRSbySRID(fcinfo, srid, false);
srs = GetSRSCacheBySRID(fcinfo, srid, false);
else
srs = getSRSbySRID(fcinfo, srid, true);
srs = GetSRSCacheBySRID(fcinfo, srid, true);
if (option & 2) lwopts &= ~LW_GML_IS_DIMS;
if (option & 4) lwopts |= LW_GML_SHORTLINE;
......@@ -334,13 +260,12 @@ Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
{
GSERIALIZED *geom;
LWGEOM *lwgeom;
lwvarlena_t *geojson;
int precision = DBL_DIG;
int output_bbox = LW_FALSE;
int output_long_crs = LW_FALSE;
int output_short_crs = LW_FALSE;
int output_guess_short_srid = LW_FALSE;
char *srs = NULL;
const char *srs = NULL;
int32_t srid;
/* Get the geometry */
......@@ -383,7 +308,7 @@ Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
if (srid != SRID_UNKNOWN && (output_short_crs || output_long_crs))
{
srs = getSRSbySRID(fcinfo, srid, !output_long_crs);
srs = GetSRSCacheBySRID(fcinfo, srid, !output_long_crs);
if (!srs)
{
......@@ -393,13 +318,7 @@ Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
}
lwgeom = lwgeom_from_gserialized(geom);
geojson = lwgeom_to_geojson(lwgeom, srs, precision, output_bbox);
lwgeom_free(lwgeom);
if (srs) pfree(srs);
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_TEXT_P(geojson);
PG_RETURN_TEXT_P(lwgeom_to_geojson(lwgeom, srs, precision, output_bbox));
}
......@@ -469,7 +388,7 @@ Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
GSERIALIZED *geom;
LWGEOM *lwgeom;
int version;
char *srs;
const char *srs;
int32_t srid;
int option = 0;
int precision = DBL_DIG;
......@@ -531,9 +450,9 @@ Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
srid = gserialized_get_srid(geom);
if (srid == SRID_UNKNOWN) srs = NULL;
else if (option & 1)
srs = getSRSbySRID(fcinfo, srid, false);
srs = GetSRSCacheBySRID(fcinfo, srid, false);
else
srs = getSRSbySRID(fcinfo, srid, true);
srs = GetSRSCacheBySRID(fcinfo, srid, true);
if (option & LW_X3D_USE_GEOCOORDS) {
if (srid != 4326) {
......
......@@ -22,5 +22,4 @@
*
**********************************************************************/
char *getSRSbySRID(FunctionCallInfo fcinfo, int32_t SRID, bool short_crs);
int getSRIDbySRS(FunctionCallInfo fcinfo, const char *SRS);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment