digraph QueryOpsHandPlan { 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_inputs { label = "Inputs (positional tables)" style = "dashed" color = "#888888" fontcolor = "#555555" margin = 18 edge_table [label = <
Table: edge
• arity 2
• rows: (src, dst)
>, fillcolor = "#E8F4FD", color = "#2196F3"] labeled_table [label = <
Table: labeled
• arity 1
• rows: (node)
>, fillcolor = "#E8F4FD", color = "#2196F3"] } subgraph cluster_atoms { label = "Atom Scans (scan_atom: Table × AtomPattern → Relation)" style = "dashed" color = "#9C27B0" fontcolor = "#7B1FA2" margin = 14 self_loops [label = <
self_loops
pattern: [Var X, Var X]
filter: row[0] == row[1]
cols: [X]
>, fillcolor = "#F3E5F5", color = "#9C27B0"] edge_xy [label = <
edge_xy
pattern: [Var X, Var Y]
filter: none
cols: [X, Y]
>, fillcolor = "#F3E5F5", color = "#9C27B0"] labeled_x [label = <
labeled_x
pattern: [Var X]
cols: [X]
>, fillcolor = "#F3E5F5", color = "#9C27B0"] labeled_y [label = <
labeled_y
pattern: [Var Y]
cols: [Y]
>, fillcolor = "#F3E5F5", color = "#9C27B0"] } subgraph cluster_joins { label = "Joins (shared cols = matching column names)" style = "dashed" color = "#4CAF50" fontcolor = "#388E3C" margin = 14 q1 [label = <
Q1: semijoin
edge(X, X), labeled(X)
keep left rows whose [X] is in right
cols: [X]
>, fillcolor = "#E8F5E9", color = "#4CAF50"] q2 [label = <
Q2: natural_join
edge(X, Y), labeled(Y)
emit left ++ (right \ shared) per match
cols: [X, Y]
>, fillcolor = "#E8F5E9", color = "#4CAF50"] } subgraph cluster_outputs { label = "Outputs (binding relations)" style = "dashed" color = "#888888" fontcolor = "#555555" margin = 18 q1_out [label = <
Q1 result
labeled self-loops
cols: [X]
>, fillcolor = "#ECEFF1", color = "#607D8B"] q2_out [label = <
Q2 result
edges into labeled nodes
cols: [X, Y]
>, fillcolor = "#ECEFF1", color = "#607D8B"] } // Atom scans consume tables edge_table -> self_loops [color = "#2196F3"] edge_table -> edge_xy [color = "#2196F3"] labeled_table -> labeled_x [color = "#2196F3"] labeled_table -> labeled_y [color = "#2196F3"] // Q1: edge(X, X), labeled(X) -> semijoin self_loops -> q1 [label = "left", color = "#9C27B0"] labeled_x -> q1 [label = "right", color = "#9C27B0"] // Q2: edge(X, Y), labeled(Y) -> natural_join edge_xy -> q2 [label = "left", color = "#9C27B0"] labeled_y -> q2 [label = "right", color = "#9C27B0"] // Final outputs q1 -> q1_out [color = "#4CAF50"] q2 -> q2_out [color = "#4CAF50"] }