mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-30 00:04:49 -04:00 
			
		
		
		
	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 | ||||
|  *	  $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 | ||||
|  * | ||||
| @ -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() */ | ||||
|  | ||||
| @ -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 - pjw@rhyme.com.au | ||||
|  * | ||||
| @ -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, | ||||
|  | ||||
| @ -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 - pjw@rhyme.com.au | ||||
|  * | ||||
| @ -74,6 +74,7 @@ | ||||
| #include "pg_backup_archiver.h" | ||||
| #include "pg_backup_db.h" | ||||
| 
 | ||||
| #include <ctype.h> | ||||
| #include <errno.h> | ||||
| #include <unistd.h>				/* 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) | ||||
| { | ||||
|  | ||||
| @ -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"); | ||||
| 	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 */ , | ||||
| 				 "" /* Copy */ , PQgetvalue(res, 0, i_dba) /* Owner */ , | ||||
| 				 "" /* Copy */ , dba /* Owner */ , | ||||
| 				 NULL /* Dumper */ , NULL /* Dumper Arg */ ); | ||||
| 
 | ||||
| 	PQclear(res); | ||||
|  | ||||
| @ -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 - 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); | ||||
| 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 */ | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user