This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: [sqlite3] check that column count is updated correctly for cached statements
Type: enhancement Stage: resolved
Components: Extension Modules Versions: Python 3.11
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: berker.peksag, erlendaasland, serhiy.storchaka
Priority: normal Keywords: patch

Created on 2021-05-04 22:33 by erlendaasland, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 25907 merged erlendaasland, 2021-05-04 22:47
Messages (3)
msg392964 - (view) Author: Erlend E. Aasland (erlendaasland) * (Python triager) Date: 2021-05-04 22:33
Pr. now, we call sqlite3_column_count() for every iteration in the _pysqlite_query_execute() loop. If detect_types is set, we call it twice for every loop.

Suggesting to move it out of the loop and into the pysqlite_Statement object. In pysqlite_statement_create(), after sqlite3_prepare_v2(), if self->is_dml == 0 we fetch the column count: self->column_count = sqlite3_column_count(). Else, it's 0.


# SQLite API interaction examples (pseudo-code), as diffs
--- now
+++ patched

## Create table
 sqlite3_prepare_v2
+sqlite3_column_count
 sqlite3_bind_blob_parameter_count
 sqlite3_step
-sqlite3_column_count
 sqlite3_last_insert_rowid
 sqlite3_reset

## Triple insert (executemany)
 sqlite3_prepare_v2
 sqlite3_get_autocommit
 sqlite3_bind_blob_parameter_count
 sqlite3_bind_int64
 sqlite3_step
-sqlite3_column_count
 sqlite3_changes
 sqlite3_reset
 sqlite3_bind_blob_parameter_count
 sqlite3_bind_int64
 sqlite3_step
-sqlite3_column_count
 sqlite3_changes
 sqlite3_reset
 sqlite3_bind_blob_parameter_count
 sqlite3_bind_int64
 sqlite3_step
-sqlite3_column_count
 sqlite3_changes
 sqlite3_reset
msg395081 - (view) Author: Erlend E. Aasland (erlendaasland) * (Python triager) Date: 2021-06-04 12:07
This change breaks existing behaviour (see test below). Also, sqlite3_column_count() is implemented as a simple lookup in SQLite; it is never an expensive function. Suggests to add the following test instead:


diff --git a/Lib/sqlite3/test/dbapi.py b/Lib/sqlite3/test/dbapi.py
index 77fafe0930..d7a3b249ab 100644
--- a/Lib/sqlite3/test/dbapi.py
+++ b/Lib/sqlite3/test/dbapi.py
@@ -555,6 +555,17 @@ def test_last_row_id_insert_o_r(self):
         ]
         self.assertEqual(results, expected)
 
+    def test_column_count(self):
+        # Check that column count is updated correctly for cached statements
+        select = "select * from test"
+        res = self.cu.execute(select)
+        old_count = len(res.description)
+        # Add a new column and execute the cached select query again
+        self.cu.execute("alter table test add newcol")
+        res = self.cu.execute(select)
+        new_count = len(res.description)
+        self.assertEqual(old_count - new_count, 1)
+
 
 class ThreadTests(unittest.TestCase):
     def setUp(self):
msg395106 - (view) Author: Pablo Galindo Salgado (pablogsal) * (Python committer) Date: 2021-06-04 17:36
New changeset 8363ac8607eca7398e568e1336154e1262a995a0 by Erlend Egeberg Aasland in branch 'main':
bpo-44041: Add test for sqlite3 column count (GH-25907)
https://github.com/python/cpython/commit/8363ac8607eca7398e568e1336154e1262a995a0
History
Date User Action Args
2022-04-11 14:59:45adminsetgithub: 88207
2021-06-04 17:36:18pablogsalsetstatus: open -> closed
nosy: - pablogsal

resolution: fixed
stage: patch review -> resolved
2021-06-04 17:36:16pablogsalsetnosy: + pablogsal
messages: + msg395106
2021-06-04 12:08:20erlendaaslandsettitle: [sqlite3] optimisation: only call sqlite3_column_count when needed -> [sqlite3] check that column count is updated correctly for cached statements
2021-06-04 12:07:59erlendaaslandsetmessages: + msg395081
2021-05-04 22:47:39erlendaaslandsetkeywords: + patch
stage: patch review
pull_requests: + pull_request24575
2021-05-04 22:33:34erlendaaslandcreate