From 15bba2966f6404a90b9e4e50c27842cfc78f5431 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Tue, 16 Nov 2010 10:16:52 +0000 Subject: [PATCH] Don't run a query at connection to detect client encoding. Use PQparameterStatus() instead. This is only guaranteed in protocol 3. --- ChangeLog | 3 ++ NEWS-2.3 | 1 + psycopg/connection.h | 3 -- psycopg/connection_int.c | 98 ++++++++++++++-------------------------- 4 files changed, 37 insertions(+), 68 deletions(-) diff --git a/ChangeLog b/ChangeLog index c3e20974..8d377b7a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,9 @@ * psycopg/connection_int.c: dropped support for protocol 2 at compile time and protocol 2-specific code. + * psycopg/connection_int.c: don't run a query at connection to detect + client encoding: use PQparameterStatus() instead. + 2010-11-11 Daniele Varrazzo * lib/extras.py: build the namedtuple only once per execution, not once diff --git a/NEWS-2.3 b/NEWS-2.3 index bf1e628b..ead9064a 100644 --- a/NEWS-2.3 +++ b/NEWS-2.3 @@ -15,6 +15,7 @@ psycopg 2.3 aims to expose some new features introduced in PostgreSQL 9.0. - Dropped support for protocol 2: Psycopg 2.3 can only connect to PostgreSQL servers with version at least 7.4. + - don't issue a query at every connection to detect the client encoding. - `mogrify()` now supports unicode queries. - subclasses of a type that can be adapted are adapted as the superclass. - `errorcodes` knows a couple of new codes introduced in PostgreSQL 9.0. diff --git a/psycopg/connection.h b/psycopg/connection.h index 5d056c5e..21069d85 100644 --- a/psycopg/connection.h +++ b/psycopg/connection.h @@ -45,7 +45,6 @@ extern "C" { /* async connection building statuses */ #define CONN_STATUS_CONNECTING 20 #define CONN_STATUS_DATESTYLE 21 -#define CONN_STATUS_CLIENT_ENCODING 22 /* async query execution status */ #define ASYNC_DONE 0 @@ -65,7 +64,6 @@ extern "C" { later change it, she must know what she's doing... these are the queries we need to issue */ #define psyco_datestyle "SET DATESTYLE TO 'ISO'" -#define psyco_client_encoding "SHOW client_encoding" #define psyco_transaction_isolation "SHOW default_transaction_isolation" extern HIDDEN PyTypeObject connectionType; @@ -118,7 +116,6 @@ typedef struct { /* C-callable functions in connection_int.c and connection_ext.c */ HIDDEN int conn_get_standard_conforming_strings(PGconn *pgconn); -HIDDEN char *conn_get_encoding(PGresult *pgres); HIDDEN int conn_get_isolation_level(PGresult *pgres); HIDDEN int conn_get_protocol_version(PGconn *pgconn); HIDDEN void conn_notice_process(connectionObject *self); diff --git a/psycopg/connection_int.c b/psycopg/connection_int.c index f98839bc..ba923e09 100644 --- a/psycopg/connection_int.c +++ b/psycopg/connection_int.c @@ -222,22 +222,36 @@ conn_get_standard_conforming_strings(PGconn *pgconn) return equote; } -char * -conn_get_encoding(PGresult *pgres) +/* Return a string containing the client_encoding setting. + * + * Return a new string allocated by malloc(): use free() to free it. + * Return NULL in case of failure. + */ +static char * +conn_get_encoding(PGconn *pgconn) { - char *tmp, *encoding; - size_t i; + const char *tmp, *i; + char *encoding, *j; + + tmp = PQparameterStatus(pgconn, "client_encoding"); + Dprintf("conn_connect: client encoding: %s", tmp ? tmp : "(none)"); + if (!tmp) { + PyErr_SetString(OperationalError, + "server didn't return client encoding"); + return NULL; + } - tmp = PQgetvalue(pgres, 0, 0); encoding = malloc(strlen(tmp)+1); if (encoding == NULL) { PyErr_NoMemory(); - IFCLEARPGRES(pgres); return NULL; } - for (i=0 ; i < strlen(tmp) ; i++) - encoding[i] = toupper(tmp[i]); - encoding[i] = '\0'; + + /* return in uppercase */ + i = tmp; + j = encoding; + while (*i) { *j++ = toupper(*i++); } + *j = '\0'; return encoding; } @@ -293,6 +307,11 @@ conn_setup(connectionObject *self, PGconn *pgconn) PyErr_SetString(InterfaceError, "only protocol 3 supported"); return -1; } + /* conn_get_encoding returns a malloc'd string */ + self->encoding = conn_get_encoding(pgconn); + if (self->encoding == NULL) { + return -1; + } Py_BEGIN_ALLOW_THREADS; pthread_mutex_lock(&self->lock); @@ -322,33 +341,6 @@ conn_setup(connectionObject *self, PGconn *pgconn) } CLEARPGRES(pgres); - if (!green) { - Py_UNBLOCK_THREADS; - pgres = PQexec(pgconn, psyco_client_encoding); - Py_BLOCK_THREADS; - } else { - pgres = psyco_exec_green(self, psyco_client_encoding); - } - - if (pgres == NULL || PQresultStatus(pgres) != PGRES_TUPLES_OK) { - PyErr_SetString(OperationalError, "can't fetch client_encoding"); - IFCLEARPGRES(pgres); - Py_UNBLOCK_THREADS; - pthread_mutex_unlock(&self->lock); - Py_BLOCK_THREADS; - return -1; - } - - /* conn_get_encoding returns a malloc'd string */ - self->encoding = conn_get_encoding(pgres); - if (self->encoding == NULL) { - Py_UNBLOCK_THREADS; - pthread_mutex_unlock(&self->lock); - Py_BLOCK_THREADS; - return -1; - } - CLEARPGRES(pgres); - if (!green) { Py_UNBLOCK_THREADS; pgres = PQexec(pgconn, psyco_transaction_isolation); @@ -638,6 +630,11 @@ _conn_poll_setup_async(connectionObject *self) PyErr_SetString(InterfaceError, "only protocol 3 supported"); break; } + /* conn_get_encoding returns a malloc'd string */ + self->encoding = conn_get_encoding(self->pgconn); + if (self->encoding == NULL) { + break; + } /* asynchronous connections always use isolation level 0, the user is * expected to manage the transactions himself, by sending @@ -667,40 +664,12 @@ _conn_poll_setup_async(connectionObject *self) } CLEARPGRES(pgres); - Dprintf("conn_poll: status -> CONN_STATUS_CLIENT_ENCODING"); - self->status = CONN_STATUS_CLIENT_ENCODING; - if (0 == pq_send_query(self, psyco_client_encoding)) { - PyErr_SetString(OperationalError, PQerrorMessage(self->pgconn)); - break; - } - Dprintf("conn_poll: async_status -> ASYNC_WRITE"); - self->async_status = ASYNC_WRITE; - res = PSYCO_POLL_WRITE; - } - break; - - case CONN_STATUS_CLIENT_ENCODING: - res = _conn_poll_query(self); - if (res == PSYCO_POLL_OK) { - res = PSYCO_POLL_ERROR; - pgres = pq_get_last_result(self); - if (pgres == NULL || PQresultStatus(pgres) != PGRES_TUPLES_OK) { - PyErr_SetString(OperationalError, "can't fetch client_encoding"); - break; - } - - /* conn_get_encoding returns a malloc'd string */ - self->encoding = conn_get_encoding(pgres); - CLEARPGRES(pgres); - if (self->encoding == NULL) { break; } - Dprintf("conn_poll: status -> CONN_STATUS_READY"); self->status = CONN_STATUS_READY; res = PSYCO_POLL_OK; } break; } - return res; } @@ -732,7 +701,6 @@ conn_poll(connectionObject *self) break; case CONN_STATUS_DATESTYLE: - case CONN_STATUS_CLIENT_ENCODING: res = _conn_poll_setup_async(self); break;