diff --git a/NEWS b/NEWS index c6635417..ec700726 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,7 @@ What's new in psycopg 2.4.3 - Fixed interaction between RealDictCursor and named cursors (ticket #67). - Dropped limit on the columns length in COPY operations (ticket #68). + - Fixed typecasting of arrays containing consecutive backslashes. - 'errorcodes' map updated to PostgreSQL 9.1. diff --git a/psycopg/typecast_array.c b/psycopg/typecast_array.c index 6bb256f1..75b84b50 100644 --- a/psycopg/typecast_array.c +++ b/psycopg/typecast_array.c @@ -133,7 +133,7 @@ typecast_array_tokenize(const char *str, Py_ssize_t strlength, } if (res == ASCAN_QUOTED) { - Py_ssize_t j; + const char *j, *jj; char *buffer = PyMem_Malloc(l+1); if (buffer == NULL) { PyErr_NoMemory(); @@ -142,10 +142,9 @@ typecast_array_tokenize(const char *str, Py_ssize_t strlength, *token = buffer; - for (j = *pos; j < *pos+l; j++) { - if (str[j] != '\\' - || (j > *pos && str[j-1] == '\\')) - *(buffer++) = str[j]; + for (j = str + *pos, jj = j + l; j < jj; ++j) { + if (*j == '\\') { ++j; } + *(buffer++) = *j; } *buffer = '\0'; diff --git a/tests/types_basic.py b/tests/types_basic.py index 3686dec4..88c3844f 100755 --- a/tests/types_basic.py +++ b/tests/types_basic.py @@ -189,6 +189,17 @@ class TypesBasicTests(unittest.TestCase): s = self.execute("SELECT '{}'::text AS foo") self.failUnlessEqual(s, "{}") + def testArrayEscape(self): + ss = ['', '\\', '"', '\\\\', '\\"'] + for s in ss: + r = self.execute("SELECT %s AS foo", (s,)) + self.failUnlessEqual(s, r) + r = self.execute("SELECT %s AS foo", ([s],)) + self.failUnlessEqual([s], r) + + r = self.execute("SELECT %s AS foo", (ss,)) + self.failUnlessEqual(ss, r) + @testutils.skip_from_python(3) def testTypeRoundtripBuffer(self): o1 = buffer("".join(map(chr, range(256))))