Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6afe858

Browse files
committed
Issue #21718: cursor.description is now available for queries using CTEs
According to PEP 249, cursor.description must be available for any SELECT statements, such as those that use CTEs. Backported from ghaering/pysqlite@f67fa9c Additional test cases added by me.
1 parent 8682f57 commit 6afe858

3 files changed

Lines changed: 48 additions & 7 deletions

File tree

Lib/sqlite3/test/types.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,45 @@ def CheckCursorDescriptionNoRow(self):
274274
self.cur.execute("select * from test where 0 = 1")
275275
self.assertEqual(self.cur.description[0][0], "x")
276276

277+
def CheckCursorDescriptionInsert(self):
278+
self.cur.execute("insert into test values (1)")
279+
self.assertIsNone(self.cur.description)
280+
281+
282+
@unittest.skipIf(sqlite.sqlite_version_info < (3, 8, 3), "CTEs not supported")
283+
class CommonTableExpressionTests(unittest.TestCase):
284+
285+
def setUp(self):
286+
self.con = sqlite.connect(":memory:")
287+
self.cur = self.con.cursor()
288+
self.cur.execute("create table test(x foo)")
289+
290+
def tearDown(self):
291+
self.cur.close()
292+
self.con.close()
293+
294+
def CheckCursorDescriptionCTESimple(self):
295+
self.cur.execute("with one as (select 1) select * from one")
296+
self.assertIsNotNone(self.cur.description)
297+
self.assertEqual(self.cur.description[0][0], "1")
298+
299+
def CheckCursorDescriptionCTESMultipleColumns(self):
300+
self.cur.execute("insert into test values(1)")
301+
self.cur.execute("insert into test values(2)")
302+
self.cur.execute("with testCTE as (select * from test) select * from testCTE")
303+
self.assertIsNotNone(self.cur.description)
304+
self.assertEqual(self.cur.description[0][0], "x")
305+
306+
def CheckCursorDescriptionCTE(self):
307+
self.cur.execute("insert into test values (1)")
308+
self.cur.execute("with bar as (select * from test) select * from test where x = 1")
309+
self.assertIsNotNone(self.cur.description)
310+
self.assertEqual(self.cur.description[0][0], "x")
311+
self.cur.execute("with bar as (select * from test) select * from test where x = 2")
312+
self.assertIsNotNone(self.cur.description)
313+
self.assertEqual(self.cur.description[0][0], "x")
314+
315+
277316
class ObjectAdaptationTests(unittest.TestCase):
278317
def cast(obj):
279318
return float(obj)
@@ -372,7 +411,8 @@ def suite():
372411
adaptation_suite = unittest.makeSuite(ObjectAdaptationTests, "Check")
373412
bin_suite = unittest.makeSuite(BinaryConverterTests, "Check")
374413
date_suite = unittest.makeSuite(DateTimeTests, "Check")
375-
return unittest.TestSuite((sqlite_type_suite, decltypes_type_suite, colnames_type_suite, adaptation_suite, bin_suite, date_suite))
414+
cte_suite = unittest.makeSuite(CommonTableExpressionTests, "Check")
415+
return unittest.TestSuite((sqlite_type_suite, decltypes_type_suite, colnames_type_suite, adaptation_suite, bin_suite, date_suite, cte_suite))
376416

377417
def test():
378418
runner = unittest.TextTestRunner()

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ Core and Builtins
4646
Library
4747
-------
4848

49+
- Issue #21718: cursor.description is now available for queries using CTEs.
50+
4951
- Issue #2466: posixpath.ismount now correctly recognizes mount points which
5052
the user does not have permission to access.
5153

Modules/_sqlite/cursor.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -646,12 +646,11 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
646646
goto error;
647647
}
648648

649-
if (rc == SQLITE_ROW || (rc == SQLITE_DONE && statement_type == STATEMENT_SELECT)) {
650-
if (self->description == Py_None) {
651-
Py_BEGIN_ALLOW_THREADS
652-
numcols = sqlite3_column_count(self->statement->st);
653-
Py_END_ALLOW_THREADS
654-
649+
if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
650+
Py_BEGIN_ALLOW_THREADS
651+
numcols = sqlite3_column_count(self->statement->st);
652+
Py_END_ALLOW_THREADS
653+
if (self->description == Py_None && numcols > 0) {
655654
Py_SETREF(self->description, PyTuple_New(numcols));
656655
if (!self->description) {
657656
goto error;

0 commit comments

Comments
 (0)