-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
[sqlite3] cleanup and harden Connection.__init__
#89289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[sqlite3] cleanup and harden Connection.__init__
#89289
Comments
Quoting Petr Viktorin in PR 27940, #27940 (comment):
import sqlite3
conn = sqlite3.connect(':memory:')
conn.execute('CREATE TABLE foo (bar)') try: conn.execute('INSERT INTO foo (bar) VALUES (1), (2), (3), (4)') Other issues:
Suggested to reorder connection __init__ in logical groups to more easily handle errors:
|
This is a minefield. If anyone has a use case for it, I'd *love* to hear it, but to me it seems that proper reinit support will be a lot of work (now and in future maintenance) for no gain. You can always create a new connection object. Consider instead deprecating reinitialization, documenting it as unpredictable & removing it in Python 3.13. Here's another thing to test: import sqlite3
conn = sqlite3.connect(':memory:')
cursor = conn.execute('CREATE TABLE foo (bar)')
try:
conn.__init__('/bad-file/')
except sqlite3.OperationalError:
pass
cursor.execute('INSERT INTO foo (bar) VALUES (1), (2), (3), (4)') And here's the kind of behavior that should be specified (and tested), and might even change to make more sense: import sqlite3
conn = sqlite3.connect(':memory:')
conn.text_factory=bytes
conn.row_factory = sqlite3.Row
cursor = conn.execute('CREATE TABLE foo (bar)')
cursor.execute('INSERT INTO foo (bar) VALUES ("1"), ("2"), ("3"), ("4")')
cursor.execute('SELECT bar FROM foo')
for row in cursor:
print(row, list(row))
break
conn.__init__(':memory:')
conn.execute('CREATE TABLE foo (bar)')
conn.execute('INSERT INTO foo (bar) VALUES ("a"), ("b"), ("c"), ("d")')
# Currently this uses the old database, old row_factory, but new text_factory"
for row in cursor:
print(row, list(row)) We should also do a review of all places And all this will also need to be done for Cursor. |
I modified your second example slightly:
Here's the output: |
Note: I ran that with PR 28227. OTOH: I do agree that there's a lot of pitfalls here, especially in the future. In the long run, it is probably best to deprecate reinit, and disable it in Python 3.13. |
Modifying the loops to also print the values: first fetch |
FYI, I've expanded the reinit tests and added a deprecation warning to the PR. |
I think a deprecation should be discussed a bit more widely than on bpo, so I opened a thread here: https://discuss.python.org/t/deprecating-sqlite-object-reinitialization/10503 |
Great, thanks. |
As for the effort to fix this: If we deprecate this, there should be no new users of it in 3.11+. If we deprecate and also fix this, and we happen to introduce bugs or behavior changes, then people that use it now will need to:
If we deprecate but keep the buggy behavior it as it is, (1) is not needed. Less work for both us and the users. |
Indeed. There's still a ref leak I'd like to take care of, though: if the first audit fails, database_obj leaks. |
I'll save the cleanup till Python 3.13 dev is started. I've opened a PR for fixing the ref leak (should be backported), and a draft PR for deprecating Connection and Cursor reinitialisation. |
Updated title to include sqlite3.Cursor as well, since cursors and connections are very much entwined. |
I think it's a good idea, but without the "will be disallowed in Python 3.13" part -- we should tell people that it's discouraged, but there's not much point in removing it. But there's no consensus whether that's a good way to handle things, in general. So I'll leave it up to you. |
There are two more issues in connection init:
Note, 3.10 does not have the |
- Make sure SQLite resources are freed if database open fails - Remove unneeded branches if init is aborted
Quoting the SQLite docs for
|
- Make sure SQLite resources are freed if database open fails - Remove unneeded branches if init is aborted
This issue was originally for |
Connection.__init__
sqlite3
connection initialisation #28227sqlite3.Connection.__init__
#28231sqlite3
Connection and Cursor reinitialization #28234sqlite3.Connection.__init__
(GH-28231) #28298sqlite3.Connection.__init__
(GH-28231). (GH-28298) #28302Note: 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:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: