Skip to main content

mz_expr_parser/
parser.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10// Copyright Materialize, Inc. and contributors. All rights reserved.
11//
12// Use of this software is governed by the Business Source License
13// included in the LICENSE file.
14//
15// As of the Change Date specified in that file, in accordance with
16// the Business Source License, use of this software will be governed
17// by the Apache License, Version 2.0.
18
19use mz_ore::collections::CollectionExt;
20use proc_macro2::LineColumn;
21use syn::Error;
22use syn::parse::{Parse, ParseStream, Parser};
23use syn::spanned::Spanned;
24
25use super::TestCatalog;
26
27use self::util::*;
28
29/// Builds a [mz_expr::MirRelationExpr] from a string.
30pub fn try_parse_mir(catalog: &TestCatalog, s: &str) -> Result<mz_expr::MirRelationExpr, String> {
31    // Define a Parser that constructs a (read-only) parsing context `ctx` and
32    // delegates to `relation::parse_expr` by passing a `ctx` as a shared ref.
33    let parser = move |input: ParseStream| {
34        let ctx = Ctx { catalog };
35        relation::parse_expr(&ctx, input)
36    };
37    // Since the syn lexer doesn't parse comments, we replace all `// {`
38    // occurrences in the input string with `:: {`.
39    let s = s.replace("// {", ":: {");
40    // Call the parser with the given input string.
41    let mut expr = parser.parse_str(&s).map_err(|err| {
42        let (line, column) = (err.span().start().line, err.span().start().column);
43        format!("parse error at {line}:{column}:\n{err}\n")
44    })?;
45    // Fix the types of the local let bindings of the parsed expression in a
46    // post-processing pass.
47    relation::fix_types(&mut expr, &mut relation::FixTypesCtx::default())?;
48    // Return the parsed, post-processed expression.
49    Ok(expr)
50}
51
52/// Builds a [mz_expr::MirScalarExpr] from a string.
53pub fn try_parse_scalar(s: &str) -> Result<mz_expr::MirScalarExpr, String> {
54    let parser = |input: syn::parse::ParseStream| {
55        let expr = scalar::parse_expr(input)?;
56        if !input.is_empty() {
57            Err(Error::new(
58                input.span(),
59                "unexpected input after expression",
60            ))?
61        }
62        Ok(expr)
63    };
64    parser.parse_str(s).map_err(|err| {
65        let (line, column) = (err.span().start().line, err.span().start().column);
66        format!("parse error at {line}:{column}:\n{err}\n")
67    })
68}
69
70/// Builds a comma-separated list of [mz_expr::MirScalarExpr]s from a string.
71pub fn try_parse_scalars(s: &str) -> Result<Vec<mz_expr::MirScalarExpr>, String> {
72    let parser = |input: syn::parse::ParseStream| {
73        let exprs = scalar::parse_exprs(input)?;
74        if !input.is_empty() {
75            Err(Error::new(
76                input.span(),
77                "unexpected input after expressions",
78            ))?
79        }
80        Ok(exprs)
81    };
82    parser.parse_str(s).map_err(|err| {
83        let (line, column) = (err.span().start().line, err.span().start().column);
84        format!("parse error at {line}:{column}:\n{err}\n")
85    })
86}
87
88/// Parses a parenthesized, comma-separated column type list, for example
89/// `(bigint, text?)`. A trailing `?` marks a column as nullable.
90pub fn try_parse_column_types(s: &str) -> Result<Vec<mz_repr::SqlColumnType>, String> {
91    let parser = |input: syn::parse::ParseStream| {
92        let inner;
93        syn::parenthesized!(inner in input);
94        let types = inner.parse_comma_sep(analyses::parse_column_type)?;
95        if !input.is_empty() {
96            Err(Error::new(input.span(), "unexpected input after type list"))?
97        }
98        Ok(types
99            .iter()
100            .map(mz_repr::SqlColumnType::from_repr)
101            .collect())
102    };
103    parser.parse_str(s).map_err(|err| {
104        let (line, column) = (err.span().start().line, err.span().start().column);
105        format!("parse error at {line}:{column}:\n{err}\n")
106    })
107}
108
109/// Builds a source definition from a string.
110pub fn try_parse_def(catalog: &TestCatalog, s: &str) -> Result<Def, String> {
111    // Define a Parser that constructs a (read-only) parsing context `ctx` and
112    // delegates to `relation::parse_expr` by passing a `ctx` as a shared ref.
113    let parser = move |input: ParseStream| {
114        let ctx = Ctx { catalog };
115        def::parse_def(&ctx, input)
116    };
117    // Call the parser with the given input string.
118    let def = parser.parse_str(s).map_err(|err| {
119        let (line, column) = (err.span().start().line, err.span().start().column);
120        format!("parse error at {line}:{column}:\n{err}\n")
121    })?;
122    // Return the parsed, post-processed expression.
123    Ok(def)
124}
125
126/// Support for parsing [mz_expr::MirRelationExpr].
127mod relation {
128    use std::collections::BTreeMap;
129
130    use mz_expr::{AccessStrategy, Id, JoinImplementation, LocalId, MirRelationExpr};
131    use mz_repr::{Diff, ReprRelationType, Row, SqlScalarType};
132
133    use crate::parser::analyses::Analyses;
134
135    use super::*;
136
137    type Result = syn::Result<MirRelationExpr>;
138
139    pub fn parse_expr(ctx: CtxRef, input: ParseStream) -> Result {
140        let lookahead = input.lookahead1();
141        if lookahead.peek(kw::Constant) {
142            parse_constant(ctx, input)
143        } else if lookahead.peek(kw::Get) {
144            parse_get(ctx, input)
145        } else if lookahead.peek(kw::Return) {
146            parse_let_or_letrec_old(ctx, input)
147        } else if lookahead.peek(kw::With) {
148            parse_let_or_letrec(ctx, input)
149        } else if lookahead.peek(kw::Project) {
150            parse_project(ctx, input)
151        } else if lookahead.peek(kw::Map) {
152            parse_map(ctx, input)
153        } else if lookahead.peek(kw::FlatMap) {
154            parse_flat_map(ctx, input)
155        } else if lookahead.peek(kw::Filter) {
156            parse_filter(ctx, input)
157        } else if lookahead.peek(kw::CrossJoin) {
158            parse_cross_join(ctx, input)
159        } else if lookahead.peek(kw::Join) {
160            parse_join(ctx, input)
161        } else if lookahead.peek(kw::Distinct) {
162            parse_distinct(ctx, input)
163        } else if lookahead.peek(kw::Reduce) {
164            parse_reduce(ctx, input)
165        } else if lookahead.peek(kw::TopK) {
166            parse_top_k(ctx, input)
167        } else if lookahead.peek(kw::Negate) {
168            parse_negate(ctx, input)
169        } else if lookahead.peek(kw::Threshold) {
170            parse_threshold(ctx, input)
171        } else if lookahead.peek(kw::Union) {
172            parse_union(ctx, input)
173        } else if lookahead.peek(kw::ArrangeBy) {
174            parse_arrange_by(ctx, input)
175        } else {
176            Err(lookahead.error())
177        }
178    }
179
180    fn parse_constant(_ctx: CtxRef, input: ParseStream) -> Result {
181        let constant = input.parse::<kw::Constant>()?;
182
183        let parse_typ = |input: ParseStream| -> syn::Result<ReprRelationType> {
184            let analyses = analyses::parse_analyses(input)?;
185            let Some(column_types) = analyses.types else {
186                let msg = "Missing expected `types` analyses for Constant line";
187                Err(Error::new(input.span(), msg))?
188            };
189            let keys = analyses.keys.unwrap_or_default();
190            Ok(ReprRelationType::new(column_types).with_keys(keys))
191        };
192        if input.eat3(syn::Token![<], kw::empty, syn::Token![>]) {
193            let typ = parse_typ(input)?;
194            Ok(MirRelationExpr::Constant {
195                rows: Ok(vec![]),
196                typ,
197            })
198        } else {
199            let typ = parse_typ(input)?;
200            let parse_children = ParseChildren::new(input, constant.span().start());
201            let rows = Ok(parse_children.parse_many(&typ, parse_constant_entry)?);
202            Ok(MirRelationExpr::Constant { rows, typ })
203        }
204    }
205
206    fn parse_constant_entry(
207        typ: &ReprRelationType,
208        input: ParseStream,
209    ) -> syn::Result<(Row, Diff)> {
210        input.parse::<syn::Token![-]>()?;
211
212        let (row, diff);
213
214        let inner1;
215        syn::parenthesized!(inner1 in input);
216
217        if inner1.peek(syn::token::Paren) {
218            let inner2;
219            syn::parenthesized!(inner2 in inner1);
220            row = row::parse_row(&inner2, &typ.column_types)?;
221            inner1.parse::<kw::x>()?;
222            diff = match inner1.parse::<syn::Lit>()? {
223                syn::Lit::Int(l) => Ok(l.base10_parse::<Diff>()?),
224                _ => Err(Error::new(inner1.span(), "expected Diff literal")),
225            }?;
226        } else {
227            row = row::parse_row(&inner1, &typ.column_types)?;
228            diff = Diff::ONE;
229        }
230
231        Ok((row, diff))
232    }
233
234    fn parse_get(ctx: CtxRef, input: ParseStream) -> Result {
235        input.parse::<kw::Get>()?;
236
237        let ident = input.parse::<syn::Ident>()?;
238        match ctx.catalog.get(&ident.to_string()) {
239            Some((id, _cols, typ)) => Ok(MirRelationExpr::Get {
240                id: Id::Global(*id),
241                typ: ReprRelationType::from(typ),
242                access_strategy: AccessStrategy::UnknownOrLocal,
243            }),
244            None => Ok(MirRelationExpr::Get {
245                id: Id::Local(parse_local_id(ident)?),
246                typ: ReprRelationType::empty(),
247                access_strategy: AccessStrategy::UnknownOrLocal,
248            }),
249        }
250    }
251
252    /// Parses a Let or a LetRec with the old order: Return first, and then CTEs in descending order.
253    fn parse_let_or_letrec_old(ctx: CtxRef, input: ParseStream) -> Result {
254        let return_ = input.parse::<kw::Return>()?;
255        let parse_body = ParseChildren::new(input, return_.span().start());
256        let body = parse_body.parse_one(ctx, parse_expr)?;
257
258        let with = input.parse::<kw::With>()?;
259        let recursive = input.eat2(kw::Mutually, kw::Recursive);
260        let parse_ctes = ParseChildren::new(input, with.span().start());
261        let mut ctes = parse_ctes.parse_many(ctx, parse_cte)?;
262
263        if ctes.is_empty() {
264            let msg = "At least one Let/LetRec cte binding expected";
265            Err(Error::new(input.span(), msg))?
266        }
267
268        ctes.reverse();
269        let cte_ids = ctes.iter().map(|(id, _, _)| id);
270        if !cte_ids.clone().is_sorted() {
271            let msg = format!(
272                "Error parsing Let/LetRec: seen Return before With, but cte ids are not ordered descending: {:?}",
273                cte_ids.collect::<Vec<_>>()
274            );
275            Err(Error::new(input.span(), msg))?
276        }
277        build_let_or_let_rec(ctes, body, recursive, with)
278    }
279
280    /// Parses a Let or a LetRec with the new order: CTEs first in ascending order, and then Return.
281    fn parse_let_or_letrec(ctx: CtxRef, input: ParseStream) -> Result {
282        let with = input.parse::<kw::With>()?;
283        let recursive = input.eat2(kw::Mutually, kw::Recursive);
284        let parse_ctes = ParseChildren::new(input, with.span().start());
285        let ctes = parse_ctes.parse_many(ctx, parse_cte)?;
286
287        let return_ = input.parse::<kw::Return>()?;
288        let parse_body = ParseChildren::new(input, return_.span().start());
289        let body = parse_body.parse_one(ctx, parse_expr)?;
290
291        if ctes.is_empty() {
292            let msg = "At least one `let cte` binding expected";
293            Err(Error::new(input.span(), msg))?
294        }
295
296        let cte_ids = ctes.iter().map(|(id, _, _)| id);
297        if !cte_ids.clone().is_sorted() {
298            let msg = format!(
299                "Error parsing Let/LetRec: seen With before Return, but cte ids are not ordered ascending: {:?}",
300                cte_ids.collect::<Vec<_>>()
301            );
302            Err(Error::new(input.span(), msg))?
303        }
304        build_let_or_let_rec(ctes, body, recursive, with)
305    }
306
307    fn build_let_or_let_rec(
308        ctes: Vec<(LocalId, Analyses, MirRelationExpr)>,
309        body: MirRelationExpr,
310        recursive: bool,
311        with: kw::With,
312    ) -> Result {
313        if recursive {
314            let (mut ids, mut values, mut limits) = (vec![], vec![], vec![]);
315            for (id, analyses, value) in ctes.into_iter() {
316                let typ = {
317                    let Some(column_types) = analyses.types else {
318                        let msg = format!("`let {}` needs a `types` analyses", id);
319                        Err(Error::new(with.span(), msg))?
320                    };
321                    let keys = analyses.keys.unwrap_or_default();
322                    ReprRelationType::new(column_types).with_keys(keys)
323                };
324                // An ugly-ugly hack to pass the type information of the WMR CTE
325                // to the `fix_types` pass.
326                let value = {
327                    let get_cte = MirRelationExpr::Get {
328                        id: Id::Local(id),
329                        typ,
330                        access_strategy: AccessStrategy::UnknownOrLocal,
331                    };
332                    // Do not use the `union` smart constructor here!
333                    MirRelationExpr::Union {
334                        base: Box::new(get_cte),
335                        inputs: vec![value],
336                    }
337                };
338
339                ids.push(id);
340                values.push(value);
341                limits.push(None); // TODO: support limits
342            }
343
344            Ok(MirRelationExpr::LetRec {
345                ids,
346                values,
347                limits,
348                body: Box::new(body),
349            })
350        } else {
351            let mut body = body;
352            for (id, _, value) in ctes.into_iter().rev() {
353                body = MirRelationExpr::Let {
354                    id,
355                    value: Box::new(value),
356                    body: Box::new(body),
357                };
358            }
359            Ok(body)
360        }
361    }
362
363    fn parse_cte(
364        ctx: CtxRef,
365        input: ParseStream,
366    ) -> syn::Result<(LocalId, analyses::Analyses, MirRelationExpr)> {
367        let cte = input.parse::<kw::cte>()?;
368
369        let ident = input.parse::<syn::Ident>()?;
370        let id = parse_local_id(ident)?;
371
372        input.parse::<syn::Token![=]>()?;
373
374        let analyses = analyses::parse_analyses(input)?;
375
376        let parse_value = ParseChildren::new(input, cte.span().start());
377        let value = parse_value.parse_one(ctx, parse_expr)?;
378
379        Ok((id, analyses, value))
380    }
381
382    fn parse_project(ctx: CtxRef, input: ParseStream) -> Result {
383        let project = input.parse::<kw::Project>()?;
384
385        let content;
386        syn::parenthesized!(content in input);
387        let outputs = content.parse_comma_sep(scalar::parse_column_index)?;
388        let parse_input = ParseChildren::new(input, project.span().start());
389        let input = Box::new(parse_input.parse_one(ctx, parse_expr)?);
390
391        Ok(MirRelationExpr::Project { input, outputs })
392    }
393
394    fn parse_map(ctx: CtxRef, input: ParseStream) -> Result {
395        let map = input.parse::<kw::Map>()?;
396
397        let scalars = {
398            let inner;
399            syn::parenthesized!(inner in input);
400            scalar::parse_exprs(&inner)?
401        };
402
403        let parse_input = ParseChildren::new(input, map.span().start());
404        let input = Box::new(parse_input.parse_one(ctx, parse_expr)?);
405
406        Ok(MirRelationExpr::Map { input, scalars })
407    }
408
409    fn parse_flat_map(ctx: CtxRef, input: ParseStream) -> Result {
410        use mz_expr::TableFunc::*;
411
412        let flat_map = input.parse::<kw::FlatMap>()?;
413
414        let ident = input.parse::<syn::Ident>()?;
415        let func = match ident.to_string().to_lowercase().as_str() {
416            "unnest_list" => UnnestList {
417                el_typ: SqlScalarType::Int64, // FIXME
418            },
419            "unnest_array" => UnnestArray {
420                el_typ: SqlScalarType::Int64, // FIXME
421            },
422            "wrap1" => Wrap {
423                types: vec![
424                    SqlScalarType::Int64.nullable(true), // FIXME
425                ],
426                width: 1,
427            },
428            "wrap2" => Wrap {
429                types: vec![
430                    SqlScalarType::Int64.nullable(true), // FIXME
431                    SqlScalarType::Int64.nullable(true), // FIXME
432                ],
433                width: 2,
434            },
435            "wrap3" => Wrap {
436                types: vec![
437                    SqlScalarType::Int64.nullable(true), // FIXME
438                    SqlScalarType::Int64.nullable(true), // FIXME
439                    SqlScalarType::Int64.nullable(true), // FIXME
440                ],
441                width: 3,
442            },
443            "generate_series" => GenerateSeriesInt64,
444            // Both int widths display as `generate_series`; this spelling lets a
445            // test pin the 32-bit variant (e.g. its widening casts) on input.
446            "generate_series_i32" => GenerateSeriesInt32,
447            "jsonb_object_keys" => JsonbObjectKeys,
448            _ => Err(Error::new(ident.span(), "unsupported function name"))?,
449        };
450
451        let exprs = {
452            let inner;
453            syn::parenthesized!(inner in input);
454            scalar::parse_exprs(&inner)?
455        };
456
457        let parse_input = ParseChildren::new(input, flat_map.span().start());
458        let input = Box::new(parse_input.parse_one(ctx, parse_expr)?);
459
460        Ok(MirRelationExpr::FlatMap { input, func, exprs })
461    }
462
463    fn parse_filter(ctx: CtxRef, input: ParseStream) -> Result {
464        use mz_expr::MirScalarExpr::CallVariadic;
465        use mz_expr::VariadicFunc::And;
466
467        let filter = input.parse::<kw::Filter>()?;
468
469        let predicates = match scalar::parse_expr(input)? {
470            CallVariadic {
471                func: And(_),
472                exprs,
473            } => exprs,
474            expr => vec![expr],
475        };
476
477        let parse_input = ParseChildren::new(input, filter.span().start());
478        let input = Box::new(parse_input.parse_one(ctx, parse_expr)?);
479
480        Ok(MirRelationExpr::Filter { input, predicates })
481    }
482
483    fn parse_cross_join(ctx: CtxRef, input: ParseStream) -> Result {
484        let join = input.parse::<kw::CrossJoin>()?;
485
486        let parse_inputs = ParseChildren::new(input, join.span().start());
487        let inputs = parse_inputs.parse_many(ctx, parse_expr)?;
488
489        Ok(MirRelationExpr::Join {
490            inputs,
491            equivalences: vec![],
492            implementation: JoinImplementation::Unimplemented,
493        })
494    }
495
496    fn parse_join(ctx: CtxRef, input: ParseStream) -> Result {
497        let join = input.parse::<kw::Join>()?;
498
499        input.parse::<kw::on>()?;
500        input.parse::<syn::Token![=]>()?;
501        let inner;
502        syn::parenthesized!(inner in input);
503        let equivalences = scalar::parse_join_equivalences(&inner)?;
504
505        let parse_inputs = ParseChildren::new(input, join.span().start());
506        let inputs = parse_inputs.parse_many(ctx, parse_expr)?;
507
508        Ok(MirRelationExpr::Join {
509            inputs,
510            equivalences,
511            implementation: JoinImplementation::Unimplemented,
512        })
513    }
514
515    fn parse_distinct(ctx: CtxRef, input: ParseStream) -> Result {
516        let reduce = input.parse::<kw::Distinct>()?;
517
518        let group_key = if input.eat(kw::project) {
519            input.parse::<syn::Token![=]>()?;
520            let inner;
521            syn::bracketed!(inner in input);
522            inner.parse_comma_sep(scalar::parse_expr)?
523        } else {
524            vec![]
525        };
526
527        let monotonic = input.eat(kw::monotonic);
528
529        let expected_group_size = if input.eat(kw::exp_group_size) {
530            input.parse::<syn::Token![=]>()?;
531            Some(input.parse::<syn::LitInt>()?.base10_parse::<u64>()?)
532        } else {
533            None
534        };
535
536        let parse_inputs = ParseChildren::new(input, reduce.span().start());
537        let input = Box::new(parse_inputs.parse_one(ctx, parse_expr)?);
538
539        Ok(MirRelationExpr::Reduce {
540            input,
541            group_key,
542            aggregates: vec![],
543            monotonic,
544            expected_group_size,
545        })
546    }
547
548    fn parse_reduce(ctx: CtxRef, input: ParseStream) -> Result {
549        let reduce = input.parse::<kw::Reduce>()?;
550
551        let group_key = if input.eat(kw::group_by) {
552            input.parse::<syn::Token![=]>()?;
553            let inner;
554            syn::bracketed!(inner in input);
555            inner.parse_comma_sep(scalar::parse_expr)?
556        } else {
557            vec![]
558        };
559
560        let aggregates = {
561            input.parse::<kw::aggregates>()?;
562            input.parse::<syn::Token![=]>()?;
563            let inner;
564            syn::bracketed!(inner in input);
565            inner.parse_comma_sep(aggregate::parse_expr)?
566        };
567
568        let monotonic = input.eat(kw::monotonic);
569
570        let expected_group_size = if input.eat(kw::exp_group_size) {
571            input.parse::<syn::Token![=]>()?;
572            Some(input.parse::<syn::LitInt>()?.base10_parse::<u64>()?)
573        } else {
574            None
575        };
576
577        let parse_inputs = ParseChildren::new(input, reduce.span().start());
578        let input = Box::new(parse_inputs.parse_one(ctx, parse_expr)?);
579
580        Ok(MirRelationExpr::Reduce {
581            input,
582            group_key,
583            aggregates,
584            monotonic,
585            expected_group_size,
586        })
587    }
588
589    fn parse_top_k(ctx: CtxRef, input: ParseStream) -> Result {
590        let top_k = input.parse::<kw::TopK>()?;
591
592        let group_key = if input.eat(kw::group_by) {
593            input.parse::<syn::Token![=]>()?;
594            let inner;
595            syn::bracketed!(inner in input);
596            inner.parse_comma_sep(scalar::parse_column_index)?
597        } else {
598            vec![]
599        };
600
601        let order_key = if input.eat(kw::order_by) {
602            input.parse::<syn::Token![=]>()?;
603            let inner;
604            syn::bracketed!(inner in input);
605            inner.parse_comma_sep(scalar::parse_column_order)?
606        } else {
607            vec![]
608        };
609
610        let limit = if input.eat(kw::limit) {
611            input.parse::<syn::Token![=]>()?;
612            Some(scalar::parse_expr(input)?)
613        } else {
614            None
615        };
616
617        let offset = if input.eat(kw::offset) {
618            input.parse::<syn::Token![=]>()?;
619            input.parse::<syn::LitInt>()?.base10_parse::<usize>()?
620        } else {
621            0
622        };
623
624        let monotonic = input.eat(kw::monotonic);
625
626        let expected_group_size = if input.eat(kw::exp_group_size) {
627            input.parse::<syn::Token![=]>()?;
628            Some(input.parse::<syn::LitInt>()?.base10_parse::<u64>()?)
629        } else {
630            None
631        };
632
633        let parse_inputs = ParseChildren::new(input, top_k.span().start());
634        let input = Box::new(parse_inputs.parse_one(ctx, parse_expr)?);
635
636        Ok(MirRelationExpr::TopK {
637            input,
638            group_key,
639            order_key,
640            limit,
641            offset,
642            monotonic,
643            expected_group_size,
644        })
645    }
646
647    fn parse_negate(ctx: CtxRef, input: ParseStream) -> Result {
648        let negate = input.parse::<kw::Negate>()?;
649
650        let parse_input = ParseChildren::new(input, negate.span().start());
651        let input = Box::new(parse_input.parse_one(ctx, parse_expr)?);
652
653        Ok(MirRelationExpr::Negate { input })
654    }
655
656    fn parse_threshold(ctx: CtxRef, input: ParseStream) -> Result {
657        let threshold = input.parse::<kw::Threshold>()?;
658
659        let parse_input = ParseChildren::new(input, threshold.span().start());
660        let input = Box::new(parse_input.parse_one(ctx, parse_expr)?);
661
662        Ok(MirRelationExpr::Threshold { input })
663    }
664
665    fn parse_union(ctx: CtxRef, input: ParseStream) -> Result {
666        let union = input.parse::<kw::Union>()?;
667
668        let parse_inputs = ParseChildren::new(input, union.span().start());
669        let mut children = parse_inputs.parse_many(ctx, parse_expr)?;
670        let inputs = children.split_off(1);
671        let base = Box::new(children.into_element());
672
673        Ok(MirRelationExpr::Union { base, inputs })
674    }
675
676    fn parse_arrange_by(ctx: CtxRef, input: ParseStream) -> Result {
677        let arrange_by = input.parse::<kw::ArrangeBy>()?;
678
679        let keys = {
680            input.parse::<kw::keys>()?;
681            input.parse::<syn::Token![=]>()?;
682            let inner;
683            syn::bracketed!(inner in input);
684            inner.parse_comma_sep(|input| {
685                let inner;
686                syn::bracketed!(inner in input);
687                scalar::parse_exprs(&inner)
688            })?
689        };
690
691        let parse_input = ParseChildren::new(input, arrange_by.span().start());
692        let input = Box::new(parse_input.parse_one(ctx, parse_expr)?);
693
694        Ok(MirRelationExpr::ArrangeBy { input, keys })
695    }
696
697    fn parse_local_id(ident: syn::Ident) -> syn::Result<LocalId> {
698        if ident.to_string().starts_with('l') {
699            let n = ident.to_string()[1..]
700                .parse::<u64>()
701                .map_err(|err| Error::new(ident.span(), err.to_string()))?;
702            Ok(mz_expr::LocalId::new(n))
703        } else {
704            Err(Error::new(ident.span(), "invalid LocalId"))
705        }
706    }
707
708    #[derive(Default)]
709    pub struct FixTypesCtx {
710        env: BTreeMap<LocalId, ReprRelationType>,
711        typ: Vec<ReprRelationType>,
712    }
713
714    pub fn fix_types(
715        expr: &mut MirRelationExpr,
716        ctx: &mut FixTypesCtx,
717    ) -> std::result::Result<(), String> {
718        match expr {
719            MirRelationExpr::Let { id, value, body } => {
720                fix_types(value, ctx)?;
721                let value_typ = ctx.typ.pop().expect("value type");
722                let prior_typ = ctx.env.insert(id.clone(), value_typ);
723                fix_types(body, ctx)?;
724                ctx.env.remove(id);
725                if let Some(prior_typ) = prior_typ {
726                    ctx.env.insert(id.clone(), prior_typ);
727                }
728            }
729            MirRelationExpr::LetRec {
730                ids,
731                values,
732                body,
733                limits: _,
734            } => {
735                // An ugly-ugly hack to pass the type information of the WMR CTE
736                // to the `fix_types` pass.
737                let mut prior_typs = BTreeMap::default();
738                for (id, value) in std::iter::zip(ids.iter_mut(), values.iter_mut()) {
739                    let MirRelationExpr::Union { base, mut inputs } = value.take_dangerous() else {
740                        unreachable!("ensured by construction");
741                    };
742                    let MirRelationExpr::Get { id: _, typ, .. } = *base else {
743                        unreachable!("ensured by construction");
744                    };
745                    if let Some(prior_typ) = ctx.env.insert(id.clone(), typ) {
746                        prior_typs.insert(id.clone(), prior_typ);
747                    }
748                    *value = inputs.pop().expect("ensured by construction");
749                }
750                for value in values.iter_mut() {
751                    fix_types(value, ctx)?;
752                }
753                fix_types(body, ctx)?;
754                for id in ids.iter() {
755                    ctx.env.remove(id);
756                    if let Some(prior_typ) = prior_typs.remove(id) {
757                        ctx.env.insert(id.clone(), prior_typ);
758                    }
759                }
760            }
761            MirRelationExpr::Get {
762                id: Id::Local(id),
763                typ,
764                ..
765            } => {
766                let env_typ = match ctx.env.get(&*id) {
767                    Some(env_typ) => env_typ,
768                    None => Err(format!("Cannot fix type of unbound CTE {}", id))?,
769                };
770                *typ = env_typ.clone();
771                ctx.typ.push(env_typ.clone());
772            }
773            _ => {
774                for input in expr.children_mut() {
775                    fix_types(input, ctx)?;
776                }
777                let input_types = ctx.typ.split_off(ctx.typ.len() - expr.num_inputs());
778                ctx.typ.push(expr.typ_with_input_types(&input_types));
779            }
780        };
781
782        Ok(())
783    }
784}
785
786/// Support for parsing [mz_expr::MirScalarExpr].
787mod scalar {
788    use mz_expr::{BinaryFunc, ColumnOrder, MirScalarExpr, UnaryFunc, VariadicFunc, func};
789    use mz_ore::collections::CollectionExt;
790    use mz_repr::adt::jsonb::JsonbPacker;
791    use mz_repr::adt::numeric::NumericMaxScale;
792    use mz_repr::{
793        AsColumnType, ColumnName, Datum, ReprColumnType, ReprScalarType, Row, RowArena,
794        SqlScalarType, strconv,
795    };
796
797    use super::*;
798
799    type Result = syn::Result<MirScalarExpr>;
800
801    pub fn parse_exprs(input: ParseStream) -> syn::Result<Vec<MirScalarExpr>> {
802        input.parse_comma_sep(parse_expr)
803    }
804
805    /// Parses a single expression.
806    ///
807    /// Because in EXPLAIN contexts parentheses might be optional, we need to
808    /// correctly handle operator precedence of infix operators.
809    ///
810    /// Currently, this works in two steps:
811    ///
812    /// 1. Convert the original infix expression to a postfix expression using
813    ///    an adapted variant of this [algorithm] with precedence taken from the
814    ///    Postgres [precedence] docs. Parenthesized operands are parsed in one
815    ///    step, so steps (3-4) from the [algorithm] are not needed here.
816    /// 2. Convert the postfix vector into a single [MirScalarExpr].
817    ///
818    /// [algorithm]: <https://www.prepbytes.com/blog/stacks/infix-to-postfix-conversion-using-stack/>
819    /// [precedence]: <https://www.postgresql.org/docs/7.2/sql-precedence.html>
820    pub fn parse_expr(input: ParseStream) -> Result {
821        let line = input.span().start().line;
822
823        /// Helper struct to keep track of the parsing state.
824        #[derive(Debug)]
825        enum Op {
826            Unr(mz_expr::UnaryFunc), // unary
827            Neg(mz_expr::UnaryFunc), // negated unary (append -.not() on fold)
828            Bin(mz_expr::BinaryFunc),
829            Var(mz_expr::VariadicFunc),
830        }
831
832        impl Op {
833            fn precedence(&self) -> Option<usize> {
834                match self {
835                    // 01: logical disjunction
836                    Op::Var(mz_expr::VariadicFunc::Or(_)) => Some(1),
837                    // 02: logical conjunction
838                    Op::Var(mz_expr::VariadicFunc::And(_)) => Some(2),
839                    // 04: equality, assignment
840                    Op::Bin(mz_expr::BinaryFunc::Eq(_)) => Some(4),
841                    Op::Bin(mz_expr::BinaryFunc::NotEq(_)) => Some(4),
842                    // 05: less than, greater than
843                    Op::Bin(mz_expr::BinaryFunc::Gt(_)) => Some(5),
844                    Op::Bin(mz_expr::BinaryFunc::Gte(_)) => Some(5),
845                    Op::Bin(mz_expr::BinaryFunc::Lt(_)) => Some(5),
846                    Op::Bin(mz_expr::BinaryFunc::Lte(_)) => Some(5),
847                    // 13: test for TRUE, FALSE, UNKNOWN, NULL
848                    Op::Unr(mz_expr::UnaryFunc::IsNull(_)) => Some(13),
849                    Op::Neg(mz_expr::UnaryFunc::IsNull(_)) => Some(13),
850                    Op::Unr(mz_expr::UnaryFunc::IsTrue(_)) => Some(13),
851                    Op::Neg(mz_expr::UnaryFunc::IsTrue(_)) => Some(13),
852                    Op::Unr(mz_expr::UnaryFunc::IsFalse(_)) => Some(13),
853                    Op::Neg(mz_expr::UnaryFunc::IsFalse(_)) => Some(13),
854                    // 14: addition, subtraction
855                    Op::Bin(mz_expr::BinaryFunc::AddInt64(_)) => Some(14),
856                    // 14: multiplication, division, modulo
857                    Op::Bin(mz_expr::BinaryFunc::MulInt64(_)) => Some(15),
858                    Op::Bin(mz_expr::BinaryFunc::DivInt64(_)) => Some(15),
859                    Op::Bin(mz_expr::BinaryFunc::ModInt64(_)) => Some(15),
860                    // unsupported
861                    _ => None,
862                }
863            }
864        }
865
866        /// Helper struct for entries in the postfix vector.
867        #[derive(Debug)]
868        enum Entry {
869            Operand(MirScalarExpr),
870            Operator(Op),
871        }
872
873        let mut opstack = vec![];
874        let mut postfix = vec![];
875        let mut exp_opd = true; // expects an argument of an operator
876
877        // Scan the given infix expression from left to right.
878        while !input.is_empty() && input.span().start().line == line {
879            // Operands and operators alternate.
880            if exp_opd {
881                postfix.push(Entry::Operand(parse_operand(input)?));
882                exp_opd = false;
883            } else {
884                // If the current symbol is an operator, then bind it to op.
885                // Else it is an operand - append it to postfix and continue.
886                let op = if input.eat(syn::Token![=]) {
887                    exp_opd = true;
888                    Op::Bin(func::Eq.into())
889                } else if input.eat(syn::Token![!=]) {
890                    exp_opd = true;
891                    Op::Bin(func::NotEq.into())
892                } else if input.eat(syn::Token![>=]) {
893                    exp_opd = true;
894                    Op::Bin(func::Gte.into())
895                } else if input.eat(syn::Token![>]) {
896                    exp_opd = true;
897                    Op::Bin(func::Gt.into())
898                } else if input.eat(syn::Token![<=]) {
899                    exp_opd = true;
900                    Op::Bin(func::Lte.into())
901                } else if input.eat(syn::Token![<]) {
902                    exp_opd = true;
903                    Op::Bin(func::Lt.into())
904                } else if input.eat(syn::Token![+]) {
905                    exp_opd = true;
906                    Op::Bin(func::AddInt64.into()) // TODO: fix placeholder
907                } else if input.eat(syn::Token![*]) {
908                    exp_opd = true;
909                    Op::Bin(func::MulInt64.into()) // TODO: fix placeholder
910                } else if input.eat(syn::Token![/]) {
911                    exp_opd = true;
912                    Op::Bin(func::DivInt64.into()) // TODO: fix placeholder
913                } else if input.eat(syn::Token![%]) {
914                    exp_opd = true;
915                    Op::Bin(func::ModInt64.into()) // TODO: fix placeholder
916                } else if input.eat(kw::AND) {
917                    exp_opd = true;
918                    Op::Var(VariadicFunc::And(func::variadic::And))
919                } else if input.eat(kw::OR) {
920                    exp_opd = true;
921                    Op::Var(VariadicFunc::Or(func::variadic::Or))
922                } else if input.eat(kw::coalesce) {
923                    exp_opd = true;
924                    Op::Var(VariadicFunc::Coalesce(func::variadic::Coalesce))
925                } else if input.eat(kw::IS) {
926                    let negate = input.eat(kw::NOT);
927
928                    let lookahead = input.lookahead1();
929                    let func = if input.look_and_eat(kw::NULL, &lookahead) {
930                        mz_expr::func::IsNull.into()
931                    } else if input.look_and_eat(kw::TRUE, &lookahead) {
932                        mz_expr::func::IsTrue.into()
933                    } else if input.look_and_eat(kw::FALSE, &lookahead) {
934                        mz_expr::func::IsFalse.into()
935                    } else {
936                        Err(lookahead.error())?
937                    };
938
939                    if negate { Op::Neg(func) } else { Op::Unr(func) }
940                } else {
941                    // We were expecting an optional operator but didn't find
942                    // anything. Exit the parsing loop and process the postfix
943                    // vector.
944                    break;
945                };
946
947                // First, pop the operators which are already on the opstack that
948                // have higher or equal precedence than the current operator and
949                // append them to the postfix.
950                while opstack
951                    .last()
952                    .map(|op1: &Op| op1.precedence() >= op.precedence())
953                    .unwrap_or(false)
954                {
955                    let op1 = opstack.pop().expect("non-empty opstack");
956                    postfix.push(Entry::Operator(op1));
957                }
958
959                // Then push the op from this iteration onto the stack.
960                opstack.push(op);
961            }
962        }
963
964        // Pop all remaining symbols from opstack and append them to postfix.
965        postfix.extend(opstack.into_iter().rev().map(Entry::Operator));
966
967        if postfix.is_empty() {
968            let msg = "Cannot parse an empty expression";
969            Err(Error::new(input.span(), msg))?
970        }
971
972        // Flatten the postfix vector into a single MirScalarExpr.
973        let mut stack = vec![];
974        postfix.reverse();
975        while let Some(entry) = postfix.pop() {
976            match entry {
977                Entry::Operand(expr) => {
978                    stack.push(expr);
979                }
980                Entry::Operator(Op::Unr(func)) => {
981                    let expr = Box::new(stack.pop().expect("non-empty stack"));
982                    stack.push(MirScalarExpr::CallUnary { func, expr });
983                }
984                Entry::Operator(Op::Neg(func)) => {
985                    let expr = Box::new(stack.pop().expect("non-empty stack"));
986                    stack.push(MirScalarExpr::CallUnary { func, expr }.not());
987                }
988                Entry::Operator(Op::Bin(func)) => {
989                    let expr2 = Box::new(stack.pop().expect("non-empty stack"));
990                    let expr1 = Box::new(stack.pop().expect("non-empty stack"));
991                    stack.push(MirScalarExpr::CallBinary { func, expr1, expr2 });
992                }
993                Entry::Operator(Op::Var(func)) => {
994                    let expr2 = stack.pop().expect("non-empty stack");
995                    let expr1 = stack.pop().expect("non-empty stack");
996                    let mut exprs = vec![];
997                    for expr in [expr1, expr2] {
998                        match expr {
999                            MirScalarExpr::CallVariadic { func: f, exprs: es } if f == func => {
1000                                exprs.extend(es);
1001                            }
1002                            expr => {
1003                                exprs.push(expr);
1004                            }
1005                        }
1006                    }
1007                    stack.push(MirScalarExpr::CallVariadic { func, exprs });
1008                }
1009            }
1010        }
1011
1012        if stack.len() != 1 {
1013            let msg = "Cannot fold postfix vector into a single MirScalarExpr";
1014            Err(Error::new(input.span(), msg))?
1015        }
1016
1017        Ok(stack.pop().unwrap())
1018    }
1019
1020    pub fn parse_operand(input: ParseStream) -> Result {
1021        let lookahead = input.lookahead1();
1022        if lookahead.peek(syn::Token![#]) {
1023            parse_column(input)
1024        } else if lookahead.peek(syn::Lit) || lookahead.peek(kw::null) {
1025            parse_literal_ok(input)
1026        } else if lookahead.peek(kw::error) {
1027            parse_literal_err(input)
1028        } else if lookahead.peek(kw::array) {
1029            parse_array(input)
1030        } else if lookahead.peek(kw::list) {
1031            parse_list(input)
1032        } else if lookahead.peek(kw::case) {
1033            parse_case(input)
1034        } else if lookahead.peek(syn::Ident) {
1035            parse_apply(input)
1036        } else if lookahead.peek(syn::token::Brace) {
1037            let inner;
1038            syn::braced!(inner in input);
1039            parse_literal_array(&inner)
1040        } else if lookahead.peek(syn::token::Bracket) {
1041            let inner;
1042            syn::bracketed!(inner in input);
1043            parse_literal_list(&inner)
1044        } else if lookahead.peek(syn::token::Paren) {
1045            let inner;
1046            syn::parenthesized!(inner in input);
1047            parse_expr(&inner)
1048        } else {
1049            Err(lookahead.error())
1050        }
1051    }
1052
1053    /// Parses `case when {cond} then {then} else {els} end`.
1054    fn parse_case(input: ParseStream) -> Result {
1055        input.parse::<kw::case>()?;
1056        if input.peek(kw::when) {
1057            input.parse::<kw::when>()?;
1058            let cond = parse_expr(input)?;
1059            input.parse::<kw::then>()?;
1060            let then = parse_expr(input)?;
1061            input.parse::<syn::Token![else]>()?;
1062            let els = parse_expr(input)?;
1063            input.parse::<kw::end>()?;
1064            Ok(MirScalarExpr::If {
1065                cond: Box::new(cond),
1066                then: Box::new(then),
1067                els: Box::new(els),
1068            })
1069        } else {
1070            Err(Error::new(input.span(), "expected 'when' after 'case'"))
1071        }
1072    }
1073
1074    pub fn parse_column(input: ParseStream) -> Result {
1075        Ok(MirScalarExpr::column(parse_column_index(input)?))
1076    }
1077
1078    pub fn parse_column_index(input: ParseStream) -> syn::Result<usize> {
1079        input.parse::<syn::Token![#]>()?;
1080        input.parse::<syn::LitInt>()?.base10_parse::<usize>()
1081    }
1082
1083    pub fn parse_column_order(input: ParseStream) -> syn::Result<ColumnOrder> {
1084        input.parse::<syn::Token![#]>()?;
1085        let column = input.parse::<syn::LitInt>()?.base10_parse::<usize>()?;
1086        let desc = input.eat(kw::desc) || !input.eat(kw::asc);
1087        let nulls_last = input.eat(kw::nulls_last) || !input.eat(kw::nulls_first);
1088        Ok(ColumnOrder {
1089            column,
1090            desc,
1091            nulls_last,
1092        })
1093    }
1094
1095    fn parse_literal_ok(input: ParseStream) -> Result {
1096        let mut row = Row::default();
1097        let mut packer = row.packer();
1098
1099        let typ = if input.eat(kw::null) {
1100            packer.push(Datum::Null);
1101            input.parse::<syn::Token![::]>()?;
1102            ReprColumnType {
1103                scalar_type: analyses::parse_scalar_type(input)?,
1104                nullable: true,
1105            }
1106        } else {
1107            let lit = input.parse::<syn::Lit>()?;
1108            if input.peek(syn::Token![::]) {
1109                // A literal with an explicit type, e.g. `2000.0::numeric` or
1110                // `"{}"::jsonb`. Coerce the literal token to the target type.
1111                input.parse::<syn::Token![::]>()?;
1112                let scalar_type = analyses::parse_scalar_type(input)?;
1113                parse_typed_literal(&mut packer, &lit, &scalar_type)?;
1114                ReprColumnType {
1115                    scalar_type,
1116                    nullable: false,
1117                }
1118            } else {
1119                match lit {
1120                    syn::Lit::Str(l) => {
1121                        packer.push(Datum::from(l.value().as_str()));
1122                        Ok(ReprColumnType::from(&String::as_column_type()))
1123                    }
1124                    syn::Lit::Int(l) => {
1125                        packer.push(Datum::from(l.base10_parse::<i64>()?));
1126                        Ok(ReprColumnType::from(&i64::as_column_type()))
1127                    }
1128                    syn::Lit::Float(l) => {
1129                        packer.push(Datum::from(l.base10_parse::<f64>()?));
1130                        Ok(ReprColumnType::from(&f64::as_column_type()))
1131                    }
1132                    syn::Lit::Bool(l) => {
1133                        packer.push(Datum::from(l.value));
1134                        Ok(ReprColumnType::from(&bool::as_column_type()))
1135                    }
1136                    _ => Err(Error::new(input.span(), "cannot parse literal")),
1137                }?
1138            }
1139        };
1140
1141        Ok(MirScalarExpr::Literal(Ok(row), typ))
1142    }
1143
1144    /// Packs a literal token coerced to the given target type.
1145    fn parse_typed_literal(
1146        packer: &mut mz_repr::RowPacker,
1147        lit: &syn::Lit,
1148        scalar_type: &ReprScalarType,
1149    ) -> syn::Result<()> {
1150        use syn::Lit::*;
1151        let err = |msg: String| Error::new(lit.span(), msg);
1152        match (lit, scalar_type) {
1153            (Int(l), ReprScalarType::Int16) => packer.push(Datum::from(l.base10_parse::<i16>()?)),
1154            (Int(l), ReprScalarType::Int32) => packer.push(Datum::from(l.base10_parse::<i32>()?)),
1155            (Int(l), ReprScalarType::Int64) => packer.push(Datum::from(l.base10_parse::<i64>()?)),
1156            (Int(l), ReprScalarType::Float64) => packer.push(Datum::from(l.base10_parse::<f64>()?)),
1157            (Float(l), ReprScalarType::Float64) => {
1158                packer.push(Datum::from(l.base10_parse::<f64>()?))
1159            }
1160            (Int(l), ReprScalarType::Numeric { .. }) => {
1161                let n = strconv::parse_numeric(l.base10_digits())
1162                    .map_err(|e| err(format!("invalid numeric literal: {e}")))?;
1163                packer.push(Datum::Numeric(n));
1164            }
1165            (Float(l), ReprScalarType::Numeric { .. }) => {
1166                let n = strconv::parse_numeric(l.base10_digits())
1167                    .map_err(|e| err(format!("invalid numeric literal: {e}")))?;
1168                packer.push(Datum::Numeric(n));
1169            }
1170            (Str(l), ReprScalarType::String) => packer.push(Datum::from(l.value().as_str())),
1171            (Str(l), ReprScalarType::Jsonb) => {
1172                JsonbPacker::new(packer)
1173                    .pack_str(&l.value())
1174                    .map_err(|e| err(format!("invalid jsonb literal: {e}")))?;
1175            }
1176            _ => Err(err("unsupported literal type annotation".to_string()))?,
1177        }
1178        Ok(())
1179    }
1180    fn parse_literal_err(input: ParseStream) -> Result {
1181        input.parse::<kw::error>()?;
1182        let mut msg = {
1183            let content;
1184            syn::parenthesized!(content in input);
1185            content.parse::<syn::LitStr>()?.value()
1186        };
1187        let err = if msg.starts_with("internal error: ") {
1188            Ok(mz_expr::EvalError::Internal(msg.split_off(16).into()))
1189        } else {
1190            Err(Error::new(msg.span(), "expected `internal error: $msg`"))
1191        }?;
1192        Ok(MirScalarExpr::literal(Err(err), ReprScalarType::Bool))
1193    }
1194
1195    fn parse_literal_array(input: ParseStream) -> Result {
1196        use mz_expr::func::variadic::ArrayCreate;
1197
1198        let elem_type = SqlScalarType::Int64; // FIXME
1199        let func = VariadicFunc::ArrayCreate(ArrayCreate { elem_type });
1200        let exprs = input.parse_comma_sep(parse_literal_ok)?;
1201
1202        // Evaluate into a datum
1203        let temp_storage = RowArena::default();
1204        let datum = func.eval(&[], &temp_storage, &exprs).expect("datum");
1205        let typ = ReprScalarType::from(&SqlScalarType::Array(Box::new(SqlScalarType::Int64))); // FIXME
1206        Ok(MirScalarExpr::literal_ok(datum, typ))
1207    }
1208    fn parse_literal_list(input: ParseStream) -> Result {
1209        use mz_expr::func::variadic::ListCreate;
1210
1211        let elem_type = SqlScalarType::Int64; // FIXME
1212        let func = VariadicFunc::ListCreate(ListCreate { elem_type });
1213        let exprs = input.parse_comma_sep(parse_literal_ok)?;
1214
1215        // Evaluate into a datum
1216        let temp_storage = RowArena::default();
1217        let datum = func.eval(&[], &temp_storage, &exprs).expect("datum");
1218        let typ = ReprScalarType::from(&SqlScalarType::Array(Box::new(SqlScalarType::Int64))); // FIXME
1219        Ok(MirScalarExpr::literal_ok(datum, typ))
1220    }
1221    fn parse_array(input: ParseStream) -> Result {
1222        use mz_expr::func::variadic::ArrayCreate;
1223
1224        input.parse::<kw::array>()?;
1225
1226        // parse brackets
1227        let inner;
1228        syn::bracketed!(inner in input);
1229
1230        let elem_type = SqlScalarType::Int64; // FIXME
1231        let func = ArrayCreate { elem_type };
1232        let exprs = inner.parse_comma_sep(parse_expr)?;
1233
1234        Ok(MirScalarExpr::call_variadic(func, exprs))
1235    }
1236
1237    fn parse_list(input: ParseStream) -> Result {
1238        use mz_expr::func::variadic::ListCreate;
1239
1240        input.parse::<kw::list>()?;
1241
1242        // parse brackets
1243        let inner;
1244        syn::bracketed!(inner in input);
1245
1246        let elem_type = SqlScalarType::Int64; // FIXME
1247        let func = ListCreate { elem_type };
1248        let exprs = inner.parse_comma_sep(parse_expr)?;
1249
1250        Ok(MirScalarExpr::call_variadic(func, exprs))
1251    }
1252
1253    fn parse_apply(input: ParseStream) -> Result {
1254        let ident = input.parse::<syn::Ident>()?;
1255
1256        // Function variants with parameters take them in brackets before the
1257        // argument list, e.g. `cast_int32_to_numeric[127](#0)`.
1258        if input.peek(syn::token::Bracket) {
1259            return parse_apply_parameterized(&ident, input);
1260        }
1261
1262        // parse parentheses
1263        let inner;
1264        syn::parenthesized!(inner in input);
1265
1266        let parse_unary = |func: UnaryFunc| -> Result {
1267            let expr = Box::new(parse_expr(&inner)?);
1268            Ok(MirScalarExpr::CallUnary { func, expr })
1269        };
1270        let parse_binary = |func: BinaryFunc| -> Result {
1271            let expr1 = Box::new(parse_expr(&inner)?);
1272            inner.parse::<syn::Token![,]>()?;
1273            let expr2 = Box::new(parse_expr(&inner)?);
1274            Ok(MirScalarExpr::CallBinary { func, expr1, expr2 })
1275        };
1276        let parse_variadic = |func: VariadicFunc| -> Result {
1277            let exprs = inner.parse_comma_sep(parse_expr)?;
1278            Ok(MirScalarExpr::call_variadic(func, exprs))
1279        };
1280
1281        // Infix binary and variadic function calls are handled in `parse_scalar_expr`.
1282        //
1283        // Some restrictions apply with the current state of the code,
1284        // most notably one cannot handle overloaded function names because we don't want to do
1285        // name resolution in the parser.
1286        match ident.to_string().to_lowercase().as_str() {
1287            // Supported unary functions:
1288            "abs" => parse_unary(func::AbsInt64.into()),
1289            "not" => parse_unary(func::Not.into()),
1290            // Supported binary functions:
1291            "ltrim" => parse_binary(func::TrimLeading.into()),
1292            // Supported variadic functions:
1293            "greatest" => parse_variadic(VariadicFunc::Greatest(func::variadic::Greatest)),
1294            "coalesce" => parse_variadic(VariadicFunc::Coalesce(func::variadic::Coalesce)),
1295            // Supported unmaterializable functions:
1296            "mz_now" => Ok(MirScalarExpr::CallUnmaterializable(
1297                mz_expr::UnmaterializableFunc::MzNow,
1298            )),
1299            // Exact function variants by their canonical name, dispatched on
1300            // the argument count (unary and binary win over variadic).
1301            name => {
1302                let exprs = inner.parse_comma_sep(parse_expr)?;
1303                parse_apply_variant(&ident, name, exprs)
1304            }
1305        }
1306    }
1307
1308    /// Applies a function variant named by its canonical (snake_case) name,
1309    /// e.g. `add_int32(#0, #1)`. See `FuncName` in `mz_expr`.
1310    fn parse_apply_variant(
1311        ident: &syn::Ident,
1312        name: &str,
1313        mut exprs: Vec<MirScalarExpr>,
1314    ) -> Result {
1315        if exprs.len() == 1 {
1316            if let Some(func) = UnaryFunc::from_variant_name(name) {
1317                let expr = Box::new(exprs.into_element());
1318                return Ok(MirScalarExpr::CallUnary { func, expr });
1319            }
1320        }
1321        if exprs.len() == 2 {
1322            if let Some(func) = BinaryFunc::from_variant_name(name) {
1323                let expr2 = Box::new(exprs.pop().expect("two exprs"));
1324                let expr1 = Box::new(exprs.pop().expect("two exprs"));
1325                return Ok(MirScalarExpr::CallBinary { func, expr1, expr2 });
1326            }
1327        }
1328        if let Some(func) = VariadicFunc::from_variant_name(name) {
1329            return Ok(MirScalarExpr::CallVariadic { func, exprs });
1330        }
1331        Err(Error::new(ident.span(), "unsupported function name"))
1332    }
1333
1334    /// Applies a parameterized function variant. The variant's parameters
1335    /// appear in brackets between the name and the argument list.
1336    fn parse_apply_parameterized(ident: &syn::Ident, input: ParseStream) -> Result {
1337        let params;
1338        syn::bracketed!(params in input);
1339        let inner;
1340        syn::parenthesized!(inner in input);
1341
1342        match ident.to_string().to_lowercase().as_str() {
1343            "cast_int32_to_numeric" => {
1344                let max_scale = if params.is_empty() {
1345                    None
1346                } else {
1347                    let scale = params.parse::<syn::LitInt>()?.base10_parse::<i64>()?;
1348                    let scale = NumericMaxScale::try_from(scale)
1349                        .map_err(|e| Error::new(params.span(), e.to_string()))?;
1350                    Some(scale)
1351                };
1352                let expr = Box::new(parse_expr(&inner)?);
1353                Ok(MirScalarExpr::CallUnary {
1354                    func: func::CastInt32ToNumeric(max_scale).into(),
1355                    expr,
1356                })
1357            }
1358            "record_get" => {
1359                let index = params.parse::<syn::LitInt>()?.base10_parse::<usize>()?;
1360                let expr = Box::new(parse_expr(&inner)?);
1361                Ok(MirScalarExpr::CallUnary {
1362                    func: func::RecordGet(index).into(),
1363                    expr,
1364                })
1365            }
1366            "record_create" => {
1367                let field_names = params
1368                    .parse_comma_sep(|p| Ok(ColumnName::from(p.parse::<syn::LitStr>()?.value())))?;
1369                let exprs = inner.parse_comma_sep(parse_expr)?;
1370                Ok(MirScalarExpr::call_variadic(
1371                    func::variadic::RecordCreate { field_names },
1372                    exprs,
1373                ))
1374            }
1375            "list_create" => {
1376                let elem_type = SqlScalarType::from_repr(&analyses::parse_scalar_type(&params)?);
1377                let exprs = inner.parse_comma_sep(parse_expr)?;
1378                Ok(MirScalarExpr::call_variadic(
1379                    func::variadic::ListCreate { elem_type },
1380                    exprs,
1381                ))
1382            }
1383            _ => Err(Error::new(
1384                ident.span(),
1385                "unsupported parameterized function",
1386            )),
1387        }
1388    }
1389
1390    pub fn parse_join_equivalences(input: ParseStream) -> syn::Result<Vec<Vec<MirScalarExpr>>> {
1391        let mut equivalences = vec![];
1392        while !input.is_empty() {
1393            let mut equivalence = vec![];
1394            loop {
1395                let mut worklist = vec![parse_operand(input)?];
1396                while let Some(operand) = worklist.pop() {
1397                    // Be more lenient and support parenthesized equivalences,
1398                    // e.g. `... AND (x = u + v = z + 1) AND ...`.
1399                    if let MirScalarExpr::CallBinary {
1400                        func: BinaryFunc::Eq(_),
1401                        expr1,
1402                        expr2,
1403                    } = operand
1404                    {
1405                        // We reverse the order in the worklist in order to get
1406                        // the correct order in the equivalence class.
1407                        worklist.push(*expr2);
1408                        worklist.push(*expr1);
1409                    } else {
1410                        equivalence.push(operand);
1411                    }
1412                }
1413                if !input.eat(syn::Token![=]) {
1414                    break;
1415                }
1416            }
1417            equivalences.push(equivalence);
1418            input.eat(kw::AND);
1419        }
1420        Ok(equivalences)
1421    }
1422}
1423
1424/// Support for parsing [mz_expr::AggregateExpr].
1425mod aggregate {
1426    use mz_expr::{AggregateExpr, MirScalarExpr};
1427
1428    use super::*;
1429
1430    type Result = syn::Result<AggregateExpr>;
1431
1432    pub fn parse_expr(input: ParseStream) -> Result {
1433        use mz_expr::AggregateFunc::*;
1434
1435        // Some restrictions apply with the current state of the code,
1436        // most notably one cannot handle overloaded function names because we don't want to do
1437        // name resolution in the parser.
1438        let ident = input.parse::<syn::Ident>()?;
1439        let func = match ident.to_string().to_lowercase().as_str() {
1440            "count" => Count,
1441            "any" => Any,
1442            "all" => All,
1443            "max" => MaxInt64,
1444            "min" => MinInt64,
1445            "sum" => SumInt64,
1446            // Exact variants, for tests that pin a specific width.
1447            "max_int32" => MaxInt32,
1448            "max_int64" => MaxInt64,
1449            "min_int32" => MinInt32,
1450            "min_int64" => MinInt64,
1451            "sum_int16" => SumInt16,
1452            "sum_int32" => SumInt32,
1453            "sum_int64" => SumInt64,
1454            _ => Err(Error::new(ident.span(), "unsupported function name"))?,
1455        };
1456
1457        // parse parentheses
1458        let inner;
1459        syn::parenthesized!(inner in input);
1460
1461        if func == Count && inner.eat(syn::Token![*]) {
1462            Ok(AggregateExpr {
1463                func,
1464                expr: MirScalarExpr::literal_true(),
1465                distinct: false, // TODO: fix explain output
1466            })
1467        } else {
1468            let distinct = inner.eat(kw::distinct);
1469            let expr = scalar::parse_expr(&inner)?;
1470            Ok(AggregateExpr {
1471                func,
1472                expr,
1473                distinct,
1474            })
1475        }
1476    }
1477}
1478
1479/// Support for parsing [mz_repr::Row].
1480mod row {
1481    use mz_repr::{Datum, ReprColumnType, ReprScalarType, Row};
1482
1483    use super::*;
1484
1485    /// Parses a comma-separated datum list into a [`Row`], coercing each datum
1486    /// to the corresponding column type where the literal admits it.
1487    ///
1488    /// Literals that do not match their column type (and datums beyond the
1489    /// column count) fall back to type inference from the literal alone. The
1490    /// parser deliberately does not reject such rows, ill-typed constants are
1491    /// valid parser output that tests feed to the typechecker.
1492    pub fn parse_row(input: ParseStream, types: &[ReprColumnType]) -> syn::Result<Row> {
1493        let mut row = Row::default();
1494        let mut packer = row.packer();
1495
1496        let mut types = types.iter();
1497        loop {
1498            if input.is_empty() {
1499                break;
1500            }
1501            parse_datum(input, &mut packer, types.next())?;
1502            if input.is_empty() {
1503                break;
1504            }
1505            input.parse::<syn::Token![,]>()?;
1506        }
1507
1508        Ok(row)
1509    }
1510
1511    fn parse_datum(
1512        input: ParseStream,
1513        packer: &mut mz_repr::RowPacker,
1514        typ: Option<&ReprColumnType>,
1515    ) -> syn::Result<()> {
1516        use ReprScalarType::*;
1517        if input.eat(kw::null) {
1518            packer.push(Datum::Null);
1519            return Ok(());
1520        }
1521        let lit = input.parse::<syn::Lit>()?;
1522        match (&lit, typ.map(|t| &t.scalar_type)) {
1523            (syn::Lit::Int(l), Some(Int16)) => packer.push(Datum::from(l.base10_parse::<i16>()?)),
1524            (syn::Lit::Int(l), Some(Int32)) => packer.push(Datum::from(l.base10_parse::<i32>()?)),
1525            (syn::Lit::Int(l), Some(Float64)) => packer.push(Datum::from(l.base10_parse::<f64>()?)),
1526            // Literal-only inference, also the fallback for literals that do
1527            // not match their column type.
1528            (syn::Lit::Str(l), _) => packer.push(Datum::from(l.value().as_str())),
1529            (syn::Lit::Int(l), _) => packer.push(Datum::from(l.base10_parse::<i64>()?)),
1530            (syn::Lit::Float(l), _) => packer.push(Datum::from(l.base10_parse::<f64>()?)),
1531            (syn::Lit::Bool(l), _) => packer.push(Datum::from(l.value)),
1532            (lit, _) => Err(Error::new(lit.span(), "cannot parse literal"))?,
1533        }
1534        Ok(())
1535    }
1536}
1537
1538mod analyses {
1539    use mz_repr::{ReprColumnType, ReprScalarType};
1540
1541    use super::*;
1542
1543    #[derive(Default)]
1544    pub struct Analyses {
1545        pub types: Option<Vec<ReprColumnType>>,
1546        pub keys: Option<Vec<Vec<usize>>>,
1547    }
1548
1549    pub fn parse_analyses(input: ParseStream) -> syn::Result<Analyses> {
1550        let mut analyses = Analyses::default();
1551
1552        // Analyses are optional, appearing after a `//` at the end of the
1553        // line. However, since the syn lexer eats comments, we assume that `//`
1554        // was replaced with `::` upfront.
1555        if input.eat(syn::Token![::]) {
1556            let inner;
1557            syn::braced!(inner in input);
1558
1559            let (start, end) = (inner.span().start(), inner.span().end());
1560            if start.line != end.line {
1561                let msg = "analyses should not span more than one line".to_string();
1562                Err(Error::new(inner.span(), msg))?
1563            }
1564
1565            while inner.peek(syn::Ident) {
1566                let ident = inner.parse::<syn::Ident>()?.to_string();
1567                match ident.as_str() {
1568                    "types" => {
1569                        inner.parse::<syn::Token![:]>()?;
1570                        let value = inner.parse::<syn::LitStr>()?.value();
1571                        analyses.types = Some(parse_types.parse_str(&value)?);
1572                    }
1573                    "keys" => {
1574                        inner.parse::<syn::Token![:]>()?;
1575                        let value = inner.parse::<syn::LitStr>()?.value();
1576                        analyses.keys = Some(parse_keys.parse_str(&value)?);
1577                    }
1578                    key => {
1579                        let msg = format!("unexpected analysis type `{}`", key);
1580                        Err(Error::new(inner.span(), msg))?;
1581                    }
1582                }
1583                inner.eat(syn::Token![,]);
1584            }
1585        }
1586        Ok(analyses)
1587    }
1588
1589    fn parse_types(input: ParseStream) -> syn::Result<Vec<ReprColumnType>> {
1590        let inner;
1591        syn::parenthesized!(inner in input);
1592        inner.parse_comma_sep(parse_column_type)
1593    }
1594
1595    /// Parses a unique keys annotation in the format printed by EXPLAIN,
1596    /// e.g. `([0], [1, 2])`.
1597    fn parse_keys(input: ParseStream) -> syn::Result<Vec<Vec<usize>>> {
1598        let inner;
1599        syn::parenthesized!(inner in input);
1600        inner.parse_comma_sep(|input| {
1601            let inner;
1602            syn::bracketed!(inner in input);
1603            inner.parse_comma_sep(|input| input.parse::<syn::LitInt>()?.base10_parse::<usize>())
1604        })
1605    }
1606
1607    pub fn parse_column_type(input: ParseStream) -> syn::Result<ReprColumnType> {
1608        let scalar_type = parse_scalar_type(input)?;
1609        Ok(ReprColumnType {
1610            scalar_type,
1611            nullable: input.eat(syn::Token![?]),
1612        })
1613    }
1614
1615    pub fn parse_scalar_type(input: ParseStream) -> syn::Result<ReprScalarType> {
1616        let lookahead = input.lookahead1();
1617
1618        let scalar_type = if input.look_and_eat(bigint, &lookahead) {
1619            ReprScalarType::Int64
1620        } else if input.look_and_eat(double, &lookahead) {
1621            input.parse::<precision>()?;
1622            ReprScalarType::Float64
1623        } else if input.look_and_eat(boolean, &lookahead) {
1624            ReprScalarType::Bool
1625        } else if input.look_and_eat(character, &lookahead) {
1626            input.parse::<varying>()?;
1627            ReprScalarType::String
1628        } else if input.look_and_eat(integer, &lookahead) {
1629            ReprScalarType::Int32
1630        } else if input.look_and_eat(smallint, &lookahead) {
1631            ReprScalarType::Int16
1632        } else if input.look_and_eat(text, &lookahead) {
1633            ReprScalarType::String
1634        } else if input.look_and_eat(jsonb, &lookahead) {
1635            ReprScalarType::Jsonb
1636        } else if input.look_and_eat(numeric, &lookahead) {
1637            ReprScalarType::Numeric
1638        } else {
1639            Err(lookahead.error())?
1640        };
1641
1642        Ok(scalar_type)
1643    }
1644
1645    syn::custom_keyword!(bigint);
1646    syn::custom_keyword!(boolean);
1647    syn::custom_keyword!(character);
1648    syn::custom_keyword!(double);
1649    syn::custom_keyword!(integer);
1650    syn::custom_keyword!(jsonb);
1651    syn::custom_keyword!(numeric);
1652    syn::custom_keyword!(precision);
1653    syn::custom_keyword!(smallint);
1654    syn::custom_keyword!(text);
1655    syn::custom_keyword!(varying);
1656}
1657
1658pub enum Def {
1659    Source {
1660        name: String,
1661        cols: Vec<String>,
1662        typ: mz_repr::SqlRelationType,
1663    },
1664}
1665
1666mod def {
1667    use mz_repr::{SqlColumnType, SqlRelationType};
1668
1669    use super::*;
1670
1671    pub fn parse_def(ctx: CtxRef, input: ParseStream) -> syn::Result<Def> {
1672        parse_def_source(ctx, input) // only one variant for now
1673    }
1674
1675    fn parse_def_source(ctx: CtxRef, input: ParseStream) -> syn::Result<Def> {
1676        let reduce = input.parse::<def::DefSource>()?;
1677
1678        let name = {
1679            input.parse::<def::name>()?;
1680            input.parse::<syn::Token![=]>()?;
1681            input.parse::<syn::Ident>()?.to_string()
1682        };
1683
1684        let keys = if input.eat(kw::keys) {
1685            input.parse::<syn::Token![=]>()?;
1686            let inner;
1687            syn::bracketed!(inner in input);
1688            inner.parse_comma_sep(|input| {
1689                let inner;
1690                syn::bracketed!(inner in input);
1691                inner.parse_comma_sep(scalar::parse_column_index)
1692            })?
1693        } else {
1694            vec![]
1695        };
1696
1697        let parse_inputs = ParseChildren::new(input, reduce.span().start());
1698        let (cols, column_types) = {
1699            let source_columns = parse_inputs.parse_many(ctx, parse_def_source_column)?;
1700            let mut column_names = vec![];
1701            let mut column_types = vec![];
1702            for (column_name, column_type) in source_columns {
1703                column_names.push(column_name);
1704                column_types.push(column_type);
1705            }
1706            (column_names, column_types)
1707        };
1708
1709        let typ = SqlRelationType { column_types, keys };
1710
1711        Ok(Def::Source { name, cols, typ })
1712    }
1713
1714    fn parse_def_source_column(
1715        _ctx: CtxRef,
1716        input: ParseStream,
1717    ) -> syn::Result<(String, SqlColumnType)> {
1718        input.parse::<syn::Token![-]>()?;
1719        let column_name = input.parse::<syn::Ident>()?.to_string();
1720        input.parse::<syn::Token![:]>()?;
1721        let column_type = SqlColumnType::from_repr(&analyses::parse_column_type(input)?);
1722        Ok((column_name, column_type))
1723    }
1724
1725    syn::custom_keyword!(DefSource);
1726    syn::custom_keyword!(name);
1727}
1728
1729/// Help utilities used by sibling modules.
1730mod util {
1731    use syn::parse::{Lookahead1, ParseBuffer, Peek};
1732
1733    use super::*;
1734
1735    /// Extension methods for [`syn::parse::ParseBuffer`].
1736    pub trait ParseBufferExt<'a> {
1737        fn look_and_eat<T: Eat>(&self, token: T, lookahead: &Lookahead1<'a>) -> bool;
1738
1739        /// Consumes a token `T` if present.
1740        fn eat<T: Eat>(&self, t: T) -> bool;
1741
1742        /// Consumes two tokens `T1 T2` if present in that order.
1743        fn eat2<T1: Eat, T2: Eat>(&self, t1: T1, t2: T2) -> bool;
1744
1745        /// Consumes three tokens `T1 T2 T3` if present in that order.
1746        fn eat3<T1: Eat, T2: Eat, T3: Eat>(&self, t1: T1, t2: T2, t3: T3) -> bool;
1747
1748        // Parse a comma-separated list of items into a vector.
1749        fn parse_comma_sep<T>(&self, p: fn(ParseStream) -> syn::Result<T>) -> syn::Result<Vec<T>>;
1750    }
1751
1752    impl<'a> ParseBufferExt<'a> for ParseBuffer<'a> {
1753        /// Consumes a token `T` if present, looking it up using the provided
1754        /// [`Lookahead1`] instance.
1755        fn look_and_eat<T: Eat>(&self, token: T, lookahead: &Lookahead1<'a>) -> bool {
1756            if lookahead.peek(token) {
1757                self.parse::<T::Token>().unwrap();
1758                true
1759            } else {
1760                false
1761            }
1762        }
1763
1764        fn eat<T: Eat>(&self, t: T) -> bool {
1765            if self.peek(t) {
1766                self.parse::<T::Token>().unwrap();
1767                true
1768            } else {
1769                false
1770            }
1771        }
1772
1773        fn eat2<T1: Eat, T2: Eat>(&self, t1: T1, t2: T2) -> bool {
1774            if self.peek(t1) && self.peek2(t2) {
1775                self.parse::<T1::Token>().unwrap();
1776                self.parse::<T2::Token>().unwrap();
1777                true
1778            } else {
1779                false
1780            }
1781        }
1782
1783        fn eat3<T1: Eat, T2: Eat, T3: Eat>(&self, t1: T1, t2: T2, t3: T3) -> bool {
1784            if self.peek(t1) && self.peek2(t2) && self.peek3(t3) {
1785                self.parse::<T1::Token>().unwrap();
1786                self.parse::<T2::Token>().unwrap();
1787                self.parse::<T3::Token>().unwrap();
1788                true
1789            } else {
1790                false
1791            }
1792        }
1793
1794        fn parse_comma_sep<T>(&self, p: fn(ParseStream) -> syn::Result<T>) -> syn::Result<Vec<T>> {
1795            Ok(self
1796                .parse_terminated(p, syn::Token![,])?
1797                .into_iter()
1798                .collect::<Vec<_>>())
1799        }
1800    }
1801
1802    // Helper trait for types that can be eaten.
1803    //
1804    // Implementing types must also implement [`Peek`], and the associated
1805    // [`Peek::Token`] type should implement [`Parse`]). For some reason the
1806    // latter bound is not present in [`Peek`] even if it makes a lot of sense,
1807    // which is why we need this helper.
1808    pub trait Eat: Peek<Token = Self::_Token> {
1809        type _Token: Parse;
1810    }
1811
1812    impl<T> Eat for T
1813    where
1814        T: Peek,
1815        T::Token: Parse,
1816    {
1817        type _Token = T::Token;
1818    }
1819
1820    pub struct Ctx<'a> {
1821        pub catalog: &'a TestCatalog,
1822    }
1823
1824    pub type CtxRef<'a> = &'a Ctx<'a>;
1825
1826    /// Provides facilities for parsing
1827    pub struct ParseChildren<'a> {
1828        stream: ParseStream<'a>,
1829        parent: LineColumn,
1830    }
1831
1832    impl<'a> ParseChildren<'a> {
1833        pub fn new(stream: ParseStream<'a>, parent: LineColumn) -> Self {
1834            Self { stream, parent }
1835        }
1836
1837        pub fn parse_one<C, T>(
1838            &self,
1839            ctx: C,
1840            function: fn(C, ParseStream) -> syn::Result<T>,
1841        ) -> syn::Result<T> {
1842            match self.maybe_child() {
1843                Ok(_) => function(ctx, self.stream),
1844                Err(e) => Err(e),
1845            }
1846        }
1847
1848        pub fn parse_many<C: Copy, T>(
1849            &self,
1850            ctx: C,
1851            function: fn(C, ParseStream) -> syn::Result<T>,
1852        ) -> syn::Result<Vec<T>> {
1853            let mut inputs = vec![self.parse_one(ctx, function)?];
1854            while self.maybe_child().is_ok() {
1855                inputs.push(function(ctx, self.stream)?);
1856            }
1857            Ok(inputs)
1858        }
1859
1860        fn maybe_child(&self) -> syn::Result<()> {
1861            let start = self.stream.span().start();
1862            if start.line <= self.parent.line {
1863                let msg = format!("child expected at line > {}", self.parent.line);
1864                Err(Error::new(self.stream.span(), msg))?
1865            }
1866            if start.column != self.parent.column + 2 {
1867                let msg = format!("child expected at column {}", self.parent.column + 2);
1868                Err(Error::new(self.stream.span(), msg))?
1869            }
1870            Ok(())
1871        }
1872    }
1873}
1874
1875/// Custom keywords used while parsing.
1876mod kw {
1877    syn::custom_keyword!(aggregates);
1878    syn::custom_keyword!(AND);
1879    syn::custom_keyword!(ArrangeBy);
1880    syn::custom_keyword!(array);
1881    syn::custom_keyword!(asc);
1882    // case when ... then ... else ... end
1883    syn::custom_keyword!(case);
1884    syn::custom_keyword!(coalesce);
1885    syn::custom_keyword!(Constant);
1886    syn::custom_keyword!(CrossJoin);
1887    syn::custom_keyword!(cte);
1888    syn::custom_keyword!(desc);
1889    syn::custom_keyword!(distinct);
1890    syn::custom_keyword!(Distinct);
1891    syn::custom_keyword!(empty);
1892    syn::custom_keyword!(end);
1893    syn::custom_keyword!(eq);
1894    syn::custom_keyword!(error);
1895    syn::custom_keyword!(exp_group_size);
1896    syn::custom_keyword!(FALSE);
1897    syn::custom_keyword!(Filter);
1898    syn::custom_keyword!(FlatMap);
1899    syn::custom_keyword!(Get);
1900    syn::custom_keyword!(group_by);
1901    syn::custom_keyword!(IS);
1902    syn::custom_keyword!(Join);
1903    syn::custom_keyword!(keys);
1904    syn::custom_keyword!(limit);
1905    syn::custom_keyword!(list);
1906    syn::custom_keyword!(Map);
1907    syn::custom_keyword!(monotonic);
1908    syn::custom_keyword!(Mutually);
1909    syn::custom_keyword!(Negate);
1910    syn::custom_keyword!(NOT);
1911    syn::custom_keyword!(null);
1912    syn::custom_keyword!(NULL);
1913    syn::custom_keyword!(nulls_first);
1914    syn::custom_keyword!(nulls_last);
1915    syn::custom_keyword!(offset);
1916    syn::custom_keyword!(on);
1917    syn::custom_keyword!(OR);
1918    syn::custom_keyword!(order_by);
1919    syn::custom_keyword!(project);
1920    syn::custom_keyword!(Project);
1921    syn::custom_keyword!(Recursive);
1922    syn::custom_keyword!(Reduce);
1923    syn::custom_keyword!(Return);
1924    syn::custom_keyword!(then);
1925    syn::custom_keyword!(Threshold);
1926    syn::custom_keyword!(TopK);
1927    syn::custom_keyword!(TRUE);
1928    syn::custom_keyword!(Union);
1929    syn::custom_keyword!(when);
1930    syn::custom_keyword!(With);
1931    syn::custom_keyword!(x);
1932}
1933
1934#[cfg(test)]
1935mod tests {
1936    use mz_expr::{MirScalarExpr, func};
1937    use mz_repr::{ReprScalarType, SqlScalarType};
1938
1939    use super::*;
1940
1941    #[mz_ore::test]
1942    fn parse_scalar_variant_names() {
1943        let actual = try_parse_scalar("is_null(add_int32(#1, #0))").unwrap();
1944        let expected = MirScalarExpr::CallUnary {
1945            func: func::IsNull.into(),
1946            expr: Box::new(MirScalarExpr::CallBinary {
1947                func: func::AddInt32.into(),
1948                expr1: Box::new(MirScalarExpr::column(1)),
1949                expr2: Box::new(MirScalarExpr::column(0)),
1950            }),
1951        };
1952        assert_eq!(actual, expected);
1953    }
1954
1955    #[mz_ore::test]
1956    fn parse_scalar_parameterized() {
1957        let actual = try_parse_scalar("record_get[1](#0)").unwrap();
1958        let expected = MirScalarExpr::CallUnary {
1959            func: func::RecordGet(1).into(),
1960            expr: Box::new(MirScalarExpr::column(0)),
1961        };
1962        assert_eq!(actual, expected);
1963
1964        let actual = try_parse_scalar("list_create[integer](#0)").unwrap();
1965        let expected = MirScalarExpr::call_variadic(
1966            func::variadic::ListCreate {
1967                elem_type: SqlScalarType::Int32,
1968            },
1969            vec![MirScalarExpr::column(0)],
1970        );
1971        assert_eq!(actual, expected);
1972    }
1973
1974    #[mz_ore::test]
1975    #[cfg_attr(miri, ignore)] // unsupported operation: can't call foreign function `decContextDefault` on OS `linux`
1976    fn parse_scalar_typed_literals() {
1977        let actual = try_parse_scalar(r#""{\"a\": 1}"::jsonb"#).unwrap();
1978        let MirScalarExpr::Literal(Ok(_), typ) = &actual else {
1979            panic!("expected literal, got {actual:?}");
1980        };
1981        assert_eq!(typ.scalar_type, ReprScalarType::Jsonb);
1982
1983        let actual = try_parse_scalar("2000.5::numeric").unwrap();
1984        let MirScalarExpr::Literal(Ok(row), typ) = &actual else {
1985            panic!("expected literal, got {actual:?}");
1986        };
1987        assert_eq!(typ.scalar_type, ReprScalarType::Numeric);
1988        assert_eq!(row.unpack_first().to_string(), "2000.5");
1989    }
1990
1991    #[mz_ore::test]
1992    fn parse_column_types() {
1993        let actual = try_parse_column_types("(bigint, text?)").unwrap();
1994        assert_eq!(actual.len(), 2);
1995        assert_eq!(actual[0].scalar_type, SqlScalarType::Int64);
1996        assert!(!actual[0].nullable);
1997        assert_eq!(actual[1].scalar_type, SqlScalarType::String);
1998        assert!(actual[1].nullable);
1999    }
2000}