]> granicus.if.org Git - postgis/commitdiff
Internal type lookups fail over FDW
authorPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 28 Jun 2019 17:29:22 +0000 (17:29 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 28 Jun 2019 17:29:22 +0000 (17:29 +0000)
References #4440

git-svn-id: http://svn.osgeo.org/postgis/branches/2.5@17568 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
libpgcommon/lwgeom_pg.c
libpgcommon/lwgeom_pg.h
libpgcommon/lwgeom_transform.c
postgis/geobuf.c
postgis/gserialized_estimate.c
postgis/gserialized_spgist_2d.c
postgis/gserialized_spgist_3d.c
postgis/mvt.c

diff --git a/NEWS b/NEWS
index 5e9bcd2c8a92677fad0567365a1f39cc9bd8533e..9733d51af4125609c013d21b13bd6a8849ad5330 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ PostGIS 2.5.3
   - #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.5.2
index d4836db47a02b5f6a4de0fcb0e9437d1eefcef8b..a0b20d64ca987166862fb4588027275e8f357c21 100644 (file)
 
 #define PGC_ERRMSG_MAXLEN 2048 //256
 
+
+/****************************************************************************************/
+/* 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
  *
index 03514cc2465c5269b663d425151d5699047343ab..8a98d974e032f9fadd890c08ae8acf4c68de7ee7 100644 (file)
 #define _LWGEOM_PG_H 1
 
 #include "postgres.h"
-#include "utils/geo_decls.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 "utils/memutils.h"
 #include "utils/lsyscache.h"
+#include "utils/syscache.h"
 
 #include "liblwgeom.h"
 #include "pgsql_compat.h"
@@ -31,6 +37,47 @@ void pg_install_lwgeom_handlers(void);
 #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
 
index f308d3ed7738e739f7a38176eb13024aecfeec91..8e0dd7fc57b4aa1c405a3a13ea33724da63c22d0 100644 (file)
@@ -690,6 +690,7 @@ static void
 SetSpatialRefSysSchema(FunctionCallInfo fcinfo)
 {
        char *nsp_name;
+       Oid nsp_oid;
 
        /* Schema info is already cached, we're done here */
        if (spatialRefSysSchema) return;
@@ -697,7 +698,9 @@ SetSpatialRefSysSchema(FunctionCallInfo fcinfo)
        /* 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;
 
index 8c729f1bc6a9913415048dd89330e50f7857ec3e..f504e2e77518ec669a553aad190b3354e9a3ec05 100644 (file)
@@ -66,7 +66,7 @@ static void encode_keys(struct geobuf_agg_context *ctx)
 #endif
                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;
index a0b5fb0828ea024629228503c8ec4120690d4560..48ad410809e2cfb233538ebbb416cc7783c9bee6 100644 (file)
@@ -175,13 +175,6 @@ Datum geometry_estimated_extent(PG_FUNCTION_ARGS);
 #define STATISTIC_SLOT_ND 0
 #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.
@@ -2428,16 +2421,6 @@ Datum geometry_estimated_extent(PG_FUNCTION_ARGS)
 
 /************************************************************************/
 
-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)
 {
@@ -2448,8 +2431,8 @@ table_get_spatial_index(Oid tbl_oid, text *col, int *key_type)
        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;
index 7c0df228429b742e7fb1de503bf23420a375fd39..3d191bb51c92f52b7efe5bb52950b4bb8a84c2b1 100644 (file)
@@ -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"
@@ -291,7 +290,7 @@ PGDLLEXPORT Datum gserialized_spgist_config_2d(PG_FUNCTION_ARGS)
 {
        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;
index f4d340d87eb1a3efe15bc0e1409dc1e115648edc..d11c291cd7cd6ee8353ab5ae2b9d464ecc4972e5 100644 (file)
@@ -373,7 +373,7 @@ PGDLLEXPORT Datum gserialized_spgist_config_3d(PG_FUNCTION_ARGS)
 {
        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;
index e76c5af0fbd31e732fdaa1cab951841a1e530a9a..333db09c4c564d9a596933c7a3fcab301c2a116d 100644 (file)
@@ -352,7 +352,7 @@ static void parse_column_keys(mvt_agg_context *ctx)
 
                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;