[postgis-tickets] [SCM] PostGIS branch stable-2.5 updated. 2.5.4-8-g526ba3d
git at osgeo.org
git at osgeo.org
Fri Apr 10 04:28:32 PDT 2020
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".
The branch, stable-2.5 has been updated
via 526ba3d7160b14de18cd3273ccf65263038a3e42 (commit)
from f290e2f63184382038eddbc9577801f98ceef4e6 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 526ba3d7160b14de18cd3273ccf65263038a3e42
Author: Raúl Marín <git at rmr.ninja>
Date: Fri Apr 10 11:47:39 2020 +0200
Fix access to spatial_ref_sys with a non default schema
References #4661
diff --git a/NEWS b/NEWS
index cd7afde..4ab6497 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ PostGIS 2.5.5
* Bug fixes *
- #4652, Fix several memory related bugs in ST_GeomFromGML (Raúl Marín)
+ - #4661, Fix access to spatial_ref_sys with a non default schema (Raúl Marín)
PostGIS 2.5.4
diff --git a/libpgcommon/lwgeom_pg.c b/libpgcommon/lwgeom_pg.c
index a0b20d6..2d1327b 100644
--- a/libpgcommon/lwgeom_pg.c
+++ b/libpgcommon/lwgeom_pg.c
@@ -18,6 +18,7 @@
#include <fmgr.h>
#include <miscadmin.h>
#include <executor/spi.h>
+#include "utils/builtins.h"
#include <utils/guc.h>
#include <utils/guc_tables.h>
@@ -70,6 +71,12 @@ getPostgisConstants(FunctionCallInfo fcinfo)
constants->install_nsp = MemoryContextStrdup(CacheMemoryContext, nsp_name);
elog(DEBUG4, "%s located %s in namespace %s", __func__, get_func_name(fcinfo->flinfo->fn_oid), nsp_name);
+ char *spatial_ref_sys_fullpath = quote_qualified_identifier(nsp_name, "spatial_ref_sys");
+ constants->spatial_ref_sys = MemoryContextStrdup(CacheMemoryContext, spatial_ref_sys_fullpath);
+ elog(DEBUG4, "%s: Spatial ref sys qualified as %s", __func__, spatial_ref_sys_fullpath);
+ pfree(nsp_name);
+ pfree(spatial_ref_sys_fullpath);
+
/* Lookup all the type names in the context of the install schema */
constants->geometry_oid = TypenameNspGetTypid("geometry", nsp_oid);
constants->geography_oid = TypenameNspGetTypid("geography", nsp_oid);
@@ -133,15 +140,20 @@ postgis_oid(postgisType typ)
}
}
-Oid
-postgis_oid_fcinfo(FunctionCallInfo fcinfo, postgisType oid)
+void
+postgis_initialize_cache(FunctionCallInfo fcinfo)
{
/* Cache the info if we don't already have it */
if (!POSTGIS_CONSTANTS)
- POSTGIS_CONSTANTS = getPostgisConstants(fcinfo);;
+ POSTGIS_CONSTANTS = getPostgisConstants(fcinfo);
+}
- if (!POSTGIS_CONSTANTS) return InvalidOid;
- return postgis_oid(oid);
+const char *
+postgis_spatial_ref_sys()
+{
+ if (!POSTGIS_CONSTANTS)
+ return NULL;
+ return POSTGIS_CONSTANTS->spatial_ref_sys;
}
/****************************************************************************************/
diff --git a/libpgcommon/lwgeom_pg.h b/libpgcommon/lwgeom_pg.h
index 8a98d97..35eebce 100644
--- a/libpgcommon/lwgeom_pg.h
+++ b/libpgcommon/lwgeom_pg.h
@@ -62,20 +62,26 @@ typedef struct
Oid raster_oid;
Oid install_nsp_oid;
char *install_nsp;
+ char *spatial_ref_sys;
} postgisConstants;
/* Global to hold all the run-time constants */
extern postgisConstants *POSTGIS_CONSTANTS;
-/* uses the nsp information of the calling function to infer the */
-/* install location of postgis, and thus the namespace to use */
-/* when looking up the type name */
-Oid postgis_oid_fcinfo(FunctionCallInfo fcinfo, postgisType typ);
+/* Infer the install location of postgis, and thus the namespace to use
+ * when looking up the type name, and cache oids */
+void postgis_initialize_cache(FunctionCallInfo fcinfo);
-/* only useful if postgis_oid_fcinfo() has been called first and */
-/* populated first, otherwise returns InvalidOid */
+/* Useful if postgis_initialize_cache() has been called before.
+ * Otherwise it tries to do a bare lookup */
Oid postgis_oid(postgisType typ);
+/* Returns the fully qualified, and properly quoted, identifier of spatial_ref_sys
+ * Note that it's length can be up to strlen(schema) + "." + strlen("spatial_ref_sys") + NULL, i.e: 80 bytes
+ * Only useful if postgis_initialize_cache has been called before. Otherwise returns "spatial_ref_sys"
+ */
+const char *postgis_spatial_ref_sys(void);
+
/****************************************************************************************/
/* Debugging macros */
diff --git a/libpgcommon/lwgeom_transform.c b/libpgcommon/lwgeom_transform.c
index 8e0dd7f..ebdf70a 100644
--- a/libpgcommon/lwgeom_transform.c
+++ b/libpgcommon/lwgeom_transform.c
@@ -34,19 +34,11 @@
#include <errno.h>
-/**
-* Global variable to hold cached information about what
-* schema functions are installed in. Currently used by
-* SetSpatialRefSysSchema and GetProj4StringSPI
-*/
-static char *spatialRefSysSchema = NULL;
-
/* Expose an internal Proj function */
int pj_transform_nodatum(projPJ srcdefn, projPJ dstdefn, long point_count, int point_offset, double *x, double *y, double *z );
-
/*
* PROJ 4 backend hash table initial hash size
* (since 16 is the default portal hash table size, and we would
@@ -345,23 +337,13 @@ char* GetProj4StringSPI(int srid)
elog(ERROR, "GetProj4StringSPI: Could not connect to database using SPI");
}
- /*
- * This global is allocated in CacheMemoryContext (lifespan of this backend)
- * and is set by SetSpatialRefSysSchema the first time
- * that GetProjectionsUsingFCInfo is called.
- */
- if (spatialRefSysSchema)
- {
- /* Format the lookup query */
- static char *proj_str_tmpl = "SELECT proj4text FROM %s.spatial_ref_sys WHERE srid = %d LIMIT 1";
- snprintf(proj4_spi_buffer, 255, proj_str_tmpl, spatialRefSysSchema, srid);
- }
- else
- {
- /* Format the lookup query */
- static char *proj_str_tmpl = "SELECT proj4text FROM spatial_ref_sys WHERE srid = %d LIMIT 1";
- snprintf(proj4_spi_buffer, 255, proj_str_tmpl, srid);
- }
+ static char *proj_str_tmpl =
+ "SELECT proj4text, auth_name, auth_srid, srtext "
+ "FROM %s "
+ "WHERE srid = %d "
+ "LIMIT 1";
+ snprintf(proj4_spi_buffer, 255, proj_str_tmpl, postgis_spatial_ref_sys(), srid);
+
/* Execute the query, noting the readonly status of this SQL */
spi_result = SPI_execute(proj4_spi_buffer, true, 1);
@@ -680,35 +662,6 @@ Proj4Cache GetPROJ4Cache(FunctionCallInfo fcinfo) {
return (Proj4Cache)GetPROJ4SRSCache(fcinfo);
}
-
-/*
-* Given a function call context, figure out what namespace the
-* function is being called from, and copy that into a global
-* for use by GetProj4StringSPI
-*/
-static void
-SetSpatialRefSysSchema(FunctionCallInfo fcinfo)
-{
- char *nsp_name;
- Oid nsp_oid;
-
- /* Schema info is already cached, we're done here */
- if (spatialRefSysSchema) return;
-
- /* For some reason we have a hobbled fcinfo/flinfo */
- if (!fcinfo || !fcinfo->flinfo) return;
-
- nsp_oid = postgis_oid_fcinfo(fcinfo, POSTGISNSPOID);
- if (!nsp_oid) return;
- nsp_name = get_namespace_name(nsp_oid);
- /* early exit if we cannot lookup nsp_name, cf #4067 */
- if (!nsp_name) return;
-
- elog(DEBUG4, "%s located %s in namespace %s", __func__, get_func_name(fcinfo->flinfo->fn_oid), nsp_name);
- spatialRefSysSchema = MemoryContextStrdup(CacheMemoryContext, nsp_name);;
- return;
-}
-
int
GetProjectionsUsingFCInfo(FunctionCallInfo fcinfo, int srid1, int srid2, projPJ *pj1, projPJ *pj2)
{
@@ -718,7 +671,7 @@ GetProjectionsUsingFCInfo(FunctionCallInfo fcinfo, int srid1, int srid2, projPJ
SetPROJ4LibPath();
/* Look up the spatial_ref_sys schema if we haven't already */
- SetSpatialRefSysSchema(fcinfo);
+ postgis_initialize_cache(fcinfo);
/* get or initialize the cache for this round */
proj_cache = GetPROJ4Cache(fcinfo);
diff --git a/postgis/geography_inout.c b/postgis/geography_inout.c
index 298b6df..7c2fbb4 100644
--- a/postgis/geography_inout.c
+++ b/postgis/geography_inout.c
@@ -295,8 +295,10 @@ Datum geography_as_gml(PG_FUNCTION_ARGS)
}
}
- if (option & 1) srs = getSRSbySRID(srid, false);
- else srs = getSRSbySRID(srid, true);
+ if (option & 1)
+ srs = getSRSbySRID(fcinfo, srid, false);
+ else
+ srs = getSRSbySRID(fcinfo, srid, true);
if (!srs)
{
elog(ERROR, "SRID %d unknown in spatial_ref_sys table", SRID_DEFAULT);
@@ -520,8 +522,10 @@ Datum geography_as_geojson(PG_FUNCTION_ARGS)
if (option & 2 || option & 4)
{
/* Geography only handle srid SRID_DEFAULT */
- if (option & 2) srs = getSRSbySRID(SRID_DEFAULT, true);
- if (option & 4) srs = getSRSbySRID(SRID_DEFAULT, false);
+ if (option & 2)
+ srs = getSRSbySRID(fcinfo, SRID_DEFAULT, true);
+ if (option & 4)
+ srs = getSRSbySRID(fcinfo, SRID_DEFAULT, false);
if (!srs)
{
diff --git a/postgis/gserialized_spgist_2d.c b/postgis/gserialized_spgist_2d.c
index 3d191bb..4967dc6 100644
--- a/postgis/gserialized_spgist_2d.c
+++ b/postgis/gserialized_spgist_2d.c
@@ -289,8 +289,10 @@ PG_FUNCTION_INFO_V1(gserialized_spgist_config_2d);
PGDLLEXPORT Datum gserialized_spgist_config_2d(PG_FUNCTION_ARGS)
{
spgConfigOut *cfg = (spgConfigOut *)PG_GETARG_POINTER(1);
+ Oid boxoid = InvalidOid;
+ postgis_initialize_cache(fcinfo);
+ boxoid = postgis_oid(BOX2DFOID);
- Oid boxoid = postgis_oid_fcinfo(fcinfo, BOX2DFOID);
cfg->prefixType = boxoid;
cfg->labelType = VOIDOID; /* We don't need node labels. */
cfg->leafType = boxoid;
diff --git a/postgis/gserialized_spgist_3d.c b/postgis/gserialized_spgist_3d.c
index d11c291..b417baa 100644
--- a/postgis/gserialized_spgist_3d.c
+++ b/postgis/gserialized_spgist_3d.c
@@ -373,7 +373,10 @@ PGDLLEXPORT Datum gserialized_spgist_config_3d(PG_FUNCTION_ARGS)
{
spgConfigOut *cfg = (spgConfigOut *)PG_GETARG_POINTER(1);
- Oid boxoid = postgis_oid_fcinfo(fcinfo, BOX3DOID);
+ Oid boxoid = InvalidOid;
+ postgis_initialize_cache(fcinfo);
+ boxoid = postgis_oid(BOX3DOID);
+
cfg->prefixType = boxoid;
cfg->labelType = VOIDOID; /* We don't need node labels. */
cfg->leafType = boxoid;
diff --git a/postgis/lwgeom_export.c b/postgis/lwgeom_export.c
index 4bc16fa..1166647 100644
--- a/postgis/lwgeom_export.c
+++ b/postgis/lwgeom_export.c
@@ -55,11 +55,15 @@ Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS);
* Could return SRS as short one (i.e EPSG:4326)
* or as long one: (i.e urn:ogc:def:crs:EPSG::4326)
*/
-char * getSRSbySRID(int srid, bool short_crs)
+
+char *
+getSRSbySRID(FunctionCallInfo fcinfo, int srid, bool short_crs)
{
- char query[256];
+ 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 ())
{
@@ -69,11 +73,19 @@ char * getSRSbySRID(int srid, bool short_crs)
}
if (short_crs)
- snprintf(query, 256, "SELECT auth_name||':'||auth_srid \
- FROM spatial_ref_sys WHERE srid='%d'", srid);
+ snprintf(query,
+ max_query_size,
+ "SELECT auth_name||':'||auth_srid \
+ FROM %s WHERE srid='%d'",
+ postgis_spatial_ref_sys(),
+ srid);
else
- snprintf(query, 256, "SELECT 'urn:ogc:def:crs:'||auth_name||'::'||auth_srid \
- FROM spatial_ref_sys WHERE srid='%d'", srid);
+ 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 )
@@ -117,17 +129,24 @@ char * getSRSbySRID(int srid, bool short_crs)
* Require valid spatial_ref_sys table entry
*
*/
-int getSRIDbySRS(const char* srs)
+int
+getSRIDbySRS(FunctionCallInfo fcinfo, const char *srs)
{
- char *query =
- "SELECT srid "
- "FROM spatial_ref_sys, "
- "regexp_matches($1::text, E'([a-z]+):([0-9]+)', 'gi') AS re "
- "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid";
+ static const int16_t max_query_size = 512;
+ char query[512];
Oid argtypes[] = {CSTRINGOID};
Datum values[] = {CStringGetDatum(srs)};
int32_t srid, err;
+ postgis_initialize_cache(fcinfo);
+ snprintf(query,
+ max_query_size,
+ "SELECT srid "
+ "FROM %s, "
+ "regexp_matches($1::text, E'([a-z]+):([0-9]+)', 'gi') AS re "
+ "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid",
+ postgis_spatial_ref_sys());
+
if (!srs) return 0;
if (SPI_OK_CONNECT != SPI_connect())
@@ -147,11 +166,13 @@ int getSRIDbySRS(const char* srs)
/* no entry in spatial_ref_sys */
if (SPI_processed <= 0)
{
- query =
- "SELECT srid "
- "FROM spatial_ref_sys, "
- "regexp_matches($1::text, E'urn:ogc:def:crs:([a-z]+):.*:([0-9]+)', 'gi') AS re "
- "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid";
+ snprintf(query,
+ max_query_size,
+ "SELECT srid "
+ "FROM %s, "
+ "regexp_matches($1::text, E'urn:ogc:def:crs:([a-z]+):.*:([0-9]+)', 'gi') AS re "
+ "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid",
+ postgis_spatial_ref_sys());
err = SPI_execute_with_args(query, 1, argtypes, values, NULL, true, 1);
if (err < 0)
@@ -264,8 +285,10 @@ Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
srid = gserialized_get_srid(geom);
if (srid == SRID_UNKNOWN) srs = NULL;
- else if (option & 1) srs = getSRSbySRID(srid, false);
- else srs = getSRSbySRID(srid, true);
+ else if (option & 1)
+ srs = getSRSbySRID(fcinfo, srid, false);
+ else
+ srs = getSRSbySRID(fcinfo, srid, true);
if (option & 2) lwopts &= ~LW_GML_IS_DIMS;
if (option & 4) lwopts |= LW_GML_SHORTLINE;
@@ -458,10 +481,10 @@ Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
if ( srid != SRID_UNKNOWN )
{
if ( option & 2 )
- srs = getSRSbySRID(srid, true);
+ srs = getSRSbySRID(fcinfo, srid, true);
if ( option & 4 )
- srs = getSRSbySRID(srid, false);
+ srs = getSRSbySRID(fcinfo, srid, false);
if ( !srs )
{
@@ -603,8 +626,10 @@ Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
lwgeom = lwgeom_from_gserialized(geom);
srid = gserialized_get_srid(geom);
if (srid == SRID_UNKNOWN) srs = NULL;
- else if (option & 1) srs = getSRSbySRID(srid, false);
- else srs = getSRSbySRID(srid, true);
+ else if (option & 1)
+ srs = getSRSbySRID(fcinfo, srid, false);
+ else
+ srs = getSRSbySRID(fcinfo, srid, true);
if (option & LW_X3D_USE_GEOCOORDS) {
if (srid != 4326) {
diff --git a/postgis/lwgeom_export.h b/postgis/lwgeom_export.h
index e9652a0..25eaa60 100644
--- a/postgis/lwgeom_export.h
+++ b/postgis/lwgeom_export.h
@@ -23,5 +23,5 @@
**********************************************************************/
-char * getSRSbySRID(int SRID, bool short_crs);
-int getSRIDbySRS(const char* SRS);
+char * getSRSbySRID(FunctionCallInfo fcinfo, int SRID, bool short_crs);
+int getSRIDbySRS(FunctionCallInfo fcinfo, const char* SRS);
diff --git a/postgis/lwgeom_in_geojson.c b/postgis/lwgeom_in_geojson.c
index eb6ec0c..12c0747 100644
--- a/postgis/lwgeom_in_geojson.c
+++ b/postgis/lwgeom_in_geojson.c
@@ -112,7 +112,7 @@ Datum geom_from_geojson(PG_FUNCTION_ARGS)
if ( srs )
{
- lwgeom_set_srid(lwgeom, getSRIDbySRS(srs));
+ lwgeom_set_srid(lwgeom, getSRIDbySRS(fcinfo, srs));
lwfree(srs);
}
diff --git a/postgis/lwgeom_in_gml.c b/postgis/lwgeom_in_gml.c
index eed2881..b4e8dee 100644
--- a/postgis/lwgeom_in_gml.c
+++ b/postgis/lwgeom_in_gml.c
@@ -112,7 +112,13 @@ Datum geom_from_gml(PG_FUNCTION_ARGS)
/* Zero for undefined */
root_srid = PG_GETARG_INT32(1);
+ /* Internally lwgeom_from_gml calls gml_reproject_pa which, for PROJ before 6, called GetProj4String.
+ * That function requires access to spatial_ref_sys, so in order to have it ready we need to ensure
+ * the internal cache is initialized
+ */
+ postgis_initialize_cache(fcinfo);
lwgeom = lwgeom_from_gml(xml);
+
if ( root_srid != SRID_UNKNOWN )
lwgeom->srid = root_srid;
-----------------------------------------------------------------------
Summary of changes:
NEWS | 1 +
libpgcommon/lwgeom_pg.c | 22 ++++++++++---
libpgcommon/lwgeom_pg.h | 18 +++++++----
libpgcommon/lwgeom_transform.c | 63 +++++-------------------------------
postgis/geography_inout.c | 12 ++++---
postgis/gserialized_spgist_2d.c | 4 ++-
postgis/gserialized_spgist_3d.c | 5 ++-
postgis/lwgeom_export.c | 71 ++++++++++++++++++++++++++++-------------
postgis/lwgeom_export.h | 4 +--
postgis/lwgeom_in_geojson.c | 2 +-
postgis/lwgeom_in_gml.c | 6 ++++
11 files changed, 110 insertions(+), 98 deletions(-)
hooks/post-receive
--
PostGIS
More information about the postgis-tickets
mailing list