bpo-38175: Fix a memory leak in comparison of sqlite3.Row objects. (GH-16155)
This commit is contained in:
parent
a9187c3118
commit
8debfa5040
|
@ -169,19 +169,33 @@ class RowFactoryTests(unittest.TestCase):
|
||||||
row_1 = self.con.execute("select 1 as a, 2 as b").fetchone()
|
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_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_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.assertTrue(row_1 == row_1)
|
||||||
self.assertEqual(row_1, row_2)
|
self.assertTrue(row_1 == row_2)
|
||||||
self.assertTrue(row_2 != row_3)
|
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_1)
|
||||||
self.assertFalse(row_1 != row_2)
|
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.assertEqual(hash(row_1), hash(row_2))
|
||||||
self.assertNotEqual(row_1, row_3)
|
|
||||||
self.assertNotEqual(hash(row_1), hash(row_3))
|
|
||||||
|
|
||||||
def CheckSqliteRowAsSequence(self):
|
def CheckSqliteRowAsSequence(self):
|
||||||
""" Checks if the row object can act like a sequence """
|
""" 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)
|
if (opid != Py_EQ && opid != Py_NE)
|
||||||
Py_RETURN_NOTIMPLEMENTED;
|
Py_RETURN_NOTIMPLEMENTED;
|
||||||
|
|
||||||
if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) {
|
if (PyObject_TypeCheck(_other, &pysqlite_RowType)) {
|
||||||
pysqlite_Row *other = (pysqlite_Row *)_other;
|
pysqlite_Row *other = (pysqlite_Row *)_other;
|
||||||
PyObject *res = PyObject_RichCompare(self->description, other->description, opid);
|
int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ);
|
||||||
if ((opid == Py_EQ && res == Py_True)
|
if (eq < 0) {
|
||||||
|| (opid == Py_NE && res == Py_False)) {
|
return NULL;
|
||||||
Py_DECREF(res);
|
}
|
||||||
|
if (eq) {
|
||||||
return PyObject_RichCompare(self->data, other->data, opid);
|
return PyObject_RichCompare(self->data, other->data, opid);
|
||||||
}
|
}
|
||||||
|
return PyBool_FromLong(opid != Py_EQ);
|
||||||
}
|
}
|
||||||
Py_RETURN_NOTIMPLEMENTED;
|
Py_RETURN_NOTIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue