[postgis-tickets] r17567 - Type lookups in FDW fail due to sparse search_path.
Paul Ramsey
pramsey at cleverelephant.ca
Fri Jun 28 09:49:59 PDT 2019
Author: pramsey
Date: 2019-06-28 09:49:59 -0700 (Fri, 28 Jun 2019)
New Revision: 17567
Modified:
trunk/NEWS
trunk/libpgcommon/lwgeom_pg.c
trunk/libpgcommon/lwgeom_pg.h
trunk/libpgcommon/lwgeom_transform.c
trunk/postgis/geobuf.c
trunk/postgis/gserialized_estimate.c
trunk/postgis/gserialized_spgist_2d.c
trunk/postgis/gserialized_spgist_3d.c
trunk/postgis/gserialized_spgist_nd.c
trunk/postgis/lwgeom_out_geojson.c
trunk/postgis/mvt.c
Log:
Type lookups in FDW fail due to sparse search_path.
References #4440
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2019-06-28 15:39:05 UTC (rev 17566)
+++ trunk/NEWS 2019-06-28 16:49:59 UTC (rev 17567)
@@ -18,6 +18,7 @@
- #3437, Speed up ST_Intersects with Points (Raúl Marín)
- #4438, Update serialization to support extended flags area (Paul Ramsey)
- #4443, Fix wagyu configure dropping CPPFLAGS (Raúl Marín)
+ - #4440, Type lookups in FDW fail (Paul Ramsey)
PostGIS 3.0.0alpha2
2019/06/02
Modified: trunk/libpgcommon/lwgeom_pg.c
===================================================================
--- trunk/libpgcommon/lwgeom_pg.c 2019-06-28 15:39:05 UTC (rev 17566)
+++ trunk/libpgcommon/lwgeom_pg.c 2019-06-28 16:49:59 UTC (rev 17567)
@@ -32,34 +32,121 @@
#define PGC_ERRMSG_MAXLEN 2048 //256
-/* Global cache to hold GEOMETRYOID */
-Oid GEOMETRYOID = InvalidOid;
-Oid GEOGRAPHYOID = InvalidOid;
+/****************************************************************************************/
+/* Global to hold all the run-time constants */
-Oid postgis_geometry_oid(void)
+postgisConstants *POSTGIS_CONSTANTS = NULL;
+
+/* Utility call to lookup type oid given name and nspoid */
+static Oid TypenameNspGetTypid(const char *typname, Oid nsp_oid)
{
- if (GEOMETRYOID == InvalidOid) {
- Oid typoid = TypenameGetTypid("geometry");
- if (OidIsValid(typoid) && get_typisdefined(typoid))
- {
- GEOMETRYOID = typoid;
- }
- }
- return GEOMETRYOID;
+ return GetSysCacheOid2(TYPENAMENSP,
+#if POSTGIS_PGSQL_VERSION >= 120
+ Anum_pg_type_oid,
+#endif
+ PointerGetDatum(typname),
+ ObjectIdGetDatum(nsp_oid));
}
-Oid postgis_geography_oid(void)
+/* Cache type lookups in per-session location */
+static postgisConstants *
+getPostgisConstants(FunctionCallInfo fcinfo)
{
- if (GEOGRAPHYOID == InvalidOid) {
- Oid typoid = TypenameGetTypid("geography");
- if (OidIsValid(typoid) && get_typisdefined(typoid))
+ char *nsp_name;
+ Oid nsp_oid;
+ postgisConstants *constants;
+
+ /* For some reason we have a hobbled fcinfo/flinfo */
+ if (!fcinfo || !fcinfo->flinfo) return NULL;
+
+ /* Allocate in the CacheContext so we don't lose this at the end of the statement */
+ constants = MemoryContextAlloc(CacheMemoryContext, sizeof(postgisConstants));
+
+ /* early exit if we cannot lookup nsp_name, cf #4067 */
+ nsp_oid = get_func_namespace(fcinfo->flinfo->fn_oid);
+ if (!nsp_oid) return NULL;
+ nsp_name = get_namespace_name(nsp_oid);
+ constants->install_nsp_oid = nsp_oid;
+ 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);
+
+ /* 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);
+ constants->box2df_oid = TypenameNspGetTypid("box2df", nsp_oid);
+ constants->box3d_oid = TypenameNspGetTypid("box3d", nsp_oid);
+ constants->gidx_oid = TypenameNspGetTypid("gidx", nsp_oid);
+ constants->raster_oid = TypenameNspGetTypid("raster", nsp_oid);
+
+ /* Done */
+ return constants;
+}
+
+Oid
+postgis_oid(postgisType typ)
+{
+ /* Use a schema qualified, cached lookup if we can */
+ postgisConstants *cnsts = POSTGIS_CONSTANTS;
+ if (cnsts)
+ {
+ switch (typ)
{
- GEOGRAPHYOID = typoid;
+ case GEOMETRYOID:
+ return cnsts->geometry_oid;
+ case GEOGRAPHYOID:
+ return cnsts->geography_oid;
+ case BOX3DOID:
+ return cnsts->box3d_oid;
+ case BOX2DFOID:
+ return cnsts->box2df_oid;
+ case GIDXOID:
+ return cnsts->gidx_oid;
+ case RASTEROID:
+ return cnsts->raster_oid;
+ case POSTGISNSPOID:
+ return cnsts->install_nsp_oid;
+ default:
+ return InvalidOid;
}
}
- return GEOGRAPHYOID;
+ /* Fall back to a bare lookup and hope the type in is */
+ /* the search_path */
+ else
+ {
+ switch (typ)
+ {
+ case GEOMETRYOID:
+ return TypenameGetTypid("geometry");
+ case GEOGRAPHYOID:
+ return TypenameGetTypid("geography");
+ case BOX3DOID:
+ return TypenameGetTypid("box3d");
+ case BOX2DFOID:
+ return TypenameGetTypid("box2df");
+ case GIDXOID:
+ return TypenameGetTypid("gidx");
+ case RASTEROID:
+ return TypenameGetTypid("raster");
+ default:
+ return InvalidOid;
+ }
+ }
}
+Oid
+postgis_oid_fcinfo(FunctionCallInfo fcinfo, postgisType oid)
+{
+ /* Cache the info if we don't already have it */
+ if (!POSTGIS_CONSTANTS)
+ POSTGIS_CONSTANTS = getPostgisConstants(fcinfo);;
+
+ if (!POSTGIS_CONSTANTS) return InvalidOid;
+ return postgis_oid(oid);
+}
+
+/****************************************************************************************/
+
+
/*
* Error message parsing functions
*
Modified: trunk/libpgcommon/lwgeom_pg.h
===================================================================
--- trunk/libpgcommon/lwgeom_pg.h 2019-06-28 15:39:05 UTC (rev 17566)
+++ trunk/libpgcommon/lwgeom_pg.h 2019-06-28 16:49:59 UTC (rev 17567)
@@ -16,19 +16,67 @@
#define _LWGEOM_PG_H 1
#include "postgres.h"
+#include "fmgr.h"
+#include "catalog/namespace.h" /* For TypenameGetTypid */
+#if POSTGIS_PGSQL_VERSION > 100
+#include "catalog/pg_type_d.h" /* For TypenameGetTypid */
+#endif
#include "utils/geo_decls.h"
-#include "fmgr.h"
#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/syscache.h"
#include "liblwgeom.h"
#include "pgsql_compat.h"
+
+/****************************************************************************************/
+
+typedef enum
+{
+ GEOMETRYOID = 1,
+ GEOGRAPHYOID,
+ BOX3DOID,
+ BOX2DFOID,
+ GIDXOID,
+ RASTEROID,
+ POSTGISNSPOID
+} postgisType;
+
+typedef struct
+{
+ Oid geometry_oid;
+ Oid geography_oid;
+ Oid box2df_oid;
+ Oid box3d_oid;
+ Oid gidx_oid;
+ Oid raster_oid;
+ Oid install_nsp_oid;
+ char *install_nsp;
+} 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);
+
+/* only useful if postgis_oid_fcinfo() has been called first and */
+/* populated first, otherwise returns InvalidOid */
+Oid postgis_oid(postgisType typ);
+
+/****************************************************************************************/
+
/* Globals to hold GEOMETRYOID, GEOGRAPHYOID */
-extern Oid GEOMETRYOID;
-extern Oid GEOGRAPHYOID;
-Oid postgis_geometry_oid(void);
-Oid postgis_geography_oid(void);
+// extern Oid GEOMETRYOID;
+// extern Oid GEOGRAPHYOID;
+// Oid postgis_geometry_oid(void);
+// Oid postgis_geography_oid(void);
+/****************************************************************************************/
+
/* Install PosgreSQL handlers for liblwgeom use */
void pg_install_lwgeom_handlers(void);
Modified: trunk/libpgcommon/lwgeom_transform.c
===================================================================
--- trunk/libpgcommon/lwgeom_transform.c 2019-06-28 15:39:05 UTC (rev 17566)
+++ trunk/libpgcommon/lwgeom_transform.c 2019-06-28 16:49:59 UTC (rev 17567)
@@ -72,6 +72,7 @@
SetSpatialRefSysSchema(FunctionCallInfo fcinfo)
{
char *nsp_name;
+ Oid nsp_oid;
/* Schema info is already cached, we're done here */
if (spatialRefSysSchema) return;
@@ -79,7 +80,9 @@
/* 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));
+ 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;
Modified: trunk/postgis/geobuf.c
===================================================================
--- trunk/postgis/geobuf.c 2019-06-28 15:39:05 UTC (rev 17566)
+++ trunk/postgis/geobuf.c 2019-06-28 16:49:59 UTC (rev 17567)
@@ -62,7 +62,7 @@
char *tkey = TupleDescAttr(tupdesc, i)->attname.data;
char *key = pstrdup(tkey);
if (ctx->geom_name == NULL) {
- if (!geom_found && typoid == TypenameGetTypid("geometry")) {
+ if (!geom_found && typoid == postgis_oid(GEOMETRYOID)) {
ctx->geom_index = i;
geom_found = 1;
continue;
Modified: trunk/postgis/gserialized_estimate.c
===================================================================
--- trunk/postgis/gserialized_estimate.c 2019-06-28 15:39:05 UTC (rev 17566)
+++ trunk/postgis/gserialized_estimate.c 2019-06-28 16:49:59 UTC (rev 17567)
@@ -167,13 +167,6 @@
#define STATISTIC_SLOT_2D 1
/*
-* To look-up the spatial index associated with a table we
-* need to find GIST indexes using our spatial keys.
-*/
-#define INDEX_KEY_ND "gidx"
-#define INDEX_KEY_2D "box2df"
-
-/*
* The SD factor restricts the side of the statistics histogram
* based on the standard deviation of the extent of the data.
* SDFACTOR is the number of standard deviations from the mean
@@ -2417,16 +2410,6 @@
/************************************************************************/
static Oid
-typname_to_oid(const char *typname)
-{
- Oid typoid = TypenameGetTypid(typname);
- if (OidIsValid(typoid) && get_typisdefined(typoid))
- return typoid;
- else
- return InvalidOid;
-}
-
-static Oid
table_get_spatial_index(Oid tbl_oid, text *col, int *key_type)
{
Relation tbl_rel;
@@ -2436,8 +2419,8 @@
char *colname = text_to_cstring(col);
/* Lookup our spatial index key types */
- Oid b2d_oid = typname_to_oid(INDEX_KEY_2D);
- Oid gdx_oid = typname_to_oid(INDEX_KEY_ND);
+ Oid b2d_oid = postgis_oid(BOX2DFOID);
+ Oid gdx_oid = postgis_oid(BOX3DOID);
if (!(b2d_oid && gdx_oid))
return InvalidOid;
Modified: trunk/postgis/gserialized_spgist_2d.c
===================================================================
--- trunk/postgis/gserialized_spgist_2d.c 2019-06-28 15:39:05 UTC (rev 17566)
+++ trunk/postgis/gserialized_spgist_2d.c 2019-06-28 16:49:59 UTC (rev 17567)
@@ -73,7 +73,6 @@
#include <postgres.h>
#include <utils/builtins.h> /* For float manipulation */
#include "access/spgist.h" /* For SP-GiST */
-#include "catalog/namespace.h" /* For TypenameGetTypid */
#include "catalog/pg_type_d.h" /* For VOIDOID */
#include "../postgis_config.h"
@@ -292,7 +291,7 @@
{
spgConfigOut *cfg = (spgConfigOut *)PG_GETARG_POINTER(1);
- Oid boxoid = TypenameGetTypid("box2df");
+ Oid boxoid = postgis_oid_fcinfo(fcinfo, BOX2DFOID);
cfg->prefixType = boxoid;
cfg->labelType = VOIDOID; /* We don't need node labels. */
cfg->leafType = boxoid;
Modified: trunk/postgis/gserialized_spgist_3d.c
===================================================================
--- trunk/postgis/gserialized_spgist_3d.c 2019-06-28 15:39:05 UTC (rev 17566)
+++ trunk/postgis/gserialized_spgist_3d.c 2019-06-28 16:49:59 UTC (rev 17567)
@@ -373,7 +373,7 @@
{
spgConfigOut *cfg = (spgConfigOut *)PG_GETARG_POINTER(1);
- Oid boxoid = TypenameGetTypid("box3d");
+ Oid boxoid = postgis_oid_fcinfo(fcinfo, BOX3DOID);
cfg->prefixType = boxoid;
cfg->labelType = VOIDOID; /* We don't need node labels. */
cfg->leafType = boxoid;
Modified: trunk/postgis/gserialized_spgist_nd.c
===================================================================
--- trunk/postgis/gserialized_spgist_nd.c 2019-06-28 15:39:05 UTC (rev 17566)
+++ trunk/postgis/gserialized_spgist_nd.c 2019-06-28 16:49:59 UTC (rev 17567)
@@ -267,7 +267,7 @@
PGDLLEXPORT Datum gserialized_spgist_config_nd(PG_FUNCTION_ARGS)
{
spgConfigOut *cfg = (spgConfigOut *)PG_GETARG_POINTER(1);
- Oid boxoid = TypenameGetTypid("gidx");
+ Oid boxoid = postgis_oid_fcinfo(fcinfo, GIDXOID);
cfg->prefixType = boxoid;
cfg->labelType = VOIDOID; /* We don't need node labels. */
Modified: trunk/postgis/lwgeom_out_geojson.c
===================================================================
--- trunk/postgis/lwgeom_out_geojson.c 2019-06-28 15:39:05 UTC (rev 17566)
+++ trunk/postgis/lwgeom_out_geojson.c 2019-06-28 16:49:59 UTC (rev 17567)
@@ -51,7 +51,8 @@
bool use_line_feeds);
static void composite_to_geojson(Datum composite,
char *geom_column_name, int32 maxdecimaldigits,
- StringInfo result, bool use_line_feeds);
+ StringInfo result, bool use_line_feeds,
+ Oid geom_oid, Oid geog_oid);
static void composite_to_json(Datum composite, StringInfo result,
bool use_line_feeds);
static void datum_to_json(Datum val, bool is_null, StringInfo result,
@@ -80,6 +81,8 @@
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);
if (strlen(geom_column) == 0)
geom_column = NULL;
@@ -86,7 +89,7 @@
result = makeStringInfo();
- composite_to_geojson(array, geom_column, maxdecimaldigits, result, do_pretty);
+ composite_to_geojson(array, geom_column, maxdecimaldigits, result, do_pretty, geom_oid, geog_oid);
PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
}
@@ -96,7 +99,7 @@
*/
static void
composite_to_geojson(Datum composite, char *geom_column_name, int32 maxdecimaldigits,
- StringInfo result, bool use_line_feeds)
+ StringInfo result, bool use_line_feeds, Oid geom_oid, Oid geog_oid)
{
HeapTupleHeader td;
Oid tupType;
@@ -109,8 +112,6 @@
const char *sep;
StringInfo props = makeStringInfo();
bool geom_column_found = false;
- Oid geom_oid = postgis_geometry_oid();
- Oid geog_oid = postgis_geography_oid();
sep = use_line_feeds ? ",\n " : ", ";
Modified: trunk/postgis/mvt.c
===================================================================
--- trunk/postgis/mvt.c 2019-06-28 15:39:05 UTC (rev 17566)
+++ trunk/postgis/mvt.c 2019-06-28 16:49:59 UTC (rev 17567)
@@ -352,7 +352,7 @@
if (ctx->geom_name == NULL)
{
- if (!geom_found && typoid == TypenameGetTypid("geometry"))
+ if (!geom_found && typoid == postgis_oid(GEOMETRYOID))
{
ctx->geom_index = i;
geom_found = true;
More information about the postgis-tickets
mailing list