On Fri, Jul 24, 2009 at 2:23 AM, Magnus Hagander<mag...@hagander.net> wrote:
>>
>> 1) it introduces a dependency for -lpgport when compiling a client
>> that uses libpq
>>    http://archives.postgresql.org/pgsql-hackers/2009-07/msg01511.php
>
> For other parts of libpgport that are needed, we pull in the
> individual source files. We specifically *don't* link libpq with
> libpgport, for a reason. There's a comment in the Makefile that
> explains why.
>

ok, attached a version that modifies src/interfaces/libpq/Makefile to
push chklocale.o and eliminate the dependency on libpgport, this
change also fixes the compile problem on windows

still, i'm not sure this patch is doing anything useful... i
initialized a cluster with utf8 and my system is using utf8 but when
executing my test script with client_encoding=auto it gets SQL_ASCII

postg...@casanova1:~/pg_releases/pgtests$ locale
LANG=es_EC.UTF-8
LC_CTYPE="es_EC.UTF-8"
LC_NUMERIC="es_EC.UTF-8"
LC_TIME="es_EC.UTF-8"
LC_COLLATE="es_EC.UTF-8"
LC_MONETARY="es_EC.UTF-8"
LC_MESSAGES="es_EC.UTF-8"
LC_PAPER="es_EC.UTF-8"
LC_NAME="es_EC.UTF-8"
LC_ADDRESS="es_EC.UTF-8"
LC_TELEPHONE="es_EC.UTF-8"
LC_MEASUREMENT="es_EC.UTF-8"
LC_IDENTIFICATION="es_EC.UTF-8"
LC_ALL=
postg...@casanova1:~/pg_releases/pgtests$ ./test-libpq
'dbname=postgres port=54329 client_encoding=auto'
client_encoding: SQL_ASCII

and when executing the same script compiled in windows i get an error,
it doesn't recognize the client_encoding option...

$ ./test-libpq.exe "dbname=postgres user=postgres host=192.168.204.101
port=54329 client_encoding=latin1"
Connection to database failed: invalid connection option "client_encoding"


-- 
Atentamente,
Jaime Casanova
Soporte y capacitación de PostgreSQL
Asesoría y desarrollo de sistemas
Guayaquil - Ecuador
Cel. +59387171157
Index: doc/src/sgml/libpq.sgml
===================================================================
RCS file: /home/postgres/pgrepo/pgsql/doc/src/sgml/libpq.sgml,v
retrieving revision 1.289
diff -c -r1.289 libpq.sgml
*** doc/src/sgml/libpq.sgml	28 May 2009 20:02:10 -0000	1.289
--- doc/src/sgml/libpq.sgml	25 Jul 2009 00:54:11 -0000
***************
*** 236,241 ****
--- 236,254 ----
           </listitem>
          </varlistentry>
  
+         <varlistentry id="libpq-connect-client-encoding" xreflabel="client_encoding">
+          <term><literal>client_encoding</literal></term>
+          <listitem>
+          <para>
+           Character encoding to use. This sets the <varname>client_encoding</varname>
+           configuration option for this connection. In addition to the values
+           accepted by the corresponding server option, you can use 'auto' to
+           determine the right encoding from the current locale in the client
+           (LC_CTYPE environment variable on Unix systems).
+          </para>
+          </listitem>
+         </varlistentry>
+ 
          <varlistentry id="libpq-connect-options" xreflabel="options">
           <term><literal>options</literal></term>
           <listitem>
***************
*** 5871,5876 ****
--- 5884,5899 ----
        linkend="libpq-connect-connect-timeout"> connection parameter.
       </para>
      </listitem>
+ 
+     <listitem>
+      <para>
+       <indexterm>
+        <primary><envar>PGCLIENTENCODING</envar></primary>
+       </indexterm>
+       <envar>PGCLIENTENCODING</envar> behaves the same as <xref
+       linkend="libpq-connect-client-encoding"> connection parameter.
+      </para>
+     </listitem>
     </itemizedlist>
    </para>
  
***************
*** 5907,5923 ****
      <listitem>
       <para>
        <indexterm>
-        <primary><envar>PGCLIENTENCODING</envar></primary>
-       </indexterm>
-       <envar>PGCLIENTENCODING</envar> sets the default client character
-       set encoding.  (Equivalent to <literal>SET client_encoding TO
-       ...</literal>.)
-      </para>
-     </listitem>
- 
-     <listitem>
-      <para>
-       <indexterm>
         <primary><envar>PGGEQO</envar></primary>
        </indexterm>
        <envar>PGGEQO</envar> sets the default mode for the genetic query
--- 5930,5935 ----
Index: src/bin/psql/command.c
===================================================================
RCS file: /home/postgres/pgrepo/pgsql/src/bin/psql/command.c,v
retrieving revision 1.206
diff -c -r1.206 command.c
*** src/bin/psql/command.c	11 Jun 2009 14:49:07 -0000	1.206
--- src/bin/psql/command.c	25 Jul 2009 00:54:11 -0000
***************
*** 1239,1246 ****
  
  	while (true)
  	{
! 		n_conn = PQsetdbLogin(host, port, NULL, NULL,
! 							  dbname, user, password);
  
  		/* We can immediately discard the password -- no longer needed */
  		if (password)
--- 1239,1245 ----
  
  	while (true)
  	{
! 		n_conn = PSQLconnect(host, port, dbname, user, password);
  
  		/* We can immediately discard the password -- no longer needed */
  		if (password)
Index: src/bin/psql/common.c
===================================================================
RCS file: /home/postgres/pgrepo/pgsql/src/bin/psql/common.c,v
retrieving revision 1.142
diff -c -r1.142 common.c
*** src/bin/psql/common.c	11 Apr 2009 18:38:54 -0000	1.142
--- src/bin/psql/common.c	25 Jul 2009 00:54:11 -0000
***************
*** 32,37 ****
--- 32,39 ----
  static bool command_no_begin(const char *query);
  static bool is_select_command(const char *query);
  
+ static char *construct_conninfo(const char * const *optarray);
+ 
  /*
   * "Safe" wrapper around strdup()
   */
***************
*** 1538,1540 ****
--- 1540,1614 ----
  
  	return *filename;
  }
+ 
+ /*
+  * Establish a connection. This has an API similar to libpq's PQsetdblogin(),
+  * but we set "client_encoding=auto" if PGCLIENTENCODING environment variable
+  * is not set.
+  */
+ PGconn *
+ PSQLconnect(const char *host,
+ 			const char *port,
+ 			const char *dbname,
+ 			const char *user,
+ 			const char *password)
+ {
+ 	char *conninfo;
+ 	PGconn *ret;
+ 
+ 	const char *opts[] = {
+ 		"host", host,
+ 		"port", port,
+ 		"dbname", dbname,
+ 		"user", user,
+ 		"password", password,
+ 		"client_encoding", getenv("PGCLIENTENCODING") ? NULL : "auto",
+ 		NULL, NULL
+ 	};
+ 
+ 	conninfo = construct_conninfo(opts);
+ 	ret = PQconnectdb(conninfo);
+ 	free(conninfo);
+ 
+ 	return ret;
+ }
+ 
+ 
+ /*
+  * Given an array of connection option name/value pairs, construct a
+  * conninfo string suitable for PQconnectdb(). The array must be terminated
+  * by a NULL pointer.
+  */
+ static char *
+ construct_conninfo(const char * const *optarray)
+ {
+ 	PQExpBufferData buf;
+ 
+ 	initPQExpBuffer(&buf);
+ 
+ 	while(*optarray)
+ 	{
+ 		const char *option = optarray[0];
+ 		const char *value = optarray[1];
+ 
+ 		if (value != NULL)
+ 		{
+ 			/* write option name */
+ 			appendPQExpBuffer(&buf, "%s = '", option);
+ 
+ 			/* write value, escaping single quotes and backslashes */
+ 			while(*value)
+ 			{
+ 				if (*value == '\'' || *value == '\\')
+ 					appendPQExpBufferChar(&buf, '\\');
+ 				appendPQExpBufferChar(&buf, *(value++));
+ 			}
+ 
+ 			appendPQExpBufferStr(&buf, "' ");
+ 		}
+ 
+ 		optarray+=2;
+ 	}
+ 
+ 	return buf.data;
+ }
Index: src/bin/psql/common.h
===================================================================
RCS file: /home/postgres/pgrepo/pgsql/src/bin/psql/common.h,v
retrieving revision 1.58
diff -c -r1.58 common.h
*** src/bin/psql/common.h	1 Jan 2009 17:23:54 -0000	1.58
--- src/bin/psql/common.h	25 Jul 2009 00:54:11 -0000
***************
*** 57,62 ****
--- 57,68 ----
  
  extern bool SendQuery(const char *query);
  
+ extern PGconn *PSQLconnect(const char *host,
+ 						   const char *port,
+ 						   const char *dbname,
+ 						   const char *user,
+ 						   const char *password);
+ 
  extern bool is_superuser(void);
  extern bool standard_strings(void);
  extern const char *session_username(void);
Index: src/bin/psql/startup.c
===================================================================
RCS file: /home/postgres/pgrepo/pgsql/src/bin/psql/startup.c,v
retrieving revision 1.156
diff -c -r1.156 startup.c
*** src/bin/psql/startup.c	5 Apr 2009 04:19:58 -0000	1.156
--- src/bin/psql/startup.c	25 Jul 2009 00:54:11 -0000
***************
*** 172,178 ****
  	do
  	{
  		new_pass = false;
! 		pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL,
  					options.action == ACT_LIST_DB && options.dbname == NULL ?
  							   "postgres" : options.dbname,
  							   options.username, password);
--- 172,178 ----
  	do
  	{
  		new_pass = false;
! 		pset.db = PSQLconnect(options.host, options.port,
  					options.action == ACT_LIST_DB && options.dbname == NULL ?
  							   "postgres" : options.dbname,
  							   options.username, password);
Index: src/interfaces/libpq/Makefile
===================================================================
RCS file: /home/postgres/pgrepo/pgsql/src/interfaces/libpq/Makefile,v
retrieving revision 1.174
diff -c -r1.174 Makefile
*** src/interfaces/libpq/Makefile	13 Jul 2009 01:37:05 -0000	1.174
--- src/interfaces/libpq/Makefile	25 Jul 2009 00:55:04 -0000
***************
*** 30,36 ****
  # platforms.
  LIBS := $(LIBS:-lpgport=)
  
! OBJS=	fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \
  	fe-protocol2.o fe-protocol3.o pqexpbuffer.o pqsignal.o fe-secure.o \
  	libpq-events.o \
  	md5.o ip.o wchar.o encnames.o noblock.o pgstrcasecmp.o thread.o \
--- 30,36 ----
  # platforms.
  LIBS := $(LIBS:-lpgport=)
  
! OBJS=	chklocale.o fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \
  	fe-protocol2.o fe-protocol3.o pqexpbuffer.o pqsignal.o fe-secure.o \
  	libpq-events.o \
  	md5.o ip.o wchar.o encnames.o noblock.o pgstrcasecmp.o thread.o \
***************
*** 80,86 ****
  # For port modules, this only happens if configure decides the module
  # is needed (see filter hack in OBJS, above).
  
! crypt.c getaddrinfo.c inet_aton.c noblock.c open.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c thread.c win32error.c pgsleep.c: % : $(top_srcdir)/src/port/%
  	rm -f $@ && $(LN_S) $< .
  
  md5.c ip.c: % : $(backend_src)/libpq/%
--- 80,86 ----
  # For port modules, this only happens if configure decides the module
  # is needed (see filter hack in OBJS, above).
  
! chklocale.c crypt.c getaddrinfo.c inet_aton.c noblock.c open.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c thread.c win32error.c pgsleep.c: % : $(top_srcdir)/src/port/%
  	rm -f $@ && $(LN_S) $< .
  
  md5.c ip.c: % : $(backend_src)/libpq/%
***************
*** 123,129 ****
  	rm -f '$(DESTDIR)$(datadir)/pg_service.conf.sample'
  
  clean distclean: clean-lib
! 	rm -f $(OBJS) pg_config_paths.h crypt.c getaddrinfo.c inet_aton.c noblock.c open.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c thread.c md5.c ip.c encnames.c wchar.c win32error.c pgsleep.c pthread.h libpq.rc
  # Might be left over from a Win32 client-only build
  	rm -f pg_config_paths.h
  
--- 123,129 ----
  	rm -f '$(DESTDIR)$(datadir)/pg_service.conf.sample'
  
  clean distclean: clean-lib
! 	rm -f $(OBJS) pg_config_paths.h chklocale.c crypt.c getaddrinfo.c inet_aton.c noblock.c open.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c thread.c md5.c ip.c encnames.c wchar.c win32error.c pgsleep.c pthread.h libpq.rc
  # Might be left over from a Win32 client-only build
  	rm -f pg_config_paths.h
  
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /home/postgres/pgrepo/pgsql/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.376
diff -c -r1.376 fe-connect.c
*** src/interfaces/libpq/fe-connect.c	24 Jul 2009 17:58:31 -0000	1.376
--- src/interfaces/libpq/fe-connect.c	25 Jul 2009 00:54:05 -0000
***************
*** 154,159 ****
--- 154,162 ----
  	{"port", "PGPORT", DEF_PGPORT_STR, NULL,
  	"Database-Port", "", 6},
  
+ 	{"client_encoding", "PGCLIENTENCODING", NULL, NULL,
+ 	"Client-Encoding", "", 10},
+ 
  	/*
  	 * "tty" is no longer used either, but keep it present for backwards
  	 * compatibility.
***************
*** 225,233 ****
  	{
  		"PGTZ", "timezone"
  	},
- 	{
- 		"PGCLIENTENCODING", "client_encoding"
- 	},
  	/* internal performance-related settings */
  	{
  		"PGGEQO", "geqo"
--- 228,233 ----
***************
*** 424,429 ****
--- 424,431 ----
  	conn->pgpass = tmp ? strdup(tmp) : NULL;
  	tmp = conninfo_getval(connOptions, "connect_timeout");
  	conn->connect_timeout = tmp ? strdup(tmp) : NULL;
+ 	tmp = conninfo_getval(connOptions, "client_encoding");
+ 	conn->client_encoding_initial = tmp ? strdup(tmp) : NULL;
  	tmp = conninfo_getval(connOptions, "sslmode");
  	conn->sslmode = tmp ? strdup(tmp) : NULL;
  	tmp = conninfo_getval(connOptions, "sslkey");
***************
*** 552,557 ****
--- 554,570 ----
  		conn->sslmode = strdup(DefaultSSLMode);
  
  	/*
+ 	 * Resolve 'auto' client_encoding
+ 	 */
+ 	if (conn->client_encoding_initial &&
+ 		strcmp(conn->client_encoding_initial, "auto") == 0)
+ 	{
+ 		int encid = pg_get_encoding_from_locale(NULL);
+ 		free(conn->client_encoding_initial);
+ 		conn->client_encoding_initial = strdup(pg_encoding_to_char(encid));
+ 	}
+ 
+ 	/*
  	 * Only if we get this far is it appropriate to try to connect. (We need a
  	 * state flag, rather than just the boolean result of this function, in
  	 * case someone tries to PQreset() the PGconn.)
***************
*** 1883,1889 ****
  				if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
  				{
  					conn->status = CONNECTION_SETENV;
! 					conn->setenv_state = SETENV_STATE_OPTION_SEND;
  					conn->next_eo = EnvironmentOptions;
  					return PGRES_POLLING_WRITING;
  				}
--- 1896,1902 ----
  				if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
  				{
  					conn->status = CONNECTION_SETENV;
! 					conn->setenv_state = SETENV_STATE_CLIENT_ENCODING_SEND;
  					conn->next_eo = EnvironmentOptions;
  					return PGRES_POLLING_WRITING;
  				}
***************
*** 3689,3694 ****
--- 3702,3714 ----
  	if (!encoding)
  		return -1;
  
+ 	/* resolve special 'auto' value from the locale */
+ 	if (strcmp(encoding, "auto") == 0)
+ 	{
+ 		int encid = pg_get_encoding_from_locale(NULL);
+ 		encoding = pg_encoding_to_char(encid);
+ 	}
+ 
  	/* check query buffer overflow */
  	if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
  		return -1;
Index: src/interfaces/libpq/fe-protocol2.c
===================================================================
RCS file: /home/postgres/pgrepo/pgsql/src/interfaces/libpq/fe-protocol2.c,v
retrieving revision 1.29
diff -c -r1.29 fe-protocol2.c
*** src/interfaces/libpq/fe-protocol2.c	1 Jan 2009 17:24:03 -0000	1.29
--- src/interfaces/libpq/fe-protocol2.c	25 Jul 2009 00:54:22 -0000
***************
*** 58,63 ****
--- 58,64 ----
  	switch (conn->setenv_state)
  	{
  			/* These are reading states */
+ 		case SETENV_STATE_CLIENT_ENCODING_WAIT:
  		case SETENV_STATE_OPTION_WAIT:
  		case SETENV_STATE_QUERY1_WAIT:
  		case SETENV_STATE_QUERY2_WAIT:
***************
*** 74,79 ****
--- 75,81 ----
  			}
  
  			/* These are writing states, so we just proceed. */
+ 		case SETENV_STATE_CLIENT_ENCODING_SEND:
  		case SETENV_STATE_OPTION_SEND:
  		case SETENV_STATE_QUERY1_SEND:
  		case SETENV_STATE_QUERY2_SEND:
***************
*** 98,103 ****
--- 100,133 ----
  	{
  		switch (conn->setenv_state)
  		{
+ 			case SETENV_STATE_CLIENT_ENCODING_SEND:
+ 				{
+ 					char		setQuery[100];	/* note length limit in
+ 												 * sprintf below */
+ 					const char *val = conn->client_encoding_initial;
+ 
+ 					if (val)
+ 					{
+ 						if (pg_strcasecmp(val, "default") == 0)
+ 							sprintf(setQuery, "SET client_encoding = DEFAULT");
+ 						else
+ 							sprintf(setQuery, "SET client_encoding = '%.60s'",
+ 									val);
+ #ifdef CONNECTDEBUG
+ 						fprintf(stderr,
+ 								"Sending client_encoding with %s\n",
+ 								setQuery);
+ #endif
+ 						if (!PQsendQuery(conn, setQuery))
+ 							goto error_return;
+ 
+ 						conn->setenv_state = SETENV_STATE_CLIENT_ENCODING_WAIT;
+ 					}
+ 					else
+ 						conn->setenv_state = SETENV_STATE_OPTION_SEND;
+ 					break;
+ 				}
+ 
  			case SETENV_STATE_OPTION_SEND:
  				{
  					/*
***************
*** 142,147 ****
--- 172,202 ----
  					break;
  				}
  
+ 			case SETENV_STATE_CLIENT_ENCODING_WAIT:
+ 				{
+ 					if (PQisBusy(conn))
+ 						return PGRES_POLLING_READING;
+ 
+ 					res = PQgetResult(conn);
+ 
+ 					if (res)
+ 					{
+ 						if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ 						{
+ 							PQclear(res);
+ 							goto error_return;
+ 						}
+ 						PQclear(res);
+ 						/* Keep reading until PQgetResult returns NULL */
+ 					}
+ 					else
+ 					{
+ 						/* Query finished, so send the next option */
+ 						conn->setenv_state = SETENV_STATE_OPTION_SEND;
+ 					}
+ 					break;
+ 				}
+ 
  			case SETENV_STATE_OPTION_WAIT:
  				{
  					if (PQisBusy(conn))
Index: src/interfaces/libpq/fe-protocol3.c
===================================================================
RCS file: /home/postgres/pgrepo/pgsql/src/interfaces/libpq/fe-protocol3.c,v
retrieving revision 1.39
diff -c -r1.39 fe-protocol3.c
*** src/interfaces/libpq/fe-protocol3.c	11 Jun 2009 14:49:14 -0000	1.39
--- src/interfaces/libpq/fe-protocol3.c	25 Jul 2009 00:54:22 -0000
***************
*** 1920,1925 ****
--- 1920,1934 ----
  			strcpy(packet + packet_len, conn->pgoptions);
  		packet_len += strlen(conn->pgoptions) + 1;
  	}
+ 	if (conn->client_encoding_initial && conn->client_encoding_initial[0])
+ 	{
+ 		if (packet)
+ 			strcpy(packet + packet_len, "client_encoding");
+ 		packet_len += strlen("client_encoding") + 1;
+ 		if (packet)
+ 			strcpy(packet + packet_len, conn->client_encoding_initial);
+ 		packet_len += strlen(conn->client_encoding_initial) + 1;
+ 	}
  
  	/* Add any environment-driven GUC settings needed */
  	for (next_eo = options; next_eo->envName; next_eo++)
Index: src/interfaces/libpq/libpq-int.h
===================================================================
RCS file: /home/postgres/pgrepo/pgsql/src/interfaces/libpq/libpq-int.h,v
retrieving revision 1.144
diff -c -r1.144 libpq-int.h
*** src/interfaces/libpq/libpq-int.h	24 Jul 2009 17:58:31 -0000	1.144
--- src/interfaces/libpq/libpq-int.h	25 Jul 2009 00:54:22 -0000
***************
*** 235,240 ****
--- 235,242 ----
  /* (this is used only for 2.0-protocol connections) */
  typedef enum
  {
+ 	SETENV_STATE_CLIENT_ENCODING_SEND,	/* About to send an Environment Option */
+ 	SETENV_STATE_CLIENT_ENCODING_WAIT,	/* Waiting for above send to complete */
  	SETENV_STATE_OPTION_SEND,	/* About to send an Environment Option */
  	SETENV_STATE_OPTION_WAIT,	/* Waiting for above send to complete */
  	SETENV_STATE_QUERY1_SEND,	/* About to send a status query */
***************
*** 294,299 ****
--- 296,302 ----
  	char	   *pgtty;			/* tty on which the backend messages is
  								 * displayed (OBSOLETE, NOT USED) */
  	char	   *connect_timeout;	/* connection timeout (numeric string) */
+ 	char	   *client_encoding_initial; /* encoding to use */
  	char	   *pgoptions;		/* options to start the backend with */
  	char	   *dbName;			/* database name */
  	char	   *pguser;			/* Postgres username and password, if any */
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to