Name | sqlalchemy-cloudflare-d1 JSON |
Version |
0.1.0
JSON |
| download |
home_page | None |
Summary | A SQLAlchemy dialect for Cloudflare's D1 Serverless SQLite Database using the REST API |
upload_time | 2025-07-24 14:46:54 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.9 |
license | MIT License
Copyright (c) 2025 Collier King
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. |
keywords |
cloudflare
d1
database
serverless
sqlalchemy
sqlite
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# SQLAlchemy Cloudflare D1 Dialect
A SQLAlchemy dialect for [Cloudflare's D1 Serverless SQLite Database](https://developers.cloudflare.com/d1/) 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
```bash
pip install sqlalchemy-cloudflare-d1
```
Or install from source:
```bash
git clone https://github.com/collierking/sqlalchemy-cloudflare-d1.git
cd sqlalchemy-cloudflare-d1
pip install -e .
```
## Prerequisites
1. A Cloudflare account with D1 enabled
2. A D1 database created via the Cloudflare dashboard or CLI
3. A Cloudflare API token with D1 permissions
### Creating a D1 Database
Using the Cloudflare CLI:
```bash
wrangler d1 create my-database
```
Or via the [Cloudflare dashboard](https://dash.cloudflare.com/).
### Creating an API Token
1. Go to [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens)
2. Click "Create Token"
3. Use the "Custom token" template
4. Add permissions: `Account:D1:Edit`
5. Add your account in "Account Resources"
6. Click "Continue to summary" and "Create Token"
## Usage
### Connection String Format
```python
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
```python
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
```python
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
```python
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:
```python
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:
```python
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:
1. **No transactions**: D1 REST API doesn't support explicit transactions. Each query is auto-committed.
2. **No isolation levels**: Connection isolation levels are not supported.
3. **Limited concurrency**: Connections are HTTP-based, not persistent database connections.
4. **No stored procedures**: D1 doesn't support stored procedures or custom functions.
5. **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:
```python
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`](.github/DEVELOPMENT.md).
### Quick Start
```bash
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
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for your changes
5. Run the test suite
6. Submit a pull request
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Related Projects
- [SQLAlchemy](https://www.sqlalchemy.org/) - The Python SQL toolkit
- [Cloudflare D1](https://developers.cloudflare.com/d1/) - Serverless SQLite database
- [httpx](https://www.python-httpx.org/) - HTTP client library used for API communication
## Support
- [GitHub Issues](https://github.com/collierking/sqlalchemy-cloudflare-d1/issues)
- [Cloudflare D1 Documentation](https://developers.cloudflare.com/d1/)
- [SQLAlchemy Documentation](https://docs.sqlalchemy.org/)
Raw data
{
"_id": null,
"home_page": null,
"name": "sqlalchemy-cloudflare-d1",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "cloudflare, d1, database, serverless, sqlalchemy, sqlite",
"author": null,
"author_email": "Collier King <collierking99@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/2d/d7/46f7a076de1e6482d394f3a5a6508328868cc5428b5c2cc8d2bff8d19136/sqlalchemy_cloudflare_d1-0.1.0.tar.gz",
"platform": null,
"description": "# SQLAlchemy Cloudflare D1 Dialect\n\nA SQLAlchemy dialect for [Cloudflare's D1 Serverless SQLite Database](https://developers.cloudflare.com/d1/) using the REST API.\n\n## Features\n\n- Full SQLAlchemy ORM and Core support\n- Async and sync query execution via D1 REST API\n- SQLite/D1 compatible SQL compilation\n- Prepared statement support with parameter binding\n- Connection pooling and management\n- Type mapping for D1/SQLite data types\n\n## Installation\n\n```bash\npip install sqlalchemy-cloudflare-d1\n```\n\nOr install from source:\n\n```bash\ngit clone https://github.com/collierking/sqlalchemy-cloudflare-d1.git\ncd sqlalchemy-cloudflare-d1\npip install -e .\n```\n\n## Prerequisites\n\n1. A Cloudflare account with D1 enabled\n2. A D1 database created via the Cloudflare dashboard or CLI\n3. A Cloudflare API token with D1 permissions\n\n### Creating a D1 Database\n\nUsing the Cloudflare CLI:\n```bash\nwrangler d1 create my-database\n```\n\nOr via the [Cloudflare dashboard](https://dash.cloudflare.com/).\n\n### Creating an API Token\n\n1. Go to [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens)\n2. Click \"Create Token\"\n3. Use the \"Custom token\" template\n4. Add permissions: `Account:D1:Edit`\n5. Add your account in \"Account Resources\"\n6. Click \"Continue to summary\" and \"Create Token\"\n\n## Usage\n\n### Connection String Format\n\n```python\nfrom sqlalchemy import create_engine\n\n# Format: cloudflare_d1://account_id:api_token@database_id\nengine = create_engine(\n \"cloudflare_d1://your_account_id:your_api_token@your_database_id\"\n)\n```\n\n### Basic Example\n\n```python\nfrom sqlalchemy import create_engine, Column, Integer, String\nfrom sqlalchemy.ext.declarative import declarative_base\nfrom sqlalchemy.orm import sessionmaker\n\n# Create engine\nengine = create_engine(\n \"cloudflare_d1://account_id:api_token@database_id\"\n)\n\n# Create base and define model\nBase = declarative_base()\n\nclass User(Base):\n __tablename__ = 'users'\n\n id = Column(Integer, primary_key=True)\n name = Column(String(50))\n email = Column(String(100))\n\n# Create tables\nBase.metadata.create_all(engine)\n\n# Create session and add data\nSession = sessionmaker(bind=engine)\nsession = Session()\n\n# Add a user\nuser = User(name=\"Alice\", email=\"alice@example.com\")\nsession.add(user)\nsession.commit()\n\n# Query users\nusers = session.query(User).all()\nfor user in users:\n print(f\"{user.name}: {user.email}\")\n\nsession.close()\n```\n\n### Core API Example\n\n```python\nfrom sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, select\n\nengine = create_engine(\"cloudflare_d1://account_id:api_token@database_id\")\n\nmetadata = MetaData()\nusers = Table('users', metadata,\n Column('id', Integer, primary_key=True),\n Column('name', String(50)),\n Column('email', String(100))\n)\n\n# Create table\nmetadata.create_all(engine)\n\nwith engine.connect() as conn:\n # Insert data\n conn.execute(users.insert().values(name=\"Bob\", email=\"bob@example.com\"))\n\n # Query data\n result = conn.execute(select(users))\n for row in result:\n print(row)\n```\n\n### Raw SQL Example\n\n```python\nfrom sqlalchemy import create_engine, text\n\nengine = create_engine(\"cloudflare_d1://account_id:api_token@database_id\")\n\nwith engine.connect() as conn:\n # Execute raw SQL\n result = conn.execute(text(\"SELECT * FROM sqlite_master WHERE type='table'\"))\n\n for row in result:\n print(row)\n```\n\n## Configuration\n\n### Connection Parameters\n\nYou can pass additional parameters via the connection string or engine creation:\n\n```python\nfrom sqlalchemy import create_engine\n\n# Via connection string query parameters\nengine = create_engine(\n \"cloudflare_d1://account_id:api_token@database_id?timeout=60\"\n)\n\n# Via connect_args\nengine = create_engine(\n \"cloudflare_d1://account_id:api_token@database_id\",\n connect_args={\n \"timeout\": 60,\n }\n)\n```\n\n### Environment Variables\n\nYou can also use environment variables:\n\n```python\nimport os\nfrom sqlalchemy import create_engine\n\nengine = create_engine(\n f\"cloudflare_d1://{os.getenv('CF_ACCOUNT_ID')}:\"\n f\"{os.getenv('CF_API_TOKEN')}@{os.getenv('CF_DATABASE_ID')}\"\n)\n```\n\n## Limitations\n\nThis dialect has some limitations due to D1's REST API nature:\n\n1. **No transactions**: D1 REST API doesn't support explicit transactions. Each query is auto-committed.\n2. **No isolation levels**: Connection isolation levels are not supported.\n3. **Limited concurrency**: Connections are HTTP-based, not persistent database connections.\n4. **No stored procedures**: D1 doesn't support stored procedures or custom functions.\n5. **Rate limiting**: Subject to Cloudflare API rate limits.\n\n## Type Mapping\n\n| SQLAlchemy Type | D1/SQLite Type | Notes |\n|----------------|----------------|-------|\n| `Integer` | `INTEGER` | |\n| `String(n)` | `VARCHAR(n)` | |\n| `Text` | `TEXT` | |\n| `Float` | `REAL` | |\n| `Numeric` | `NUMERIC` | |\n| `Boolean` | `INTEGER` | Stored as 0/1 |\n| `DateTime` | `TEXT` | ISO format string |\n| `Date` | `TEXT` | ISO format string |\n| `Time` | `TEXT` | ISO format string |\n\n## Error Handling\n\nThe dialect will raise appropriate SQLAlchemy exceptions:\n\n```python\nfrom sqlalchemy.exc import SQLAlchemyError, OperationalError\n\ntry:\n result = conn.execute(\"SELECT * FROM nonexistent_table\")\nexcept OperationalError as e:\n print(f\"Database error: {e}\")\nexcept SQLAlchemyError as e:\n print(f\"SQLAlchemy error: {e}\")\n```\n\n## Development\n\nFor detailed development instructions, see [`.github/DEVELOPMENT.md`](.github/DEVELOPMENT.md).\n\n### Quick Start\n\n```bash\ngit clone https://github.com/collierking/sqlalchemy-cloudflare-d1.git\ncd sqlalchemy-cloudflare-d1\n\n# Install dependencies and setup pre-commit hooks\nmake install\nmake setup_hooks\n\n# Run tests and linting\nmake check\n\n# Build package\nmake build\n```\n\n### Development Tools\n\n- **Ruff**: Fast Python linter and formatter\n- **mypy**: Static type checking\n- **codespell**: Spell checking\n- **pre-commit**: Automated pre-commit checks\n- **pytest**: Testing framework with socket control\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests for your changes\n5. Run the test suite\n6. Submit a pull request\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Related Projects\n\n- [SQLAlchemy](https://www.sqlalchemy.org/) - The Python SQL toolkit\n- [Cloudflare D1](https://developers.cloudflare.com/d1/) - Serverless SQLite database\n- [httpx](https://www.python-httpx.org/) - HTTP client library used for API communication\n\n## Support\n\n- [GitHub Issues](https://github.com/collierking/sqlalchemy-cloudflare-d1/issues)\n- [Cloudflare D1 Documentation](https://developers.cloudflare.com/d1/)\n- [SQLAlchemy Documentation](https://docs.sqlalchemy.org/)\n",
"bugtrack_url": null,
"license": "MIT License\n \n Copyright (c) 2025 Collier King\n \n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n \n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n \n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.",
"summary": "A SQLAlchemy dialect for Cloudflare's D1 Serverless SQLite Database using the REST API",
"version": "0.1.0",
"project_urls": {
"Homepage": "https://github.com/collierking/sqlalchemy-cloudflare-d1",
"Issues": "https://github.com/collierking/sqlalchemy-cloudflare-d1/issues",
"Repository": "https://github.com/collierking/sqlalchemy-cloudflare-d1"
},
"split_keywords": [
"cloudflare",
" d1",
" database",
" serverless",
" sqlalchemy",
" sqlite"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "b4a12dedee58fd35138bcf658918820b840529eed83a56989ed94e8590d2efd2",
"md5": "a5f7e5c5dee3baa1aa48b2f830de1ae2",
"sha256": "3b19f6c352c05c1f6e4750ea9f31bae16273cca09dc0b72f7f15e3461dbb4d8c"
},
"downloads": -1,
"filename": "sqlalchemy_cloudflare_d1-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a5f7e5c5dee3baa1aa48b2f830de1ae2",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 15126,
"upload_time": "2025-07-24T14:46:53",
"upload_time_iso_8601": "2025-07-24T14:46:53.222955Z",
"url": "https://files.pythonhosted.org/packages/b4/a1/2dedee58fd35138bcf658918820b840529eed83a56989ed94e8590d2efd2/sqlalchemy_cloudflare_d1-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "2dd746f7a076de1e6482d394f3a5a6508328868cc5428b5c2cc8d2bff8d19136",
"md5": "4f68f9f6c5172261475b4280519e360d",
"sha256": "39cac0f9e3e1ae8acd7101ee1ce0205a11fd03f3903f865742553648826de365"
},
"downloads": -1,
"filename": "sqlalchemy_cloudflare_d1-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "4f68f9f6c5172261475b4280519e360d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 49620,
"upload_time": "2025-07-24T14:46:54",
"upload_time_iso_8601": "2025-07-24T14:46:54.888156Z",
"url": "https://files.pythonhosted.org/packages/2d/d7/46f7a076de1e6482d394f3a5a6508328868cc5428b5c2cc8d2bff8d19136/sqlalchemy_cloudflare_d1-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-24 14:46:54",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "collierking",
"github_project": "sqlalchemy-cloudflare-d1",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "sqlalchemy-cloudflare-d1"
}