1use 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
29pub fn try_parse_mir(catalog: &TestCatalog, s: &str) -> Result<mz_expr::MirRelationExpr, String> {
31 let parser = move |input: ParseStream| {
34 let ctx = Ctx { catalog };
35 relation::parse_expr(&ctx, input)
36 };
37 let s = s.replace("// {", ":: {");
40 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 relation::fix_types(&mut expr, &mut relation::FixTypesCtx::default())?;
48 Ok(expr)
50}
51
52pub 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
70pub 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
88pub 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
109pub fn try_parse_def(catalog: &TestCatalog, s: &str) -> Result<Def, String> {
111 let parser = move |input: ParseStream| {
114 let ctx = Ctx { catalog };
115 def::parse_def(&ctx, input)
116 };
117 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 Ok(def)
124}
125
126mod 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 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 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 let value = {
327 let get_cte = MirRelationExpr::Get {
328 id: Id::Local(id),
329 typ,
330 access_strategy: AccessStrategy::UnknownOrLocal,
331 };
332 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); }
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, },
419 "unnest_array" => UnnestArray {
420 el_typ: SqlScalarType::Int64, },
422 "wrap1" => Wrap {
423 types: vec![
424 SqlScalarType::Int64.nullable(true), ],
426 width: 1,
427 },
428 "wrap2" => Wrap {
429 types: vec![
430 SqlScalarType::Int64.nullable(true), SqlScalarType::Int64.nullable(true), ],
433 width: 2,
434 },
435 "wrap3" => Wrap {
436 types: vec![
437 SqlScalarType::Int64.nullable(true), SqlScalarType::Int64.nullable(true), SqlScalarType::Int64.nullable(true), ],
441 width: 3,
442 },
443 "generate_series" => GenerateSeriesInt64,
444 "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 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
786mod 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 pub fn parse_expr(input: ParseStream) -> Result {
821 let line = input.span().start().line;
822
823 #[derive(Debug)]
825 enum Op {
826 Unr(mz_expr::UnaryFunc), Neg(mz_expr::UnaryFunc), Bin(mz_expr::BinaryFunc),
829 Var(mz_expr::VariadicFunc),
830 }
831
832 impl Op {
833 fn precedence(&self) -> Option<usize> {
834 match self {
835 Op::Var(mz_expr::VariadicFunc::Or(_)) => Some(1),
837 Op::Var(mz_expr::VariadicFunc::And(_)) => Some(2),
839 Op::Bin(mz_expr::BinaryFunc::Eq(_)) => Some(4),
841 Op::Bin(mz_expr::BinaryFunc::NotEq(_)) => Some(4),
842 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 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 Op::Bin(mz_expr::BinaryFunc::AddInt64(_)) => Some(14),
856 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 _ => None,
862 }
863 }
864 }
865
866 #[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; while !input.is_empty() && input.span().start().line == line {
879 if exp_opd {
881 postfix.push(Entry::Operand(parse_operand(input)?));
882 exp_opd = false;
883 } else {
884 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()) } else if input.eat(syn::Token![*]) {
908 exp_opd = true;
909 Op::Bin(func::MulInt64.into()) } else if input.eat(syn::Token![/]) {
911 exp_opd = true;
912 Op::Bin(func::DivInt64.into()) } else if input.eat(syn::Token![%]) {
914 exp_opd = true;
915 Op::Bin(func::ModInt64.into()) } 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 break;
945 };
946
947 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 opstack.push(op);
961 }
962 }
963
964 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 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 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 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 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; let func = VariadicFunc::ArrayCreate(ArrayCreate { elem_type });
1200 let exprs = input.parse_comma_sep(parse_literal_ok)?;
1201
1202 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))); 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; let func = VariadicFunc::ListCreate(ListCreate { elem_type });
1213 let exprs = input.parse_comma_sep(parse_literal_ok)?;
1214
1215 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))); 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 let inner;
1228 syn::bracketed!(inner in input);
1229
1230 let elem_type = SqlScalarType::Int64; 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 let inner;
1244 syn::bracketed!(inner in input);
1245
1246 let elem_type = SqlScalarType::Int64; 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 if input.peek(syn::token::Bracket) {
1259 return parse_apply_parameterized(&ident, input);
1260 }
1261
1262 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 match ident.to_string().to_lowercase().as_str() {
1287 "abs" => parse_unary(func::AbsInt64.into()),
1289 "not" => parse_unary(func::Not.into()),
1290 "ltrim" => parse_binary(func::TrimLeading.into()),
1292 "greatest" => parse_variadic(VariadicFunc::Greatest(func::variadic::Greatest)),
1294 "coalesce" => parse_variadic(VariadicFunc::Coalesce(func::variadic::Coalesce)),
1295 "mz_now" => Ok(MirScalarExpr::CallUnmaterializable(
1297 mz_expr::UnmaterializableFunc::MzNow,
1298 )),
1299 name => {
1302 let exprs = inner.parse_comma_sep(parse_expr)?;
1303 parse_apply_variant(&ident, name, exprs)
1304 }
1305 }
1306 }
1307
1308 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 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(¶ms)?);
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 if let MirScalarExpr::CallBinary {
1400 func: BinaryFunc::Eq(_),
1401 expr1,
1402 expr2,
1403 } = operand
1404 {
1405 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
1424mod 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 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 "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 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, })
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
1479mod row {
1481 use mz_repr::{Datum, ReprColumnType, ReprScalarType, Row};
1482
1483 use super::*;
1484
1485 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 (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 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 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) }
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
1729mod util {
1731 use syn::parse::{Lookahead1, ParseBuffer, Peek};
1732
1733 use super::*;
1734
1735 pub trait ParseBufferExt<'a> {
1737 fn look_and_eat<T: Eat>(&self, token: T, lookahead: &Lookahead1<'a>) -> bool;
1738
1739 fn eat<T: Eat>(&self, t: T) -> bool;
1741
1742 fn eat2<T1: Eat, T2: Eat>(&self, t1: T1, t2: T2) -> bool;
1744
1745 fn eat3<T1: Eat, T2: Eat, T3: Eat>(&self, t1: T1, t2: T2, t3: T3) -> bool;
1747
1748 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 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 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 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
1875mod 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 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)] 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}