Skip to main content

polyglot_sql/optimizer/
simplify.rs

1//! Expression Simplification
2//!
3//! This module provides boolean and expression simplification for SQL AST nodes.
4//! It applies various algebraic transformations to simplify expressions:
5//! - De Morgan's laws (NOT (A AND B) -> NOT A OR NOT B)
6//! - Constant folding (1 + 2 -> 3)
7//! - Boolean absorption (A AND (A OR B) -> A)
8//! - Complement removal (A AND NOT A -> FALSE)
9//! - Connector flattening (A AND (B AND C) -> A AND B AND C)
10//!
11//! Based on SQLGlot's optimizer/simplify.py
12
13use crate::dialects::DialectType;
14use crate::expressions::{
15    BinaryOp, BooleanLiteral, Case, ConcatWs, DateTruncFunc, Expression, Literal, Null, Paren,
16    UnaryOp,
17};
18
19/// Main entry point for expression simplification
20pub fn simplify(expression: Expression, dialect: Option<DialectType>) -> Expression {
21    let mut simplifier = Simplifier::new(dialect);
22    simplifier.simplify(expression)
23}
24
25/// Check if expression is always true
26pub fn always_true(expr: &Expression) -> bool {
27    match expr {
28        Expression::Boolean(b) => b.value,
29        Expression::Literal(Literal::Number(n)) => {
30            // Non-zero numbers are truthy
31            if let Ok(num) = n.parse::<f64>() {
32                num != 0.0
33            } else {
34                false
35            }
36        }
37        _ => false,
38    }
39}
40
41/// Check if expression is a boolean TRUE literal (not just truthy)
42pub fn is_boolean_true(expr: &Expression) -> bool {
43    matches!(expr, Expression::Boolean(b) if b.value)
44}
45
46/// Check if expression is a boolean FALSE literal (not just falsy)
47pub fn is_boolean_false(expr: &Expression) -> bool {
48    matches!(expr, Expression::Boolean(b) if !b.value)
49}
50
51/// Check if expression is always false
52pub fn always_false(expr: &Expression) -> bool {
53    is_false(expr) || is_null(expr) || is_zero(expr)
54}
55
56/// Check if expression is boolean FALSE
57pub fn is_false(expr: &Expression) -> bool {
58    matches!(expr, Expression::Boolean(b) if !b.value)
59}
60
61/// Check if expression is NULL
62pub fn is_null(expr: &Expression) -> bool {
63    matches!(expr, Expression::Null(_))
64}
65
66/// Check if expression is zero
67pub fn is_zero(expr: &Expression) -> bool {
68    match expr {
69        Expression::Literal(Literal::Number(n)) => {
70            if let Ok(num) = n.parse::<f64>() {
71                num == 0.0
72            } else {
73                false
74            }
75        }
76        _ => false,
77    }
78}
79
80/// Check if b is the complement of a (i.e., b = NOT a)
81pub fn is_complement(a: &Expression, b: &Expression) -> bool {
82    if let Expression::Not(not_op) = b {
83        &not_op.this == a
84    } else {
85        false
86    }
87}
88
89/// Create a TRUE boolean literal
90pub fn bool_true() -> Expression {
91    Expression::Boolean(BooleanLiteral { value: true })
92}
93
94/// Create a FALSE boolean literal
95pub fn bool_false() -> Expression {
96    Expression::Boolean(BooleanLiteral { value: false })
97}
98
99/// Create a NULL expression
100pub fn null() -> Expression {
101    Expression::Null(Null)
102}
103
104/// Evaluate a boolean comparison between two numbers
105pub fn eval_boolean_nums(op: &str, a: f64, b: f64) -> Option<Expression> {
106    let result = match op {
107        "=" | "==" => a == b,
108        "!=" | "<>" => a != b,
109        ">" => a > b,
110        ">=" => a >= b,
111        "<" => a < b,
112        "<=" => a <= b,
113        _ => return None,
114    };
115    Some(if result { bool_true() } else { bool_false() })
116}
117
118/// Evaluate a boolean comparison between two strings
119pub fn eval_boolean_strings(op: &str, a: &str, b: &str) -> Option<Expression> {
120    let result = match op {
121        "=" | "==" => a == b,
122        "!=" | "<>" => a != b,
123        ">" => a > b,
124        ">=" => a >= b,
125        "<" => a < b,
126        "<=" => a <= b,
127        _ => return None,
128    };
129    Some(if result { bool_true() } else { bool_false() })
130}
131
132/// Expression simplifier
133pub struct Simplifier {
134    _dialect: Option<DialectType>,
135    max_iterations: usize,
136}
137
138impl Simplifier {
139    /// Create a new simplifier
140    pub fn new(dialect: Option<DialectType>) -> Self {
141        Self {
142            _dialect: dialect,
143            max_iterations: 100,
144        }
145    }
146
147    /// Simplify an expression
148    pub fn simplify(&mut self, expression: Expression) -> Expression {
149        // Apply simplifications until no more changes (or max iterations)
150        let mut current = expression;
151        for _ in 0..self.max_iterations {
152            let simplified = self.simplify_once(current.clone());
153            if expressions_equal(&simplified, &current) {
154                return simplified;
155            }
156            current = simplified;
157        }
158        current
159    }
160
161    /// Apply one round of simplifications
162    fn simplify_once(&mut self, expression: Expression) -> Expression {
163        match expression {
164            // Binary logical operations
165            Expression::And(op) => self.simplify_and(*op),
166            Expression::Or(op) => self.simplify_or(*op),
167
168            // NOT operation - De Morgan's laws
169            Expression::Not(op) => self.simplify_not(*op),
170
171            // Arithmetic operations - constant folding
172            Expression::Add(op) => self.simplify_add(*op),
173            Expression::Sub(op) => self.simplify_sub(*op),
174            Expression::Mul(op) => self.simplify_mul(*op),
175            Expression::Div(op) => self.simplify_div(*op),
176
177            // Comparison operations
178            Expression::Eq(op) => self.simplify_comparison(*op, "="),
179            Expression::Neq(op) => self.simplify_comparison(*op, "!="),
180            Expression::Gt(op) => self.simplify_comparison(*op, ">"),
181            Expression::Gte(op) => self.simplify_comparison(*op, ">="),
182            Expression::Lt(op) => self.simplify_comparison(*op, "<"),
183            Expression::Lte(op) => self.simplify_comparison(*op, "<="),
184
185            // Negation
186            Expression::Neg(op) => self.simplify_neg(*op),
187
188            // CASE expression
189            Expression::Case(case) => self.simplify_case(*case),
190
191            // String concatenation
192            Expression::Concat(op) => self.simplify_concat(*op),
193            Expression::ConcatWs(concat_ws) => self.simplify_concat_ws(*concat_ws),
194
195            // Parentheses - remove if unnecessary
196            Expression::Paren(paren) => self.simplify_paren(*paren),
197
198            // Date truncation
199            Expression::DateTrunc(dt) => self.simplify_datetrunc(*dt),
200            Expression::TimestampTrunc(dt) => self.simplify_datetrunc(*dt),
201
202            // Recursively simplify children for other expressions
203            other => self.simplify_children(other),
204        }
205    }
206
207    /// Simplify AND operation
208    fn simplify_and(&mut self, op: BinaryOp) -> Expression {
209        let left = self.simplify_once(op.left);
210        let right = self.simplify_once(op.right);
211
212        // FALSE AND x -> FALSE
213        // x AND FALSE -> FALSE
214        if is_boolean_false(&left) || is_boolean_false(&right) {
215            return bool_false();
216        }
217
218        // 0 AND x -> FALSE (in boolean context)
219        // x AND 0 -> FALSE
220        if is_zero(&left) || is_zero(&right) {
221            return bool_false();
222        }
223
224        // NULL AND NULL -> NULL
225        // NULL AND TRUE -> NULL
226        // TRUE AND NULL -> NULL
227        if (is_null(&left) && is_null(&right))
228            || (is_null(&left) && is_boolean_true(&right))
229            || (is_boolean_true(&left) && is_null(&right))
230        {
231            return null();
232        }
233
234        // TRUE AND x -> x (only when left is actually boolean TRUE)
235        if is_boolean_true(&left) {
236            return right;
237        }
238
239        // x AND TRUE -> x (only when right is actually boolean TRUE)
240        if is_boolean_true(&right) {
241            return left;
242        }
243
244        // A AND NOT A -> FALSE (complement elimination)
245        if is_complement(&left, &right) || is_complement(&right, &left) {
246            return bool_false();
247        }
248
249        // A AND A -> A (idempotent)
250        if expressions_equal(&left, &right) {
251            return left;
252        }
253
254        // Apply absorption rules
255        // A AND (A OR B) -> A
256        // A AND (NOT A OR B) -> A AND B
257        absorb_and_eliminate_and(left, right)
258    }
259
260    /// Simplify OR operation
261    fn simplify_or(&mut self, op: BinaryOp) -> Expression {
262        let left = self.simplify_once(op.left);
263        let right = self.simplify_once(op.right);
264
265        // TRUE OR x -> TRUE (only when left is actually boolean TRUE)
266        if is_boolean_true(&left) {
267            return bool_true();
268        }
269
270        // x OR TRUE -> TRUE (only when right is actually boolean TRUE)
271        if is_boolean_true(&right) {
272            return bool_true();
273        }
274
275        // NULL OR NULL -> NULL
276        // NULL OR FALSE -> NULL
277        // FALSE OR NULL -> NULL
278        if (is_null(&left) && is_null(&right))
279            || (is_null(&left) && is_boolean_false(&right))
280            || (is_boolean_false(&left) && is_null(&right))
281        {
282            return null();
283        }
284
285        // FALSE OR x -> x (only when left is actually boolean FALSE)
286        if is_boolean_false(&left) {
287            return right;
288        }
289
290        // x OR FALSE -> x (only when right is actually boolean FALSE)
291        if is_boolean_false(&right) {
292            return left;
293        }
294
295        // A OR A -> A (idempotent)
296        if expressions_equal(&left, &right) {
297            return left;
298        }
299
300        // Apply absorption rules
301        // A OR (A AND B) -> A
302        // A OR (NOT A AND B) -> A OR B
303        absorb_and_eliminate_or(left, right)
304    }
305
306    /// Simplify NOT operation (De Morgan's laws)
307    fn simplify_not(&mut self, op: UnaryOp) -> Expression {
308        // Check for De Morgan's laws BEFORE simplifying inner expression
309        // This prevents constant folding from eliminating the comparison operator
310        match &op.this {
311            // NOT (a = b) -> a != b
312            Expression::Eq(inner_op) => {
313                let left = self.simplify_once(inner_op.left.clone());
314                let right = self.simplify_once(inner_op.right.clone());
315                return Expression::Neq(Box::new(BinaryOp::new(left, right)));
316            }
317            // NOT (a != b) -> a = b
318            Expression::Neq(inner_op) => {
319                let left = self.simplify_once(inner_op.left.clone());
320                let right = self.simplify_once(inner_op.right.clone());
321                return Expression::Eq(Box::new(BinaryOp::new(left, right)));
322            }
323            // NOT (a > b) -> a <= b
324            Expression::Gt(inner_op) => {
325                let left = self.simplify_once(inner_op.left.clone());
326                let right = self.simplify_once(inner_op.right.clone());
327                return Expression::Lte(Box::new(BinaryOp::new(left, right)));
328            }
329            // NOT (a >= b) -> a < b
330            Expression::Gte(inner_op) => {
331                let left = self.simplify_once(inner_op.left.clone());
332                let right = self.simplify_once(inner_op.right.clone());
333                return Expression::Lt(Box::new(BinaryOp::new(left, right)));
334            }
335            // NOT (a < b) -> a >= b
336            Expression::Lt(inner_op) => {
337                let left = self.simplify_once(inner_op.left.clone());
338                let right = self.simplify_once(inner_op.right.clone());
339                return Expression::Gte(Box::new(BinaryOp::new(left, right)));
340            }
341            // NOT (a <= b) -> a > b
342            Expression::Lte(inner_op) => {
343                let left = self.simplify_once(inner_op.left.clone());
344                let right = self.simplify_once(inner_op.right.clone());
345                return Expression::Gt(Box::new(BinaryOp::new(left, right)));
346            }
347            _ => {}
348        }
349
350        // Now simplify the inner expression for other patterns
351        let inner = self.simplify_once(op.this);
352
353        // NOT NULL -> NULL (with TRUE for SQL semantics)
354        if is_null(&inner) {
355            return null();
356        }
357
358        // NOT TRUE -> FALSE (only for boolean TRUE literal)
359        if is_boolean_true(&inner) {
360            return bool_false();
361        }
362
363        // NOT FALSE -> TRUE (only for boolean FALSE literal)
364        if is_boolean_false(&inner) {
365            return bool_true();
366        }
367
368        // NOT NOT x -> x (double negation elimination)
369        if let Expression::Not(inner_not) = &inner {
370            return inner_not.this.clone();
371        }
372
373        Expression::Not(Box::new(UnaryOp { this: inner }))
374    }
375
376    /// Simplify addition (constant folding)
377    fn simplify_add(&mut self, op: BinaryOp) -> Expression {
378        let left = self.simplify_once(op.left);
379        let right = self.simplify_once(op.right);
380
381        // Try constant folding for numbers
382        if let (Some(a), Some(b)) = (get_number(&left), get_number(&right)) {
383            return Expression::Literal(Literal::Number((a + b).to_string()));
384        }
385
386        // x + 0 -> x
387        if is_zero(&right) {
388            return left;
389        }
390
391        // 0 + x -> x
392        if is_zero(&left) {
393            return right;
394        }
395
396        Expression::Add(Box::new(BinaryOp::new(left, right)))
397    }
398
399    /// Simplify subtraction (constant folding)
400    fn simplify_sub(&mut self, op: BinaryOp) -> Expression {
401        let left = self.simplify_once(op.left);
402        let right = self.simplify_once(op.right);
403
404        // Try constant folding for numbers
405        if let (Some(a), Some(b)) = (get_number(&left), get_number(&right)) {
406            return Expression::Literal(Literal::Number((a - b).to_string()));
407        }
408
409        // x - 0 -> x
410        if is_zero(&right) {
411            return left;
412        }
413
414        // x - x -> 0 (only for literals/constants)
415        if expressions_equal(&left, &right) {
416            if let Expression::Literal(Literal::Number(_)) = &left {
417                return Expression::Literal(Literal::Number("0".to_string()));
418            }
419        }
420
421        Expression::Sub(Box::new(BinaryOp::new(left, right)))
422    }
423
424    /// Simplify multiplication (constant folding)
425    fn simplify_mul(&mut self, op: BinaryOp) -> Expression {
426        let left = self.simplify_once(op.left);
427        let right = self.simplify_once(op.right);
428
429        // Try constant folding for numbers
430        if let (Some(a), Some(b)) = (get_number(&left), get_number(&right)) {
431            return Expression::Literal(Literal::Number((a * b).to_string()));
432        }
433
434        // x * 0 -> 0
435        if is_zero(&right) {
436            return Expression::Literal(Literal::Number("0".to_string()));
437        }
438
439        // 0 * x -> 0
440        if is_zero(&left) {
441            return Expression::Literal(Literal::Number("0".to_string()));
442        }
443
444        // x * 1 -> x
445        if is_one(&right) {
446            return left;
447        }
448
449        // 1 * x -> x
450        if is_one(&left) {
451            return right;
452        }
453
454        Expression::Mul(Box::new(BinaryOp::new(left, right)))
455    }
456
457    /// Simplify division (constant folding)
458    fn simplify_div(&mut self, op: BinaryOp) -> Expression {
459        let left = self.simplify_once(op.left);
460        let right = self.simplify_once(op.right);
461
462        // Try constant folding for numbers (but not integer division)
463        if let (Some(a), Some(b)) = (get_number(&left), get_number(&right)) {
464            // Only fold if both are floats to avoid integer division issues
465            if b != 0.0 && (a.fract() != 0.0 || b.fract() != 0.0) {
466                return Expression::Literal(Literal::Number((a / b).to_string()));
467            }
468        }
469
470        // 0 / x -> 0 (when x != 0)
471        if is_zero(&left) && !is_zero(&right) {
472            return Expression::Literal(Literal::Number("0".to_string()));
473        }
474
475        // x / 1 -> x
476        if is_one(&right) {
477            return left;
478        }
479
480        Expression::Div(Box::new(BinaryOp::new(left, right)))
481    }
482
483    /// Simplify negation
484    fn simplify_neg(&mut self, op: UnaryOp) -> Expression {
485        let inner = self.simplify_once(op.this);
486
487        // -(-x) -> x (double negation)
488        if let Expression::Neg(inner_neg) = inner {
489            return inner_neg.this;
490        }
491
492        // -(number) -> -number
493        if let Some(n) = get_number(&inner) {
494            return Expression::Literal(Literal::Number((-n).to_string()));
495        }
496
497        Expression::Neg(Box::new(UnaryOp { this: inner }))
498    }
499
500    /// Simplify comparison operations (constant folding)
501    fn simplify_comparison(&mut self, op: BinaryOp, operator: &str) -> Expression {
502        let left = self.simplify_once(op.left);
503        let right = self.simplify_once(op.right);
504
505        // Try constant folding for numbers
506        if let (Some(a), Some(b)) = (get_number(&left), get_number(&right)) {
507            if let Some(result) = eval_boolean_nums(operator, a, b) {
508                return result;
509            }
510        }
511
512        // Try constant folding for strings
513        if let (Some(a), Some(b)) = (get_string(&left), get_string(&right)) {
514            if let Some(result) = eval_boolean_strings(operator, &a, &b) {
515                return result;
516            }
517        }
518
519        // For equality, try to solve simple equations (x + 1 = 3 -> x = 2)
520        if operator == "=" {
521            if let Some(simplified) = self.simplify_equality(left.clone(), right.clone()) {
522                return simplified;
523            }
524        }
525
526        // Reconstruct the comparison
527        let new_op = BinaryOp::new(left, right);
528
529        match operator {
530            "=" => Expression::Eq(Box::new(new_op)),
531            "!=" | "<>" => Expression::Neq(Box::new(new_op)),
532            ">" => Expression::Gt(Box::new(new_op)),
533            ">=" => Expression::Gte(Box::new(new_op)),
534            "<" => Expression::Lt(Box::new(new_op)),
535            "<=" => Expression::Lte(Box::new(new_op)),
536            _ => Expression::Eq(Box::new(new_op)),
537        }
538    }
539
540    /// Simplify CASE expression
541    fn simplify_case(&mut self, case: Case) -> Expression {
542        let mut new_whens = Vec::new();
543
544        for (cond, then_expr) in case.whens {
545            let simplified_cond = self.simplify_once(cond);
546
547            // If condition is always true, return the THEN expression
548            if always_true(&simplified_cond) {
549                return self.simplify_once(then_expr);
550            }
551
552            // If condition is always false, skip this WHEN clause
553            if always_false(&simplified_cond) {
554                continue;
555            }
556
557            new_whens.push((simplified_cond, self.simplify_once(then_expr)));
558        }
559
560        // If no WHEN clauses remain, return the ELSE expression (or NULL)
561        if new_whens.is_empty() {
562            return case
563                .else_
564                .map(|e| self.simplify_once(e))
565                .unwrap_or_else(null);
566        }
567
568        Expression::Case(Box::new(Case {
569            operand: case.operand.map(|e| self.simplify_once(e)),
570            whens: new_whens,
571            else_: case.else_.map(|e| self.simplify_once(e)),
572            comments: Vec::new(),
573        }))
574    }
575
576    /// Simplify string concatenation (Concat is || operator)
577    ///
578    /// Folds adjacent string literals:
579    /// - 'a' || 'b' -> 'ab'
580    /// - 'a' || 'b' || 'c' -> 'abc'
581    /// - '' || x -> x
582    /// - x || '' -> x
583    fn simplify_concat(&mut self, op: BinaryOp) -> Expression {
584        let left = self.simplify_once(op.left);
585        let right = self.simplify_once(op.right);
586
587        // Fold two string literals: 'a' || 'b' -> 'ab'
588        if let (Some(a), Some(b)) = (get_string(&left), get_string(&right)) {
589            return Expression::Literal(Literal::String(format!("{}{}", a, b)));
590        }
591
592        // '' || x -> x
593        if let Some(s) = get_string(&left) {
594            if s.is_empty() {
595                return right;
596            }
597        }
598
599        // x || '' -> x
600        if let Some(s) = get_string(&right) {
601            if s.is_empty() {
602                return left;
603            }
604        }
605
606        // NULL || x -> NULL, x || NULL -> NULL (SQL string concat semantics)
607        if is_null(&left) || is_null(&right) {
608            return null();
609        }
610
611        Expression::Concat(Box::new(BinaryOp::new(left, right)))
612    }
613
614    /// Simplify CONCAT_WS function
615    ///
616    /// CONCAT_WS(sep, a, b, c) -> concatenates with separator, skipping NULLs
617    /// - CONCAT_WS(',', 'a', 'b') -> 'a,b' (when all are literals)
618    /// - CONCAT_WS(',', 'a', NULL, 'b') -> 'a,b' (NULLs are skipped)
619    /// - CONCAT_WS(NULL, ...) -> NULL
620    fn simplify_concat_ws(&mut self, concat_ws: ConcatWs) -> Expression {
621        let separator = self.simplify_once(concat_ws.separator);
622
623        // If separator is NULL, result is NULL
624        if is_null(&separator) {
625            return null();
626        }
627
628        let expressions: Vec<Expression> = concat_ws
629            .expressions
630            .into_iter()
631            .map(|e| self.simplify_once(e))
632            .filter(|e| !is_null(e)) // Skip NULL values
633            .collect();
634
635        // If no expressions remain, return empty string
636        if expressions.is_empty() {
637            return Expression::Literal(Literal::String(String::new()));
638        }
639
640        // Try to fold if all are string literals
641        if let Some(sep) = get_string(&separator) {
642            let all_strings: Option<Vec<String>> =
643                expressions.iter().map(|e| get_string(e)).collect();
644
645            if let Some(strings) = all_strings {
646                return Expression::Literal(Literal::String(strings.join(&sep)));
647            }
648        }
649
650        // Return simplified CONCAT_WS
651        Expression::ConcatWs(Box::new(ConcatWs {
652            separator,
653            expressions,
654        }))
655    }
656
657    /// Simplify parentheses
658    ///
659    /// Remove unnecessary parentheses:
660    /// - (x) -> x when x is a literal, column, or already parenthesized
661    /// - ((x)) -> (x) -> x (recursive simplification)
662    fn simplify_paren(&mut self, paren: Paren) -> Expression {
663        let inner = self.simplify_once(paren.this);
664
665        // If inner is a literal, column, boolean, null, or already parenthesized,
666        // we can remove the parentheses
667        match &inner {
668            Expression::Literal(_)
669            | Expression::Boolean(_)
670            | Expression::Null(_)
671            | Expression::Column(_)
672            | Expression::Paren(_) => inner,
673            // For other expressions, keep the parentheses
674            _ => Expression::Paren(Box::new(Paren {
675                this: inner,
676                trailing_comments: paren.trailing_comments,
677            })),
678        }
679    }
680
681    /// Simplify DATE_TRUNC and TIMESTAMP_TRUNC
682    ///
683    /// Currently just simplifies children and passes through.
684    /// Future: could fold DATE_TRUNC('day', '2024-01-15') -> '2024-01-15'
685    fn simplify_datetrunc(&mut self, dt: DateTruncFunc) -> Expression {
686        let inner = self.simplify_once(dt.this);
687
688        // For now, just return with simplified inner expression
689        // A more advanced implementation would fold constant date/timestamps
690        Expression::DateTrunc(Box::new(DateTruncFunc {
691            this: inner,
692            unit: dt.unit,
693        }))
694    }
695
696    /// Simplify equality with arithmetic (solve simple equations)
697    ///
698    /// - x + 1 = 3 -> x = 2
699    /// - x - 1 = 3 -> x = 4
700    /// - x * 2 = 6 -> x = 3 (only when divisible)
701    /// - 1 + x = 3 -> x = 2 (commutative)
702    fn simplify_equality(&mut self, left: Expression, right: Expression) -> Option<Expression> {
703        // Only works when right side is a constant
704        let right_val = get_number(&right)?;
705
706        // Check if left side is arithmetic with one constant
707        match left {
708            Expression::Add(ref op) => {
709                // x + c = r -> x = r - c
710                if let Some(c) = get_number(&op.right) {
711                    let new_right =
712                        Expression::Literal(Literal::Number((right_val - c).to_string()));
713                    return Some(Expression::Eq(Box::new(BinaryOp::new(
714                        op.left.clone(),
715                        new_right,
716                    ))));
717                }
718                // c + x = r -> x = r - c
719                if let Some(c) = get_number(&op.left) {
720                    let new_right =
721                        Expression::Literal(Literal::Number((right_val - c).to_string()));
722                    return Some(Expression::Eq(Box::new(BinaryOp::new(
723                        op.right.clone(),
724                        new_right,
725                    ))));
726                }
727            }
728            Expression::Sub(ref op) => {
729                // x - c = r -> x = r + c
730                if let Some(c) = get_number(&op.right) {
731                    let new_right =
732                        Expression::Literal(Literal::Number((right_val + c).to_string()));
733                    return Some(Expression::Eq(Box::new(BinaryOp::new(
734                        op.left.clone(),
735                        new_right,
736                    ))));
737                }
738                // c - x = r -> x = c - r
739                if let Some(c) = get_number(&op.left) {
740                    let new_right =
741                        Expression::Literal(Literal::Number((c - right_val).to_string()));
742                    return Some(Expression::Eq(Box::new(BinaryOp::new(
743                        op.right.clone(),
744                        new_right,
745                    ))));
746                }
747            }
748            Expression::Mul(ref op) => {
749                // x * c = r -> x = r / c (only for non-zero c and when divisible)
750                if let Some(c) = get_number(&op.right) {
751                    if c != 0.0 && right_val % c == 0.0 {
752                        let new_right =
753                            Expression::Literal(Literal::Number((right_val / c).to_string()));
754                        return Some(Expression::Eq(Box::new(BinaryOp::new(
755                            op.left.clone(),
756                            new_right,
757                        ))));
758                    }
759                }
760                // c * x = r -> x = r / c
761                if let Some(c) = get_number(&op.left) {
762                    if c != 0.0 && right_val % c == 0.0 {
763                        let new_right =
764                            Expression::Literal(Literal::Number((right_val / c).to_string()));
765                        return Some(Expression::Eq(Box::new(BinaryOp::new(
766                            op.right.clone(),
767                            new_right,
768                        ))));
769                    }
770                }
771            }
772            _ => {}
773        }
774
775        None
776    }
777
778    /// Recursively simplify children of an expression
779    fn simplify_children(&mut self, expr: Expression) -> Expression {
780        // For expressions we don't have specific simplification rules for,
781        // we still want to simplify their children
782        match expr {
783            Expression::Alias(mut alias) => {
784                alias.this = self.simplify_once(alias.this);
785                Expression::Alias(alias)
786            }
787            Expression::Between(mut between) => {
788                between.this = self.simplify_once(between.this);
789                between.low = self.simplify_once(between.low);
790                between.high = self.simplify_once(between.high);
791                Expression::Between(between)
792            }
793            Expression::In(mut in_expr) => {
794                in_expr.this = self.simplify_once(in_expr.this);
795                in_expr.expressions = in_expr
796                    .expressions
797                    .into_iter()
798                    .map(|e| self.simplify_once(e))
799                    .collect();
800                Expression::In(in_expr)
801            }
802            Expression::Function(mut func) => {
803                func.args = func
804                    .args
805                    .into_iter()
806                    .map(|e| self.simplify_once(e))
807                    .collect();
808                Expression::Function(func)
809            }
810            // For other expressions, return as-is for now
811            other => other,
812        }
813    }
814}
815
816/// Check if expression equals 1
817fn is_one(expr: &Expression) -> bool {
818    match expr {
819        Expression::Literal(Literal::Number(n)) => {
820            if let Ok(num) = n.parse::<f64>() {
821                num == 1.0
822            } else {
823                false
824            }
825        }
826        _ => false,
827    }
828}
829
830/// Get numeric value from expression if it's a number literal
831fn get_number(expr: &Expression) -> Option<f64> {
832    match expr {
833        Expression::Literal(Literal::Number(n)) => n.parse().ok(),
834        _ => None,
835    }
836}
837
838/// Get string value from expression if it's a string literal
839fn get_string(expr: &Expression) -> Option<String> {
840    match expr {
841        Expression::Literal(Literal::String(s)) => Some(s.clone()),
842        _ => None,
843    }
844}
845
846/// Check if two expressions are structurally equal
847/// This is a simplified comparison - a full implementation would need deep comparison
848fn expressions_equal(a: &Expression, b: &Expression) -> bool {
849    // For now, use Debug representation for comparison
850    // A proper implementation would do structural comparison
851    format!("{:?}", a) == format!("{:?}", b)
852}
853
854/// Flatten nested AND expressions into a list of operands
855/// e.g., (A AND (B AND C)) -> [A, B, C]
856fn flatten_and(expr: &Expression) -> Vec<Expression> {
857    match expr {
858        Expression::And(op) => {
859            let mut result = flatten_and(&op.left);
860            result.extend(flatten_and(&op.right));
861            result
862        }
863        other => vec![other.clone()],
864    }
865}
866
867/// Flatten nested OR expressions into a list of operands
868/// e.g., (A OR (B OR C)) -> [A, B, C]
869fn flatten_or(expr: &Expression) -> Vec<Expression> {
870    match expr {
871        Expression::Or(op) => {
872            let mut result = flatten_or(&op.left);
873            result.extend(flatten_or(&op.right));
874            result
875        }
876        other => vec![other.clone()],
877    }
878}
879
880/// Rebuild an AND expression from a list of operands
881fn rebuild_and(operands: Vec<Expression>) -> Expression {
882    if operands.is_empty() {
883        return bool_true(); // Empty AND is TRUE
884    }
885    let mut result = operands.into_iter();
886    let first = result.next().unwrap();
887    result.fold(first, |acc, op| {
888        Expression::And(Box::new(BinaryOp::new(acc, op)))
889    })
890}
891
892/// Rebuild an OR expression from a list of operands
893fn rebuild_or(operands: Vec<Expression>) -> Expression {
894    if operands.is_empty() {
895        return bool_false(); // Empty OR is FALSE
896    }
897    let mut result = operands.into_iter();
898    let first = result.next().unwrap();
899    result.fold(first, |acc, op| {
900        Expression::Or(Box::new(BinaryOp::new(acc, op)))
901    })
902}
903
904/// Get the inner expression of a NOT, if it is one
905fn get_not_inner(expr: &Expression) -> Option<&Expression> {
906    match expr {
907        Expression::Not(op) => Some(&op.this),
908        _ => None,
909    }
910}
911
912/// Apply Boolean absorption and elimination rules to an AND expression
913///
914/// Absorption:
915///   A AND (A OR B) -> A
916///   A AND (NOT A OR B) -> A AND B
917///
918/// Elimination:
919///   (A OR B) AND (A OR NOT B) -> A
920pub fn absorb_and_eliminate_and(left: Expression, right: Expression) -> Expression {
921    // Flatten both sides
922    let left_ops = flatten_and(&left);
923    let right_ops = flatten_and(&right);
924    let all_ops: Vec<Expression> = left_ops.iter().chain(right_ops.iter()).cloned().collect();
925
926    // Build a set of string representations for quick lookup
927    let op_strings: std::collections::HashSet<String> = all_ops.iter().map(gen).collect();
928
929    let mut result_ops: Vec<Expression> = Vec::new();
930    let mut absorbed = std::collections::HashSet::new();
931
932    for (i, op) in all_ops.iter().enumerate() {
933        let op_str = gen(op);
934
935        // Skip if already absorbed
936        if absorbed.contains(&op_str) {
937            continue;
938        }
939
940        // Check if this is an OR expression (potential absorption target)
941        if let Expression::Or(_) = op {
942            let or_operands = flatten_or(op);
943
944            // Absorption: A AND (A OR B) -> A
945            // Check if any OR operand is already in our AND operands
946            let absorbed_by_existing = or_operands.iter().any(|or_op| {
947                let or_op_str = gen(or_op);
948                // Check if this OR operand exists in other AND operands (not this OR itself)
949                all_ops
950                    .iter()
951                    .enumerate()
952                    .any(|(j, other)| i != j && gen(other) == or_op_str)
953            });
954
955            if absorbed_by_existing {
956                // This OR is absorbed, skip it
957                absorbed.insert(op_str);
958                continue;
959            }
960
961            // Absorption with complement: A AND (NOT A OR B) -> A AND B
962            // Check if any OR operand's complement is in our AND operands
963            let mut remaining_or_ops: Vec<Expression> = Vec::new();
964            let mut had_complement_absorption = false;
965
966            for or_op in or_operands {
967                let complement_str = if let Some(inner) = get_not_inner(&or_op) {
968                    // or_op is NOT X, complement is X
969                    gen(inner)
970                } else {
971                    // or_op is X, complement is NOT X
972                    format!("NOT {}", gen(&or_op))
973                };
974
975                // Check if complement exists in our AND operands
976                let has_complement = all_ops
977                    .iter()
978                    .enumerate()
979                    .any(|(j, other)| i != j && gen(other) == complement_str)
980                    || op_strings.contains(&complement_str);
981
982                if has_complement {
983                    // This OR operand's complement exists, so this term becomes TRUE in AND context
984                    // NOT A OR B, where A exists, becomes TRUE OR B (when A is true) or B (when A is false)
985                    // Actually: A AND (NOT A OR B) -> A AND B, so we drop NOT A from the OR
986                    had_complement_absorption = true;
987                    // Drop this operand from OR
988                } else {
989                    remaining_or_ops.push(or_op);
990                }
991            }
992
993            if had_complement_absorption {
994                if remaining_or_ops.is_empty() {
995                    // All OR operands were absorbed, the OR becomes TRUE
996                    // A AND TRUE -> A, so we just skip adding this
997                    absorbed.insert(op_str);
998                    continue;
999                } else if remaining_or_ops.len() == 1 {
1000                    // Single remaining operand
1001                    result_ops.push(remaining_or_ops.into_iter().next().unwrap());
1002                    absorbed.insert(op_str);
1003                    continue;
1004                } else {
1005                    // Rebuild the OR with remaining operands
1006                    result_ops.push(rebuild_or(remaining_or_ops));
1007                    absorbed.insert(op_str);
1008                    continue;
1009                }
1010            }
1011        }
1012
1013        result_ops.push(op.clone());
1014    }
1015
1016    // Deduplicate
1017    let mut seen = std::collections::HashSet::new();
1018    result_ops.retain(|op| seen.insert(gen(op)));
1019
1020    if result_ops.is_empty() {
1021        bool_true()
1022    } else {
1023        rebuild_and(result_ops)
1024    }
1025}
1026
1027/// Apply Boolean absorption and elimination rules to an OR expression
1028///
1029/// Absorption:
1030///   A OR (A AND B) -> A
1031///   A OR (NOT A AND B) -> A OR B
1032///
1033/// Elimination:
1034///   (A AND B) OR (A AND NOT B) -> A
1035pub fn absorb_and_eliminate_or(left: Expression, right: Expression) -> Expression {
1036    // Flatten both sides
1037    let left_ops = flatten_or(&left);
1038    let right_ops = flatten_or(&right);
1039    let all_ops: Vec<Expression> = left_ops.iter().chain(right_ops.iter()).cloned().collect();
1040
1041    // Build a set of string representations for quick lookup
1042    let op_strings: std::collections::HashSet<String> = all_ops.iter().map(gen).collect();
1043
1044    let mut result_ops: Vec<Expression> = Vec::new();
1045    let mut absorbed = std::collections::HashSet::new();
1046
1047    for (i, op) in all_ops.iter().enumerate() {
1048        let op_str = gen(op);
1049
1050        // Skip if already absorbed
1051        if absorbed.contains(&op_str) {
1052            continue;
1053        }
1054
1055        // Check if this is an AND expression (potential absorption target)
1056        if let Expression::And(_) = op {
1057            let and_operands = flatten_and(op);
1058
1059            // Absorption: A OR (A AND B) -> A
1060            // Check if any AND operand is already in our OR operands
1061            let absorbed_by_existing = and_operands.iter().any(|and_op| {
1062                let and_op_str = gen(and_op);
1063                // Check if this AND operand exists in other OR operands (not this AND itself)
1064                all_ops
1065                    .iter()
1066                    .enumerate()
1067                    .any(|(j, other)| i != j && gen(other) == and_op_str)
1068            });
1069
1070            if absorbed_by_existing {
1071                // This AND is absorbed, skip it
1072                absorbed.insert(op_str);
1073                continue;
1074            }
1075
1076            // Absorption with complement: A OR (NOT A AND B) -> A OR B
1077            // Check if any AND operand's complement is in our OR operands
1078            let mut remaining_and_ops: Vec<Expression> = Vec::new();
1079            let mut had_complement_absorption = false;
1080
1081            for and_op in and_operands {
1082                let complement_str = if let Some(inner) = get_not_inner(&and_op) {
1083                    // and_op is NOT X, complement is X
1084                    gen(inner)
1085                } else {
1086                    // and_op is X, complement is NOT X
1087                    format!("NOT {}", gen(&and_op))
1088                };
1089
1090                // Check if complement exists in our OR operands
1091                let has_complement = all_ops
1092                    .iter()
1093                    .enumerate()
1094                    .any(|(j, other)| i != j && gen(other) == complement_str)
1095                    || op_strings.contains(&complement_str);
1096
1097                if has_complement {
1098                    // This AND operand's complement exists, so this term becomes FALSE in OR context
1099                    // A OR (NOT A AND B) -> A OR B, so we drop NOT A from the AND
1100                    had_complement_absorption = true;
1101                    // Drop this operand from AND
1102                } else {
1103                    remaining_and_ops.push(and_op);
1104                }
1105            }
1106
1107            if had_complement_absorption {
1108                if remaining_and_ops.is_empty() {
1109                    // All AND operands were absorbed, the AND becomes FALSE
1110                    // A OR FALSE -> A, so we just skip adding this
1111                    absorbed.insert(op_str);
1112                    continue;
1113                } else if remaining_and_ops.len() == 1 {
1114                    // Single remaining operand
1115                    result_ops.push(remaining_and_ops.into_iter().next().unwrap());
1116                    absorbed.insert(op_str);
1117                    continue;
1118                } else {
1119                    // Rebuild the AND with remaining operands
1120                    result_ops.push(rebuild_and(remaining_and_ops));
1121                    absorbed.insert(op_str);
1122                    continue;
1123                }
1124            }
1125        }
1126
1127        result_ops.push(op.clone());
1128    }
1129
1130    // Deduplicate
1131    let mut seen = std::collections::HashSet::new();
1132    result_ops.retain(|op| seen.insert(gen(op)));
1133
1134    if result_ops.is_empty() {
1135        bool_false()
1136    } else {
1137        rebuild_or(result_ops)
1138    }
1139}
1140
1141/// Generate a simple string representation of an expression for sorting/deduping
1142pub fn gen(expr: &Expression) -> String {
1143    match expr {
1144        Expression::Literal(lit) => match lit {
1145            Literal::String(s) => format!("'{}'", s),
1146            Literal::Number(n) => n.clone(),
1147            _ => format!("{:?}", lit),
1148        },
1149        Expression::Boolean(b) => if b.value { "TRUE" } else { "FALSE" }.to_string(),
1150        Expression::Null(_) => "NULL".to_string(),
1151        Expression::Column(col) => {
1152            if let Some(ref table) = col.table {
1153                format!("{}.{}", table.name, col.name.name)
1154            } else {
1155                col.name.name.clone()
1156            }
1157        }
1158        Expression::And(op) => format!("({} AND {})", gen(&op.left), gen(&op.right)),
1159        Expression::Or(op) => format!("({} OR {})", gen(&op.left), gen(&op.right)),
1160        Expression::Not(op) => format!("NOT {}", gen(&op.this)),
1161        Expression::Eq(op) => format!("{} = {}", gen(&op.left), gen(&op.right)),
1162        Expression::Neq(op) => format!("{} <> {}", gen(&op.left), gen(&op.right)),
1163        Expression::Gt(op) => format!("{} > {}", gen(&op.left), gen(&op.right)),
1164        Expression::Gte(op) => format!("{} >= {}", gen(&op.left), gen(&op.right)),
1165        Expression::Lt(op) => format!("{} < {}", gen(&op.left), gen(&op.right)),
1166        Expression::Lte(op) => format!("{} <= {}", gen(&op.left), gen(&op.right)),
1167        Expression::Add(op) => format!("{} + {}", gen(&op.left), gen(&op.right)),
1168        Expression::Sub(op) => format!("{} - {}", gen(&op.left), gen(&op.right)),
1169        Expression::Mul(op) => format!("{} * {}", gen(&op.left), gen(&op.right)),
1170        Expression::Div(op) => format!("{} / {}", gen(&op.left), gen(&op.right)),
1171        Expression::Function(f) => {
1172            let args: Vec<String> = f.args.iter().map(|a| gen(a)).collect();
1173            format!("{}({})", f.name.to_uppercase(), args.join(", "))
1174        }
1175        _ => format!("{:?}", expr),
1176    }
1177}
1178
1179#[cfg(test)]
1180mod tests {
1181    use super::*;
1182
1183    fn make_int(val: i64) -> Expression {
1184        Expression::Literal(Literal::Number(val.to_string()))
1185    }
1186
1187    fn make_string(val: &str) -> Expression {
1188        Expression::Literal(Literal::String(val.to_string()))
1189    }
1190
1191    fn make_bool(val: bool) -> Expression {
1192        Expression::Boolean(BooleanLiteral { value: val })
1193    }
1194
1195    fn make_column(name: &str) -> Expression {
1196        use crate::expressions::{Column, Identifier};
1197        Expression::Column(Column {
1198            name: Identifier::new(name),
1199            table: None,
1200            join_mark: false,
1201            trailing_comments: vec![],
1202        })
1203    }
1204
1205    #[test]
1206    fn test_always_true_false() {
1207        assert!(always_true(&make_bool(true)));
1208        assert!(!always_true(&make_bool(false)));
1209        assert!(always_true(&make_int(1)));
1210        assert!(!always_true(&make_int(0)));
1211
1212        assert!(always_false(&make_bool(false)));
1213        assert!(!always_false(&make_bool(true)));
1214        assert!(always_false(&null()));
1215        assert!(always_false(&make_int(0)));
1216    }
1217
1218    #[test]
1219    fn test_simplify_and_with_true() {
1220        let mut simplifier = Simplifier::new(None);
1221
1222        // TRUE AND TRUE -> TRUE
1223        let expr = Expression::And(Box::new(BinaryOp::new(make_bool(true), make_bool(true))));
1224        let result = simplifier.simplify(expr);
1225        assert!(always_true(&result));
1226
1227        // TRUE AND FALSE -> FALSE
1228        let expr = Expression::And(Box::new(BinaryOp::new(make_bool(true), make_bool(false))));
1229        let result = simplifier.simplify(expr);
1230        assert!(always_false(&result));
1231
1232        // TRUE AND x -> x
1233        let x = make_int(42);
1234        let expr = Expression::And(Box::new(BinaryOp::new(make_bool(true), x.clone())));
1235        let result = simplifier.simplify(expr);
1236        assert_eq!(format!("{:?}", result), format!("{:?}", x));
1237    }
1238
1239    #[test]
1240    fn test_simplify_or_with_false() {
1241        let mut simplifier = Simplifier::new(None);
1242
1243        // FALSE OR FALSE -> FALSE
1244        let expr = Expression::Or(Box::new(BinaryOp::new(make_bool(false), make_bool(false))));
1245        let result = simplifier.simplify(expr);
1246        assert!(always_false(&result));
1247
1248        // FALSE OR TRUE -> TRUE
1249        let expr = Expression::Or(Box::new(BinaryOp::new(make_bool(false), make_bool(true))));
1250        let result = simplifier.simplify(expr);
1251        assert!(always_true(&result));
1252
1253        // FALSE OR x -> x
1254        let x = make_int(42);
1255        let expr = Expression::Or(Box::new(BinaryOp::new(make_bool(false), x.clone())));
1256        let result = simplifier.simplify(expr);
1257        assert_eq!(format!("{:?}", result), format!("{:?}", x));
1258    }
1259
1260    #[test]
1261    fn test_simplify_not() {
1262        let mut simplifier = Simplifier::new(None);
1263
1264        // NOT TRUE -> FALSE
1265        let expr = Expression::Not(Box::new(UnaryOp::new(make_bool(true))));
1266        let result = simplifier.simplify(expr);
1267        assert!(is_false(&result));
1268
1269        // NOT FALSE -> TRUE
1270        let expr = Expression::Not(Box::new(UnaryOp::new(make_bool(false))));
1271        let result = simplifier.simplify(expr);
1272        assert!(always_true(&result));
1273
1274        // NOT NOT x -> x
1275        let x = make_int(42);
1276        let inner_not = Expression::Not(Box::new(UnaryOp::new(x.clone())));
1277        let expr = Expression::Not(Box::new(UnaryOp::new(inner_not)));
1278        let result = simplifier.simplify(expr);
1279        assert_eq!(format!("{:?}", result), format!("{:?}", x));
1280    }
1281
1282    #[test]
1283    fn test_simplify_demorgan_comparison() {
1284        let mut simplifier = Simplifier::new(None);
1285
1286        // NOT (a = b) -> a != b (using columns to avoid constant folding)
1287        let a = make_column("a");
1288        let b = make_column("b");
1289        let eq = Expression::Eq(Box::new(BinaryOp::new(a.clone(), b.clone())));
1290        let expr = Expression::Not(Box::new(UnaryOp::new(eq)));
1291        let result = simplifier.simplify(expr);
1292        assert!(matches!(result, Expression::Neq(_)));
1293
1294        // NOT (a > b) -> a <= b
1295        let gt = Expression::Gt(Box::new(BinaryOp::new(a, b)));
1296        let expr = Expression::Not(Box::new(UnaryOp::new(gt)));
1297        let result = simplifier.simplify(expr);
1298        assert!(matches!(result, Expression::Lte(_)));
1299    }
1300
1301    #[test]
1302    fn test_constant_folding_add() {
1303        let mut simplifier = Simplifier::new(None);
1304
1305        // 1 + 2 -> 3
1306        let expr = Expression::Add(Box::new(BinaryOp::new(make_int(1), make_int(2))));
1307        let result = simplifier.simplify(expr);
1308        assert_eq!(get_number(&result), Some(3.0));
1309
1310        // x + 0 -> x
1311        let x = make_int(42);
1312        let expr = Expression::Add(Box::new(BinaryOp::new(x.clone(), make_int(0))));
1313        let result = simplifier.simplify(expr);
1314        assert_eq!(format!("{:?}", result), format!("{:?}", x));
1315    }
1316
1317    #[test]
1318    fn test_constant_folding_mul() {
1319        let mut simplifier = Simplifier::new(None);
1320
1321        // 3 * 4 -> 12
1322        let expr = Expression::Mul(Box::new(BinaryOp::new(make_int(3), make_int(4))));
1323        let result = simplifier.simplify(expr);
1324        assert_eq!(get_number(&result), Some(12.0));
1325
1326        // x * 0 -> 0
1327        let x = make_int(42);
1328        let expr = Expression::Mul(Box::new(BinaryOp::new(x, make_int(0))));
1329        let result = simplifier.simplify(expr);
1330        assert_eq!(get_number(&result), Some(0.0));
1331
1332        // x * 1 -> x
1333        let x = make_int(42);
1334        let expr = Expression::Mul(Box::new(BinaryOp::new(x.clone(), make_int(1))));
1335        let result = simplifier.simplify(expr);
1336        assert_eq!(format!("{:?}", result), format!("{:?}", x));
1337    }
1338
1339    #[test]
1340    fn test_constant_folding_comparison() {
1341        let mut simplifier = Simplifier::new(None);
1342
1343        // 1 = 1 -> TRUE
1344        let expr = Expression::Eq(Box::new(BinaryOp::new(make_int(1), make_int(1))));
1345        let result = simplifier.simplify(expr);
1346        assert!(always_true(&result));
1347
1348        // 1 = 2 -> FALSE
1349        let expr = Expression::Eq(Box::new(BinaryOp::new(make_int(1), make_int(2))));
1350        let result = simplifier.simplify(expr);
1351        assert!(is_false(&result));
1352
1353        // 3 > 2 -> TRUE
1354        let expr = Expression::Gt(Box::new(BinaryOp::new(make_int(3), make_int(2))));
1355        let result = simplifier.simplify(expr);
1356        assert!(always_true(&result));
1357
1358        // 'a' = 'a' -> TRUE
1359        let expr = Expression::Eq(Box::new(BinaryOp::new(
1360            make_string("abc"),
1361            make_string("abc"),
1362        )));
1363        let result = simplifier.simplify(expr);
1364        assert!(always_true(&result));
1365    }
1366
1367    #[test]
1368    fn test_simplify_negation() {
1369        let mut simplifier = Simplifier::new(None);
1370
1371        // -(-5) -> 5
1372        let inner = Expression::Neg(Box::new(UnaryOp::new(make_int(5))));
1373        let expr = Expression::Neg(Box::new(UnaryOp::new(inner)));
1374        let result = simplifier.simplify(expr);
1375        assert_eq!(get_number(&result), Some(5.0));
1376
1377        // -(3) -> -3
1378        let expr = Expression::Neg(Box::new(UnaryOp::new(make_int(3))));
1379        let result = simplifier.simplify(expr);
1380        assert_eq!(get_number(&result), Some(-3.0));
1381    }
1382
1383    #[test]
1384    fn test_gen_simple() {
1385        assert_eq!(gen(&make_int(42)), "42");
1386        assert_eq!(gen(&make_string("hello")), "'hello'");
1387        assert_eq!(gen(&make_bool(true)), "TRUE");
1388        assert_eq!(gen(&make_bool(false)), "FALSE");
1389        assert_eq!(gen(&null()), "NULL");
1390    }
1391
1392    #[test]
1393    fn test_gen_operations() {
1394        let add = Expression::Add(Box::new(BinaryOp::new(make_int(1), make_int(2))));
1395        assert_eq!(gen(&add), "1 + 2");
1396
1397        let and = Expression::And(Box::new(BinaryOp::new(make_bool(true), make_bool(false))));
1398        assert_eq!(gen(&and), "(TRUE AND FALSE)");
1399    }
1400
1401    #[test]
1402    fn test_complement_elimination() {
1403        let mut simplifier = Simplifier::new(None);
1404
1405        // x AND NOT x -> FALSE
1406        let x = make_int(42);
1407        let not_x = Expression::Not(Box::new(UnaryOp::new(x.clone())));
1408        let expr = Expression::And(Box::new(BinaryOp::new(x, not_x)));
1409        let result = simplifier.simplify(expr);
1410        assert!(is_false(&result));
1411    }
1412
1413    #[test]
1414    fn test_idempotent() {
1415        let mut simplifier = Simplifier::new(None);
1416
1417        // x AND x -> x
1418        let x = make_int(42);
1419        let expr = Expression::And(Box::new(BinaryOp::new(x.clone(), x.clone())));
1420        let result = simplifier.simplify(expr);
1421        assert_eq!(format!("{:?}", result), format!("{:?}", x));
1422
1423        // x OR x -> x
1424        let x = make_int(42);
1425        let expr = Expression::Or(Box::new(BinaryOp::new(x.clone(), x.clone())));
1426        let result = simplifier.simplify(expr);
1427        assert_eq!(format!("{:?}", result), format!("{:?}", x));
1428    }
1429
1430    #[test]
1431    fn test_absorption_and() {
1432        let mut simplifier = Simplifier::new(None);
1433
1434        // A AND (A OR B) -> A
1435        let a = make_column("a");
1436        let b = make_column("b");
1437        let a_or_b = Expression::Or(Box::new(BinaryOp::new(a.clone(), b.clone())));
1438        let expr = Expression::And(Box::new(BinaryOp::new(a.clone(), a_or_b)));
1439        let result = simplifier.simplify(expr);
1440        // Result should be just A
1441        assert_eq!(gen(&result), gen(&a));
1442    }
1443
1444    #[test]
1445    fn test_absorption_or() {
1446        let mut simplifier = Simplifier::new(None);
1447
1448        // A OR (A AND B) -> A
1449        let a = make_column("a");
1450        let b = make_column("b");
1451        let a_and_b = Expression::And(Box::new(BinaryOp::new(a.clone(), b.clone())));
1452        let expr = Expression::Or(Box::new(BinaryOp::new(a.clone(), a_and_b)));
1453        let result = simplifier.simplify(expr);
1454        // Result should be just A
1455        assert_eq!(gen(&result), gen(&a));
1456    }
1457
1458    #[test]
1459    fn test_absorption_with_complement_and() {
1460        let mut simplifier = Simplifier::new(None);
1461
1462        // A AND (NOT A OR B) -> A AND B
1463        let a = make_column("a");
1464        let b = make_column("b");
1465        let not_a = Expression::Not(Box::new(UnaryOp::new(a.clone())));
1466        let not_a_or_b = Expression::Or(Box::new(BinaryOp::new(not_a, b.clone())));
1467        let expr = Expression::And(Box::new(BinaryOp::new(a.clone(), not_a_or_b)));
1468        let result = simplifier.simplify(expr);
1469        // Result should be A AND B
1470        let expected = Expression::And(Box::new(BinaryOp::new(a, b)));
1471        assert_eq!(gen(&result), gen(&expected));
1472    }
1473
1474    #[test]
1475    fn test_absorption_with_complement_or() {
1476        let mut simplifier = Simplifier::new(None);
1477
1478        // A OR (NOT A AND B) -> A OR B
1479        let a = make_column("a");
1480        let b = make_column("b");
1481        let not_a = Expression::Not(Box::new(UnaryOp::new(a.clone())));
1482        let not_a_and_b = Expression::And(Box::new(BinaryOp::new(not_a, b.clone())));
1483        let expr = Expression::Or(Box::new(BinaryOp::new(a.clone(), not_a_and_b)));
1484        let result = simplifier.simplify(expr);
1485        // Result should be A OR B
1486        let expected = Expression::Or(Box::new(BinaryOp::new(a, b)));
1487        assert_eq!(gen(&result), gen(&expected));
1488    }
1489
1490    #[test]
1491    fn test_flatten_and() {
1492        // (A AND (B AND C)) should flatten to [A, B, C]
1493        let a = make_column("a");
1494        let b = make_column("b");
1495        let c = make_column("c");
1496        let b_and_c = Expression::And(Box::new(BinaryOp::new(b.clone(), c.clone())));
1497        let expr = Expression::And(Box::new(BinaryOp::new(a.clone(), b_and_c)));
1498        let flattened = flatten_and(&expr);
1499        assert_eq!(flattened.len(), 3);
1500        assert_eq!(gen(&flattened[0]), "a");
1501        assert_eq!(gen(&flattened[1]), "b");
1502        assert_eq!(gen(&flattened[2]), "c");
1503    }
1504
1505    #[test]
1506    fn test_flatten_or() {
1507        // (A OR (B OR C)) should flatten to [A, B, C]
1508        let a = make_column("a");
1509        let b = make_column("b");
1510        let c = make_column("c");
1511        let b_or_c = Expression::Or(Box::new(BinaryOp::new(b.clone(), c.clone())));
1512        let expr = Expression::Or(Box::new(BinaryOp::new(a.clone(), b_or_c)));
1513        let flattened = flatten_or(&expr);
1514        assert_eq!(flattened.len(), 3);
1515        assert_eq!(gen(&flattened[0]), "a");
1516        assert_eq!(gen(&flattened[1]), "b");
1517        assert_eq!(gen(&flattened[2]), "c");
1518    }
1519
1520    #[test]
1521    fn test_simplify_concat() {
1522        let mut simplifier = Simplifier::new(None);
1523
1524        // 'a' || 'b' -> 'ab'
1525        let expr = Expression::Concat(Box::new(BinaryOp::new(
1526            make_string("hello"),
1527            make_string("world"),
1528        )));
1529        let result = simplifier.simplify(expr);
1530        assert_eq!(get_string(&result), Some("helloworld".to_string()));
1531
1532        // '' || x -> x
1533        let x = make_string("test");
1534        let expr = Expression::Concat(Box::new(BinaryOp::new(make_string(""), x.clone())));
1535        let result = simplifier.simplify(expr);
1536        assert_eq!(get_string(&result), Some("test".to_string()));
1537
1538        // x || '' -> x
1539        let expr = Expression::Concat(Box::new(BinaryOp::new(x, make_string(""))));
1540        let result = simplifier.simplify(expr);
1541        assert_eq!(get_string(&result), Some("test".to_string()));
1542
1543        // NULL || x -> NULL
1544        let expr = Expression::Concat(Box::new(BinaryOp::new(null(), make_string("test"))));
1545        let result = simplifier.simplify(expr);
1546        assert!(is_null(&result));
1547    }
1548
1549    #[test]
1550    fn test_simplify_concat_ws() {
1551        let mut simplifier = Simplifier::new(None);
1552
1553        // CONCAT_WS(',', 'a', 'b', 'c') -> 'a,b,c'
1554        let expr = Expression::ConcatWs(Box::new(ConcatWs {
1555            separator: make_string(","),
1556            expressions: vec![make_string("a"), make_string("b"), make_string("c")],
1557        }));
1558        let result = simplifier.simplify(expr);
1559        assert_eq!(get_string(&result), Some("a,b,c".to_string()));
1560
1561        // CONCAT_WS with NULL separator -> NULL
1562        let expr = Expression::ConcatWs(Box::new(ConcatWs {
1563            separator: null(),
1564            expressions: vec![make_string("a"), make_string("b")],
1565        }));
1566        let result = simplifier.simplify(expr);
1567        assert!(is_null(&result));
1568
1569        // CONCAT_WS with empty expressions -> ''
1570        let expr = Expression::ConcatWs(Box::new(ConcatWs {
1571            separator: make_string(","),
1572            expressions: vec![],
1573        }));
1574        let result = simplifier.simplify(expr);
1575        assert_eq!(get_string(&result), Some("".to_string()));
1576
1577        // CONCAT_WS skips NULLs
1578        let expr = Expression::ConcatWs(Box::new(ConcatWs {
1579            separator: make_string("-"),
1580            expressions: vec![make_string("a"), null(), make_string("b")],
1581        }));
1582        let result = simplifier.simplify(expr);
1583        assert_eq!(get_string(&result), Some("a-b".to_string()));
1584    }
1585
1586    #[test]
1587    fn test_simplify_paren() {
1588        let mut simplifier = Simplifier::new(None);
1589
1590        // (42) -> 42
1591        let expr = Expression::Paren(Box::new(Paren {
1592            this: make_int(42),
1593            trailing_comments: vec![],
1594        }));
1595        let result = simplifier.simplify(expr);
1596        assert_eq!(get_number(&result), Some(42.0));
1597
1598        // (TRUE) -> TRUE
1599        let expr = Expression::Paren(Box::new(Paren {
1600            this: make_bool(true),
1601            trailing_comments: vec![],
1602        }));
1603        let result = simplifier.simplify(expr);
1604        assert!(is_boolean_true(&result));
1605
1606        // (NULL) -> NULL
1607        let expr = Expression::Paren(Box::new(Paren {
1608            this: null(),
1609            trailing_comments: vec![],
1610        }));
1611        let result = simplifier.simplify(expr);
1612        assert!(is_null(&result));
1613
1614        // ((x)) -> x
1615        let inner_paren = Expression::Paren(Box::new(Paren {
1616            this: make_int(10),
1617            trailing_comments: vec![],
1618        }));
1619        let expr = Expression::Paren(Box::new(Paren {
1620            this: inner_paren,
1621            trailing_comments: vec![],
1622        }));
1623        let result = simplifier.simplify(expr);
1624        assert_eq!(get_number(&result), Some(10.0));
1625    }
1626
1627    #[test]
1628    fn test_simplify_equality_solve() {
1629        let mut simplifier = Simplifier::new(None);
1630
1631        // x + 1 = 3 -> x = 2
1632        let x = make_column("x");
1633        let x_plus_1 = Expression::Add(Box::new(BinaryOp::new(x.clone(), make_int(1))));
1634        let expr = Expression::Eq(Box::new(BinaryOp::new(x_plus_1, make_int(3))));
1635        let result = simplifier.simplify(expr);
1636        // Result should be x = 2
1637        if let Expression::Eq(op) = &result {
1638            assert_eq!(gen(&op.left), "x");
1639            assert_eq!(get_number(&op.right), Some(2.0));
1640        } else {
1641            panic!("Expected Eq expression");
1642        }
1643
1644        // x - 1 = 3 -> x = 4
1645        let x_minus_1 = Expression::Sub(Box::new(BinaryOp::new(x.clone(), make_int(1))));
1646        let expr = Expression::Eq(Box::new(BinaryOp::new(x_minus_1, make_int(3))));
1647        let result = simplifier.simplify(expr);
1648        if let Expression::Eq(op) = &result {
1649            assert_eq!(gen(&op.left), "x");
1650            assert_eq!(get_number(&op.right), Some(4.0));
1651        } else {
1652            panic!("Expected Eq expression");
1653        }
1654
1655        // x * 2 = 6 -> x = 3
1656        let x_times_2 = Expression::Mul(Box::new(BinaryOp::new(x.clone(), make_int(2))));
1657        let expr = Expression::Eq(Box::new(BinaryOp::new(x_times_2, make_int(6))));
1658        let result = simplifier.simplify(expr);
1659        if let Expression::Eq(op) = &result {
1660            assert_eq!(gen(&op.left), "x");
1661            assert_eq!(get_number(&op.right), Some(3.0));
1662        } else {
1663            panic!("Expected Eq expression");
1664        }
1665
1666        // 1 + x = 3 -> x = 2 (commutative)
1667        let one_plus_x = Expression::Add(Box::new(BinaryOp::new(make_int(1), x.clone())));
1668        let expr = Expression::Eq(Box::new(BinaryOp::new(one_plus_x, make_int(3))));
1669        let result = simplifier.simplify(expr);
1670        if let Expression::Eq(op) = &result {
1671            assert_eq!(gen(&op.left), "x");
1672            assert_eq!(get_number(&op.right), Some(2.0));
1673        } else {
1674            panic!("Expected Eq expression");
1675        }
1676    }
1677
1678    #[test]
1679    fn test_simplify_datetrunc() {
1680        use crate::expressions::DateTimeField;
1681        let mut simplifier = Simplifier::new(None);
1682
1683        // DATE_TRUNC('day', x) with a column just passes through with simplified children
1684        let x = make_column("x");
1685        let expr = Expression::DateTrunc(Box::new(DateTruncFunc {
1686            this: x.clone(),
1687            unit: DateTimeField::Day,
1688        }));
1689        let result = simplifier.simplify(expr);
1690        if let Expression::DateTrunc(dt) = &result {
1691            assert_eq!(gen(&dt.this), "x");
1692            assert_eq!(dt.unit, DateTimeField::Day);
1693        } else {
1694            panic!("Expected DateTrunc expression");
1695        }
1696    }
1697}