A SQLAlchemy dialect for Cloudflare's D1 Serverless SQLite Database
Project description
SQLAlchemy Cloudflare D1 Dialect
A SQLAlchemy dialect for Cloudflare's D1 Serverless SQLite Database using the REST API.
Features
- Full SQLAlchemy ORM and Core support
- Async and sync query execution via D1 REST API
- SQLite/D1 compatible SQL compilation
- Prepared statement support with parameter binding
- Connection pooling and management
- Type mapping for D1/SQLite data types
Installation
pip install sqlalchemy-cloudflare-d1
Or install from source:
git clone https://github.com/collierking/sqlalchemy-cloudflare-d1.git
cd sqlalchemy-cloudflare-d1
pip install -e .
Prerequisites
- A Cloudflare account with D1 enabled
- A D1 database created via the Cloudflare dashboard or CLI
- A Cloudflare API token with D1 permissions
Creating a D1 Database
Using the Cloudflare CLI:
wrangler d1 create my-database
Or via the Cloudflare dashboard.
Creating an API Token
- Go to Cloudflare API Tokens
- Click "Create Token"
- Use the "Custom token" template
- Add permissions:
Account:D1:Edit - Add your account in "Account Resources"
- Click "Continue to summary" and "Create Token"
Usage
Connection String Format
from sqlalchemy import create_engine
# Format: cloudflare_d1://account_id:api_token@database_id
engine = create_engine(
"cloudflare_d1://your_account_id:your_api_token@your_database_id"
)
Basic Example
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# Create engine
engine = create_engine(
"cloudflare_d1://account_id:api_token@database_id"
)
# Create base and define model
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
email = Column(String(100))
# Create tables
Base.metadata.create_all(engine)
# Create session and add data
Session = sessionmaker(bind=engine)
session = Session()
# Add a user
user = User(name="Alice", email="alice@example.com")
session.add(user)
session.commit()
# Query users
users = session.query(User).all()
for user in users:
print(f"{user.name}: {user.email}")
session.close()
Core API Example
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, select
engine = create_engine("cloudflare_d1://account_id:api_token@database_id")
metadata = MetaData()
users = Table('users', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('email', String(100))
)
# Create table
metadata.create_all(engine)
with engine.connect() as conn:
# Insert data
conn.execute(users.insert().values(name="Bob", email="bob@example.com"))
# Query data
result = conn.execute(select(users))
for row in result:
print(row)
Raw SQL Example
from sqlalchemy import create_engine, text
engine = create_engine("cloudflare_d1://account_id:api_token@database_id")
with engine.connect() as conn:
# Execute raw SQL
result = conn.execute(text("SELECT * FROM sqlite_master WHERE type='table'"))
for row in result:
print(row)
Configuration
Connection Parameters
You can pass additional parameters via the connection string or engine creation:
from sqlalchemy import create_engine
# Via connection string query parameters
engine = create_engine(
"cloudflare_d1://account_id:api_token@database_id?timeout=60"
)
# Via connect_args
engine = create_engine(
"cloudflare_d1://account_id:api_token@database_id",
connect_args={
"timeout": 60,
}
)
Environment Variables
You can also use environment variables:
import os
from sqlalchemy import create_engine
engine = create_engine(
f"cloudflare_d1://{os.getenv('CF_ACCOUNT_ID')}:"
f"{os.getenv('CF_API_TOKEN')}@{os.getenv('CF_DATABASE_ID')}"
)
Limitations
This dialect has some limitations due to D1's REST API nature:
- No transactions: D1 REST API doesn't support explicit transactions. Each query is auto-committed.
- No isolation levels: Connection isolation levels are not supported.
- Limited concurrency: Connections are HTTP-based, not persistent database connections.
- No stored procedures: D1 doesn't support stored procedures or custom functions.
- Rate limiting: Subject to Cloudflare API rate limits.
Type Mapping
| SQLAlchemy Type | D1/SQLite Type | Notes |
|---|---|---|
Integer |
INTEGER |
|
String(n) |
VARCHAR(n) |
|
Text |
TEXT |
|
Float |
REAL |
|
Numeric |
NUMERIC |
|
Boolean |
INTEGER |
Stored as 0/1 |
DateTime |
TEXT |
ISO format string |
Date |
TEXT |
ISO format string |
Time |
TEXT |
ISO format string |
Error Handling
The dialect will raise appropriate SQLAlchemy exceptions:
from sqlalchemy.exc import SQLAlchemyError, OperationalError
try:
result = conn.execute("SELECT * FROM nonexistent_table")
except OperationalError as e:
print(f"Database error: {e}")
except SQLAlchemyError as e:
print(f"SQLAlchemy error: {e}")
Development
For detailed development instructions, see .github/DEVELOPMENT.md.
Quick Start
git clone https://github.com/collierking/sqlalchemy-cloudflare-d1.git
cd sqlalchemy-cloudflare-d1
# Install dependencies and setup pre-commit hooks
make install
make setup_hooks
# Run tests and linting
make check
# Build package
make build
Development Tools
- Ruff: Fast Python linter and formatter
- mypy: Static type checking
- codespell: Spell checking
- pre-commit: Automated pre-commit checks
- pytest: Testing framework with socket control
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for your changes
- Run the test suite
- Submit a pull request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Related Projects
- SQLAlchemy - The Python SQL toolkit
- Cloudflare D1 - Serverless SQLite database
- httpx - HTTP client library used for API communication
Support
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 sqlalchemy_cloudflare_d1-0.3.1.tar.gz.
File metadata
- Download URL: sqlalchemy_cloudflare_d1-0.3.1.tar.gz
- Upload date:
- Size: 105.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b813da5164577197e5c068e65654c6def0ade7d8f0383d06f2d75ce14486dd6
|
|
| MD5 |
fdd96bcc9868198dde9ec8fe128ea200
|
|
| BLAKE2b-256 |
328cfa5c8559bf59d4364cd645fb3f8f7768022f1d575366fe275ff290e1fa5b
|
Provenance
The following attestation bundles were made for sqlalchemy_cloudflare_d1-0.3.1.tar.gz:
Publisher:
release.yml on CollierKing/sqlalchemy-cloudflare-d1
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sqlalchemy_cloudflare_d1-0.3.1.tar.gz -
Subject digest:
3b813da5164577197e5c068e65654c6def0ade7d8f0383d06f2d75ce14486dd6 - Sigstore transparency entry: 771861368
- Sigstore integration time:
-
Permalink:
CollierKing/sqlalchemy-cloudflare-d1@0774287942919affda9c55a4b6156b35ea4c9dc1 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/CollierKing
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0774287942919affda9c55a4b6156b35ea4c9dc1 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file sqlalchemy_cloudflare_d1-0.3.1-py3-none-any.whl.
File metadata
- Download URL: sqlalchemy_cloudflare_d1-0.3.1-py3-none-any.whl
- Upload date:
- Size: 23.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e441b868e536f27014c754806160b32802349ff0c0b3ddfce97ca00d0a89a75
|
|
| MD5 |
c14e47a1015624d868ec7d0159986ebf
|
|
| BLAKE2b-256 |
9e1441a11f85d48b7cb4b3e034cd1a9d57e16ab589558418bf0b7340536dba44
|
Provenance
The following attestation bundles were made for sqlalchemy_cloudflare_d1-0.3.1-py3-none-any.whl:
Publisher:
release.yml on CollierKing/sqlalchemy-cloudflare-d1
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sqlalchemy_cloudflare_d1-0.3.1-py3-none-any.whl -
Subject digest:
8e441b868e536f27014c754806160b32802349ff0c0b3ddfce97ca00d0a89a75 - Sigstore transparency entry: 771861369
- Sigstore integration time:
-
Permalink:
CollierKing/sqlalchemy-cloudflare-d1@0774287942919affda9c55a4b6156b35ea4c9dc1 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/CollierKing
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0774287942919affda9c55a4b6156b35ea4c9dc1 -
Trigger Event:
workflow_dispatch
-
Statement type: