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