You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
sqlite3 dml statement detection does not account for CTEs #81040
36859-2.patch: Working patch that retains backwards-compatibility.
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=Nonecreated_at=<Date2019-05-08.23:08:24.384>labels= ['3.8', 'type-bug', 'library']
title='sqlite3 dml statement detection does not account for CTEs'updated_at=<Date2021-08-11.21:02:17.366>user='https://github.com/coleifer'
In statement.c, there is some logic which detects whether or not an incoming statement is a DML-type. The logic, as of 2019-05-08, I am referring to is here:
importsqlite3conn=sqlite3.connect(':memory:')
conn.execute('create table kv ("key" text primary key, "value" integer)')
conn.execute('insert into kv (key, value) values (?, ?), (?, ?)',
('k1', 1, 'k2', 2))
assertconn.in_transaction# Yes we are in a transaction.conn.commit()
assertnotconn.in_transaction# Not anymore, as expected.rc=conn.execute(
'with c(k, v) as (select key, value + 10 from kv) ''update kv set value=(select v from c where k=kv.key)')
print(rc.rowcount) # Should be 2, prints "-1".#assert conn.in_transaction # !!! Fails.curs=conn.execute('select * from kv order by key;')
print(curs.fetchall()) # [('k1', 11), ('k2', 12)]
Sqlite since 3.7.11 provides sqlite3_stmt_readonly() API for determining if a prepared statement will affect the database. I made the change, removing the SQL scanning code and replacing it with:
self->is_dml = !sqlite3_stmt_readonly(self->st);
But then I see a number of test failures, mostly related to the fact that table-creation is now treated as "is_dml" with the above change.
I don't know if the above API is going to be a workable path forward, since it seems like DML statements *not* automatically starting a transaction is a behavior a lot of people may have come to depend on (whether or not it is correct).
I've attached a patch just-in-case anyone's interested.
coleifer commented on May 9, 2019
coleifermannequin
MannequinAuthor
More actions
Oh, one more thing that is actually quite important -- since BEGIN IMMEDIATE and BEGIN EXCLUSIVE "modify" the database, these statements (intended to begin a transaction) are treated as "is_dml" when using the sqlite3_stmt_readonly API.
coleifer commented on May 9, 2019
coleifermannequin
MannequinAuthor
More actions
I've got a patch working now that:
retains complete backwards-compatibility for DDL (as well as BEGIN EXCLUSIVE/IMMEDIATE) -- tests are passing locally.
retains previous behavior for old sqlite that do not have the sqlite3_stmt_readonly API.
I think this should be good-to-go and I've in fact merged a similar patch on my own standalone pysqlite3 package.
Also I will add that the little 'test script' I provided is working as-expected with this patch applied.
I believe #13216 would be an improvement. I see that your original branch is unavailable, Charles; would you mind if I cherry-picked it and rebased it onto master? The sqlite3 module now requires SQLite >= 3.7.15 which simplifies the change a lot.
coleifer commented on Feb 9, 2021
coleifermannequin
MannequinAuthor
More actions
Yeah, go for it erlendaasland - I abandoned all hope of getting it merged, and have just been maintaining my own pysqlite3 which simplifies my life greatly.
Activity
coleifer commentedon May 8, 2019
In statement.c, there is some logic which detects whether or not an incoming statement is a DML-type. The logic, as of 2019-05-08, I am referring to is here:
cpython/Modules/_sqlite/statement.c
Lines 78 to 93 in fc662ac
To demonstrate the bug:
coleifer commentedon May 9, 2019
Sqlite since 3.7.11 provides sqlite3_stmt_readonly() API for determining if a prepared statement will affect the database. I made the change, removing the SQL scanning code and replacing it with:
self->is_dml = !sqlite3_stmt_readonly(self->st);
But then I see a number of test failures, mostly related to the fact that table-creation is now treated as "is_dml" with the above change.
I don't know if the above API is going to be a workable path forward, since it seems like DML statements *not* automatically starting a transaction is a behavior a lot of people may have come to depend on (whether or not it is correct).
I've attached a patch just-in-case anyone's interested.
coleifer commentedon May 9, 2019
Oh, one more thing that is actually quite important -- since BEGIN IMMEDIATE and BEGIN EXCLUSIVE "modify" the database, these statements (intended to begin a transaction) are treated as "is_dml" when using the sqlite3_stmt_readonly API.
coleifer commentedon May 9, 2019
I've got a patch working now that:
I think this should be good-to-go and I've in fact merged a similar patch on my own standalone pysqlite3 package.
Also I will add that the little 'test script' I provided is working as-expected with this patch applied.
tirkarthi commentedon May 9, 2019
CPython now accepts PRs on GitHub. Please try raising a PR as per devuguide : https://devguide.python.org/
erlend-aasland commentedon Feb 9, 2021
I believe #13216 would be an improvement. I see that your original branch is unavailable, Charles; would you mind if I cherry-picked it and rebased it onto master? The sqlite3 module now requires SQLite >= 3.7.15 which simplifies the change a lot.
coleifer commentedon Feb 9, 2021
Yeah, go for it erlendaasland - I abandoned all hope of getting it merged, and have just been maintaining my own pysqlite3 which simplifies my life greatly.
erlend-aasland commentedon Feb 9, 2021
Thanks, Charles. I'll give it a shot and see if get can provoke a response :)
erlend-aasland commentedon Aug 11, 2021
See also gh-79579 (bpo-35398)
6 remaining items
erlend-aasland commentedon Jun 21, 2022
I'm reopening this, because this issue materialises into two problems:
in_transaction).Superseded by: Add an autocommit property to sqlite3.Connection with a PEP 249 compliant manual commit mode and migrate #83638
rowcountis not updated as expected for CTE's.erlend-aasland commentedon Jul 17, 2022
Suggesting to address the
rowcountissue by improving the accuracy of therowcountdocs. We can then close this issue.pythongh-81040: Improve sqlite3.Cursor.rowcount docs
gh-81040: Improve sqlite3.Cursor.rowcount docs (#94940)
pythongh-81040: Improve sqlite3.Cursor.rowcount docs (pythonGH-94940)
pythongh-81040: Improve sqlite3.Cursor.rowcount docs (pythonGH-94940)
erlend-aasland commentedon Jul 22, 2022
Rowcount docs are updated in the following branches:
Considering this as resolved.
gh-81040: Improve sqlite3.Cursor.rowcount docs (GH-94940)
gh-81040: Improve sqlite3.Cursor.rowcount docs (GH-94940)