[postgis-tickets] r17569 - Internal type lookups fail over FDW

Paul Ramsey pramsey at cleverelephant.ca
Fri Jun 28 11:03:24 PDT 2019


Author: pramsey
Date: 2019-06-28 11:03:24 -0700 (Fri, 28 Jun 2019)
New Revision: 17569

Modified:
   branches/2.4/NEWS
   branches/2.4/libpgcommon/lwgeom_pg.c
   branches/2.4/libpgcommon/lwgeom_pg.h
   branches/2.4/libpgcommon/lwgeom_transform.c
   branches/2.4/postgis/geobuf.c
   branches/2.4/postgis/mvt.c
Log:
Internal type lookups fail over FDW 
Closes #4440


Modified: branches/2.4/NEWS
===================================================================
--- branches/2.4/NEWS	2019-06-28 17:29:22 UTC (rev 17568)
+++ branches/2.4/NEWS	2019-06-28 18:03:24 UTC (rev 17569)
@@ -8,6 +8,7 @@
   - #4388, AddRasterConstraints: Ignore NULLs when generating constraints (Raúl Marín)
   - #4327, Avoid pfree'ing the result of getenv (Raúl Marín)
   - #4406, Throw on invalid characters when decoding geohash (Raúl Marín)
+  - #4440, Internal type lookups fail over FDW (Paul Ramsey)
 
 
 PostGIS 2.4.7

Modified: branches/2.4/libpgcommon/lwgeom_pg.c
===================================================================
--- branches/2.4/libpgcommon/lwgeom_pg.c	2019-06-28 17:29:22 UTC (rev 17568)
+++ branches/2.4/libpgcommon/lwgeom_pg.c	2019-06-28 18:03:24 UTC (rev 17569)
@@ -65,6 +65,125 @@
 }
 
 
+
+/****************************************************************************************/
+/* Global to hold all the run-time constants */
+
+postgisConstants *POSTGIS_CONSTANTS = NULL;
+
+/* Utility call to lookup type oid given name and nspoid */
+static Oid TypenameNspGetTypid(const char *typname, Oid nsp_oid)
+  {
+	return GetSysCacheOid2(TYPENAMENSP,
+#if POSTGIS_PGSQL_VERSION >= 120
+	                       Anum_pg_type_oid,
+#endif
+	                       PointerGetDatum(typname),
+	                       ObjectIdGetDatum(nsp_oid));
+  }
+
+/* Cache type lookups in per-session location */
+static postgisConstants *
+getPostgisConstants(FunctionCallInfo fcinfo)
+  {
+	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)
+		{
+			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;
+		}
+	}
+	/* 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: branches/2.4/libpgcommon/lwgeom_pg.h
===================================================================
--- branches/2.4/libpgcommon/lwgeom_pg.h	2019-06-28 17:29:22 UTC (rev 17568)
+++ branches/2.4/libpgcommon/lwgeom_pg.h	2019-06-28 18:03:24 UTC (rev 17569)
@@ -16,9 +16,15 @@
 #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/memutils.h"
 #include "utils/lsyscache.h"
+#include "utils/syscache.h"
 
 #include "liblwgeom.h"
 #include "pgsql_compat.h"
@@ -31,6 +37,47 @@
 #define PG_GETARG_GSERIALIZED_P_COPY(varno) ((GSERIALIZED *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(varno)))
 #define PG_GETARG_GSERIALIZED_P_SLICE(varno, start, size) ((GSERIALIZED *)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(varno), start, size))
 
+/****************************************************************************************
+* Caching machinery to hold information about Oid numbers for PostGIS
+* types.
+*/
+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);
+
+/****************************************************************************************/
+
 /* Debugging macros */
 #if POSTGIS_DEBUG_LEVEL > 0
 

Modified: branches/2.4/libpgcommon/lwgeom_transform.c
===================================================================
--- branches/2.4/libpgcommon/lwgeom_transform.c	2019-06-28 17:29:22 UTC (rev 17568)
+++ branches/2.4/libpgcommon/lwgeom_transform.c	2019-06-28 18:03:24 UTC (rev 17569)
@@ -688,6 +688,7 @@
 SetSpatialRefSysSchema(FunctionCallInfo fcinfo)
 {
 	char *nsp_name;
+	Oid nsp_oid;
 
 	/* Schema info is already cached, we're done here */
 	if (spatialRefSysSchema) return;
@@ -695,7 +696,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: branches/2.4/postgis/geobuf.c
===================================================================
--- branches/2.4/postgis/geobuf.c	2019-06-28 17:29:22 UTC (rev 17568)
+++ branches/2.4/postgis/geobuf.c	2019-06-28 18:03:24 UTC (rev 17569)
@@ -67,7 +67,7 @@
 		char *key = palloc(strlen(tkey) + 1);
 		strcpy(key, 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: branches/2.4/postgis/mvt.c
===================================================================
--- branches/2.4/postgis/mvt.c	2019-06-28 17:29:22 UTC (rev 17568)
+++ branches/2.4/postgis/mvt.c	2019-06-28 18:03:24 UTC (rev 17569)
@@ -324,7 +324,7 @@
 #endif
 		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 = true;
 				continue;



More information about the postgis-tickets mailing list