]> granicus.if.org Git - postgis/commitdiff
2.3 fix, st_transform does not qualify query to spatial_ref_sys (references #3975)
authorPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 12 Jan 2018 13:55:02 +0000 (13:55 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 12 Jan 2018 13:55:02 +0000 (13:55 +0000)
git-svn-id: http://svn.osgeo.org/postgis/branches/2.3@16272 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
libpgcommon/lwgeom_pg.h
libpgcommon/lwgeom_transform.c
libpgcommon/lwgeom_transform.h

diff --git a/NEWS b/NEWS
index 216843d92c9609203e54bc4ab0ee730f420f2494..d4088f68095f20f50dd8160845a5d50d5a29a372 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,8 @@ PostGIS 2.3.6
   - #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)
 
 PostGIS 2.3.5
 2017/11/15
index 1184af2aea6fad92556fc5d828a46fd68d16a92a..28b7007b188443d939f5d5cd9b9ed316ab78ee98 100644 (file)
@@ -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"
index b27c7f651b3d4f7b2a355a5288fbfc8e545d76c6..ef1e2a0353fdd7863b6ef5786046a98b32506416 100644 (file)
 #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 );
 
@@ -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)
@@ -429,7 +454,7 @@ static char* GetProj4String(int srid)
                        int yzone = zone / 20;
                        double lat_0 = 30.0 * (yzone - 3) + 15.0;
                        double lon_0 = 0.0;
-                       
+
                        /* The number of xzones is variable depending on yzone */
                        if  ( yzone == 2 || yzone == 3 )
                                lon_0 = 30.0 * (xzone - 6) + 15.0;
@@ -439,7 +464,7 @@ static char* GetProj4String(int srid)
                                lon_0 = 90.0 * (xzone - 2) + 45.0;
                        else
                                lwerror("Unknown yzone encountered!");
-                       
+
                        snprintf(proj_str, maxproj4len, "+proj=laea +ellps=WGS84 +datum=WGS84 +lat_0=%g +lon_0=%g +units=m +no_defs", lat_0, lon_0);
                }
                /* Lambert Azimuthal Equal Area South Pole */
@@ -511,7 +536,7 @@ AddToPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid, int other_srid)
                char *pj_errstr = pj_strerrno(*pj_get_errno_ref());
                if ( ! pj_errstr )
                        pj_errstr = "";
-               
+
                elog(ERROR,
                    "AddToPROJ4SRSCache: could not parse proj4 string '%s' %s",
                    proj_str, pj_errstr);
@@ -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 )
@@ -781,11 +833,11 @@ srs_precision srid_axis_precision(FunctionCallInfo fcinfo, int srid, int precisi
        projPJ pj2;
 
        srs_precision sp;
-       
+
        sp.precision_xy = precision;
        sp.precision_z = precision;
        sp.precision_m = precision;
-       
+
        if ( srid == SRID_UNKNOWN )
                return sp;
 
@@ -797,6 +849,6 @@ srs_precision srid_axis_precision(FunctionCallInfo fcinfo, int srid, int precisi
                sp.precision_xy += 5;
                return sp;
        }
-       
+
        return sp;
 }
index 413c15ddb659fb59493837981d7b83fd9a4bf7ee..f44b39273e5a94be367c46866556fbcf12596b3f 100644 (file)
@@ -23,7 +23,6 @@ typedef struct srs_precision
 char* GetProj4StringSPI(int srid);
 void SetPROJ4LibPath(void) ;
 
-
 /**
  * Opaque type to use in the projection cache API.
  */