Be more wary about mixed-case database names and user names. Get
authorTom Lane
Mon, 11 Feb 2002 00:18:20 +0000 (00:18 +0000)
committerTom Lane
Mon, 11 Feb 2002 00:18:20 +0000 (00:18 +0000)
the CREATE DATABASE command right in pg_dump -C case.

src/bin/pg_dump/common.c
src/bin/pg_dump/pg_backup.h
src/bin/pg_dump/pg_backup_archiver.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/bin/pg_dump/pg_dumpall.sh

index 1a32e22b22b3747a7c1bc8a90e7dbb4fcc5da147..907590518cf40834632e1e499a244ae65bd372de 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.61 2002/01/11 23:21:55 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.62 2002/02/11 00:18:20 tgl Exp $
  *
  * Modifications - 6/12/96 - [email protected] - version 1.13.dhb.2
  *
@@ -590,65 +590,3 @@ findFuncByName(FuncInfo *finfo, int numFuncs, const char *name)
    }
    return -1;
 }
-
-/*
- * fmtId
- *
- * checks input string for non-lowercase characters
- * returns pointer to input string or string surrounded by double quotes
- *
- * Note that the returned string should be used immediately since it
- * uses a static buffer to hold the string. Non-reentrant but faster?
- */
-const char *
-fmtId(const char *rawid, bool force_quotes)
-{
-   static PQExpBuffer id_return = NULL;
-   const char *cp;
-
-   if (!force_quotes)
-   {
-       /* do a quick check on the first character... */
-       if (!islower((unsigned char) *rawid))
-           force_quotes = true;
-       /* otherwise check the entire string */
-       else
-           for (cp = rawid; *cp; cp++)
-           {
-               if (!(islower((unsigned char) *cp) ||
-                     isdigit((unsigned char) *cp) ||
-                     (*cp == '_')))
-               {
-                   force_quotes = true;
-                   break;
-               }
-           }
-   }
-
-   if (!force_quotes)
-       return rawid;           /* no quoting needed */
-
-   if (id_return)
-       resetPQExpBuffer(id_return);
-   else
-       id_return = createPQExpBuffer();
-
-   appendPQExpBufferChar(id_return, '\"');
-   for (cp = rawid; *cp; cp++)
-   {
-       /*
-        * Did we find a double-quote in the string? Then make this a
-        * double double-quote per SQL99. Before, we put in a
-        * backslash/double-quote pair. - thomas 2000-08-05
-        */
-       if (*cp == '\"')
-       {
-           appendPQExpBufferChar(id_return, '\"');
-           appendPQExpBufferChar(id_return, '\"');
-       }
-       appendPQExpBufferChar(id_return, *cp);
-   }
-   appendPQExpBufferChar(id_return, '\"');
-
-   return id_return->data;
-}  /* fmtId() */
index b81b029e293cbdcd7b06e21d8ec43b669a71cbed..32d4c1e88eb1720eb38eec942b128953cbe77645 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *     $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.17 2001/10/28 06:25:58 momjian Exp $
+ *     $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.18 2002/02/11 00:18:20 tgl Exp $
  *
  * Modifications - 28-Jun-2000 - [email protected]
  *
@@ -136,10 +136,11 @@ extern void
 exit_horribly(Archive *AH, const char *modulename, const char *fmt,...)
 __attribute__((format(printf, 3, 4)));
 
-extern char *
-           simple_prompt(const char *prompt, int maxlen, bool echo);
+extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
 
-/* Lets the archibe know we have a DB connection to shutdown if it dies */
+extern const char *fmtId(const char *identifier, bool force_quotes);
+
+/* Lets the archive know we have a DB connection to shutdown if it dies */
 
 PGconn *ConnectDatabase(Archive *AH,
                const char *dbname,
index baebc56e4d4300c6d71c363c1e0d0cde9c1e3b11..2c8ea7d828f899992e07f98cc3008bd7d9eb1094 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *     $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.41 2002/02/06 17:27:50 tgl Exp $
+ *     $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.42 2002/02/11 00:18:20 tgl Exp $
  *
  * Modifications - 28-Jun-2000 - [email protected]
  *
@@ -74,6 +74,7 @@
 #include "pg_backup_archiver.h"
 #include "pg_backup_db.h"
 
+#include 
 #include 
 #include                 /* for dup */
 
@@ -1953,7 +1954,7 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
  * user, this won't do anything.
  *
  * If we're currently restoring right into a database, this will
- * actuall establish a connection. Otherwise it puts a \connect into
+ * actually establish a connection.    Otherwise it puts a \connect into
  * the script output.
  */
 static void
@@ -1974,7 +1975,8 @@ _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
            PQExpBuffer qry = createPQExpBuffer();
            PGresult   *res;
 
-           appendPQExpBuffer(qry, "SET SESSION AUTHORIZATION '%s';", user);
+           appendPQExpBuffer(qry, "SET SESSION AUTHORIZATION %s;",
+                             fmtId(user, false));
            res = PQexec(AH->connection, qry->data);
 
            if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
@@ -1985,19 +1987,29 @@ _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
            destroyPQExpBuffer(qry);
        }
        else
-           ahprintf(AH, "SET SESSION AUTHORIZATION '%s';\n\n", user);
+           ahprintf(AH, "SET SESSION AUTHORIZATION %s;\n\n",
+                    fmtId(user, false));
    }
-   /* When -R was given, don't do anything. */
    else if (AH->ropt && AH->ropt->noReconnect)
+   {
+       /* When -R was given, don't do anything. */
        return;
-
+   }
    else if (RestoringToDB(AH))
        ReconnectToServer(AH, dbname, user);
    else
-       /* FIXME: does not handle mixed case user names */
-       ahprintf(AH, "\\connect %s %s\n\n",
-                dbname ? dbname : "-",
-                user ? user : "-");
+   {
+       PQExpBuffer qry = createPQExpBuffer();
+
+       appendPQExpBuffer(qry, "\\connect %s",
+                         dbname ? fmtId(dbname, false) : "-");
+       appendPQExpBuffer(qry, " %s\n\n",
+                         fmtId(user, false));
+
+       ahprintf(AH, qry->data);
+
+       destroyPQExpBuffer(qry);
+   }
 
    /*
     * NOTE: currUser keeps track of what the imaginary session user in
@@ -2025,6 +2037,69 @@ _reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te)
 }
 
 
+/*
+ * fmtId
+ *
+ * checks input string for non-lowercase characters
+ * returns pointer to input string or string surrounded by double quotes
+ *
+ * Note that the returned string should be used immediately since it
+ * uses a static buffer to hold the string. Non-reentrant but faster?
+ */
+const char *
+fmtId(const char *rawid, bool force_quotes)
+{
+   static PQExpBuffer id_return = NULL;
+   const char *cp;
+
+   if (!force_quotes)
+   {
+       /* do a quick check on the first character... */
+       if (!islower((unsigned char) *rawid))
+           force_quotes = true;
+       /* otherwise check the entire string */
+       else
+           for (cp = rawid; *cp; cp++)
+           {
+               if (!(islower((unsigned char) *cp) ||
+                     isdigit((unsigned char) *cp) ||
+                     (*cp == '_')))
+               {
+                   force_quotes = true;
+                   break;
+               }
+           }
+   }
+
+   if (!force_quotes)
+       return rawid;           /* no quoting needed */
+
+   if (id_return)
+       resetPQExpBuffer(id_return);
+   else
+       id_return = createPQExpBuffer();
+
+   appendPQExpBufferChar(id_return, '\"');
+   for (cp = rawid; *cp; cp++)
+   {
+       /*
+        * Did we find a double-quote in the string? Then make this a
+        * double double-quote per SQL99. Before, we put in a
+        * backslash/double-quote pair. - thomas 2000-08-05
+        */
+       if (*cp == '\"')
+       {
+           appendPQExpBufferChar(id_return, '\"');
+           appendPQExpBufferChar(id_return, '\"');
+       }
+       appendPQExpBufferChar(id_return, *cp);
+   }
+   appendPQExpBufferChar(id_return, '\"');
+
+   return id_return->data;
+}
+
+
 static int
 _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData)
 {
index 0eb30b58d16f72ac53e0381bb411f8ad0df1db0b..64b4887e29c48e3dbaf06f1c7d7c57d37c6e223d 100644 (file)
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.240 2002/02/06 17:27:50 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.241 2002/02/11 00:18:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1141,15 +1141,24 @@ dumpDatabase(Archive *AH)
    PQExpBuffer creaQry = createPQExpBuffer();
    PGresult   *res;
    int         ntups;
-   int         i_dba;
+   int         i_dba,
+               i_encoding,
+               i_datpath;
+   const char *datname,
+              *dba,
+              *encoding,
+              *datpath;
+
+   datname = PQdb(g_conn);
 
    if (g_verbose)
        write_msg(NULL, "saving database definition\n");
 
-   /* Get the dba */
-   appendPQExpBuffer(dbQry, "select (select usename from pg_user where datdba = usesysid) as dba from pg_database"
+   /* Get the database owner and parameters from pg_database */
+   appendPQExpBuffer(dbQry, "select (select usename from pg_user where usesysid = datdba) as dba,"
+                     " encoding, datpath from pg_database"
                      " where datname = ");
-   formatStringLiteral(dbQry, PQdb(g_conn), CONV_ALL);
+   formatStringLiteral(dbQry, datname, CONV_ALL);
 
    res = PQexec(g_conn, dbQry->data);
    if (!res ||
@@ -1165,24 +1174,39 @@ dumpDatabase(Archive *AH)
 
    if (ntups <= 0)
    {
-       write_msg(NULL, "missing pg_database entry for database \"%s\"\n", PQdb(g_conn));
+       write_msg(NULL, "missing pg_database entry for database \"%s\"\n",
+                 datname);
        exit_nicely();
    }
 
    if (ntups != 1)
    {
        write_msg(NULL, "query returned more than one (%d) pg_database entry for database \"%s\"\n",
-                 ntups, PQdb(g_conn));
+                 ntups, datname);
        exit_nicely();
    }
 
-   appendPQExpBuffer(creaQry, "Create Database \"%s\";\n", PQdb(g_conn));
-   appendPQExpBuffer(delQry, "Drop Database \"%s\";\n", PQdb(g_conn));
    i_dba = PQfnumber(res, "dba");
-
-   ArchiveEntry(AH, "0" /* OID */ , PQdb(g_conn) /* Name */ , "DATABASE", NULL,
+   i_encoding = PQfnumber(res, "encoding");
+   i_datpath = PQfnumber(res, "datpath");
+   dba = PQgetvalue(res, 0, i_dba);
+   encoding = PQgetvalue(res, 0, i_encoding);
+   datpath = PQgetvalue(res, 0, i_datpath);
+
+   appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0",
+                     fmtId(datname, force_quotes));
+   if (strlen(encoding) > 0)
+       appendPQExpBuffer(creaQry, " ENCODING = %s", encoding);
+   if (strlen(datpath) > 0)
+       appendPQExpBuffer(creaQry, " LOCATION = '%s'", datpath);
+   appendPQExpBuffer(creaQry, ";\n");
+
+   appendPQExpBuffer(delQry, "DROP DATABASE %s;\n",
+                     fmtId(datname, force_quotes));
+
+   ArchiveEntry(AH, "0" /* OID */ , datname /* Name */ , "DATABASE", NULL,
                 creaQry->data /* Create */ , delQry->data /* Del */ ,
-                "" /* Copy */ , PQgetvalue(res, 0, i_dba) /* Owner */ ,
+                "" /* Copy */ , dba /* Owner */ ,
                 NULL /* Dumper */ , NULL /* Dumper Arg */ );
 
    PQclear(res);
index 3af39b8d2e59979132a84995d19f4a313dfc7764..0d69fda200b78945b175c50ddc45461987a662a1 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_dump.h,v 1.77 2002/01/11 23:21:55 tgl Exp $
+ * $Id: pg_dump.h,v 1.78 2002/02/11 00:18:20 tgl Exp $
  *
  * Modifications - 6/12/96 - [email protected] - version 1.13.dhb.2
  *
@@ -280,7 +280,6 @@ extern void dumpTables(Archive *fout, TableInfo *tbinfo, int numTables,
           const bool schemaOnly, const bool dataOnly);
 extern void dumpIndexes(Archive *fout, IndInfo *indinfo, int numIndexes,
            TableInfo *tbinfo, int numTables, const char *tablename);
-extern const char *fmtId(const char *identifier, bool force_quotes);
 extern void exit_nicely(void);
 
 #endif   /* PG_DUMP_H */
index 122cf75b2dc33ced1768101c7cbb080270cdf220..7aab5e2d7664e654bc225b79a069d28022ffd489 100644 (file)
@@ -6,7 +6,7 @@
 # and "pg_group" tables, which belong to the whole installation rather
 # than any one individual database.
 #
-# $Header: /cvsroot/pgsql/src/bin/pg_dump/Attic/pg_dumpall.sh,v 1.14 2002/01/09 04:56:44 momjian Exp $
+# $Header: /cvsroot/pgsql/src/bin/pg_dump/Attic/pg_dumpall.sh,v 1.15 2002/02/11 00:18:20 tgl Exp $
 
 CMDNAME=`basename $0`
 
@@ -217,7 +217,7 @@ while read DATABASE DBOWNER ENCODING ISTEMPLATE DBPATH; do
     echo "--"
     echo "-- Database $DATABASE"
     echo "--"
-    echo "${BS}connect template1 $DBOWNER"
+    echo "${BS}connect template1 \"$DBOWNER\""
 
     if [ "$cleanschema" = yes -a "$DATABASE" != template1 ] ; then
         echo "DROP DATABASE \"$DATABASE\";"
@@ -234,7 +234,7 @@ while read DATABASE DBOWNER ENCODING ISTEMPLATE DBPATH; do
    echo "$createdbcmd;"
     fi
 
-    echo "${BS}connect $DATABASE $DBOWNER"
+    echo "${BS}connect \"$DATABASE\" \"$DBOWNER\""
     echo "dumping database \"$DATABASE\"..." 1>&2
     $PGDUMP "$DATABASE" <&4
     if [ "$?" -ne 0 ] ; then