Skip to content

Commit 6712c9c

Browse files
authored
Add Union/Intersect/Except to parser (#111)
1 parent 4dd86eb commit 6712c9c

File tree

4 files changed

+197
-88
lines changed

4 files changed

+197
-88
lines changed

partiql-ast/src/ast.rs

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,21 @@ impl<T> ToAstNode for T {}
6464
/// for creating the node. See [ToAstNode] for more details on the usage.
6565
///
6666
/// [1]: https://crates.io/crates/derive_builder
67-
#[derive(Builder, Clone, Eq, PartialEq, Debug)]
67+
#[derive(Builder, Clone, Debug)]
6868
pub struct AstNode<T, Loc: Display> {
6969
pub node: T,
7070
#[builder(setter(strip_option), default)]
7171
pub location: Option<Location<Loc>>,
7272
}
7373

74+
impl<T: PartialEq, Loc: Display> PartialEq for AstNode<T, Loc> {
75+
fn eq(&self, other: &Self) -> bool {
76+
self.node == other.node
77+
}
78+
}
79+
80+
impl<T: Eq, Loc: Display> Eq for AstNode<T, Loc> {}
81+
7482
#[derive(Clone, Debug, PartialEq)]
7583
pub struct Item {
7684
pub kind: ItemKind,
@@ -206,11 +214,6 @@ pub enum ConflictAction {
206214
DoNothing,
207215
}
208216

209-
#[derive(Clone, Debug, PartialEq)]
210-
pub struct Query {
211-
pub expr: Box<Expr>,
212-
}
213-
214217
#[derive(Clone, Debug, PartialEq)]
215218
pub struct Expr {
216219
pub kind: ExprKind,
@@ -233,9 +236,7 @@ pub type BetweenAst = AstBytePos<Between>;
233236
pub type InAst = AstBytePos<In>;
234237
pub type SimpleCaseAst = AstBytePos<SimpleCase>;
235238
pub type SearchCaseAst = AstBytePos<SearchCase>;
236-
pub type UnionAst = AstBytePos<Union>;
237-
pub type ExceptAst = AstBytePos<Except>;
238-
pub type IntersectAst = AstBytePos<Intersect>;
239+
pub type SetExprAst = AstBytePos<SetExpr>;
239240
pub type PathAst = AstBytePos<Path>;
240241
pub type CallAst = AstBytePos<Call>;
241242
pub type CallAggAst = AstBytePos<CallAgg>;
@@ -251,6 +252,38 @@ pub type GroupByExprAst = AstBytePos<GroupByExpr>;
251252
pub type GroupKeyAst = AstBytePos<GroupKey>;
252253
pub type OrderByExprAst = AstBytePos<OrderByExpr>;
253254
pub type SortSpecAst = AstBytePos<SortSpec>;
255+
pub type QueryAst = AstBytePos<Query>;
256+
pub type QuerySetAst = AstBytePos<QuerySet>;
257+
258+
#[derive(Clone, Debug, PartialEq)]
259+
pub struct Query {
260+
pub set: QuerySetAst,
261+
pub order_by: Option<Box<OrderByExprAst>>,
262+
pub limit: Option<Box<Expr>>,
263+
pub offset: Option<Box<Expr>>,
264+
}
265+
266+
#[derive(Clone, Debug, PartialEq)]
267+
pub enum QuerySet {
268+
SetOp(Box<SetExprAst>),
269+
Select(Box<SelectAst>),
270+
Expr(Box<Expr>),
271+
}
272+
273+
#[derive(Clone, Debug, PartialEq)]
274+
pub struct SetExpr {
275+
pub setop: SetOperator,
276+
pub setq: SetQuantifier,
277+
pub lhs: Box<QuerySetAst>,
278+
pub rhs: Box<QuerySetAst>,
279+
}
280+
281+
#[derive(Clone, Debug, PartialEq)]
282+
pub enum SetOperator {
283+
Union,
284+
Except,
285+
Intersect,
286+
}
254287

255288
/// The expressions that can result in values.
256289
#[derive(Clone, Debug, PartialEq)]
@@ -277,17 +310,13 @@ pub enum ExprKind {
277310
Bag(BagAst),
278311
List(ListAst),
279312
Sexp(SexpAst),
280-
/// Set operators
281-
Union(UnionAst),
282-
Except(ExceptAst),
283-
Intersect(IntersectAst),
284313
/// Other expression types
285314
Path(PathAst),
286315
Call(CallAst),
287316
CallAgg(CallAggAst),
288317

289-
/// `SELECT` and its parts.
290-
Select(SelectAst),
318+
/// Query, e.g. `UNION` | `EXCEPT` | `INTERSECT` | `SELECT` and their parts.
319+
Query(QueryAst),
291320

292321
/// Indicates an error occurred during query processing; The exact error details are out of band of the AST
293322
Error,
@@ -454,24 +483,6 @@ pub struct LitTime {
454483
pub value: TimeValue,
455484
}
456485

457-
#[derive(Clone, Debug, PartialEq)]
458-
pub struct Union {
459-
pub setq: SetQuantifier,
460-
pub operands: Vec<Box<Expr>>,
461-
}
462-
463-
#[derive(Clone, Debug, PartialEq)]
464-
pub struct Except {
465-
pub setq: SetQuantifier,
466-
pub operands: Vec<Box<Expr>>,
467-
}
468-
469-
#[derive(Clone, Debug, PartialEq)]
470-
pub struct Intersect {
471-
pub setq: SetQuantifier,
472-
pub operands: Vec<Box<Expr>>,
473-
}
474-
475486
#[derive(Clone, Debug, PartialEq)]
476487
pub struct Path {
477488
pub root: Box<Expr>,
@@ -529,9 +540,6 @@ pub struct Select {
529540
pub where_clause: Option<Box<Expr>>,
530541
pub group_by: Option<Box<GroupByExprAst>>,
531542
pub having: Option<Box<Expr>>,
532-
pub order_by: Option<Box<OrderByExprAst>>,
533-
pub limit: Option<Box<Expr>>,
534-
pub offset: Option<Box<Expr>>,
535543
}
536544

537545
#[derive(Clone, Debug, PartialEq)]

partiql-ast/tests/test_ast.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ fn test_ast_init() {
1010

1111
let _i = Item {
1212
kind: ItemKind::Query(Query {
13-
expr: Box::new(Expr {
13+
set: QuerySet::Expr(Box::new(Expr {
1414
kind: ExprKind::Lit(Lit::Int32Lit(23).to_ast(BytePosition::from(1)..12.into())),
15-
}),
15+
}))
16+
.to_ast(BytePosition::from(1)..12.into()),
17+
offset: None,
18+
order_by: None,
19+
limit: None,
1620
}),
1721
};
1822

partiql-parser/src/parse/mod.rs

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ mod tests {
124124
let res = parse_partiql($q);
125125
println!("{:#?}", res);
126126
match res {
127-
Ok(_) => (),
128-
_ => assert!(false, "{:?}", res),
127+
Ok(ast) => ast,
128+
_ => panic!("{:?}", res),
129129
}
130130
}};
131131
}
@@ -265,32 +265,32 @@ mod tests {
265265

266266
#[test]
267267
fn or_simple() {
268-
parse!(r#"TRUE OR FALSE"#)
268+
parse!(r#"TRUE OR FALSE"#);
269269
}
270270

271271
#[test]
272272
fn or() {
273-
parse!(r#"t1.super OR test(t2.name, t1.name)"#)
273+
parse!(r#"t1.super OR test(t2.name, t1.name)"#);
274274
}
275275

276276
#[test]
277277
fn and_simple() {
278-
parse!(r#"TRUE and FALSE"#)
278+
parse!(r#"TRUE and FALSE"#);
279279
}
280280

281281
#[test]
282282
fn and() {
283-
parse!(r#"test(t2.name, t1.name) AND t1.id = t2.id"#)
283+
parse!(r#"test(t2.name, t1.name) AND t1.id = t2.id"#);
284284
}
285285

286286
#[test]
287287
fn or_and() {
288-
parse!(r#"t1.super OR test(t2.name, t1.name) AND t1.id = t2.id"#)
288+
parse!(r#"t1.super OR test(t2.name, t1.name) AND t1.id = t2.id"#);
289289
}
290290

291291
#[test]
292292
fn infix() {
293-
parse!(r#"1 + -2 * +3 % 4^5 / 6 - 7 <= 3.14 AND 'foo' || 'bar' LIKE '%oba%'"#)
293+
parse!(r#"1 + -2 * +3 % 4^5 / 6 - 7 <= 3.14 AND 'foo' || 'bar' LIKE '%oba%'"#);
294294
}
295295
}
296296

@@ -299,37 +299,37 @@ mod tests {
299299

300300
#[test]
301301
fn selectstar() {
302-
parse!("SELECT *")
302+
parse!("SELECT *");
303303
}
304304

305305
#[test]
306306
fn select1() {
307-
parse!("SELECT g")
307+
parse!("SELECT g");
308308
}
309309

310310
#[test]
311311
fn select_list() {
312-
parse!("SELECT g, k as ck, h")
312+
parse!("SELECT g, k as ck, h");
313313
}
314314

315315
#[test]
316316
fn fun_call() {
317-
parse!(r#"fun_call('bar', 1,2,3,4,5,'foo')"#)
317+
parse!(r#"fun_call('bar', 1,2,3,4,5,'foo')"#);
318318
}
319319

320320
#[test]
321321
fn select3() {
322-
parse!("SELECT g, k, function('2') as fn_result")
322+
parse!("SELECT g, k, function('2') as fn_result");
323323
}
324324

325325
#[test]
326326
fn group() {
327-
parse!("SELECT g FROM data GROUP BY a")
327+
parse!("SELECT g FROM data GROUP BY a");
328328
}
329329

330330
#[test]
331331
fn group_complex() {
332-
parse!("SELECT g FROM data GROUP BY a AS x, b + c AS y, foo(d) AS z GROUP AS g")
332+
parse!("SELECT g FROM data GROUP BY a AS x, b + c AS y, foo(d) AS z GROUP AS g");
333333
}
334334

335335
#[test]
@@ -341,27 +341,29 @@ mod tests {
341341

342342
#[test]
343343
fn where_simple() {
344-
parse!(r#"SELECT a FROM tb WHERE hk = 1"#)
344+
parse!(r#"SELECT a FROM tb WHERE hk = 1"#);
345345
}
346346

347347
#[test]
348348
fn where_boolean() {
349-
parse!(r#"SELECT a FROM tb WHERE t1.super OR test(t2.name, t1.name) AND t1.id = t2.id"#)
349+
parse!(
350+
r#"SELECT a FROM tb WHERE t1.super OR test(t2.name, t1.name) AND t1.id = t2.id"#
351+
);
350352
}
351353

352354
#[test]
353355
fn limit() {
354-
parse!(r#"SELECT * FROM a LIMIT 10"#)
356+
parse!(r#"SELECT * FROM a LIMIT 10"#);
355357
}
356358

357359
#[test]
358360
fn offset() {
359-
parse!(r#"SELECT * FROM a OFFSET 10"#)
361+
parse!(r#"SELECT * FROM a OFFSET 10"#);
360362
}
361363

362364
#[test]
363365
fn limit_offset() {
364-
parse!(r#"SELECT * FROM a LIMIT 10 OFFSET 2"#)
366+
parse!(r#"SELECT * FROM a LIMIT 10 OFFSET 2"#);
365367
}
366368

367369
#[test]
@@ -378,7 +380,44 @@ mod tests {
378380
)
379381
AS deltas FROM SOURCE_VIEW_DELTA_FULL_TRANSACTIONS delta_full_transactions
380382
"#;
381-
parse!(q)
383+
parse!(q);
384+
}
385+
}
386+
387+
mod set_ops {
388+
use super::*;
389+
390+
#[test]
391+
fn set_ops() {
392+
parse!(
393+
r#"(SELECT * FROM a LIMIT 10 OFFSET 2) UNION SELECT * FROM b INTERSECT c EXCEPT SELECT * FROM d"#
394+
);
395+
}
396+
397+
#[test]
398+
fn union_prec() {
399+
let l = parse!(r#"a union b union c"#);
400+
let r = parse!(r#"(a union b) union c"#);
401+
assert_eq!(l, r);
402+
}
403+
404+
#[test]
405+
fn intersec_prec() {
406+
let l = parse!(r#"a union b intersect c"#);
407+
let r = parse!(r#"a union (b intersect c)"#);
408+
assert_eq!(l, r);
409+
}
410+
411+
#[test]
412+
fn limit() {
413+
let l = parse!(r#"SELECT a FROM b UNION SELECT x FROM y ORDER BY a LIMIT 10 OFFSET 5"#);
414+
let r =
415+
parse!(r#"(SELECT a FROM b UNION SELECT x FROM y) ORDER BY a LIMIT 10 OFFSET 5"#);
416+
assert_eq!(l, r);
417+
let r2 =
418+
parse!(r#"SELECT a FROM b UNION (SELECT x FROM y ORDER BY a LIMIT 10 OFFSET 5)"#);
419+
assert_ne!(l, r2);
420+
assert_ne!(r, r2);
382421
}
383422
}
384423

0 commit comments

Comments
 (0)