Be more wary about mixed-case database names and user names. Get
the CREATE DATABASE command right in pg_dump -C case.
This commit is contained in:
parent
906254a53c
commit
15c30b6f9a
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 - dave@bensoft.com - version 1.13.dhb.2
|
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
|
||||||
*
|
*
|
||||||
@ -590,65 +590,3 @@ findFuncByName(FuncInfo *finfo, int numFuncs, const char *name)
|
|||||||
}
|
}
|
||||||
return -1;
|
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() */
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 - pjw@rhyme.com.au
|
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
|
||||||
*
|
*
|
||||||
@ -136,10 +136,11 @@ extern void
|
|||||||
exit_horribly(Archive *AH, const char *modulename, const char *fmt,...)
|
exit_horribly(Archive *AH, const char *modulename, const char *fmt,...)
|
||||||
__attribute__((format(printf, 3, 4)));
|
__attribute__((format(printf, 3, 4)));
|
||||||
|
|
||||||
extern char *
|
extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
|
||||||
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,
|
PGconn *ConnectDatabase(Archive *AH,
|
||||||
const char *dbname,
|
const char *dbname,
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 - pjw@rhyme.com.au
|
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
|
||||||
*
|
*
|
||||||
@ -74,6 +74,7 @@
|
|||||||
#include "pg_backup_archiver.h"
|
#include "pg_backup_archiver.h"
|
||||||
#include "pg_backup_db.h"
|
#include "pg_backup_db.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h> /* for dup */
|
#include <unistd.h> /* for dup */
|
||||||
|
|
||||||
@ -1953,7 +1954,7 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
|
|||||||
* user, this won't do anything.
|
* user, this won't do anything.
|
||||||
*
|
*
|
||||||
* If we're currently restoring right into a database, this will
|
* 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.
|
* the script output.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
@ -1974,7 +1975,8 @@ _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
|
|||||||
PQExpBuffer qry = createPQExpBuffer();
|
PQExpBuffer qry = createPQExpBuffer();
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
|
|
||||||
appendPQExpBuffer(qry, "SET SESSION AUTHORIZATION '%s';", user);
|
appendPQExpBuffer(qry, "SET SESSION AUTHORIZATION %s;",
|
||||||
|
fmtId(user, false));
|
||||||
res = PQexec(AH->connection, qry->data);
|
res = PQexec(AH->connection, qry->data);
|
||||||
|
|
||||||
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
|
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
@ -1985,19 +1987,29 @@ _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
|
|||||||
destroyPQExpBuffer(qry);
|
destroyPQExpBuffer(qry);
|
||||||
}
|
}
|
||||||
else
|
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)
|
else if (AH->ropt && AH->ropt->noReconnect)
|
||||||
|
{
|
||||||
|
/* When -R was given, don't do anything. */
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
else if (RestoringToDB(AH))
|
else if (RestoringToDB(AH))
|
||||||
ReconnectToServer(AH, dbname, user);
|
ReconnectToServer(AH, dbname, user);
|
||||||
else
|
else
|
||||||
/* FIXME: does not handle mixed case user names */
|
{
|
||||||
ahprintf(AH, "\\connect %s %s\n\n",
|
PQExpBuffer qry = createPQExpBuffer();
|
||||||
dbname ? dbname : "-",
|
|
||||||
user ? user : "-");
|
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
|
* 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
|
static int
|
||||||
_printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData)
|
_printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData)
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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();
|
PQExpBuffer creaQry = createPQExpBuffer();
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
int ntups;
|
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)
|
if (g_verbose)
|
||||||
write_msg(NULL, "saving database definition\n");
|
write_msg(NULL, "saving database definition\n");
|
||||||
|
|
||||||
/* Get the dba */
|
/* Get the database owner and parameters from pg_database */
|
||||||
appendPQExpBuffer(dbQry, "select (select usename from pg_user where datdba = usesysid) as dba from pg_database"
|
appendPQExpBuffer(dbQry, "select (select usename from pg_user where usesysid = datdba) as dba,"
|
||||||
|
" encoding, datpath from pg_database"
|
||||||
" where datname = ");
|
" where datname = ");
|
||||||
formatStringLiteral(dbQry, PQdb(g_conn), CONV_ALL);
|
formatStringLiteral(dbQry, datname, CONV_ALL);
|
||||||
|
|
||||||
res = PQexec(g_conn, dbQry->data);
|
res = PQexec(g_conn, dbQry->data);
|
||||||
if (!res ||
|
if (!res ||
|
||||||
@ -1165,24 +1174,39 @@ dumpDatabase(Archive *AH)
|
|||||||
|
|
||||||
if (ntups <= 0)
|
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();
|
exit_nicely();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntups != 1)
|
if (ntups != 1)
|
||||||
{
|
{
|
||||||
write_msg(NULL, "query returned more than one (%d) pg_database entry for database \"%s\"\n",
|
write_msg(NULL, "query returned more than one (%d) pg_database entry for database \"%s\"\n",
|
||||||
ntups, PQdb(g_conn));
|
ntups, datname);
|
||||||
exit_nicely();
|
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");
|
i_dba = PQfnumber(res, "dba");
|
||||||
|
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);
|
||||||
|
|
||||||
ArchiveEntry(AH, "0" /* OID */ , PQdb(g_conn) /* Name */ , "DATABASE", NULL,
|
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 */ ,
|
creaQry->data /* Create */ , delQry->data /* Del */ ,
|
||||||
"" /* Copy */ , PQgetvalue(res, 0, i_dba) /* Owner */ ,
|
"" /* Copy */ , dba /* Owner */ ,
|
||||||
NULL /* Dumper */ , NULL /* Dumper Arg */ );
|
NULL /* Dumper */ , NULL /* Dumper Arg */ );
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 - dave@bensoft.com - version 1.13.dhb.2
|
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
|
||||||
*
|
*
|
||||||
@ -280,7 +280,6 @@ extern void dumpTables(Archive *fout, TableInfo *tbinfo, int numTables,
|
|||||||
const bool schemaOnly, const bool dataOnly);
|
const bool schemaOnly, const bool dataOnly);
|
||||||
extern void dumpIndexes(Archive *fout, IndInfo *indinfo, int numIndexes,
|
extern void dumpIndexes(Archive *fout, IndInfo *indinfo, int numIndexes,
|
||||||
TableInfo *tbinfo, int numTables, const char *tablename);
|
TableInfo *tbinfo, int numTables, const char *tablename);
|
||||||
extern const char *fmtId(const char *identifier, bool force_quotes);
|
|
||||||
extern void exit_nicely(void);
|
extern void exit_nicely(void);
|
||||||
|
|
||||||
#endif /* PG_DUMP_H */
|
#endif /* PG_DUMP_H */
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
# and "pg_group" tables, which belong to the whole installation rather
|
# and "pg_group" tables, which belong to the whole installation rather
|
||||||
# than any one individual database.
|
# 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`
|
CMDNAME=`basename $0`
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ while read DATABASE DBOWNER ENCODING ISTEMPLATE DBPATH; do
|
|||||||
echo "--"
|
echo "--"
|
||||||
echo "-- Database $DATABASE"
|
echo "-- Database $DATABASE"
|
||||||
echo "--"
|
echo "--"
|
||||||
echo "${BS}connect template1 $DBOWNER"
|
echo "${BS}connect template1 \"$DBOWNER\""
|
||||||
|
|
||||||
if [ "$cleanschema" = yes -a "$DATABASE" != template1 ] ; then
|
if [ "$cleanschema" = yes -a "$DATABASE" != template1 ] ; then
|
||||||
echo "DROP DATABASE \"$DATABASE\";"
|
echo "DROP DATABASE \"$DATABASE\";"
|
||||||
@ -234,7 +234,7 @@ while read DATABASE DBOWNER ENCODING ISTEMPLATE DBPATH; do
|
|||||||
echo "$createdbcmd;"
|
echo "$createdbcmd;"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "${BS}connect $DATABASE $DBOWNER"
|
echo "${BS}connect \"$DATABASE\" \"$DBOWNER\""
|
||||||
echo "dumping database \"$DATABASE\"..." 1>&2
|
echo "dumping database \"$DATABASE\"..." 1>&2
|
||||||
$PGDUMP "$DATABASE" <&4
|
$PGDUMP "$DATABASE" <&4
|
||||||
if [ "$?" -ne 0 ] ; then
|
if [ "$?" -ne 0 ] ; then
|
||||||
|
Loading…
x
Reference in New Issue
Block a user