]> granicus.if.org Git - postgis/commitdiff
#3238, handle case of "placeholder" GUC as well as real GUC conflicts
authorPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 18 Aug 2015 20:59:00 +0000 (20:59 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 18 Aug 2015 20:59:00 +0000 (20:59 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@13937 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/lwgeom_backend_api.c

index 5fbfa54afef7768e822a0e36dd5cc62c8f212caa..9da26bf4d0652697b81b5dfc7181c7951a108a22 100644 (file)
@@ -102,6 +102,88 @@ static void lwgeom_backend_switch( const char* newvalue, void* extra )
     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 */
@@ -110,19 +192,19 @@ void lwgeom_init_backend()
        /* already be loaded in memory and the GUC already defined. We */
        /* can skip GUC definition in this case, so we just return. */
        static const char *guc_name = "postgis.backend";
-       const char *guc_installed = GetConfigOption(guc_name, TRUE, FALSE);
-
+       // const char *guc_installed = GetConfigOption(guc_name, TRUE, FALSE);
+               
        /* Uh oh, this GUC name already exists. Ordinarily we could just go on */
        /* our way, but the way the postgis.backend works is by using the "assign" */
        /* 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_installed )
+       if ( 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 */
                /* upgrade, so the old library is where the callback ties to. */
-               elog(WARNING, "'%s' is currently set to '%s' and cannot be changed until you reconnect", guc_name, guc_installed);
+               elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", guc_name);
                return;
        }
 
@@ -143,6 +225,19 @@ void lwgeom_init_backend()
                                );
 }
 
+#if 0
+
+backend/utils/misc/guc.h
+int GetNumConfigOptions(void) returns num_guc_variables
+
+backend/utils/misc/guc_tables.h
+struct config_generic ** get_guc_variables(void)
+
+
+
+
+#endif
+
 PG_FUNCTION_INFO_V1(intersects);
 Datum intersects(PG_FUNCTION_ARGS)
 {