diff options
| author | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2011-04-08 11:27:45 +0100 |
|---|---|---|
| committer | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2011-04-08 13:48:11 +0100 |
| commit | 88803695ac3158f76d29ff1cdd3621740e6af53f (patch) | |
| tree | 1b92171a59d8759d62f9966c56616767086f5e42 /psycopg/connection_int.c | |
| parent | bf4870686888288ca3d259c2098a227a85f31fce (diff) | |
| download | psycopg2-88803695ac3158f76d29ff1cdd3621740e6af53f.tar.gz | |
Normalize the encoding name at connection
The encoding can be set by PGCLIENTENCODING, which may be an alternative
spelling. Bug reported by Peter Eisentraut.
At this point the idea of considering one of the random spellings such as
EUC_CN as somewhat "blessed" is debunked. So just store the cleaned-up
version of the encoding in the mapping table. Note that the cleaned-up
version was needed by the unicode adapter: this requirement has been
surpassed as the connection now contains a copy of the Python codec name
set whenever the client encoding is set.
Diffstat (limited to 'psycopg/connection_int.c')
| -rw-r--r-- | psycopg/connection_int.c | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/psycopg/connection_int.c b/psycopg/connection_int.c index fa714f6..6006b15 100644 --- a/psycopg/connection_int.c +++ b/psycopg/connection_int.c @@ -236,6 +236,39 @@ conn_get_standard_conforming_strings(PGconn *pgconn) return equote; } + +/* Remove irrelevant chars from encoding name and turn it uppercase. + * + * Return a buffer allocated on Python heap, + * NULL and set an exception on error. + */ +static char * +clean_encoding_name(const char *enc) +{ + const char *i = enc; + char *rv, *j; + + /* convert to upper case and remove '-' and '_' from string */ + if (!(j = rv = PyMem_Malloc(strlen(enc) + 1))) { + PyErr_NoMemory(); + return NULL; + } + + while (*i) { + if (!isalnum(*i)) { + ++i; + } + else { + *j++ = toupper(*i++); + } + } + *j = '\0'; + + Dprintf("clean_encoding_name: %s -> %s", enc, rv); + + return rv; +} + /* Convert a PostgreSQL encoding to a Python codec. * * Return a new copy of the codec name allocated on the Python heap, @@ -246,11 +279,16 @@ conn_encoding_to_codec(const char *enc) { char *tmp; Py_ssize_t size; + char *norm_enc = NULL; PyObject *pyenc = NULL; char *rv = NULL; + if (!(norm_enc = clean_encoding_name(enc))) { + goto exit; + } + /* Find the Py codec name from the PG encoding */ - if (!(pyenc = PyDict_GetItemString(psycoEncodings, enc))) { + if (!(pyenc = PyDict_GetItemString(psycoEncodings, norm_enc))) { PyErr_Format(OperationalError, "no Python codec for client encoding '%s'", enc); goto exit; @@ -270,6 +308,7 @@ conn_encoding_to_codec(const char *enc) rv = psycopg_strdup(tmp, size); exit: + PyMem_Free(norm_enc); Py_XDECREF(pyenc); return rv; } @@ -285,7 +324,7 @@ exit: static int conn_read_encoding(connectionObject *self, PGconn *pgconn) { - char *enc = NULL, *codec = NULL, *j; + char *enc = NULL, *codec = NULL; const char *tmp; int rv = -1; @@ -297,16 +336,10 @@ conn_read_encoding(connectionObject *self, PGconn *pgconn) goto exit; } - if (!(enc = PyMem_Malloc(strlen(tmp)+1))) { - PyErr_NoMemory(); + if (!(enc = psycopg_strdup(tmp, 0))) { goto exit; } - /* turn encoding in uppercase */ - j = enc; - while (*tmp) { *j++ = toupper(*tmp++); } - *j = '\0'; - /* Look for this encoding in Python codecs. */ if (!(codec = conn_encoding_to_codec(enc))) { goto exit; |
