mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +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) | ||||
| 
 | ||||
| 
 | ||||
| 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__": | ||||
|     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) | ||||
| { | ||||
|     Py_ssize_t _idx; | ||||
|     Py_ssize_t nitems, i; | ||||
| 
 | ||||
|     if (PyLong_Check(idx)) { | ||||
|         _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); | ||||
|         return Py_XNewRef(item); | ||||
|     } 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; | ||||
|             obj = PyTuple_GET_ITEM(self->description, i); | ||||
|             obj = PyTuple_GET_ITEM(obj, 0); | ||||
|  | @ -189,17 +192,19 @@ static PyObject * | |||
| pysqlite_row_keys_impl(pysqlite_Row *self) | ||||
| /*[clinic end generated code: output=efe3dfb3af6edc07 input=7549a122827c5563]*/ | ||||
| { | ||||
|     PyObject* list; | ||||
|     Py_ssize_t nitems, i; | ||||
| 
 | ||||
|     list = PyList_New(0); | ||||
|     PyObject *list = PyList_New(0); | ||||
|     if (!list) { | ||||
|         return NULL; | ||||
|     } | ||||
|     nitems = PyTuple_Size(self->description); | ||||
|     if (Py_IsNone(self->description)) { | ||||
|         return list; | ||||
|     } | ||||
| 
 | ||||
|     for (i = 0; i < nitems; i++) { | ||||
|         if (PyList_Append(list, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)) != 0) { | ||||
|     Py_ssize_t nitems = PyTuple_GET_SIZE(self->description); | ||||
|     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); | ||||
|             return NULL; | ||||
|         } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Erlend E. Aasland
						Erlend E. Aasland