Don't run a query at connection to detect client encoding.

Use PQparameterStatus() instead. This is only guaranteed in protocol 3.
This commit is contained in:
Daniele Varrazzo 2010-11-16 10:16:52 +00:00
parent a88d7ab424
commit 15bba2966f
4 changed files with 37 additions and 68 deletions

View File

@ -6,6 +6,9 @@
* psycopg/connection_int.c: dropped support for protocol 2 at compile * psycopg/connection_int.c: dropped support for protocol 2 at compile
time and protocol 2-specific code. 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 <daniele.varrazzo@gmail.com> 2010-11-11 Daniele Varrazzo <daniele.varrazzo@gmail.com>
* lib/extras.py: build the namedtuple only once per execution, not once * lib/extras.py: build the namedtuple only once per execution, not once

View File

@ -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 - Dropped support for protocol 2: Psycopg 2.3 can only connect to PostgreSQL
servers with version at least 7.4. 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. - `mogrify()` now supports unicode queries.
- subclasses of a type that can be adapted are adapted as the superclass. - 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. - `errorcodes` knows a couple of new codes introduced in PostgreSQL 9.0.

View File

@ -45,7 +45,6 @@ extern "C" {
/* async connection building statuses */ /* async connection building statuses */
#define CONN_STATUS_CONNECTING 20 #define CONN_STATUS_CONNECTING 20
#define CONN_STATUS_DATESTYLE 21 #define CONN_STATUS_DATESTYLE 21
#define CONN_STATUS_CLIENT_ENCODING 22
/* async query execution status */ /* async query execution status */
#define ASYNC_DONE 0 #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 later change it, she must know what she's doing... these are the queries we
need to issue */ need to issue */
#define psyco_datestyle "SET DATESTYLE TO 'ISO'" #define psyco_datestyle "SET DATESTYLE TO 'ISO'"
#define psyco_client_encoding "SHOW client_encoding"
#define psyco_transaction_isolation "SHOW default_transaction_isolation" #define psyco_transaction_isolation "SHOW default_transaction_isolation"
extern HIDDEN PyTypeObject connectionType; extern HIDDEN PyTypeObject connectionType;
@ -118,7 +116,6 @@ typedef struct {
/* C-callable functions in connection_int.c and connection_ext.c */ /* C-callable functions in connection_int.c and connection_ext.c */
HIDDEN int conn_get_standard_conforming_strings(PGconn *pgconn); 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_isolation_level(PGresult *pgres);
HIDDEN int conn_get_protocol_version(PGconn *pgconn); HIDDEN int conn_get_protocol_version(PGconn *pgconn);
HIDDEN void conn_notice_process(connectionObject *self); HIDDEN void conn_notice_process(connectionObject *self);

View File

@ -222,22 +222,36 @@ conn_get_standard_conforming_strings(PGconn *pgconn)
return equote; return equote;
} }
char * /* Return a string containing the client_encoding setting.
conn_get_encoding(PGresult *pgres) *
* 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; const char *tmp, *i;
size_t 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); encoding = malloc(strlen(tmp)+1);
if (encoding == NULL) { if (encoding == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
IFCLEARPGRES(pgres);
return NULL; return NULL;
} }
for (i=0 ; i < strlen(tmp) ; i++)
encoding[i] = toupper(tmp[i]); /* return in uppercase */
encoding[i] = '\0'; i = tmp;
j = encoding;
while (*i) { *j++ = toupper(*i++); }
*j = '\0';
return encoding; return encoding;
} }
@ -293,6 +307,11 @@ conn_setup(connectionObject *self, PGconn *pgconn)
PyErr_SetString(InterfaceError, "only protocol 3 supported"); PyErr_SetString(InterfaceError, "only protocol 3 supported");
return -1; 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; Py_BEGIN_ALLOW_THREADS;
pthread_mutex_lock(&self->lock); pthread_mutex_lock(&self->lock);
@ -322,33 +341,6 @@ conn_setup(connectionObject *self, PGconn *pgconn)
} }
CLEARPGRES(pgres); 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) { if (!green) {
Py_UNBLOCK_THREADS; Py_UNBLOCK_THREADS;
pgres = PQexec(pgconn, psyco_transaction_isolation); pgres = PQexec(pgconn, psyco_transaction_isolation);
@ -638,6 +630,11 @@ _conn_poll_setup_async(connectionObject *self)
PyErr_SetString(InterfaceError, "only protocol 3 supported"); PyErr_SetString(InterfaceError, "only protocol 3 supported");
break; 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 /* asynchronous connections always use isolation level 0, the user is
* expected to manage the transactions himself, by sending * expected to manage the transactions himself, by sending
@ -667,40 +664,12 @@ _conn_poll_setup_async(connectionObject *self)
} }
CLEARPGRES(pgres); 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"); Dprintf("conn_poll: status -> CONN_STATUS_READY");
self->status = CONN_STATUS_READY; self->status = CONN_STATUS_READY;
res = PSYCO_POLL_OK; res = PSYCO_POLL_OK;
} }
break; break;
} }
return res; return res;
} }
@ -732,7 +701,6 @@ conn_poll(connectionObject *self)
break; break;
case CONN_STATUS_DATESTYLE: case CONN_STATUS_DATESTYLE:
case CONN_STATUS_CLIENT_ENCODING:
res = _conn_poll_setup_async(self); res = _conn_poll_setup_async(self);
break; break;