[postgis-tickets] r14680 - #2743, avoid re-definition of GUCs during upgrade
Paul Ramsey
pramsey at cleverelephant.ca
Wed Feb 24 07:19:04 PST 2016
Author: pramsey
Date: 2016-02-24 07:19:04 -0800 (Wed, 24 Feb 2016)
New Revision: 14680
Modified:
trunk/libpgcommon/lwgeom_pg.c
trunk/libpgcommon/lwgeom_pg.h
trunk/postgis/lwgeom_backend_api.c
trunk/raster/rt_pg/rtpostgis.c
Log:
#2743, avoid re-definition of GUCs during upgrade
Modified: trunk/libpgcommon/lwgeom_pg.c
===================================================================
--- trunk/libpgcommon/lwgeom_pg.c 2016-02-24 14:32:39 UTC (rev 14679)
+++ trunk/libpgcommon/lwgeom_pg.c 2016-02-24 15:19:04 UTC (rev 14680)
@@ -16,8 +16,10 @@
#include <postgres.h>
#include <fmgr.h>
+#include <miscadmin.h>
#include <executor/spi.h>
-#include <miscadmin.h>
+#include <utils/guc.h>
+#include <utils/guc_tables.h>
#include "../postgis_config.h"
#include "liblwgeom.h"
@@ -279,3 +281,81 @@
va_end(ap);
}
+
+
+/*
+ * the bare comparison function for GUC names
+ */
+int
+postgis_guc_name_compare(const char *namea, const char *nameb)
+{
+ /*
+ * The temptation to use strcasecmp() here must be resisted, because the
+ * array ordering has to remain stable across setlocale() calls. So, build
+ * our own with a simple ASCII-only downcasing.
+ */
+ while (*namea && *nameb)
+ {
+ char cha = *namea++;
+ char chb = *nameb++;
+
+ if (cha >= 'A' && cha <= 'Z')
+ cha += 'a' - 'A';
+ if (chb >= 'A' && chb <= 'Z')
+ chb += 'a' - 'A';
+ if (cha != chb)
+ return cha - chb;
+ }
+ if (*namea)
+ return 1; /* a is longer */
+ if (*nameb)
+ return -1; /* b is longer */
+ return 0;
+}
+
+/*
+ * comparator for qsorting and bsearching guc_variables array
+ */
+int
+postgis_guc_var_compare(const void *a, const void *b)
+{
+ const struct config_generic *confa = *(struct config_generic * const *) a;
+ const struct config_generic *confb = *(struct config_generic * const *) b;
+
+ return postgis_guc_name_compare(confa->name, confb->name);
+}
+
+/*
+* This is copied from the top half of the find_option function
+* in postgresql's guc.c. We search the guc_variables for our option.
+* Then we make sure it's not a placeholder. Only then are we sure
+* we have a potential conflict, of the sort experienced during an
+* extension upgrade.
+*/
+int
+postgis_guc_find_option(const char *name)
+{
+ const char **key = &name;
+ struct config_generic **res;
+
+ /*
+ * By equating const char ** with struct config_generic *, we are assuming
+ * the name field is first in config_generic.
+ */
+ res = (struct config_generic **) bsearch((void *) &key,
+ (void *) get_guc_variables(),
+ GetNumConfigOptions(),
+ sizeof(struct config_generic *),
+ postgis_guc_var_compare);
+
+ /* Found nothing? Good */
+ if ( ! res ) return 0;
+
+ /* Hm, you found something, but maybe it's just a placeholder? */
+ /* We'll consider a placehold a "not found" */
+ if ( (*res)->flags & GUC_CUSTOM_PLACEHOLDER )
+ return 0;
+
+ return 1;
+}
+
Modified: trunk/libpgcommon/lwgeom_pg.h
===================================================================
--- trunk/libpgcommon/lwgeom_pg.h 2016-02-24 14:32:39 UTC (rev 14679)
+++ trunk/libpgcommon/lwgeom_pg.h 2016-02-24 15:19:04 UTC (rev 14680)
@@ -60,6 +60,13 @@
#endif /* POSTGIS_DEBUG_LEVEL */
+/*
+* GUC name search functions stolen from PostgreSQL to
+* support searching for already-defined GUC variables
+*/
+int postgis_guc_name_compare(const char *namea, const char *nameb);
+int postgis_guc_var_compare(const void *a, const void *b);
+int postgis_guc_find_option(const char *name);
/*
* Standard macro for reporting parser errors to PostgreSQL
Modified: trunk/postgis/lwgeom_backend_api.c
===================================================================
--- trunk/postgis/lwgeom_backend_api.c 2016-02-24 14:32:39 UTC (rev 14679)
+++ trunk/postgis/lwgeom_backend_api.c 2016-02-24 15:19:04 UTC (rev 14680)
@@ -113,88 +113,6 @@
lwpgerror("Can't find %s geometry backend", newvalue );
}
-
-#include "utils/guc.h"
-#include "utils/guc_tables.h"
-
-
-/*
- * the bare comparison function for GUC names
- */
-static int
-guc_name_compare(const char *namea, const char *nameb)
-{
- /*
- * The temptation to use strcasecmp() here must be resisted, because the
- * array ordering has to remain stable across setlocale() calls. So, build
- * our own with a simple ASCII-only downcasing.
- */
- while (*namea && *nameb)
- {
- char cha = *namea++;
- char chb = *nameb++;
-
- if (cha >= 'A' && cha <= 'Z')
- cha += 'a' - 'A';
- if (chb >= 'A' && chb <= 'Z')
- chb += 'a' - 'A';
- if (cha != chb)
- return cha - chb;
- }
- if (*namea)
- return 1; /* a is longer */
- if (*nameb)
- return -1; /* b is longer */
- return 0;
-}
-
-/*
- * comparator for qsorting and bsearching guc_variables array
- */
-static int
-guc_var_compare(const void *a, const void *b)
-{
- const struct config_generic *confa = *(struct config_generic * const *) a;
- const struct config_generic *confb = *(struct config_generic * const *) b;
-
- return guc_name_compare(confa->name, confb->name);
-}
-
-/*
-* This is copied from the top half of the find_option function
-* in postgresql's guc.c. We search the guc_variables for our option.
-* Then we make sure it's not a placeholder. Only then are we sure
-* we have a potential conflict, of the sort experienced during an
-* extension upgrade.
-*/
-static int
-guc_find_option(const char *name)
-{
- const char **key = &name;
- struct config_generic **res;
-
- /*
- * By equating const char ** with struct config_generic *, we are assuming
- * the name field is first in config_generic.
- */
- res = (struct config_generic **) bsearch((void *) &key,
- (void *) get_guc_variables(),
- GetNumConfigOptions(),
- sizeof(struct config_generic *),
- guc_var_compare);
-
- /* Found nothing? Good */
- if ( ! res ) return 0;
-
- /* Hm, you found something, but maybe it's just a placeholder? */
- /* We'll consider a placehold a "not found" */
- if ( (*res)->flags & GUC_CUSTOM_PLACEHOLDER )
- return 0;
-
- return 1;
-}
-
-
void lwgeom_init_backend()
{
/* #2382 Before trying to create a user GUC, make sure */
@@ -210,7 +128,7 @@
/* callback to change which backend is in use by flipping a global variable */
/* over. This saves the overhead of looking up the engine every time, at */
/* the expense of the extra complexity. */
- if ( guc_find_option(guc_name) )
+ if ( postgis_guc_find_option(guc_name) )
{
/* In this narrow case the previously installed GUC is tied to the callback in */
/* the previously loaded library. Probably this is happening during an */
Modified: trunk/raster/rt_pg/rtpostgis.c
===================================================================
--- trunk/raster/rt_pg/rtpostgis.c 2016-02-24 14:32:39 UTC (rev 14679)
+++ trunk/raster/rt_pg/rtpostgis.c 2016-02-24 15:19:04 UTC (rev 14680)
@@ -385,50 +385,80 @@
/* Define custom GUC variables. */
- DefineCustomStringVariable(
- "postgis.gdal_datapath", /* name */
- "Path to GDAL data files.", /* short_desc */
- "Physical path to directory containing GDAL data files (sets the GDAL_DATA config option).", /* long_desc */
- &gdal_datapath, /* valueAddr */
- NULL, /* bootValue */
- PGC_SUSET, /* GucContext context */
- 0, /* int flags */
+ if ( postgis_guc_find_option("postgis.gdal_datapath") )
+ {
+ /* In this narrow case the previously installed GUC is tied to the callback in */
+ /* the previously loaded library. Probably this is happening during an */
+ /* upgrade, so the old library is where the callback ties to. */
+ elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", "postgis.gdal_datapath");
+ }
+ else
+ {
+ DefineCustomStringVariable(
+ "postgis.gdal_datapath", /* name */
+ "Path to GDAL data files.", /* short_desc */
+ "Physical path to directory containing GDAL data files (sets the GDAL_DATA config option).", /* long_desc */
+ &gdal_datapath, /* valueAddr */
+ NULL, /* bootValue */
+ PGC_SUSET, /* GucContext context */
+ 0, /* int flags */
#if POSTGIS_PGSQL_VERSION >= 91
- NULL, /* GucStringCheckHook check_hook */
+ NULL, /* GucStringCheckHook check_hook */
#endif
- rtpg_assignHookGDALDataPath, /* GucStringAssignHook assign_hook */
- NULL /* GucShowHook show_hook */
- );
+ rtpg_assignHookGDALDataPath, /* GucStringAssignHook assign_hook */
+ NULL /* GucShowHook show_hook */
+ );
+ }
- DefineCustomStringVariable(
- "postgis.gdal_enabled_drivers", /* name */
- "Enabled GDAL drivers.", /* short_desc */
- "List of enabled GDAL drivers by short name. To enable/disable all drivers, use 'ENABLE_ALL' or 'DISABLE_ALL' (sets the GDAL_SKIP config option).", /* long_desc */
- &gdal_enabled_drivers, /* valueAddr */
- boot_postgis_gdal_enabled_drivers, /* bootValue */
- PGC_SUSET, /* GucContext context */
- 0, /* int flags */
+ if ( postgis_guc_find_option("postgis.gdal_enabled_drivers") )
+ {
+ /* In this narrow case the previously installed GUC is tied to the callback in */
+ /* the previously loaded library. Probably this is happening during an */
+ /* upgrade, so the old library is where the callback ties to. */
+ elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", "postgis.gdal_enabled_drivers");
+ }
+ else
+ {
+ DefineCustomStringVariable(
+ "postgis.gdal_enabled_drivers", /* name */
+ "Enabled GDAL drivers.", /* short_desc */
+ "List of enabled GDAL drivers by short name. To enable/disable all drivers, use 'ENABLE_ALL' or 'DISABLE_ALL' (sets the GDAL_SKIP config option).", /* long_desc */
+ &gdal_enabled_drivers, /* valueAddr */
+ boot_postgis_gdal_enabled_drivers, /* bootValue */
+ PGC_SUSET, /* GucContext context */
+ 0, /* int flags */
#if POSTGIS_PGSQL_VERSION >= 91
- NULL, /* GucStringCheckHook check_hook */
+ NULL, /* GucStringCheckHook check_hook */
#endif
- rtpg_assignHookGDALEnabledDrivers, /* GucStringAssignHook assign_hook */
- NULL /* GucShowHook show_hook */
- );
+ rtpg_assignHookGDALEnabledDrivers, /* GucStringAssignHook assign_hook */
+ NULL /* GucShowHook show_hook */
+ );
+ }
- DefineCustomBoolVariable(
- "postgis.enable_outdb_rasters", /* name */
- "Enable Out-DB raster bands", /* short_desc */
- "If true, rasters can access data located outside the database", /* long_desc */
- &enable_outdb_rasters, /* valueAddr */
- boot_postgis_enable_outdb_rasters, /* bootValue */
- PGC_SUSET, /* GucContext context */
- 0, /* int flags */
+ if ( postgis_guc_find_option("postgis.enable_outdb_rasters") )
+ {
+ /* In this narrow case the previously installed GUC is tied to the callback in */
+ /* the previously loaded library. Probably this is happening during an */
+ /* upgrade, so the old library is where the callback ties to. */
+ elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", "postgis.enable_outdb_rasters");
+ }
+ else
+ {
+ DefineCustomBoolVariable(
+ "postgis.enable_outdb_rasters", /* name */
+ "Enable Out-DB raster bands", /* short_desc */
+ "If true, rasters can access data located outside the database", /* long_desc */
+ &enable_outdb_rasters, /* valueAddr */
+ boot_postgis_enable_outdb_rasters, /* bootValue */
+ PGC_SUSET, /* GucContext context */
+ 0, /* int flags */
#if POSTGIS_PGSQL_VERSION >= 91
- NULL, /* GucStringCheckHook check_hook */
+ NULL, /* GucStringCheckHook check_hook */
#endif
- rtpg_assignHookEnableOutDBRasters, /* GucBoolAssignHook assign_hook */
- NULL /* GucShowHook show_hook */
- );
+ rtpg_assignHookEnableOutDBRasters, /* GucBoolAssignHook assign_hook */
+ NULL /* GucShowHook show_hook */
+ );
+ }
/* free memory allocations */
pfree(boot_postgis_gdal_enabled_drivers);
More information about the postgis-tickets
mailing list