bpo-38175: Fix a memory leak in comparison of sqlite3.Row objects. (GH-16155)
(cherry picked from commit 8debfa5040
)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
d90bb231c2
commit
f04299d978
|
@ -169,19 +169,33 @@ class RowFactoryTests(unittest.TestCase):
|
|||
row_1 = self.con.execute("select 1 as a, 2 as b").fetchone()
|
||||
row_2 = self.con.execute("select 1 as a, 2 as b").fetchone()
|
||||
row_3 = self.con.execute("select 1 as a, 3 as b").fetchone()
|
||||
row_4 = self.con.execute("select 1 as b, 2 as a").fetchone()
|
||||
row_5 = self.con.execute("select 2 as b, 1 as a").fetchone()
|
||||
|
||||
self.assertEqual(row_1, row_1)
|
||||
self.assertEqual(row_1, row_2)
|
||||
self.assertTrue(row_2 != row_3)
|
||||
self.assertTrue(row_1 == row_1)
|
||||
self.assertTrue(row_1 == row_2)
|
||||
self.assertFalse(row_1 == row_3)
|
||||
self.assertFalse(row_1 == row_4)
|
||||
self.assertFalse(row_1 == row_5)
|
||||
self.assertFalse(row_1 == object())
|
||||
|
||||
self.assertFalse(row_1 != row_1)
|
||||
self.assertFalse(row_1 != row_2)
|
||||
self.assertFalse(row_2 == row_3)
|
||||
self.assertTrue(row_1 != row_3)
|
||||
self.assertTrue(row_1 != row_4)
|
||||
self.assertTrue(row_1 != row_5)
|
||||
self.assertTrue(row_1 != object())
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
row_1 > row_2
|
||||
with self.assertRaises(TypeError):
|
||||
row_1 < row_2
|
||||
with self.assertRaises(TypeError):
|
||||
row_1 >= row_2
|
||||
with self.assertRaises(TypeError):
|
||||
row_1 <= row_2
|
||||
|
||||
self.assertEqual(row_1, row_2)
|
||||
self.assertEqual(hash(row_1), hash(row_2))
|
||||
self.assertNotEqual(row_1, row_3)
|
||||
self.assertNotEqual(hash(row_1), hash(row_3))
|
||||
|
||||
def CheckSqliteRowAsSequence(self):
|
||||
""" Checks if the row object can act like a sequence """
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Fix a memory leak in comparison of :class:`sqlite3.Row` objects.
|
|
@ -192,14 +192,16 @@ static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other,
|
|||
if (opid != Py_EQ && opid != Py_NE)
|
||||
Py_RETURN_NOTIMPLEMENTED;
|
||||
|
||||
if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) {
|
||||
if (PyObject_TypeCheck(_other, &pysqlite_RowType)) {
|
||||
pysqlite_Row *other = (pysqlite_Row *)_other;
|
||||
PyObject *res = PyObject_RichCompare(self->description, other->description, opid);
|
||||
if ((opid == Py_EQ && res == Py_True)
|
||||
|| (opid == Py_NE && res == Py_False)) {
|
||||
Py_DECREF(res);
|
||||
int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ);
|
||||
if (eq < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (eq) {
|
||||
return PyObject_RichCompare(self->data, other->data, opid);
|
||||
}
|
||||
return PyBool_FromLong(opid != Py_EQ);
|
||||
}
|
||||
Py_RETURN_NOTIMPLEMENTED;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue