rudb_parse/ast.rs
1//! rudb's abstract syntax tree.
2//!
3//! The parse tree the matcher produces is DuckDB's grammar, faithfully. That is the point of it and
4//! it is also why nothing downstream should read it: a bump of the vendored grammar is allowed to
5//! rename `BetweenInLikeExpression`, and if the binder is matching on that name then the bump is a
6//! rewrite. This module is the boundary. It is ours, it changes when we decide it changes, and
7//! `transform` is the one place that knows both shapes.
8//!
9//! Everything is an arena with `u32` indices, per `spec/04-architecture.md` section 4.5. There is
10//! no `Box` and no `Vec` inside a node. A list of children is a [`Slice`] into a side vector, which
11//! means a node is a fixed size, the whole tree is a handful of allocations, and walking it is a
12//! sequential read rather than a pointer chase per node. It also means an `Ast` is `Clone` and
13//! `Send` without any thought, and that a subtree can be addressed by a `u32` in a plan or an
14//! error without borrowing anything.
15//!
16//! The one cost is that you cannot hold a reference to a node and index the arena at the same time,
17//! so the code reads a node out by value first. Nodes are small and `Copy`, so that is a register
18//! move.
19
20use crate::matcher::NONE;
21
22/// A run of items in one of the side vectors.
23///
24/// Empty is `len == 0`, and `start` is then meaningless rather than wrong. There is no `Option`
25/// wrapper because an absent list and an empty list are the same thing everywhere this is used.
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
27pub struct Slice {
28 /// The first item.
29 pub start: u32,
30 /// How many items.
31 pub len: u32,
32}
33
34impl Slice {
35 /// Whether the run is empty.
36 pub const fn is_empty(self) -> bool {
37 self.len == 0
38 }
39
40 /// The run as a range, for indexing the backing vector.
41 pub const fn range(self) -> std::ops::Range<usize> {
42 self.start as usize..(self.start + self.len) as usize
43 }
44}
45
46/// An index into `Ast::strings`.
47pub type StrRef = u32;
48/// An index into `Ast::exprs`.
49pub type ExprRef = u32;
50/// An index into `Ast::sources`.
51pub type SourceRef = u32;
52/// An index into `Ast::queries`.
53pub type QueryRef = u32;
54/// An index into `Ast::selects`.
55pub type SelectRef = u32;
56
57/// One statement.
58///
59/// Only `SELECT` is here, which is what M0 needs. The other twenty six statement kinds the grammar
60/// reaches are a transform error naming the rule rather than a variant that nothing fills in, so
61/// that adding one is a compile error somewhere useful rather than a silent `todo!()`.
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum Statement {
64 /// A query, meaning a `SELECT` or a set operation over two of them.
65 Query(QueryRef),
66}
67
68/// A query: a body, plus the modifiers that apply to whatever the body produced.
69///
70/// The split is the grammar's, not an invention. `SelectStatementInternal <- WithClause?
71/// SelectSetOpChain ResultModifiers?` puts `ORDER BY` and `LIMIT` outside the set operator chain,
72/// which is the only place they can go and be right: `a UNION b ORDER BY x` sorts the union and not
73/// the second half of it. Hanging them off `Select` instead would have made that unrepresentable.
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub struct Query {
76 /// What produces the rows.
77 pub body: QueryBody,
78 /// The `ORDER BY` list, as a run of [`OrderItem`].
79 pub order_by: Slice,
80 /// Whether the clause was `ORDER BY ALL`.
81 pub order_by_all: bool,
82 /// The `LIMIT` expression, or `NONE`.
83 pub limit: ExprRef,
84 /// Whether the limit was a percentage rather than a row count.
85 pub limit_percent: bool,
86 /// The `OFFSET` expression, or `NONE`.
87 pub offset: ExprRef,
88}
89
90impl Query {
91 /// A query with no modifiers on it.
92 pub const fn bare(body: QueryBody) -> Self {
93 Self {
94 body,
95 order_by: Slice { start: 0, len: 0 },
96 order_by_all: false,
97 limit: NONE,
98 limit_percent: false,
99 offset: NONE,
100 }
101 }
102}
103
104/// What produces the rows of a query.
105#[derive(Debug, Clone, Copy, PartialEq, Eq)]
106pub enum QueryBody {
107 /// One `SELECT ... FROM ... WHERE ...` block.
108 Select(SelectRef),
109 /// `UNION`, `EXCEPT` or `INTERSECT` over two queries.
110 SetOp {
111 /// Which operator.
112 op: SetOp,
113 /// Whether duplicates survive.
114 quantifier: Quantifier,
115 /// Whether the columns are matched up by name rather than by position.
116 by_name: bool,
117 /// The query on the left.
118 left: QueryRef,
119 /// The query on the right.
120 right: QueryRef,
121 },
122}
123
124/// Which set operator.
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126pub enum SetOp {
127 /// `UNION`.
128 Union,
129 /// `EXCEPT`.
130 Except,
131 /// `INTERSECT`.
132 Intersect,
133}
134
135/// Whether a set operator or an aggregate keeps duplicates.
136///
137/// `Unstated` is not the same as `All` even though the two agree for `UNION`, because they disagree
138/// for `INTERSECT` in some dialects and because an error message that says what was written is
139/// better than one that says what it was taken to mean.
140#[derive(Debug, Clone, Copy, PartialEq, Eq)]
141pub enum Quantifier {
142 /// Neither word was written.
143 Unstated,
144 /// `ALL`.
145 All,
146 /// `DISTINCT`.
147 Distinct,
148}
149
150/// What the `DISTINCT` clause of a select said.
151#[derive(Debug, Clone, Copy, PartialEq, Eq)]
152pub enum Distinct {
153 /// No clause, or the no-op `SELECT ALL`.
154 No,
155 /// `SELECT DISTINCT`.
156 Yes,
157 /// `SELECT DISTINCT ON (a, b)`, holding the expressions in the parentheses.
158 On(Slice),
159}
160
161/// One select block.
162///
163/// Every optional expression is `NONE` when it is absent rather than an `Option<u32>`, which keeps
164/// the struct at forty bytes and keeps the absent case spelled the same way it is spelled in the
165/// parse tree arena.
166#[derive(Debug, Clone, Copy, PartialEq, Eq)]
167pub struct Select {
168 /// The `DISTINCT` clause.
169 pub distinct: Distinct,
170 /// The target list, as a run of [`Target`].
171 pub targets: Slice,
172 /// The `FROM` list, as a run of [`SourceRef`]. Several entries mean a cross product.
173 pub from: Slice,
174 /// The `WHERE` expression, or `NONE`.
175 pub filter: ExprRef,
176 /// The `GROUP BY` list, as a run of [`ExprRef`].
177 pub group_by: Slice,
178 /// Whether the clause was `GROUP BY ALL`.
179 pub group_by_all: bool,
180 /// The `HAVING` expression, or `NONE`.
181 pub having: ExprRef,
182}
183
184impl Select {
185 /// An empty select, which is what the transformer fills in from.
186 pub const fn empty() -> Self {
187 Self {
188 distinct: Distinct::No,
189 targets: Slice { start: 0, len: 0 },
190 from: Slice { start: 0, len: 0 },
191 filter: NONE,
192 group_by: Slice { start: 0, len: 0 },
193 group_by_all: false,
194 having: NONE,
195 }
196 }
197}
198
199/// One entry of a target list.
200#[derive(Debug, Clone, Copy, PartialEq, Eq)]
201pub struct Target {
202 /// What is being selected.
203 pub expr: ExprRef,
204 /// The alias, or `NONE`. The binder invents one when there is none, because what it invents
205 /// depends on the expression and that is a binder question rather than a parser question.
206 pub alias: StrRef,
207}
208
209/// One entry of an order by list.
210#[derive(Debug, Clone, Copy, PartialEq, Eq)]
211pub struct OrderItem {
212 /// What to sort on.
213 pub expr: ExprRef,
214 /// The direction.
215 pub order: Order,
216 /// Where nulls go.
217 pub nulls: Nulls,
218}
219
220/// Sort direction, with the unwritten case kept apart from the default it resolves to.
221#[derive(Debug, Clone, Copy, PartialEq, Eq)]
222pub enum Order {
223 /// Nothing was written.
224 Unstated,
225 /// `ASC` or `ASCENDING`.
226 Ascending,
227 /// `DESC` or `DESCENDING`.
228 Descending,
229}
230
231/// Null placement in a sort.
232#[derive(Debug, Clone, Copy, PartialEq, Eq)]
233pub enum Nulls {
234 /// Nothing was written, so the session default applies.
235 Unstated,
236 /// `NULLS FIRST`.
237 First,
238 /// `NULLS LAST`.
239 Last,
240}
241
242/// One entry in a `FROM` clause, which is a tree because joins nest.
243#[derive(Debug, Clone, Copy, PartialEq, Eq)]
244pub enum Source {
245 /// A named table, possibly qualified by schema and catalog.
246 Table {
247 /// The name, as a run of [`StrRef`] in `Ast::parts`, outermost first.
248 name: Slice,
249 /// The alias, or `NONE`.
250 alias: StrRef,
251 /// Column aliases from `AS t(a, b)`, as a run of [`StrRef`].
252 columns: Slice,
253 },
254 /// A parenthesised query in the `FROM` clause.
255 Subquery {
256 /// The query.
257 query: QueryRef,
258 /// The alias, or `NONE`.
259 alias: StrRef,
260 /// Column aliases, as a run of [`StrRef`].
261 columns: Slice,
262 },
263 /// Two sources joined.
264 Join {
265 /// The left side.
266 left: SourceRef,
267 /// The right side.
268 right: SourceRef,
269 /// Which join.
270 kind: JoinKind,
271 /// Whether it was written `NATURAL`.
272 natural: bool,
273 /// The `ON` expression, or `NONE`.
274 on: ExprRef,
275 /// The `USING` column list, as a run of [`StrRef`].
276 using: Slice,
277 },
278}
279
280/// Which join.
281#[derive(Debug, Clone, Copy, PartialEq, Eq)]
282pub enum JoinKind {
283 /// `[INNER] JOIN`.
284 Inner,
285 /// `LEFT [OUTER] JOIN`.
286 Left,
287 /// `RIGHT [OUTER] JOIN`.
288 Right,
289 /// `FULL [OUTER] JOIN`.
290 Full,
291 /// `SEMI JOIN`.
292 Semi,
293 /// `ANTI JOIN`.
294 Anti,
295 /// `CROSS JOIN`.
296 Cross,
297 /// `POSITIONAL JOIN`, which is DuckDB's own and pairs rows by ordinal.
298 Positional,
299}
300
301/// One expression.
302///
303/// Twenty four bytes, which is the widest variant rounded up. The precedence chain in the grammar
304/// does not survive into here: twenty levels of `X <- Y Tail*` become one [`Expr::Binary`] tree,
305/// because the levels exist to make the grammar unambiguous and mean nothing afterwards.
306#[derive(Debug, Clone, Copy, PartialEq, Eq)]
307pub enum Expr {
308 /// `*`, or `t.*` with a qualifier.
309 Star {
310 /// The qualifier, as a run of [`StrRef`], empty for a bare star.
311 qualifier: Slice,
312 },
313 /// A column reference, qualified or not.
314 Column {
315 /// The name, as a run of [`StrRef`], outermost first, so `s.t.a` is three parts.
316 name: Slice,
317 },
318 /// A literal, kept as the text that was written.
319 Literal {
320 /// Which kind.
321 kind: LiteralKind,
322 /// The text, with quotes stripped and escapes resolved for a string, `NONE` for a keyword
323 /// literal like `NULL` where the kind already says everything.
324 text: StrRef,
325 },
326 /// A prefix or postfix operator.
327 Unary {
328 /// Which operator.
329 op: UnaryOp,
330 /// What it applies to.
331 operand: ExprRef,
332 },
333 /// An infix operator.
334 Binary {
335 /// Which operator.
336 op: BinaryOp,
337 /// The left operand.
338 left: ExprRef,
339 /// The right operand.
340 right: ExprRef,
341 },
342 /// A function call.
343 Function {
344 /// The name, as a run of [`StrRef`], so `main.count` is two parts.
345 name: Slice,
346 /// The arguments, as a run of [`ExprRef`].
347 args: Slice,
348 /// Whether the call said `DISTINCT`.
349 distinct: bool,
350 },
351 /// `CAST(x AS t)` or `TRY_CAST(x AS t)`.
352 Cast {
353 /// What is being cast.
354 operand: ExprRef,
355 /// The target type, as the text it was written with. Parsing it is `rudb-common`'s job and
356 /// doing it here would put the type system in the parser.
357 ty: StrRef,
358 /// Whether a failure yields null rather than an error.
359 try_cast: bool,
360 },
361 /// `CASE`, searched or simple.
362 Case {
363 /// The operand of a simple `CASE x WHEN`, or `NONE` for a searched one.
364 operand: ExprRef,
365 /// The arms, as a run of [`CaseArm`].
366 arms: Slice,
367 /// The `ELSE`, or `NONE`.
368 otherwise: ExprRef,
369 },
370 /// `x BETWEEN a AND b`.
371 Between {
372 /// What is being tested.
373 operand: ExprRef,
374 /// The lower bound.
375 low: ExprRef,
376 /// The upper bound.
377 high: ExprRef,
378 /// Whether it was written `NOT BETWEEN`.
379 negated: bool,
380 },
381 /// `x IN (a, b, c)`.
382 In {
383 /// What is being tested.
384 operand: ExprRef,
385 /// The list, as a run of [`ExprRef`].
386 list: Slice,
387 /// Whether it was written `NOT IN`.
388 negated: bool,
389 },
390 /// A parenthesised list of more than one expression, which is a row value.
391 Row {
392 /// The items, as a run of [`ExprRef`].
393 items: Slice,
394 },
395 /// A scalar subquery, `(SELECT ...)` where an expression is expected.
396 Subquery {
397 /// The query.
398 query: QueryRef,
399 },
400}
401
402/// One `WHEN a THEN b`.
403#[derive(Debug, Clone, Copy, PartialEq, Eq)]
404pub struct CaseArm {
405 /// The `WHEN`.
406 pub when: ExprRef,
407 /// The `THEN`.
408 pub then: ExprRef,
409}
410
411/// Which literal.
412#[derive(Debug, Clone, Copy, PartialEq, Eq)]
413pub enum LiteralKind {
414 /// A number, kept as text because the width it wants depends on where it lands.
415 Number,
416 /// A string.
417 String,
418 /// `NULL`.
419 Null,
420 /// `TRUE`.
421 True,
422 /// `FALSE`.
423 False,
424}
425
426/// A prefix or postfix operator.
427#[derive(Debug, Clone, Copy, PartialEq, Eq)]
428pub enum UnaryOp {
429 /// `NOT x`.
430 Not,
431 /// `-x`.
432 Negate,
433 /// `+x`, which is a no-op that still has to survive to the binder so that `+'a'` errors.
434 Plus,
435 /// `~x`.
436 BitNot,
437 /// `x!`.
438 Factorial,
439 /// `x IS NULL` or `x ISNULL`.
440 IsNull,
441 /// `x IS NOT NULL` or `x NOTNULL`.
442 IsNotNull,
443 /// `x IS TRUE`.
444 IsTrue,
445 /// `x IS NOT TRUE`.
446 IsNotTrue,
447 /// `x IS FALSE`.
448 IsFalse,
449 /// `x IS NOT FALSE`.
450 IsNotFalse,
451 /// `x IS UNKNOWN`.
452 IsUnknown,
453 /// `x IS NOT UNKNOWN`.
454 IsNotUnknown,
455}
456
457/// An infix operator.
458///
459/// The list is the dialect and not a general idea of what operators are. `Named` is the one open
460/// door, because `OperatorLiteral` in the grammar takes any run of operator characters that is not
461/// already a token, and rejecting that here would reject SQL DuckDB accepts.
462#[derive(Debug, Clone, Copy, PartialEq, Eq)]
463pub enum BinaryOp {
464 /// `OR`.
465 Or,
466 /// `AND`.
467 And,
468 /// `=` or `==`.
469 Eq,
470 /// `!=` or `<>`.
471 NotEq,
472 /// `<`.
473 Lt,
474 /// `>`.
475 Gt,
476 /// `<=`.
477 LtEq,
478 /// `>=`.
479 GtEq,
480 /// `IS DISTINCT FROM`.
481 IsDistinctFrom,
482 /// `IS NOT DISTINCT FROM`.
483 IsNotDistinctFrom,
484 /// `+`.
485 Add,
486 /// `-`.
487 Subtract,
488 /// `*`.
489 Multiply,
490 /// `/`.
491 Divide,
492 /// `//`, integer division.
493 IntegerDivide,
494 /// `%`.
495 Modulo,
496 /// `^` or `**`.
497 Power,
498 /// `&`.
499 BitAnd,
500 /// `|`.
501 BitOr,
502 /// `<<`.
503 ShiftLeft,
504 /// `>>`.
505 ShiftRight,
506 /// `||`.
507 Concat,
508 /// `LIKE` or `~~`.
509 Like,
510 /// `NOT LIKE` or `!~~`.
511 NotLike,
512 /// `ILIKE` or `~~*`.
513 ILike,
514 /// `NOT ILIKE` or `!~~*`.
515 NotILike,
516 /// `GLOB` or `~~~`.
517 Glob,
518 /// `SIMILAR TO`.
519 SimilarTo,
520 /// `!~`, which the grammar calls the not-similar-to operator.
521 NotSimilarTo,
522 /// `~`, a regex match.
523 Regex,
524 /// `~*`, a case insensitive regex match.
525 RegexInsensitive,
526 /// `!~*`, a negated case insensitive regex match.
527 NotRegexInsensitive,
528 /// `COLLATE`.
529 Collate,
530 /// `AT TIME ZONE`.
531 AtTimeZone,
532 /// `->`.
533 Arrow,
534 /// `->>`.
535 LongArrow,
536 /// `@>`, contains.
537 Contains,
538 /// `<@`, contained by.
539 ContainedBy,
540 /// `&&`, overlaps.
541 Overlaps,
542 /// `^@`, starts with.
543 StartsWith,
544 /// `<<=`, an inet operator.
545 InetContainedByOrEq,
546 /// `>>=`, an inet operator.
547 InetContainsOrEq,
548 /// An operator the dialect does not name, which DuckDB resolves as a binary function of that
549 /// name. `a <=> b` is the shape.
550 Named(StrRef),
551}
552
553/// A parsed statement or script, with every arena it points into.
554///
555/// Cheap to clone, cheap to send, and self contained: no index in here refers to anything outside
556/// it, and nothing in here borrows the query text. The text is copied into `strings` on the way in,
557/// which costs one allocation per distinct identifier and buys an `Ast` that outlives the string it
558/// came from.
559#[derive(Debug, Clone, Default, PartialEq, Eq)]
560pub struct Ast {
561 /// The statements in the script, in order.
562 pub statements: Vec<Statement>,
563 /// The query arena.
564 pub queries: Vec<Query>,
565 /// The select arena.
566 pub selects: Vec<Select>,
567 /// The expression arena.
568 pub exprs: Vec<Expr>,
569 /// The from-item arena.
570 pub sources: Vec<Source>,
571 /// Interned text. Identifiers keep the case they were written in, because DuckDB does not fold
572 /// it at any point, including for quoted identifiers.
573 pub strings: Vec<String>,
574 /// Backing store for every [`Slice`] of names.
575 pub parts: Vec<StrRef>,
576 /// Backing store for every [`Slice`] of expressions.
577 pub expr_lists: Vec<ExprRef>,
578 /// Backing store for every [`Slice`] of from items.
579 pub source_lists: Vec<SourceRef>,
580 /// Backing store for every [`Slice`] of target list entries.
581 pub targets: Vec<Target>,
582 /// Backing store for every [`Slice`] of order by entries.
583 pub order_items: Vec<OrderItem>,
584 /// Backing store for every [`Slice`] of case arms.
585 pub case_arms: Vec<CaseArm>,
586}
587
588impl Ast {
589 /// The text behind a [`StrRef`], or the empty string for `NONE`.
590 pub fn string(&self, index: StrRef) -> &str {
591 if index == NONE { "" } else { &self.strings[index as usize] }
592 }
593
594 /// The parts of a name, outermost first.
595 pub fn name(&self, slice: Slice) -> impl Iterator<Item = &str> {
596 self.parts[slice.range()].iter().map(|&part| self.string(part))
597 }
598
599 /// A name written back out with dots between the parts, for error messages and tests.
600 pub fn name_text(&self, slice: Slice) -> String {
601 self.name(slice).collect::<Vec<_>>().join(".")
602 }
603
604 /// One expression.
605 pub fn expr(&self, index: ExprRef) -> Expr {
606 self.exprs[index as usize]
607 }
608
609 /// One from item.
610 pub fn source(&self, index: SourceRef) -> Source {
611 self.sources[index as usize]
612 }
613
614 /// One query.
615 pub fn query(&self, index: QueryRef) -> Query {
616 self.queries[index as usize]
617 }
618
619 /// One select block.
620 pub fn select(&self, index: SelectRef) -> Select {
621 self.selects[index as usize]
622 }
623
624 /// The expressions of a list.
625 pub fn expr_list(&self, slice: Slice) -> &[ExprRef] {
626 &self.expr_lists[slice.range()]
627 }
628
629 /// The from items of a list.
630 pub fn source_list(&self, slice: Slice) -> &[SourceRef] {
631 &self.source_lists[slice.range()]
632 }
633
634 /// The entries of a target list.
635 pub fn target_list(&self, slice: Slice) -> &[Target] {
636 &self.targets[slice.range()]
637 }
638
639 /// The entries of an order by list.
640 pub fn order_list(&self, slice: Slice) -> &[OrderItem] {
641 &self.order_items[slice.range()]
642 }
643
644 /// The arms of a case.
645 pub fn arm_list(&self, slice: Slice) -> &[CaseArm] {
646 &self.case_arms[slice.range()]
647 }
648
649 /// How many nodes the whole tree is, across every arena.
650 ///
651 /// The number to watch when the transformer changes. A parse tree of five thousand nodes that
652 /// becomes an AST of thirty is the twenty precedence levels being thrown away, which is the
653 /// whole reason this module exists.
654 pub fn node_count(&self) -> usize {
655 self.queries.len() + self.selects.len() + self.exprs.len() + self.sources.len()
656 }
657}