diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 86ca52a92403b2b183230dca4568008fe9d443a2..ec76ecdb99712abc54e04a68c1f7791bd5c3161a 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -12,7 +12,7 @@ * by PostgreSQL * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.413 2005/07/02 17:01:51 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.414 2005/07/10 14:26:29 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -2258,6 +2258,7 @@ getFuncs(int *numFuncs) int i_proargtypes; int i_prorettype; int i_proacl; + int i_is_pl_handler; /* Make sure we are in proper schema */ selectSourceSchema("pg_catalog"); @@ -2266,15 +2267,36 @@ getFuncs(int *numFuncs) if (g_fout->remoteVersion >= 70300) { + /* + * We now collect info on pg_catalog resident functions, but + * only if they are language call handlers or validators, and + * only for non-default languages (i.e. not internal/C/SQL). + */ appendPQExpBuffer(query, "SELECT tableoid, oid, proname, prolang, " "pronargs, proargtypes, prorettype, proacl, " "pronamespace, " - "(select usename from pg_user where proowner = usesysid) as usename " + "(select usename from pg_user " + " where proowner = usesysid) as usename, " + "CASE WHEN oid IN " + " (select lanplcallfoid from pg_language " + " where lanplcallfoid != 0) THEN true " + " WHEN oid IN " + " (select lanvalidator from pg_language " + " where lanplcallfoid != 0) THEN true " + " ELSE false END AS is_pl_handler " "FROM pg_proc " "WHERE NOT proisagg " - "AND pronamespace != " - "(select oid from pg_namespace where nspname = 'pg_catalog')"); + "AND (pronamespace != " + " (select oid from pg_namespace " + " where nspname = 'pg_catalog')" + " OR oid IN " + " (select lanplcallfoid from pg_language " + " where lanplcallfoid != 0) " + " OR oid IN " + " (select lanvalidator from pg_language " + " where lanplcallfoid != 0))" + ); } else if (g_fout->remoteVersion >= 70100) { @@ -2283,7 +2305,9 @@ getFuncs(int *numFuncs) "pronargs, proargtypes, prorettype, " "'{=X}' as proacl, " "0::oid as pronamespace, " - "(select usename from pg_user where proowner = usesysid) as usename " + "(select usename from pg_user " + " where proowner = usesysid) as usename, " + "false AS is_pl_handler " "FROM pg_proc " "where pg_proc.oid > '%u'::oid", g_last_builtin_oid); @@ -2292,12 +2316,15 @@ getFuncs(int *numFuncs) { appendPQExpBuffer(query, "SELECT " - "(SELECT oid FROM pg_class WHERE relname = 'pg_proc') AS tableoid, " + "(SELECT oid FROM pg_class " + " WHERE relname = 'pg_proc') AS tableoid, " "oid, proname, prolang, " "pronargs, proargtypes, prorettype, " "'{=X}' as proacl, " "0::oid as pronamespace, " - "(select usename from pg_user where proowner = usesysid) as usename " + "(select usename from pg_user " + " where proowner = usesysid) as usename, " + "false AS is_pl_handler " "FROM pg_proc " "where pg_proc.oid > '%u'::oid", g_last_builtin_oid); @@ -2322,6 +2349,7 @@ getFuncs(int *numFuncs) i_proargtypes = PQfnumber(res, "proargtypes"); i_prorettype = PQfnumber(res, "prorettype"); i_proacl = PQfnumber(res, "proacl"); + i_is_pl_handler = PQfnumber(res,"is_pl_handler"); for (i = 0; i < ntups; i++) { @@ -2330,13 +2358,16 @@ getFuncs(int *numFuncs) finfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); AssignDumpId(&finfo[i].dobj); finfo[i].dobj.name = strdup(PQgetvalue(res, i, i_proname)); - finfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_pronamespace)), + finfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_pronamespace)), finfo[i].dobj.catId.oid); finfo[i].usename = strdup(PQgetvalue(res, i, i_usename)); finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang)); finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype)); finfo[i].proacl = strdup(PQgetvalue(res, i, i_proacl)); finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs)); + finfo[i].isProlangFunc = + strcmp(PQgetvalue(res, i, i_is_pl_handler), "t") == 0; if (finfo[i].nargs == 0) finfo[i].argtypes = NULL; else @@ -2347,7 +2378,8 @@ getFuncs(int *numFuncs) } if (strlen(finfo[i].usename) == 0) - write_msg(NULL, "WARNING: owner of function \"%s\" appears to be invalid\n", + write_msg(NULL, + "WARNING: owner of function \"%s\" appears to be invalid\n", finfo[i].dobj.name); } @@ -5040,23 +5072,19 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) return; /* - * Current theory is to dump PLs iff their underlying functions will - * be dumped (are in a dumpable namespace, or have a non-system OID in - * pre-7.3 databases). Actually, we treat the PL itself as being in + * We dump PLs iff their underlying call handler functions have been + * marked as language functions (or have a non-system OID in + * pre-7.3 databases). We treat the PL itself as being in * the underlying function's namespace, though it isn't really. This * avoids searchpath problems for the HANDLER clause. * - * If the underlying function is in the pg_catalog namespace, we won't - * have loaded it into finfo[] at all; therefore, treat failure to - * find it in finfo[] as indicating we shouldn't dump it, not as an - * error condition. Ditto for the validator. */ funcInfo = findFuncByOid(plang->lanplcallfoid); if (funcInfo == NULL) return; - if (!funcInfo->dobj.namespace->dump) + if (!funcInfo->isProlangFunc && !funcInfo->dobj.namespace->dump) return; if (OidIsValid(plang->lanvalidator)) @@ -5254,10 +5282,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo) char **argmodes = NULL; char **argnames = NULL; - /* Dump only funcs in dumpable namespaces */ - if (!finfo->dobj.namespace->dump || dataOnly) + /* Dump only funcs in dumpable namespaces, or needed language handlers */ + if ((!finfo->isProlangFunc && !finfo->dobj.namespace->dump) || dataOnly) return; + query = createPQExpBuffer(); q = createPQExpBuffer(); delqry = createPQExpBuffer(); diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 7b0c51aa4ff57387d3dc52455126bc69bfa6b55d..eb5979483449005b976ab031600ea1b100e0252e 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.116 2005/06/30 03:03:02 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.117 2005/07/10 14:26:29 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -132,6 +132,7 @@ typedef struct _funcInfo Oid *argtypes; Oid prorettype; char *proacl; + bool isProlangFunc; } FuncInfo; /* AggInfo is a superset of FuncInfo */ diff --git a/src/bin/scripts/createlang.c b/src/bin/scripts/createlang.c index d088dad4f97a3901fbd15f7a43ed3121ab4c317a..78a46ed4a1774d803c82cbd8ea191d5514df68b8 100644 --- a/src/bin/scripts/createlang.c +++ b/src/bin/scripts/createlang.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.17 2005/06/22 16:45:50 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.18 2005/07/10 14:26:30 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -140,7 +140,10 @@ main(int argc, char *argv[]) conn = connectDatabase(dbname, host, port, username, password, progname); - printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", (CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" FROM pg_language WHERE lanispl IS TRUE;", _("Name"), _("yes"), _("no"), _("Trusted?")); + printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", (CASE WHEN lanpltrusted " + "THEN '%s' ELSE '%s' END) as \"%s\" FROM pg_language " + "WHERE lanispl IS TRUE;", + _("Name"), _("yes"), _("no"), _("Trusted?")); result = executeQuery(conn, sql.data, progname, echo); memset(&popt, 0, sizeof(popt)); @@ -209,8 +212,10 @@ main(int argc, char *argv[]) } else { - fprintf(stderr, _("%s: unsupported language \"%s\"\n"), progname, langname); - fprintf(stderr, _("Supported languages are plpgsql, pltcl, pltclu, plperl, plperlu, and plpythonu.\n")); + fprintf(stderr, _("%s: unsupported language \"%s\"\n"), + progname, langname); + fprintf(stderr, _("Supported languages are plpgsql, pltcl, pltclu, " + "plperl, plperlu, and plpythonu.\n")); exit(1); } @@ -219,13 +224,16 @@ main(int argc, char *argv[]) /* * Make sure the language isn't already installed */ - printfPQExpBuffer(&sql, "SELECT oid FROM pg_language WHERE lanname = '%s';", langname); + printfPQExpBuffer(&sql, + "SELECT oid FROM pg_language WHERE lanname = '%s';", + langname); result = executeQuery(conn, sql.data, progname, echo); if (PQntuples(result) > 0) { PQfinish(conn); fprintf(stderr, - _("%s: language \"%s\" is already installed in database \"%s\"\n"), + _("%s: language \"%s\" is already installed in " + "database \"%s\"\n"), progname, langname, dbname); /* separate exit status for "already installed" */ exit(2); @@ -235,7 +243,9 @@ main(int argc, char *argv[]) /* * Check whether the call handler exists */ - printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' AND prorettype = 'pg_catalog.language_handler'::regtype AND pronargs = 0;", handler); + printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' " + "AND prorettype = 'pg_catalog.language_handler'::regtype " + "AND pronargs = 0;", handler); result = executeQuery(conn, sql.data, progname, echo); handlerexists = (PQntuples(result) > 0); PQclear(result); @@ -245,7 +255,9 @@ main(int argc, char *argv[]) */ if (validator) { - printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' AND proargtypes[0] = 'pg_catalog.oid'::regtype AND pronargs = 1;", validator); + printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s'" + " AND proargtypes[0] = 'pg_catalog.oid'::regtype " + " AND pronargs = 1;", validator); result = executeQuery(conn, sql.data, progname, echo); validatorexists = (PQntuples(result) > 0); PQclear(result); @@ -260,20 +272,22 @@ main(int argc, char *argv[]) if (!handlerexists) appendPQExpBuffer(&sql, - "CREATE FUNCTION \"%s\" () RETURNS language_handler AS '%s/%s' LANGUAGE C;\n", + "CREATE FUNCTION pg_catalog.\"%s\" () RETURNS " + "language_handler AS '%s/%s' LANGUAGE C;\n", handler, pglib, object); if (!validatorexists) appendPQExpBuffer(&sql, - "CREATE FUNCTION \"%s\" (oid) RETURNS void AS '%s/%s' LANGUAGE C;\n", + "CREATE FUNCTION pg_catalog.\"%s\" (oid) RETURNS " + "void AS '%s/%s' LANGUAGE C;\n", validator, pglib, object); appendPQExpBuffer(&sql, - "CREATE %sLANGUAGE \"%s\" HANDLER \"%s\"", + "CREATE %sLANGUAGE \"%s\" HANDLER pg_catalog.\"%s\"", (trusted ? "TRUSTED " : ""), langname, handler); if (validator) - appendPQExpBuffer(&sql, " VALIDATOR \"%s\"", validator); + appendPQExpBuffer(&sql, " VALIDATOR pg_catalog.\"%s\"", validator); appendPQExpBuffer(&sql, ";\n"); diff --git a/src/bin/scripts/droplang.c b/src/bin/scripts/droplang.c index 5be336dd6d704a216e0cc3349442a69b1717f72c..5c3c226b75ed3b98c90dd2d4895e7e2e9924f962 100644 --- a/src/bin/scripts/droplang.c +++ b/src/bin/scripts/droplang.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.15 2005/06/14 02:57:45 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.16 2005/07/10 14:26:30 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -52,6 +52,8 @@ main(int argc, char *argv[]) Oid lanvalidator; char *handler; char *validator; + char *handler_ns; + char *validator_ns; bool keephandler; bool keepvalidator; @@ -135,9 +137,13 @@ main(int argc, char *argv[]) { printQueryOpt popt; - conn = connectDatabase(dbname, host, port, username, password, progname); + conn = connectDatabase(dbname, host, port, username, password, + progname); - printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", (CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" FROM pg_language WHERE lanispl IS TRUE;", _("Name"), _("yes"), _("no"), _("Trusted?")); + printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", (CASE " + "WHEN lanpltrusted THEN '%s' ELSE '%s' END) " + "as \"%s\" FROM pg_language WHERE lanispl IS TRUE;", + _("Name"), _("yes"), _("no"), _("Trusted?")); result = executeQuery(conn, sql.data, progname, echo); memset(&popt, 0, sizeof(popt)); @@ -153,8 +159,10 @@ main(int argc, char *argv[]) if (langname == NULL) { - fprintf(stderr, _("%s: missing required argument language name\n"), progname); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + fprintf(stderr, _("%s: missing required argument language name\n"), + progname); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); exit(1); } @@ -168,12 +176,15 @@ main(int argc, char *argv[]) * Make sure the language is installed and find the OIDs of the * handler and validator functions */ - printfPQExpBuffer(&sql, "SELECT lanplcallfoid, lanvalidator FROM pg_language WHERE lanname = '%s' AND lanispl;", langname); + printfPQExpBuffer(&sql, "SELECT lanplcallfoid, lanvalidator " + "FROM pg_language WHERE lanname = '%s' AND lanispl;", + langname); result = executeQuery(conn, sql.data, progname, echo); if (PQntuples(result) == 0) { PQfinish(conn); - fprintf(stderr, _("%s: language \"%s\" is not installed in database \"%s\"\n"), + fprintf(stderr, _("%s: language \"%s\" is not installed in " + "database \"%s\"\n"), progname, langname, dbname); exit(1); } @@ -184,13 +195,16 @@ main(int argc, char *argv[]) /* * Check that there are no functions left defined in that language */ - printfPQExpBuffer(&sql, "SELECT count(proname) FROM pg_proc P, pg_language L WHERE P.prolang = L.oid AND L.lanname = '%s';", langname); + printfPQExpBuffer(&sql, "SELECT count(proname) FROM pg_proc P, " + "pg_language L WHERE P.prolang = L.oid " + "AND L.lanname = '%s';", langname); result = executeQuery(conn, sql.data, progname, echo); if (strcmp(PQgetvalue(result, 0, 0), "0") != 0) { PQfinish(conn); fprintf(stderr, - _("%s: still %s functions declared in language \"%s\"; language not removed\n"), + _("%s: still %s functions declared in language \"%s\"; " + "language not removed\n"), progname, PQgetvalue(result, 0, 0), langname); exit(1); } @@ -199,7 +213,9 @@ main(int argc, char *argv[]) /* * Check that the handler function isn't used by some other language */ - printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language WHERE lanplcallfoid = %u AND lanname <> '%s';", lanplcallfoid, langname); + printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language " + "WHERE lanplcallfoid = %u AND lanname <> '%s';", + lanplcallfoid, langname); result = executeQuery(conn, sql.data, progname, echo); if (strcmp(PQgetvalue(result, 0, 0), "0") == 0) keephandler = false; @@ -212,20 +228,29 @@ main(int argc, char *argv[]) */ if (!keephandler) { - printfPQExpBuffer(&sql, "SELECT proname FROM pg_proc WHERE oid = %u;", lanplcallfoid); + printfPQExpBuffer(&sql, "SELECT proname, (SELECT nspname " + "FROM pg_namespace ns WHERE ns.oid = pronamespace) " + "AS prons FROM pg_proc WHERE oid = %u;", + lanplcallfoid); result = executeQuery(conn, sql.data, progname, echo); handler = strdup(PQgetvalue(result, 0, 0)); + handler_ns = strdup(PQgetvalue(result, 0, 1)); PQclear(result); } else + { handler = NULL; + handler_ns = NULL; + } /* * Check that the validator function isn't used by some other language */ if (OidIsValid(lanvalidator)) { - printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language WHERE lanvalidator = %u AND lanname <> '%s';", lanvalidator, langname); + printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language WHERE " + "lanvalidator = %u AND lanname <> '%s';", + lanvalidator, langname); result = executeQuery(conn, sql.data, progname, echo); if (strcmp(PQgetvalue(result, 0, 0), "0") == 0) keepvalidator = false; @@ -241,22 +266,31 @@ main(int argc, char *argv[]) */ if (!keepvalidator) { - printfPQExpBuffer(&sql, "SELECT proname FROM pg_proc WHERE oid = %u;", lanvalidator); + printfPQExpBuffer(&sql, "SELECT proname, (SELECT nspname " + "FROM pg_namespace ns WHERE ns.oid = pronamespace) " + "AS prons FROM pg_proc WHERE oid = %u;", + lanvalidator); result = executeQuery(conn, sql.data, progname, echo); validator = strdup(PQgetvalue(result, 0, 0)); + validator_ns = strdup(PQgetvalue(result, 0, 1)); PQclear(result); } else + { validator = NULL; + validator_ns = NULL; + } /* * Drop the language and the functions */ printfPQExpBuffer(&sql, "DROP LANGUAGE \"%s\";\n", langname); if (!keephandler) - appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\" ();\n", handler); + appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\".\"%s\" ();\n", + handler_ns, handler); if (!keepvalidator) - appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\" (oid);\n", validator); + appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\".\"%s\" (oid);\n", + validator_ns, validator); if (echo) printf("%s", sql.data); result = PQexec(conn, sql.data);