datafusion_dft/tui/handlers/
sql.rs1use std::sync::Arc;
19
20use log::{error, info};
21use ratatui::crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
22
23use super::App;
24use crate::tui::{handlers::tab_navigation_handler, state::tabs::sql::SQLTabMode, AppEvent};
25
26pub fn normal_mode_handler(app: &mut App, key: KeyEvent) {
27 match key.code {
28 KeyCode::Char('q') => app.state.should_quit = true,
29 tab @ (KeyCode::Char('1')
30 | KeyCode::Char('2')
31 | KeyCode::Char('3')
32 | KeyCode::Char('4')
33 | KeyCode::Char('5')) => tab_navigation_handler(app, tab),
34 KeyCode::Char('c') => app.state.sql_tab.clear_editor(&app.state.config),
35 KeyCode::Char('e') => {
36 let editor = app.state.sql_tab.editor();
37 let lines = editor.lines();
38 let content = lines.join("");
39 let default = "Enter a query here.";
40 if content == default {
41 app.state.sql_tab.clear_placeholder();
42 }
43 app.state.sql_tab.edit();
44 }
45 KeyCode::Char('d') => app.state.sql_tab.set_mode(SQLTabMode::DDL),
46 KeyCode::Char('n') => app.state.sql_tab.set_mode(SQLTabMode::Normal),
47 KeyCode::Char('s') => {
48 if *app.state.sql_tab.mode() == SQLTabMode::DDL {
49 let textarea = app.state.sql_tab.active_editor_cloned();
50 let ddl = textarea.lines().join("\n");
51 app.execution.save_ddl(ddl)
52 }
53 }
54 KeyCode::Down => {
55 if let Some(s) = app.state.sql_tab.query_results_state() {
56 info!("Select next");
57 let mut s = s.borrow_mut();
58 s.select_next();
59 }
60 }
61 KeyCode::Up => {
62 if let Some(s) = app.state.sql_tab.query_results_state() {
63 info!("Select previous");
64 let mut s = s.borrow_mut();
65 s.select_previous();
66 }
67 }
68
69 KeyCode::Enter => match app.state.sql_tab.mode() {
70 SQLTabMode::Normal => {
71 let sql = app.state.sql_tab.sql();
72 info!("Running query: {}", sql);
73 let _event_tx = app.event_tx().clone();
74 let execution = Arc::clone(&app.execution);
75 let sqls: Vec<String> = sql.split(';').map(|s| s.to_string()).collect();
76 let handle = tokio::spawn(execution.run_sqls(sqls, _event_tx));
77 app.state.sql_tab.set_execution_task(handle);
78 }
79 SQLTabMode::DDL => {
80 let _event_tx = app.event_tx().clone();
81 let ddl = app.execution.load_ddl().unwrap_or_default();
84 if let Err(e) = _event_tx.send(AppEvent::ExecuteDDL(ddl)) {
85 error!("Error sending ExecuteDDL event: {:?}", e);
86 }
87 }
88 },
89 KeyCode::Right => {
90 let _event_tx = app.event_tx().clone();
91 if let (Some(p), c) = (
92 app.state().sql_tab.current_page(),
93 app.state().sql_tab.batches_count(),
94 ) {
95 if p < c - 1 {
98 app.state.sql_tab.next_page();
99 app.state.sql_tab.refresh_query_results_state();
100 return;
101 }
102 }
103 if let Some(p) = app.state.history_tab.history().last() {
104 let execution = Arc::clone(&app.execution);
105 let sql = p.sql().clone();
106 tokio::spawn(async move {
107 execution.next_batch(sql, _event_tx).await;
108 });
109 }
110 }
111 KeyCode::Left => {
112 app.state.sql_tab.previous_page();
113 app.state.sql_tab.refresh_query_results_state();
114 }
115 _ => {}
116 }
117}
118
119pub fn editable_handler(app: &mut App, key: KeyEvent) {
120 match (key.code, key.modifiers) {
121 (KeyCode::Left, KeyModifiers::ALT) => app.state.sql_tab.previous_word(),
122 (KeyCode::Right, KeyModifiers::ALT) => app.state.sql_tab.next_word(),
123 (KeyCode::Backspace, KeyModifiers::ALT) => app.state.sql_tab.delete_word(),
124 (KeyCode::Esc, _) => app.state.sql_tab.exit_edit(),
125 (KeyCode::Enter, KeyModifiers::ALT) => {
126 match app.state.sql_tab.mode() {
127 SQLTabMode::Normal => {
129 let sql = app.state.sql_tab.sql();
130 info!("Running query: {}", sql);
131 let _event_tx = app.event_tx().clone();
132 let execution = Arc::clone(&app.execution);
133 let sqls: Vec<String> = sql.split(';').map(|s| s.to_string()).collect();
134 let handle = tokio::spawn(execution.run_sqls(sqls, _event_tx));
135 app.state.sql_tab.set_execution_task(handle);
136 }
137 SQLTabMode::DDL => {
138 let _event_tx = app.event_tx().clone();
139 let ddl = app.execution.load_ddl().unwrap_or_default();
142 if let Err(e) = _event_tx.send(AppEvent::ExecuteDDL(ddl)) {
143 error!("Error sending ExecuteDDL event: {:?}", e);
144 }
145 }
146 }
147 }
148 _ => app.state.sql_tab.update_editor_content(key),
149 }
150}
151
152pub fn app_event_handler(app: &mut App, event: AppEvent) {
153 match event {
154 AppEvent::Key(key) => match app.state.sql_tab.editable() {
155 true => editable_handler(app, key),
156 false => normal_mode_handler(app, key),
157 },
158 AppEvent::Error => {}
159 _ => {}
160 };
161}