sql_cli/debug/
dataview_debug.rs

1use crate::data::data_view::{DataView, SortOrder};
2use crate::debug::debug_trace::{DebugSection, DebugSectionBuilder, DebugTrace, Priority};
3use std::sync::Arc;
4
5/// Debug trace implementation for DataView
6pub struct DataViewDebugProvider {
7    dataview: Arc<DataView>,
8}
9
10impl DataViewDebugProvider {
11    pub fn new(dataview: Arc<DataView>) -> Self {
12        Self { dataview }
13    }
14}
15
16impl DebugTrace for DataViewDebugProvider {
17    fn name(&self) -> &str {
18        "DataView"
19    }
20
21    fn debug_sections(&self) -> Vec<DebugSection> {
22        let mut builder = DebugSectionBuilder::new();
23
24        // Main DataView state section
25        builder.add_section("DATAVIEW STATE", "", Priority::DATAVIEW);
26
27        // Basic counts
28        builder.add_field("Visible Rows", self.dataview.row_count());
29        builder.add_field("Visible Columns", self.dataview.column_count());
30        builder.add_field("Source Rows", self.dataview.source().row_count());
31        builder.add_field("Source Columns", self.dataview.source().column_count());
32
33        // Column mapping information
34        builder.add_line("");
35        builder.add_line(&self.dataview.get_column_debug_info());
36
37        // Show visible columns in order
38        let visible_columns = self.dataview.column_names();
39        let column_mappings = self.dataview.get_column_index_mapping();
40        builder.add_line(format!(
41            "\nVisible Columns ({}) with Index Mapping:",
42            visible_columns.len()
43        ));
44        for (visible_idx, col_name, datatable_idx) in &column_mappings {
45            builder.add_line(format!(
46                "  V[{:3}] → DT[{:3}] : {}",
47                visible_idx, datatable_idx, col_name
48            ));
49        }
50
51        // Show internal state
52        builder.add_line("\n--- Internal State ---");
53        let visible_indices = self.dataview.get_visible_column_indices();
54        builder.add_line(format!("visible_columns array: {:?}", visible_indices));
55
56        // Pinned columns
57        let pinned_names = self.dataview.get_pinned_column_names();
58        if !pinned_names.is_empty() {
59            builder.add_line(format!("\nPinned Columns ({}):", pinned_names.len()));
60            for (idx, name) in pinned_names.iter().enumerate() {
61                let source_idx = self.dataview.source().get_column_index(name).unwrap_or(999);
62                builder.add_line(format!("  [{}] {} (source_idx: {})", idx, name, source_idx));
63            }
64        } else {
65            builder.add_line("Pinned Columns: None");
66        }
67
68        // Sort state
69        let sort_state = self.dataview.get_sort_state();
70        match sort_state.order {
71            SortOrder::None => {
72                builder.add_line("Sort State: None");
73            }
74            SortOrder::Ascending => {
75                if let Some(col_idx) = sort_state.column {
76                    let col_name = visible_columns
77                        .get(col_idx)
78                        .map(|s| s.as_str())
79                        .unwrap_or("unknown");
80                    builder.add_line(format!(
81                        "Sort State: Column {} ('{}') Ascending ↑",
82                        col_idx, col_name
83                    ));
84                } else {
85                    builder.add_line("Sort State: Ascending (no column)");
86                }
87            }
88            SortOrder::Descending => {
89                if let Some(col_idx) = sort_state.column {
90                    let col_name = visible_columns
91                        .get(col_idx)
92                        .map(|s| s.as_str())
93                        .unwrap_or("unknown");
94                    builder.add_line(format!(
95                        "Sort State: Column {} ('{}') Descending ↓",
96                        col_idx, col_name
97                    ));
98                } else {
99                    builder.add_line("Sort State: Descending (no column)");
100                }
101            }
102        }
103
104        // Filter state
105        if let Some(filter) = self.dataview.get_filter_pattern() {
106            builder.add_line(format!("\nText Filter Active: '{}'", filter));
107        }
108        if let Some(fuzzy) = self.dataview.get_fuzzy_filter_pattern() {
109            builder.add_line(format!("Fuzzy Filter Active: '{}'", fuzzy));
110        }
111        if self.dataview.has_column_search() {
112            if let Some(pattern) = self.dataview.column_search_pattern() {
113                builder.add_line(format!("Column Search Active: '{}'", pattern));
114                let matches = self.dataview.get_matching_columns();
115                builder.add_line(format!("  {} matches found", matches.len()));
116            }
117        }
118
119        // Column order changes
120        let original_columns = self.dataview.source().column_names();
121        if visible_columns != original_columns {
122            builder.add_line("\nColumn Order Changed: YES");
123
124            // Show hidden columns
125            let hidden: Vec<String> = original_columns
126                .iter()
127                .filter(|col| !visible_columns.contains(col))
128                .cloned()
129                .collect();
130            if !hidden.is_empty() {
131                builder.add_line(format!("Hidden Columns ({}):", hidden.len()));
132                for col in hidden {
133                    builder.add_line(format!("  - {}", col));
134                }
135            }
136        } else {
137            builder.add_line("\nColumn Order Changed: NO");
138        }
139
140        builder.build()
141    }
142
143    fn debug_summary(&self) -> Option<String> {
144        let rows = self.dataview.row_count();
145        let cols = self.dataview.column_count();
146        let pinned = self.dataview.get_pinned_columns().len();
147        let filtered = self.dataview.has_filter();
148
149        let mut summary = format!("{}x{} view", rows, cols);
150        if pinned > 0 {
151            summary.push_str(&format!(", {} pinned", pinned));
152        }
153        if filtered {
154            summary.push_str(", filtered");
155        }
156
157        Some(summary)
158    }
159
160    fn is_active(&self) -> bool {
161        true
162    }
163}