Skip to content

Commit 98c1459

Browse files
committed
Add initial egraph state to debug data
1 parent 7c9ecd6 commit 98c1459

File tree

2 files changed

+57
-28
lines changed

2 files changed

+57
-28
lines changed

rust/cubesql/cubesql/egraph-debug-template/src/index.js

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { iterations } from './iterations';
1+
import { states } from './states';
22
import { createRoot } from 'react-dom/client';
33
import ELK from 'elkjs/lib/elk.bundled.js';
44
import React, { useCallback, useState, useEffect, useMemo } from 'react';
@@ -14,7 +14,9 @@ import ReactFlow, {
1414

1515
import 'reactflow/dist/style.css';
1616

17-
const data = { nodes: iterations[0].nodes, edges: iterations[0].edges, combos: iterations[0].combos };
17+
// First is initial state
18+
const totalIterations = states.length - 1;
19+
const data = { nodes: states[0].nodes, edges: states[0].edges, combos: states[0].combos };
1820
const sizeByNode = (n) => [60 + n.label.length * 5, 30];
1921
const toGroupNode = (n) => ({ ...n, type: 'group', data: { label: n.label }, position: { x: 0, y: 0 }, width: 200, height: 200 });
2022
const toRegularNode = (n) => ({
@@ -183,20 +185,20 @@ const LayoutFlow = () => {
183185
const [{ preNodes, preEdges }, setPreNodesEdges] = useState({ preNodes: initialNodes, preEdges: initialEdges });
184186
const [nodes, setNodes, onNodesChange] = useNodesState(JSON.parse(JSON.stringify(initialNodes)));
185187
const [edges, setEdges, onEdgesChange] = useEdgesState(JSON.parse(JSON.stringify(initialEdges)));
186-
const [iteration, setIteration] = useState(0);
188+
const [stateIdx, setStateIdx] = useState(0);
187189
const { fitView } = useReactFlow();
188190

189191
const [navigateTo, setNavigateTo] = useState('');
190192
const [navHistory, setNavHistory] = useState([]);
191193
const [showOnlySelected, setShowOnlySelected] = useState(false);
192194

193-
const prevIter = () => {
194-
if (iteration === 0) {
195+
const prevState = () => {
196+
if (stateIdx === 0) {
195197
return;
196198
}
197199
let newNodes = preNodes;
198200
let newEdges = preEdges;
199-
const toRemove = iterations[iteration];
201+
const toRemove = states[stateIdx];
200202
let toRemoveNodeIds = toRemove.nodes.concat(toRemove.combos).map((n) => n.id);
201203
let toRemoveEdgeIds = toRemove.edges.map((n) => toEdge(n).id);
202204
newNodes = newNodes.filter((n) => !toRemoveNodeIds.includes(n.id));
@@ -205,21 +207,21 @@ const LayoutFlow = () => {
205207
newNodes = newNodes.concat((toRemove.removedNodes || []).map(toRegularNode));
206208
const edgeMap = (toRemove.removedEdges || []).map(toEdge).reduce((acc, val) => ({ ...acc, [val.id]: val }), {});
207209
newEdges = newEdges.concat(Object.keys(edgeMap).map(key => edgeMap[key]));
208-
const toHighlight = iterations[iteration - 1];
210+
const toHighlight = states[stateIdx - 1];
209211
const toHighlightNodeIds = toHighlight.nodes.concat(toHighlight.combos).map((n) => n.id);
210212
newNodes = newNodes.map(n => ({...n, style: { ...n.style, backgroundColor: toHighlightNodeIds.includes(n.id) ? highlightColor : undefined }}));
211-
setIteration(iteration - 1);
213+
setStateIdx(stateIdx - 1);
212214
setPreNodesEdges({ preNodes: newNodes, preEdges: newEdges });
213215
}
214216

215-
const nextIter = () => {
216-
if (iteration === iterations.length - 1) {
217+
const nextState = () => {
218+
if (stateIdx === states.length - 1) {
217219
return;
218220
}
219221
let newNodes = preNodes;
220222
let newEdges = preEdges;
221-
setIteration(iteration + 1);
222-
const toAdd = iterations[iteration + 1];
223+
setStateIdx(stateIdx + 1);
224+
const toAdd = states[stateIdx + 1];
223225
let toRemoveNodeIds = toAdd.removedNodes.concat(toAdd.removedCombos).map((n) => n.id);
224226
let toRemoveEdgeIds = toAdd.removedEdges.map((n) => toEdge(n).id);
225227
newNodes = newNodes.filter((n) => !toRemoveNodeIds.includes(n.id));
@@ -248,7 +250,9 @@ const LayoutFlow = () => {
248250

249251
useEffect(() => {
250252
layout({}, JSON.parse(JSON.stringify(preNodes)), JSON.parse(JSON.stringify(preEdges)), setNodes, setEdges, fitView, navHistory, showOnlySelected);
251-
}, [preNodes, setNodes, setEdges, iteration, showOnlySelected, navHistory]);
253+
}, [preNodes, setNodes, setEdges, stateIdx, showOnlySelected, navHistory]);
254+
255+
const stateLabel = stateIdx === 0 ? "Initial state" : `After iteration ${stateIdx} / ${totalIterations}`;
252256

253257
return (
254258
<ReactFlow
@@ -265,9 +269,9 @@ const LayoutFlow = () => {
265269
<div>
266270
<input type="checkbox" checked={showOnlySelected} onChange={() => setShowOnlySelected(!showOnlySelected)}/>
267271
<span style={{ paddingLeft: 4, paddingRight: 4 }}>Show only selected</span>
268-
<button onClick={() => prevIter()}>Prev Iter</button>
269-
<button onClick={() => nextIter()}>Next Iter</button>
270-
<span style={{ paddingLeft: 4, paddingRight: 4 }}>Iteration #{iteration + 1} / {iterations.length}</span>
272+
<button onClick={() => prevState()}>Prev State</button>
273+
<button onClick={() => nextState()}>Next State</button>
274+
<span style={{ paddingLeft: 4, paddingRight: 4 }}>{stateLabel}</span>
271275
<input placeholder="Search Class ID" onChange={(e) => setNavigateTo(e.target.value)} value={navigateTo}></input>
272276
<button onClick={() => {
273277
navigate(navigateTo);
@@ -284,7 +288,7 @@ const LayoutFlow = () => {
284288
}
285289
</div>
286290
<div>
287-
<span>{iterations[iteration].appliedRules.join(', ')}</span>
291+
<span>{states[stateIdx].appliedRules.join(', ')}</span>
288292
</div>
289293
</Panel>
290294
</ReactFlow>

rust/cubesql/cubesql/src/compile/rewrite/rewriter.rs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,11 @@ impl IterationData<LogicalPlanLanguage, LogicalPlanAnalysis> for IterInfo {
185185
}
186186
}
187187

188-
fn write_debug_iterations(runner: &CubeRunner, stage: &str) -> Result<(), CubeError> {
188+
fn write_debug_states(
189+
init_debug_data: &DebugData,
190+
runner: &CubeRunner,
191+
stage: &str,
192+
) -> Result<(), CubeError> {
189193
let dir = format!("egraph-debug-{}", stage);
190194
let _ = fs::create_dir_all(dir.clone());
191195
let _ = fs::create_dir_all(format!("{}/public", dir));
@@ -203,11 +207,21 @@ fn write_debug_iterations(runner: &CubeRunner, stage: &str) -> Result<(), CubeEr
203207
format!("{}/src/index.js", dir),
204208
)?;
205209

206-
let mut iterations = Vec::new();
210+
let mut states = Vec::new();
207211
let mut last_debug_data: Option<DebugData> = None;
208-
for i in &runner.iterations {
209-
let debug_data_clone = i.data.debug_info.as_ref().unwrap().debug_data.clone();
210-
let mut debug_data = i.data.debug_info.as_ref().unwrap().debug_data.clone();
212+
213+
let states_data =
214+
std::iter::once((init_debug_data, None)).chain(runner.iterations.iter().map(|i| {
215+
(
216+
&i.data.debug_info.as_ref().unwrap().debug_data,
217+
Some(&i.applied),
218+
)
219+
}));
220+
221+
for (debug_data, applied) in states_data {
222+
let mut debug_data = debug_data.clone();
223+
let debug_data_clone = debug_data.clone();
224+
211225
if let Some(last) = last_debug_data {
212226
debug_data
213227
.nodes
@@ -238,15 +252,19 @@ fn write_debug_iterations(runner: &CubeRunner, stage: &str) -> Result<(), CubeEr
238252
.removed_combos
239253
.retain(|n| !debug_data_clone.combos.iter().any(|ln| ln.id == n.id));
240254
}
241-
debug_data.applied_rules = Some(i.applied.iter().map(|s| format!("{:?}", s)).collect());
242-
iterations.push(debug_data);
255+
debug_data.applied_rules = Some(
256+
applied
257+
.map(|applied| applied.iter().map(|s| format!("{:?}", s)).collect())
258+
.unwrap_or(vec![]),
259+
);
260+
states.push(debug_data);
243261
last_debug_data = Some(debug_data_clone);
244262
}
245263
fs::write(
246-
format!("{}/src/iterations.js", dir),
264+
format!("{}/src/states.js", dir),
247265
&format!(
248-
"export const iterations = {};",
249-
serde_json::to_string_pretty(&iterations)?
266+
"export const states = {};",
267+
serde_json::to_string_pretty(&states)?
250268
),
251269
)?;
252270

@@ -463,6 +481,10 @@ impl Rewriter {
463481
rules: Arc<Vec<CubeRewrite>>,
464482
stage: &str,
465483
) -> Result<(CubeRunner, Vec<QtraceEgraphIteration>), CubeError> {
484+
// Capture initial egraph state, before rewrites
485+
let init_debug_data =
486+
IterInfo::egraph_debug_enabled().then(|| IterDebugInfo::prepare_debug_data(&egraph));
487+
466488
let runner = Self::rewrite_runner(cube_context.clone(), egraph);
467489
let runner = runner.run(rules.iter());
468490
if !IterInfo::egraph_debug_enabled() {
@@ -482,7 +504,10 @@ impl Rewriter {
482504
}
483505
};
484506
if IterInfo::egraph_debug_enabled() {
485-
write_debug_iterations(&runner, stage)?;
507+
// `unwrap()` should be ok here
508+
// When IterInfo::egraph_debug_enabled() init_debug_data should be filled
509+
let init_debug_data = init_debug_data.unwrap();
510+
write_debug_states(&init_debug_data, &runner, stage)?;
486511
}
487512
if let Some(stop_reason) = stop_reason {
488513
return Err(CubeError::user(format!(

0 commit comments

Comments
 (0)