Skip to content

Commit 20baa47

Browse files
authored
docs: update examples to use current SQLSpec API patterns (#37)
Bring examples up to date with latest SQLSpec architecture: ## πŸ”„ API Updates - Changed `spec.register_config()` β†’ `spec.add_config()` - Updated SQL execution to use `SQL()` objects instead of raw strings - Fixed Litestar examples to use proper SQLSpec plugin integration - Updated service examples with correct session management
1 parent ff38634 commit 20baa47

26 files changed

+700
-624
lines changed

β€ŽREADME.mdβ€Ž

Lines changed: 78 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,26 @@
44

55
SQLSpec is an experimental Python library designed to streamline and modernize your SQL interactions across a variety of database systems. While still in its early stages, SQLSpec aims to provide a flexible, typed, and extensible interface for working with SQL in Python.
66

7-
**Note**: SQLSpec is currently under active development and the API is subject to change. It is not yet ready for production use. Contributions are welcome!
7+
**Note**: SQLSpec is currently under active development and the API is subject to change. It is not yet ready for production use. Contributions are welcome!
88

9-
## Core Features (Planned but subject to change, removal or redesign)
9+
## Core Features (Current and Planned)
10+
11+
### Currently Implemented
1012

1113
- **Consistent Database Session Interface**: Provides a consistent connectivity interface for interacting with one or more database systems, including SQLite, Postgres, DuckDB, MySQL, Oracle, SQL Server, Spanner, BigQuery, and more.
12-
- **Emphasis on RAW SQL and Minimal Abstractions and Performance**: SQLSpec is a library for working with SQL in Python. It's goals are to offer minimal abstractions between the user and the database. It does not aim to be an ORM library.
14+
- **Emphasis on RAW SQL and Minimal Abstractions**: SQLSpec is a library for working with SQL in Python. Its goals are to offer minimal abstractions between the user and the database. It does not aim to be an ORM library.
1315
- **Type-Safe Queries**: Quickly map SQL queries to typed objects using libraries such as Pydantic, Msgspec, Attrs, etc.
14-
- **Extensible Design**: Easily add support for new database dialects or extend existing functionality to meet your specific needs. Easily add support for async and sync database drivers.
15-
- **Minimal Dependencies**: SQLSpec is designed to be lightweight and can run on it's own or with other libraries such as `litestar`, `fastapi`, `flask` and more. (Contributions welcome!)
16-
- **Dynamic Query Manipulation**: Easily apply filters to pre-defined queries with a fluent, Pythonic API. Safely manipulate queries without the risk of SQL injection.
17-
- **Dialect Validation and Conversion**: Use `sqlglot` to validate your SQL against specific dialects and seamlessly convert between them.
16+
- **Extensible Design**: Easily add support for new database dialects or extend existing functionality to meet your specific needs. Easily add support for async and sync database drivers.
17+
- **Minimal Dependencies**: SQLSpec is designed to be lightweight and can run on its own or with other libraries such as `litestar`, `fastapi`, `flask` and more. (Contributions welcome!)
1818
- **Support for Async and Sync Database Drivers**: SQLSpec supports both async and sync database drivers, allowing you to choose the style that best fits your application.
19+
20+
### Experimental Features (API will change rapidly)
21+
22+
- **SQL Builder API**: Type-safe query builder with method chaining (experimental and subject to significant changes)
23+
- **Dynamic Query Manipulation**: Apply filters to pre-defined queries with a fluent API. Safely manipulate queries without SQL injection risk.
24+
- **Dialect Validation and Conversion**: Use `sqlglot` to validate your SQL against specific dialects and seamlessly convert between them.
25+
- **Storage Operations**: Direct export to Parquet, CSV, JSON with Arrow integration
26+
- **Instrumentation**: OpenTelemetry and Prometheus metrics support
1927
- **Basic Migration Management**: A mechanism to generate empty migration files where you can add your own SQL and intelligently track which migrations have been applied.
2028

2129
## What SQLSpec Is Not (Yet)
@@ -26,16 +34,60 @@ SQLSpec is a work in progress. While it offers a solid foundation for modern SQL
2634

2735
We've talked about what SQLSpec is not, so let's look at what it can do.
2836

29-
These are just a few of the examples that demonstrate SQLSpec's flexibility and each of the bundled adapters offer the same config and driver interfaces.
37+
These are just a few examples that demonstrate SQLSpec's flexibility. Each of the bundled adapters offers the same config and driver interfaces.
38+
39+
### Basic Usage
40+
41+
```python
42+
from sqlspec import SQLSpec
43+
from sqlspec.adapters.sqlite import SqliteConfig
44+
from pydantic import BaseModel
45+
# Create SQLSpec instance and configure database
46+
sql = SQLSpec()
47+
config = sql.add_config(SqliteConfig(database=":memory:"))
48+
49+
# Execute queries with automatic result mapping
50+
with sql.provide_session(config) as session:
51+
# Simple query
52+
result = session.execute("SELECT 'Hello, SQLSpec!' as message")
53+
print(result.get_first()) # {'message': 'Hello, SQLSpec!'}
54+
```
55+
56+
### SQL Builder Example (Experimental)
57+
58+
**Warning**: The SQL Builder API is highly experimental and will change significantly.
59+
60+
```python
61+
from sqlspec import sql
62+
63+
# Build a simple query
64+
query = sql.select("id", "name", "email").from_("users").where("active = ?", True)
65+
print(query.build().sql) # SELECT id, name, email FROM users WHERE active = ?
66+
67+
# More complex example with joins
68+
query = (
69+
sql.select("u.name", "COUNT(o.id) as order_count")
70+
.from_("users u")
71+
.left_join("orders o", "u.id = o.user_id")
72+
.where("u.created_at > ?", "2024-01-01")
73+
.group_by("u.name")
74+
.having("COUNT(o.id) > ?", 5)
75+
.order_by("order_count", desc=True)
76+
)
77+
78+
# Execute the built query
79+
with sql.provide_session(config) as session:
80+
results = session.execute(query.build())
81+
```
3082

3183
### DuckDB LLM
3284

33-
This is a quick implementation using some of the built in Secret and Extension management features of SQLSpec's DuckDB integration.
85+
This is a quick implementation using some of the built-in Secret and Extension management features of SQLSpec's DuckDB integration.
3486

35-
It allows you to communicate with any compatible OpenAPI conversations endpoint (such as Ollama). This examples:
87+
It allows you to communicate with any compatible OpenAPI conversations endpoint (such as Ollama). This example:
3688

3789
- auto installs the `open_prompt` DuckDB extensions
38-
- automatically creates the correct `open_prompt` comptaible secret required to use the extension
90+
- automatically creates the correct `open_prompt` compatible secret required to use the extension
3991

4092
```py
4193
# /// script
@@ -80,12 +132,12 @@ with sql.provide_session(etl_config) as session:
80132

81133
### DuckDB Gemini Embeddings
82134

83-
In this example, we are again using DuckDB. However, we are going to use the built in to call the Google Gemini embeddings service directly from the database.
135+
In this example, we are again using DuckDB. However, we are going to use the built-in to call the Google Gemini embeddings service directly from the database.
84136

85-
This example will
137+
This example will:
86138

87139
- auto installs the `http_client` and `vss` (vector similarity search) DuckDB extensions
88-
- when a connection is created, it ensures that the `generate_embeddings` macro exists in the DuckDB database.
140+
- when a connection is created, it ensures that the `generate_embeddings` macro exists in the DuckDB database
89141
- Execute a simple query to call the Google API
90142

91143
```py
@@ -131,8 +183,8 @@ etl_config = sql.add_config(
131183
)
132184
)
133185
with sql.provide_session(etl_config) as session:
134-
result = session.select_one("SELECT generate_embedding('example text')")
135-
print(result) # result is a dictionary when `schema_type` is omitted.
186+
result = session.execute("SELECT generate_embedding('example text')")
187+
print(result.get_first()) # result is a dictionary when `schema_type` is omitted.
136188
```
137189

138190
### Basic Litestar Integration
@@ -147,27 +199,29 @@ In this example we are going to demonstrate how to create a basic configuration
147199
# ]
148200
# ///
149201

150-
from aiosqlite import Connection
151202
from litestar import Litestar, get
152203

153204
from sqlspec.adapters.aiosqlite import AiosqliteConfig, AiosqliteDriver
154-
from sqlspec.extensions.litestar import SQLSpec
205+
from sqlspec.extensions.litestar import DatabaseConfig, SQLSpec
155206

156207

157208
@get("/")
158209
async def simple_sqlite(db_session: AiosqliteDriver) -> dict[str, str]:
159210
return await db_session.select_one("SELECT 'Hello, world!' AS greeting")
160211

161212

162-
sqlspec = SQLSpec(config=DatabaseConfig(
163-
config=[AiosqliteConfig(), commit_mode="autocommit")],
213+
sqlspec = SQLSpec(
214+
config=DatabaseConfig(
215+
config=AiosqliteConfig(),
216+
commit_mode="autocommit"
217+
)
164218
)
165219
app = Litestar(route_handlers=[simple_sqlite], plugins=[sqlspec])
166220
```
167221

168222
## Inspiration and Future Direction
169223

170-
SQLSpec originally drew inspiration from features found in the `aiosql` library. This is a great library for working with and executed SQL stored in files. It's unclear how much of an overlap there will be between the two libraries, but it's possible that some features will be contributed back to `aiosql` where appropriate.
224+
SQLSpec originally drew inspiration from features found in the `aiosql` library. This is a great library for working with and executing SQL stored in files. It's unclear how much of an overlap there will be between the two libraries, but it's possible that some features will be contributed back to `aiosql` where appropriate.
171225

172226
## Current Focus: Universal Connectivity
173227

@@ -207,9 +261,10 @@ This list is not final. If you have a driver you'd like to see added, please ope
207261
- `litestar/`: Litestar framework integration βœ…
208262
- `fastapi/`: Future home of `fastapi` integration.
209263
- `flask/`: Future home of `flask` integration.
210-
- `*/`: Future home of your favorite framework integration πŸ”Œ ✨
264+
- `*/`: Future home of your favorite framework integration
211265
- `base.py`: Contains base protocols for database configurations.
212-
- `filters.py`: Contains the `Filter` class which is used to apply filters to pre-defined SQL queries.
266+
- `statement/`: Contains the SQL statement system with builders, validation, and transformation.
267+
- `storage/`: Contains unified storage operations for data import/export.
213268
- `utils/`: Contains utility functions used throughout the project.
214269
- `exceptions.py`: Contains custom exceptions for SQLSpec.
215270
- `typing.py`: Contains type hints, type guards and several facades for optional libraries that are not required for the core functionality of SQLSpec.

β€Ždocs/PYPI_README.mdβ€Ž

Lines changed: 78 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,26 @@
44

55
SQLSpec is an experimental Python library designed to streamline and modernize your SQL interactions across a variety of database systems. While still in its early stages, SQLSpec aims to provide a flexible, typed, and extensible interface for working with SQL in Python.
66

7-
**Note**: SQLSpec is currently under active development and the API is subject to change. It is not yet ready for production use. Contributions are welcome!
7+
**Note**: SQLSpec is currently under active development and the API is subject to change. It is not yet ready for production use. Contributions are welcome!
88

9-
## Core Features (Planned but subject to change, removal or redesign)
9+
## Core Features (Current and Planned)
10+
11+
### Currently Implemented
1012

1113
- **Consistent Database Session Interface**: Provides a consistent connectivity interface for interacting with one or more database systems, including SQLite, Postgres, DuckDB, MySQL, Oracle, SQL Server, Spanner, BigQuery, and more.
12-
- **Emphasis on RAW SQL and Minimal Abstractions and Performance**: SQLSpec is a library for working with SQL in Python. It's goals are to offer minimal abstractions between the user and the database. It does not aim to be an ORM library.
14+
- **Emphasis on RAW SQL and Minimal Abstractions**: SQLSpec is a library for working with SQL in Python. Its goals are to offer minimal abstractions between the user and the database. It does not aim to be an ORM library.
1315
- **Type-Safe Queries**: Quickly map SQL queries to typed objects using libraries such as Pydantic, Msgspec, Attrs, etc.
14-
- **Extensible Design**: Easily add support for new database dialects or extend existing functionality to meet your specific needs. Easily add support for async and sync database drivers.
15-
- **Minimal Dependencies**: SQLSpec is designed to be lightweight and can run on it's own or with other libraries such as `litestar`, `fastapi`, `flask` and more. (Contributions welcome!)
16-
- **Dynamic Query Manipulation**: Easily apply filters to pre-defined queries with a fluent, Pythonic API. Safely manipulate queries without the risk of SQL injection.
17-
- **Dialect Validation and Conversion**: Use `sqlglot` to validate your SQL against specific dialects and seamlessly convert between them.
16+
- **Extensible Design**: Easily add support for new database dialects or extend existing functionality to meet your specific needs. Easily add support for async and sync database drivers.
17+
- **Minimal Dependencies**: SQLSpec is designed to be lightweight and can run on its own or with other libraries such as `litestar`, `fastapi`, `flask` and more. (Contributions welcome!)
1818
- **Support for Async and Sync Database Drivers**: SQLSpec supports both async and sync database drivers, allowing you to choose the style that best fits your application.
19+
20+
### Experimental Features (API will change rapidly)
21+
22+
- **SQL Builder API**: Type-safe query builder with method chaining (experimental and subject to significant changes)
23+
- **Dynamic Query Manipulation**: Apply filters to pre-defined queries with a fluent API. Safely manipulate queries without SQL injection risk.
24+
- **Dialect Validation and Conversion**: Use `sqlglot` to validate your SQL against specific dialects and seamlessly convert between them.
25+
- **Storage Operations**: Direct export to Parquet, CSV, JSON with Arrow integration
26+
- **Instrumentation**: OpenTelemetry and Prometheus metrics support
1927
- **Basic Migration Management**: A mechanism to generate empty migration files where you can add your own SQL and intelligently track which migrations have been applied.
2028

2129
## What SQLSpec Is Not (Yet)
@@ -26,16 +34,60 @@ SQLSpec is a work in progress. While it offers a solid foundation for modern SQL
2634

2735
We've talked about what SQLSpec is not, so let's look at what it can do.
2836

29-
These are just a few of the examples that demonstrate SQLSpec's flexibility and each of the bundled adapters offer the same config and driver interfaces.
37+
These are just a few examples that demonstrate SQLSpec's flexibility. Each of the bundled adapters offers the same config and driver interfaces.
38+
39+
### Basic Usage
40+
41+
```python
42+
from sqlspec import SQLSpec
43+
from sqlspec.adapters.sqlite import SqliteConfig
44+
from pydantic import BaseModel
45+
# Create SQLSpec instance and configure database
46+
sql = SQLSpec()
47+
config = sql.add_config(SqliteConfig(database=":memory:"))
48+
49+
# Execute queries with automatic result mapping
50+
with sql.provide_session(config) as session:
51+
# Simple query
52+
result = session.execute("SELECT 'Hello, SQLSpec!' as message")
53+
print(result.get_first()) # {'message': 'Hello, SQLSpec!'}
54+
```
55+
56+
### SQL Builder Example (Experimental)
57+
58+
**Warning**: The SQL Builder API is highly experimental and will change significantly.
59+
60+
```python
61+
from sqlspec import sql
62+
63+
# Build a simple query
64+
query = sql.select("id", "name", "email").from_("users").where("active = ?", True)
65+
print(query.build().sql) # SELECT id, name, email FROM users WHERE active = ?
66+
67+
# More complex example with joins
68+
query = (
69+
sql.select("u.name", "COUNT(o.id) as order_count")
70+
.from_("users u")
71+
.left_join("orders o", "u.id = o.user_id")
72+
.where("u.created_at > ?", "2024-01-01")
73+
.group_by("u.name")
74+
.having("COUNT(o.id) > ?", 5)
75+
.order_by("order_count", desc=True)
76+
)
77+
78+
# Execute the built query
79+
with sql.provide_session(config) as session:
80+
results = session.execute(query.build())
81+
```
3082

3183
### DuckDB LLM
3284

33-
This is a quick implementation using some of the built in Secret and Extension management features of SQLSpec's DuckDB integration.
85+
This is a quick implementation using some of the built-in Secret and Extension management features of SQLSpec's DuckDB integration.
3486

35-
It allows you to communicate with any compatible OpenAPI conversations endpoint (such as Ollama). This examples:
87+
It allows you to communicate with any compatible OpenAPI conversations endpoint (such as Ollama). This example:
3688

3789
- auto installs the `open_prompt` DuckDB extensions
38-
- automatically creates the correct `open_prompt` comptaible secret required to use the extension
90+
- automatically creates the correct `open_prompt` compatible secret required to use the extension
3991

4092
```py
4193
# /// script
@@ -80,12 +132,12 @@ with sql.provide_session(etl_config) as session:
80132

81133
### DuckDB Gemini Embeddings
82134

83-
In this example, we are again using DuckDB. However, we are going to use the built in to call the Google Gemini embeddings service directly from the database.
135+
In this example, we are again using DuckDB. However, we are going to use the built-in to call the Google Gemini embeddings service directly from the database.
84136

85-
This example will
137+
This example will:
86138

87139
- auto installs the `http_client` and `vss` (vector similarity search) DuckDB extensions
88-
- when a connection is created, it ensures that the `generate_embeddings` macro exists in the DuckDB database.
140+
- when a connection is created, it ensures that the `generate_embeddings` macro exists in the DuckDB database
89141
- Execute a simple query to call the Google API
90142

91143
```py
@@ -131,8 +183,8 @@ etl_config = sql.add_config(
131183
)
132184
)
133185
with sql.provide_session(etl_config) as session:
134-
result = session.select_one("SELECT generate_embedding('example text')")
135-
print(result) # result is a dictionary when `schema_type` is omitted.
186+
result = session.execute("SELECT generate_embedding('example text')")
187+
print(result.get_first()) # result is a dictionary when `schema_type` is omitted.
136188
```
137189

138190
### Basic Litestar Integration
@@ -147,27 +199,29 @@ In this example we are going to demonstrate how to create a basic configuration
147199
# ]
148200
# ///
149201

150-
from aiosqlite import Connection
151202
from litestar import Litestar, get
152203

153204
from sqlspec.adapters.aiosqlite import AiosqliteConfig, AiosqliteDriver
154-
from sqlspec.extensions.litestar import SQLSpec
205+
from sqlspec.extensions.litestar import DatabaseConfig, SQLSpec
155206

156207

157208
@get("/")
158209
async def simple_sqlite(db_session: AiosqliteDriver) -> dict[str, str]:
159210
return await db_session.select_one("SELECT 'Hello, world!' AS greeting")
160211

161212

162-
sqlspec = SQLSpec(config=DatabaseConfig(
163-
config=[AiosqliteConfig(), commit_mode="autocommit")],
213+
sqlspec = SQLSpec(
214+
config=DatabaseConfig(
215+
config=AiosqliteConfig(),
216+
commit_mode="autocommit"
217+
)
164218
)
165219
app = Litestar(route_handlers=[simple_sqlite], plugins=[sqlspec])
166220
```
167221

168222
## Inspiration and Future Direction
169223

170-
SQLSpec originally drew inspiration from features found in the `aiosql` library. This is a great library for working with and executed SQL stored in files. It's unclear how much of an overlap there will be between the two libraries, but it's possible that some features will be contributed back to `aiosql` where appropriate.
224+
SQLSpec originally drew inspiration from features found in the `aiosql` library. This is a great library for working with and executing SQL stored in files. It's unclear how much of an overlap there will be between the two libraries, but it's possible that some features will be contributed back to `aiosql` where appropriate.
171225

172226
## Current Focus: Universal Connectivity
173227

@@ -207,9 +261,10 @@ This list is not final. If you have a driver you'd like to see added, please ope
207261
- `litestar/`: Litestar framework integration βœ…
208262
- `fastapi/`: Future home of `fastapi` integration.
209263
- `flask/`: Future home of `flask` integration.
210-
- `*/`: Future home of your favorite framework integration πŸ”Œ ✨
264+
- `*/`: Future home of your favorite framework integration
211265
- `base.py`: Contains base protocols for database configurations.
212-
- `filters.py`: Contains the `Filter` class which is used to apply filters to pre-defined SQL queries.
266+
- `statement/`: Contains the SQL statement system with builders, validation, and transformation.
267+
- `storage/`: Contains unified storage operations for data import/export.
213268
- `utils/`: Contains utility functions used throughout the project.
214269
- `exceptions.py`: Contains custom exceptions for SQLSpec.
215270
- `typing.py`: Contains type hints, type guards and several facades for optional libraries that are not required for the core functionality of SQLSpec.

0 commit comments

Comments
Β (0)