From 0fdc6c4cc0a1b84844caa29b5a8fb6cb5f28b752 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 19 Mar 2004 18:58:07 +0000 Subject: Create a validator for plpgsql, so that some minimal syntax checking is done at creation time for plpgsql functions. Improve createlang and droplang to support adding/dropping validators for PLs. Initial steps towards producing a syntax error position from plpgsql syntax errors (this part is a work in progress, and will change depending on outcome of current discussions). --- src/bin/scripts/droplang.c | 61 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 12 deletions(-) (limited to 'src/bin/scripts/droplang.c') diff --git a/src/bin/scripts/droplang.c b/src/bin/scripts/droplang.c index 93c68161995..43f57115f53 100644 --- a/src/bin/scripts/droplang.c +++ b/src/bin/scripts/droplang.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.6 2003/11/29 19:52:07 pgsql Exp $ + * $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.7 2004/03/19 18:58:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -14,6 +14,8 @@ #include "common.h" #include "print.h" +#define atooid(x) ((Oid) strtoul((x), NULL, 10)) + static void help(const char *progname); @@ -46,9 +48,12 @@ main(int argc, char *argv[]) char *langname = NULL; char *p; - char *lanplcallfoid; + Oid lanplcallfoid; + Oid lanvalidator; char *handler; + char *validator; bool keephandler; + bool keepvalidator; PQExpBufferData sql; @@ -159,10 +164,10 @@ main(int argc, char *argv[]) conn = connectDatabase(dbname, host, port, username, password, progname); /* - * Make sure the language is installed and find the OID of the handler - * function + * Make sure the language is installed and find the OIDs of the handler + * and validator functions */ - printfPQExpBuffer(&sql, "SELECT lanplcallfoid 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) { @@ -171,8 +176,9 @@ main(int argc, char *argv[]) progname, langname, dbname); exit(1); } - lanplcallfoid = PQgetvalue(result, 0, 0); - /* result not cleared! */ + lanplcallfoid = atooid(PQgetvalue(result, 0, 0)); + lanvalidator = atooid(PQgetvalue(result, 0, 1)); + PQclear(result); /* * Check that there are no functions left defined in that language @@ -192,7 +198,7 @@ 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 = %s 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; @@ -205,20 +211,51 @@ main(int argc, char *argv[]) */ if (!keephandler) { - printfPQExpBuffer(&sql, "SELECT proname FROM pg_proc WHERE oid = %s;", lanplcallfoid); + printfPQExpBuffer(&sql, "SELECT proname FROM pg_proc WHERE oid = %u;", lanplcallfoid); result = executeQuery(conn, sql.data, progname, echo); - handler = PQgetvalue(result, 0, 0); - /* result not cleared! */ + handler = strdup(PQgetvalue(result, 0, 0)); + PQclear(result); } else handler = NULL; /* - * Drop the language + * 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); + result = executeQuery(conn, sql.data, progname, echo); + if (strcmp(PQgetvalue(result, 0, 0), "0") == 0) + keepvalidator = false; + else + keepvalidator = true; + PQclear(result); + } + else + keepvalidator = true; /* don't try to delete it */ + + /* + * Find the validator name + */ + if (!keepvalidator) + { + printfPQExpBuffer(&sql, "SELECT proname FROM pg_proc WHERE oid = %u;", lanvalidator); + result = executeQuery(conn, sql.data, progname, echo); + validator = strdup(PQgetvalue(result, 0, 0)); + PQclear(result); + } + else + validator = NULL; + + /* + * Drop the language and the functions */ printfPQExpBuffer(&sql, "DROP LANGUAGE \"%s\";\n", langname); if (!keephandler) appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\" ();\n", handler); + if (!keepvalidator) + appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\" (oid);\n", validator); if (echo) printf("%s", sql.data); result = PQexec(conn, sql.data); -- cgit v1.2.3