Make createlang and droplang proof against weird search_path settings
authorTom Lane
Mon, 15 Aug 2005 21:02:26 +0000 (21:02 +0000)
committerTom Lane
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 
 #include 
 
+#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)