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

Mechanism for executing "isolated" database operations without prepared connection stuff #2218

Closed
simonw opened this issue Dec 19, 2023 · 4 comments

Comments

@simonw
Copy link
Owner

simonw commented Dec 19, 2023

This one is a bit complicated.

Datasette Cloud needs a way to prevent people with write access (via datasette-write) from dropping certain important tables.

I've been building https://github.com/datasette/datasette-sqlite-authorizer to handle this - it can now be used to make a table completely read-only such that it can't be dropped even by db.execute_write(...).

Then I found a problem: running VACUUM against a database needs permission to insert/update into tables that should otherwise be protected.

... and datasette-edit-schema runs a VACUUM after deleting a table.

So I need a way to run a SQL operation that doesn't get affected by the various things plugins may have done to the DB connection (such as installing authorization callbacks).

@simonw
Copy link
Owner Author

simonw commented Dec 19, 2023

Design for this:

def vacuum(conn):
    conn.execute("vacuum")

await db.execute_isolated_fn(vacuum)

@simonw
Copy link
Owner Author

simonw commented Dec 19, 2023

Implemented in a branch. Needs tests and documentation.

Another neat thing this can be used for is running "unsafe" SQLite extensions safely from within a plugin.

The plugin can define a function which takes the connection, enables the extension, then does things with it - and that extension will never be available to other connections outside of that isolated function execution.

@simonw
Copy link
Owner Author

simonw commented Dec 19, 2023

I think I can test if a connection was reused or not with CREATE TEMPORARY TABLE temp_table_name (... - that should only exist within the same connection.

I'll create one in the write thread, then use the isolated mechanism to see if it's there or not and create a new one, then check if that new one is gone in the write thread again.

@simonw
Copy link
Owner Author

simonw commented Dec 19, 2023

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

No branches or pull requests

1 participant