diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | psycopg/adapter_list.c | 16 | ||||
-rwxr-xr-x | tests/test_types_basic.py | 9 |
3 files changed, 22 insertions, 4 deletions
@@ -41,6 +41,7 @@ What's new in psycopg 2.7.6 (:ticket:`#746`). - Fixed building on modern FreeBSD versions with Python 3.7 (:ticket:`#755`). - Fixed hang trying to :sql:`COPY` via `~cursor.execute()` (:ticket:`#781`). +- Fixed adaptation of arrays of empty arrays (:ticket:`#788`). - Fixed segfault accessing the `connection.readonly` and `connection.deferrable` repeatedly (:ticket:`#790`). - `~psycopg2.extras.execute_values()` accepts `~psycopg2.sql.Composable` diff --git a/psycopg/adapter_list.c b/psycopg/adapter_list.c index 3fdff76..5c6fa69 100644 --- a/psycopg/adapter_list.c +++ b/psycopg/adapter_list.c @@ -55,6 +55,8 @@ list_quote(listObject *self) /* empty arrays are converted to NULLs (still searching for a way to insert an empty array in postgresql */ if (len == 0) { + /* it cannot be ARRAY[] because it would make empty lists unusable + * in any() without a cast. But we may convert it into ARRAY[] below */ res = Bytes_FromString("'{}'"); goto exit; } @@ -79,7 +81,19 @@ list_quote(listObject *self) /* Lists of arrays containing only nulls are also not supported * by the ARRAY construct so we should do some special casing */ - if (!PyList_Check(wrapped) || Bytes_AS_STRING(qs[i])[0] == 'A') { + if (PyList_Check(wrapped)) { + if (Bytes_AS_STRING(qs[i])[0] == 'A') { + all_nulls = 0; + } + else if (0 == strcmp(Bytes_AS_STRING(qs[i]), "'{}'")) { + /* case of issue #788: '{{}}' is not supported but + * array[array[]] is */ + all_nulls = 0; + Py_CLEAR(qs[i]); + qs[i] = Bytes_FromString("ARRAY[]"); + } + } + else { all_nulls = 0; } } diff --git a/tests/test_types_basic.py b/tests/test_types_basic.py index 63f74b0..499fdd1 100755 --- a/tests/test_types_basic.py +++ b/tests/test_types_basic.py @@ -167,9 +167,12 @@ class TypesBasicTests(ConnectingTestCase): curs.execute("select col from array_test where id = 2") self.assertEqual(curs.fetchone()[0], []) - # issue #788 (test commented out until issue fixed) - # curs.execute("select null = any(%s)", ([[]], )) - # self.assertFalse(curs.fetchone()[0]) + @testutils.skip_before_postgres(8, 4) + def testNestedEmptyArray(self): + # issue #788 + curs = self.conn.cursor() + curs.execute("select 10 = any(%s::int[])", ([[]], )) + self.assertFalse(curs.fetchone()[0]) def testEmptyArrayNoCast(self): s = self.execute("SELECT '{}' AS foo") |