mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-28 11:53:43 +03:00
Merge branch 'adapt-list-of-none' into maint_2_6
This commit is contained in:
commit
57a4342946
1
NEWS
1
NEWS
|
@ -4,6 +4,7 @@ Current release
|
||||||
What's new in psycopg 2.6.1
|
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`).
|
- Fixed deadlock in multithread programs using OpenSSL (:ticket:`#290`).
|
||||||
- Correctly unlock the connection after error in flush (:ticket:`#294`).
|
- Correctly unlock the connection after error in flush (:ticket:`#294`).
|
||||||
- Fixed ``MinTimeLoggingCursor.callproc()`` (:ticket:`#309`).
|
- Fixed ``MinTimeLoggingCursor.callproc()`` (:ticket:`#309`).
|
||||||
|
|
|
@ -39,6 +39,14 @@ list_quote(listObject *self)
|
||||||
/* adapt the list by calling adapt() recursively and then wrapping
|
/* adapt the list by calling adapt() recursively and then wrapping
|
||||||
everything into "ARRAY[]" */
|
everything into "ARRAY[]" */
|
||||||
PyObject *tmp = NULL, *str = NULL, *joined = NULL, *res = NULL;
|
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;
|
Py_ssize_t i, len;
|
||||||
|
|
||||||
len = PyList_GET_SIZE(self->wrapped);
|
len = PyList_GET_SIZE(self->wrapped);
|
||||||
|
@ -60,6 +68,7 @@ list_quote(listObject *self)
|
||||||
quoted = microprotocol_getquoted(wrapped,
|
quoted = microprotocol_getquoted(wrapped,
|
||||||
(connectionObject*)self->connection);
|
(connectionObject*)self->connection);
|
||||||
if (quoted == NULL) goto error;
|
if (quoted == NULL) goto error;
|
||||||
|
all_nulls = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* here we don't loose a refcnt: SET_ITEM does not change the
|
/* 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);
|
joined = PyObject_CallMethod(str, "join", "(O)", tmp);
|
||||||
if (joined == NULL) goto error;
|
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:
|
error:
|
||||||
Py_XDECREF(tmp);
|
Py_XDECREF(tmp);
|
||||||
|
|
|
@ -192,6 +192,40 @@ class TypesBasicTests(ConnectingTestCase):
|
||||||
self.assertRaises(psycopg2.DataError,
|
self.assertRaises(psycopg2.DataError,
|
||||||
psycopg2.extensions.STRINGARRAY, b(s), curs)
|
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)
|
@testutils.skip_from_python(3)
|
||||||
def testTypeRoundtripBuffer(self):
|
def testTypeRoundtripBuffer(self):
|
||||||
o1 = buffer("".join(map(chr, range(256))))
|
o1 = buffer("".join(map(chr, range(256))))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user