Make createlang and droplang proof against weird search_path settings
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 15 Aug 2005 21:02:26 +0000 (21:02 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 15 Aug 2005 21:02:26 +0000 (21:02 +0000)
by forcing search_path to be just pg_catalog.

src/bin/scripts/common.c
src/bin/scripts/common.h
src/bin/scripts/createlang.c
src/bin/scripts/droplang.c

index 4bffa5003f8654d6ec8112bd03bda0f4d6930663..7036ef1b1c592e43850472d947c6b10d5e74dd87 100644 (file)
@@ -1,22 +1,28 @@
 /*-------------------------------------------------------------------------
  *
- * Miscellaneous shared code
+ *     common.c
+ *             Common support routines for bin/scripts/
+ *
  *
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/scripts/common.c,v 1.17 2005/02/22 04:41:30 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/scripts/common.c,v 1.18 2005/08/15 21:02:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres_fe.h"
-#include "common.h"
-#include "libpq-fe.h"
 
 #include <pwd.h>
 #include <unistd.h>
 
+#include "common.h"
+
+#ifndef HAVE_INT_OPTRESET
+int            optreset;
+#endif
+
 
 /*
  * Returns the current user name.
@@ -55,7 +61,8 @@ get_user_name(const char *progname)
  * options.
  */
 void
-handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
+handle_help_version_opts(int argc, char *argv[],
+                                                const char *fixed_progname, help_handler hlp)
 {
        if (argc > 1)
        {
@@ -79,7 +86,8 @@ handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, hel
  */
 PGconn *
 connectDatabase(const char *dbname, const char *pghost, const char *pgport,
-                const char *pguser, bool require_password, const char *progname)
+                               const char *pguser, bool require_password,
+                               const char *progname)
 {
        PGconn     *conn;
        char       *password = NULL;
@@ -146,8 +154,10 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
        if (!res ||
                PQresultStatus(res) != PGRES_TUPLES_OK)
        {
-               fprintf(stderr, _("%s: query failed: %s"), progname, PQerrorMessage(conn));
-               fprintf(stderr, _("%s: query was: %s\n"), progname, query);
+               fprintf(stderr, _("%s: query failed: %s"),
+                               progname, PQerrorMessage(conn));
+               fprintf(stderr, _("%s: query was: %s\n"),
+                               progname, query);
                PQfinish(conn);
                exit(1);
        }
@@ -156,6 +166,34 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
 }
 
 
+/*
+ * As above for a SQL command (which returns nothing).
+ */
+void
+executeCommand(PGconn *conn, const char *query,
+                          const char *progname, bool echo)
+{
+       PGresult   *res;
+
+       if (echo)
+               printf("%s\n", query);
+
+       res = PQexec(conn, query);
+       if (!res ||
+               PQresultStatus(res) != PGRES_COMMAND_OK)
+       {
+               fprintf(stderr, _("%s: query failed: %s"),
+                               progname, PQerrorMessage(conn));
+               fprintf(stderr, _("%s: query was: %s\n"),
+                               progname, query);
+               PQfinish(conn);
+               exit(1);
+       }
+
+       PQclear(res);
+}
+
+
 /*
  * Check yes/no answer in a localized way.     1=yes, 0=no, -1=neither.
  */
index 46e2a610aaa7dc9b73d12173e4a0a872a9781b5a..eac2674ea6c160140e2db265e8833165f5c6fddb 100644 (file)
@@ -1,24 +1,40 @@
-#include "postgres_fe.h"
+/*
+ *     common.h
+ *             Common support routines for bin/scripts/
+ *
+ *     Copyright (c) 2003-2005, PostgreSQL Global Development Group
+ *
+ *     $PostgreSQL: pgsql/src/bin/scripts/common.h,v 1.11 2005/08/15 21:02:26 tgl Exp $
+ */
+#ifndef COMMON_H
+#define COMMON_H
 
 #include "libpq-fe.h"
 #include "pqexpbuffer.h"
 #include "getopt_long.h"
 
 #ifndef HAVE_INT_OPTRESET
-int                    optreset;
+extern int             optreset;
 #endif
 
-const char *get_user_name(const char *progname);
+typedef void (*help_handler) (const char *progname);
 
-typedef void (*help_handler) (const char *);
+extern const char *get_user_name(const char *progname);
 
-void           handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp);
+extern void handle_help_version_opts(int argc, char *argv[],
+                                                                        const char *fixed_progname,
+                                                                        help_handler hlp);
 
-PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
-               const char *pguser, bool require_password, const char *progname);
+extern PGconn *connectDatabase(const char *dbname, const char *pghost,
+                                                          const char *pgport, const char *pguser,
+                                                          bool require_password, const char *progname);
 
-PGresult *
-                       executeQuery(PGconn *conn, const char *command, const char *progname, bool echo);
+extern PGresult *executeQuery(PGconn *conn, const char *query,
+                                                         const char *progname, bool echo);
 
-int
-                       check_yesno_response(const char *string);
+extern void executeCommand(PGconn *conn, const char *query,
+                                                  const char *progname, bool echo);
+
+extern int     check_yesno_response(const char *string);
+
+#endif /* COMMON_H */
index 78a46ed4a1774d803c82cbd8ea191d5514df68b8..082f348f9688f19bd4c6f7948012657b830d86e3 100644 (file)
@@ -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.18 2005/07/10 14:26:30 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.19 2005/08/15 21:02:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -138,11 +138,12 @@ 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;", 
+               printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
+                                                 "(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
+                                                 "FROM pg_catalog.pg_language WHERE lanispl;", 
                                                  _("Name"), _("yes"), _("no"), _("Trusted?"));
                result = executeQuery(conn, sql.data, progname, echo);
 
@@ -221,6 +222,13 @@ main(int argc, char *argv[])
 
        conn = connectDatabase(dbname, host, port, username, password, progname);
 
+       /*
+        * Force schema search path to be just pg_catalog, so that we don't
+        * have to be paranoid about search paths below.
+        */
+       executeCommand(conn, "SET search_path = pg_catalog;",
+                                  progname, echo);
+
        /*
         * Make sure the language isn't already installed
         */
@@ -232,8 +240,7 @@ main(int argc, char *argv[])
        {
                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);
@@ -244,7 +251,8 @@ 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 pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') "
+                                         "AND prorettype = 'language_handler'::regtype "
                                          "AND pronargs = 0;", handler);
        result = executeQuery(conn, sql.data, progname, echo);
        handlerexists = (PQntuples(result) > 0);
@@ -255,9 +263,10 @@ 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 pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') "
+                                                 "AND proargtypes[0] = 'oid'::regtype "
+                                                 "AND pronargs = 1;", validator);
                result = executeQuery(conn, sql.data, progname, echo);
                validatorexists = (PQntuples(result) > 0);
                PQclear(result);
@@ -267,27 +276,30 @@ main(int argc, char *argv[])
 
        /*
         * Create the function(s) and the language
+        *
+        * NOTE: the functions will be created in pg_catalog because
+        * of our previous "SET search_path".
         */
        resetPQExpBuffer(&sql);
 
        if (!handlerexists)
                appendPQExpBuffer(&sql,
-                                                 "CREATE FUNCTION pg_catalog.\"%s\" () RETURNS "
-                                                 "language_handler AS '%s/%s' LANGUAGE C;\n",
+                                                 "CREATE FUNCTION \"%s\" () RETURNS language_handler "
+                                                 "AS '%s/%s' LANGUAGE C;\n",
                                                  handler, pglib, object);
 
        if (!validatorexists)
                appendPQExpBuffer(&sql,
-                                                 "CREATE FUNCTION pg_catalog.\"%s\" (oid) RETURNS "
-                                                 "void AS '%s/%s' LANGUAGE C;\n",
+                                                 "CREATE FUNCTION \"%s\" (oid) RETURNS void "
+                                                 "AS '%s/%s' LANGUAGE C;\n",
                                                  validator, pglib, object);
 
        appendPQExpBuffer(&sql,
-                                         "CREATE %sLANGUAGE \"%s\" HANDLER pg_catalog.\"%s\"",
+                                         "CREATE %sLANGUAGE \"%s\" HANDLER \"%s\"",
                                          (trusted ? "TRUSTED " : ""), langname, handler);
 
        if (validator)
-               appendPQExpBuffer(&sql, " VALIDATOR pg_catalog.\"%s\"", validator);
+               appendPQExpBuffer(&sql, " VALIDATOR \"%s\"", validator);
 
        appendPQExpBuffer(&sql, ";\n");
 
index 5c3c226b75ed3b98c90dd2d4895e7e2e9924f962..52eb06986e6358b49cac21b332c129044569343d 100644 (file)
@@ -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.16 2005/07/10 14:26:30 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.17 2005/08/15 21:02:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -140,9 +140,9 @@ 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;", 
+               printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
+                                                 "(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
+                                                 "FROM pg_catalog.pg_language WHERE lanispl;", 
                                                  _("Name"), _("yes"), _("no"), _("Trusted?"));
                result = executeQuery(conn, sql.data, progname, echo);
 
@@ -172,6 +172,13 @@ main(int argc, char *argv[])
 
        conn = connectDatabase(dbname, host, port, username, password, progname);
 
+       /*
+        * Force schema search path to be just pg_catalog, so that we don't
+        * have to be paranoid about search paths below.
+        */
+       executeCommand(conn, "SET search_path = pg_catalog;",
+                                  progname, echo);
+
        /*
         * Make sure the language is installed and find the OIDs of the
         * handler and validator functions
@@ -248,8 +255,8 @@ main(int argc, char *argv[])
         */
        if (OidIsValid(lanvalidator))
        {
-               printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language WHERE "
-                                                 "lanvalidator = %u AND lanname <> '%s';", 
+               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)