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

gluesql / gluesql / 18519170559

15 Oct 2025 05:50AM UTC coverage: 97.964% (+0.02%) from 97.941%
18519170559

push

github

web-flow
Add JSON -> operator support  (#1807)

Adds Arrow operator (->): AST variant and SQL emission, translator mapping, evaluator dispatch, a new select function for Map/List, two new EvaluateError variants, duplicate Evaluated::arrow implementations, and new tests exercising arrow behavior.

52 of 59 new or added lines in 5 files covered. (88.14%)

38438 of 39237 relevant lines covered (97.96%)

72244.53 hits per line

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

99.51
/core/src/ast/operator.rs
1
use {
2
    crate::ast::ToSql,
3
    serde::{Deserialize, Serialize},
4
};
5

6
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
7
pub enum UnaryOperator {
8
    Plus,
9
    Minus,
10
    Not,
11
    Factorial,
12
    BitwiseNot,
13
}
14

15
impl ToSql for UnaryOperator {
16
    fn to_sql(&self) -> String {
2,046✔
17
        match self {
2,046✔
18
            UnaryOperator::Plus => "+".to_owned(),
681✔
19
            UnaryOperator::Minus => "-".to_owned(),
1,362✔
20
            UnaryOperator::Not => "NOT ".to_owned(),
1✔
21
            UnaryOperator::Factorial => "!".to_owned(),
1✔
22
            UnaryOperator::BitwiseNot => "~".to_owned(),
1✔
23
        }
24
    }
2,046✔
25
}
26

27
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
28
pub enum BinaryOperator {
29
    Plus,
30
    Minus,
31
    Multiply,
32
    Divide,
33
    Modulo,
34
    StringConcat,
35
    Gt,
36
    Lt,
37
    GtEq,
38
    LtEq,
39
    Eq,
40
    NotEq,
41
    And,
42
    Or,
43
    Xor,
44
    BitwiseAnd,
45
    BitwiseShiftLeft,
46
    BitwiseShiftRight,
47
    Arrow,
48
}
49

50
impl ToSql for BinaryOperator {
51
    fn to_sql(&self) -> String {
3,865✔
52
        match self {
3,865✔
53
            BinaryOperator::Plus => "+".to_owned(),
599✔
54
            BinaryOperator::Minus => "-".to_owned(),
2✔
55
            BinaryOperator::Multiply => "*".to_owned(),
1,363✔
56
            BinaryOperator::Divide => "/".to_owned(),
1✔
57
            BinaryOperator::Modulo => "%".to_owned(),
1✔
58
            BinaryOperator::StringConcat => "+".to_owned(),
1,191✔
59
            BinaryOperator::Gt => ">".to_owned(),
5✔
60
            BinaryOperator::Lt => "<".to_owned(),
1✔
61
            BinaryOperator::GtEq => ">=".to_owned(),
1✔
62
            BinaryOperator::LtEq => "<=".to_owned(),
3✔
63
            BinaryOperator::Eq => "=".to_owned(),
9✔
64
            BinaryOperator::NotEq => "<>".to_owned(),
1✔
65
            BinaryOperator::And => "AND".to_owned(),
3✔
66
            BinaryOperator::Or => "OR".to_owned(),
681✔
67
            BinaryOperator::Xor => "XOR".to_owned(),
1✔
68
            BinaryOperator::BitwiseAnd => "&".to_owned(),
1✔
69
            BinaryOperator::BitwiseShiftLeft => "<<".to_owned(),
1✔
70
            BinaryOperator::BitwiseShiftRight => ">>".to_owned(),
1✔
NEW
71
            BinaryOperator::Arrow => "->".to_owned(),
×
72
        }
73
    }
3,865✔
74
}
75

76
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
77
pub enum IndexOperator {
78
    Gt,
79
    Lt,
80
    GtEq,
81
    LtEq,
82
    Eq,
83
}
84

85
impl IndexOperator {
86
    pub fn reverse(self) -> Self {
765✔
87
        use IndexOperator::*;
88

89
        match self {
765✔
90
            Gt => Lt,
255✔
91
            Lt => Gt,
85✔
92
            GtEq => LtEq,
85✔
93
            LtEq => GtEq,
85✔
94
            Eq => Eq,
255✔
95
        }
96
    }
765✔
97
}
98

99
impl From<IndexOperator> for BinaryOperator {
100
    fn from(index_op: IndexOperator) -> Self {
263,245✔
101
        match index_op {
263,245✔
102
            IndexOperator::Gt => BinaryOperator::Gt,
51,340✔
103
            IndexOperator::Lt => BinaryOperator::Lt,
43,095✔
104
            IndexOperator::GtEq => BinaryOperator::GtEq,
17,935✔
105
            IndexOperator::LtEq => BinaryOperator::LtEq,
17,850✔
106
            IndexOperator::Eq => BinaryOperator::Eq,
133,025✔
107
        }
108
    }
263,245✔
109
}
110

111
#[cfg(test)]
112
mod tests {
113
    use {
114
        crate::ast::{AstLiteral, BinaryOperator, Expr, ToSql, UnaryOperator},
115
        bigdecimal::BigDecimal,
116
    };
117
    #[test]
118
    fn to_sql() {
1✔
119
        assert_eq!(
1✔
120
            "1 + 2",
121
            Expr::BinaryOp {
1✔
122
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1)))),
1✔
123
                op: BinaryOperator::Plus,
1✔
124
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(2))))
1✔
125
            }
1✔
126
            .to_sql()
1✔
127
        );
128

129
        assert_eq!(
1✔
130
            "100 - 10",
131
            Expr::BinaryOp {
1✔
132
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(100)))),
1✔
133
                op: BinaryOperator::Minus,
1✔
134
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(10))))
1✔
135
            }
1✔
136
            .to_sql()
1✔
137
        );
138

139
        assert_eq!(
1✔
140
            "1024 * 1024",
141
            Expr::BinaryOp {
1✔
142
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1024)))),
1✔
143
                op: BinaryOperator::Multiply,
1✔
144
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1024))))
1✔
145
            }
1✔
146
            .to_sql()
1✔
147
        );
148

149
        assert_eq!(
1✔
150
            "1024 / 8",
151
            Expr::BinaryOp {
1✔
152
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1024)))),
1✔
153
                op: BinaryOperator::Divide,
1✔
154
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(8))))
1✔
155
            }
1✔
156
            .to_sql()
1✔
157
        );
158

159
        assert_eq!(
1✔
160
            "1024 % 4",
161
            &Expr::BinaryOp {
1✔
162
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1024)))),
1✔
163
                op: BinaryOperator::Modulo,
1✔
164
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(4))))
1✔
165
            }
1✔
166
            .to_sql()
1✔
167
        );
168

169
        assert_eq!(
1✔
170
            "'Glue' + 'SQL'",
171
            &Expr::BinaryOp {
1✔
172
                left: Box::new(Expr::Literal(AstLiteral::QuotedString("Glue".to_owned()))),
1✔
173
                op: BinaryOperator::StringConcat,
1✔
174
                right: Box::new(Expr::Literal(AstLiteral::QuotedString("SQL".to_owned())))
1✔
175
            }
1✔
176
            .to_sql()
1✔
177
        );
178
        assert_eq!(
1✔
179
            "1024 > 4",
180
            &Expr::BinaryOp {
1✔
181
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1024)))),
1✔
182
                op: BinaryOperator::Gt,
1✔
183
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(4))))
1✔
184
            }
1✔
185
            .to_sql()
1✔
186
        );
187
        assert_eq!(
1✔
188
            "8 < 1024",
189
            &Expr::BinaryOp {
1✔
190
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(8)))),
1✔
191
                op: BinaryOperator::Lt,
1✔
192
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1024))))
1✔
193
            }
1✔
194
            .to_sql()
1✔
195
        );
196
        assert_eq!(
1✔
197
            "1024 >= 1024",
198
            &Expr::BinaryOp {
1✔
199
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1024)))),
1✔
200
                op: BinaryOperator::GtEq,
1✔
201
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1024))))
1✔
202
            }
1✔
203
            .to_sql()
1✔
204
        );
205
        assert_eq!(
1✔
206
            "8 <= 8",
207
            &Expr::BinaryOp {
1✔
208
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(8)))),
1✔
209
                op: BinaryOperator::LtEq,
1✔
210
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(8))))
1✔
211
            }
1✔
212
            .to_sql()
1✔
213
        );
214
        assert_eq!(
1✔
215
            "1024 = 1024",
216
            &Expr::BinaryOp {
1✔
217
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1024)))),
1✔
218
                op: BinaryOperator::Eq,
1✔
219
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1024))))
1✔
220
            }
1✔
221
            .to_sql()
1✔
222
        );
223
        assert_eq!(
1✔
224
            "1024 <> 1024",
225
            &Expr::BinaryOp {
1✔
226
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1024)))),
1✔
227
                op: BinaryOperator::NotEq,
1✔
228
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1024))))
1✔
229
            }
1✔
230
            .to_sql()
1✔
231
        );
232
        assert_eq!(
1✔
233
            "1 << 2",
234
            &Expr::BinaryOp {
1✔
235
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1)))),
1✔
236
                op: BinaryOperator::BitwiseShiftLeft,
1✔
237
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(2))))
1✔
238
            }
1✔
239
            .to_sql()
1✔
240
        );
241
        assert_eq!(
1✔
242
            "1 >> 2",
243
            &Expr::BinaryOp {
1✔
244
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1)))),
1✔
245
                op: BinaryOperator::BitwiseShiftRight,
1✔
246
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(2))))
1✔
247
            }
1✔
248
            .to_sql()
1✔
249
        );
250
        assert_eq!(
1✔
251
            r#""condition_0" AND "condition_1""#,
252
            &Expr::BinaryOp {
1✔
253
                left: Box::new(Expr::Identifier("condition_0".to_owned())),
1✔
254
                op: BinaryOperator::And,
1✔
255
                right: Box::new(Expr::Identifier("condition_1".to_owned()))
1✔
256
            }
1✔
257
            .to_sql()
1✔
258
        );
259
        assert_eq!(
1✔
260
            r#""condition_0" OR "condition_1""#,
261
            &Expr::BinaryOp {
1✔
262
                left: Box::new(Expr::Identifier("condition_0".to_owned())),
1✔
263
                op: BinaryOperator::Or,
1✔
264
                right: Box::new(Expr::Identifier("condition_1".to_owned()))
1✔
265
            }
1✔
266
            .to_sql()
1✔
267
        );
268
        assert_eq!(
1✔
269
            r#""condition_0" XOR "condition_1""#,
270
            &Expr::BinaryOp {
1✔
271
                left: Box::new(Expr::Identifier("condition_0".to_owned())),
1✔
272
                op: BinaryOperator::Xor,
1✔
273
                right: Box::new(Expr::Identifier("condition_1".to_owned()))
1✔
274
            }
1✔
275
            .to_sql()
1✔
276
        );
277
        assert_eq!(
1✔
278
            "+8",
279
            Expr::UnaryOp {
1✔
280
                op: UnaryOperator::Plus,
1✔
281
                expr: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(8)))),
1✔
282
            }
1✔
283
            .to_sql(),
1✔
284
        );
285

286
        assert_eq!(
1✔
287
            "-8",
288
            Expr::UnaryOp {
1✔
289
                op: UnaryOperator::Minus,
1✔
290
                expr: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(8)))),
1✔
291
            }
1✔
292
            .to_sql(),
1✔
293
        );
294

295
        assert_eq!(
1✔
296
            r#"NOT "id""#,
297
            Expr::UnaryOp {
1✔
298
                op: UnaryOperator::Not,
1✔
299
                expr: Box::new(Expr::Identifier("id".to_owned())),
1✔
300
            }
1✔
301
            .to_sql(),
1✔
302
        );
303

304
        assert_eq!(
1✔
305
            "5!",
306
            Expr::UnaryOp {
1✔
307
                op: UnaryOperator::Factorial,
1✔
308
                expr: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(5)))),
1✔
309
            }
1✔
310
            .to_sql(),
1✔
311
        );
312

313
        assert_eq!(
1✔
314
            "29 & 15",
315
            &Expr::BinaryOp {
1✔
316
                left: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(29)))),
1✔
317
                op: BinaryOperator::BitwiseAnd,
1✔
318
                right: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(15))))
1✔
319
            }
1✔
320
            .to_sql()
1✔
321
        );
322

323
        assert_eq!(
1✔
324
            "~1",
325
            Expr::UnaryOp {
1✔
326
                op: UnaryOperator::BitwiseNot,
1✔
327
                expr: Box::new(Expr::Literal(AstLiteral::Number(BigDecimal::from(1)))),
1✔
328
            }
1✔
329
            .to_sql(),
1✔
330
        )
331
    }
1✔
332
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc