[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