On 02/02/2010 10:23 PM, Tom Lane wrote:
> Joe Conway <m...@joeconway.com> writes:
>> Should I also be looking to replace all (or most) other instances of
>> PQsetdbLogin()?
> 
> I think we at least wanted to fix pg_dump(all)/pg_restore.  Not sure if
> the others are worth troubling over.

OK, this one includes pg_dump(all)/pg_restore and common.c from
bin/scripts (createdb, vacuumdb, etc). I still need to adjust the docs,
but other than that any remaining complaints?

Joe

Index: src/bin/pg_dump/pg_backup_db.c
===================================================================
RCS file: /opt/src/cvs/pgsql/src/bin/pg_dump/pg_backup_db.c,v
retrieving revision 1.85
diff -c -r1.85 pg_backup_db.c
*** src/bin/pg_dump/pg_backup_db.c	14 Dec 2009 00:39:11 -0000	1.85
--- src/bin/pg_dump/pg_backup_db.c	4 Feb 2010 03:57:42 -0000
***************
*** 154,163 ****
  
  	do
  	{
  		new_pass = false;
! 		newConn = PQsetdbLogin(PQhost(AH->connection), PQport(AH->connection),
! 							   NULL, NULL, newdb,
! 							   newuser, password);
  		if (!newConn)
  			die_horribly(AH, modulename, "failed to reconnect to database\n");
  
--- 154,187 ----
  
  	do
  	{
+ #define PARAMS_ARRAY_SIZE	7
+ 		const char **keywords = malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
+ 		const char **values = malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
+ 
+ 		if (!keywords || !values)
+ 			die_horribly(AH, modulename, "out of memory\n");
+ 
+ 		keywords[0]	= "host";
+ 		values[0]	= PQhost(AH->connection);
+ 		keywords[1]	= "port";
+ 		values[1]	= PQport(AH->connection);
+ 		keywords[2]	= "user";
+ 		values[2]	= newuser;
+ 		keywords[3]	= "password";
+ 		values[3]	= password;
+ 		keywords[4]	= "dbname";
+ 		values[4]	= newdb;
+ 		keywords[5]	= "fallback_application_name";
+ 		values[5]	= progname;
+ 		keywords[6]	= NULL;
+ 		values[6]	= NULL;
+ 
  		new_pass = false;
! 		newConn = PQconnectdbParams(keywords, values, true);
! 
! 		free(keywords);
! 		free(values);
! 
  		if (!newConn)
  			die_horribly(AH, modulename, "failed to reconnect to database\n");
  
***************
*** 237,245 ****
  	 */
  	do
  	{
  		new_pass = false;
! 		AH->connection = PQsetdbLogin(pghost, pgport, NULL, NULL,
! 									  dbname, username, password);
  
  		if (!AH->connection)
  			die_horribly(AH, modulename, "failed to connect to database\n");
--- 261,293 ----
  	 */
  	do
  	{
+ #define PARAMS_ARRAY_SIZE	7
+ 		const char **keywords = malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
+ 		const char **values = malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
+ 
+ 		if (!keywords || !values)
+ 			die_horribly(AH, modulename, "out of memory\n");
+ 
+ 		keywords[0]	= "host";
+ 		values[0]	= pghost;
+ 		keywords[1]	= "port";
+ 		values[1]	= pgport;
+ 		keywords[2]	= "user";
+ 		values[2]	= username;
+ 		keywords[3]	= "password";
+ 		values[3]	= password;
+ 		keywords[4]	= "dbname";
+ 		values[4]	= dbname;
+ 		keywords[5]	= "fallback_application_name";
+ 		values[5]	= progname;
+ 		keywords[6]	= NULL;
+ 		values[6]	= NULL;
+ 
  		new_pass = false;
! 		AH->connection = PQconnectdbParams(keywords, values, true);
! 
! 		free(keywords);
! 		free(values);
  
  		if (!AH->connection)
  			die_horribly(AH, modulename, "failed to connect to database\n");
***************
*** 697,699 ****
--- 745,748 ----
  	else
  		return false;
  }
+ 
Index: src/bin/pg_dump/pg_dumpall.c
===================================================================
RCS file: /opt/src/cvs/pgsql/src/bin/pg_dump/pg_dumpall.c,v
retrieving revision 1.131
diff -c -r1.131 pg_dumpall.c
*** src/bin/pg_dump/pg_dumpall.c	6 Jan 2010 03:34:41 -0000	1.131
--- src/bin/pg_dump/pg_dumpall.c	4 Feb 2010 03:55:45 -0000
***************
*** 1618,1625 ****
  	 */
  	do
  	{
  		new_pass = false;
! 		conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password);
  
  		if (!conn)
  		{
--- 1618,1653 ----
  	 */
  	do
  	{
+ #define PARAMS_ARRAY_SIZE	7
+ 		const char **keywords = malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
+ 		const char **values = malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
+ 
+ 		if (!keywords || !values)
+ 		{
+ 			fprintf(stderr, _("%s: out of memory\n"), progname);
+ 			exit(1);
+ 		}
+ 
+ 		keywords[0]	= "host";
+ 		values[0]	= pghost;
+ 		keywords[1]	= "port";
+ 		values[1]	= pgport;
+ 		keywords[2]	= "user";
+ 		values[2]	= pguser;
+ 		keywords[3]	= "password";
+ 		values[3]	= password;
+ 		keywords[4]	= "dbname";
+ 		values[4]	= dbname;
+ 		keywords[5]	= "fallback_application_name";
+ 		values[5]	= progname;
+ 		keywords[6]	= NULL;
+ 		values[6]	= NULL;
+ 
  		new_pass = false;
! 		conn = PQconnectdbParams(keywords, values, true);
! 
! 		free(keywords);
! 		free(values);
  
  		if (!conn)
  		{
Index: src/bin/psql/command.c
===================================================================
RCS file: /opt/src/cvs/pgsql/src/bin/psql/command.c,v
retrieving revision 1.213
diff -c -r1.213 command.c
*** src/bin/psql/command.c	2 Jan 2010 16:57:59 -0000	1.213
--- src/bin/psql/command.c	4 Feb 2010 01:18:34 -0000
***************
*** 1213,1219 ****
   * Connects to a database with given parameters. If there exists an
   * established connection, NULL values will be replaced with the ones
   * in the current connection. Otherwise NULL will be passed for that
!  * parameter to PQsetdbLogin(), so the libpq defaults will be used.
   *
   * In interactive mode, if connection fails with the given parameters,
   * the old connection will be kept.
--- 1213,1219 ----
   * Connects to a database with given parameters. If there exists an
   * established connection, NULL values will be replaced with the ones
   * in the current connection. Otherwise NULL will be passed for that
!  * parameter to PQconnectdbParams(), so the libpq defaults will be used.
   *
   * In interactive mode, if connection fails with the given parameters,
   * the old connection will be kept.
***************
*** 1255,1262 ****
  
  	while (true)
  	{
! 		n_conn = PQsetdbLogin(host, port, NULL, NULL,
! 							  dbname, user, password);
  
  		/* We can immediately discard the password -- no longer needed */
  		if (password)
--- 1255,1283 ----
  
  	while (true)
  	{
! #define PARAMS_ARRAY_SIZE	7
! 		const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
! 		const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
! 
! 		keywords[0]	= "host";
! 		values[0]	= host;
! 		keywords[1]	= "port";
! 		values[1]	= port;
! 		keywords[2]	= "user";
! 		values[2]	= user;
! 		keywords[3]	= "password";
! 		values[3]	= password;
! 		keywords[4]	= "dbname";
! 		values[4]	= dbname;
! 		keywords[5]	= "fallback_application_name";
! 		values[5]	= pset.progname;
! 		keywords[6]	= NULL;
! 		values[6]	= NULL;
! 
! 		n_conn = PQconnectdbParams(keywords, values, true);
! 
! 		free(keywords);
! 		free(values);
  
  		/* We can immediately discard the password -- no longer needed */
  		if (password)
Index: src/bin/psql/startup.c
===================================================================
RCS file: /opt/src/cvs/pgsql/src/bin/psql/startup.c,v
retrieving revision 1.159
diff -c -r1.159 startup.c
*** src/bin/psql/startup.c	28 Jan 2010 06:28:26 -0000	1.159
--- src/bin/psql/startup.c	4 Feb 2010 02:31:32 -0000
***************
*** 90,97 ****
  	char	   *password = NULL;
  	char	   *password_prompt = NULL;
  	bool		new_pass;
- 	const char *keywords[] = {"host","port","dbname","user",
- 							  "password","application_name",NULL};
  
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql"));
  
--- 90,95 ----
***************
*** 173,192 ****
  	/* loop until we have a password if requested by backend */
  	do
  	{
!         const char *values[] = {
!                   options.host,
!                   options.port,
!                   (options.action == ACT_LIST_DB && 
!                                options.dbname == NULL) ? "postgres" : options.dbname,
!                   options.username,
!                   password,
!                   pset.progname,
!                   NULL
!               };
!         
!         new_pass = false;
! 
!         pset.db = PQconnectdbParams(keywords, values);
  
  		if (PQstatus(pset.db) == CONNECTION_BAD &&
  			PQconnectionNeedsPassword(pset.db) &&
--- 171,201 ----
  	/* loop until we have a password if requested by backend */
  	do
  	{
! #define PARAMS_ARRAY_SIZE	7
! 		const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
! 		const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
! 
! 		keywords[0]	= "host";
! 		values[0]	= options.host;
! 		keywords[1]	= "port";
! 		values[1]	= options.port;
! 		keywords[2]	= "user";
! 		values[2]	= options.username;
! 		keywords[3]	= "password";
! 		values[3]	= password;
! 		keywords[4]	= "dbname";
! 		values[4]	= (options.action == ACT_LIST_DB &&
! 						options.dbname == NULL) ?
! 						"postgres" : options.dbname;
! 		keywords[5]	= "fallback_application_name";
! 		values[5]	= pset.progname;
! 		keywords[6]	= NULL;
! 		values[6]	= NULL;
! 
! 		new_pass = false;
! 		pset.db = PQconnectdbParams(keywords, values, true);
! 		free(keywords);
! 		free(values);
  
  		if (PQstatus(pset.db) == CONNECTION_BAD &&
  			PQconnectionNeedsPassword(pset.db) &&
Index: src/bin/scripts/common.c
===================================================================
RCS file: /opt/src/cvs/pgsql/src/bin/scripts/common.c,v
retrieving revision 1.38
diff -c -r1.38 common.c
*** src/bin/scripts/common.c	2 Jan 2010 16:58:00 -0000	1.38
--- src/bin/scripts/common.c	4 Feb 2010 03:54:14 -0000
***************
*** 108,115 ****
  	 */
  	do
  	{
  		new_pass = false;
! 		conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password);
  
  		if (!conn)
  		{
--- 108,143 ----
  	 */
  	do
  	{
+ #define PARAMS_ARRAY_SIZE	7
+ 		const char **keywords = malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
+ 		const char **values = malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
+ 
+ 		if (!keywords || !values)
+ 		{
+ 			fprintf(stderr, _("%s: out of memory\n"), progname);
+ 			exit(1);
+ 		}
+ 
+ 		keywords[0]	= "host";
+ 		values[0]	= pghost;
+ 		keywords[1]	= "port";
+ 		values[1]	= pgport;
+ 		keywords[2]	= "user";
+ 		values[2]	= pguser;
+ 		keywords[3]	= "password";
+ 		values[3]	= password;
+ 		keywords[4]	= "dbname";
+ 		values[4]	= dbname;
+ 		keywords[5]	= "fallback_application_name";
+ 		values[5]	= progname;
+ 		keywords[6]	= NULL;
+ 		values[6]	= NULL;
+ 
  		new_pass = false;
! 		conn = PQconnectdbParams(keywords, values, true);
! 
! 		free(keywords);
! 		free(values);
  
  		if (!conn)
  		{
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /opt/src/cvs/pgsql/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.385
diff -c -r1.385 fe-connect.c
*** src/interfaces/libpq/fe-connect.c	28 Jan 2010 06:28:26 -0000	1.385
--- src/interfaces/libpq/fe-connect.c	3 Feb 2010 16:56:45 -0000
***************
*** 269,275 ****
  			   PQExpBuffer errorMessage, bool use_defaults);
  static PQconninfoOption *conninfo_array_parse(const char **keywords,
  				const char **values, PQExpBuffer errorMessage,
! 				bool use_defaults);
  static char *conninfo_getval(PQconninfoOption *connOptions,
  				const char *keyword);
  static void defaultNoticeReceiver(void *arg, const PGresult *res);
--- 269,275 ----
  			   PQExpBuffer errorMessage, bool use_defaults);
  static PQconninfoOption *conninfo_array_parse(const char **keywords,
  				const char **values, PQExpBuffer errorMessage,
! 				bool use_defaults, bool expand_dbname);
  static char *conninfo_getval(PQconninfoOption *connOptions,
  				const char *keyword);
  static void defaultNoticeReceiver(void *arg, const PGresult *res);
***************
*** 336,344 ****
   * call succeeded.
   */
  PGconn *
! PQconnectdbParams(const char **keywords, const char **values)
  {
! 	PGconn	   *conn = PQconnectStartParams(keywords, values);
  
  	if (conn && conn->status != CONNECTION_BAD)
  		(void) connectDBComplete(conn);
--- 336,346 ----
   * call succeeded.
   */
  PGconn *
! PQconnectdbParams(const char **keywords,
! 				  const char **values,
! 				  bool expand_dbname)
  {
! 	PGconn	   *conn = PQconnectStartParams(keywords, values, expand_dbname);
  
  	if (conn && conn->status != CONNECTION_BAD)
  		(void) connectDBComplete(conn);
***************
*** 400,406 ****
   * See PQconnectPoll for more info.
   */
  PGconn *
! PQconnectStartParams(const char **keywords, const char **values)
  {
  	PGconn			   *conn;
  	PQconninfoOption   *connOptions;
--- 402,410 ----
   * See PQconnectPoll for more info.
   */
  PGconn *
! PQconnectStartParams(const char **keywords,
! 					 const char **values,
! 					 bool expand_dbname)
  {
  	PGconn			   *conn;
  	PQconninfoOption   *connOptions;
***************
*** 416,422 ****
  	 * Parse the conninfo arrays
  	 */
  	connOptions = conninfo_array_parse(keywords, values,
! 									   &conn->errorMessage, true);
  	if (connOptions == NULL)
  	{
  		conn->status = CONNECTION_BAD;
--- 420,427 ----
  	 * Parse the conninfo arrays
  	 */
  	connOptions = conninfo_array_parse(keywords, values,
! 									   &conn->errorMessage,
! 									   true, expand_dbname);
  	if (connOptions == NULL)
  	{
  		conn->status = CONNECTION_BAD;
***************
*** 3729,3744 ****
   * left in errorMessage.
   * Defaults are supplied (from a service file, environment variables, etc)
   * for unspecified options, but only if use_defaults is TRUE.
   */
  static PQconninfoOption *
  conninfo_array_parse(const char **keywords, const char **values,
! 					 PQExpBuffer errorMessage, bool use_defaults)
  {
  	char			   *tmp;
  	PQconninfoOption   *options;
  	PQconninfoOption   *option;
  	int					i = 0;
  
  	/* Make a working copy of PQconninfoOptions */
  	options = malloc(sizeof(PQconninfoOptions));
  	if (options == NULL)
--- 3734,3786 ----
   * left in errorMessage.
   * Defaults are supplied (from a service file, environment variables, etc)
   * for unspecified options, but only if use_defaults is TRUE.
+  *
+  * If expand_dbname is TRUE, and the value passed for keyword "dbname"
+  * contains an "=", assume it is a conninfo string and process it,
+  * overriding any previously processed conflicting keywords. Subsequent
+  * keywords will take precedence, however.
   */
  static PQconninfoOption *
  conninfo_array_parse(const char **keywords, const char **values,
! 					 PQExpBuffer errorMessage, bool use_defaults,
! 					 bool expand_dbname)
  {
  	char			   *tmp;
  	PQconninfoOption   *options;
+ 	PQconninfoOption   *str_options = NULL;
  	PQconninfoOption   *option;
  	int					i = 0;
  
+ 	/*
+ 	 * If expand_dbname is true, check keyword "dbname"
+ 	 * to see if val is actually a conninfo string
+ 	 */
+ 	while(expand_dbname && keywords[i])
+ 	{
+ 		const char *pname = keywords[i];
+ 		const char *pvalue  = values[i];
+ 
+ 		/* first find "dbname" if any */
+ 		if (strcmp(pname, "dbname") == 0)
+ 		{
+ 			/* next look for "=" in the value */
+ 			if (pvalue && strchr(pvalue, '='))
+ 			{
+ 				/*
+ 				 * Must be a conninfo string, so parse it, but do not
+ 				 * use defaults here -- those get picked up later.
+ 				 * We only want to override for those parameters actually
+ 				 * passed.
+ 				 */
+ 				str_options = conninfo_parse(pvalue, errorMessage, false);
+ 				if (str_options == NULL)
+ 					return NULL;
+ 			}
+ 			break;
+ 		}
+ 		++i;
+ 	}
+ 
  	/* Make a working copy of PQconninfoOptions */
  	options = malloc(sizeof(PQconninfoOptions));
  	if (options == NULL)
***************
*** 3749,3754 ****
--- 3791,3797 ----
  	}
  	memcpy(options, PQconninfoOptions, sizeof(PQconninfoOptions));
  
+ 	i = 0;
  	/* Parse the keywords/values arrays */
  	while(keywords[i])
  	{
***************
*** 3774,3792 ****
  				return NULL;
  			}
  
! 		    /*
! 		     * Store the value
! 		     */
! 		    if (option->val)
! 		    	free(option->val);
! 		    option->val = strdup(pvalue);
! 		    if (!option->val)
! 		    {
! 		    	printfPQExpBuffer(errorMessage,
! 		    					  libpq_gettext("out of memory\n"));
! 		    	PQconninfoFree(options);
! 		    	return NULL;
! 		    }
  		}
  		++i;
  	}
--- 3817,3867 ----
  				return NULL;
  			}
  
! 			/*
! 			 * If we are on the dbname parameter, and we have a parsed
! 			 * conninfo string, copy those parameters across, overriding
! 			 * any existing previous settings
! 			 */
! 			if (strcmp(pname, "dbname") == 0 && str_options)
! 			{
! 				PQconninfoOption *str_option;
! 
! 				for (str_option = str_options; str_option->keyword != NULL; str_option++)
! 				{
! 					if (str_option->val != NULL)
! 					{
! 						int			k;
! 
! 						for (k = 0; options[k].keyword; k++)
! 						{
! 							if (strcmp(options[k].keyword, str_option->keyword) == 0)
! 							{
! 								if (options[k].val)
! 									free(options[k].val);
! 								options[k].val = strdup(str_option->val);
! 								break;
! 							}
! 						}
! 					}
! 				}
! 				PQconninfoFree(str_options);
! 			}
! 			else
! 			{
! 				/*
! 				 * Store the value, overriding previous settings
! 				 */
! 				if (option->val)
! 					free(option->val);
! 				option->val = strdup(pvalue);
! 				if (!option->val)
! 				{
! 					printfPQExpBuffer(errorMessage,
! 									  libpq_gettext("out of memory\n"));
! 					PQconninfoFree(options);
! 					return NULL;
! 				}
! 			}
  		}
  		++i;
  	}
Index: src/interfaces/libpq/libpq-fe.h
===================================================================
RCS file: /opt/src/cvs/pgsql/src/interfaces/libpq/libpq-fe.h,v
retrieving revision 1.150
diff -c -r1.150 libpq-fe.h
*** src/interfaces/libpq/libpq-fe.h	28 Jan 2010 06:28:26 -0000	1.150
--- src/interfaces/libpq/libpq-fe.h	4 Feb 2010 01:20:00 -0000
***************
*** 226,237 ****
  /* make a new client connection to the backend */
  /* Asynchronous (non-blocking) */
  extern PGconn *PQconnectStart(const char *conninfo);
! extern PGconn *PQconnectStartParams(const char **keywords, const char **values);
  extern PostgresPollingStatusType PQconnectPoll(PGconn *conn);
  
  /* Synchronous (blocking) */
  extern PGconn *PQconnectdb(const char *conninfo);
! extern PGconn *PQconnectdbParams(const char **keywords, const char **values);
  extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
  			 const char *pgoptions, const char *pgtty,
  			 const char *dbName,
--- 226,239 ----
  /* make a new client connection to the backend */
  /* Asynchronous (non-blocking) */
  extern PGconn *PQconnectStart(const char *conninfo);
! extern PGconn *PQconnectStartParams(const char **keywords,
! 			 const char **values, bool expand_dbname);
  extern PostgresPollingStatusType PQconnectPoll(PGconn *conn);
  
  /* Synchronous (blocking) */
  extern PGconn *PQconnectdb(const char *conninfo);
! extern PGconn *PQconnectdbParams(const char **keywords,
! 			 const char **values, bool expand_dbname);
  extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
  			 const char *pgoptions, const char *pgtty,
  			 const char *dbName,

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to