Skip to main content

sochdb_query/executor/
explain.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3//! EXPLAIN operator — generates query plan description as rows.
4
5use crate::soch_ql::SochValue;
6use super::node::PlanNode;
7use super::types::{Row, Schema, ColumnMeta};
8use sochdb_core::Result;
9
10/// Explain operator: returns the plan description as text rows.
11pub struct ExplainNode {
12    schema: Schema,
13    lines: Vec<String>,
14    pos: usize,
15}
16
17impl ExplainNode {
18    pub fn new(plan_text: String) -> Self {
19        let lines: Vec<String> = plan_text.lines().map(|l| l.to_string()).collect();
20        Self {
21            schema: Schema::new(vec![ColumnMeta::new("QUERY PLAN".to_string())]),
22            lines,
23            pos: 0,
24        }
25    }
26}
27
28impl PlanNode for ExplainNode {
29    fn schema(&self) -> &Schema {
30        &self.schema
31    }
32
33    fn next(&mut self) -> Result<Option<Row>> {
34        if self.pos < self.lines.len() {
35            let line = self.lines[self.pos].clone();
36            self.pos += 1;
37            Ok(Some(vec![SochValue::Text(line)]))
38        } else {
39            Ok(None)
40        }
41    }
42
43    fn reset(&mut self) -> Result<()> {
44        self.pos = 0;
45        Ok(())
46    }
47}
48
49/// Generate a human-readable plan description from an operator tree.
50pub fn describe_plan(node: &dyn PlanNode, _depth: usize) -> String {
51    // We'll use the schema to identify operator type
52    let schema = node.schema();
53    let cols = schema.column_names().join(", ");
54    format!("Operator [columns={}]", cols)
55}
56
57/// Generate EXPLAIN output for a planned query.
58///
59/// This creates a structured plan description showing:
60/// - Operator type
61/// - Estimated cost/rows (if available)
62/// - Column list
63pub fn format_plan_tree(description: &str) -> String {
64    description.to_string()
65}