sql_cli/services/
query_orchestrator.rs1use crate::app_state_container::AppStateContainer;
2use crate::config::config::BehaviorConfig;
3use crate::data::data_view::DataView;
4use crate::services::{QueryExecutionResult, QueryExecutionService};
5use crate::ui::search::vim_search_adapter::VimSearchAdapter;
6use anyhow::Result;
7use std::cell::RefCell;
8use tracing::{debug, info};
9
10pub struct QueryOrchestrator {
13 query_execution_service: QueryExecutionService,
14}
15
16impl QueryOrchestrator {
17 pub fn new(case_insensitive: bool, auto_hide_empty: bool) -> Self {
18 Self {
19 query_execution_service: QueryExecutionService::new(case_insensitive, auto_hide_empty),
20 }
21 }
22
23 pub fn with_behavior_config(behavior_config: BehaviorConfig) -> Self {
24 Self {
25 query_execution_service: QueryExecutionService::with_behavior_config(behavior_config),
26 }
27 }
28
29 pub fn execute_query(
31 &mut self,
32 query: &str,
33 state_container: &mut AppStateContainer,
34 vim_search_adapter: &RefCell<VimSearchAdapter>,
35 ) -> Result<QueryExecutionContext> {
36 info!(target: "query", "Executing query: {}", query);
37
38 self.clear_all_search_state(state_container, vim_search_adapter);
40
41 self.record_query_execution(query, state_container);
43
44 state_container.set_status_message(format!("Executing query: '{}'...", query));
46
47 let current_dataview = state_container.get_buffer_dataview();
49 let original_source = state_container.get_original_source();
50
51 if let Some(ref orig) = original_source {
53 debug!(
54 "QueryOrchestrator: Have original source with {} columns",
55 orig.column_count()
56 );
57 } else {
58 debug!("QueryOrchestrator: WARNING - No original source available!");
59 }
60
61 if let Some(ref view) = current_dataview {
62 debug!(
63 "QueryOrchestrator: Current view has {} columns, source has {} columns",
64 view.column_count(),
65 view.source().column_count()
66 );
67 }
68
69 let result =
70 self.query_execution_service
71 .execute(query, current_dataview, original_source)?;
72
73 self.clear_all_filters(state_container);
75
76 Ok(QueryExecutionContext {
78 result,
79 query: query.to_string(),
80 })
81 }
82
83 fn clear_all_search_state(
85 &self,
86 state_container: &mut AppStateContainer,
87 vim_search_adapter: &RefCell<VimSearchAdapter>,
88 ) {
89 state_container.clear_search();
91 state_container.clear_column_search();
92
93 vim_search_adapter.borrow_mut().cancel_search();
95 }
96
97 fn record_query_execution(&self, query: &str, state_container: &mut AppStateContainer) {
99 state_container.set_last_query(query.to_string());
100 state_container.set_last_executed_query(query.to_string());
101 }
102
103 fn clear_all_filters(&self, state_container: &mut AppStateContainer) {
105 state_container.set_filter_pattern(String::new());
106 state_container.set_fuzzy_filter_pattern(String::new());
107 state_container.set_filter_active(false);
108 state_container.set_fuzzy_filter_active(false);
109 }
110
111 pub fn set_case_insensitive(&mut self, case_insensitive: bool) {
113 self.query_execution_service
114 .set_case_insensitive(case_insensitive);
115 }
116
117 pub fn set_auto_hide_empty(&mut self, auto_hide: bool) {
118 self.query_execution_service.set_auto_hide_empty(auto_hide);
119 }
120}
121
122pub struct QueryExecutionContext {
124 pub result: QueryExecutionResult,
125 pub query: String,
126}
127
128impl QueryExecutionContext {
129 pub fn apply_to_tui(
132 self,
133 state_container: &mut AppStateContainer,
134 update_viewport: impl FnOnce(DataView),
135 calculate_widths: impl FnOnce(),
136 reset_table: impl FnOnce(),
137 ) -> Result<()> {
138 state_container.set_dataview(Some(self.result.dataview.clone()));
140
141 update_viewport(self.result.dataview.clone());
143
144 state_container
146 .update_data_size(self.result.stats.row_count, self.result.stats.column_count);
147
148 calculate_widths();
150
151 state_container.set_status_message(self.result.status_message());
153
154 state_container
156 .command_history_mut()
157 .add_entry_with_schema(
158 self.query.clone(),
159 true,
160 Some(self.result.stats.execution_time.as_millis() as u64),
161 self.result.column_names(),
162 Some(self.result.table_name()),
163 )?;
164
165 state_container.set_mode(crate::buffer::AppMode::Results);
167
168 reset_table();
170
171 Ok(())
172 }
173}