Commit 07931080 authored by Bruce Momjian's avatar Bruce Momjian

This patch implements putting language handlers for the optional PLs

into pg_catalog rather than public, and supports dumping languages whose
handlers are found there. This will make it easier to drop the public
schema if desired.

Unlike the previous patch, the comments have been updated and I have
reformatted some code to meet Alvarro's request to stick to 80 cols. (I
actually aghree with this - it makes printing the code much nicer).

I think I did the right thing w.r.t versions earlier than 7.3, but I
have no real way of checking, so that should be checked by someone with
more/older knowledge than me ;-)

Andrew Dunstan
parent d51df918
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* by PostgreSQL * by PostgreSQL
* *
* IDENTIFICATION * 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) ...@@ -2258,6 +2258,7 @@ getFuncs(int *numFuncs)
int i_proargtypes; int i_proargtypes;
int i_prorettype; int i_prorettype;
int i_proacl; int i_proacl;
int i_is_pl_handler;
/* Make sure we are in proper schema */ /* Make sure we are in proper schema */
selectSourceSchema("pg_catalog"); selectSourceSchema("pg_catalog");
...@@ -2266,15 +2267,36 @@ getFuncs(int *numFuncs) ...@@ -2266,15 +2267,36 @@ getFuncs(int *numFuncs)
if (g_fout->remoteVersion >= 70300) 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, appendPQExpBuffer(query,
"SELECT tableoid, oid, proname, prolang, " "SELECT tableoid, oid, proname, prolang, "
"pronargs, proargtypes, prorettype, proacl, " "pronargs, proargtypes, prorettype, proacl, "
"pronamespace, " "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 " "FROM pg_proc "
"WHERE NOT proisagg " "WHERE NOT proisagg "
"AND pronamespace != " "AND (pronamespace != "
"(select oid from pg_namespace where nspname = 'pg_catalog')"); " (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) else if (g_fout->remoteVersion >= 70100)
{ {
...@@ -2283,7 +2305,9 @@ getFuncs(int *numFuncs) ...@@ -2283,7 +2305,9 @@ getFuncs(int *numFuncs)
"pronargs, proargtypes, prorettype, " "pronargs, proargtypes, prorettype, "
"'{=X}' as proacl, " "'{=X}' as proacl, "
"0::oid as pronamespace, " "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 " "FROM pg_proc "
"where pg_proc.oid > '%u'::oid", "where pg_proc.oid > '%u'::oid",
g_last_builtin_oid); g_last_builtin_oid);
...@@ -2292,12 +2316,15 @@ getFuncs(int *numFuncs) ...@@ -2292,12 +2316,15 @@ getFuncs(int *numFuncs)
{ {
appendPQExpBuffer(query, appendPQExpBuffer(query,
"SELECT " "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, " "oid, proname, prolang, "
"pronargs, proargtypes, prorettype, " "pronargs, proargtypes, prorettype, "
"'{=X}' as proacl, " "'{=X}' as proacl, "
"0::oid as pronamespace, " "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 " "FROM pg_proc "
"where pg_proc.oid > '%u'::oid", "where pg_proc.oid > '%u'::oid",
g_last_builtin_oid); g_last_builtin_oid);
...@@ -2322,6 +2349,7 @@ getFuncs(int *numFuncs) ...@@ -2322,6 +2349,7 @@ getFuncs(int *numFuncs)
i_proargtypes = PQfnumber(res, "proargtypes"); i_proargtypes = PQfnumber(res, "proargtypes");
i_prorettype = PQfnumber(res, "prorettype"); i_prorettype = PQfnumber(res, "prorettype");
i_proacl = PQfnumber(res, "proacl"); i_proacl = PQfnumber(res, "proacl");
i_is_pl_handler = PQfnumber(res,"is_pl_handler");
for (i = 0; i < ntups; i++) for (i = 0; i < ntups; i++)
{ {
...@@ -2330,13 +2358,16 @@ getFuncs(int *numFuncs) ...@@ -2330,13 +2358,16 @@ getFuncs(int *numFuncs)
finfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); finfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&finfo[i].dobj); AssignDumpId(&finfo[i].dobj);
finfo[i].dobj.name = strdup(PQgetvalue(res, i, i_proname)); 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].dobj.catId.oid);
finfo[i].usename = strdup(PQgetvalue(res, i, i_usename)); finfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang)); finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype)); finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
finfo[i].proacl = strdup(PQgetvalue(res, i, i_proacl)); finfo[i].proacl = strdup(PQgetvalue(res, i, i_proacl));
finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs)); 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) if (finfo[i].nargs == 0)
finfo[i].argtypes = NULL; finfo[i].argtypes = NULL;
else else
...@@ -2347,7 +2378,8 @@ getFuncs(int *numFuncs) ...@@ -2347,7 +2378,8 @@ getFuncs(int *numFuncs)
} }
if (strlen(finfo[i].usename) == 0) 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); finfo[i].dobj.name);
} }
...@@ -5040,23 +5072,19 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) ...@@ -5040,23 +5072,19 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
return; return;
/* /*
* Current theory is to dump PLs iff their underlying functions will * We dump PLs iff their underlying call handler functions have been
* be dumped (are in a dumpable namespace, or have a non-system OID in * marked as language functions (or have a non-system OID in
* pre-7.3 databases). Actually, we treat the PL itself as being in * pre-7.3 databases). We treat the PL itself as being in
* the underlying function's namespace, though it isn't really. This * the underlying function's namespace, though it isn't really. This
* avoids searchpath problems for the HANDLER clause. * 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); funcInfo = findFuncByOid(plang->lanplcallfoid);
if (funcInfo == NULL) if (funcInfo == NULL)
return; return;
if (!funcInfo->dobj.namespace->dump) if (!funcInfo->isProlangFunc && !funcInfo->dobj.namespace->dump)
return; return;
if (OidIsValid(plang->lanvalidator)) if (OidIsValid(plang->lanvalidator))
...@@ -5254,10 +5282,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo) ...@@ -5254,10 +5282,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
char **argmodes = NULL; char **argmodes = NULL;
char **argnames = NULL; char **argnames = NULL;
/* Dump only funcs in dumpable namespaces */ /* Dump only funcs in dumpable namespaces, or needed language handlers */
if (!finfo->dobj.namespace->dump || dataOnly) if ((!finfo->isProlangFunc && !finfo->dobj.namespace->dump) || dataOnly)
return; return;
query = createPQExpBuffer(); query = createPQExpBuffer();
q = createPQExpBuffer(); q = createPQExpBuffer();
delqry = createPQExpBuffer(); delqry = createPQExpBuffer();
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 ...@@ -132,6 +132,7 @@ typedef struct _funcInfo
Oid *argtypes; Oid *argtypes;
Oid prorettype; Oid prorettype;
char *proacl; char *proacl;
bool isProlangFunc;
} FuncInfo; } FuncInfo;
/* AggInfo is a superset of FuncInfo */ /* AggInfo is a superset of FuncInfo */
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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[]) ...@@ -140,7 +140,10 @@ main(int argc, char *argv[])
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); result = executeQuery(conn, sql.data, progname, echo);
memset(&popt, 0, sizeof(popt)); memset(&popt, 0, sizeof(popt));
...@@ -209,8 +212,10 @@ main(int argc, char *argv[]) ...@@ -209,8 +212,10 @@ main(int argc, char *argv[])
} }
else else
{ {
fprintf(stderr, _("%s: unsupported language \"%s\"\n"), progname, langname); fprintf(stderr, _("%s: unsupported language \"%s\"\n"),
fprintf(stderr, _("Supported languages are plpgsql, pltcl, pltclu, plperl, plperlu, and plpythonu.\n")); progname, langname);
fprintf(stderr, _("Supported languages are plpgsql, pltcl, pltclu, "
"plperl, plperlu, and plpythonu.\n"));
exit(1); exit(1);
} }
...@@ -219,13 +224,16 @@ main(int argc, char *argv[]) ...@@ -219,13 +224,16 @@ main(int argc, char *argv[])
/* /*
* Make sure the language isn't already installed * 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); result = executeQuery(conn, sql.data, progname, echo);
if (PQntuples(result) > 0) if (PQntuples(result) > 0)
{ {
PQfinish(conn); PQfinish(conn);
fprintf(stderr, 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); progname, langname, dbname);
/* separate exit status for "already installed" */ /* separate exit status for "already installed" */
exit(2); exit(2);
...@@ -235,7 +243,9 @@ main(int argc, char *argv[]) ...@@ -235,7 +243,9 @@ main(int argc, char *argv[])
/* /*
* Check whether the call handler exists * 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); result = executeQuery(conn, sql.data, progname, echo);
handlerexists = (PQntuples(result) > 0); handlerexists = (PQntuples(result) > 0);
PQclear(result); PQclear(result);
...@@ -245,7 +255,9 @@ main(int argc, char *argv[]) ...@@ -245,7 +255,9 @@ main(int argc, char *argv[])
*/ */
if (validator) 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); result = executeQuery(conn, sql.data, progname, echo);
validatorexists = (PQntuples(result) > 0); validatorexists = (PQntuples(result) > 0);
PQclear(result); PQclear(result);
...@@ -260,20 +272,22 @@ main(int argc, char *argv[]) ...@@ -260,20 +272,22 @@ main(int argc, char *argv[])
if (!handlerexists) if (!handlerexists)
appendPQExpBuffer(&sql, 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); handler, pglib, object);
if (!validatorexists) if (!validatorexists)
appendPQExpBuffer(&sql, 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); validator, pglib, object);
appendPQExpBuffer(&sql, appendPQExpBuffer(&sql,
"CREATE %sLANGUAGE \"%s\" HANDLER \"%s\"", "CREATE %sLANGUAGE \"%s\" HANDLER pg_catalog.\"%s\"",
(trusted ? "TRUSTED " : ""), langname, handler); (trusted ? "TRUSTED " : ""), langname, handler);
if (validator) if (validator)
appendPQExpBuffer(&sql, " VALIDATOR \"%s\"", validator); appendPQExpBuffer(&sql, " VALIDATOR pg_catalog.\"%s\"", validator);
appendPQExpBuffer(&sql, ";\n"); appendPQExpBuffer(&sql, ";\n");
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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[]) ...@@ -52,6 +52,8 @@ main(int argc, char *argv[])
Oid lanvalidator; Oid lanvalidator;
char *handler; char *handler;
char *validator; char *validator;
char *handler_ns;
char *validator_ns;
bool keephandler; bool keephandler;
bool keepvalidator; bool keepvalidator;
...@@ -135,9 +137,13 @@ main(int argc, char *argv[]) ...@@ -135,9 +137,13 @@ main(int argc, char *argv[])
{ {
printQueryOpt popt; 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); result = executeQuery(conn, sql.data, progname, echo);
memset(&popt, 0, sizeof(popt)); memset(&popt, 0, sizeof(popt));
...@@ -153,8 +159,10 @@ main(int argc, char *argv[]) ...@@ -153,8 +159,10 @@ main(int argc, char *argv[])
if (langname == NULL) if (langname == NULL)
{ {
fprintf(stderr, _("%s: missing required argument language name\n"), progname); fprintf(stderr, _("%s: missing required argument language name\n"),
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); progname);
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
progname);
exit(1); exit(1);
} }
...@@ -168,12 +176,15 @@ main(int argc, char *argv[]) ...@@ -168,12 +176,15 @@ main(int argc, char *argv[])
* Make sure the language is installed and find the OIDs of the * Make sure the language is installed and find the OIDs of the
* handler and validator functions * 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); result = executeQuery(conn, sql.data, progname, echo);
if (PQntuples(result) == 0) if (PQntuples(result) == 0)
{ {
PQfinish(conn); 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); progname, langname, dbname);
exit(1); exit(1);
} }
...@@ -184,13 +195,16 @@ main(int argc, char *argv[]) ...@@ -184,13 +195,16 @@ main(int argc, char *argv[])
/* /*
* Check that there are no functions left defined in that language * 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); result = executeQuery(conn, sql.data, progname, echo);
if (strcmp(PQgetvalue(result, 0, 0), "0") != 0) if (strcmp(PQgetvalue(result, 0, 0), "0") != 0)
{ {
PQfinish(conn); PQfinish(conn);
fprintf(stderr, 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); progname, PQgetvalue(result, 0, 0), langname);
exit(1); exit(1);
} }
...@@ -199,7 +213,9 @@ main(int argc, char *argv[]) ...@@ -199,7 +213,9 @@ main(int argc, char *argv[])
/* /*
* Check that the handler function isn't used by some other language * 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); result = executeQuery(conn, sql.data, progname, echo);
if (strcmp(PQgetvalue(result, 0, 0), "0") == 0) if (strcmp(PQgetvalue(result, 0, 0), "0") == 0)
keephandler = false; keephandler = false;
...@@ -212,20 +228,29 @@ main(int argc, char *argv[]) ...@@ -212,20 +228,29 @@ main(int argc, char *argv[])
*/ */
if (!keephandler) 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); result = executeQuery(conn, sql.data, progname, echo);
handler = strdup(PQgetvalue(result, 0, 0)); handler = strdup(PQgetvalue(result, 0, 0));
handler_ns = strdup(PQgetvalue(result, 0, 1));
PQclear(result); PQclear(result);
} }
else else
{
handler = NULL; handler = NULL;
handler_ns = NULL;
}
/* /*
* Check that the validator function isn't used by some other language * Check that the validator function isn't used by some other language
*/ */
if (OidIsValid(lanvalidator)) 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); result = executeQuery(conn, sql.data, progname, echo);
if (strcmp(PQgetvalue(result, 0, 0), "0") == 0) if (strcmp(PQgetvalue(result, 0, 0), "0") == 0)
keepvalidator = false; keepvalidator = false;
...@@ -241,22 +266,31 @@ main(int argc, char *argv[]) ...@@ -241,22 +266,31 @@ main(int argc, char *argv[])
*/ */
if (!keepvalidator) 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); result = executeQuery(conn, sql.data, progname, echo);
validator = strdup(PQgetvalue(result, 0, 0)); validator = strdup(PQgetvalue(result, 0, 0));
validator_ns = strdup(PQgetvalue(result, 0, 1));
PQclear(result); PQclear(result);
} }
else else
{
validator = NULL; validator = NULL;
validator_ns = NULL;
}
/* /*
* Drop the language and the functions * Drop the language and the functions
*/ */
printfPQExpBuffer(&sql, "DROP LANGUAGE \"%s\";\n", langname); printfPQExpBuffer(&sql, "DROP LANGUAGE \"%s\";\n", langname);
if (!keephandler) if (!keephandler)
appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\" ();\n", handler); appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\".\"%s\" ();\n",
handler_ns, handler);
if (!keepvalidator) if (!keepvalidator)
appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\" (oid);\n", validator); appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\".\"%s\" (oid);\n",
validator_ns, validator);
if (echo) if (echo)
printf("%s", sql.data); printf("%s", sql.data);
result = PQexec(conn, sql.data); result = PQexec(conn, sql.data);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment