On Fri, Jul 24, 2009 at 2:23 AM, Magnus Hagander<[email protected]> 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers