[postgis-tickets] [SCM] PostGIS branch stable-2.4 updated. 40015c93263fd242ad8661488b315f4aa80a97d6

git at osgeo.org git at osgeo.org
Fri Apr 10 04:30:09 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.4 has been updated
       via  40015c93263fd242ad8661488b315f4aa80a97d6 (commit)
      from  489ca327b8fb2d690cd17bc7becfd32d8cb703bd (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 40015c93263fd242ad8661488b315f4aa80a97d6
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
    
    Closes #4661

diff --git a/NEWS b/NEWS
index dbbb2f7..a67f447 100644
--- a/NEWS
+++ b/NEWS
@@ -24,6 +24,7 @@ XXXX/XX/XX
   - #4621, Prevent stack overflow when parsing WKB (Raúl Marín)
   - #4646, Fix gserialized_cmp incorrect comparison (dkvash)
   - #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.4.8
diff --git a/libpgcommon/lwgeom_pg.c b/libpgcommon/lwgeom_pg.c
index ccdac1a..b25c997 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>
 
@@ -104,6 +105,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);
@@ -167,15 +174,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 6d1b43b..a392f83 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 7982f45..16376d6 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);
 
@@ -679,36 +661,6 @@ Proj4Cache GetPROJ4Cache(FunctionCallInfo 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 = MemoryContextAlloc(CacheMemoryContext, strlen(nsp_name)+1);
-	strcpy(spatialRefSysSchema, nsp_name);
-	return;
-}
-
 int
 GetProjectionsUsingFCInfo(FunctionCallInfo fcinfo, int srid1, int srid2, projPJ *pj1, projPJ *pj2)
 {
@@ -718,7 +670,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 16dad00..00b11d8 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);
@@ -504,8 +506,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/lwgeom_export.c b/postgis/lwgeom_export.c
index fcf2eae..e70b7fa 100644
--- a/postgis/lwgeom_export.c
+++ b/postgis/lwgeom_export.c
@@ -54,11 +54,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 ())
 	{
@@ -68,11 +72,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 )
@@ -116,13 +128,11 @@ 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;
@@ -130,6 +140,15 @@ int getSRIDbySRS(const char* srs)
 	if (srs == NULL)
 		return 0;
 
+	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 (SPI_OK_CONNECT != SPI_connect())
 	{
 		elog(NOTICE, "getSRIDbySRS: could not connect to SPI manager");
@@ -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)
@@ -270,8 +291,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;
@@ -447,10 +470,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 )
 				{
@@ -592,8 +615,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 2f43e9d..21810b8 100644
--- a/postgis/lwgeom_in_geojson.c
+++ b/postgis/lwgeom_in_geojson.c
@@ -90,7 +90,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 71637a0..e71ed67 100644
--- a/postgis/lwgeom_in_gml.c
+++ b/postgis/lwgeom_in_gml.c
@@ -111,7 +111,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 | 64 +++++--------------------------------
 postgis/geography_inout.c      | 12 ++++---
 postgis/lwgeom_export.c        | 71 ++++++++++++++++++++++++++++--------------
 postgis/lwgeom_export.h        |  4 +--
 postgis/lwgeom_in_geojson.c    |  2 +-
 postgis/lwgeom_in_gml.c        |  6 ++++
 9 files changed, 103 insertions(+), 97 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list