API for executing multiple queries within a transaction
Project description
datasette-transactions
A Datasette plugin providing an API for executing multiple SQL commands within a single transaction, with support for SQLite authorization callbacks to control table-level read/write access.
Installation
Install this plugin in the same environment as Datasette.
datasette install datasette-transactions
Usage
Begin a Transaction
POST /-/transactions/begin/<database>
Content-Type: application/json
{
"read": ["table1", "table2"],
"write": ["table1"],
"timeout_ms": 5000
}
Parameters:
read: List of tables the transaction can read fromwrite: List of tables the transaction can write totimeout_ms: Optional timeout in milliseconds (transaction auto-rolls back after this time)
Response:
{
"ok": true,
"transaction_id": "550e8400-e29b-41d4-a716-446655440000"
}
Required Permissions:
execute-sqlon the databaseview-tableon each table in thereadlistinsert-rowandupdate-rowon each table in thewritelist
Execute SQL
POST /-/transactions/<transaction_id>
Content-Type: application/json
{
"sql": "INSERT INTO table1 (name) VALUES (:name)",
"params": {"name": "Alice"}
}
Response:
{
"ok": true,
"rows": [],
"columns": [],
"truncated": false
}
For SELECT queries, rows contains the results as a list of objects.
Create a Savepoint
POST /-/transactions/<transaction_id>/savepoint
Content-Type: application/json
{
"name": "before_batch"
}
Response:
{
"ok": true,
"savepoint": "before_batch"
}
Release a Savepoint
POST /-/transactions/<transaction_id>/release
Content-Type: application/json
{
"name": "before_batch"
}
Rollback to a Savepoint
POST /-/transactions/<transaction_id>/rollback-to
Content-Type: application/json
{
"name": "before_batch"
}
Commit a Transaction
POST /-/transactions/commit/<transaction_id>
Response:
{
"ok": true
}
Rollback a Transaction
POST /-/transactions/rollback/<transaction_id>
Response:
{
"ok": true
}
Error Codes
| Status | Meaning |
|---|---|
| 400 | Bad request (invalid JSON, missing parameters, SQL error) |
| 403 | Permission denied (missing required permissions, table access denied) |
| 404 | Transaction or savepoint not found |
| 405 | Method not allowed (use POST) |
| 410 | Transaction expired (timed out) |
| 429 | Too many concurrent transactions (max 5 per database) |
Authorization
The plugin uses SQLite's set_authorizer() callback to enforce table-level permissions:
- Reading from tables not in
readlist is blocked - Writing to tables not in
writelist is blocked ATTACH DATABASEis always blocked
Concurrency
- Maximum 5 concurrent transactions per database
- Read-only transactions use
BEGIN DEFERRED(allows concurrent reads) - Write transactions use
BEGIN IMMEDIATE(exclusive lock)
Example: Batch Insert with Rollback on Error
import httpx
# Begin transaction
response = httpx.post(
"http://localhost:8001/-/transactions/begin/mydb",
json={"read": ["users"], "write": ["users"]}
)
tx_id = response.json()["transaction_id"]
try:
# Insert multiple rows
for user in users:
httpx.post(
f"http://localhost:8001/-/transactions/{tx_id}",
json={
"sql": "INSERT INTO users (name, email) VALUES (:name, :email)",
"params": user
}
)
# Commit if all succeeded
httpx.post(f"http://localhost:8001/-/transactions/commit/{tx_id}")
except Exception:
# Rollback on error
httpx.post(f"http://localhost:8001/-/transactions/rollback/{tx_id}")
raise
Development
To set up this plugin locally, first checkout the code:
cd datasette-transactions
uv run pytest # Run tests
This project follows TDD (Test-Driven Development). See CLAUDE.md for development guidelines.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file datasette_transactions-0.1a0.tar.gz.
File metadata
- Download URL: datasette_transactions-0.1a0.tar.gz
- Upload date:
- Size: 19.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b94f948cf16139595ca9fd484846829273c186e80e875d5d8e06e3d1aa1709b9
|
|
| MD5 |
5dee2b91905e3ee6be1b081baad13a10
|
|
| BLAKE2b-256 |
e504114faa37c67a497d76fce140f97cb91928da9dc98f5010cebc22897bd564
|
Provenance
The following attestation bundles were made for datasette_transactions-0.1a0.tar.gz:
Publisher:
publish.yml on datasette/datasette-transactions
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
datasette_transactions-0.1a0.tar.gz -
Subject digest:
b94f948cf16139595ca9fd484846829273c186e80e875d5d8e06e3d1aa1709b9 - Sigstore transparency entry: 812661564
- Sigstore integration time:
-
Permalink:
datasette/datasette-transactions@370a8507ac632d3825ae16c31c55ae3ccdda47d7 -
Branch / Tag:
refs/tags/0.1a0 - Owner: https://github.com/datasette
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@370a8507ac632d3825ae16c31c55ae3ccdda47d7 -
Trigger Event:
release
-
Statement type:
File details
Details for the file datasette_transactions-0.1a0-py3-none-any.whl.
File metadata
- Download URL: datasette_transactions-0.1a0-py3-none-any.whl
- Upload date:
- Size: 13.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
87581716bebd87e76c47072ea407f02acc41047eeef1805e6c5f3881bd356650
|
|
| MD5 |
be734d395951697e1a27f469e1743af8
|
|
| BLAKE2b-256 |
428f17e3c95c5cd808fd237ff41ba428a2647e0aabc8f221bf2e5b14f29c0878
|
Provenance
The following attestation bundles were made for datasette_transactions-0.1a0-py3-none-any.whl:
Publisher:
publish.yml on datasette/datasette-transactions
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
datasette_transactions-0.1a0-py3-none-any.whl -
Subject digest:
87581716bebd87e76c47072ea407f02acc41047eeef1805e6c5f3881bd356650 - Sigstore transparency entry: 812661566
- Sigstore integration time:
-
Permalink:
datasette/datasette-transactions@370a8507ac632d3825ae16c31c55ae3ccdda47d7 -
Branch / Tag:
refs/tags/0.1a0 - Owner: https://github.com/datasette
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@370a8507ac632d3825ae16c31c55ae3ccdda47d7 -
Trigger Event:
release
-
Statement type: