Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ repos:
- id: mixed-line-ending
- id: trailing-whitespace
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: "v0.14.3"
rev: "v0.14.4"
hooks:
- id: ruff
args: ["--fix"]
Expand Down
Empty file.
22 changes: 22 additions & 0 deletions docs/examples/quickstart/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from __future__ import annotations

from collections.abc import Generator

import pytest
from pytest_databases.docker.postgres import PostgresService

pytest_plugins = ["pytest_databases.docker.postgres"]


@pytest.fixture(scope="session", autouse=True)
def quickstart_postgres_env(postgres_service: PostgresService) -> Generator[None, None, None]:
"""Expose pytest-databases Postgres settings to docs quickstart examples."""

patcher = pytest.MonkeyPatch()
patcher.setenv("SQLSPEC_QUICKSTART_PG_HOST", postgres_service.host)
patcher.setenv("SQLSPEC_QUICKSTART_PG_PORT", str(postgres_service.port))
patcher.setenv("SQLSPEC_QUICKSTART_PG_USER", postgres_service.user)
patcher.setenv("SQLSPEC_QUICKSTART_PG_PASSWORD", postgres_service.password)
patcher.setenv("SQLSPEC_QUICKSTART_PG_DATABASE", postgres_service.database)
yield
patcher.undo()
17 changes: 17 additions & 0 deletions docs/examples/quickstart/quickstart_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from sqlspec import SQLSpec
from sqlspec.adapters.sqlite import SqliteConfig

__all__ = ("test_quickstart_1",)


def test_quickstart_1() -> None:
# Create SQLSpec instance and configure database
db_manager = SQLSpec()
db = db_manager.add_config(SqliteConfig(pool_config={"database": ":memory:"}))

# Execute a query
with db_manager.provide_session(db) as session:
result = session.execute("SELECT 'Hello, SQLSpec!' as message")
print(result.get_first()) # {'message': 'Hello, SQLSpec!'}

assert result.get_first() == {"message": "Hello, SQLSpec!"}
44 changes: 44 additions & 0 deletions docs/examples/quickstart/quickstart_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from sqlspec import SQLSpec
from sqlspec.adapters.sqlite import SqliteConfig

__all__ = ("test_quickstart_2",)


def test_quickstart_2() -> None:
db_manager = SQLSpec()
db = db_manager.add_config(SqliteConfig(pool_config={"database": ":memory:"}))

with db_manager.provide_session(db) as session:
# Create a table
_ = session.execute("""
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
)
""")

# Insert data
_ = session.execute("INSERT INTO users (name, email) VALUES (?, ?)", "Alice", "alice@example.com")

# Insert multiple rows
_ = session.execute_many(
"INSERT INTO users (name, email) VALUES (?, ?)",
[("Bob", "bob@example.com"), ("Charlie", "charlie@example.com")],
)

# Query all users
users = session.select("SELECT * FROM users")
print(f"All users: {users}")

# Query single user
alice = session.select_one("SELECT * FROM users WHERE name = ?", "Alice")
print(f"Alice: {alice}")

# Query scalar value
count = session.select_value("SELECT COUNT(*) FROM users")
print(f"Total users: {count}")

assert len(users) == 3 # noqa: PLR2004
assert alice == {"id": 1, "name": "Alice", "email": "alice@example.com"}
assert count == 3 # noqa: PLR2004
39 changes: 39 additions & 0 deletions docs/examples/quickstart/quickstart_3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from pydantic import BaseModel

from sqlspec import SQLSpec
from sqlspec.adapters.sqlite import SqliteConfig

__all__ = ("User",)


class User(BaseModel):
id: int
name: str
email: str


def test_quickstart_3() -> None:
db_manager = SQLSpec()
db = db_manager.add_config(SqliteConfig(pool_config={"database": ":memory:"}))

with db_manager.provide_session(db) as session:
# Setup
_ = session.execute("""
CREATE TABLE users (id INTEGER, name TEXT, email TEXT)
""")
_ = session.execute("INSERT INTO users VALUES (?, ?, ?)", 1, "Alice", "alice@example.com")

# Type-safe query - returns User instance
user = session.select_one("SELECT * FROM users WHERE id = ?", 1, schema_type=User)

# Now you have type hints and autocomplete!
print(f"User: {user.name} ({user.email})") # IDE knows these fields exist

# Multiple results
all_users = session.select("SELECT * FROM users", schema_type=User)
for u in all_users:
print(f"User: {u.name}") # Each item is a typed User

assert user == User(id=1, name="Alice", email="alice@example.com")
assert len(all_users) == 1
assert isinstance(all_users[0], User)
36 changes: 36 additions & 0 deletions docs/examples/quickstart/quickstart_4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from pydantic import BaseModel

from sqlspec import SQLSpec
from sqlspec.adapters.aiosqlite import AiosqliteConfig

__all__ = ("User", "test_quickstart_4")


class User(BaseModel):
id: int
name: str
email: str


async def test_quickstart_4() -> None:
db_manager = SQLSpec()
db = db_manager.add_config(AiosqliteConfig(pool_config={"database": ":memory:"}))

async with db_manager.provide_session(db) as session:
# Create table
_ = await session.execute("""
CREATE TABLE users (id INTEGER, name TEXT, email TEXT)
""")

# Insert data
_ = await session.execute("INSERT INTO users VALUES (?, ?, ?)", 1, "Alice", "alice@example.com")

# Type-safe async query
user = await session.select_one("SELECT * FROM users WHERE id = ?", 1, schema_type=User)

print(f"User: {user.name}")

assert user == User(id=1, name="Alice", email="alice@example.com")
assert isinstance(user, User)
assert user.name == "Alice"
assert user.email == "alice@example.com"
53 changes: 53 additions & 0 deletions docs/examples/quickstart/quickstart_5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import os
from typing import Any

from pydantic import BaseModel

from sqlspec import SQLSpec
from sqlspec.adapters.asyncpg import AsyncpgConfig

__all__ = ("User", "test_quickstart_5")


class User(BaseModel):
id: int
name: str
email: str


def _pool_config() -> "dict[str, Any]":
return {
"host": os.getenv("SQLSPEC_QUICKSTART_PG_HOST", "localhost"),
"port": int(os.getenv("SQLSPEC_QUICKSTART_PG_PORT", "5432")),
"user": os.getenv("SQLSPEC_QUICKSTART_PG_USER", "postgres"),
"password": os.getenv("SQLSPEC_QUICKSTART_PG_PASSWORD", "postgres"),
"database": os.getenv("SQLSPEC_QUICKSTART_PG_DATABASE", "mydb"),
}


async def _seed_users(session: Any) -> None:
await session.execute(
"""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL
)
"""
)
await session.execute("TRUNCATE TABLE users")
await session.execute("INSERT INTO users (id, name, email) VALUES ($1, $2, $3)", 1, "Alice", "alice@example.com")


async def test_quickstart_5() -> None:
db_manager = SQLSpec()
db = db_manager.add_config(AsyncpgConfig(pool_config=_pool_config()))

async with db_manager.provide_session(db) as session:
await _seed_users(session)

# PostgreSQL uses $1, $2 for parameters instead of ?
user = await session.select_one("SELECT * FROM users WHERE id = $1", 1, schema_type=User)
print(f"User: {user.name}")

assert user == User(id=1, name="Alice", email="alice@example.com")
23 changes: 23 additions & 0 deletions docs/examples/quickstart/quickstart_6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from sqlspec import SQLSpec
from sqlspec.adapters.duckdb import DuckDBConfig
from sqlspec.adapters.sqlite import SqliteConfig

__all__ = ("test_quickstart_6",)


def test_quickstart_6() -> None:
db_manager = SQLSpec()

# Register multiple databases
sqlite_db = db_manager.add_config(SqliteConfig(pool_config={"database": "app.db"}))
duckdb_db = db_manager.add_config(DuckDBConfig(pool_config={"database": "analytics.duckdb"}))

# Use different databases
with db_manager.provide_session(sqlite_db) as sqlite_session:
users = sqlite_session.select("SELECT 1")

with db_manager.provide_session(duckdb_db) as duckdb_session:
analytics = duckdb_session.select("SELECT 1")

assert isinstance(users, list)
assert isinstance(analytics, list)
44 changes: 44 additions & 0 deletions docs/examples/quickstart/quickstart_7.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from sqlspec import SQLSpec
from sqlspec.adapters.sqlite import SqliteConfig

__all__ = ("test_quickstart_7",)


def test_quickstart_7() -> None:
db_manager = SQLSpec()

db = db_manager.add_config(SqliteConfig(pool_config={"database": ":memory:"}))

# Transaction committed on successful exit
with db_manager.provide_session(db) as session:
session.begin()
_ = session.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
)
""")
_ = session.execute("""
CREATE TABLE IF NOT EXISTS orders (
id INTEGER PRIMARY KEY,
user_name TEXT NOT NULL
)
""")
_ = session.execute("DELETE FROM users")
_ = session.execute("DELETE FROM orders")
_ = session.execute("INSERT INTO users (name) VALUES (?)", "Alice")
_ = session.execute("INSERT INTO orders (user_name) VALUES (?)", "Alice")
session.commit()

with db_manager.provide_session(db) as session:
session.begin()
_ = session.execute("INSERT INTO users (name) VALUES (?)", "Bob")
session.rollback()

with db_manager.provide_session(db) as session:
alice = session.select_one_or_none("SELECT * FROM users WHERE name = ?", "Alice")
bob = session.select_one_or_none("SELECT * FROM users WHERE name = ?", "Bob")

assert alice is not None
assert alice["name"] == "Alice"
assert bob is None
26 changes: 26 additions & 0 deletions docs/examples/quickstart/quickstart_8.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from sqlspec import SQLSpec, sql
from sqlspec.adapters.sqlite import SqliteConfig

__all__ = ("test_quickstart_8",)


def test_quickstart_8() -> None:
# Build a query programmatically
query = sql.select("id", "name", "email").from_("users").where("age > ?").order_by("name")

db_manager = SQLSpec()
db = db_manager.add_config(SqliteConfig(pool_config={"database": ":memory:"}))

with db_manager.provide_session(db) as session:
# Setup
_ = session.execute("""
CREATE TABLE users (id INTEGER, name TEXT, email TEXT, age INTEGER)
""")
_ = session.execute("INSERT INTO users VALUES (?, ?, ?, ?)", 1, "Alice", "alice@example.com", 30)

# Execute built query
results = session.select(query, 25)
print(results)

assert len(results) == 1
assert results[0] == {"id": 1, "name": "Alice", "email": "alice@example.com"}
Loading
Loading