If a loadable module has wrong values in its magic block, spell out
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 3 Sep 2008 22:34:50 +0000 (22:34 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 3 Sep 2008 22:34:50 +0000 (22:34 +0000)
exactly what they are in the complaint message.  Marko Kreen,
some editorialization by me.

src/backend/utils/fmgr/dfmgr.c
src/include/fmgr.h

index 743df3a916ec1fb1df5be57829a05b281f506054..eedab5f30b666af3f7667e3cc2bb718acc907e5e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.96 2008/01/01 19:45:53 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.97 2008/09/03 22:34:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,7 @@
 #else
 #include "port/dynloader/win32.h"
 #endif
+#include "lib/stringinfo.h"
 #include "miscadmin.h"
 #include "utils/dynamic_loader.h"
 #include "utils/hsearch.h"
@@ -71,6 +72,8 @@ static DynamicFileList *file_tail = NULL;
 char      *Dynamic_library_path;
 
 static void *internal_load_library(const char *libname);
+static void incompatible_module_error(const char *libname,
+                                   const Pg_magic_struct *module_magic_data);
 static void internal_unload_library(const char *libname);
 static bool file_exists(const char *name);
 static char *expand_dynamic_library_name(const char *name);
@@ -257,23 +260,8 @@ internal_load_library(const char *libname)
                pg_dlclose(file_scanner->handle);
                free((char *) file_scanner);
 
-               /*
-                * Report suitable error.  It's probably not worth writing a
-                * separate error message for each field; only the most common
-                * case of wrong major version gets its own message.
-                */
-               if (module_magic_data.version != magic_data.version)
-                   ereport(ERROR,
-                    (errmsg("incompatible library \"%s\": version mismatch",
-                            libname),
-                     errdetail("Server is version %d.%d, library is version %d.%d.",
-                               magic_data.version / 100,
-                               magic_data.version % 100,
-                               module_magic_data.version / 100,
-                               module_magic_data.version % 100)));
-               ereport(ERROR,
-                (errmsg("incompatible library \"%s\": magic block mismatch",
-                        libname)));
+               /* issue suitable complaint */
+               incompatible_module_error(libname, &module_magic_data);
            }
        }
        else
@@ -306,6 +294,93 @@ internal_load_library(const char *libname)
    return file_scanner->handle;
 }
 
+/*
+ * Report a suitable error for an incompatible magic block.
+ */
+static void
+incompatible_module_error(const char *libname,
+                         const Pg_magic_struct *module_magic_data)
+{
+   StringInfoData  details;
+
+   /*
+    * If the version doesn't match, just report that, because the rest of the
+    * block might not even have the fields we expect.
+    */
+   if (magic_data.version != module_magic_data->version)
+       ereport(ERROR,
+               (errmsg("incompatible library \"%s\": version mismatch",
+                       libname),
+                errdetail("Server is version %d.%d, library is version %d.%d.",
+                          magic_data.version / 100,
+                          magic_data.version % 100,
+                          module_magic_data->version / 100,
+                          module_magic_data->version % 100)));
+
+   /*
+    * Otherwise, spell out which fields don't agree.
+    *
+    * XXX this code has to be adjusted any time the set of fields in a magic
+    * block change!
+    */
+   initStringInfo(&details);
+
+   if (module_magic_data->funcmaxargs != magic_data.funcmaxargs)
+   {
+       if (details.len)
+           appendStringInfoChar(&details, '\n');
+       appendStringInfo(&details,
+                        _("Server has FUNC_MAX_ARGS = %d, library has %d."),
+                        magic_data.funcmaxargs,
+                        module_magic_data->funcmaxargs);
+   }
+   if (module_magic_data->indexmaxkeys != magic_data.indexmaxkeys)
+   {
+       if (details.len)
+           appendStringInfoChar(&details, '\n');
+       appendStringInfo(&details,
+                        _("Server has INDEX_MAX_KEYS = %d, library has %d."),
+                        magic_data.indexmaxkeys,
+                        module_magic_data->indexmaxkeys);
+   }
+   if (module_magic_data->namedatalen != magic_data.namedatalen)
+   {
+       if (details.len)
+           appendStringInfoChar(&details, '\n');
+       appendStringInfo(&details,
+                        _("Server has NAMEDATALEN = %d, library has %d."),
+                        magic_data.namedatalen,
+                        module_magic_data->namedatalen);
+   }
+   if (module_magic_data->float4byval != magic_data.float4byval)
+   {
+       if (details.len)
+           appendStringInfoChar(&details, '\n');
+       appendStringInfo(&details,
+                        _("Server has FLOAT4PASSBYVAL = %s, library has %s."),
+                        magic_data.float4byval ? "true" : "false",
+                        module_magic_data->float4byval ? "true" : "false");
+   }
+   if (module_magic_data->float8byval != magic_data.float8byval)
+   {
+       if (details.len)
+           appendStringInfoChar(&details, '\n');
+       appendStringInfo(&details,
+                        _("Server has FLOAT8PASSBYVAL = %s, library has %s."),
+                        magic_data.float8byval ? "true" : "false",
+                        module_magic_data->float8byval ? "true" : "false");
+   }
+
+   if (details.len == 0)
+       appendStringInfo(&details,
+                        _("Magic block has unexpected length or padding difference."));
+
+   ereport(ERROR,
+           (errmsg("incompatible library \"%s\": magic block mismatch",
+                   libname),
+            errdetail("%s", details.data)));
+}
+
 /*
  * Unload the specified dynamic-link library file, if it is loaded.
  *
index f0cc26f531182017503110980542ae89d47b05cf..c348086fbc8e3770658504dd8d7e08217b959e61 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/fmgr.h,v 1.59 2008/05/15 00:17:41 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/fmgr.h,v 1.60 2008/09/03 22:34:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -357,6 +357,9 @@ extern int no_such_variable
  *
  * Note: we compare magic blocks with memcmp(), so there had better not be
  * any alignment pad bytes in them.
+ *
+ * Note: when changing the contents of magic blocks, be sure to adjust the
+ * incompatible_module_error() function in dfmgr.c.
  *-------------------------------------------------------------------------
  */