aboutsummaryrefslogtreecommitdiff
path: root/src/bin/scripts
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-03-19 18:58:07 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-03-19 18:58:07 +0000
commit0fdc6c4cc0a1b84844caa29b5a8fb6cb5f28b752 (patch)
tree9b256a6e4eb8a4862754fd12921cabbcecf5634e /src/bin/scripts
parent74ffc77279d092eb9e31c5e13a015173fca7addb (diff)
downloadpostgresql-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.c34
-rw-r--r--src/bin/scripts/droplang.c61
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);