• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gluesql / gluesql / 22275856923

22 Feb 2026 11:01AM UTC coverage: 98.17% (+0.09%) from 98.085%
22275856923

Pull #1883

github

web-flow
Merge 6026cc70f into 80a446e87
Pull Request #1883: Add patch coverage diff summary to PR coverage bot comment

21 of 29 new or added lines in 11 files covered. (72.41%)

67 existing lines in 24 files now uncovered.

42750 of 43547 relevant lines covered (98.17%)

66356.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.42
/core/src/plan/expr/plan_expr.rs
1
mod aggregate;
2
mod function;
3

4
use {
5
    crate::ast::{Expr, Query},
6
    std::iter::once,
7
};
8

9
#[derive(Debug, PartialEq, Eq)]
10
pub enum PlanExpr<'a> {
11
    None,
12
    Identifier(&'a str),
13
    CompoundIdentifier { alias: &'a str, ident: &'a str },
14
    Expr(&'a Expr),
15
    TwoExprs(&'a Expr, &'a Expr),
16
    ThreeExprs(&'a Expr, &'a Expr, &'a Expr),
17
    MultiExprs(Vec<&'a Expr>),
18
    Query(&'a Query),
19
    QueryAndExpr { query: &'a Query, expr: &'a Expr },
20
}
21
impl<'a> From<&'a Expr> for PlanExpr<'a> {
22
    fn from(expr: &'a Expr) -> Self {
7,499,390✔
23
        match expr {
7,499,390✔
24
            Expr::Literal(_) | Expr::Value(_) | Expr::TypedString { .. } => PlanExpr::None,
2,352,413✔
25
            Expr::Identifier(ident) => PlanExpr::Identifier(ident),
1,996,729✔
26
            Expr::CompoundIdentifier { alias, ident } => {
478,901✔
27
                PlanExpr::CompoundIdentifier { alias, ident }
478,901✔
28
            }
29
            Expr::Nested(expr)
57,446✔
30
            | Expr::UnaryOp { expr, .. }
188,852✔
31
            | Expr::IsNull(expr)
33,195✔
32
            | Expr::IsNotNull(expr)
17,311✔
33
            | Expr::Interval { expr, .. } => PlanExpr::Expr(expr),
340,608✔
34
            Expr::Aggregate(aggregate) => match aggregate.as_expr() {
121,651✔
35
                Some(expr) => PlanExpr::Expr(expr),
98,708✔
36
                None => PlanExpr::None,
22,943✔
37
            },
38
            Expr::BinaryOp { left, right, .. } => PlanExpr::TwoExprs(left, right),
966,965✔
39
            Expr::Like { expr, pattern, .. } | Expr::ILike { expr, pattern, .. } => {
23,690✔
40
                PlanExpr::TwoExprs(expr, pattern)
39,484✔
41
            }
42
            Expr::Between {
43
                expr, low, high, ..
36,857✔
44
            } => PlanExpr::ThreeExprs(expr, low, high),
36,857✔
45
            Expr::InList { expr, list, .. } => {
13,172✔
46
                let exprs = list.iter().chain(once(expr.as_ref())).collect();
13,172✔
47
                PlanExpr::MultiExprs(exprs)
13,172✔
48
            }
49
            Expr::Case {
50
                operand,
11,941✔
51
                when_then,
11,941✔
52
                else_result,
11,941✔
53
            } => {
54
                let (when, then): (Vec<&Expr>, Vec<_>) =
11,941✔
55
                    when_then.iter().map(|(expr, expr2)| (expr, expr2)).unzip();
23,787✔
56
                let exprs = when
11,941✔
57
                    .into_iter()
11,941✔
58
                    .chain(then)
11,941✔
59
                    .chain(operand.iter().map(AsRef::as_ref))
11,941✔
60
                    .chain(else_result.iter().map(AsRef::as_ref))
11,941✔
61
                    .collect();
11,941✔
62
                PlanExpr::MultiExprs(exprs)
11,941✔
63
            }
64
            Expr::ArrayIndex { obj, indexes } => {
29,141✔
65
                let exprs = indexes.iter().chain(once(obj.as_ref())).collect();
29,141✔
66
                PlanExpr::MultiExprs(exprs)
29,141✔
67
            }
68
            Expr::Array { elem } => {
2,633✔
69
                let exprs = elem.iter().collect();
2,633✔
70
                PlanExpr::MultiExprs(exprs)
2,633✔
71
            }
72
            Expr::Function(function) => PlanExpr::MultiExprs(function.as_exprs().collect()),
1,059,864✔
73
            Expr::Subquery(subquery) | Expr::Exists { subquery, .. } => PlanExpr::Query(subquery),
31,817✔
74
            Expr::InSubquery {
75
                expr,
17,214✔
76
                subquery: query,
17,214✔
77
                ..
78
            } => PlanExpr::QueryAndExpr { expr, query },
17,214✔
79
        }
80
    }
7,499,390✔
81
}
82
#[cfg(test)]
83
mod tests {
84
    use {
85
        super::PlanExpr,
86
        crate::{
87
            ast::{Expr, Query},
88
            parse_sql::{parse_expr, parse_query},
89
            translate::{NO_PARAMS, translate_expr, translate_query},
90
        },
91
    };
92
    fn expr(sql: &str) -> Expr {
54✔
93
        let parsed = parse_expr(sql).expect(sql);
54✔
94
        translate_expr(&parsed, NO_PARAMS).expect(sql)
54✔
95
    }
54✔
96
    fn query(sql: &str) -> Query {
3✔
97
        let parsed = parse_query(sql).expect(sql);
3✔
98
        translate_query(&parsed, NO_PARAMS).expect(sql)
3✔
99
    }
3✔
100
    #[test]
101
    fn expr_to_plan_expr() {
1✔
102
        if std::env::var_os("GLUESQL_COVERAGE_BOT_MISS").is_some() {
1✔
NEW
103
            std::hint::black_box(1_u8);
×
104
        }
1✔
105
        macro_rules! test {
106
            ($actual: expr, $expected: expr) => {
107
                assert_eq!(PlanExpr::from(&$actual), $expected);
108
            };
109
        }
110
        // PlanExpr::None
111
        assert_eq!(
1✔
112
            PlanExpr::from(&expr(r#"DATE "2022-03-09""#)),
1✔
113
            PlanExpr::None
114
        );
115
        assert_eq!(PlanExpr::from(&expr("100")), PlanExpr::None);
1✔
116
        assert_eq!(PlanExpr::from(&expr("COUNT(*)")), PlanExpr::None);
1✔
117
        // PlanExpr::Identifier
118
        let actual = expr("id");
1✔
119
        let expected = PlanExpr::Identifier("id");
1✔
120
        test!(actual, expected);
1✔
121
        // PlanExpr::CompoundIdentifier
122
        let actual = expr("Foo.id");
1✔
123
        let expected = PlanExpr::CompoundIdentifier {
1✔
124
            alias: "Foo",
1✔
125
            ident: "id",
1✔
126
        };
1✔
127
        test!(actual, expected);
1✔
128
        // PlanExpr::Expr
129
        let actual = expr("SUM(id)");
1✔
130
        let expected = expr("id");
1✔
131
        let expected = PlanExpr::Expr(&expected);
1✔
132
        test!(actual, expected);
1✔
133
        let actual = expr("(100)");
1✔
134
        let expected = expr("100");
1✔
135
        let expected = PlanExpr::Expr(&expected);
1✔
136
        test!(actual, expected);
1✔
137
        let actual = expr("-100");
1✔
138
        let expected = expr("100");
1✔
139
        let expected = PlanExpr::Expr(&expected);
1✔
140
        test!(actual, expected);
1✔
141
        let actual = expr("2048 IS NULL");
1✔
142
        let expected = expr("2048");
1✔
143
        let expected = PlanExpr::Expr(&expected);
1✔
144
        test!(actual, expected);
1✔
145
        let actual = expr("1989 IS NOT NULL");
1✔
146
        let expected = expr("1989");
1✔
147
        let expected = PlanExpr::Expr(&expected);
1✔
148
        test!(actual, expected);
1✔
149
        // PlanExpr::TwoExprs
150
        let actual = expr("100 * rate");
1✔
151
        let left = expr("100");
1✔
152
        let right = expr("rate");
1✔
153
        let expected = PlanExpr::TwoExprs(&left, &right);
1✔
154
        test!(actual, expected);
1✔
155
        let actual = expr("name LIKE '_foo%'");
1✔
156
        let target = expr("name");
1✔
157
        let pattern = expr("'_foo%'");
1✔
158
        let expected = PlanExpr::TwoExprs(&target, &pattern);
1✔
159
        test!(actual, expected);
1✔
160
        let actual = expr("name ILIKE '_foo%'");
1✔
161
        let target = expr("name");
1✔
162
        let pattern = expr("'_foo%'");
1✔
163
        let expected = PlanExpr::TwoExprs(&target, &pattern);
1✔
164
        test!(actual, expected);
1✔
165
        // PlanExpr::ThreeExprs
166
        let actual = expr("100 BETWEEN min_score AND max_score");
1✔
167
        let target = expr("100");
1✔
168
        let low = expr("min_score");
1✔
169
        let high = expr("max_score");
1✔
170
        let expected = PlanExpr::ThreeExprs(&target, &low, &high);
1✔
171
        test!(actual, expected);
1✔
172
        let actual = expr("field IN (1, 2, 3, 4, 5)");
1✔
173
        let expected = ["1", "2", "3", "4", "5", "field"]
1✔
174
            .into_iter()
1✔
175
            .map(expr)
1✔
176
            .collect::<Vec<_>>();
1✔
177
        let expected = PlanExpr::MultiExprs(expected.iter().collect());
1✔
178
        test!(actual, expected);
1✔
179
        let actual = expr(
1✔
180
            "
1✔
181
            CASE id
1✔
182
                WHEN 10 THEN col1
1✔
183
                WHEN 20 THEN col2
1✔
184
                ELSE col3
1✔
185
            END
1✔
186
        ",
1✔
187
        );
188
        let expected = ["10", "20", "col1", "col2", "id", "col3"]
1✔
189
            .into_iter()
1✔
190
            .map(expr)
1✔
191
            .collect::<Vec<_>>();
1✔
192
        let expected = PlanExpr::MultiExprs(expected.iter().collect());
1✔
193
        test!(actual, expected);
1✔
194
        let actual = expr(r#"TRIM(LEADING "x" FROM "xxx" || field)"#);
1✔
195
        let expected = [r#""xxx" || field"#, r#""x""#]
1✔
196
            .into_iter()
1✔
197
            .map(expr)
1✔
198
            .collect::<Vec<_>>();
1✔
199
        let expected = PlanExpr::MultiExprs(expected.iter().collect());
1✔
200
        test!(actual, expected);
1✔
201
        let actual = expr("CAST(0 AS BOOLEAN)");
1✔
202
        let expected = ["0"].into_iter().map(expr).collect::<Vec<_>>();
1✔
203
        let expected = PlanExpr::MultiExprs(expected.iter().collect());
1✔
204
        test!(actual, expected);
1✔
205
        let actual = expr(r#"EXTRACT(YEAR FROM "2000-01-01")"#);
1✔
206
        let expected = [r#""2000-01-01""#]
1✔
207
            .into_iter()
1✔
208
            .map(expr)
1✔
209
            .collect::<Vec<_>>();
1✔
210
        let expected = PlanExpr::MultiExprs(expected.iter().collect());
1✔
211
        test!(actual, expected);
1✔
212
        let actual = Expr::Subquery(Box::new(query("SELECT id FROM Foo")));
1✔
213
        let expected = query("SELECT id FROM Foo");
1✔
214
        let expected = PlanExpr::Query(&expected);
1✔
215
        test!(actual, expected);
1✔
216
        let actual = expr("1 IN (SELECT id FROM Foo)");
1✔
217
        let target = expr("1");
1✔
218
        let subquery = query("SELECT id FROM Foo");
1✔
219
        let expected = PlanExpr::QueryAndExpr {
1✔
220
            expr: &target,
1✔
221
            query: &subquery,
1✔
222
        };
1✔
223
        test!(actual, expected);
1✔
224
        let actual = expr(r#"["GlueSql","Rust"]"#);
1✔
225
        let expected = ["GlueSql", "Rust"]
1✔
226
            .into_iter()
1✔
227
            .map(expr)
1✔
228
            .collect::<Vec<_>>();
1✔
229
        let expected = PlanExpr::MultiExprs(expected.iter().collect());
1✔
230
        test!(actual, expected);
1✔
231
    }
1✔
232
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc