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