[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