mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-25 10:23:43 +03:00
Fixed adaptation of lists of None
Note: lists of lists of None are not supported yet.
This commit is contained in:
parent
8d4ac25b56
commit
b0058c0cc8
1
NEWS
1
NEWS
|
@ -15,6 +15,7 @@ New features:
|
|||
What's new in psycopg 2.6.1
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Lists consisting of only `None` are escaped correctly (:ticket:`#285`).
|
||||
- Fixed deadlock in multithread programs using OpenSSL (:ticket:`#290`).
|
||||
- Correctly unlock the connection after error in flush (:ticket:`#294`).
|
||||
- Fixed ``MinTimeLoggingCursor.callproc()`` (:ticket:`#309`).
|
||||
|
|
|
@ -39,6 +39,14 @@ list_quote(listObject *self)
|
|||
/* adapt the list by calling adapt() recursively and then wrapping
|
||||
everything into "ARRAY[]" */
|
||||
PyObject *tmp = NULL, *str = NULL, *joined = NULL, *res = NULL;
|
||||
|
||||
/* list consisting of only NULL don't work with the ARRAY[] construct
|
||||
* so we use the {NULL,...} syntax. Note however that list of lists where
|
||||
* some element is a list of only null still fails: for that we should use
|
||||
* the '{...}' syntax uniformly but we cannot do it in the current
|
||||
* infrastructure. TODO in psycopg3 */
|
||||
int all_nulls = 1;
|
||||
|
||||
Py_ssize_t i, len;
|
||||
|
||||
len = PyList_GET_SIZE(self->wrapped);
|
||||
|
@ -60,6 +68,7 @@ list_quote(listObject *self)
|
|||
quoted = microprotocol_getquoted(wrapped,
|
||||
(connectionObject*)self->connection);
|
||||
if (quoted == NULL) goto error;
|
||||
all_nulls = 0;
|
||||
}
|
||||
|
||||
/* here we don't loose a refcnt: SET_ITEM does not change the
|
||||
|
@ -74,7 +83,12 @@ list_quote(listObject *self)
|
|||
joined = PyObject_CallMethod(str, "join", "(O)", tmp);
|
||||
if (joined == NULL) goto error;
|
||||
|
||||
res = Bytes_FromFormat("ARRAY[%s]", Bytes_AsString(joined));
|
||||
/* PG doesn't like ARRAY[NULL..] */
|
||||
if (!all_nulls) {
|
||||
res = Bytes_FromFormat("ARRAY[%s]", Bytes_AsString(joined));
|
||||
} else {
|
||||
res = Bytes_FromFormat("'{%s}'", Bytes_AsString(joined));
|
||||
}
|
||||
|
||||
error:
|
||||
Py_XDECREF(tmp);
|
||||
|
|
|
@ -192,6 +192,40 @@ class TypesBasicTests(ConnectingTestCase):
|
|||
self.assertRaises(psycopg2.DataError,
|
||||
psycopg2.extensions.STRINGARRAY, b(s), curs)
|
||||
|
||||
def testArrayOfNulls(self):
|
||||
curs = self.conn.cursor()
|
||||
curs.execute("""
|
||||
create table na (
|
||||
texta text[],
|
||||
inta int[],
|
||||
boola boolean[],
|
||||
|
||||
textaa text[][],
|
||||
intaa int[][],
|
||||
boolaa boolean[][]
|
||||
)""")
|
||||
|
||||
curs.execute("insert into na (texta) values (%s)", ([None],))
|
||||
curs.execute("insert into na (texta) values (%s)", (['a', None],))
|
||||
curs.execute("insert into na (texta) values (%s)", ([None, None],))
|
||||
curs.execute("insert into na (inta) values (%s)", ([None],))
|
||||
curs.execute("insert into na (inta) values (%s)", ([42, None],))
|
||||
curs.execute("insert into na (inta) values (%s)", ([None, None],))
|
||||
curs.execute("insert into na (boola) values (%s)", ([None],))
|
||||
curs.execute("insert into na (boola) values (%s)", ([True, None],))
|
||||
curs.execute("insert into na (boola) values (%s)", ([None, None],))
|
||||
|
||||
# TODO: array of array of nulls are not supported yet
|
||||
# curs.execute("insert into na (textaa) values (%s)", ([[None]],))
|
||||
curs.execute("insert into na (textaa) values (%s)", ([['a', None]],))
|
||||
# curs.execute("insert into na (textaa) values (%s)", ([[None, None]],))
|
||||
# curs.execute("insert into na (intaa) values (%s)", ([[None]],))
|
||||
curs.execute("insert into na (intaa) values (%s)", ([[42, None]],))
|
||||
# curs.execute("insert into na (intaa) values (%s)", ([[None, None]],))
|
||||
# curs.execute("insert into na (boolaa) values (%s)", ([[None]],))
|
||||
curs.execute("insert into na (boolaa) values (%s)", ([[True, None]],))
|
||||
# curs.execute("insert into na (boolaa) values (%s)", ([[None, None]],))
|
||||
|
||||
@testutils.skip_from_python(3)
|
||||
def testTypeRoundtripBuffer(self):
|
||||
o1 = buffer("".join(map(chr, range(256))))
|
||||
|
|
Loading…
Reference in New Issue
Block a user