Skip to main content

sql_rs/query/
parser.rs

1use crate::{SqlRsError, Result, Value};
2
3#[derive(Debug, Clone, PartialEq)]
4pub enum AggregateFunction {
5    Count,
6    Sum,
7    Avg,
8    Min,
9    Max,
10}
11
12#[derive(Debug, Clone)]
13pub enum SelectColumn {
14    Star,
15    Column(String),
16    Aggregate {
17        function: AggregateFunction,
18        column: String,
19    },
20}
21
22#[derive(Debug, Clone)]
23pub enum Statement {
24    CreateTable {
25        name: String,
26        columns: Vec<(String, String)>,
27    },
28    Insert {
29        table: String,
30        columns: Vec<String>,
31        values: Vec<Value>,
32    },
33    Select {
34        table: String,
35        columns: Vec<SelectColumn>,
36        joins: Vec<Join>,
37        where_clause: Option<WhereClause>,
38        group_by: Option<Vec<String>>,
39        order_by: Option<OrderBy>,
40        limit: Option<usize>,
41        offset: Option<usize>,
42    },
43    Update {
44        table: String,
45        sets: Vec<(String, Value)>,
46        where_clause: Option<WhereClause>,
47    },
48    Delete {
49        table: String,
50        where_clause: Option<WhereClause>,
51    },
52    DropTable {
53        name: String,
54    },
55    CreateIndex {
56        index_name: String,
57        table: String,
58        column: String,
59    },
60    DropIndex {
61        index_name: String,
62    },
63}
64
65#[derive(Debug, Clone)]
66pub enum WhereExpression {
67    Condition {
68        column: String,
69        operator: String,
70        value: Value,
71    },
72    And {
73        left: Box<WhereExpression>,
74        right: Box<WhereExpression>,
75    },
76    Or {
77        left: Box<WhereExpression>,
78        right: Box<WhereExpression>,
79    },
80}
81
82// For backward compatibility, WhereClause is now a type alias
83pub type WhereClause = WhereExpression;
84
85#[derive(Debug, Clone)]
86pub struct OrderBy {
87    pub column: String,
88    pub ascending: bool,
89}
90
91#[derive(Debug, Clone, PartialEq)]
92pub enum JoinType {
93    Inner,
94    Left,
95    Right,
96}
97
98#[derive(Debug, Clone)]
99pub struct Join {
100    pub join_type: JoinType,
101    pub table: String,
102    pub on_left: String,
103    pub on_right: String,
104}
105
106pub fn parse_sql(sql: &str) -> Result<Statement> {
107    let sql = sql.trim();
108    let upper = sql.to_uppercase();
109    
110    // Use split_whitespace to handle multiple spaces between keywords
111    let words: Vec<&str> = upper.split_whitespace().collect();
112    
113    if words.len() >= 2 && words[0] == "CREATE" && words[1] == "TABLE" {
114        parse_create_table(sql)
115    } else if words.len() >= 2 && words[0] == "CREATE" && words[1] == "INDEX" {
116        parse_create_index(sql)
117    } else if words.len() >= 2 && words[0] == "INSERT" && words[1] == "INTO" {
118        parse_insert(sql)
119    } else if words.len() >= 1 && words[0] == "SELECT" {
120        parse_select(sql)
121    } else if words.len() >= 1 && words[0] == "UPDATE" {
122        parse_update(sql)
123    } else if words.len() >= 2 && words[0] == "DELETE" && words[1] == "FROM" {
124        parse_delete(sql)
125    } else if words.len() >= 2 && words[0] == "DROP" && words[1] == "TABLE" {
126        parse_drop_table(sql)
127    } else if words.len() >= 2 && words[0] == "DROP" && words[1] == "INDEX" {
128        parse_drop_index(sql)
129    } else {
130        Err(SqlRsError::Query(format!(
131            "Unsupported SQL statement: {}",
132            sql
133        )))
134    }
135}
136
137fn parse_create_table(sql: &str) -> Result<Statement> {
138    let parts: Vec<&str> = sql.split_whitespace().collect();
139
140    if parts.len() < 4 {
141        return Err(SqlRsError::Query(
142            "Invalid CREATE TABLE syntax".to_string(),
143        ));
144    }
145
146    let name = parts[2].to_string();
147
148    let columns_start = sql
149        .find('(')
150        .ok_or_else(|| SqlRsError::Query("Missing column definitions".to_string()))?;
151    let columns_end = sql
152        .rfind(')')
153        .ok_or_else(|| SqlRsError::Query("Missing closing parenthesis".to_string()))?;
154
155    let columns_str = &sql[columns_start + 1..columns_end];
156    let column_defs: Vec<&str> = columns_str.split(',').map(|s| s.trim()).collect();
157
158    let mut columns = Vec::new();
159    for def in column_defs {
160        let parts: Vec<&str> = def.split_whitespace().collect();
161        if parts.len() >= 2 {
162            columns.push((parts[0].to_string(), parts[1].to_uppercase()));
163        }
164    }
165
166    if columns.is_empty() {
167        return Err(SqlRsError::Query("No valid column definitions found".to_string()));
168    }
169
170    Ok(Statement::CreateTable { name, columns })
171}
172
173fn parse_insert(sql: &str) -> Result<Statement> {
174    let upper = sql.to_uppercase();
175
176    let table_start = upper
177        .find("INTO")
178        .ok_or_else(|| SqlRsError::Query("Missing INTO".to_string()))?
179        + 4;
180    let values_start = upper
181        .find("VALUES")
182        .ok_or_else(|| SqlRsError::Query("Missing VALUES".to_string()))?;
183
184    let table_part = sql[table_start..values_start].trim();
185
186    let (table, columns) = if let Some(paren_start) = table_part.find('(') {
187        let table = table_part[..paren_start].trim().to_string();
188        let paren_end = table_part
189            .rfind(')')
190            .ok_or_else(|| SqlRsError::Query("Missing closing parenthesis".to_string()))?;
191        let cols_str = &table_part[paren_start + 1..paren_end];
192        let columns: Vec<String> = cols_str.split(',').map(|s| s.trim().to_string()).collect();
193        (table, columns)
194    } else {
195        (table_part.to_string(), Vec::new())
196    };
197
198    let values_part = &sql[values_start + 6..].trim();
199    let values_start = values_part
200        .find('(')
201        .ok_or_else(|| SqlRsError::Query("Missing values parenthesis".to_string()))?;
202    let values_end = values_part
203        .rfind(')')
204        .ok_or_else(|| SqlRsError::Query("Missing closing parenthesis".to_string()))?;
205
206    let values_str = &values_part[values_start + 1..values_end];
207    let value_strs: Vec<&str> = values_str.split(',').map(|s| s.trim()).collect();
208
209    let mut values = Vec::new();
210    for val_str in value_strs {
211        values.push(parse_value(val_str)?);
212    }
213
214    Ok(Statement::Insert {
215        table,
216        columns,
217        values,
218    })
219}
220
221fn parse_select(sql: &str) -> Result<Statement> {
222    let upper = sql.to_uppercase();
223
224    let from_pos = upper
225        .find("FROM")
226        .ok_or_else(|| SqlRsError::Query("Missing FROM".to_string()))?;
227
228    let cols_str = sql[6..from_pos].trim();
229    let columns = parse_select_columns(cols_str)?;
230
231    let after_from = &sql[from_pos + 4..];
232    let upper_after_from = after_from.to_uppercase();
233
234    // Find positions of JOIN types, WHERE, GROUP BY, ORDER BY, LIMIT, OFFSET
235    let inner_join_pos = upper_after_from.find("INNER JOIN");
236    let left_join_pos = upper_after_from.find("LEFT JOIN");
237    let right_join_pos = upper_after_from.find("RIGHT JOIN");
238    let join_pos = upper_after_from.find("JOIN");
239    let where_pos = upper_after_from.find("WHERE");
240    let group_pos = upper_after_from.find("GROUP BY");
241    let order_pos = upper_after_from.find("ORDER BY");
242    let limit_pos = upper_after_from.find("LIMIT");
243    let offset_pos = upper_after_from.find("OFFSET");
244
245    // Find the first JOIN position (if any)
246    let first_join_pos = [inner_join_pos, left_join_pos, right_join_pos, join_pos]
247        .iter()
248        .filter_map(|&p| p)
249        .min();
250
251    // Determine the end of the table name
252    let table_end = [first_join_pos, where_pos, group_pos, order_pos, limit_pos, offset_pos]
253        .iter()
254        .filter_map(|&p| p)
255        .min()
256        .unwrap_or(after_from.len());
257
258    let table = after_from[..table_end].trim().to_string();
259
260    // Parse JOIN clauses
261    let joins = if first_join_pos.is_some() {
262        parse_joins(after_from, first_join_pos.unwrap())?
263    } else {
264        Vec::new()
265    };
266
267    // Parse WHERE clause
268    let where_clause = if let Some(pos) = where_pos {
269        let where_end = [group_pos, order_pos, limit_pos, offset_pos]
270            .iter()
271            .filter_map(|&p| p)
272            .filter(|&p| p > pos)
273            .min()
274            .unwrap_or(after_from.len());
275        let where_str = after_from[pos + 5..where_end].trim();
276        Some(parse_where(where_str)?)
277    } else {
278        None
279    };
280
281    // Parse GROUP BY clause
282    let group_by = if let Some(pos) = group_pos {
283        let group_end = [order_pos, limit_pos, offset_pos]
284            .iter()
285            .filter_map(|&p| p)
286            .filter(|&p| p > pos)
287            .min()
288            .unwrap_or(after_from.len());
289        let group_str = after_from[pos + 8..group_end].trim();
290        let columns: Vec<String> = group_str.split(',').map(|s| s.trim().to_string()).collect();
291        Some(columns)
292    } else {
293        None
294    };
295
296    // Parse ORDER BY clause
297    let order_by = if let Some(pos) = order_pos {
298        let order_end = [limit_pos, offset_pos]
299            .iter()
300            .filter_map(|&p| p)
301            .filter(|&p| p > pos)
302            .min()
303            .unwrap_or(after_from.len());
304        let order_str = after_from[pos + 8..order_end].trim();
305        Some(parse_order_by(order_str)?)
306    } else {
307        None
308    };
309
310    // Parse LIMIT clause
311    let limit = if let Some(pos) = limit_pos {
312        let limit_end = offset_pos
313            .filter(|&p| p > pos)
314            .unwrap_or(after_from.len());
315        let limit_str = after_from[pos + 5..limit_end].trim();
316        Some(limit_str.parse::<usize>().map_err(|_| {
317            SqlRsError::Query("Invalid LIMIT value".to_string())
318        })?)
319    } else {
320        None
321    };
322
323    // Parse OFFSET clause
324    let offset = if let Some(pos) = offset_pos {
325        let offset_str = after_from[pos + 6..].trim();
326        Some(offset_str.parse::<usize>().map_err(|_| {
327            SqlRsError::Query("Invalid OFFSET value".to_string())
328        })?)
329    } else {
330        None
331    };
332
333    Ok(Statement::Select {
334        table,
335        columns,
336        joins,
337        where_clause,
338        group_by,
339        order_by,
340        limit,
341        offset,
342    })
343}
344
345fn parse_joins(after_from: &str, start_pos: usize) -> Result<Vec<Join>> {
346    let upper = after_from.to_uppercase();
347    let mut joins = Vec::new();
348    let mut current_pos = start_pos;
349
350    // Find WHERE, GROUP BY, ORDER BY, LIMIT, OFFSET to know where JOINs end
351    let where_pos = upper.find("WHERE");
352    let group_pos = upper.find("GROUP BY");
353    let order_pos = upper.find("ORDER BY");
354    let limit_pos = upper.find("LIMIT");
355    let offset_pos = upper.find("OFFSET");
356    
357    let joins_end = [where_pos, group_pos, order_pos, limit_pos, offset_pos]
358        .iter()
359        .filter_map(|&p| p)
360        .min()
361        .unwrap_or(after_from.len());
362
363    while current_pos < joins_end {
364        let remaining = &after_from[current_pos..joins_end];
365        let remaining_upper = remaining.to_uppercase();
366
367        // Determine join type
368        let (join_type, keyword_len) = if remaining_upper.starts_with("INNER JOIN") {
369            (JoinType::Inner, 10)
370        } else if remaining_upper.starts_with("LEFT JOIN") {
371            (JoinType::Left, 9)
372        } else if remaining_upper.starts_with("RIGHT JOIN") {
373            (JoinType::Right, 10)
374        } else if remaining_upper.starts_with("JOIN") {
375            (JoinType::Inner, 4) // Default JOIN is INNER JOIN
376        } else {
377            break;
378        };
379
380        // Skip the JOIN keyword
381        let after_join = &remaining[keyword_len..].trim_start();
382        let after_join_upper = after_join.to_uppercase();
383
384        // Find ON keyword
385        let on_pos = after_join_upper.find(" ON ")
386            .ok_or_else(|| SqlRsError::Query("Missing ON clause in JOIN".to_string()))?;
387
388        let table_name = after_join[..on_pos].trim().to_string();
389
390        // Parse ON condition
391        let after_on = &after_join[on_pos + 4..];
392        
393        // Find the end of ON clause (next JOIN or end of joins section)
394        let next_inner_join = after_on.to_uppercase().find("INNER JOIN");
395        let next_left_join = after_on.to_uppercase().find("LEFT JOIN");
396        let next_right_join = after_on.to_uppercase().find("RIGHT JOIN");
397        let next_join = after_on.to_uppercase().find(" JOIN");
398        
399        let on_end = [next_inner_join, next_left_join, next_right_join, next_join]
400            .iter()
401            .filter_map(|&p| p)
402            .min()
403            .unwrap_or(after_on.len());
404
405        let on_clause = after_on[..on_end].trim();
406
407        // Parse ON condition (e.g., "table1.id = table2.id")
408        let parts: Vec<&str> = on_clause.split('=').map(|s| s.trim()).collect();
409        if parts.len() != 2 {
410            return Err(SqlRsError::Query("Invalid ON clause format".to_string()));
411        }
412
413        let on_left = parts[0].to_string();
414        let on_right = parts[1].to_string();
415
416        joins.push(Join {
417            join_type,
418            table: table_name,
419            on_left,
420            on_right,
421        });
422
423        // Move to next potential JOIN
424        // We need to move past the current JOIN keyword, table name, ON keyword, and ON clause
425        let consumed = keyword_len + on_pos + 4 + on_end;
426        current_pos = current_pos + consumed;
427        
428        // Skip any whitespace
429        while current_pos < joins_end && after_from.as_bytes().get(current_pos).map_or(false, |&b| b.is_ascii_whitespace()) {
430            current_pos += 1;
431        }
432    }
433
434    Ok(joins)
435}
436
437fn parse_select_columns(cols_str: &str) -> Result<Vec<SelectColumn>> {
438    let cols_str = cols_str.trim();
439    
440    if cols_str.is_empty() {
441        return Err(SqlRsError::Query("Empty column list in SELECT".to_string()));
442    }
443    
444    if cols_str == "*" {
445        return Ok(vec![SelectColumn::Star]);
446    }
447
448    let mut columns = Vec::new();
449    for col_str in cols_str.split(',') {
450        let col_str = col_str.trim();
451        let col_upper = col_str.to_uppercase();
452
453        // Check for aggregate functions
454        if col_upper.starts_with("COUNT(") {
455            let inner = &col_str[6..col_str.len().saturating_sub(1)].trim();
456            columns.push(SelectColumn::Aggregate {
457                function: AggregateFunction::Count,
458                column: inner.to_string(),
459            });
460        } else if col_upper.starts_with("SUM(") {
461            let inner = &col_str[4..col_str.len().saturating_sub(1)].trim();
462            columns.push(SelectColumn::Aggregate {
463                function: AggregateFunction::Sum,
464                column: inner.to_string(),
465            });
466        } else if col_upper.starts_with("AVG(") {
467            let inner = &col_str[4..col_str.len().saturating_sub(1)].trim();
468            columns.push(SelectColumn::Aggregate {
469                function: AggregateFunction::Avg,
470                column: inner.to_string(),
471            });
472        } else if col_upper.starts_with("MIN(") {
473            let inner = &col_str[4..col_str.len().saturating_sub(1)].trim();
474            columns.push(SelectColumn::Aggregate {
475                function: AggregateFunction::Min,
476                column: inner.to_string(),
477            });
478        } else if col_upper.starts_with("MAX(") {
479            let inner = &col_str[4..col_str.len().saturating_sub(1)].trim();
480            columns.push(SelectColumn::Aggregate {
481                function: AggregateFunction::Max,
482                column: inner.to_string(),
483            });
484        } else {
485            // Regular column
486            columns.push(SelectColumn::Column(col_str.to_string()));
487        }
488    }
489
490    Ok(columns)
491}
492
493fn parse_update(sql: &str) -> Result<Statement> {
494    let upper = sql.to_uppercase();
495
496    // Find UPDATE and table name
497    let update_pos = 0;
498    let set_pos = upper
499        .find("SET")
500        .ok_or_else(|| SqlRsError::Query("Missing SET in UPDATE".to_string()))?;
501
502    let table = sql[update_pos + 6..set_pos].trim().to_string();
503
504    // Find WHERE clause if exists
505    let after_set = &sql[set_pos + 3..].trim();
506
507    let (set_where_str, where_clause) =
508        if let Some(where_pos) = after_set.to_uppercase().find("WHERE") {
509            let set_str = &after_set[..where_pos];
510            let where_str = &after_set[where_pos + 5..];
511            (set_str.to_string(), Some(parse_where(where_str.trim())?))
512        } else {
513            (after_set.to_string(), None)
514        };
515
516    // Parse SET clauses (e.g., "col1 = val1, col2 = val2")
517    let mut sets = Vec::new();
518    for set_clause in set_where_str.split(',') {
519        let set_clause = set_clause.trim();
520        if let Some(eq_pos) = set_clause.find('=') {
521            let column = set_clause[..eq_pos].trim().to_string();
522            let value_str = set_clause[eq_pos + 1..].trim();
523            let value = parse_value(value_str)?;
524            sets.push((column, value));
525        } else {
526            return Err(SqlRsError::Query(format!(
527                "Invalid SET clause: {}",
528                set_clause
529            )));
530        }
531    }
532
533    if sets.is_empty() {
534        return Err(SqlRsError::Query("No SET clauses provided".to_string()));
535    }
536
537    Ok(Statement::Update {
538        table,
539        sets,
540        where_clause,
541    })
542}
543
544fn parse_where(where_str: &str) -> Result<WhereExpression> {
545    // Parse OR (lowest precedence)
546    parse_or_expression(where_str)
547}
548
549fn parse_or_expression(where_str: &str) -> Result<WhereExpression> {
550    let upper = where_str.to_uppercase();
551
552    // Find all OR positions that are not within parentheses
553    let or_positions = find_logical_operator_positions(&upper, "OR");
554
555    // If we found OR, split and parse recursively
556    if !or_positions.is_empty() {
557        // Use the first OR position (left-to-right associativity)
558        let or_pos = or_positions[0];
559        let left_str = &where_str[..or_pos];
560        let right_str = &where_str[or_pos + 3..]; // Skip "OR"
561
562        return Ok(WhereExpression::Or {
563            left: Box::new(parse_and_expression(left_str.trim())?),
564            right: Box::new(parse_or_expression(right_str.trim())?),
565        });
566    }
567
568    // No OR found, try AND
569    parse_and_expression(where_str)
570}
571
572fn parse_and_expression(where_str: &str) -> Result<WhereExpression> {
573    let upper = where_str.to_uppercase();
574
575    // Find all AND positions that are not within parentheses
576    let and_positions = find_logical_operator_positions(&upper, "AND");
577
578    // If we found AND, split and parse recursively
579    if !and_positions.is_empty() {
580        // Use the first AND position (left-to-right associativity)
581        let and_pos = and_positions[0];
582        let left_str = &where_str[..and_pos];
583        let right_str = &where_str[and_pos + 4..]; // Skip "AND "
584
585        return Ok(WhereExpression::And {
586            left: Box::new(parse_and_expression(left_str.trim())?),
587            right: Box::new(parse_and_expression(right_str.trim())?),
588        });
589    }
590
591    // No AND found, parse as a single condition
592    parse_condition(where_str)
593}
594
595fn find_logical_operator_positions(upper: &str, operator: &str) -> Vec<usize> {
596    let mut positions = Vec::new();
597    let mut depth = 0;
598    let bytes = upper.as_bytes();
599    let op_bytes = operator.as_bytes();
600    let op_len = op_bytes.len();
601
602    for i in 0..bytes.len() {
603        match bytes[i] {
604            b'(' => depth += 1,
605            b')' => depth -= 1,
606            _ if depth == 0 => {
607                // Check if we can find the operator at this position
608                if i + op_len <= bytes.len() && &bytes[i..i + op_len] == op_bytes {
609                    // Check if it's surrounded by spaces (or at boundaries with proper spacing)
610                    let before_ok = i == 0 || bytes[i - 1].is_ascii_whitespace();
611                    let after_ok = i + op_len >= bytes.len() || bytes[i + op_len].is_ascii_whitespace();
612
613                    if before_ok && after_ok {
614                        positions.push(i);
615                    }
616                }
617            }
618            _ => {}
619        }
620    }
621
622    positions
623}
624
625fn parse_condition(where_str: &str) -> Result<WhereExpression> {
626    let trimmed = where_str.trim();
627
628    // Handle parentheses for grouping
629    if trimmed.starts_with('(') {
630        // Find matching closing parenthesis
631        let mut depth = 0;
632        let mut close_pos = 0;
633        let mut chars = trimmed.chars().enumerate();
634
635        while let Some((pos, c)) = chars.next() {
636            match c {
637                '(' => depth += 1,
638                ')' => {
639                    depth -= 1;
640                    if depth == 0 {
641                        close_pos = pos;
642                        break;
643                    }
644                }
645                _ => {}
646            }
647        }
648
649        if close_pos > 0 {
650            let inner = &trimmed[1..close_pos];
651            let remaining = &trimmed[close_pos + 1..].trim();
652
653            // If there's remaining text after the parentheses, parse it as an AND/OR
654            if remaining.is_empty() {
655                return parse_or_expression(inner);
656            } else {
657                // Combine the parenthesized expression with the remaining part
658                // This handles cases like "(a = 1) OR (b = 2)"
659                let left_expr = parse_or_expression(inner)?;
660
661                // Try to parse the remaining part as AND/OR
662                let remaining_upper = remaining.to_uppercase();
663                if remaining_upper.starts_with("AND ") {
664                    let right_str = remaining[4..].trim();
665                    let right_expr = parse_or_expression(right_str)?;
666                    return Ok(WhereExpression::And {
667                        left: Box::new(left_expr),
668                        right: Box::new(right_expr),
669                    });
670                } else if remaining_upper.starts_with("OR ") {
671                    let right_str = remaining[3..].trim();
672                    let right_expr = parse_or_expression(right_str)?;
673                    return Ok(WhereExpression::Or {
674                        left: Box::new(left_expr),
675                        right: Box::new(right_expr),
676                    });
677                }
678            }
679        }
680    }
681
682    // Parse as a simple condition
683    let operators = [">=", "<=", "!=", "=", ">", "<"];
684
685    for op in &operators {
686        if let Some(pos) = trimmed.find(op) {
687            let column = trimmed[..pos].trim().to_string();
688            let value_str = trimmed[pos + op.len()..].trim();
689            let value = parse_value(value_str)?;
690
691            return Ok(WhereExpression::Condition {
692                column,
693                operator: op.to_string(),
694                value,
695            });
696        }
697    }
698
699    Err(SqlRsError::Query("Invalid WHERE clause".to_string()))
700}
701
702fn parse_delete(sql: &str) -> Result<Statement> {
703    let upper = sql.to_uppercase();
704
705    let from_pos = upper
706        .find("FROM")
707        .ok_or_else(|| SqlRsError::Query("Missing FROM in DELETE".to_string()))?;
708
709    let after_from = &sql[from_pos + 4..].trim();
710
711    let (table, where_clause) = if let Some(where_pos) = after_from.to_uppercase().find("WHERE") {
712        let table = after_from[..where_pos].trim().to_string();
713        let where_str = after_from[where_pos + 5..].trim();
714        (table, Some(parse_where(where_str)?))
715    } else {
716        (after_from.to_string(), None)
717    };
718
719    if table.is_empty() {
720        return Err(SqlRsError::Query("Missing table name in DELETE".to_string()));
721    }
722
723    Ok(Statement::Delete {
724        table,
725        where_clause,
726    })
727}
728
729fn parse_drop_table(sql: &str) -> Result<Statement> {
730    let parts: Vec<&str> = sql.split_whitespace().collect();
731
732    if parts.len() < 3 {
733        return Err(SqlRsError::Query(
734            "Invalid DROP TABLE syntax".to_string(),
735        ));
736    }
737
738    let name = parts[2].to_string();
739
740    Ok(Statement::DropTable { name })
741}
742
743fn parse_order_by(order_str: &str) -> Result<OrderBy> {
744    let upper = order_str.to_uppercase();
745    let ascending = !upper.ends_with("DESC");
746    
747    let column = if upper.ends_with("ASC") {
748        order_str[..order_str.len() - 3].trim().to_string()
749    } else if upper.ends_with("DESC") {
750        order_str[..order_str.len() - 4].trim().to_string()
751    } else {
752        order_str.trim().to_string()
753    };
754    
755    Ok(OrderBy { column, ascending })
756}
757
758fn parse_value(s: &str) -> Result<Value> {
759    let s = s.trim();
760
761    if s.eq_ignore_ascii_case("NULL") {
762        return Ok(Value::Null);
763    }
764
765    if s.eq_ignore_ascii_case("TRUE") {
766        return Ok(Value::Boolean(true));
767    }
768
769    if s.eq_ignore_ascii_case("FALSE") {
770        return Ok(Value::Boolean(false));
771    }
772
773    if (s.starts_with('\'') && s.ends_with('\'')) || (s.starts_with('"') && s.ends_with('"')) {
774        return Ok(Value::Text(s[1..s.len() - 1].to_string()));
775    }
776
777    if let Ok(i) = s.parse::<i64>() {
778        return Ok(Value::Integer(i));
779    }
780
781    if let Ok(f) = s.parse::<f64>() {
782        return Ok(Value::Float(f));
783    }
784
785    Ok(Value::Text(s.to_string()))
786}
787
788fn parse_create_index(sql: &str) -> Result<Statement> {
789    // CREATE INDEX index_name ON table_name (column_name)
790    let upper = sql.to_uppercase();
791    
792    let on_pos = upper
793        .find(" ON ")
794        .ok_or_else(|| SqlRsError::Query("Missing ON in CREATE INDEX".to_string()))?;
795    
796    let index_part = &sql[12..on_pos].trim(); // Skip "CREATE INDEX"
797    let index_name = index_part.to_string();
798    
799    if index_name.is_empty() {
800        return Err(SqlRsError::Query("Missing index name in CREATE INDEX".to_string()));
801    }
802    
803    let after_on = &sql[on_pos + 4..].trim();
804    
805    // Find opening parenthesis
806    let paren_start = after_on
807        .find('(')
808        .ok_or_else(|| SqlRsError::Query("Missing column specification in CREATE INDEX".to_string()))?;
809    
810    let table = after_on[..paren_start].trim().to_string();
811    
812    if table.is_empty() {
813        return Err(SqlRsError::Query("Missing table name in CREATE INDEX".to_string()));
814    }
815    
816    let paren_end = after_on
817        .rfind(')')
818        .ok_or_else(|| SqlRsError::Query("Missing closing parenthesis in CREATE INDEX".to_string()))?;
819    
820    let column = after_on[paren_start + 1..paren_end].trim().to_string();
821    
822    if column.is_empty() {
823        return Err(SqlRsError::Query("Missing column name in CREATE INDEX".to_string()));
824    }
825    
826    Ok(Statement::CreateIndex {
827        index_name,
828        table,
829        column,
830    })
831}
832
833fn parse_drop_index(sql: &str) -> Result<Statement> {
834    // DROP INDEX index_name
835    let parts: Vec<&str> = sql.split_whitespace().collect();
836    
837    if parts.len() < 3 {
838        return Err(SqlRsError::Query("Invalid DROP INDEX syntax".to_string()));
839    }
840    
841    let index_name = parts[2].to_string();
842    
843    if index_name.is_empty() {
844        return Err(SqlRsError::Query("Missing index name in DROP INDEX".to_string()));
845    }
846    
847    Ok(Statement::DropIndex { index_name })
848}