[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0alpha1-51-gb48fb3e
git at osgeo.org
git at osgeo.org
Fri Apr 10 03:28:47 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, master has been updated
via b48fb3e2272568aa6310fc26aefc69010d4f37e3 (commit)
from 8b548a4697490b7e45508b91cb340eb79b424a92 (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 b48fb3e2272568aa6310fc26aefc69010d4f37e3
Author: Raúl Marín <git at rmr.ninja>
Date: Fri Apr 10 12:28:31 2020 +0200
Fix access to spatial_ref_sys with a non default schema
References #4661
Closes https://github.com/postgis/postgis/pull/553
diff --git a/NEWS b/NEWS
index e655f2e..8659b46 100644
--- a/NEWS
+++ b/NEWS
@@ -11,9 +11,11 @@ Only tickets not included in 3.1.0alpha1
* Enhancements *
- #4651: ST_Simplify: Don't copy if nothing is removed (Raúl Marín)
+ - #4657: Avoid De-TOASTing where possible (Paul Ramsey)
* Bug fixes *
- #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 3.1.0alpha1
2020/02/01
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..2009eff 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();
+
/****************************************************************************************/
/* Globals to hold GEOMETRYOID, GEOGRAPHYOID */
diff --git a/libpgcommon/lwgeom_transform.c b/libpgcommon/lwgeom_transform.c
index 6d9c2f5..cacccd1 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)
{
@@ -166,23 +132,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);
@@ -366,6 +321,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
@@ -381,6 +337,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
@@ -534,7 +491,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 f9ee8e5..074c213 100644
--- a/postgis/lwgeom_export.c
+++ b/postgis/lwgeom_export.c
@@ -58,11 +58,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 ())
{
@@ -72,11 +74,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 )
@@ -120,17 +130,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())
@@ -150,11 +167,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)
@@ -267,8 +286,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;
@@ -374,7 +395,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)
{
@@ -536,8 +557,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_inout.c b/postgis/lwgeom_inout.c
index 3a31a2d..3573d28 100644
--- a/postgis/lwgeom_inout.c
+++ b/postgis/lwgeom_inout.c
@@ -147,7 +147,7 @@ Datum LWGEOM_in(PG_FUNCTION_ARGS)
lwgeom = lwgeom_from_geojson(str, &srs);
if (srs)
{
- srid = getSRIDbySRS(srs);
+ srid = getSRIDbySRS(fcinfo, srs);
lwfree(srs);
lwgeom_set_srid(lwgeom, 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 | 2 ++
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_inout.c | 2 +-
postgis/lwgeom_out_geojson.c | 8 +++--
15 files changed, 123 insertions(+), 98 deletions(-)
hooks/post-receive
--
PostGIS
More information about the postgis-tickets
mailing list