Store a normalized version of the PG encoding in the connection

This way looking up into extensions.encodings will not break.
This commit is contained in:
Daniele Varrazzo 2011-04-08 13:27:11 +01:00
parent 88803695ac
commit 19653a88ec

View File

@ -273,22 +273,19 @@ clean_encoding_name(const char *enc)
* *
* Return a new copy of the codec name allocated on the Python heap, * Return a new copy of the codec name allocated on the Python heap,
* NULL with exception in case of error. * NULL with exception in case of error.
*
* 'enc' should be already normalized (uppercase, no - or _).
*/ */
static char * static char *
conn_encoding_to_codec(const char *enc) conn_encoding_to_codec(const char *enc)
{ {
char *tmp; char *tmp;
Py_ssize_t size; Py_ssize_t size;
char *norm_enc = NULL;
PyObject *pyenc = NULL; PyObject *pyenc = NULL;
char *rv = NULL; char *rv = NULL;
if (!(norm_enc = clean_encoding_name(enc))) {
goto exit;
}
/* Find the Py codec name from the PG encoding */ /* Find the Py codec name from the PG encoding */
if (!(pyenc = PyDict_GetItemString(psycoEncodings, norm_enc))) { if (!(pyenc = PyDict_GetItemString(psycoEncodings, enc))) {
PyErr_Format(OperationalError, PyErr_Format(OperationalError,
"no Python codec for client encoding '%s'", enc); "no Python codec for client encoding '%s'", enc);
goto exit; goto exit;
@ -308,7 +305,6 @@ conn_encoding_to_codec(const char *enc)
rv = psycopg_strdup(tmp, size); rv = psycopg_strdup(tmp, size);
exit: exit:
PyMem_Free(norm_enc);
Py_XDECREF(pyenc); Py_XDECREF(pyenc);
return rv; return rv;
} }
@ -336,7 +332,7 @@ conn_read_encoding(connectionObject *self, PGconn *pgconn)
goto exit; goto exit;
} }
if (!(enc = psycopg_strdup(tmp, 0))) { if (!(enc = clean_encoding_name(tmp))) {
goto exit; goto exit;
} }
@ -998,21 +994,23 @@ conn_set_client_encoding(connectionObject *self, const char *enc)
PGresult *pgres = NULL; PGresult *pgres = NULL;
char *error = NULL; char *error = NULL;
char query[48]; char query[48];
int res = 0; int res = 1;
char *codec; char *codec = NULL;
char *clean_enc = NULL;
/* If the current encoding is equal to the requested one we don't /* If the current encoding is equal to the requested one we don't
issue any query to the backend */ issue any query to the backend */
if (strcmp(self->encoding, enc) == 0) return 0; if (strcmp(self->encoding, enc) == 0) return 0;
/* We must know what python codec this encoding is. */ /* We must know what python codec this encoding is. */
if (!(codec = conn_encoding_to_codec(enc))) { return -1; } if (!(clean_enc = clean_encoding_name(enc))) { goto exit; }
if (!(codec = conn_encoding_to_codec(clean_enc))) { goto exit; }
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
pthread_mutex_lock(&self->lock); pthread_mutex_lock(&self->lock);
/* set encoding, no encoding string is longer than 24 bytes */ /* set encoding, no encoding string is longer than 24 bytes */
PyOS_snprintf(query, 47, "SET client_encoding = '%s'", enc); PyOS_snprintf(query, 47, "SET client_encoding = '%s'", clean_enc);
/* abort the current transaction, to set the encoding ouside of /* abort the current transaction, to set the encoding ouside of
transactions */ transactions */
@ -1027,21 +1025,18 @@ conn_set_client_encoding(connectionObject *self, const char *enc)
/* no error, we can proceeed and store the new encoding */ /* no error, we can proceeed and store the new encoding */
{ {
char *tmp = self->encoding; char *tmp = self->encoding;
self->encoding = NULL; self->encoding = clean_enc;
PyMem_Free(tmp); PyMem_Free(tmp);
} clean_enc = NULL;
if (!(self->encoding = psycopg_strdup(enc, 0))) {
res = 1; /* don't call pq_complete_error below */
goto endlock;
} }
/* Store the python codec too. */ /* Store the python codec too. */
{ {
char *tmp = self->codec; char *tmp = self->codec;
self->codec = NULL; self->codec = codec;
PyMem_Free(tmp); PyMem_Free(tmp);
codec = NULL;
} }
self->codec = codec;
Dprintf("conn_set_client_encoding: set encoding to %s (codec: %s)", Dprintf("conn_set_client_encoding: set encoding to %s (codec: %s)",
self->encoding, self->codec); self->encoding, self->codec);
@ -1054,6 +1049,10 @@ endlock:
if (res < 0) if (res < 0)
pq_complete_error(self, &pgres, &error); pq_complete_error(self, &pgres, &error);
exit:
PyMem_Free(clean_enc);
PyMem_Free(codec);
return res; return res;
} }