Skip to content
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

gh-128505: Expose an interface to sqlite3_file_control #128507

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

hashbrowncipher
Copy link
Contributor

@hashbrowncipher hashbrowncipher commented Jan 5, 2025

sqlite3_file_control can affect the semantics of a sqlite3 database, but is not exposed by the sqlite.Connection class. In particular, this addition allows callers to use the SQLITE_FCNTL_PERSIST_WAL opcode. SQLITE_FCNTL_PERSIST_WAL ensures that callers can open a WAL-mode database on a read-only mount even when the writers have closed the DB.

Copy link

cpython-cla-bot bot commented Jan 5, 2025

All commit authors signed the Contributor License Agreement.
CLA signed

@erlend-aasland erlend-aasland self-assigned this Jan 5, 2025
Copy link
Contributor

@erlend-aasland erlend-aasland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I briefly started looking at this; will do a full review later today (CET).

@@ -0,0 +1 @@
sqlite Connection objects now expose a method set_file_control, which is a thin wrapper for `sqlite3_file_control https://www.sqlite.org/c3ref/file_control.html`_.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See https://devguide.python.org/documentation/markup/ for help with docs markup.

/*[clinic end generated code: output=d9d2d311892893b6 input=0253798d9514fea2]*/
{
int rc;
long val = arg;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all sqlite3_file_control opcodes use the int1 datatype. For example SQLITE_FCNTL_VFSNAME and SQLITE_FCNTL_TEMPFILENAME are char *. Suggesting to limit this (like we do for sqlite3_db_config) to only the supported opcodes, and raise an exception for unsupported opcodes.

In any case, we should use int here.

Suggested change
long val = arg;
int val = arg;

Footnotes

  1. int, not long

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also address the first part of this remark.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops! sorry for making you ask twice

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I have also removed the SQLITE_FCNTL_TEMPFILENAME and SQLITE_FCNTL_VFSNAME constants. I hope that's alright.

@erlend-aasland
Copy link
Contributor

Just a heads-up: we normally do not force-push. PRs are squashed into a single commit when we merge to main anyway, so there is no need to try and keep a nice Git commit history. See also the devguide.

@hashbrowncipher hashbrowncipher marked this pull request as ready for review January 7, 2025 07:11
erlend-aasland and others added 4 commits February 10, 2025 01:55
Add a private API for raising DB-API compatible exceptions based on the
result code of SQLite C APIs. Some APIs do not store the error indicator
on the database pointer, so we need to be able to deduce the DB-API
compatible exception directly from the error code.

- rename _pysqlite_seterror() as set_error_from_db()
- introduce set_error_from_code()

def test_file_control_raises(self):
with memory_database() as cx:
with self.assertRaises(sqlite.InternalError):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InternalError sounds suspicious. What's the underlying SQLite error code? SQLITE_MISUSE?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the failed test run, the full exception is sqlite3.InternalError: unknown operation, which appears to correspond to SQLITE_NOTFOUND.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants