From 07dab90bd603def0ef251caa28aba7f14c1a7bf8 Mon Sep 17 00:00:00 2001 From: Hassan Abedi Date: Fri, 5 Jun 2026 13:05:27 +0200 Subject: [PATCH] WIP --- .../plan-runner/docs/diagrams/make_figures.sh | 14 ++ crates/plan-runner/docs/diagrams/workflow.dot | 136 ++++++++++++ crates/plan-runner/docs/diagrams/workflow.svg | 202 ++++++++++++++++++ 3 files changed, 352 insertions(+) create mode 100755 crates/plan-runner/docs/diagrams/make_figures.sh create mode 100644 crates/plan-runner/docs/diagrams/workflow.dot create mode 100644 crates/plan-runner/docs/diagrams/workflow.svg diff --git a/crates/plan-runner/docs/diagrams/make_figures.sh b/crates/plan-runner/docs/diagrams/make_figures.sh new file mode 100755 index 0000000..6d30150 --- /dev/null +++ b/crates/plan-runner/docs/diagrams/make_figures.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# You need to have Graphviz installed to run this script +# On Debian-based OSes, you can install it using: sudo apt-get install graphviz + +# Directory containing .dot files. Defaults to the script's own directory so the +# script works regardless of the caller's working directory. +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +ASSET_DIR=${1:-"${SCRIPT_DIR}"} + +# Make figures from .dot files +for f in "${ASSET_DIR}"/*.dot; do + dot -Tsvg "$f" -o "${f%.dot}.svg" +done diff --git a/crates/plan-runner/docs/diagrams/workflow.dot b/crates/plan-runner/docs/diagrams/workflow.dot new file mode 100644 index 0000000..831c94b --- /dev/null +++ b/crates/plan-runner/docs/diagrams/workflow.dot @@ -0,0 +1,136 @@ +digraph PlanRunnerWorkflow { +fontname = "Helvetica,Arial,sans-serif" +layout = dot +rankdir = LR +ranksep = 0.9; +nodesep = 0.7; +splines = true; +compound = true; +bgcolor = "white" + +node [ +fontname = "Helvetica,Arial,sans-serif", +shape = box, +style = "filled,rounded", +color = "#555555", +fillcolor = "white", +penwidth = 1.5 +] +edge [ +fontname = "Helvetica,Arial,sans-serif", +color = "#333333", +fontsize = 9, +fontcolor = "#555555", +labeldistance = 2.0, +penwidth = 1.2 +] + +subgraph cluster_input { +label = "Input" +style = "dashed" +color = "#888888" +fontcolor = "#555555" +margin = 18 +json_plan [label = < + + + + + +
JSON Plan
• schema: name -> arity
• facts: name -> rows
• query: { root, nodes }
• expected_bindings (optional oracle)
>, fillcolor = "#E8F4FD", color = "#2196F3"] +} + +subgraph cluster_parse { +label = "Parse" +style = "dashed" +color = "#9C27B0" +fontcolor = "#7B1FA2" +margin = 14 +parse_plan [label = "parse_plan(json)\n-> Plan", fillcolor = "#F3E5F5", color = "#9C27B0"] +} + +subgraph cluster_load { +label = "Load Tables (--backend selects the path)" +style = "dashed" +color = "#4CAF50" +fontcolor = "#388E3C" +margin = 14 +build_pure [label = < + + + +
build_tables(plan)
--backend memory
direct from plan.facts
>, fillcolor = "#E8F5E9", color = "#4CAF50"] +build_storage [label = < + + + + + +
build_tables_via_storage<S: Storage>
--backend memory-storage
--backend lmdb / redb / fjall
--backend sqlite / geomerge
create_relation → tx.insert → scan_as_table
>, fillcolor = "#E8F5E9", color = "#4CAF50"] +tables_map [label = < + + +
HashMap<String, Table>
positional rows per relation
>, fillcolor = "#E8F4FD", color = "#2196F3"] +} + +subgraph cluster_execute { +label = "Execute (walk node DAG in id order)" +style = "dashed" +color = "#FF9800" +fontcolor = "#F57C00" +margin = 14 +execute_node [label = < + + + + + + +
execute(tables, query)
Action::Scan → scan_atom
Action::Join Left → semijoin(l, r)
Action::Join Right → semijoin(r, l)
Action::Join Natural → natural_join(l, r)
cache per-node Relation; return root
>, fillcolor = "#FFF3E0", color = "#FF9800"] +relation_out [label = < + + + +
Relation
columns: variables + wildcards
rows: bindings
>, fillcolor = "#FFF3E0", color = "#FF9800"] +} + +subgraph cluster_verify { +label = "Verify (when expected_bindings is present)" +style = "dashed" +color = "#9C27B0" +fontcolor = "#7B1FA2" +margin = 14 +verify_node [label = < + + + +
verify(plan, relation)
project to expected.columns
multiset compare against expected.rows
>, fillcolor = "#F3E5F5", color = "#9C27B0"] +} + +subgraph cluster_output { +label = "Output" +style = "dashed" +color = "#888888" +fontcolor = "#555555" +margin = 18 +stdout_json [label = < + + +
stdout JSON
{ columns, rows }
>, fillcolor = "#ECEFF1", color = "#607D8B"] +oracle_pass [label = "Ok(true) / VerifyError\n(used by tests/examples.rs)", fillcolor = "#ECEFF1", color = "#607D8B"] +} + +// Pipeline edges +json_plan -> parse_plan [color = "#2196F3"] +parse_plan -> build_pure [label = "Backend::Memory", color = "#9C27B0"] +parse_plan -> build_storage [label = "Backend::*Storage", color = "#9C27B0"] +build_pure -> tables_map [color = "#4CAF50"] +build_storage -> tables_map [color = "#4CAF50"] +tables_map -> execute_node [color = "#2196F3"] +parse_plan -> execute_node [style = "dashed", label = "plan.query", color = "#9C27B0"] +execute_node -> relation_out [color = "#FF9800"] +relation_out -> stdout_json [color = "#607D8B"] +relation_out -> verify_node [style = "dashed", color = "#FF9800"] +parse_plan -> verify_node [style = "dashed", label = "plan.expected_bindings", color = "#9C27B0"] +verify_node -> oracle_pass [color = "#9C27B0"] +} diff --git a/crates/plan-runner/docs/diagrams/workflow.svg b/crates/plan-runner/docs/diagrams/workflow.svg new file mode 100644 index 0000000..11a0ee4 --- /dev/null +++ b/crates/plan-runner/docs/diagrams/workflow.svg @@ -0,0 +1,202 @@ + + + + + + +PlanRunnerWorkflow + + +cluster_input + +Input + + +cluster_parse + +Parse + + +cluster_load + +Load Tables  (--backend selects the path) + + +cluster_execute + +Execute  (walk node DAG in id order) + + +cluster_verify + +Verify  (when expected_bindings is present) + + +cluster_output + +Output + + + +json_plan + +JSON Plan +• schema: name -> arity +• facts: name -> rows +• query: { root, nodes } +• expected_bindings (optional oracle) + + + +parse_plan + +parse_plan(json) +-> Plan + + + +json_plan->parse_plan + + + + + +build_pure + +build_tables(plan) +--backend memory +direct from plan.facts + + + +parse_plan->build_pure + + +Backend::Memory + + + +build_storage + +build_tables_via_storage<S: Storage> +--backend memory-storage +--backend lmdb / redb / fjall +--backend sqlite / geomerge +create_relation → tx.insert → scan_as_table + + + +parse_plan->build_storage + + +Backend::*Storage + + + +execute_node + +execute(tables, query) +Action::Scan  → scan_atom +Action::Join Left  → semijoin(l, r) +Action::Join Right → semijoin(r, l) +Action::Join Natural → natural_join(l, r) +cache per-node Relation; return root + + + +parse_plan->execute_node + + +plan.query + + + +verify_node + +verify(plan, relation) +project to expected.columns +multiset compare against expected.rows + + + +parse_plan->verify_node + + +plan.expected_bindings + + + +tables_map + +HashMap<String, Table> +positional rows per relation + + + +build_pure->tables_map + + + + + +build_storage->tables_map + + + + + +tables_map->execute_node + + + + + +relation_out + +Relation +columns: variables + wildcards +rows: bindings + + + +execute_node->relation_out + + + + + +relation_out->verify_node + + + + + +stdout_json + +stdout JSON +{ columns, rows } + + + +relation_out->stdout_json + + + + + +oracle_pass + +Ok(true)  /  VerifyError +(used by tests/examples.rs) + + + +verify_node->oracle_pass + + + + +