diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2004-03-19 18:58:07 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2004-03-19 18:58:07 +0000 |
commit | 0fdc6c4cc0a1b84844caa29b5a8fb6cb5f28b752 (patch) | |
tree | 9b256a6e4eb8a4862754fd12921cabbcecf5634e /src/bin/scripts | |
parent | 74ffc77279d092eb9e31c5e13a015173fca7addb (diff) | |
download | postgresql-0fdc6c4cc0a1b84844caa29b5a8fb6cb5f28b752.tar.gz postgresql-0fdc6c4cc0a1b84844caa29b5a8fb6cb5f28b752.zip |
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).
Diffstat (limited to 'src/bin/scripts')
-rw-r--r-- | src/bin/scripts/createlang.c | 34 | ||||
-rw-r--r-- | src/bin/scripts/droplang.c | 61 |
2 files changed, 79 insertions, 16 deletions
diff --git a/src/bin/scripts/createlang.c b/src/bin/scripts/createlang.c index d81f4207559..64e257bc2f0 100644 --- a/src/bin/scripts/createlang.c +++ b/src/bin/scripts/createlang.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/createlang.c,v 1.7 2003/11/29 19:52:07 pgsql Exp $ + * $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.8 2004/03/19 18:58:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,8 +49,10 @@ main(int argc, char *argv[]) char *p; bool handlerexists; + bool validatorexists; bool trusted; char *handler; + char *validator = NULL; char *object; PQExpBufferData sql; @@ -169,6 +171,7 @@ main(int argc, char *argv[]) { trusted = true; handler = "plpgsql_call_handler"; + validator = "plpgsql_validator"; object = "plpgsql"; } else if (strcmp(langname, "pltcl") == 0) @@ -229,13 +232,26 @@ main(int argc, char *argv[]) /* * Check whether the call handler exists */ - printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' AND prorettype = (SELECT oid FROM pg_type WHERE typname = 'language_handler') 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); /* - * Create the call handler and the language + * Check whether the validator exists + */ + if (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); + } + else + validatorexists = true; /* don't try to create it */ + + /* + * Create the function(s) and the language */ resetPQExpBuffer(&sql); @@ -244,10 +260,20 @@ main(int argc, char *argv[]) "CREATE FUNCTION \"%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", + validator, pglib, object); + appendPQExpBuffer(&sql, - "CREATE %sLANGUAGE \"%s\" HANDLER \"%s\";\n", + "CREATE %sLANGUAGE \"%s\" HANDLER \"%s\"", (trusted ? "TRUSTED " : ""), langname, handler); + if (validator) + appendPQExpBuffer(&sql, " VALIDATOR \"%s\"", validator); + + appendPQExpBuffer(&sql, ";\n"); + if (echo) printf("%s", sql.data); result = PQexec(conn, sql.data); 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); |