GraphSQL
An experimental SQLAlchemy dialect that lets SQL-first tools query a GraphQL API and receive tabular results.
- Status
- Prototype
- Source
- Public
- Evidence
- Public source · Documentation · Screenshots · Reproducible harness · Prototype
- Stack
- Python · SQLAlchemy · GraphQL · DuckDB · Apache Superset
- Period
- 2025
01
Overview
What this is
GraphSQL is an experimental SQLAlchemy dialect and DB-API bridge that lets SQL-first tools query a GraphQL API and receive tabular results. The prototype introspects a schema, maps SQL selections and filters into GraphQL, fetches nested JSON, flattens it into rows, and applies the remaining SQL work through DuckDB.
The goal was not to pretend GraphQL is a relational database. It was to test how far a practical bridge could go and whether an existing tool such as Apache Superset could sit on top of it. The result proved the route on a bounded subset, then stopped before the project disguised a partial query planner as a general-purpose database driver.
Built as a technical study for teams or analysts whose tooling speaks SQL or SQLAlchemy while the available data source exposes GraphQL.
The problem
BI tools expect tables, columns, cursors, and SQL semantics; GraphQL exposes typed fields and nested selection sets. Connecting them requires more than forwarding a query: the bridge must infer mappings, translate supported operations, and state clearly where SQL behavior does not exist.
What I built and owned
I designed the mapping strategy, built the DB-API and SQLAlchemy surfaces, implemented schema introspection, SQL-to-GraphQL translation, HTTP execution, JSON flattening, and DuckDB post-processing, and validated the prototype through Superset examples and tests.
02
Detail
How it works
The bridge pipeline
A SQL client enters through a normal DB-API or SQLAlchemy connection. GraphSQL parses the supported SQL subset, uses GraphQL introspection and mapping rules to produce a typed query, calls the endpoint, and receives nested JSON. The response is flattened into rows and columns, then DuckDB applies the tabular operations that are better handled after retrieval.
That division is what made the proof useful: it reused the semantics each side already understands instead of forcing every SQL operation into a GraphQL request or asking a BI tool to understand nested response objects.
Diagram · select to open the full view
Text description of this diagram
Apache Superset or another SQLAlchemy client connects through the GraphSQL DB-API. GraphSQL parses supported SELECT statements, projections, filters, and nested field mappings. It uses GraphQL schema introspection to build a typed request and sends that request over HTTP.
The GraphQL endpoint returns nested JSON. GraphSQL normalizes the records into rows and columns, uses DuckDB for remaining tabular post-processing, and returns DB-API result metadata to the SQL client. The pipeline demonstrates a bounded compatibility layer; it does not claim arbitrary SQL and arbitrary GraphQL are equivalent.
2 images · select one to open the full view
What the proof covered
- 01
Schema discovery
GraphQL introspection is cached and mapped into the tables, columns, and relationships expected by a SQL-facing client.
- 02
Query translation
A supported SQL subset becomes GraphQL selections, nested fields, filters, and variables.
- 03
Tabularisation
Nested JSON becomes rows and columns, with DuckDB available for post-retrieval SQL behavior.
- 04
Tool integration
The DB-API and SQLAlchemy surfaces were sufficient to exercise the bridge through Apache Superset.
GraphSQL supports a deliberately bounded subset and is installed from source; there is no PyPI release. General joins, ordering, interface-type handling, and full SQL equivalence were not completed. The useful result is the proven bridge and the boundary it exposed—not a production-ready universal driver.
03
Result
What came of it
04
Links
Where to look
Something similar in mind?
If this is close to a problem you have, the fastest thing is usually a short conversation about what you are actually trying to change.
Discuss a project