*** a/src/backend/utils/fmgr/dfmgr.c --- b/src/backend/utils/fmgr/dfmgr.c *************** *** 19,28 **** --- 19,29 ---- #ifndef WIN32_ONLY_COMPILER #include "dynloader.h" #else #include "port/dynloader/win32.h" #endif + #include "lib/stringinfo.h" #include "miscadmin.h" #include "utils/dynamic_loader.h" #include "utils/hsearch.h" *************** PGFunction *** 163,172 **** --- 164,213 ---- lookup_external_function(void *filehandle, char *funcname) { return (PGFunction) pg_dlsym(filehandle, funcname); } + /* + * Detailed error report when module incompatibility is detected. + */ + + #define MAGIC_FIELD_TEST(field) do { \ + if (srv->field != mod->field) { \ + if (det->len) \ + appendStringInfo(det, ", "); \ + appendStringInfo(det, "%s: %d != %d", #field, mod->field, srv->field); \ + } \ + } while (0) + + static void + module_incompat_error(const Pg_magic_struct *mod, const Pg_magic_struct *srv, const char *libname) + { + StringInfo det; + + if (mod->version != srv->version) + ereport(ERROR, + (errmsg("incompatible library \"%s\": version mismatch", + libname), + errdetail("Server is version %d.%d, library is version %d.%d.", + srv->version / 100, + srv->version % 100, + mod->version / 100, + mod->version % 100))); + + det = makeStringInfo(); + + MAGIC_FIELD_TEST(funcmaxargs); + MAGIC_FIELD_TEST(indexmaxkeys); + MAGIC_FIELD_TEST(namedatalen); + MAGIC_FIELD_TEST(float4byval); + MAGIC_FIELD_TEST(float8byval); + + ereport(ERROR, + (errmsg("incompatible library \"%s\": magic block mismatch: %s", + libname, det->data))); + } + #undef MAGIC_FIELD_TEST /* * Load the specified dynamic-link library file, unless it already is * loaded. Return the pg_dl* handle for the file. * *************** internal_load_library(const char *libnam *** 255,281 **** /* try to unlink library */ 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))); } } else { /* try to unlink library */ --- 296,306 ---- /* try to unlink library */ pg_dlclose(file_scanner->handle); free((char *) file_scanner); ! module_incompat_error(&module_magic_data, &magic_data, libname); } } else { /* try to unlink library */