Skip to content

[WIP] feat: Automated SQLAlchemy integration#1321

Open
KarolJagodzinski wants to merge 1 commit intomainfrom
orm_shortcut
Open

[WIP] feat: Automated SQLAlchemy integration#1321
KarolJagodzinski wants to merge 1 commit intomainfrom
orm_shortcut

Conversation

@KarolJagodzinski
Copy link
Copy Markdown
Collaborator

@KarolJagodzinski KarolJagodzinski commented May 6, 2026

Add experimental SQLAlchemy integration: ariadne.contrib.sqlalchemy

Introduces an opt-in module (pip install ariadne[sqlalchemy]) that wires SQLAlchemy 2.0 models into Ariadne with two cooperating execution paths:

  • Auto eager-load path — SQLAlchemyQueryType walks the GraphQL selection set ahead of time and builds one optimised statement per top-level field, applying selectinload / joinedload / load_only based on what the client
    actually asked for.
  • DataLoader fallback path — SQLAlchemyObjectType resolves relationships on objects that weren't prepared by the eager-load path (e.g. results from a manual @field resolver) through a per-request SQLAlchemyDataLoader,
    batching lookups to avoid N+1.

What's included

  • SQLAlchemyQueryType — root-field auto-resolver; reads the session from info.context["session"] via an overridable get_session_from_context.
  • SQLAlchemyObjectType — relationship auto-binding with per-type aliases, strategies, and max_depth (default 3) options.
  • SQLAlchemyDataLoaderExtension — manages a per-request LoaderRegistry; configurable session_key / registry_key, or you can populate the registry yourself in get_context.
  • Two runnable examples in examples/sqlalchemy/:
    • 01_auto_eager_load.py — Quick Start with in-memory SQLite and seed data.
    • 02_dataloader_fallback.py — manual resolver scenario showing the three-statement batched fallback (run with echo=True to verify).
  • Full guide at docs/07-Contrib/02-sqlalchemy.md.

Status

Experimental. API may change based on feedback before it's locked in.

Summary by CodeRabbit

  • New Features

    • Automated SQLAlchemy 2.0 integration: auto-resolvers, eager-loading and DataLoader batching to prevent N+1 queries; new QueryType/MutationType and per-request loader extension.
  • Documentation

    • Comprehensive SQLAlchemy guide, added "Running Examples" section, README feature note, and updated final checklist.
  • Examples

    • Multiple runnable examples demonstrating sync/async integration and startup/run instructions.
  • Tests

    • Extensive test suite covering loaders, object/query behavior, eager-loading utilities and registry scenarios.
  • Chores

    • Added optional SQLAlchemy dependency and new changelog entry.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

Adds a new SQLAlchemy 2.0 contrib to Ariadne: guarded exports, dataloader + registry, request extension, SQLAlchemy-backed ObjectType and QueryType, auto-eager-load utilities, examples, docs, packaging extras, and extensive tests; plus small unrelated internal refinements and docs/checklist tweaks.

Changes

SQLAlchemy 2.0 Integration for Ariadne

Layer / File(s) Summary
Type Definitions & Protocols
ariadne/contrib/sqlalchemy/types.py
Adds LoadStrategy Protocol for typing load-option callables (no runtime SQLAlchemy dependency).
Data Loading Infrastructure
ariadne/contrib/sqlalchemy/dataloaders.py
Adds SQLAlchemyDataLoader (composite keys, many‑to‑many, sync/async session support, batch_load_fn) and LoaderRegistry (per-session/request loader cache).
Request Lifecycle / Extension
ariadne/contrib/sqlalchemy/extension.py
Adds SQLAlchemyDataLoaderExtension that initializes a per-request LoaderRegistry from a session found in context and stores it under a configurable key.
Auto Eager Loading
ariadne/contrib/sqlalchemy/utils.py
Adds auto_eager_load() plus _build_options/_resolve_load_option to derive and apply SQLAlchemy load options from GraphQL selections (depth checks, aliases, strategies).
SQLAlchemy Object Binding
ariadne/contrib/sqlalchemy/objects.py
Adds SQLAlchemyObjectType that auto-binds resolvers for aliased columns and relationships, uses LoaderRegistry from context, and exposes registry lookup helper.
SQLAlchemy Query Root
ariadne/contrib/sqlalchemy/query.py
Adds SQLAlchemyQueryType to auto-wire root Query field resolvers for registered SQLAlchemyObjectTypes; includes session extraction, base-query hook, eager-loading, filtering, and sync/async execution paths.
Module Exports
ariadne/contrib/sqlalchemy/__init__.py
Adds guarded imports and updates __all__ to expose the new SQLAlchemy APIs and provide a helpful ImportError when extras are missing.
Examples
examples/sqlalchemy/01_auto_eager_load.py, examples/sqlalchemy/02_dataloader_fallback.py
Adds two runnable Starlette examples demonstrating auto-eager-load and DataLoader-fallback (in-memory SQLite, models, middleware, uvicorn run hints).
Docs & Guides
docs/07-Contrib/02-sqlalchemy.md, docs/01-Docs/13-dataloaders.md, docs/01-Docs/17-bindables.md, README.md, AGENTS.md
Adds full SQLAlchemy contrib documentation and quick-start; updates dataloader docs (async-only note), registers built-in bindables, adds README feature bullet and AGENTS run examples & checklist edits.
Tests & Fixtures
tests/sqlalchemy/*
Adds fixtures and extensive tests covering loader init, query generation, sync/async batch paths, composite keys, LoaderRegistry, object-type binding, resolver behavior, and QueryType wiring.
Packaging / Config
pyproject.toml
Adds optional sqlalchemy extras (sqlalchemy>=2.0.0, aiodataloader>=0.2.0) and Hatch feature flags for types/tests including SQLAlchemy.
Minor Refactors
ariadne/objects.py, ariadne/schema_visitor.py, ariadne/contrib/tracing/utils.py
objects.py: set_alias accepts callables and adds QueryType/MutationType convenience classes. schema_visitor.py and tracing util use simpler internal traversals; no public API changes otherwise.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant GraphQL as GraphQL Server
    participant Eager as auto_eager_load
    participant SQLA as SQLAlchemy
    participant DB

    Client->>GraphQL: send GraphQL query
    GraphQL->>Eager: analyze selection set
    Eager->>SQLA: apply load strategies (selectinload/joinedload)
    SQLA->>DB: execute optimized queries
    DB-->>SQLA: return rows
    SQLA-->>Eager: loaded related objects
    Eager-->>GraphQL: resolved nested fields
    GraphQL-->>Client: return response
Loading
sequenceDiagram
    participant Client
    participant GraphQL as GraphQL Server
    participant Resolver
    participant Registry as Loader Registry
    participant DataLoader
    participant SQLA as SQLAlchemy
    participant DB

    Client->>GraphQL: request field with relations
    GraphQL->>Resolver: invoke field resolver
    Resolver->>Registry: obtain DataLoader for relation
    Registry->>DataLoader: schedule batch load
    DataLoader->>SQLA: execute WHERE IN / multi-col IN
    SQLA->>DB: run query
    DB-->>SQLA: rows
    SQLA-->>DataLoader: fetched rows
    DataLoader-->>Resolver: grouped results
    Resolver-->>GraphQL: return resolved value
    GraphQL-->>Client: response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Suggested reviewers

  • DamianCzajkowski

"🐰 I hopped through code and stitched the seams,
Loaders gather friends in batched-filled dreams,
Eager fields lean in, no N+1 screams,
Models and schema dance in bright moonbeams,
Hop, run the examples — delight, it seems!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.97% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[WIP] feat: Automated SQLAlchemy integration' clearly summarizes the primary change—adding automated SQLAlchemy integration to Ariadne—and is specific about the feature being introduced.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch orm_shortcut

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 6, 2026

Codecov Report

❌ Patch coverage is 99.20000% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.45%. Comparing base (ca42731) to head (6f2b5fc).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
ariadne/contrib/sqlalchemy/objects.py 95.00% 3 Missing ⚠️
ariadne/contrib/sqlalchemy/__init__.py 80.00% 2 Missing ⚠️
tests/sqlalchemy/test_utils.py 98.97% 2 Missing ⚠️
ariadne/contrib/sqlalchemy/query.py 98.14% 1 Missing ⚠️
ariadne/objects.py 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1321      +/-   ##
==========================================
+ Coverage   97.25%   97.45%   +0.20%     
==========================================
  Files         127      140      +13     
  Lines        9214    10331    +1117     
==========================================
+ Hits         8961    10068    +1107     
- Misses        253      263      +10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@KarolJagodzinski KarolJagodzinski force-pushed the orm_shortcut branch 5 times, most recently from fcb998f to 0d3908d Compare May 6, 2026 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant