mirror of
https://github.com/python/cpython.git
synced 2025-10-25 10:44:55 +00:00
(cherry picked from commit 7e6ee50b6b)
This commit is contained in:
parent
d26c2fe7a2
commit
d6daeeeb2f
3 changed files with 83 additions and 10 deletions
|
|
@ -1947,5 +1947,70 @@ def wait():
|
||||||
self.assertEqual(proc.returncode, 0)
|
self.assertEqual(proc.returncode, 0)
|
||||||
|
|
||||||
|
|
||||||
|
class RowTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.cx = sqlite.connect(":memory:")
|
||||||
|
self.cx.row_factory = sqlite.Row
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.cx.close()
|
||||||
|
|
||||||
|
def test_row_keys(self):
|
||||||
|
cu = self.cx.execute("SELECT 1 as first, 2 as second")
|
||||||
|
row = cu.fetchone()
|
||||||
|
self.assertEqual(row.keys(), ["first", "second"])
|
||||||
|
|
||||||
|
def test_row_length(self):
|
||||||
|
cu = self.cx.execute("SELECT 1, 2, 3")
|
||||||
|
row = cu.fetchone()
|
||||||
|
self.assertEqual(len(row), 3)
|
||||||
|
|
||||||
|
def test_row_getitem(self):
|
||||||
|
cu = self.cx.execute("SELECT 1 as a, 2 as b")
|
||||||
|
row = cu.fetchone()
|
||||||
|
self.assertEqual(row[0], 1)
|
||||||
|
self.assertEqual(row[1], 2)
|
||||||
|
self.assertEqual(row["a"], 1)
|
||||||
|
self.assertEqual(row["b"], 2)
|
||||||
|
for key in "nokey", 4, 1.2:
|
||||||
|
with self.subTest(key=key):
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
row[key]
|
||||||
|
|
||||||
|
def test_row_equality(self):
|
||||||
|
c1 = self.cx.execute("SELECT 1 as a")
|
||||||
|
r1 = c1.fetchone()
|
||||||
|
|
||||||
|
c2 = self.cx.execute("SELECT 1 as a")
|
||||||
|
r2 = c2.fetchone()
|
||||||
|
|
||||||
|
self.assertIsNot(r1, r2)
|
||||||
|
self.assertEqual(r1, r2)
|
||||||
|
|
||||||
|
c3 = self.cx.execute("SELECT 1 as b")
|
||||||
|
r3 = c3.fetchone()
|
||||||
|
|
||||||
|
self.assertNotEqual(r1, r3)
|
||||||
|
|
||||||
|
def test_row_no_description(self):
|
||||||
|
cu = self.cx.cursor()
|
||||||
|
self.assertIsNone(cu.description)
|
||||||
|
|
||||||
|
row = sqlite.Row(cu, ())
|
||||||
|
self.assertEqual(row.keys(), [])
|
||||||
|
with self.assertRaisesRegex(IndexError, "nokey"):
|
||||||
|
row["nokey"]
|
||||||
|
|
||||||
|
def test_row_is_a_sequence(self):
|
||||||
|
from collections.abc import Sequence
|
||||||
|
|
||||||
|
cu = self.cx.execute("SELECT 1")
|
||||||
|
row = cu.fetchone()
|
||||||
|
|
||||||
|
self.assertTrue(issubclass(sqlite.Row, Sequence))
|
||||||
|
self.assertTrue(isinstance(row, Sequence))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
Fix bugs where :class:`sqlite3.Row` objects could segfault if their
|
||||||
|
inherited :attr:`~sqlite3.Cursor.description` was set to ``None``. Patch by
|
||||||
|
Erlend Aasland.
|
||||||
|
|
@ -132,7 +132,6 @@ static PyObject *
|
||||||
pysqlite_row_subscript(pysqlite_Row *self, PyObject *idx)
|
pysqlite_row_subscript(pysqlite_Row *self, PyObject *idx)
|
||||||
{
|
{
|
||||||
Py_ssize_t _idx;
|
Py_ssize_t _idx;
|
||||||
Py_ssize_t nitems, i;
|
|
||||||
|
|
||||||
if (PyLong_Check(idx)) {
|
if (PyLong_Check(idx)) {
|
||||||
_idx = PyNumber_AsSsize_t(idx, PyExc_IndexError);
|
_idx = PyNumber_AsSsize_t(idx, PyExc_IndexError);
|
||||||
|
|
@ -144,9 +143,13 @@ pysqlite_row_subscript(pysqlite_Row *self, PyObject *idx)
|
||||||
PyObject *item = PyTuple_GetItem(self->data, _idx);
|
PyObject *item = PyTuple_GetItem(self->data, _idx);
|
||||||
return Py_XNewRef(item);
|
return Py_XNewRef(item);
|
||||||
} else if (PyUnicode_Check(idx)) {
|
} else if (PyUnicode_Check(idx)) {
|
||||||
nitems = PyTuple_Size(self->description);
|
if (Py_IsNone(self->description)) {
|
||||||
|
PyErr_Format(PyExc_IndexError, "No item with key %R", idx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_ssize_t nitems = PyTuple_GET_SIZE(self->description);
|
||||||
|
|
||||||
for (i = 0; i < nitems; i++) {
|
for (Py_ssize_t i = 0; i < nitems; i++) {
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
obj = PyTuple_GET_ITEM(self->description, i);
|
obj = PyTuple_GET_ITEM(self->description, i);
|
||||||
obj = PyTuple_GET_ITEM(obj, 0);
|
obj = PyTuple_GET_ITEM(obj, 0);
|
||||||
|
|
@ -189,17 +192,19 @@ static PyObject *
|
||||||
pysqlite_row_keys_impl(pysqlite_Row *self)
|
pysqlite_row_keys_impl(pysqlite_Row *self)
|
||||||
/*[clinic end generated code: output=efe3dfb3af6edc07 input=7549a122827c5563]*/
|
/*[clinic end generated code: output=efe3dfb3af6edc07 input=7549a122827c5563]*/
|
||||||
{
|
{
|
||||||
PyObject* list;
|
PyObject *list = PyList_New(0);
|
||||||
Py_ssize_t nitems, i;
|
|
||||||
|
|
||||||
list = PyList_New(0);
|
|
||||||
if (!list) {
|
if (!list) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
nitems = PyTuple_Size(self->description);
|
if (Py_IsNone(self->description)) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < nitems; i++) {
|
Py_ssize_t nitems = PyTuple_GET_SIZE(self->description);
|
||||||
if (PyList_Append(list, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)) != 0) {
|
for (Py_ssize_t i = 0; i < nitems; i++) {
|
||||||
|
PyObject *descr = PyTuple_GET_ITEM(self->description, i);
|
||||||
|
PyObject *name = PyTuple_GET_ITEM(descr, 0);
|
||||||
|
if (PyList_Append(list, name) < 0) {
|
||||||
Py_DECREF(list);
|
Py_DECREF(list);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue