https://github.com/yeongseon/azure-functions-db-python
Database trigger and input/output bindings for Azure Functions Python v2 — Part of the Azure Functions Python DX Toolkit
https://github.com/yeongseon/azure-functions-db-python
azure azure-functions binding database dx-toolkit python serverless sqlalchemy trigger
Last synced: 14 days ago
JSON representation
Database trigger and input/output bindings for Azure Functions Python v2 — Part of the Azure Functions Python DX Toolkit
- Host: GitHub
- URL: https://github.com/yeongseon/azure-functions-db-python
- Owner: yeongseon
- License: mit
- Created: 2026-04-08T00:17:26.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-05-21T00:34:15.000Z (about 1 month ago)
- Last Synced: 2026-05-22T05:48:18.336Z (about 1 month ago)
- Topics: azure, azure-functions, binding, database, dx-toolkit, python, serverless, sqlalchemy, trigger
- Language: Python
- Homepage: https://yeongseon.github.io/azure-functions-db-python/
- Size: 1.41 MB
- Stars: 4
- Watchers: 0
- Forks: 0
- Open Issues: 11
-
Metadata Files:
- Readme: README.ja.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
- Support: SUPPORT.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
# Azure Functions DB
[](https://pypi.org/project/azure-functions-db-python/)
[](https://pypi.org/project/azure-functions-db-python/)
[](https://github.com/yeongseon/azure-functions-db-python/actions/workflows/ci-test.yml)
[](https://github.com/yeongseon/azure-functions-db-python/actions/workflows/publish-pypi.yml)
[](https://codecov.io/gh/yeongseon/azure-functions-db-python)
[](https://pre-commit.com/)
[](https://yeongseon.github.io/azure-functions-db-python/)
[](LICENSE)
Read this in: [English](README.md) | [한국어](README.ko.md) | [简体中文](README.zh-CN.md)
**Azure Functions Python v2** 向けのデータベース統合ライブラリです。SQLAlchemy を使ったポーリング型変更検知トリガーと入出力バインディングを提供します。
---
**Azure Functions Python DX Toolkit** の一部
→ Azure Functions に FastAPI ライクな開発体験を提供
## これが必要な理由
Azure Functions Python v2 には、データベース統合の標準的な仕組みがありません。
- **DB トリガーがない** — Cosmos DB とは異なり、RDB 向けのネイティブトリガーがない
- **入出力バインディングがない** — 関数で DB 行を宣言的に読み書きする方法がない
- **ドライバー選定が複雑** — DB ごとにドライバー、接続文字列、セットアップが異なる
- **変更検知がない** — polling / CDC / outbox を毎回ゼロから実装する必要がある
## 提供機能
- **疑似 DB トリガー** — チェックポイント、リース、at-least-once 配信を備えたポーリング型変更検知
- **マルチ DB 対応** — SQLAlchemy dialect により PostgreSQL / MySQL / SQL Server をサポート
- **単一 `pip install`** — DB ごとの optional extras を持つ 1 パッケージ
- **データ注入** — `input` はクエリ結果を直接注入し、`output` は戻り値の書き込みを自動化
- **クライアント注入** — 必要に応じて `inject_reader`/`inject_writer` で命令的制御が可能
## Shared Core
`azure-functions-db-python` は今後のバインディングで共有する基盤を公開しています。正規化された接続設定には `DbConfig` を、複数コンポーネントで遅延生成された SQLAlchemy エンジンを共有する場合は `EngineProvider` を利用してください。
## Installation
```bash
# Core package (pick your database)
pip install azure-functions-db-python[postgres]
pip install azure-functions-db-python[mysql]
pip install azure-functions-db-python[mssql]
# Multiple databases
pip install azure-functions-db-python[postgres,mysql]
# All drivers
pip install azure-functions-db-python[all]
```
Function App の依存関係には次を含めてください。
```text
azure-functions
azure-functions-db-python[postgres]
```
## Quick Start
### どのデコレーターを使うべきか?
| Need | Decorator | Mode |
|------|-----------|------|
| Read data into handler | `input` | Declarative (data injection) |
| Write data to DB | `output` | Declarative (data injection) |
| Complex reads (multiple queries) | `inject_reader` | Imperative (client injection) |
| Complex writes (transactions) | `inject_writer` | Imperative (client injection) |
| React to DB changes | `trigger` | Event-driven (pseudo-trigger) |
### Input Binding (data injection)
`input` は実際のクエリ結果をそのままハンドラーに注入します。クライアントは不要です。
**Row lookup mode** — 主キーで 1 行取得:
```python
from azure_functions_db import DbBindings
db = DbBindings()
# Static primary key
@db.input("user", url="%DB_URL%", table="users", pk={"id": 42})
def load_user(user: dict | None) -> None:
if user:
print(user["name"])
# Dynamic primary key — resolved from handler kwargs
@db.input("user", url="%DB_URL%", table="users",
pk=lambda req: {"id": req.params["id"]})
def get_user(req, user: dict | None) -> None:
print(user)
```
**Query mode** — SQL で複数行取得:
```python
# Multiple rows by SQL query
@db.input("users", url="%DB_URL%",
query="SELECT * FROM users WHERE active = :active",
params={"active": True})
def list_active_users(users: list[dict]) -> None:
for user in users:
print(user["email"])
```
### Output Binding (data injection)
`output` は `DbOut` インスタンスをハンドラーに注入します。明示的に書き込むには `.set()` を呼びます。
```python
from azure_functions_db import DbBindings, DbOut
db = DbBindings()
# Insert — call .set() with a dict for single row, list[dict] for batch
@db.output("out", url="%DB_URL%", table="orders")
def create_order(out: DbOut) -> str:
out.set({"id": 1, "status": "pending", "total": 99.99})
return "Created"
# Upsert — set action and conflict_columns
@db.output("out", url="%DB_URL%", table="orders",
action="upsert", conflict_columns=["id"])
def upsert_orders(out: DbOut) -> str:
out.set([
{"id": 1, "status": "shipped", "total": 99.99},
{"id": 2, "status": "pending", "total": 49.99},
])
return "Upserted"
```
ハンドラーの戻り値は書き込み処理とは独立しています。HTTP レスポンスなどに自由に使えます。
```python
import azure.functions as func
from azure_functions_db import DbBindings, DbOut
db = DbBindings()
@db.output("out", url="%DB_URL%", table="orders")
def create_order(req: func.HttpRequest, out: DbOut) -> func.HttpResponse:
out.set({"id": 1, "status": "pending"})
return func.HttpResponse("Created", status_code=201)
```
対応 upsert dialect: PostgreSQL, SQLite, MySQL。
### Client Injection (imperative escape hatches)
複雑な処理(複数クエリ、トランザクション、update/delete)では、`inject_reader`/`inject_writer` でクライアントを注入して使います。
```python
from azure_functions_db import DbBindings, DbReader, DbWriter
db = DbBindings()
@db.inject_reader("reader", url="%DB_URL%", table="users")
def complex_read(reader: DbReader) -> None:
user = reader.get(pk={"id": 42})
orders = reader.query("SELECT * FROM orders WHERE user_id = :uid", params={"uid": 42})
@db.inject_writer("writer", url="%DB_URL%", table="orders")
def complex_write(writer: DbWriter) -> None:
writer.insert(data={"id": 1, "status": "pending"})
writer.update(data={"status": "shipped"}, pk={"id": 1})
writer.delete(pk={"id": 1})
```
### Trigger (change detection)
```python
import azure.functions as func
from azure.storage.blob import ContainerClient
from azure_functions_db import BlobCheckpointStore, DbBindings, RowChange, SqlAlchemySource
app = func.FunctionApp()
db = DbBindings()
source = SqlAlchemySource(
url="%ORDERS_DB_URL%",
table="orders",
schema="public",
cursor_column="updated_at",
pk_columns=["id"],
)
checkpoint_store = BlobCheckpointStore(
container_client=ContainerClient.from_connection_string(
conn_str="%AzureWebJobsStorage%",
container_name="db-state",
),
source_fingerprint=source.source_descriptor.fingerprint,
)
@app.function_name(name="orders_poll")
@app.schedule(schedule="0 */1 * * * *", arg_name="timer", use_monitor=True)
@db.trigger(arg_name="events", source=source, checkpoint_store=checkpoint_store)
def orders_poll(timer: func.TimerRequest, events: list[RowChange]) -> None:
for event in events:
print(f"Order {event.pk}: {event.op}")
```
> これは **疑似トリガー** です。実際に動かすには Azure Functions の実トリガー(例: timer)が必要です。
> API 全体は [Python API Spec](docs/04-python-api-spec.md) を参照してください。
### Combined: Trigger + Binding
DB 変更を処理し、結果を別テーブルへ書き込みます。接続プール共有のため `EngineProvider` を利用します。
```python
import azure.functions as func
from azure.storage.blob import ContainerClient
from azure_functions_db import (
BlobCheckpointStore,
DbBindings,
DbOut,
EngineProvider,
RowChange,
SqlAlchemySource,
)
app = func.FunctionApp()
db = DbBindings()
engine_provider = EngineProvider()
source = SqlAlchemySource(
url="%SOURCE_DB_URL%",
table="orders",
cursor_column="updated_at",
pk_columns=["id"],
engine_provider=engine_provider,
)
checkpoint_store = BlobCheckpointStore(
container_client=ContainerClient.from_connection_string(
conn_str="%AzureWebJobsStorage%",
container_name="db-state",
),
source_fingerprint=source.source_descriptor.fingerprint,
)
@app.function_name(name="orders_poll")
@app.schedule(schedule="0 */1 * * * *", arg_name="timer", use_monitor=True)
@db.trigger(arg_name="events", source=source, checkpoint_store=checkpoint_store)
@db.output(
"out",
url="%DEST_DB_URL%",
table="processed_orders",
action="upsert",
conflict_columns=["order_id"],
engine_provider=engine_provider,
)
def orders_poll(timer: func.TimerRequest, events: list[RowChange], out: DbOut) -> None:
out.set([
{
"order_id": event.pk["id"],
"customer": event.after["name"],
"processed_at": str(event.cursor),
}
for event in events
if event.after is not None
])
```
完全に実行可能なサンプルは [`examples/trigger_with_binding/`](examples/trigger_with_binding/) を参照してください。
## Supported Databases
| Database | Extra | Driver |
|----------|-------|--------|
| PostgreSQL | `azure-functions-db-python[postgres]` | [psycopg](https://www.psycopg.org/) |
| MySQL | `azure-functions-db-python[mysql]` | [PyMySQL](https://pymysql.readthedocs.io/) |
| SQL Server | `azure-functions-db-python[mssql]` | [pyodbc](https://github.com/mkleehammer/pyodbc) |
## Scope
- Azure Functions Python **v2 programming model**
- Timer-triggered functions for poll-based change detection
- SQLAlchemy 2.0+ for database abstraction
- Checkpoint storage via Azure Blob Storage
- Read/write bindings via HTTP/Queue/Event triggers
このパッケージはネイティブ Azure Functions トリガー拡張を実装しません。既存の timer trigger 上で動くポーリング方式を採用しています。
## Observability
`azure-functions-db-python` は構造化ログヘルパーと軽量な `MetricsCollector` プロトコルを提供し、重い依存追加なしで任意のメトリクス基盤と接続できます。
```python
from collections.abc import Mapping
from azure_functions_db import MetricsCollector, PollTrigger
class PrintMetricsCollector:
def increment(
self, name: str, value: float = 1, *, labels: Mapping[str, str] | None = None
) -> None:
print("increment", name, value, labels)
def observe(
self, name: str, value: float, *, labels: Mapping[str, str] | None = None
) -> None:
print("observe", name, value, labels)
def set_gauge(
self, name: str, value: float, *, labels: Mapping[str, str] | None = None
) -> None:
print("gauge", name, value, labels)
trigger = PollTrigger(
name="orders",
source=source,
checkpoint_store=checkpoint_store,
metrics=PrintMetricsCollector(),
)
```
## Key Design Decisions
- **Pseudo trigger** — native C# extension ではなく timer ベース polling ([ADR-001](docs/16-ADR-001-pseudo-trigger-over-native.md))
- **SQLAlchemy-centric** — 全 DB 向け単一 ORM レイヤー ([ADR-002](docs/17-ADR-002-sqlalchemy-centric-adapter.md))
- **Blob checkpoint** — チェックポイント永続化に Azure Blob Storage ([ADR-003](docs/18-ADR-003-blob-checkpoint-mvp.md))
- **At-least-once** — 冪等性を前提にした既定配信保証 ([ADR-004](docs/19-ADR-004-at-least-once-default.md))
- **Unified package** — trigger + binding を 1 パッケージで提供 ([ADR-005](docs/23-ADR-005-unified-package-design.md))
## Duplicate Handling
このパッケージは **at-least-once** 配信を提供します。プロセスクラッシュ、リース遷移、コミット失敗時に重複が発生する可能性があります。ハンドラーは冪等に実装してください。詳細は [Semantics — Duplicate Windows](docs/03-semantics.md#13-duplicate-and-reprocessing-windows) を参照してください。
## Documentation
- Full docs: [yeongseon.github.io/azure-functions-db-python](https://yeongseon.github.io/azure-functions-db-python/)
- Examples: `examples/`
- [Architecture](docs/02-architecture.md)
- [Semantics](docs/03-semantics.md)
- [Python API Spec](docs/04-python-api-spec.md)
- [Adapter SDK](docs/05-adapter-sdk.md)
## Ecosystem
**Azure Functions Python DX Toolkit** の一部:
| Package | Role |
|---------|------|
| [azure-functions-openapi-python](https://github.com/yeongseon/azure-functions-openapi-python) | OpenAPI spec generation and Swagger UI |
| [azure-functions-validation-python](https://github.com/yeongseon/azure-functions-validation-python) | Request/response validation and serialization |
| **azure-functions-db-python** | Database bindings for SQL, PostgreSQL, MySQL, SQLite, and Cosmos DB |
| [azure-functions-langgraph-python](https://github.com/yeongseon/azure-functions-langgraph-python) | LangGraph deployment adapter for Azure Functions |
| [azure-functions-scaffold-python](https://github.com/yeongseon/azure-functions-scaffold-python) | Project scaffolding CLI |
| [azure-functions-logging-python](https://github.com/yeongseon/azure-functions-logging-python) | Structured logging and observability |
| [azure-functions-doctor-python](https://github.com/yeongseon/azure-functions-doctor-python) | Pre-deploy diagnostic CLI |
| [azure-functions-durable-graph-python](https://github.com/yeongseon/azure-functions-durable-graph-python) | Manifest-first graph runtime with Durable Functions *(experimental)* |
| [azure-functions-cookbook-python](https://github.com/yeongseon/azure-functions-cookbook-python) | Recipes and examples |
## Disclaimer
このプロジェクトは独立したコミュニティプロジェクトであり、Microsoft とは提携・承認・保守関係にありません。
Azure および Azure Functions は Microsoft Corporation の商標です。
## License
MIT