From: Paul Ramsey Date: Fri, 12 Jan 2018 13:47:51 +0000 (+0000) Subject: 2.4 fix, st_transform does not qualify query to spatial_ref_sys (references #3975) X-Git-Tag: 2.4.3rc1~11 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=40ac54854a82e4cbf554c9cef6bac5e32f575f21;p=postgis 2.4 fix, st_transform does not qualify query to spatial_ref_sys (references #3975) git-svn-id: http://svn.osgeo.org/postgis/branches/2.4@16271 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/NEWS b/NEWS index 9c713fd1f..1139cee54 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ PostGIS 2.4.3 - #3956, Brin opclass object does not upgrade properly (Sandro Santilli) - #3982, ST_AsEncodedPolyline supports LINESTRING EMPTY and MULTIPOINT EMPTY (Darafei Praliaskouski) + - #3975, ST_Transform runs query on spatial_ref_sys without schema + qualification. May cause restore issues. (Paul Ramsey) * Enhancements * - #3944, Update to EPSG register v9.2 (Even Rouault) diff --git a/libpgcommon/lwgeom_pg.h b/libpgcommon/lwgeom_pg.h index 1a7fa3508..596179aa6 100644 --- a/libpgcommon/lwgeom_pg.h +++ b/libpgcommon/lwgeom_pg.h @@ -18,6 +18,7 @@ #include "postgres.h" #include "utils/geo_decls.h" #include "fmgr.h" +#include "utils/lsyscache.h" #include "liblwgeom.h" #include "pgsql_compat.h" diff --git a/libpgcommon/lwgeom_transform.c b/libpgcommon/lwgeom_transform.c index 454e76320..ef1e2a035 100644 --- a/libpgcommon/lwgeom_transform.c +++ b/libpgcommon/lwgeom_transform.c @@ -34,6 +34,15 @@ #include +/** +* 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 ); @@ -349,9 +358,25 @@ char* GetProj4StringSPI(int srid) elog(ERROR, "GetProj4StringSPI: Could not connect to database using SPI"); } - /* Execute the lookup query */ - snprintf(proj4_spi_buffer, 255, "SELECT proj4text FROM spatial_ref_sys WHERE srid = %d LIMIT 1", srid); - spi_result = SPI_exec(proj4_spi_buffer, 1); + /* + * 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); + } + /* Execute the query, noting the readonly status of this SQL */ + spi_result = SPI_execute(proj4_spi_buffer, true, 1); /* Read back the PROJ4 text */ if (spi_result == SPI_OK_SELECT && SPI_processed > 0) @@ -698,6 +723,30 @@ static PROJ4PortalCache *GetPROJ4SRSCache(FunctionCallInfo fcinfo) } #endif +/* +* 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; + + /* 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_name = get_namespace_name(get_func_namespace(fcinfo->flinfo->fn_oid)); + 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) { @@ -706,6 +755,9 @@ GetProjectionsUsingFCInfo(FunctionCallInfo fcinfo, int srid1, int srid2, projPJ /* Set the search path if we haven't already */ SetPROJ4LibPath(); + /* Look up the spatial_ref_sys schema if we haven't already */ + SetSpatialRefSysSchema(fcinfo); + /* get or initialize the cache for this round */ proj_cache = GetPROJ4Cache(fcinfo); if ( !proj_cache ) diff --git a/libpgcommon/lwgeom_transform.h b/libpgcommon/lwgeom_transform.h index 413c15ddb..f44b39273 100644 --- a/libpgcommon/lwgeom_transform.h +++ b/libpgcommon/lwgeom_transform.h @@ -23,7 +23,6 @@ typedef struct srs_precision char* GetProj4StringSPI(int srid); void SetPROJ4LibPath(void) ; - /** * Opaque type to use in the projection cache API. */