Skip to content

Commit 15c30b6

Browse files
committed
Be more wary about mixed-case database names and user names. Get
the CREATE DATABASE command right in pg_dump -C case.
1 parent 906254a commit 15c30b6

File tree

6 files changed

+131
-94
lines changed

6 files changed

+131
-94
lines changed

src/bin/pg_dump/common.c

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.61 2002/01/11 23:21:55 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.62 2002/02/11 00:18:20 tgl Exp $
1212
*
1313
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
1414
*
@@ -590,65 +590,3 @@ findFuncByName(FuncInfo *finfo, int numFuncs, const char *name)
590590
}
591591
return -1;
592592
}
593-
594-
/*
595-
* fmtId
596-
*
597-
* checks input string for non-lowercase characters
598-
* returns pointer to input string or string surrounded by double quotes
599-
*
600-
* Note that the returned string should be used immediately since it
601-
* uses a static buffer to hold the string. Non-reentrant but faster?
602-
*/
603-
const char *
604-
fmtId(const char *rawid, bool force_quotes)
605-
{
606-
static PQExpBuffer id_return = NULL;
607-
const char *cp;
608-
609-
if (!force_quotes)
610-
{
611-
/* do a quick check on the first character... */
612-
if (!islower((unsigned char) *rawid))
613-
force_quotes = true;
614-
/* otherwise check the entire string */
615-
else
616-
for (cp = rawid; *cp; cp++)
617-
{
618-
if (!(islower((unsigned char) *cp) ||
619-
isdigit((unsigned char) *cp) ||
620-
(*cp == '_')))
621-
{
622-
force_quotes = true;
623-
break;
624-
}
625-
}
626-
}
627-
628-
if (!force_quotes)
629-
return rawid; /* no quoting needed */
630-
631-
if (id_return)
632-
resetPQExpBuffer(id_return);
633-
else
634-
id_return = createPQExpBuffer();
635-
636-
appendPQExpBufferChar(id_return, '\"');
637-
for (cp = rawid; *cp; cp++)
638-
{
639-
/*
640-
* Did we find a double-quote in the string? Then make this a
641-
* double double-quote per SQL99. Before, we put in a
642-
* backslash/double-quote pair. - thomas 2000-08-05
643-
*/
644-
if (*cp == '\"')
645-
{
646-
appendPQExpBufferChar(id_return, '\"');
647-
appendPQExpBufferChar(id_return, '\"');
648-
}
649-
appendPQExpBufferChar(id_return, *cp);
650-
}
651-
appendPQExpBufferChar(id_return, '\"');
652-
653-
return id_return->data;
654-
} /* fmtId() */

src/bin/pg_dump/pg_backup.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.17 2001/10/28 06:25:58 momjian Exp $
18+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.18 2002/02/11 00:18:20 tgl Exp $
1919
*
2020
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
2121
*
@@ -136,10 +136,11 @@ extern void
136136
exit_horribly(Archive *AH, const char *modulename, const char *fmt,...)
137137
__attribute__((format(printf, 3, 4)));
138138

139-
extern char *
140-
simple_prompt(const char *prompt, int maxlen, bool echo);
139+
extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
141140

142-
/* Lets the archibe know we have a DB connection to shutdown if it dies */
141+
extern const char *fmtId(const char *identifier, bool force_quotes);
142+
143+
/* Lets the archive know we have a DB connection to shutdown if it dies */
143144

144145
PGconn *ConnectDatabase(Archive *AH,
145146
const char *dbname,

src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.41 2002/02/06 17:27:50 tgl Exp $
18+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.42 2002/02/11 00:18:20 tgl Exp $
1919
*
2020
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
2121
*
@@ -74,6 +74,7 @@
7474
#include "pg_backup_archiver.h"
7575
#include "pg_backup_db.h"
7676

77+
#include <ctype.h>
7778
#include <errno.h>
7879
#include <unistd.h> /* for dup */
7980

@@ -1953,7 +1954,7 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
19531954
* user, this won't do anything.
19541955
*
19551956
* If we're currently restoring right into a database, this will
1956-
* actuall establish a connection. Otherwise it puts a \connect into
1957+
* actually establish a connection. Otherwise it puts a \connect into
19571958
* the script output.
19581959
*/
19591960
static void
@@ -1974,7 +1975,8 @@ _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
19741975
PQExpBuffer qry = createPQExpBuffer();
19751976
PGresult *res;
19761977

1977-
appendPQExpBuffer(qry, "SET SESSION AUTHORIZATION '%s';", user);
1978+
appendPQExpBuffer(qry, "SET SESSION AUTHORIZATION %s;",
1979+
fmtId(user, false));
19781980
res = PQexec(AH->connection, qry->data);
19791981

19801982
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
@@ -1985,19 +1987,29 @@ _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
19851987
destroyPQExpBuffer(qry);
19861988
}
19871989
else
1988-
ahprintf(AH, "SET SESSION AUTHORIZATION '%s';\n\n", user);
1990+
ahprintf(AH, "SET SESSION AUTHORIZATION %s;\n\n",
1991+
fmtId(user, false));
19891992
}
1990-
/* When -R was given, don't do anything. */
19911993
else if (AH->ropt && AH->ropt->noReconnect)
1994+
{
1995+
/* When -R was given, don't do anything. */
19921996
return;
1993-
1997+
}
19941998
else if (RestoringToDB(AH))
19951999
ReconnectToServer(AH, dbname, user);
19962000
else
1997-
/* FIXME: does not handle mixed case user names */
1998-
ahprintf(AH, "\\connect %s %s\n\n",
1999-
dbname ? dbname : "-",
2000-
user ? user : "-");
2001+
{
2002+
PQExpBuffer qry = createPQExpBuffer();
2003+
2004+
appendPQExpBuffer(qry, "\\connect %s",
2005+
dbname ? fmtId(dbname, false) : "-");
2006+
appendPQExpBuffer(qry, " %s\n\n",
2007+
fmtId(user, false));
2008+
2009+
ahprintf(AH, qry->data);
2010+
2011+
destroyPQExpBuffer(qry);
2012+
}
20012013

20022014
/*
20032015
* NOTE: currUser keeps track of what the imaginary session user in
@@ -2025,6 +2037,69 @@ _reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te)
20252037
}
20262038

20272039

2040+
/*
2041+
* fmtId
2042+
*
2043+
* checks input string for non-lowercase characters
2044+
* returns pointer to input string or string surrounded by double quotes
2045+
*
2046+
* Note that the returned string should be used immediately since it
2047+
* uses a static buffer to hold the string. Non-reentrant but faster?
2048+
*/
2049+
const char *
2050+
fmtId(const char *rawid, bool force_quotes)
2051+
{
2052+
static PQExpBuffer id_return = NULL;
2053+
const char *cp;
2054+
2055+
if (!force_quotes)
2056+
{
2057+
/* do a quick check on the first character... */
2058+
if (!islower((unsigned char) *rawid))
2059+
force_quotes = true;
2060+
/* otherwise check the entire string */
2061+
else
2062+
for (cp = rawid; *cp; cp++)
2063+
{
2064+
if (!(islower((unsigned char) *cp) ||
2065+
isdigit((unsigned char) *cp) ||
2066+
(*cp == '_')))
2067+
{
2068+
force_quotes = true;
2069+
break;
2070+
}
2071+
}
2072+
}
2073+
2074+
if (!force_quotes)
2075+
return rawid; /* no quoting needed */
2076+
2077+
if (id_return)
2078+
resetPQExpBuffer(id_return);
2079+
else
2080+
id_return = createPQExpBuffer();
2081+
2082+
appendPQExpBufferChar(id_return, '\"');
2083+
for (cp = rawid; *cp; cp++)
2084+
{
2085+
/*
2086+
* Did we find a double-quote in the string? Then make this a
2087+
* double double-quote per SQL99. Before, we put in a
2088+
* backslash/double-quote pair. - thomas 2000-08-05
2089+
*/
2090+
if (*cp == '\"')
2091+
{
2092+
appendPQExpBufferChar(id_return, '\"');
2093+
appendPQExpBufferChar(id_return, '\"');
2094+
}
2095+
appendPQExpBufferChar(id_return, *cp);
2096+
}
2097+
appendPQExpBufferChar(id_return, '\"');
2098+
2099+
return id_return->data;
2100+
}
2101+
2102+
20282103
static int
20292104
_printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData)
20302105
{

src/bin/pg_dump/pg_dump.c

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*
2323
*
2424
* IDENTIFICATION
25-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.240 2002/02/06 17:27:50 tgl Exp $
25+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.241 2002/02/11 00:18:20 tgl Exp $
2626
*
2727
*-------------------------------------------------------------------------
2828
*/
@@ -1141,15 +1141,24 @@ dumpDatabase(Archive *AH)
11411141
PQExpBuffer creaQry = createPQExpBuffer();
11421142
PGresult *res;
11431143
int ntups;
1144-
int i_dba;
1144+
int i_dba,
1145+
i_encoding,
1146+
i_datpath;
1147+
const char *datname,
1148+
*dba,
1149+
*encoding,
1150+
*datpath;
1151+
1152+
datname = PQdb(g_conn);
11451153

11461154
if (g_verbose)
11471155
write_msg(NULL, "saving database definition\n");
11481156

1149-
/* Get the dba */
1150-
appendPQExpBuffer(dbQry, "select (select usename from pg_user where datdba = usesysid) as dba from pg_database"
1157+
/* Get the database owner and parameters from pg_database */
1158+
appendPQExpBuffer(dbQry, "select (select usename from pg_user where usesysid = datdba) as dba,"
1159+
" encoding, datpath from pg_database"
11511160
" where datname = ");
1152-
formatStringLiteral(dbQry, PQdb(g_conn), CONV_ALL);
1161+
formatStringLiteral(dbQry, datname, CONV_ALL);
11531162

11541163
res = PQexec(g_conn, dbQry->data);
11551164
if (!res ||
@@ -1165,24 +1174,39 @@ dumpDatabase(Archive *AH)
11651174

11661175
if (ntups <= 0)
11671176
{
1168-
write_msg(NULL, "missing pg_database entry for database \"%s\"\n", PQdb(g_conn));
1177+
write_msg(NULL, "missing pg_database entry for database \"%s\"\n",
1178+
datname);
11691179
exit_nicely();
11701180
}
11711181

11721182
if (ntups != 1)
11731183
{
11741184
write_msg(NULL, "query returned more than one (%d) pg_database entry for database \"%s\"\n",
1175-
ntups, PQdb(g_conn));
1185+
ntups, datname);
11761186
exit_nicely();
11771187
}
11781188

1179-
appendPQExpBuffer(creaQry, "Create Database \"%s\";\n", PQdb(g_conn));
1180-
appendPQExpBuffer(delQry, "Drop Database \"%s\";\n", PQdb(g_conn));
11811189
i_dba = PQfnumber(res, "dba");
1182-
1183-
ArchiveEntry(AH, "0" /* OID */ , PQdb(g_conn) /* Name */ , "DATABASE", NULL,
1190+
i_encoding = PQfnumber(res, "encoding");
1191+
i_datpath = PQfnumber(res, "datpath");
1192+
dba = PQgetvalue(res, 0, i_dba);
1193+
encoding = PQgetvalue(res, 0, i_encoding);
1194+
datpath = PQgetvalue(res, 0, i_datpath);
1195+
1196+
appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0",
1197+
fmtId(datname, force_quotes));
1198+
if (strlen(encoding) > 0)
1199+
appendPQExpBuffer(creaQry, " ENCODING = %s", encoding);
1200+
if (strlen(datpath) > 0)
1201+
appendPQExpBuffer(creaQry, " LOCATION = '%s'", datpath);
1202+
appendPQExpBuffer(creaQry, ";\n");
1203+
1204+
appendPQExpBuffer(delQry, "DROP DATABASE %s;\n",
1205+
fmtId(datname, force_quotes));
1206+
1207+
ArchiveEntry(AH, "0" /* OID */ , datname /* Name */ , "DATABASE", NULL,
11841208
creaQry->data /* Create */ , delQry->data /* Del */ ,
1185-
"" /* Copy */ , PQgetvalue(res, 0, i_dba) /* Owner */ ,
1209+
"" /* Copy */ , dba /* Owner */ ,
11861210
NULL /* Dumper */ , NULL /* Dumper Arg */ );
11871211

11881212
PQclear(res);

src/bin/pg_dump/pg_dump.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: pg_dump.h,v 1.77 2002/01/11 23:21:55 tgl Exp $
9+
* $Id: pg_dump.h,v 1.78 2002/02/11 00:18:20 tgl Exp $
1010
*
1111
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
1212
*
@@ -280,7 +280,6 @@ extern void dumpTables(Archive *fout, TableInfo *tbinfo, int numTables,
280280
const bool schemaOnly, const bool dataOnly);
281281
extern void dumpIndexes(Archive *fout, IndInfo *indinfo, int numIndexes,
282282
TableInfo *tbinfo, int numTables, const char *tablename);
283-
extern const char *fmtId(const char *identifier, bool force_quotes);
284283
extern void exit_nicely(void);
285284

286285
#endif /* PG_DUMP_H */

src/bin/pg_dump/pg_dumpall.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# and "pg_group" tables, which belong to the whole installation rather
77
# than any one individual database.
88
#
9-
# $Header: /cvsroot/pgsql/src/bin/pg_dump/Attic/pg_dumpall.sh,v 1.14 2002/01/09 04:56:44 momjian Exp $
9+
# $Header: /cvsroot/pgsql/src/bin/pg_dump/Attic/pg_dumpall.sh,v 1.15 2002/02/11 00:18:20 tgl Exp $
1010

1111
CMDNAME=`basename $0`
1212

@@ -217,7 +217,7 @@ while read DATABASE DBOWNER ENCODING ISTEMPLATE DBPATH; do
217217
echo "--"
218218
echo "-- Database $DATABASE"
219219
echo "--"
220-
echo "${BS}connect template1 $DBOWNER"
220+
echo "${BS}connect template1 \"$DBOWNER\""
221221

222222
if [ "$cleanschema" = yes -a "$DATABASE" != template1 ] ; then
223223
echo "DROP DATABASE \"$DATABASE\";"
@@ -234,7 +234,7 @@ while read DATABASE DBOWNER ENCODING ISTEMPLATE DBPATH; do
234234
echo "$createdbcmd;"
235235
fi
236236

237-
echo "${BS}connect $DATABASE $DBOWNER"
237+
echo "${BS}connect \"$DATABASE\" \"$DBOWNER\""
238238
echo "dumping database \"$DATABASE\"..." 1>&2
239239
$PGDUMP "$DATABASE" <&4
240240
if [ "$?" -ne 0 ] ; then

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy