[postgis-tickets] [SCM] PostGIS branch stable-3.0 updated. 3.0.1-10-gefafa58
git at osgeo.org
git at osgeo.org
Fri Apr 10 04:25:28 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-3.0 has been updated
via efafa58a6878f34055c616a3aa16566c2e598127 (commit)
from b5cba66de3148fd115a92666d890b97a7ddbde41 (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 efafa58a6878f34055c616a3aa16566c2e598127
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 5afd631..39ecad0 100644
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,8 @@ PostGIS 3.0.2
2020/XX/XX
* Bug Fixes and Enhancements *
- - #4652, Fix several memory related bugs in ST_GeomFromGML
+ - #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)
diff --git a/libpgcommon/lwgeom_pg.c b/libpgcommon/lwgeom_pg.c
index e2ee6b8..aecc38a 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>
#include <catalog/namespace.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 93a52b9..546ea10 100644
--- a/libpgcommon/lwgeom_pg.h
+++ b/libpgcommon/lwgeom_pg.h
@@ -53,20 +53,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);
+
/****************************************************************************************/
/* Globals to hold GEOMETRYOID, GEOGRAPHYOID */
diff --git a/libpgcommon/lwgeom_transform.c b/libpgcommon/lwgeom_transform.c
index d8a172e..ab07c63 100644
--- a/libpgcommon/lwgeom_transform.c
+++ b/libpgcommon/lwgeom_transform.c
@@ -33,12 +33,6 @@
#include <stdio.h>
-/**
-* Global variable to hold cached information about what
-* schema functions are installed in. Currently used by
-* SetSpatialRefSysSchema and GetProjStringsSPI
-*/
-static char *spatialRefSysSchema = NULL;
/*
* PROJ 4 backend hash table initial hash size
@@ -63,34 +57,6 @@ typedef struct {
static LWPROJ *AddToPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to);
static void DeleteFromPROJSRSCache(PROJPortalCache *PROJCache, uint32_t position);
-/*
-* Given a function call context, figure out what namespace the
-* function is being called from, and copy that into a global
-* for use by GetProjStringsSPI
-*/
-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;
-}
-
static void
PROJSRSDestroyPJ(void *projection)
{
@@ -369,23 +335,12 @@ GetProjStringsSPI(int32_t srid)
elog(ERROR, "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 GetPJUsingFCInfo is called.
- */
- static char *proj_str_tmpl = "SELECT proj4text, auth_name, auth_srid, srtext "
- "FROM %s%sspatial_ref_sys "
- "WHERE srid = %d "
- "LIMIT 1";
- if (spatialRefSysSchema)
- {
- snprintf(proj_spi_buffer, spibufferlen, proj_str_tmpl, spatialRefSysSchema, ".", srid);
- }
- else
- {
- snprintf(proj_spi_buffer, spibufferlen, proj_str_tmpl, "", "", srid);
- }
+ static char *proj_str_tmpl =
+ "SELECT proj4text, auth_name, auth_srid, srtext "
+ "FROM %s "
+ "WHERE srid = %d "
+ "LIMIT 1";
+ snprintf(proj_spi_buffer, spibufferlen, proj_str_tmpl, postgis_spatial_ref_sys(), srid);
/* Execute the query, noting the readonly status of this SQL */
spi_result = SPI_execute(proj_spi_buffer, true, 1);
@@ -569,6 +524,7 @@ pgstrs_get_entry(const PjStrs *strs, int n)
}
#endif
+#if POSTGIS_PROJ_VERSION < 60
/*
* Utility function for GML reader that still
* needs proj4text access
@@ -584,6 +540,7 @@ GetProj4String(int32_t srid)
pjstrs_pfree(&strs);
return proj4str;
}
+#endif
/**
* Add an entry to the local PROJ SRS cache. If we need to wrap around then
@@ -766,7 +723,7 @@ GetPJUsingFCInfo(FunctionCallInfo fcinfo, int32_t srid_from, int32_t srid_to, LW
PROJPortalCache *proj_cache = NULL;
/* 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 = GetPROJSRSCache(fcinfo);
diff --git a/libpgcommon/lwgeom_transform.h b/libpgcommon/lwgeom_transform.h
index 951aa80..2d2cd2d 100644
--- a/libpgcommon/lwgeom_transform.h
+++ b/libpgcommon/lwgeom_transform.h
@@ -22,7 +22,10 @@ typedef struct srs_precision
int precision_m;
} srs_precision;
+#if POSTGIS_PROJ_VERSION < 60
+/* Needs to call postgis_initialize_cache first */
char *GetProj4String(int32_t srid);
+#endif
/**
* Opaque type to use in the projection cache API.
diff --git a/postgis/geography_inout.c b/postgis/geography_inout.c
index 9fc77f6..55cb152 100644
--- a/postgis/geography_inout.c
+++ b/postgis/geography_inout.c
@@ -291,8 +291,10 @@ Datum geography_as_gml(PG_FUNCTION_ARGS)
id = id_buf;
}
- 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);
@@ -453,8 +455,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 38e9bd1..fc60e18 100644
--- a/postgis/gserialized_spgist_2d.c
+++ b/postgis/gserialized_spgist_2d.c
@@ -290,8 +290,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/gserialized_spgist_nd.c b/postgis/gserialized_spgist_nd.c
index 5d624df..1576048 100644
--- a/postgis/gserialized_spgist_nd.c
+++ b/postgis/gserialized_spgist_nd.c
@@ -267,7 +267,9 @@ PG_FUNCTION_INFO_V1(gserialized_spgist_config_nd);
PGDLLEXPORT Datum gserialized_spgist_config_nd(PG_FUNCTION_ARGS)
{
spgConfigOut *cfg = (spgConfigOut *)PG_GETARG_POINTER(1);
- Oid boxoid = postgis_oid_fcinfo(fcinfo, GIDXOID);
+ Oid boxoid = InvalidOid;
+ postgis_initialize_cache(fcinfo);
+ boxoid = postgis_oid(GIDXOID);
cfg->prefixType = boxoid;
cfg->labelType = VOIDOID; /* We don't need node labels. */
diff --git a/postgis/lwgeom_export.c b/postgis/lwgeom_export.c
index b8f83ae..9d08b82 100644
--- a/postgis/lwgeom_export.c
+++ b/postgis/lwgeom_export.c
@@ -63,11 +63,13 @@ Datum geometry_to_jsonb(PG_FUNCTION_ARGS);
* or as long one: (i.e urn:ogc:def:crs:EPSG::4326)
*/
char *
-getSRSbySRID(int32_t srid, bool short_crs)
+getSRSbySRID(FunctionCallInfo fcinfo, int32_t 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 ())
{
@@ -77,11 +79,19 @@ getSRSbySRID(int32_t 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 )
@@ -125,17 +135,24 @@ getSRSbySRID(int32_t 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())
@@ -155,11 +172,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)
@@ -272,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;
@@ -404,7 +425,7 @@ Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
if (srid != SRID_UNKNOWN && (output_short_crs || output_long_crs))
{
- srs = getSRSbySRID(srid, !output_long_crs);
+ srs = getSRSbySRID(fcinfo, srid, !output_long_crs);
if (!srs)
{
@@ -566,8 +587,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 e01a6ee..b5de2ba 100644
--- a/postgis/lwgeom_export.h
+++ b/postgis/lwgeom_export.h
@@ -22,5 +22,5 @@
*
**********************************************************************/
-char *getSRSbySRID(int32_t SRID, bool short_crs);
-int getSRIDbySRS(const char* SRS);
+char *getSRSbySRID(FunctionCallInfo fcinfo, int32_t 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 08b52a7..58cef93 100644
--- a/postgis/lwgeom_in_geojson.c
+++ b/postgis/lwgeom_in_geojson.c
@@ -110,7 +110,7 @@ Datum geom_from_geojson(PG_FUNCTION_ARGS)
if (srs)
{
- srid = getSRIDbySRS(srs);
+ srid = getSRIDbySRS(fcinfo, srs);
lwfree(srs);
}
diff --git a/postgis/lwgeom_in_gml.c b/postgis/lwgeom_in_gml.c
index ef1840e..1a5eecf 100644
--- a/postgis/lwgeom_in_gml.c
+++ b/postgis/lwgeom_in_gml.c
@@ -113,6 +113,13 @@ Datum geom_from_gml(PG_FUNCTION_ARGS)
/* Zero for undefined */
root_srid = PG_GETARG_INT32(1);
+#if POSTGIS_PROJ_VERSION < 60
+ /* 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);
+#endif
lwgeom = lwgeom_from_gml(xml, xml_size);
if ( root_srid != SRID_UNKNOWN )
lwgeom->srid = root_srid;
diff --git a/postgis/lwgeom_out_geojson.c b/postgis/lwgeom_out_geojson.c
index 138ddc7..4d82148 100644
--- a/postgis/lwgeom_out_geojson.c
+++ b/postgis/lwgeom_out_geojson.c
@@ -86,8 +86,12 @@ ST_AsGeoJsonRow(PG_FUNCTION_ARGS)
bool do_pretty = PG_GETARG_BOOL(3);
StringInfo result;
char *geom_column = text_to_cstring(geom_column_text);
- Oid geom_oid = postgis_oid_fcinfo(fcinfo, GEOMETRYOID);
- Oid geog_oid = postgis_oid_fcinfo(fcinfo, GEOGRAPHYOID);
+ Oid geom_oid = InvalidOid;
+ Oid geog_oid = InvalidOid;
+
+ postgis_initialize_cache(fcinfo);
+ geom_oid = postgis_oid(GEOMETRYOID);
+ geog_oid = postgis_oid(GEOGRAPHYOID);
if (strlen(geom_column) == 0)
geom_column = NULL;
-----------------------------------------------------------------------
Summary of changes:
NEWS | 3 +-
libpgcommon/lwgeom_pg.c | 22 +++++++++++---
libpgcommon/lwgeom_pg.h | 18 +++++++----
libpgcommon/lwgeom_transform.c | 61 ++++++-------------------------------
libpgcommon/lwgeom_transform.h | 3 ++
postgis/geography_inout.c | 12 +++++---
postgis/gserialized_spgist_2d.c | 4 ++-
postgis/gserialized_spgist_3d.c | 5 ++-
postgis/gserialized_spgist_nd.c | 4 ++-
postgis/lwgeom_export.c | 67 +++++++++++++++++++++++++++--------------
postgis/lwgeom_export.h | 4 +--
postgis/lwgeom_in_geojson.c | 2 +-
postgis/lwgeom_in_gml.c | 7 +++++
postgis/lwgeom_out_geojson.c | 8 +++--
14 files changed, 122 insertions(+), 98 deletions(-)
hooks/post-receive
--
PostGIS
More information about the postgis-tickets
mailing list