sql_cli/sql/parser/
legacy.rs

1//! Legacy parser types for backward compatibility
2//!
3//! These types were previously defined in parser.rs and are needed
4//! by various parts of the codebase.
5
6use crate::config::schema_config;
7
8#[derive(Debug, Clone, PartialEq)]
9pub enum SqlToken {
10    Select,
11    From,
12    Where,
13    OrderBy,
14    Identifier(String),
15    Column(String),
16    Table(String),
17    Operator(String),
18    String(String),
19    Number(String),
20    Function(String),
21    Comma,
22    Dot,
23    OpenParen,
24    CloseParen,
25}
26
27#[derive(Debug, Clone, PartialEq)]
28pub enum ParseState {
29    Start,
30    AfterSelect,
31    InColumnList,
32    AfterFrom,
33    InTableName,
34    AfterTable,
35    InWhere,
36    InOrderBy,
37}
38
39impl ParseState {
40    pub fn get_suggestions(&self, schema: &Schema) -> Vec<String> {
41        match self {
42            ParseState::Start => vec!["SELECT".to_string()],
43            ParseState::AfterSelect => schema.get_all_columns(),
44            ParseState::InColumnList => {
45                let mut suggestions = schema.get_all_columns();
46                suggestions.push("FROM".to_string());
47                suggestions
48            }
49            ParseState::AfterFrom => schema.get_table_names(),
50            ParseState::InTableName => schema.get_table_names(),
51            ParseState::AfterTable => vec!["WHERE".to_string(), "ORDER BY".to_string()],
52            ParseState::InWhere => schema.get_all_columns(),
53            ParseState::InOrderBy => schema.get_all_columns(),
54        }
55    }
56}
57
58#[derive(Debug, Clone)]
59pub struct ParseContext {
60    pub state: ParseState,
61    pub partial_word: Option<String>,
62}
63
64#[derive(Debug, Clone)]
65pub struct SqlParser {
66    pub tokens: Vec<SqlToken>,
67    pub current_state: ParseState,
68}
69
70impl Default for SqlParser {
71    fn default() -> Self {
72        Self::new()
73    }
74}
75
76impl SqlParser {
77    #[must_use]
78    pub fn new() -> Self {
79        Self {
80            tokens: Vec::new(),
81            current_state: ParseState::Start,
82        }
83    }
84
85    pub fn parse_quick(&mut self, query: &str) -> ParseState {
86        // Simple quick parsing - just look for keywords
87        let query_upper = query.to_uppercase();
88        if query_upper.contains("SELECT") && query_upper.contains("FROM") {
89            if query_upper.contains("WHERE") {
90                ParseState::InWhere
91            } else {
92                ParseState::AfterFrom
93            }
94        } else if query_upper.contains("SELECT") {
95            ParseState::AfterSelect
96        } else {
97            ParseState::Start
98        }
99    }
100
101    pub fn parse_to_position(&mut self, query: &str, position: usize) -> ParseState {
102        let query_up_to_position = &query[..position.min(query.len())];
103        self.parse_quick(query_up_to_position)
104    }
105
106    pub fn get_completion_context(&mut self, input: &str) -> ParseContext {
107        ParseContext {
108            state: self.parse_quick(input),
109            partial_word: None, // Simple implementation
110        }
111    }
112
113    pub fn parse_partial(&mut self, input: &str) -> ParseState {
114        self.parse_quick(input)
115    }
116}
117
118#[derive(Debug, Clone)]
119pub struct Schema {
120    tables: Vec<TableInfo>,
121}
122
123#[derive(Debug, Clone)]
124pub struct TableInfo {
125    pub name: String,
126    pub columns: Vec<String>,
127}
128
129impl Default for Schema {
130    fn default() -> Self {
131        Self::new()
132    }
133}
134
135impl Schema {
136    #[must_use]
137    pub fn new() -> Self {
138        // Use the complete column list from schema_config
139        let trade_deal_columns = schema_config::get_full_trade_deal_columns();
140
141        Self {
142            tables: vec![
143                TableInfo {
144                    name: "trade_deal".to_string(),
145                    columns: trade_deal_columns,
146                },
147                TableInfo {
148                    name: "test".to_string(),
149                    columns: vec![
150                        "id".to_string(),
151                        "name".to_string(),
152                        "value".to_string(),
153                        "timestamp".to_string(),
154                    ],
155                },
156            ],
157        }
158    }
159
160    pub fn get_table_names(&self) -> Vec<String> {
161        self.tables.iter().map(|t| t.name.clone()).collect()
162    }
163
164    pub fn get_columns_for_table(&self, table_name: &str) -> Vec<String> {
165        self.tables
166            .iter()
167            .find(|t| t.name.eq_ignore_ascii_case(table_name))
168            .map(|t| t.columns.clone())
169            .unwrap_or_default()
170    }
171
172    pub fn get_all_columns(&self) -> Vec<String> {
173        let mut all_columns = Vec::new();
174        for table in &self.tables {
175            all_columns.extend(table.columns.clone());
176        }
177        all_columns.sort();
178        all_columns.dedup();
179        all_columns
180    }
181
182    // Legacy compatibility methods
183    pub fn set_single_table(&mut self, table_name: &str, columns: Vec<String>) {
184        self.tables.clear();
185        self.tables.push(TableInfo {
186            name: table_name.to_string(),
187            columns,
188        });
189    }
190
191    pub fn get_columns(&self, table_name: &str) -> Vec<String> {
192        self.get_columns_for_table(table_name)
193    }
194
195    pub fn get_first_table_name(&self) -> Option<String> {
196        self.tables.first().map(|t| t.name.clone())
197    }
198
199    pub fn add_table(&mut self, name: String, columns: Vec<String>) {
200        // Remove table if it already exists
201        self.tables.retain(|t| t.name != name);
202        self.tables.push(TableInfo { name, columns });
203    }
204
205    pub fn has_table(&self, table_name: &str) -> bool {
206        self.tables
207            .iter()
208            .any(|t| t.name.eq_ignore_ascii_case(table_name))
209    }
210}