gopgql

One annotated GraphQL SDL document → PostgreSQL 19 SQL/PGQ. Each tab below is a complete, editable scenario: put a schema and a query in on the left, press Generate, and read the generated database schema and the compiled query on the right. It runs entirely in your browser as compiled Go (WebAssembly) — the real sdl+generator+migrate+compiler packages, no server and no JavaScript re-implementation. Nothing is hardcoded: every output is generated from your input.

There is no database here, so query results can't be shown — only the generated SQL. Shaping rows into nested JSON (with parent dedup) happens at execution time against PostgreSQL; it is covered by the godog integration suite, not this browser demo.

loading WebAssembly…

Nesting extends one MATCH chain rather than spawning a second query, so a three-hop traversal is still a single GRAPH_TABLE. Argument values travel as bind parameters ($1, …) and are never interpolated, and every pair of vertex positions that could bind the same row is guarded with <> — PostgreSQL does not enforce edge isomorphism.

Generate

SQL/PGQ has no variable-length paths, so gopgql refuses a selection nested past MaxDepth instead of silently truncating the pattern. The rejection is a typed *compiler.DepthExceededError raised at compile time, so no SQL exists to send. The ceiling is per-Compiler configuration (compiler.WithMaxDepth), not a constant — it defaults to 3. Raise it below to compile this four-hop query, or lower it until a shorter one is refused.

Generate

@column(name:) renames the physical column — and with it the property the graph exposes, which is why the compiled query below projects name while the GraphQL field is still title. @column(type:) overrides the default scalar mapping, @unique makes the database itself reject a duplicate, and @index adds a secondary index with an optional access method — bare, the name is derived from the table and column.

Generate

Selecting two relationships at one level would need comma-separated path patterns in a single MATCH — PG19 parses those but will not execute them. gopgql splits instead: the chain up to the branching level stays one GRAPH_TABLE, each branch becomes its own, and the outer query LEFT JOINs them on the projected ids. Guards that would have spanned the split move to the ON clause, so a branch still cannot walk back to a vertex an ancestor bound.

Generate

A GraphQL interface makes several tables one queryable position. An interface carrying @node(label:) becomes a label its implementors' tables all expose — (v0 IS actor); an interface without it is matched by alternation over their own labels — (v0 IS bot|person). Edit the query to { profiles { name } } to see the second form.

Generate

The initial 0001_init.sql goose migration generated from a schema: the full CREATE DDL, with a -- +goose Down section that is its exact inverse.

Generate

Revise that schema and gopgql folds the initial migration back into a model, diffs it, and emits the delta — ALTER TABLE plus a recreated property graph. The revision below is diffed against the schema in the scenario above, so editing either one regenerates it.

Generate