Explore the demo

An illustrative demo on a synthetic shop schema. Every solid wire and every key is the output of the real planning engine; the dashed wire is a demo hint for a column the engine left unlinked. 7 tables, 6 with keys, 6 relationships

Illustrative demo
Tab moves between tables and wires · Enter selects · Esc clears

Select a table or a wire. The explanation appears below.

Checked against the data computed on the synthetic demo data

What validate_plan answers for this plan: is every key unique and free of NULLs, and does every reference find its target? The counts below come from the same checks, run over the synthetic rows of fabric_backend.seed in an in-memory database; on a real source they run as small counting queries against the SQL analytics endpoint. Also as JSON at /demo/validation.json.

6 of 6 keys unique, 6 of 6 relationships hold without orphans

Keys

TableKey (rule)RowsDistinctNULLsVerdict
customerscustomer_id K210100unique in all 10 rows
categoriesid K2330unique in all 3 rows
productsproduct_id K2880unique in all 8 rows
addressesaddress_id K217170unique in all 17 rows
ordersorder_id K260600unique in all 60 rows
order_itemsorder_id + line_no K11341340unique in all 134 rows

Relationships

Reference (rule)Rows with a valueOrphansVerdict
products.category_id → categories.id R180holds for all 8 rows with a value
addresses.customer_id → customers.customer_id R1170holds for all 17 rows with a value
orders.customer_id → customers.customer_id R1600holds for all 60 rows with a value
order_items.order_id → orders.order_id R11340holds for all 134 rows with a value
order_items.product_id → products.product_id R11340holds for all 134 rows with a value
audit_log.customer_id → customers.customer_id R1400holds for all 40 rows with a value

Composite keys the plan suggests before any override

  • none
The plan as text

The same plan the graph draws, as plain text. Generated by the engine on the synthetic shop schema; keys were given for order_items only.

7 tables, 6 with keys, 6 relationships
no key (query only; can reference others, cannot be referenced): audit_log

Tables and keys

  • customers: key customer_id by rule K2 (a column named id, <table>_id, <table>id, <singular>_id, <singular>id, <table>_key, <table>_code, <table>_nr, <table>_no, or an abbreviation of the table name (four letters or more) with one of those suffixes); columns customer_id, name, country
  • categories: key id by rule K2 (a column named id, <table>_id, <table>id, <singular>_id, <singular>id, <table>_key, <table>_code, <table>_nr, <table>_no, or an abbreviation of the table name (four letters or more) with one of those suffixes); columns id, name
  • products: key product_id by rule K2 (a column named id, <table>_id, <table>id, <singular>_id, <singular>id, <table>_key, <table>_code, <table>_nr, <table>_no, or an abbreviation of the table name (four letters or more) with one of those suffixes); columns product_id, name, category_id
  • addresses: key address_id by rule K2 (a column named id, <table>_id, <table>id, <singular>_id, <singular>id, <table>_key, <table>_code, <table>_nr, <table>_no, or an abbreviation of the table name (four letters or more) with one of those suffixes); columns address_id, customer_id, city
  • orders: key order_id by rule K2 (a column named id, <table>_id, <table>id, <singular>_id, <singular>id, <table>_key, <table>_code, <table>_nr, <table>_no, or an abbreviation of the table name (four letters or more) with one of those suffixes); columns order_id, customer_id, order_date, ship_to_id
  • order_items: key order_id + line_no by rule K1 (keys override from the caller); columns order_id, line_no, product_id, quantity
  • audit_log: no key, rule K3 (nothing — the table gets no key; it can be queried but not by pk, and nothing can point at it); columns event, customer_id, happened_at

Relationships

  • products.category_id → categories.id by rule R1 (column named <B>_id / <B>id / <singular B>_id / <singular B>id (also _key, _code, _nr, _no) where B has a single key); GraphQL fields category and products
  • addresses.customer_id → customers.customer_id by rule R1 (column named <B>_id / <B>id / <singular B>_id / <singular B>id (also _key, _code, _nr, _no) where B has a single key); GraphQL fields customer and addresses
  • orders.customer_id → customers.customer_id by rule R1 (column named <B>_id / <B>id / <singular B>_id / <singular B>id (also _key, _code, _nr, _no) where B has a single key); GraphQL fields customer and orders
  • order_items.order_id → orders.order_id by rule R1 (column named <B>_id / <B>id / <singular B>_id / <singular B>id (also _key, _code, _nr, _no) where B has a single key); GraphQL fields order and order_items
  • order_items.product_id → products.product_id by rule R1 (column named <B>_id / <B>id / <singular B>_id / <singular B>id (also _key, _code, _nr, _no) where B has a single key); GraphQL fields product and order_items
  • audit_log.customer_id → customers.customer_id by rule R1 (column named <B>_id / <B>id / <singular B>_id / <singular B>id (also _key, _code, _nr, _no) where B has a single key); GraphQL fields customer and audit_log

Left unlinked

  • orders.ship_to_id: no rule matched: not named after another table, and not another table's key name