Skip to main content

mz_sql/plan/
hir.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//! This file houses HIR, a representation of a SQL plan that is parallel to MIR, but represents
11//! an earlier phase of planning. It's structurally very similar to MIR, with some differences
12//! which are noted below. It gets turned into MIR via a call to lower().
13
14use std::collections::{BTreeMap, BTreeSet};
15use std::fmt::{Display, Formatter};
16use std::sync::Arc;
17use std::{fmt, mem};
18
19use itertools::Itertools;
20use mz_expr::virtual_syntax::{AlgExcept, Except, IR};
21use mz_expr::visit::{Visit, VisitChildren};
22use mz_expr::{CollectionPlan, Id, LetRecLimit, RowSetFinishing, func};
23// these happen to be unchanged at the moment, but there might be additions later
24use mz_expr::AggregateFunc::{FusedWindowAggregate, WindowAggregate};
25use mz_expr::func::variadic::{And, Or};
26pub use mz_expr::{
27    BinaryFunc, ColumnOrder, TableFunc, UnaryFunc, UnmaterializableFunc, VariadicFunc, WindowFrame,
28};
29use mz_ore::collections::CollectionExt;
30use mz_ore::error::ErrorExt;
31use mz_ore::str::separated;
32use mz_ore::treat_as_equal::TreatAsEqual;
33use mz_ore::{soft_assert_or_log, stack};
34use mz_repr::adt::array::ArrayDimension;
35use mz_repr::adt::numeric::NumericMaxScale;
36use mz_repr::*;
37use serde::{Deserialize, Serialize};
38
39use crate::plan::error::PlanError;
40use crate::plan::query::{
41    EXECUTE_CAST_CONTEXT, ExprContext, execute_expr_context, offset_into_value,
42};
43use crate::plan::typeconv::{self, CastContext, plan_cast};
44use crate::plan::{Params, QueryContext, QueryLifetime, StatementContext};
45
46use super::plan_utils::GroupSizeHints;
47
48#[allow(missing_debug_implementations)]
49pub struct Hir;
50
51impl IR for Hir {
52    type Relation = HirRelationExpr;
53    type Scalar = HirScalarExpr;
54}
55
56impl AlgExcept for Hir {
57    fn except(all: &bool, lhs: Self::Relation, rhs: Self::Relation) -> Self::Relation {
58        if *all {
59            let rhs = rhs.negate();
60            HirRelationExpr::union(lhs, rhs).threshold()
61        } else {
62            let lhs = lhs.distinct();
63            let rhs = rhs.distinct().negate();
64            HirRelationExpr::union(lhs, rhs).threshold()
65        }
66    }
67
68    fn un_except<'a>(expr: &'a Self::Relation) -> Option<Except<'a, Self>> {
69        let mut result = None;
70
71        use HirRelationExpr::*;
72        if let Threshold { input } = expr {
73            if let Union { base: lhs, inputs } = input.as_ref() {
74                if let [rhs] = &inputs[..] {
75                    if let Negate { input: rhs } = rhs {
76                        match (lhs.as_ref(), rhs.as_ref()) {
77                            (Distinct { input: lhs }, Distinct { input: rhs }) => {
78                                let all = false;
79                                let lhs = lhs.as_ref();
80                                let rhs = rhs.as_ref();
81                                result = Some(Except { all, lhs, rhs })
82                            }
83                            (lhs, rhs) => {
84                                let all = true;
85                                result = Some(Except { all, lhs, rhs })
86                            }
87                        }
88                    }
89                }
90            }
91        }
92
93        result
94    }
95}
96
97#[derive(
98    Debug,
99    Clone,
100    PartialEq,
101    Eq,
102    PartialOrd,
103    Ord,
104    Hash,
105    Serialize,
106    Deserialize
107)]
108/// Just like [`mz_expr::MirRelationExpr`], except where otherwise noted below.
109pub enum HirRelationExpr {
110    Constant {
111        rows: Vec<Row>,
112        typ: SqlRelationType,
113    },
114    Get {
115        id: mz_expr::Id,
116        typ: SqlRelationType,
117    },
118    /// Mutually recursive CTE
119    LetRec {
120        /// Maximum number of iterations to evaluate. If None, then there is no limit.
121        limit: Option<LetRecLimit>,
122        /// List of bindings all of which are in scope of each other.
123        bindings: Vec<(String, mz_expr::LocalId, HirRelationExpr, SqlRelationType)>,
124        /// Result of the AST node.
125        body: Box<HirRelationExpr>,
126    },
127    /// CTE
128    Let {
129        name: String,
130        /// The identifier to be used in `Get` variants to retrieve `value`.
131        id: mz_expr::LocalId,
132        /// The collection to be bound to `name`.
133        value: Box<HirRelationExpr>,
134        /// The result of the `Let`, evaluated with `name` bound to `value`.
135        body: Box<HirRelationExpr>,
136    },
137    Project {
138        input: Box<HirRelationExpr>,
139        outputs: Vec<usize>,
140    },
141    Map {
142        input: Box<HirRelationExpr>,
143        scalars: Vec<HirScalarExpr>,
144    },
145    CallTable {
146        func: TableFunc,
147        exprs: Vec<HirScalarExpr>,
148    },
149    Filter {
150        input: Box<HirRelationExpr>,
151        predicates: Vec<HirScalarExpr>,
152    },
153    /// Unlike MirRelationExpr, we haven't yet compiled LeftOuter/RightOuter/FullOuter
154    /// joins away into more primitive exprs
155    Join {
156        left: Box<HirRelationExpr>,
157        right: Box<HirRelationExpr>,
158        on: HirScalarExpr,
159        kind: JoinKind,
160    },
161    /// Unlike MirRelationExpr, when `key` is empty AND `input` is empty this returns
162    /// a single row with the aggregates evaluated over empty groups, rather than returning zero
163    /// rows
164    Reduce {
165        input: Box<HirRelationExpr>,
166        group_key: Vec<usize>,
167        aggregates: Vec<AggregateExpr>,
168        expected_group_size: Option<u64>,
169    },
170    Distinct {
171        input: Box<HirRelationExpr>,
172    },
173    /// Groups and orders within each group, limiting output.
174    TopK {
175        /// The source collection.
176        input: Box<HirRelationExpr>,
177        /// Column indices used to form groups.
178        group_key: Vec<usize>,
179        /// Column indices used to order rows within groups.
180        order_key: Vec<ColumnOrder>,
181        /// Number of records to retain.
182        /// It is of SqlScalarType::Int64.
183        /// (UInt64 would make sense in theory: Then we wouldn't need to manually check
184        /// non-negativity, but would just get this for free when casting to UInt64. However, Int64
185        /// is better for Postgres compat. This is because if there is a $1 here, then when external
186        /// tools `describe` the prepared statement, they discover this type. If what they find
187        /// were UInt64, then they might have trouble calling the prepared statement, because the
188        /// unsigned types are non-standard, and also don't exist even in Postgres.)
189        limit: Option<HirScalarExpr>,
190        /// Number of records to skip.
191        /// It is of SqlScalarType::Int64.
192        /// This can contain parameters at first, but by the time we reach lowering, this should
193        /// already be simply a Literal.
194        offset: HirScalarExpr,
195        /// User-supplied hint: how many rows will have the same group key.
196        expected_group_size: Option<u64>,
197    },
198    Negate {
199        input: Box<HirRelationExpr>,
200    },
201    /// Keep rows from a dataflow where the row counts are positive.
202    Threshold {
203        input: Box<HirRelationExpr>,
204    },
205    Union {
206        base: Box<HirRelationExpr>,
207        inputs: Vec<HirRelationExpr>,
208    },
209}
210
211/// Stored column metadata.
212pub type NameMetadata = TreatAsEqual<Option<Arc<str>>>;
213
214#[derive(
215    Debug,
216    Clone,
217    PartialEq,
218    Eq,
219    PartialOrd,
220    Ord,
221    Hash,
222    Serialize,
223    Deserialize
224)]
225/// Just like [`mz_expr::MirScalarExpr`], except where otherwise noted below.
226pub enum HirScalarExpr {
227    /// Unlike mz_expr::MirScalarExpr, we can nest HirRelationExprs via eg Exists. This means that a
228    /// variable could refer to a column of the current input, or to a column of an outer relation.
229    /// We use ColumnRef to denote the difference.
230    Column(ColumnRef, NameMetadata),
231    Parameter(usize, NameMetadata),
232    Literal(Row, SqlColumnType, NameMetadata),
233    CallUnmaterializable(UnmaterializableFunc, NameMetadata),
234    CallUnary {
235        func: UnaryFunc,
236        expr: Box<HirScalarExpr>,
237        name: NameMetadata,
238    },
239    CallBinary {
240        func: BinaryFunc,
241        expr1: Box<HirScalarExpr>,
242        expr2: Box<HirScalarExpr>,
243        name: NameMetadata,
244    },
245    CallVariadic {
246        func: VariadicFunc,
247        exprs: Vec<HirScalarExpr>,
248        name: NameMetadata,
249    },
250    If {
251        cond: Box<HirScalarExpr>,
252        then: Box<HirScalarExpr>,
253        els: Box<HirScalarExpr>,
254        name: NameMetadata,
255    },
256    /// Returns true if `expr` returns any rows
257    Exists(Box<HirRelationExpr>, NameMetadata),
258    /// Given `expr` with arity 1. If expr returns:
259    /// * 0 rows, return NULL
260    /// * 1 row, return the value of that row
261    /// * >1 rows, we return an error
262    Select(Box<HirRelationExpr>, NameMetadata),
263    Windowing(WindowExpr, NameMetadata),
264}
265
266#[derive(
267    Debug,
268    Clone,
269    PartialEq,
270    Eq,
271    PartialOrd,
272    Ord,
273    Hash,
274    Serialize,
275    Deserialize
276)]
277/// Represents the invocation of a window function over an optional partitioning with an optional
278/// order.
279pub struct WindowExpr {
280    pub func: WindowExprType,
281    pub partition_by: Vec<HirScalarExpr>,
282    /// ORDER BY is represented in a complicated way: `plan_function_order_by` gave us two things:
283    ///  - the `ColumnOrder`s we have put in the `order_by` fields in the `WindowExprType` in `func`
284    ///    above,
285    ///  - the `HirScalarExpr`s we have put in the following `order_by` field.
286    /// These are separated because they are used in different places: the outer `order_by` is used
287    /// in the lowering: based on it, we create a Row constructor that collects the scalar exprs;
288    /// the inner `order_by` is used in the rendering to actually execute the ordering on these Rows.
289    /// (`WindowExpr` exists only in HIR, but not in MIR.)
290    /// Note that the `column` field in the `ColumnOrder`s point into the Row constructed in the
291    /// lowering, and not to original input columns.
292    pub order_by: Vec<HirScalarExpr>,
293}
294
295impl WindowExpr {
296    pub fn visit_expressions<'a, F, E>(&'a self, f: &mut F) -> Result<(), E>
297    where
298        F: FnMut(&'a HirScalarExpr) -> Result<(), E>,
299    {
300        #[allow(deprecated)]
301        self.func.visit_expressions(f)?;
302        for expr in self.partition_by.iter() {
303            f(expr)?;
304        }
305        for expr in self.order_by.iter() {
306            f(expr)?;
307        }
308        Ok(())
309    }
310
311    pub fn visit_expressions_mut<'a, F, E>(&'a mut self, f: &mut F) -> Result<(), E>
312    where
313        F: FnMut(&'a mut HirScalarExpr) -> Result<(), E>,
314    {
315        #[allow(deprecated)]
316        self.func.visit_expressions_mut(f)?;
317        for expr in self.partition_by.iter_mut() {
318            f(expr)?;
319        }
320        for expr in self.order_by.iter_mut() {
321            f(expr)?;
322        }
323        Ok(())
324    }
325}
326
327/// Yields the scalars in `func`'s arguments, plus those in `partition_by`
328/// and `order_by`; does not descend into them.
329impl VisitChildren<HirScalarExpr> for WindowExpr {
330    fn visit_children<F>(&self, mut f: F)
331    where
332        F: FnMut(&HirScalarExpr),
333    {
334        self.func.visit_children(&mut f);
335        for expr in self.partition_by.iter() {
336            f(expr);
337        }
338        for expr in self.order_by.iter() {
339            f(expr);
340        }
341    }
342
343    fn visit_mut_children<F>(&mut self, mut f: F)
344    where
345        F: FnMut(&mut HirScalarExpr),
346    {
347        self.func.visit_mut_children(&mut f);
348        for expr in self.partition_by.iter_mut() {
349            f(expr);
350        }
351        for expr in self.order_by.iter_mut() {
352            f(expr);
353        }
354    }
355
356    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
357    where
358        F: FnMut(&HirScalarExpr) -> Result<(), E>,
359    {
360        self.func.try_visit_children(&mut f)?;
361        for expr in self.partition_by.iter() {
362            f(expr)?;
363        }
364        for expr in self.order_by.iter() {
365            f(expr)?;
366        }
367        Ok(())
368    }
369
370    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
371    where
372        F: FnMut(&mut HirScalarExpr) -> Result<(), E>,
373    {
374        self.func.try_visit_mut_children(&mut f)?;
375        for expr in self.partition_by.iter_mut() {
376            f(expr)?;
377        }
378        for expr in self.order_by.iter_mut() {
379            f(expr)?;
380        }
381        Ok(())
382    }
383
384    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a HirScalarExpr>
385    where
386        HirScalarExpr: 'a,
387    {
388        self.func
389            .children()
390            .chain(self.partition_by.iter())
391            .chain(self.order_by.iter())
392    }
393
394    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut HirScalarExpr>
395    where
396        HirScalarExpr: 'a,
397    {
398        self.func
399            .children_mut()
400            .chain(self.partition_by.iter_mut())
401            .chain(self.order_by.iter_mut())
402    }
403}
404
405#[derive(
406    Debug,
407    Clone,
408    PartialEq,
409    Eq,
410    PartialOrd,
411    Ord,
412    Hash,
413    Serialize,
414    Deserialize
415)]
416/// A window function with its parameters.
417///
418/// There are three types of window functions:
419/// - scalar window functions, which return a different scalar value for each
420///   row within a partition that depends exclusively on the position of the row
421///   within the partition;
422/// - value window functions, which return a scalar value for each row within a
423///   partition that might be computed based on a single row, which is usually not
424///   the current row (e.g., previous or following row; first or last row of the
425///   partition);
426/// - aggregate window functions, which compute a traditional aggregation as a
427///   window function (e.g. `sum(x) OVER (...)`).
428///   (Aggregate window  functions can in some cases be computed by joining the
429///   input relation with a reduction over the same relation that computes the
430///   aggregation using the partition key as its grouping key, but we don't
431///   automatically do this currently.)
432pub enum WindowExprType {
433    Scalar(ScalarWindowExpr),
434    Value(ValueWindowExpr),
435    Aggregate(AggregateWindowExpr),
436}
437
438impl WindowExprType {
439    #[deprecated = "Use `VisitChildren<HirScalarExpr>::visit_children` instead."]
440    pub fn visit_expressions<'a, F, E>(&'a self, f: &mut F) -> Result<(), E>
441    where
442        F: FnMut(&'a HirScalarExpr) -> Result<(), E>,
443    {
444        #[allow(deprecated)]
445        match self {
446            Self::Scalar(expr) => expr.visit_expressions(f),
447            Self::Value(expr) => expr.visit_expressions(f),
448            Self::Aggregate(expr) => expr.visit_expressions(f),
449        }
450    }
451
452    #[deprecated = "Use `VisitChildren<HirScalarExpr>::visit_mut_children` instead."]
453    pub fn visit_expressions_mut<'a, F, E>(&'a mut self, f: &mut F) -> Result<(), E>
454    where
455        F: FnMut(&'a mut HirScalarExpr) -> Result<(), E>,
456    {
457        #[allow(deprecated)]
458        match self {
459            Self::Scalar(expr) => expr.visit_expressions_mut(f),
460            Self::Value(expr) => expr.visit_expressions_mut(f),
461            Self::Aggregate(expr) => expr.visit_expressions_mut(f),
462        }
463    }
464
465    fn typ(
466        &self,
467        outers: &[SqlRelationType],
468        inner: &SqlRelationType,
469        params: &BTreeMap<usize, SqlScalarType>,
470    ) -> SqlColumnType {
471        match self {
472            Self::Scalar(expr) => expr.typ(outers, inner, params),
473            Self::Value(expr) => expr.typ(outers, inner, params),
474            Self::Aggregate(expr) => expr.typ(outers, inner, params),
475        }
476    }
477}
478
479/// Dispatches to the inner `Value` / `Aggregate` variant's scalar children;
480/// `Scalar` window functions have no scalar children.
481impl VisitChildren<HirScalarExpr> for WindowExprType {
482    fn visit_children<F>(&self, f: F)
483    where
484        F: FnMut(&HirScalarExpr),
485    {
486        match self {
487            Self::Scalar(_) => (),
488            Self::Value(expr) => expr.visit_children(f),
489            Self::Aggregate(expr) => expr.visit_children(f),
490        }
491    }
492
493    fn visit_mut_children<F>(&mut self, f: F)
494    where
495        F: FnMut(&mut HirScalarExpr),
496    {
497        match self {
498            Self::Scalar(_) => (),
499            Self::Value(expr) => expr.visit_mut_children(f),
500            Self::Aggregate(expr) => expr.visit_mut_children(f),
501        }
502    }
503
504    fn try_visit_children<F, E>(&self, f: F) -> Result<(), E>
505    where
506        F: FnMut(&HirScalarExpr) -> Result<(), E>,
507    {
508        match self {
509            Self::Scalar(_) => Ok(()),
510            Self::Value(expr) => expr.try_visit_children(f),
511            Self::Aggregate(expr) => expr.try_visit_children(f),
512        }
513    }
514
515    fn try_visit_mut_children<F, E>(&mut self, f: F) -> Result<(), E>
516    where
517        F: FnMut(&mut HirScalarExpr) -> Result<(), E>,
518    {
519        match self {
520            Self::Scalar(_) => Ok(()),
521            Self::Value(expr) => expr.try_visit_mut_children(f),
522            Self::Aggregate(expr) => expr.try_visit_mut_children(f),
523        }
524    }
525
526    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a HirScalarExpr>
527    where
528        HirScalarExpr: 'a,
529    {
530        match self {
531            Self::Scalar(_) => vec![],
532            Self::Value(expr) => expr.children().collect(),
533            Self::Aggregate(expr) => expr.children().collect(),
534        }
535        .into_iter()
536    }
537
538    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut HirScalarExpr>
539    where
540        HirScalarExpr: 'a,
541    {
542        match self {
543            Self::Scalar(_) => vec![],
544            Self::Value(expr) => expr.children_mut().collect(),
545            Self::Aggregate(expr) => expr.children_mut().collect(),
546        }
547        .into_iter()
548    }
549}
550
551#[derive(
552    Debug,
553    Clone,
554    PartialEq,
555    Eq,
556    PartialOrd,
557    Ord,
558    Hash,
559    Serialize,
560    Deserialize
561)]
562pub struct ScalarWindowExpr {
563    pub func: ScalarWindowFunc,
564    pub order_by: Vec<ColumnOrder>,
565}
566
567impl ScalarWindowExpr {
568    #[deprecated = "Implement `VisitChildren<HirScalarExpr>` if needed."]
569    pub fn visit_expressions<'a, F, E>(&'a self, _f: &mut F) -> Result<(), E>
570    where
571        F: FnMut(&'a HirScalarExpr) -> Result<(), E>,
572    {
573        match self.func {
574            ScalarWindowFunc::RowNumber => {}
575            ScalarWindowFunc::Rank => {}
576            ScalarWindowFunc::DenseRank => {}
577        }
578        Ok(())
579    }
580
581    #[deprecated = "Implement `VisitChildren<HirScalarExpr>` if needed."]
582    pub fn visit_expressions_mut<'a, F, E>(&'a self, _f: &mut F) -> Result<(), E>
583    where
584        F: FnMut(&'a mut HirScalarExpr) -> Result<(), E>,
585    {
586        match self.func {
587            ScalarWindowFunc::RowNumber => {}
588            ScalarWindowFunc::Rank => {}
589            ScalarWindowFunc::DenseRank => {}
590        }
591        Ok(())
592    }
593
594    fn typ(
595        &self,
596        _outers: &[SqlRelationType],
597        _inner: &SqlRelationType,
598        _params: &BTreeMap<usize, SqlScalarType>,
599    ) -> SqlColumnType {
600        self.func.output_sql_type()
601    }
602
603    pub fn into_expr(self) -> mz_expr::AggregateFunc {
604        match self.func {
605            ScalarWindowFunc::RowNumber => mz_expr::AggregateFunc::RowNumber {
606                order_by: self.order_by,
607            },
608            ScalarWindowFunc::Rank => mz_expr::AggregateFunc::Rank {
609                order_by: self.order_by,
610            },
611            ScalarWindowFunc::DenseRank => mz_expr::AggregateFunc::DenseRank {
612                order_by: self.order_by,
613            },
614        }
615    }
616}
617
618#[derive(
619    Debug,
620    Clone,
621    PartialEq,
622    Eq,
623    PartialOrd,
624    Ord,
625    Hash,
626    Serialize,
627    Deserialize
628)]
629/// Scalar Window functions
630pub enum ScalarWindowFunc {
631    RowNumber,
632    Rank,
633    DenseRank,
634}
635
636impl Display for ScalarWindowFunc {
637    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
638        match self {
639            ScalarWindowFunc::RowNumber => write!(f, "row_number"),
640            ScalarWindowFunc::Rank => write!(f, "rank"),
641            ScalarWindowFunc::DenseRank => write!(f, "dense_rank"),
642        }
643    }
644}
645
646impl ScalarWindowFunc {
647    pub fn output_sql_type(&self) -> SqlColumnType {
648        match self {
649            ScalarWindowFunc::RowNumber => SqlScalarType::Int64.nullable(false),
650            ScalarWindowFunc::Rank => SqlScalarType::Int64.nullable(false),
651            ScalarWindowFunc::DenseRank => SqlScalarType::Int64.nullable(false),
652        }
653    }
654}
655
656#[derive(
657    Debug,
658    Clone,
659    PartialEq,
660    Eq,
661    PartialOrd,
662    Ord,
663    Hash,
664    Serialize,
665    Deserialize
666)]
667pub struct ValueWindowExpr {
668    pub func: ValueWindowFunc,
669    /// If the argument list has a single element (e.g., for `first_value`), then it's that element.
670    /// If the argument list has multiple elements (e.g., for `lag`), then it's encoded in a record,
671    /// e.g., `row(#1, 3, null)`.
672    /// If it's a fused window function, then the arguments of each of the constituent function
673    /// calls are wrapped in an outer record.
674    pub args: Box<HirScalarExpr>,
675    /// See comment on `WindowExpr::order_by`.
676    pub order_by: Vec<ColumnOrder>,
677    pub window_frame: WindowFrame,
678    pub ignore_nulls: bool,
679}
680
681impl Display for ValueWindowFunc {
682    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
683        match self {
684            ValueWindowFunc::Lag => write!(f, "lag"),
685            ValueWindowFunc::Lead => write!(f, "lead"),
686            ValueWindowFunc::FirstValue => write!(f, "first_value"),
687            ValueWindowFunc::LastValue => write!(f, "last_value"),
688            ValueWindowFunc::Fused(funcs) => write!(f, "fused[{}]", separated(", ", funcs)),
689        }
690    }
691}
692
693impl ValueWindowExpr {
694    #[deprecated = "Use `VisitChildren<HirScalarExpr>::visit_children` instead."]
695    pub fn visit_expressions<'a, F, E>(&'a self, f: &mut F) -> Result<(), E>
696    where
697        F: FnMut(&'a HirScalarExpr) -> Result<(), E>,
698    {
699        f(&self.args)
700    }
701
702    #[deprecated = "Use `VisitChildren<HirScalarExpr>::visit_mut_children` instead."]
703    pub fn visit_expressions_mut<'a, F, E>(&'a mut self, f: &mut F) -> Result<(), E>
704    where
705        F: FnMut(&'a mut HirScalarExpr) -> Result<(), E>,
706    {
707        f(&mut self.args)
708    }
709
710    fn typ(
711        &self,
712        outers: &[SqlRelationType],
713        inner: &SqlRelationType,
714        params: &BTreeMap<usize, SqlScalarType>,
715    ) -> SqlColumnType {
716        self.func
717            .output_sql_type(self.args.typ(outers, inner, params))
718    }
719
720    /// Converts into `mz_expr::AggregateFunc`.
721    pub fn into_expr(self) -> (Box<HirScalarExpr>, mz_expr::AggregateFunc) {
722        (
723            self.args,
724            self.func
725                .into_expr(self.order_by, self.window_frame, self.ignore_nulls),
726        )
727    }
728}
729
730/// Yields `args` (the value-window function's argument expression);
731/// does not descend into it.
732impl VisitChildren<HirScalarExpr> for ValueWindowExpr {
733    // `visit_children` and friends are not implemented explicitly: the trait
734    // defaults delegate to `children`/`children_mut` below, which yield the
735    // single argument expression.
736
737    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a HirScalarExpr>
738    where
739        HirScalarExpr: 'a,
740    {
741        // Yield `args` itself; we must not descend into it (see the impl-level
742        // doc comment). Descending would skip `args` when it is a leaf node
743        // (e.g. `first_value(mz_now())`), breaking `contains_temporal`.
744        std::iter::once(&*self.args)
745    }
746
747    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut HirScalarExpr>
748    where
749        HirScalarExpr: 'a,
750    {
751        std::iter::once(&mut *self.args)
752    }
753}
754
755#[derive(
756    Debug,
757    Clone,
758    PartialEq,
759    Eq,
760    PartialOrd,
761    Ord,
762    Hash,
763    Serialize,
764    Deserialize
765)]
766/// Value Window functions
767pub enum ValueWindowFunc {
768    Lag,
769    Lead,
770    FirstValue,
771    LastValue,
772    Fused(Vec<ValueWindowFunc>),
773}
774
775impl ValueWindowFunc {
776    pub fn output_sql_type(&self, input_type: SqlColumnType) -> SqlColumnType {
777        match self {
778            ValueWindowFunc::Lag | ValueWindowFunc::Lead => {
779                // The input is a (value, offset, default) record, so extract the type of the first arg
780                input_type.scalar_type.unwrap_record_element_type()[0]
781                    .clone()
782                    .nullable(true)
783            }
784            ValueWindowFunc::FirstValue | ValueWindowFunc::LastValue => {
785                input_type.scalar_type.nullable(true)
786            }
787            ValueWindowFunc::Fused(funcs) => {
788                let input_types = input_type.scalar_type.unwrap_record_element_column_type();
789                SqlScalarType::Record {
790                    fields: funcs
791                        .iter()
792                        .zip_eq(input_types)
793                        .map(|(f, t)| (ColumnName::from(""), f.output_sql_type(t.clone())))
794                        .collect(),
795                    custom_id: None,
796                }
797                .nullable(false)
798            }
799        }
800    }
801
802    pub fn into_expr(
803        self,
804        order_by: Vec<ColumnOrder>,
805        window_frame: WindowFrame,
806        ignore_nulls: bool,
807    ) -> mz_expr::AggregateFunc {
808        match self {
809            // Lag and Lead are fundamentally the same function, just with opposite directions
810            ValueWindowFunc::Lag => mz_expr::AggregateFunc::LagLead {
811                order_by,
812                lag_lead: mz_expr::LagLeadType::Lag,
813                ignore_nulls,
814            },
815            ValueWindowFunc::Lead => mz_expr::AggregateFunc::LagLead {
816                order_by,
817                lag_lead: mz_expr::LagLeadType::Lead,
818                ignore_nulls,
819            },
820            ValueWindowFunc::FirstValue => mz_expr::AggregateFunc::FirstValue {
821                order_by,
822                window_frame,
823            },
824            ValueWindowFunc::LastValue => mz_expr::AggregateFunc::LastValue {
825                order_by,
826                window_frame,
827            },
828            ValueWindowFunc::Fused(funcs) => mz_expr::AggregateFunc::FusedValueWindowFunc {
829                funcs: funcs
830                    .into_iter()
831                    .map(|func| {
832                        func.into_expr(order_by.clone(), window_frame.clone(), ignore_nulls)
833                    })
834                    .collect(),
835                order_by,
836            },
837        }
838    }
839}
840
841#[derive(
842    Debug,
843    Clone,
844    PartialEq,
845    Eq,
846    PartialOrd,
847    Ord,
848    Hash,
849    Serialize,
850    Deserialize
851)]
852pub struct AggregateWindowExpr {
853    pub aggregate_expr: AggregateExpr,
854    pub order_by: Vec<ColumnOrder>,
855    pub window_frame: WindowFrame,
856}
857
858impl AggregateWindowExpr {
859    #[deprecated = "Use `VisitChildren<HirScalarExpr>::visit_children` instead."]
860    pub fn visit_expressions<'a, F, E>(&'a self, f: &mut F) -> Result<(), E>
861    where
862        F: FnMut(&'a HirScalarExpr) -> Result<(), E>,
863    {
864        f(&self.aggregate_expr.expr)
865    }
866
867    #[deprecated = "Use `VisitChildren<HirScalarExpr>::visit_mut_children` instead."]
868    pub fn visit_expressions_mut<'a, F, E>(&'a mut self, f: &mut F) -> Result<(), E>
869    where
870        F: FnMut(&'a mut HirScalarExpr) -> Result<(), E>,
871    {
872        f(&mut self.aggregate_expr.expr)
873    }
874
875    fn typ(
876        &self,
877        outers: &[SqlRelationType],
878        inner: &SqlRelationType,
879        params: &BTreeMap<usize, SqlScalarType>,
880    ) -> SqlColumnType {
881        self.aggregate_expr
882            .func
883            .output_sql_type(self.aggregate_expr.expr.typ(outers, inner, params))
884    }
885
886    pub fn into_expr(self) -> (Box<HirScalarExpr>, mz_expr::AggregateFunc) {
887        if let AggregateFunc::FusedWindowAgg { funcs } = &self.aggregate_expr.func {
888            (
889                self.aggregate_expr.expr,
890                FusedWindowAggregate {
891                    wrapped_aggregates: funcs.iter().map(|f| f.clone().into_expr()).collect(),
892                    order_by: self.order_by,
893                    window_frame: self.window_frame,
894                },
895            )
896        } else {
897            (
898                self.aggregate_expr.expr,
899                WindowAggregate {
900                    wrapped_aggregate: Box::new(self.aggregate_expr.func.into_expr()),
901                    order_by: self.order_by,
902                    window_frame: self.window_frame,
903                },
904            )
905        }
906    }
907}
908
909/// Yields the aggregate's argument expression (`aggregate_expr.expr`);
910/// does not descend into it.
911impl VisitChildren<HirScalarExpr> for AggregateWindowExpr {
912    // `visit_children` and friends are not implemented explicitly: the trait
913    // defaults delegate to `children`/`children_mut` below, which yield the
914    // single aggregate argument expression.
915
916    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a HirScalarExpr>
917    where
918        HirScalarExpr: 'a,
919    {
920        // Yield the aggregate's argument expression itself; we must not descend
921        // into it. Descending would skip the argument when it is a leaf node
922        // (e.g. `max(mz_now())`), breaking `contains_temporal`.
923        std::iter::once(&*self.aggregate_expr.expr)
924    }
925
926    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut HirScalarExpr>
927    where
928        HirScalarExpr: 'a,
929    {
930        std::iter::once(&mut *self.aggregate_expr.expr)
931    }
932}
933
934/// A `CoercibleScalarExpr` is a [`HirScalarExpr`] whose type is not fully
935/// determined. Several SQL expressions can be freely coerced based upon where
936/// in the expression tree they appear. For example, the string literal '42'
937/// will be automatically coerced to the integer 42 if used in a numeric
938/// context:
939///
940/// ```sql
941/// SELECT '42' + 42
942/// ```
943///
944/// This separate type gives the code that needs to interact with coercions very
945/// fine-grained control over what coercions happen and when.
946///
947/// The primary driver of coercion is function and operator selection, as
948/// choosing the correct function or operator implementation depends on the type
949/// of the provided arguments. Coercion also occurs at the very root of the
950/// scalar expression tree. For example in
951///
952/// ```sql
953/// SELECT ... WHERE $1
954/// ```
955///
956/// the `WHERE` clause will coerce the contained unconstrained type parameter
957/// `$1` to have type bool.
958#[derive(Clone, Debug)]
959pub enum CoercibleScalarExpr {
960    Coerced(HirScalarExpr),
961    Parameter(usize),
962    LiteralNull,
963    LiteralString(String),
964    LiteralRecord(Vec<CoercibleScalarExpr>),
965}
966
967impl CoercibleScalarExpr {
968    pub fn type_as(
969        self,
970        ecx: &ExprContext,
971        ty: &SqlScalarType,
972    ) -> Result<HirScalarExpr, PlanError> {
973        let expr = typeconv::plan_coerce(ecx, self, ty)?;
974        let expr_ty = ecx.scalar_type(&expr);
975        if ty != &expr_ty {
976            sql_bail!(
977                "{} must have type {}, not type {}",
978                ecx.name,
979                ecx.humanize_sql_scalar_type(ty, false),
980                ecx.humanize_sql_scalar_type(&expr_ty, false),
981            );
982        }
983        Ok(expr)
984    }
985
986    pub fn type_as_any(self, ecx: &ExprContext) -> Result<HirScalarExpr, PlanError> {
987        typeconv::plan_coerce(ecx, self, &SqlScalarType::String)
988    }
989
990    pub fn cast_to(
991        self,
992        ecx: &ExprContext,
993        ccx: CastContext,
994        ty: &SqlScalarType,
995    ) -> Result<HirScalarExpr, PlanError> {
996        let expr = typeconv::plan_coerce(ecx, self, ty)?;
997        typeconv::plan_cast(ecx, ccx, expr, ty)
998    }
999}
1000
1001/// The column type for a [`CoercibleScalarExpr`].
1002#[derive(Clone, Debug)]
1003pub enum CoercibleColumnType {
1004    Coerced(SqlColumnType),
1005    Record(Vec<CoercibleColumnType>),
1006    Uncoerced,
1007}
1008
1009impl CoercibleColumnType {
1010    /// Reports the nullability of the type.
1011    pub fn nullable(&self) -> bool {
1012        match self {
1013            // A coerced value's nullability is known.
1014            CoercibleColumnType::Coerced(ct) => ct.nullable,
1015
1016            // A literal record can never be null.
1017            CoercibleColumnType::Record(_) => false,
1018
1019            // An uncoerced literal may be the literal `NULL`, so we have
1020            // to conservatively assume it is nullable.
1021            CoercibleColumnType::Uncoerced => true,
1022        }
1023    }
1024}
1025
1026/// The scalar type for a [`CoercibleScalarExpr`].
1027#[derive(Clone, Debug)]
1028pub enum CoercibleScalarType {
1029    Coerced(SqlScalarType),
1030    Record(Vec<CoercibleColumnType>),
1031    Uncoerced,
1032}
1033
1034impl CoercibleScalarType {
1035    /// Reports whether the scalar type has been coerced.
1036    pub fn is_coerced(&self) -> bool {
1037        matches!(self, CoercibleScalarType::Coerced(_))
1038    }
1039
1040    /// Returns the coerced scalar type, if the type is coerced.
1041    pub fn as_coerced(&self) -> Option<&SqlScalarType> {
1042        match self {
1043            CoercibleScalarType::Coerced(t) => Some(t),
1044            _ => None,
1045        }
1046    }
1047
1048    /// If the type is coerced, apply the mapping function to the contained
1049    /// scalar type.
1050    pub fn map_coerced<F>(self, f: F) -> CoercibleScalarType
1051    where
1052        F: FnOnce(SqlScalarType) -> SqlScalarType,
1053    {
1054        match self {
1055            CoercibleScalarType::Coerced(t) => CoercibleScalarType::Coerced(f(t)),
1056            _ => self,
1057        }
1058    }
1059
1060    /// If the type is an coercible record, forcibly converts to a coerced
1061    /// record type. Any uncoerced field types are assumed to be of type text.
1062    ///
1063    /// Generally you should prefer to use [`typeconv::plan_coerce`], which
1064    /// accepts a type hint that can indicate the types of uncoerced field
1065    /// types.
1066    pub fn force_coerced_if_record(&mut self) {
1067        fn convert(uncoerced_fields: impl Iterator<Item = CoercibleColumnType>) -> SqlScalarType {
1068            let mut fields = vec![];
1069            for (i, uf) in uncoerced_fields.enumerate() {
1070                let name = ColumnName::from(format!("f{}", i + 1));
1071                let ty = match uf {
1072                    CoercibleColumnType::Coerced(ty) => ty,
1073                    CoercibleColumnType::Record(mut fields) => {
1074                        convert(fields.drain(..)).nullable(false)
1075                    }
1076                    CoercibleColumnType::Uncoerced => SqlScalarType::String.nullable(true),
1077                };
1078                fields.push((name, ty))
1079            }
1080            SqlScalarType::Record {
1081                fields: fields.into(),
1082                custom_id: None,
1083            }
1084        }
1085
1086        if let CoercibleScalarType::Record(fields) = self {
1087            *self = CoercibleScalarType::Coerced(convert(fields.drain(..)));
1088        }
1089    }
1090}
1091
1092/// An expression whose type can be ascertained.
1093///
1094/// Abstracts over `ScalarExpr` and `CoercibleScalarExpr`.
1095pub trait AbstractExpr {
1096    type Type: AbstractColumnType;
1097
1098    /// Computes the type of the expression.
1099    fn typ(
1100        &self,
1101        outers: &[SqlRelationType],
1102        inner: &SqlRelationType,
1103        params: &BTreeMap<usize, SqlScalarType>,
1104    ) -> Self::Type;
1105}
1106
1107impl AbstractExpr for CoercibleScalarExpr {
1108    type Type = CoercibleColumnType;
1109
1110    fn typ(
1111        &self,
1112        outers: &[SqlRelationType],
1113        inner: &SqlRelationType,
1114        params: &BTreeMap<usize, SqlScalarType>,
1115    ) -> Self::Type {
1116        match self {
1117            CoercibleScalarExpr::Coerced(expr) => {
1118                CoercibleColumnType::Coerced(expr.typ(outers, inner, params))
1119            }
1120            CoercibleScalarExpr::LiteralRecord(scalars) => {
1121                let fields = scalars
1122                    .iter()
1123                    .map(|s| s.typ(outers, inner, params))
1124                    .collect();
1125                CoercibleColumnType::Record(fields)
1126            }
1127            _ => CoercibleColumnType::Uncoerced,
1128        }
1129    }
1130}
1131
1132/// A column type-like object whose underlying scalar type-like object can be
1133/// ascertained.
1134///
1135/// Abstracts over `SqlColumnType` and `CoercibleColumnType`.
1136pub trait AbstractColumnType {
1137    type AbstractScalarType;
1138
1139    /// Converts the column type-like object into its inner scalar type-like
1140    /// object.
1141    fn scalar_type(self) -> Self::AbstractScalarType;
1142}
1143
1144impl AbstractColumnType for SqlColumnType {
1145    type AbstractScalarType = SqlScalarType;
1146
1147    fn scalar_type(self) -> Self::AbstractScalarType {
1148        self.scalar_type
1149    }
1150}
1151
1152impl AbstractColumnType for CoercibleColumnType {
1153    type AbstractScalarType = CoercibleScalarType;
1154
1155    fn scalar_type(self) -> Self::AbstractScalarType {
1156        match self {
1157            CoercibleColumnType::Coerced(t) => CoercibleScalarType::Coerced(t.scalar_type),
1158            CoercibleColumnType::Record(t) => CoercibleScalarType::Record(t),
1159            CoercibleColumnType::Uncoerced => CoercibleScalarType::Uncoerced,
1160        }
1161    }
1162}
1163
1164impl From<HirScalarExpr> for CoercibleScalarExpr {
1165    fn from(expr: HirScalarExpr) -> CoercibleScalarExpr {
1166        CoercibleScalarExpr::Coerced(expr)
1167    }
1168}
1169
1170/// A leveled column reference.
1171///
1172/// In the course of decorrelation, multiple levels of nested subqueries are
1173/// traversed, and references to columns may correspond to different levels
1174/// of containing outer subqueries.
1175///
1176/// A `ColumnRef` allows expressions to refer to columns while being clear
1177/// about which level the column references without manually performing the
1178/// bookkeeping tracking their actual column locations.
1179///
1180/// Specifically, a `ColumnRef` refers to a column `level` subquery level *out*
1181/// from the reference, using `column` as a unique identifier in that subquery level.
1182/// A `level` of zero corresponds to the current scope, and levels increase to
1183/// indicate subqueries further "outwards".
1184#[derive(
1185    Debug,
1186    Clone,
1187    Copy,
1188    PartialEq,
1189    Eq,
1190    Hash,
1191    Ord,
1192    PartialOrd,
1193    Serialize,
1194    Deserialize
1195)]
1196pub struct ColumnRef {
1197    // scope level, where 0 is the current scope and 1+ are outer scopes.
1198    pub level: usize,
1199    // level-local column identifier used.
1200    pub column: usize,
1201}
1202
1203#[derive(
1204    Debug,
1205    Clone,
1206    PartialEq,
1207    Eq,
1208    PartialOrd,
1209    Ord,
1210    Hash,
1211    Serialize,
1212    Deserialize
1213)]
1214pub enum JoinKind {
1215    Inner,
1216    LeftOuter,
1217    RightOuter,
1218    FullOuter,
1219}
1220
1221impl fmt::Display for JoinKind {
1222    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1223        write!(
1224            f,
1225            "{}",
1226            match self {
1227                JoinKind::Inner => "Inner",
1228                JoinKind::LeftOuter => "LeftOuter",
1229                JoinKind::RightOuter => "RightOuter",
1230                JoinKind::FullOuter => "FullOuter",
1231            }
1232        )
1233    }
1234}
1235
1236impl JoinKind {
1237    pub fn can_be_correlated(&self) -> bool {
1238        match self {
1239            JoinKind::Inner | JoinKind::LeftOuter => true,
1240            JoinKind::RightOuter | JoinKind::FullOuter => false,
1241        }
1242    }
1243
1244    pub fn can_elide_identity_left_join(&self) -> bool {
1245        match self {
1246            JoinKind::Inner | JoinKind::RightOuter => true,
1247            JoinKind::LeftOuter | JoinKind::FullOuter => false,
1248        }
1249    }
1250
1251    pub fn can_elide_identity_right_join(&self) -> bool {
1252        match self {
1253            JoinKind::Inner | JoinKind::LeftOuter => true,
1254            JoinKind::RightOuter | JoinKind::FullOuter => false,
1255        }
1256    }
1257}
1258
1259#[derive(
1260    Debug,
1261    Clone,
1262    PartialEq,
1263    Eq,
1264    PartialOrd,
1265    Ord,
1266    Hash,
1267    Serialize,
1268    Deserialize
1269)]
1270pub struct AggregateExpr {
1271    pub func: AggregateFunc,
1272    pub expr: Box<HirScalarExpr>,
1273    pub distinct: bool,
1274}
1275
1276/// Aggregate functions analogous to `mz_expr::AggregateFunc`, but whose
1277/// types may be different.
1278///
1279/// Specifically, the nullability of the aggregate columns is more common
1280/// here than in `expr`, as these aggregates may be applied over empty
1281/// result sets and should be null in those cases, whereas `expr` variants
1282/// only return null values when supplied nulls as input.
1283#[derive(
1284    Clone,
1285    Debug,
1286    Eq,
1287    PartialEq,
1288    PartialOrd,
1289    Ord,
1290    Hash,
1291    Serialize,
1292    Deserialize
1293)]
1294pub enum AggregateFunc {
1295    MaxNumeric,
1296    MaxInt16,
1297    MaxInt32,
1298    MaxInt64,
1299    MaxUInt16,
1300    MaxUInt32,
1301    MaxUInt64,
1302    MaxMzTimestamp,
1303    MaxFloat32,
1304    MaxFloat64,
1305    MaxBool,
1306    MaxString,
1307    MaxDate,
1308    MaxTimestamp,
1309    MaxTimestampTz,
1310    MaxInterval,
1311    MaxTime,
1312    MaxArray,
1313    MaxList,
1314    MinNumeric,
1315    MinInt16,
1316    MinInt32,
1317    MinInt64,
1318    MinUInt16,
1319    MinUInt32,
1320    MinUInt64,
1321    MinMzTimestamp,
1322    MinFloat32,
1323    MinFloat64,
1324    MinBool,
1325    MinString,
1326    MinDate,
1327    MinTimestamp,
1328    MinTimestampTz,
1329    MinInterval,
1330    MinTime,
1331    MinArray,
1332    MinList,
1333    SumInt16,
1334    SumInt32,
1335    SumInt64,
1336    SumUInt16,
1337    SumUInt32,
1338    SumUInt64,
1339    SumFloat32,
1340    SumFloat64,
1341    SumNumeric,
1342    SumInterval,
1343    Count,
1344    Any,
1345    All,
1346    /// Accumulates `Datum::List`s whose first element is a JSON-typed `Datum`s
1347    /// into a JSON list. The other elements are columns used by `order_by`.
1348    ///
1349    /// WARNING: Unlike the `jsonb_agg` function that is exposed by the SQL
1350    /// layer, this function filters out `Datum::Null`, for consistency with
1351    /// the other aggregate functions.
1352    JsonbAgg {
1353        order_by: Vec<ColumnOrder>,
1354    },
1355    /// Zips `Datum::List`s whose first element is a JSON-typed `Datum`s into a
1356    /// JSON map. The other elements are columns used by `order_by`.
1357    JsonbObjectAgg {
1358        order_by: Vec<ColumnOrder>,
1359    },
1360    /// Zips a `Datum::List` whose first element is a `Datum::List` guaranteed
1361    /// to be non-empty and whose len % 2 == 0 into a `Datum::Map`. The other
1362    /// elements are columns used by `order_by`.
1363    MapAgg {
1364        order_by: Vec<ColumnOrder>,
1365        value_type: SqlScalarType,
1366    },
1367    /// Accumulates `Datum::List`s whose first element is a `Datum::Array` into a
1368    /// single `Datum::Array`. The other elements are columns used by `order_by`.
1369    ArrayConcat {
1370        order_by: Vec<ColumnOrder>,
1371    },
1372    /// Accumulates `Datum::List`s whose first element is a `Datum::List` into a
1373    /// single `Datum::List`. The other elements are columns used by `order_by`.
1374    ListConcat {
1375        order_by: Vec<ColumnOrder>,
1376    },
1377    StringAgg {
1378        order_by: Vec<ColumnOrder>,
1379    },
1380    /// A bundle of fused window aggregations: its input is a record, whose each
1381    /// component will be the input to one of the `AggregateFunc`s.
1382    ///
1383    /// Importantly, this aggregation can only be present inside a `WindowExpr`,
1384    /// more specifically an `AggregateWindowExpr`.
1385    FusedWindowAgg {
1386        funcs: Vec<AggregateFunc>,
1387    },
1388    /// Accumulates any number of `Datum::Dummy`s into `Datum::Dummy`.
1389    ///
1390    /// Useful for removing an expensive aggregation while maintaining the shape
1391    /// of a reduce operator.
1392    Dummy,
1393}
1394
1395impl AggregateFunc {
1396    /// Converts the `sql::AggregateFunc` to a corresponding `mz_expr::AggregateFunc`.
1397    pub fn into_expr(self) -> mz_expr::AggregateFunc {
1398        match self {
1399            AggregateFunc::MaxNumeric => mz_expr::AggregateFunc::MaxNumeric,
1400            AggregateFunc::MaxInt16 => mz_expr::AggregateFunc::MaxInt16,
1401            AggregateFunc::MaxInt32 => mz_expr::AggregateFunc::MaxInt32,
1402            AggregateFunc::MaxInt64 => mz_expr::AggregateFunc::MaxInt64,
1403            AggregateFunc::MaxUInt16 => mz_expr::AggregateFunc::MaxUInt16,
1404            AggregateFunc::MaxUInt32 => mz_expr::AggregateFunc::MaxUInt32,
1405            AggregateFunc::MaxUInt64 => mz_expr::AggregateFunc::MaxUInt64,
1406            AggregateFunc::MaxMzTimestamp => mz_expr::AggregateFunc::MaxMzTimestamp,
1407            AggregateFunc::MaxFloat32 => mz_expr::AggregateFunc::MaxFloat32,
1408            AggregateFunc::MaxFloat64 => mz_expr::AggregateFunc::MaxFloat64,
1409            AggregateFunc::MaxBool => mz_expr::AggregateFunc::MaxBool,
1410            AggregateFunc::MaxString => mz_expr::AggregateFunc::MaxString,
1411            AggregateFunc::MaxDate => mz_expr::AggregateFunc::MaxDate,
1412            AggregateFunc::MaxTimestamp => mz_expr::AggregateFunc::MaxTimestamp,
1413            AggregateFunc::MaxTimestampTz => mz_expr::AggregateFunc::MaxTimestampTz,
1414            AggregateFunc::MaxInterval => mz_expr::AggregateFunc::MaxInterval,
1415            AggregateFunc::MaxTime => mz_expr::AggregateFunc::MaxTime,
1416            AggregateFunc::MaxArray => mz_expr::AggregateFunc::MaxArray,
1417            AggregateFunc::MaxList => mz_expr::AggregateFunc::MaxList,
1418            AggregateFunc::MinNumeric => mz_expr::AggregateFunc::MinNumeric,
1419            AggregateFunc::MinInt16 => mz_expr::AggregateFunc::MinInt16,
1420            AggregateFunc::MinInt32 => mz_expr::AggregateFunc::MinInt32,
1421            AggregateFunc::MinInt64 => mz_expr::AggregateFunc::MinInt64,
1422            AggregateFunc::MinUInt16 => mz_expr::AggregateFunc::MinUInt16,
1423            AggregateFunc::MinUInt32 => mz_expr::AggregateFunc::MinUInt32,
1424            AggregateFunc::MinUInt64 => mz_expr::AggregateFunc::MinUInt64,
1425            AggregateFunc::MinMzTimestamp => mz_expr::AggregateFunc::MinMzTimestamp,
1426            AggregateFunc::MinFloat32 => mz_expr::AggregateFunc::MinFloat32,
1427            AggregateFunc::MinFloat64 => mz_expr::AggregateFunc::MinFloat64,
1428            AggregateFunc::MinBool => mz_expr::AggregateFunc::MinBool,
1429            AggregateFunc::MinString => mz_expr::AggregateFunc::MinString,
1430            AggregateFunc::MinDate => mz_expr::AggregateFunc::MinDate,
1431            AggregateFunc::MinTimestamp => mz_expr::AggregateFunc::MinTimestamp,
1432            AggregateFunc::MinTimestampTz => mz_expr::AggregateFunc::MinTimestampTz,
1433            AggregateFunc::MinInterval => mz_expr::AggregateFunc::MinInterval,
1434            AggregateFunc::MinTime => mz_expr::AggregateFunc::MinTime,
1435            AggregateFunc::MinArray => mz_expr::AggregateFunc::MinArray,
1436            AggregateFunc::MinList => mz_expr::AggregateFunc::MinList,
1437            AggregateFunc::SumInt16 => mz_expr::AggregateFunc::SumInt16,
1438            AggregateFunc::SumInt32 => mz_expr::AggregateFunc::SumInt32,
1439            AggregateFunc::SumInt64 => mz_expr::AggregateFunc::SumInt64,
1440            AggregateFunc::SumUInt16 => mz_expr::AggregateFunc::SumUInt16,
1441            AggregateFunc::SumUInt32 => mz_expr::AggregateFunc::SumUInt32,
1442            AggregateFunc::SumUInt64 => mz_expr::AggregateFunc::SumUInt64,
1443            AggregateFunc::SumFloat32 => mz_expr::AggregateFunc::SumFloat32,
1444            AggregateFunc::SumFloat64 => mz_expr::AggregateFunc::SumFloat64,
1445            AggregateFunc::SumNumeric => mz_expr::AggregateFunc::SumNumeric,
1446            AggregateFunc::SumInterval => mz_expr::AggregateFunc::SumInterval,
1447            AggregateFunc::Count => mz_expr::AggregateFunc::Count,
1448            AggregateFunc::Any => mz_expr::AggregateFunc::Any,
1449            AggregateFunc::All => mz_expr::AggregateFunc::All,
1450            AggregateFunc::JsonbAgg { order_by } => mz_expr::AggregateFunc::JsonbAgg { order_by },
1451            AggregateFunc::JsonbObjectAgg { order_by } => {
1452                mz_expr::AggregateFunc::JsonbObjectAgg { order_by }
1453            }
1454            AggregateFunc::MapAgg {
1455                order_by,
1456                value_type,
1457            } => mz_expr::AggregateFunc::MapAgg {
1458                order_by,
1459                value_type,
1460            },
1461            AggregateFunc::ArrayConcat { order_by } => {
1462                mz_expr::AggregateFunc::ArrayConcat { order_by }
1463            }
1464            AggregateFunc::ListConcat { order_by } => {
1465                mz_expr::AggregateFunc::ListConcat { order_by }
1466            }
1467            AggregateFunc::StringAgg { order_by } => mz_expr::AggregateFunc::StringAgg { order_by },
1468            // `AggregateFunc::FusedWindowAgg` should be specially handled in
1469            // `AggregateWindowExpr::into_expr`.
1470            AggregateFunc::FusedWindowAgg { funcs: _ } => {
1471                panic!("into_expr called on FusedWindowAgg")
1472            }
1473            AggregateFunc::Dummy => mz_expr::AggregateFunc::Dummy,
1474        }
1475    }
1476
1477    /// Returns a datum whose inclusion in the aggregation will not change its
1478    /// result.
1479    ///
1480    /// # Panics
1481    ///
1482    /// Panics if called on a `FusedWindowAgg`.
1483    pub fn identity_datum(&self) -> Datum<'static> {
1484        match self {
1485            AggregateFunc::Any => Datum::False,
1486            AggregateFunc::All => Datum::True,
1487            AggregateFunc::Dummy => Datum::Dummy,
1488            AggregateFunc::ArrayConcat { .. } => Datum::empty_array(),
1489            AggregateFunc::ListConcat { .. } => Datum::empty_list(),
1490            AggregateFunc::MaxNumeric
1491            | AggregateFunc::MaxInt16
1492            | AggregateFunc::MaxInt32
1493            | AggregateFunc::MaxInt64
1494            | AggregateFunc::MaxUInt16
1495            | AggregateFunc::MaxUInt32
1496            | AggregateFunc::MaxUInt64
1497            | AggregateFunc::MaxMzTimestamp
1498            | AggregateFunc::MaxFloat32
1499            | AggregateFunc::MaxFloat64
1500            | AggregateFunc::MaxBool
1501            | AggregateFunc::MaxString
1502            | AggregateFunc::MaxDate
1503            | AggregateFunc::MaxTimestamp
1504            | AggregateFunc::MaxTimestampTz
1505            | AggregateFunc::MaxInterval
1506            | AggregateFunc::MaxTime
1507            | AggregateFunc::MaxArray
1508            | AggregateFunc::MaxList
1509            | AggregateFunc::MinNumeric
1510            | AggregateFunc::MinInt16
1511            | AggregateFunc::MinInt32
1512            | AggregateFunc::MinInt64
1513            | AggregateFunc::MinUInt16
1514            | AggregateFunc::MinUInt32
1515            | AggregateFunc::MinUInt64
1516            | AggregateFunc::MinMzTimestamp
1517            | AggregateFunc::MinFloat32
1518            | AggregateFunc::MinFloat64
1519            | AggregateFunc::MinBool
1520            | AggregateFunc::MinString
1521            | AggregateFunc::MinDate
1522            | AggregateFunc::MinTimestamp
1523            | AggregateFunc::MinTimestampTz
1524            | AggregateFunc::MinInterval
1525            | AggregateFunc::MinTime
1526            | AggregateFunc::MinArray
1527            | AggregateFunc::MinList
1528            | AggregateFunc::SumInt16
1529            | AggregateFunc::SumInt32
1530            | AggregateFunc::SumInt64
1531            | AggregateFunc::SumUInt16
1532            | AggregateFunc::SumUInt32
1533            | AggregateFunc::SumUInt64
1534            | AggregateFunc::SumFloat32
1535            | AggregateFunc::SumFloat64
1536            | AggregateFunc::SumNumeric
1537            | AggregateFunc::SumInterval
1538            | AggregateFunc::Count
1539            | AggregateFunc::JsonbAgg { .. }
1540            | AggregateFunc::JsonbObjectAgg { .. }
1541            | AggregateFunc::MapAgg { .. }
1542            | AggregateFunc::StringAgg { .. } => Datum::Null,
1543            AggregateFunc::FusedWindowAgg { funcs: _ } => {
1544                // `identity_datum` is used only in HIR planning, and `FusedWindowAgg` can't occur
1545                // in HIR planning, because it is introduced only during HIR transformation.
1546                //
1547                // The implementation could be something like the following, except that we need to
1548                // return a `Datum<'static>`, so we can't actually dynamically compute this.
1549                // ```
1550                // let temp_storage = RowArena::new();
1551                // temp_storage.make_datum(|packer| packer.push_list(funcs.iter().map(|f| f.identity_datum())))
1552                // ```
1553                panic!("FusedWindowAgg doesn't have an identity_datum")
1554            }
1555        }
1556    }
1557
1558    /// The output column type for the result of an aggregation.
1559    ///
1560    /// The output column type also contains nullability information, which
1561    /// is (without further information) true for aggregations that are not
1562    /// counts.
1563    pub fn output_sql_type(&self, input_type: SqlColumnType) -> SqlColumnType {
1564        let scalar_type = match self {
1565            AggregateFunc::Count => SqlScalarType::Int64,
1566            AggregateFunc::Any => SqlScalarType::Bool,
1567            AggregateFunc::All => SqlScalarType::Bool,
1568            AggregateFunc::JsonbAgg { .. } => SqlScalarType::Jsonb,
1569            AggregateFunc::JsonbObjectAgg { .. } => SqlScalarType::Jsonb,
1570            AggregateFunc::StringAgg { .. } => SqlScalarType::String,
1571            AggregateFunc::SumInt16 | AggregateFunc::SumInt32 => SqlScalarType::Int64,
1572            AggregateFunc::SumInt64 => SqlScalarType::Numeric {
1573                max_scale: Some(NumericMaxScale::ZERO),
1574            },
1575            AggregateFunc::SumUInt16 | AggregateFunc::SumUInt32 => SqlScalarType::UInt64,
1576            AggregateFunc::SumUInt64 => SqlScalarType::Numeric {
1577                max_scale: Some(NumericMaxScale::ZERO),
1578            },
1579            AggregateFunc::MapAgg { value_type, .. } => SqlScalarType::Map {
1580                value_type: Box::new(value_type.clone()),
1581                custom_id: None,
1582            },
1583            AggregateFunc::ArrayConcat { .. } | AggregateFunc::ListConcat { .. } => {
1584                match input_type.scalar_type {
1585                    // The input is wrapped in a Record if there's an ORDER BY, so extract it out.
1586                    SqlScalarType::Record { fields, .. } => fields[0].1.scalar_type.clone(),
1587                    _ => unreachable!(),
1588                }
1589            }
1590            AggregateFunc::MaxNumeric
1591            | AggregateFunc::MaxInt16
1592            | AggregateFunc::MaxInt32
1593            | AggregateFunc::MaxInt64
1594            | AggregateFunc::MaxUInt16
1595            | AggregateFunc::MaxUInt32
1596            | AggregateFunc::MaxUInt64
1597            | AggregateFunc::MaxMzTimestamp
1598            | AggregateFunc::MaxFloat32
1599            | AggregateFunc::MaxFloat64
1600            | AggregateFunc::MaxBool
1601            | AggregateFunc::MaxString
1602            | AggregateFunc::MaxDate
1603            | AggregateFunc::MaxTimestamp
1604            | AggregateFunc::MaxTimestampTz
1605            | AggregateFunc::MaxInterval
1606            | AggregateFunc::MaxTime
1607            | AggregateFunc::MaxArray
1608            | AggregateFunc::MaxList
1609            | AggregateFunc::MinNumeric
1610            | AggregateFunc::MinInt16
1611            | AggregateFunc::MinInt32
1612            | AggregateFunc::MinInt64
1613            | AggregateFunc::MinUInt16
1614            | AggregateFunc::MinUInt32
1615            | AggregateFunc::MinUInt64
1616            | AggregateFunc::MinMzTimestamp
1617            | AggregateFunc::MinFloat32
1618            | AggregateFunc::MinFloat64
1619            | AggregateFunc::MinBool
1620            | AggregateFunc::MinString
1621            | AggregateFunc::MinDate
1622            | AggregateFunc::MinTimestamp
1623            | AggregateFunc::MinTimestampTz
1624            | AggregateFunc::MinInterval
1625            | AggregateFunc::MinTime
1626            | AggregateFunc::MinArray
1627            | AggregateFunc::MinList
1628            | AggregateFunc::SumFloat32
1629            | AggregateFunc::SumFloat64
1630            | AggregateFunc::SumNumeric
1631            | AggregateFunc::SumInterval
1632            | AggregateFunc::Dummy => input_type.scalar_type,
1633            AggregateFunc::FusedWindowAgg { funcs } => {
1634                let input_types = input_type.scalar_type.unwrap_record_element_column_type();
1635                SqlScalarType::Record {
1636                    fields: funcs
1637                        .iter()
1638                        .zip_eq(input_types)
1639                        .map(|(f, t)| (ColumnName::from(""), f.output_sql_type(t.clone())))
1640                        .collect(),
1641                    custom_id: None,
1642                }
1643            }
1644        };
1645        // max/min/sum return null on empty sets
1646        let nullable = !matches!(self, AggregateFunc::Count);
1647        scalar_type.nullable(nullable)
1648    }
1649
1650    pub fn is_order_sensitive(&self) -> bool {
1651        use AggregateFunc::*;
1652        matches!(
1653            self,
1654            JsonbAgg { .. }
1655                | JsonbObjectAgg { .. }
1656                | MapAgg { .. }
1657                | ArrayConcat { .. }
1658                | ListConcat { .. }
1659                | StringAgg { .. }
1660        )
1661    }
1662}
1663
1664impl HirRelationExpr {
1665    /// Gets the SQL type of a self-contained, top-level expression.
1666    pub fn top_level_typ(&self) -> SqlRelationType {
1667        self.typ(&[], &BTreeMap::new())
1668    }
1669
1670    /// Gets the SQL type of the expression.
1671    ///
1672    /// `outers` gives types for outer relations.
1673    /// `params` gives types for parameters.
1674    pub fn typ(
1675        &self,
1676        outers: &[SqlRelationType],
1677        params: &BTreeMap<usize, SqlScalarType>,
1678    ) -> SqlRelationType {
1679        stack::maybe_grow(|| match self {
1680            HirRelationExpr::Constant { typ, .. } => typ.clone(),
1681            HirRelationExpr::Get { typ, .. } => typ.clone(),
1682            HirRelationExpr::Let { body, .. } => body.typ(outers, params),
1683            HirRelationExpr::LetRec { body, .. } => body.typ(outers, params),
1684            HirRelationExpr::Project { input, outputs } => {
1685                let input_typ = input.typ(outers, params);
1686                SqlRelationType::new(
1687                    outputs
1688                        .iter()
1689                        .map(|&i| input_typ.column_types[i].clone())
1690                        .collect(),
1691                )
1692            }
1693            HirRelationExpr::Map { input, scalars } => {
1694                let mut typ = input.typ(outers, params);
1695                for scalar in scalars {
1696                    typ.column_types.push(scalar.typ(outers, &typ, params));
1697                }
1698                typ
1699            }
1700            HirRelationExpr::CallTable { func, exprs: _ } => func.output_sql_type(),
1701            HirRelationExpr::Filter { input, .. } | HirRelationExpr::TopK { input, .. } => {
1702                input.typ(outers, params)
1703            }
1704            HirRelationExpr::Join {
1705                left, right, kind, ..
1706            } => {
1707                let left_nullable = matches!(kind, JoinKind::RightOuter | JoinKind::FullOuter);
1708                let right_nullable =
1709                    matches!(kind, JoinKind::LeftOuter { .. } | JoinKind::FullOuter);
1710                let lt = left.typ(outers, params).column_types.into_iter().map(|t| {
1711                    let nullable = t.nullable || left_nullable;
1712                    t.nullable(nullable)
1713                });
1714                let mut outers = outers.to_vec();
1715                outers.insert(0, SqlRelationType::new(lt.clone().collect()));
1716                let rt = right
1717                    .typ(&outers, params)
1718                    .column_types
1719                    .into_iter()
1720                    .map(|t| {
1721                        let nullable = t.nullable || right_nullable;
1722                        t.nullable(nullable)
1723                    });
1724                SqlRelationType::new(lt.chain(rt).collect())
1725            }
1726            HirRelationExpr::Reduce {
1727                input,
1728                group_key,
1729                aggregates,
1730                expected_group_size: _,
1731            } => {
1732                let input_typ = input.typ(outers, params);
1733                let mut column_types = group_key
1734                    .iter()
1735                    .map(|&i| input_typ.column_types[i].clone())
1736                    .collect::<Vec<_>>();
1737                for agg in aggregates {
1738                    column_types.push(agg.typ(outers, &input_typ, params));
1739                }
1740                // TODO(frank): add primary key information.
1741                SqlRelationType::new(column_types)
1742            }
1743            // TODO(frank): check for removal; add primary key information.
1744            HirRelationExpr::Distinct { input }
1745            | HirRelationExpr::Negate { input }
1746            | HirRelationExpr::Threshold { input } => input.typ(outers, params),
1747            HirRelationExpr::Union { base, inputs } => {
1748                let mut base_cols = base.typ(outers, params).column_types;
1749                for input in inputs {
1750                    for (base_col, col) in base_cols
1751                        .iter_mut()
1752                        .zip_eq(input.typ(outers, params).column_types)
1753                    {
1754                        *base_col = base_col.sql_union(&col).unwrap(); // HIR deliberately not using `union`
1755                    }
1756                }
1757                SqlRelationType::new(base_cols)
1758            }
1759        })
1760    }
1761
1762    pub fn arity(&self) -> usize {
1763        match self {
1764            HirRelationExpr::Constant { typ, .. } => typ.column_types.len(),
1765            HirRelationExpr::Get { typ, .. } => typ.column_types.len(),
1766            HirRelationExpr::Let { body, .. } => body.arity(),
1767            HirRelationExpr::LetRec { body, .. } => body.arity(),
1768            HirRelationExpr::Project { outputs, .. } => outputs.len(),
1769            HirRelationExpr::Map { input, scalars } => input.arity() + scalars.len(),
1770            HirRelationExpr::CallTable { func, exprs: _ } => func.output_arity(),
1771            HirRelationExpr::Filter { input, .. }
1772            | HirRelationExpr::TopK { input, .. }
1773            | HirRelationExpr::Distinct { input }
1774            | HirRelationExpr::Negate { input }
1775            | HirRelationExpr::Threshold { input } => input.arity(),
1776            HirRelationExpr::Join { left, right, .. } => left.arity() + right.arity(),
1777            HirRelationExpr::Union { base, .. } => base.arity(),
1778            HirRelationExpr::Reduce {
1779                group_key,
1780                aggregates,
1781                ..
1782            } => group_key.len() + aggregates.len(),
1783        }
1784    }
1785
1786    /// The number of relation nodes in this expression.
1787    ///
1788    /// Relations reached through scalar subqueries are included. The scalar
1789    /// nodes themselves are not, so a large predicate over a small input still
1790    /// counts as small. This is a structural size for comparing two
1791    /// expressions against each other, not a cost estimate.
1792    pub fn relation_node_count(&self) -> usize {
1793        let mut count = 0;
1794        self.visit_post(&mut |_| count += 1);
1795        count
1796    }
1797
1798    /// If self is a constant, return the value and the type, otherwise `None`.
1799    pub fn as_const(&self) -> Option<(&Vec<Row>, &SqlRelationType)> {
1800        match self {
1801            Self::Constant { rows, typ } => Some((rows, typ)),
1802            _ => None,
1803        }
1804    }
1805
1806    /// Reports whether this expression contains a column reference to its
1807    /// direct parent scope.
1808    pub fn is_correlated(&self) -> bool {
1809        let mut correlated = false;
1810        #[allow(deprecated)]
1811        self.visit_columns(0, &mut |depth, col| {
1812            if col.level > depth && col.level - depth == 1 {
1813                correlated = true;
1814            }
1815        });
1816        correlated
1817    }
1818
1819    pub fn is_join_identity(&self) -> bool {
1820        match self {
1821            HirRelationExpr::Constant { rows, .. } => rows.len() == 1 && self.arity() == 0,
1822            _ => false,
1823        }
1824    }
1825
1826    pub fn project(self, outputs: Vec<usize>) -> Self {
1827        if outputs.iter().copied().eq(0..self.arity()) {
1828            // The projection is trivial. Suppress it.
1829            self
1830        } else {
1831            HirRelationExpr::Project {
1832                input: Box::new(self),
1833                outputs,
1834            }
1835        }
1836    }
1837
1838    pub fn map(mut self, scalars: Vec<HirScalarExpr>) -> Self {
1839        if scalars.is_empty() {
1840            // The map is trivial. Suppress it.
1841            self
1842        } else if let HirRelationExpr::Map {
1843            scalars: old_scalars,
1844            input: _,
1845        } = &mut self
1846        {
1847            // Map applied to a map. Fuse the maps.
1848            old_scalars.extend(scalars);
1849            self
1850        } else {
1851            HirRelationExpr::Map {
1852                input: Box::new(self),
1853                scalars,
1854            }
1855        }
1856    }
1857
1858    pub fn filter(mut self, mut preds: Vec<HirScalarExpr>) -> Self {
1859        if let HirRelationExpr::Filter {
1860            input: _,
1861            predicates,
1862        } = &mut self
1863        {
1864            predicates.extend(preds);
1865            predicates.sort();
1866            predicates.dedup();
1867            self
1868        } else {
1869            preds.sort();
1870            preds.dedup();
1871            HirRelationExpr::Filter {
1872                input: Box::new(self),
1873                predicates: preds,
1874            }
1875        }
1876    }
1877
1878    pub fn reduce(
1879        self,
1880        group_key: Vec<usize>,
1881        aggregates: Vec<AggregateExpr>,
1882        expected_group_size: Option<u64>,
1883    ) -> Self {
1884        HirRelationExpr::Reduce {
1885            input: Box::new(self),
1886            group_key,
1887            aggregates,
1888            expected_group_size,
1889        }
1890    }
1891
1892    pub fn top_k(
1893        self,
1894        group_key: Vec<usize>,
1895        order_key: Vec<ColumnOrder>,
1896        limit: Option<HirScalarExpr>,
1897        offset: HirScalarExpr,
1898        expected_group_size: Option<u64>,
1899    ) -> Self {
1900        HirRelationExpr::TopK {
1901            input: Box::new(self),
1902            group_key,
1903            order_key,
1904            limit,
1905            offset,
1906            expected_group_size,
1907        }
1908    }
1909
1910    pub fn negate(self) -> Self {
1911        if let HirRelationExpr::Negate { input } = self {
1912            *input
1913        } else {
1914            HirRelationExpr::Negate {
1915                input: Box::new(self),
1916            }
1917        }
1918    }
1919
1920    pub fn distinct(self) -> Self {
1921        if let HirRelationExpr::Distinct { .. } = self {
1922            self
1923        } else {
1924            HirRelationExpr::Distinct {
1925                input: Box::new(self),
1926            }
1927        }
1928    }
1929
1930    pub fn threshold(self) -> Self {
1931        if let HirRelationExpr::Threshold { .. } = self {
1932            self
1933        } else {
1934            HirRelationExpr::Threshold {
1935                input: Box::new(self),
1936            }
1937        }
1938    }
1939
1940    pub fn union(self, other: Self) -> Self {
1941        let mut terms = Vec::new();
1942        if let HirRelationExpr::Union { base, inputs } = self {
1943            terms.push(*base);
1944            terms.extend(inputs);
1945        } else {
1946            terms.push(self);
1947        }
1948        if let HirRelationExpr::Union { base, inputs } = other {
1949            terms.push(*base);
1950            terms.extend(inputs);
1951        } else {
1952            terms.push(other);
1953        }
1954        HirRelationExpr::Union {
1955            base: Box::new(terms.remove(0)),
1956            inputs: terms,
1957        }
1958    }
1959
1960    pub fn exists(self) -> HirScalarExpr {
1961        HirScalarExpr::Exists(Box::new(self), NameMetadata::default())
1962    }
1963
1964    pub fn select(self) -> HirScalarExpr {
1965        HirScalarExpr::Select(Box::new(self), NameMetadata::default())
1966    }
1967
1968    pub fn join(
1969        self,
1970        mut right: HirRelationExpr,
1971        on: HirScalarExpr,
1972        kind: JoinKind,
1973    ) -> HirRelationExpr {
1974        if self.is_join_identity()
1975            && !right.is_correlated()
1976            && on == HirScalarExpr::literal_true()
1977            && kind.can_elide_identity_left_join()
1978        {
1979            // The join can be elided, but we need to adjust column references
1980            // on the right-hand side to account for the removal of the scope
1981            // introduced by the join.
1982            #[allow(deprecated)]
1983            right.visit_columns_mut(0, &mut |depth, col| {
1984                if col.level > depth {
1985                    col.level -= 1;
1986                }
1987            });
1988            right
1989        } else if right.is_join_identity()
1990            && on == HirScalarExpr::literal_true()
1991            && kind.can_elide_identity_right_join()
1992        {
1993            self
1994        } else {
1995            HirRelationExpr::Join {
1996                left: Box::new(self),
1997                right: Box::new(right),
1998                on,
1999                kind,
2000            }
2001        }
2002    }
2003
2004    pub fn take(&mut self) -> HirRelationExpr {
2005        mem::replace(
2006            self,
2007            HirRelationExpr::constant(vec![], SqlRelationType::new(Vec::new())),
2008        )
2009    }
2010
2011    #[deprecated = "Use `Visit::visit_post`."]
2012    pub fn visit<'a, F>(&'a self, depth: usize, f: &mut F)
2013    where
2014        F: FnMut(&'a Self, usize),
2015    {
2016        #[allow(deprecated)]
2017        let _ = self.visit_fallible(depth, &mut |e: &HirRelationExpr,
2018                                                 depth: usize|
2019         -> Result<(), ()> {
2020            f(e, depth);
2021            Ok(())
2022        });
2023    }
2024
2025    #[deprecated = "Use `Visit::try_visit_post`."]
2026    pub fn visit_fallible<'a, F, E>(&'a self, depth: usize, f: &mut F) -> Result<(), E>
2027    where
2028        F: FnMut(&'a Self, usize) -> Result<(), E>,
2029    {
2030        #[allow(deprecated)]
2031        // Grow the stack: this recurses over the relation tree, whose depth is
2032        // user-controlled (e.g. a long JOIN chain or a chain of CTEs).
2033        stack::maybe_grow(|| {
2034            self.visit1(depth, |e: &HirRelationExpr, depth: usize| {
2035                e.visit_fallible(depth, f)
2036            })
2037        })?;
2038        f(self, depth)
2039    }
2040
2041    /// WARNING: `VisitChildren<HirRelationExpr>::try_visit_children` is NOT a
2042    /// drop-in replacement: in addition to the relation children visited here,
2043    /// it also descends into every subquery (`Exists`/`Select`) reachable
2044    /// through `self`'s scalar children — at any depth of scalar nesting.
2045    #[deprecated = "Use `VisitChildren<HirRelationExpr>::try_visit_children` instead."]
2046    pub fn visit1<'a, F, E>(&'a self, depth: usize, mut f: F) -> Result<(), E>
2047    where
2048        F: FnMut(&'a Self, usize) -> Result<(), E>,
2049    {
2050        match self {
2051            HirRelationExpr::Constant { .. }
2052            | HirRelationExpr::Get { .. }
2053            | HirRelationExpr::CallTable { .. } => (),
2054            HirRelationExpr::Let { body, value, .. } => {
2055                f(value, depth)?;
2056                f(body, depth)?;
2057            }
2058            HirRelationExpr::LetRec {
2059                limit: _,
2060                bindings,
2061                body,
2062            } => {
2063                for (_, _, value, _) in bindings.iter() {
2064                    f(value, depth)?;
2065                }
2066                f(body, depth)?;
2067            }
2068            HirRelationExpr::Project { input, .. } => {
2069                f(input, depth)?;
2070            }
2071            HirRelationExpr::Map { input, .. } => {
2072                f(input, depth)?;
2073            }
2074            HirRelationExpr::Filter { input, .. } => {
2075                f(input, depth)?;
2076            }
2077            HirRelationExpr::Join { left, right, .. } => {
2078                f(left, depth)?;
2079                f(right, depth + 1)?;
2080            }
2081            HirRelationExpr::Reduce { input, .. } => {
2082                f(input, depth)?;
2083            }
2084            HirRelationExpr::Distinct { input } => {
2085                f(input, depth)?;
2086            }
2087            HirRelationExpr::TopK { input, .. } => {
2088                f(input, depth)?;
2089            }
2090            HirRelationExpr::Negate { input } => {
2091                f(input, depth)?;
2092            }
2093            HirRelationExpr::Threshold { input } => {
2094                f(input, depth)?;
2095            }
2096            HirRelationExpr::Union { base, inputs } => {
2097                f(base, depth)?;
2098                for input in inputs {
2099                    f(input, depth)?;
2100                }
2101            }
2102        }
2103        Ok(())
2104    }
2105
2106    #[deprecated = "Use `Visit::visit_mut_post` instead."]
2107    pub fn visit_mut<F>(&mut self, depth: usize, f: &mut F)
2108    where
2109        F: FnMut(&mut Self, usize),
2110    {
2111        #[allow(deprecated)]
2112        let _ = self.visit_mut_fallible(depth, &mut |e: &mut HirRelationExpr,
2113                                                     depth: usize|
2114         -> Result<(), ()> {
2115            f(e, depth);
2116            Ok(())
2117        });
2118    }
2119
2120    #[deprecated = "Use `Visit::try_visit_mut_post` instead."]
2121    pub fn visit_mut_fallible<F, E>(&mut self, depth: usize, f: &mut F) -> Result<(), E>
2122    where
2123        F: FnMut(&mut Self, usize) -> Result<(), E>,
2124    {
2125        #[allow(deprecated)]
2126        // Grow the stack: this recurses over the relation tree, whose depth is
2127        // user-controlled (e.g. a long JOIN chain or a chain of CTEs).
2128        stack::maybe_grow(|| {
2129            self.visit1_mut(depth, |e: &mut HirRelationExpr, depth: usize| {
2130                e.visit_mut_fallible(depth, f)
2131            })
2132        })?;
2133        f(self, depth)
2134    }
2135
2136    /// WARNING: `VisitChildren<HirRelationExpr>::try_visit_mut_children` is NOT a
2137    /// drop-in replacement: in addition to the relation children visited here,
2138    /// it also descends into every subquery (`Exists`/`Select`) reachable
2139    /// through `self`'s scalar children — at any depth of scalar nesting.
2140    #[deprecated = "Use `VisitChildren<HirRelationExpr>::try_visit_mut_children` instead."]
2141    pub fn visit1_mut<'a, F, E>(&'a mut self, depth: usize, mut f: F) -> Result<(), E>
2142    where
2143        F: FnMut(&'a mut Self, usize) -> Result<(), E>,
2144    {
2145        match self {
2146            HirRelationExpr::Constant { .. }
2147            | HirRelationExpr::Get { .. }
2148            | HirRelationExpr::CallTable { .. } => (),
2149            HirRelationExpr::Let { body, value, .. } => {
2150                f(value, depth)?;
2151                f(body, depth)?;
2152            }
2153            HirRelationExpr::LetRec {
2154                limit: _,
2155                bindings,
2156                body,
2157            } => {
2158                for (_, _, value, _) in bindings.iter_mut() {
2159                    f(value, depth)?;
2160                }
2161                f(body, depth)?;
2162            }
2163            HirRelationExpr::Project { input, .. } => {
2164                f(input, depth)?;
2165            }
2166            HirRelationExpr::Map { input, .. } => {
2167                f(input, depth)?;
2168            }
2169            HirRelationExpr::Filter { input, .. } => {
2170                f(input, depth)?;
2171            }
2172            HirRelationExpr::Join { left, right, .. } => {
2173                f(left, depth)?;
2174                f(right, depth + 1)?;
2175            }
2176            HirRelationExpr::Reduce { input, .. } => {
2177                f(input, depth)?;
2178            }
2179            HirRelationExpr::Distinct { input } => {
2180                f(input, depth)?;
2181            }
2182            HirRelationExpr::TopK { input, .. } => {
2183                f(input, depth)?;
2184            }
2185            HirRelationExpr::Negate { input } => {
2186                f(input, depth)?;
2187            }
2188            HirRelationExpr::Threshold { input } => {
2189                f(input, depth)?;
2190            }
2191            HirRelationExpr::Union { base, inputs } => {
2192                f(base, depth)?;
2193                for input in inputs {
2194                    f(input, depth)?;
2195                }
2196            }
2197        }
2198        Ok(())
2199    }
2200
2201    #[deprecated = "Use a combination of `Visit` and `VisitChildren` methods."]
2202    /// Visits all scalar expressions directly held by relation nodes within the sub-tree of `self`.
2203    ///
2204    /// Note: this does NOT descend into subqueries that may appear inside the visited
2205    /// `HirScalarExpr`s (i.e., `HirScalarExpr::Exists` / `HirScalarExpr::Select`). The closure
2206    /// `f` is invoked once per top-level scalar expression attached to a relation node, and it
2207    /// is the closure's responsibility to recurse into any subqueries if desired.
2208    ///
2209    /// The `depth` argument is just a seed: it is the value passed to `f` for scalar expressions
2210    /// at the root of `self`, and it is incremented by 1 when descending into the RHS of a
2211    /// `Join` node (the only place this function increments it). It does NOT control or limit
2212    /// recursion; passing `0` is the usual choice.
2213    pub fn visit_scalar_expressions<F, E>(&self, depth: usize, f: &mut F) -> Result<(), E>
2214    where
2215        F: FnMut(&HirScalarExpr, usize) -> Result<(), E>,
2216    {
2217        #[allow(deprecated)]
2218        self.visit_fallible(depth, &mut |e: &HirRelationExpr,
2219                                         depth: usize|
2220         -> Result<(), E> {
2221            match e {
2222                HirRelationExpr::Join { on, .. } => {
2223                    f(on, depth)?;
2224                }
2225                HirRelationExpr::Map { scalars, .. } => {
2226                    for scalar in scalars {
2227                        f(scalar, depth)?;
2228                    }
2229                }
2230                HirRelationExpr::CallTable { exprs, .. } => {
2231                    for expr in exprs {
2232                        f(expr, depth)?;
2233                    }
2234                }
2235                HirRelationExpr::Filter { predicates, .. } => {
2236                    for predicate in predicates {
2237                        f(predicate, depth)?;
2238                    }
2239                }
2240                HirRelationExpr::Reduce { aggregates, .. } => {
2241                    for aggregate in aggregates {
2242                        f(&aggregate.expr, depth)?;
2243                    }
2244                }
2245                HirRelationExpr::TopK { limit, offset, .. } => {
2246                    if let Some(limit) = limit {
2247                        f(limit, depth)?;
2248                    }
2249                    f(offset, depth)?;
2250                }
2251                HirRelationExpr::Union { .. }
2252                | HirRelationExpr::Let { .. }
2253                | HirRelationExpr::LetRec { .. }
2254                | HirRelationExpr::Project { .. }
2255                | HirRelationExpr::Distinct { .. }
2256                | HirRelationExpr::Negate { .. }
2257                | HirRelationExpr::Threshold { .. }
2258                | HirRelationExpr::Constant { .. }
2259                | HirRelationExpr::Get { .. } => (),
2260            }
2261            Ok(())
2262        })
2263    }
2264
2265    #[deprecated = "Use a combination of `Visit` and `VisitChildren` methods."]
2266    /// Like `visit_scalar_expressions`, but permits mutating the expressions.
2267    ///
2268    /// In particular, this also does NOT descend into subqueries inside the visited scalar
2269    /// expressions, and `depth` is just a seed for the value passed to `f` (see
2270    /// [`HirRelationExpr::visit_scalar_expressions`]).
2271    pub fn visit_scalar_expressions_mut<F, E>(&mut self, depth: usize, f: &mut F) -> Result<(), E>
2272    where
2273        F: FnMut(&mut HirScalarExpr, usize) -> Result<(), E>,
2274    {
2275        #[allow(deprecated)]
2276        self.visit_mut_fallible(depth, &mut |e: &mut HirRelationExpr,
2277                                             depth: usize|
2278         -> Result<(), E> {
2279            match e {
2280                HirRelationExpr::Join { on, .. } => {
2281                    f(on, depth)?;
2282                }
2283                HirRelationExpr::Map { scalars, .. } => {
2284                    for scalar in scalars.iter_mut() {
2285                        f(scalar, depth)?;
2286                    }
2287                }
2288                HirRelationExpr::CallTable { exprs, .. } => {
2289                    for expr in exprs.iter_mut() {
2290                        f(expr, depth)?;
2291                    }
2292                }
2293                HirRelationExpr::Filter { predicates, .. } => {
2294                    for predicate in predicates.iter_mut() {
2295                        f(predicate, depth)?;
2296                    }
2297                }
2298                HirRelationExpr::Reduce { aggregates, .. } => {
2299                    for aggregate in aggregates.iter_mut() {
2300                        f(&mut aggregate.expr, depth)?;
2301                    }
2302                }
2303                HirRelationExpr::TopK { limit, offset, .. } => {
2304                    if let Some(limit) = limit {
2305                        f(limit, depth)?;
2306                    }
2307                    f(offset, depth)?;
2308                }
2309                HirRelationExpr::Union { .. }
2310                | HirRelationExpr::Let { .. }
2311                | HirRelationExpr::LetRec { .. }
2312                | HirRelationExpr::Project { .. }
2313                | HirRelationExpr::Distinct { .. }
2314                | HirRelationExpr::Negate { .. }
2315                | HirRelationExpr::Threshold { .. }
2316                | HirRelationExpr::Constant { .. }
2317                | HirRelationExpr::Get { .. } => (),
2318            }
2319            Ok(())
2320        })
2321    }
2322
2323    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
2324    /// Visits the column references in this relation expression.
2325    ///
2326    /// The `depth` argument should indicate the subquery nesting depth of the expression,
2327    /// which will be incremented when entering the RHS of a join or a subquery and
2328    /// presented to the supplied function `f`.
2329    pub fn visit_columns<F>(&self, depth: usize, f: &mut F)
2330    where
2331        F: FnMut(usize, &ColumnRef),
2332    {
2333        #[allow(deprecated)]
2334        let _ = self.visit_scalar_expressions(depth, &mut |e: &HirScalarExpr,
2335                                                           depth: usize|
2336         -> Result<(), ()> {
2337            e.visit_columns(depth, f);
2338            Ok(())
2339        });
2340    }
2341
2342    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
2343    /// Like `visit_columns`, but permits mutating the column references.
2344    pub fn visit_columns_mut<F>(&mut self, depth: usize, f: &mut F)
2345    where
2346        F: FnMut(usize, &mut ColumnRef),
2347    {
2348        #[allow(deprecated)]
2349        let _ = self.visit_scalar_expressions_mut(depth, &mut |e: &mut HirScalarExpr,
2350                                                               depth: usize|
2351         -> Result<(), ()> {
2352            e.visit_columns_mut(depth, f);
2353            Ok(())
2354        });
2355    }
2356
2357    /// Replaces parameter references in the expression with the corresponding datum from `params`.
2358    /// Additionally, it simplifies OFFSET clauses to constants after parameter binding, and checks
2359    /// them for non-negativity.
2360    ///
2361    /// This walks the entire `HirRelationExpr` tree, including subqueries nested inside scalar
2362    /// expressions: `visit_scalar_expressions_mut` covers the scalar expressions held directly
2363    /// by relation nodes, and the corecursive call into
2364    /// [`HirScalarExpr::bind_parameters_and_simplify_offset`] (made by the closure below) is
2365    /// what descends into subqueries occurring inside those scalar expressions.
2366    pub fn bind_parameters_and_simplify_offset(
2367        &mut self,
2368        scx: &StatementContext,
2369        lifetime: QueryLifetime,
2370        params: &Params,
2371    ) -> Result<(), PlanError> {
2372        #[allow(deprecated)]
2373        self.visit_scalar_expressions_mut(0, &mut |e: &mut HirScalarExpr, _: usize| {
2374            e.bind_parameters_and_simplify_offset(scx, lifetime, params)
2375        })?;
2376
2377        // OFFSET clauses in `expr` should become constants with the above binding of parameters.
2378        // Let's check this and simplify them to literals.
2379        self.try_visit_mut_pre(&mut |expr| {
2380            if let HirRelationExpr::TopK { offset, .. } = expr {
2381                let offset_value = offset_into_value(offset.take())?;
2382                *offset = HirScalarExpr::literal(Datum::Int64(offset_value), SqlScalarType::Int64);
2383            }
2384            Ok::<(), PlanError>(())
2385        })
2386        // (We don't need to simplify LIMIT clauses in `expr`, because we can handle non-constant
2387        // expressions there. If they happen to be simplifiable to literals, then the optimizer will do
2388        // so later.)
2389    }
2390
2391    pub fn contains_parameters(&self) -> Result<bool, PlanError> {
2392        let mut contains_parameters = false;
2393        #[allow(deprecated)]
2394        self.visit_scalar_expressions(0, &mut |e: &HirScalarExpr, _: usize| {
2395            if e.contains_parameters() {
2396                contains_parameters = true;
2397            }
2398            Ok::<(), PlanError>(())
2399        })?;
2400        Ok(contains_parameters)
2401    }
2402
2403    /// See the documentation for [`HirScalarExpr::splice_parameters`].
2404    pub fn splice_parameters(&mut self, params: &[HirScalarExpr], depth: usize) {
2405        #[allow(deprecated)]
2406        let _ = self.visit_scalar_expressions_mut(depth, &mut |e: &mut HirScalarExpr,
2407                                                               depth: usize|
2408         -> Result<(), ()> {
2409            e.splice_parameters(params, depth);
2410            Ok(())
2411        });
2412    }
2413
2414    /// Constructs a constant collection from specific rows and schema.
2415    pub fn constant(rows: Vec<Vec<Datum>>, typ: SqlRelationType) -> Self {
2416        let rows = rows
2417            .into_iter()
2418            .map(move |datums| Row::pack_slice(&datums))
2419            .collect();
2420        HirRelationExpr::Constant { rows, typ }
2421    }
2422
2423    /// A `RowSetFinishing` can only be directly applied to the result of a one-shot select.
2424    /// This function is concerned with maintained queries, e.g., an index or materialized view.
2425    /// Instead of directly applying the given `RowSetFinishing`, it converts the `RowSetFinishing`
2426    /// to a `TopK`, which it then places at the top of `self`. Additionally, it turns the given
2427    /// finishing into a trivial finishing.
2428    pub fn finish_maintained(
2429        &mut self,
2430        finishing: &mut RowSetFinishing<HirScalarExpr, HirScalarExpr>,
2431        group_size_hints: GroupSizeHints,
2432    ) {
2433        if !HirRelationExpr::is_trivial_row_set_finishing_hir(finishing, self.arity()) {
2434            let old_finishing = mem::replace(
2435                finishing,
2436                HirRelationExpr::trivial_row_set_finishing_hir(finishing.project.len()),
2437            );
2438            *self = HirRelationExpr::top_k(
2439                std::mem::replace(
2440                    self,
2441                    HirRelationExpr::Constant {
2442                        rows: vec![],
2443                        typ: SqlRelationType::new(Vec::new()),
2444                    },
2445                ),
2446                vec![],
2447                old_finishing.order_by,
2448                old_finishing.limit,
2449                old_finishing.offset,
2450                group_size_hints.limit_input_group_size,
2451            )
2452            .project(old_finishing.project);
2453        }
2454    }
2455
2456    /// Returns a trivial finishing, i.e., that does nothing to the result set.
2457    ///
2458    /// (There is also `RowSetFinishing::trivial`, but that is specialized for when the O generic
2459    /// parameter is not an HirScalarExpr anymore.)
2460    pub fn trivial_row_set_finishing_hir(
2461        arity: usize,
2462    ) -> RowSetFinishing<HirScalarExpr, HirScalarExpr> {
2463        RowSetFinishing {
2464            order_by: Vec::new(),
2465            limit: None,
2466            offset: HirScalarExpr::literal(Datum::Int64(0), SqlScalarType::Int64),
2467            project: (0..arity).collect(),
2468        }
2469    }
2470
2471    /// True if the finishing does nothing to any result set.
2472    ///
2473    /// (There is also `RowSetFinishing::is_trivial`, but that is specialized for when the O generic
2474    /// parameter is not an HirScalarExpr anymore.)
2475    pub fn is_trivial_row_set_finishing_hir(
2476        rsf: &RowSetFinishing<HirScalarExpr, HirScalarExpr>,
2477        arity: usize,
2478    ) -> bool {
2479        rsf.limit.is_none()
2480            && rsf.order_by.is_empty()
2481            && rsf
2482                .offset
2483                .clone()
2484                .try_into_literal_int64()
2485                .is_ok_and(|o| o == 0)
2486            && rsf.project.iter().copied().eq(0..arity)
2487    }
2488
2489    /// The HirRelationExpr is considered potentially expensive if and only if
2490    /// at least one of the following conditions is true:
2491    ///
2492    ///  - It contains at least one HirScalarExpr with a function call.
2493    ///  - It contains at least one CallTable or a Reduce operator.
2494    ///  - We run into a RecursionLimitError while analyzing the expression.
2495    ///
2496    /// !!!WARNING!!!: this method has an MirRelationExpr counterpart. The two
2497    /// should be kept in sync w.r.t. HIR ⇒ MIR lowering!
2498    pub fn could_run_expensive_function(&self) -> bool {
2499        let mut result = false;
2500        self.visit_pre(&mut |e: &HirRelationExpr| {
2501            use HirRelationExpr::*;
2502            use HirScalarExpr::*;
2503
2504            e.visit_children(|scalar: &HirScalarExpr| {
2505                scalar.visit_pre(&mut |scalar: &HirScalarExpr| {
2506                    result |= match scalar {
2507                        Column(..)
2508                        | Literal(..)
2509                        | CallUnmaterializable(..)
2510                        | If { .. }
2511                        | Parameter(..)
2512                        | Select(..)
2513                        | Exists(..) => false,
2514                        // Function calls are considered expensive
2515                        CallUnary { .. }
2516                        | CallBinary { .. }
2517                        | CallVariadic { .. }
2518                        | Windowing(..) => true,
2519                    };
2520                })
2521            });
2522
2523            // CallTable has a table function; Reduce has an aggregate function.
2524            // Other constructs use MirScalarExpr to run a function
2525            result |= matches!(e, CallTable { .. } | Reduce { .. });
2526        });
2527
2528        result
2529    }
2530
2531    /// Whether the expression contains an [`UnmaterializableFunc::MzNow`] call.
2532    pub fn contains_temporal(&self) -> bool {
2533        let mut contains = false;
2534        self.visit_post(&mut |expr| {
2535            expr.visit_children(|expr: &HirScalarExpr| {
2536                contains = contains || expr.contains_temporal()
2537            })
2538        });
2539        contains
2540    }
2541
2542    /// Whether the expression contains any [`UnmaterializableFunc`] call.
2543    pub fn contains_unmaterializable(&self) -> bool {
2544        let mut contains = false;
2545        self.visit_post(&mut |expr| {
2546            expr.visit_children(|expr: &HirScalarExpr| {
2547                contains = contains || expr.contains_unmaterializable()
2548            })
2549        });
2550        contains
2551    }
2552
2553    /// Whether the expression contains any [`UnmaterializableFunc`] call other than
2554    /// [`UnmaterializableFunc::MzNow`].
2555    pub fn contains_unmaterializable_except_temporal(&self) -> bool {
2556        let mut contains = false;
2557        self.visit_post(&mut |expr| {
2558            expr.visit_children(|expr: &HirScalarExpr| {
2559                contains = contains || expr.contains_unmaterializable_except_temporal()
2560            })
2561        });
2562        contains
2563    }
2564}
2565
2566impl CollectionPlan for HirRelationExpr {
2567    /// Collects the global collections that this HIR expression directly depends on, i.e., that it
2568    /// has a `Get` for. (It does _not_ traverse view definitions transitively.)
2569    /// (It does explore inside subqueries.)
2570    ///
2571    /// !!!WARNING!!!: this method has an MirRelationExpr counterpart. The two
2572    /// should be kept in sync w.r.t. HIR ⇒ MIR lowering!
2573    fn depends_on_into(&self, out: &mut BTreeSet<GlobalId>) {
2574        if let Self::Get {
2575            id: Id::Global(id), ..
2576        } = self
2577        {
2578            out.insert(*id);
2579        }
2580        self.visit_children(|expr: &HirRelationExpr| expr.depends_on_into(out))
2581    }
2582}
2583
2584/// In addition to direct relation children of `self`, this also yields every
2585/// subquery (`Exists` / `Select`) reachable through `self`'s scalar children,
2586/// at any depth of scalar nesting. This is the asymmetry warned about on the
2587/// [`VisitChildren`] trait; the matching impl on `HirScalarExpr` deliberately
2588/// does not do the symmetric thing, to avoid mutual recursion.
2589impl VisitChildren<Self> for HirRelationExpr {
2590    fn visit_children<F>(&self, mut f: F)
2591    where
2592        F: FnMut(&Self),
2593    {
2594        // subqueries of type HirRelationExpr might be wrapped in
2595        // Exists or Select variants within HirScalarExpr trees
2596        // attached at the current node, and we want to visit them as well
2597        VisitChildren::visit_children(self, |expr: &HirScalarExpr| {
2598            expr.visit_direct_subqueries(&mut f);
2599        });
2600
2601        use HirRelationExpr::*;
2602        match self {
2603            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2604            Let {
2605                name: _,
2606                id: _,
2607                value,
2608                body,
2609            } => {
2610                f(value);
2611                f(body);
2612            }
2613            LetRec {
2614                limit: _,
2615                bindings,
2616                body,
2617            } => {
2618                for (_, _, value, _) in bindings.iter() {
2619                    f(value);
2620                }
2621                f(body);
2622            }
2623            Project { input, outputs: _ } => f(input),
2624            Map { input, scalars: _ } => {
2625                f(input);
2626            }
2627            CallTable { func: _, exprs: _ } => (),
2628            Filter {
2629                input,
2630                predicates: _,
2631            } => {
2632                f(input);
2633            }
2634            Join {
2635                left,
2636                right,
2637                on: _,
2638                kind: _,
2639            } => {
2640                f(left);
2641                f(right);
2642            }
2643            Reduce {
2644                input,
2645                group_key: _,
2646                aggregates: _,
2647                expected_group_size: _,
2648            } => {
2649                f(input);
2650            }
2651            Distinct { input }
2652            | TopK {
2653                input,
2654                group_key: _,
2655                order_key: _,
2656                limit: _,
2657                offset: _,
2658                expected_group_size: _,
2659            }
2660            | Negate { input }
2661            | Threshold { input } => {
2662                f(input);
2663            }
2664            Union { base, inputs } => {
2665                f(base);
2666                for input in inputs {
2667                    f(input);
2668                }
2669            }
2670        }
2671    }
2672
2673    fn visit_mut_children<F>(&mut self, mut f: F)
2674    where
2675        F: FnMut(&mut Self),
2676    {
2677        // subqueries of type HirRelationExpr might be wrapped in
2678        // Exists or Select variants within HirScalarExpr trees
2679        // attached at the current node, and we want to visit them as well
2680        VisitChildren::visit_mut_children(self, |expr: &mut HirScalarExpr| {
2681            expr.visit_direct_subqueries_mut(&mut f);
2682        });
2683
2684        use HirRelationExpr::*;
2685        match self {
2686            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2687            Let {
2688                name: _,
2689                id: _,
2690                value,
2691                body,
2692            } => {
2693                f(value);
2694                f(body);
2695            }
2696            LetRec {
2697                limit: _,
2698                bindings,
2699                body,
2700            } => {
2701                for (_, _, value, _) in bindings.iter_mut() {
2702                    f(value);
2703                }
2704                f(body);
2705            }
2706            Project { input, outputs: _ } => f(input),
2707            Map { input, scalars: _ } => {
2708                f(input);
2709            }
2710            CallTable { func: _, exprs: _ } => (),
2711            Filter {
2712                input,
2713                predicates: _,
2714            } => {
2715                f(input);
2716            }
2717            Join {
2718                left,
2719                right,
2720                on: _,
2721                kind: _,
2722            } => {
2723                f(left);
2724                f(right);
2725            }
2726            Reduce {
2727                input,
2728                group_key: _,
2729                aggregates: _,
2730                expected_group_size: _,
2731            } => {
2732                f(input);
2733            }
2734            Distinct { input }
2735            | TopK {
2736                input,
2737                group_key: _,
2738                order_key: _,
2739                limit: _,
2740                offset: _,
2741                expected_group_size: _,
2742            }
2743            | Negate { input }
2744            | Threshold { input } => {
2745                f(input);
2746            }
2747            Union { base, inputs } => {
2748                f(base);
2749                for input in inputs {
2750                    f(input);
2751                }
2752            }
2753        }
2754    }
2755
2756    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
2757    where
2758        F: FnMut(&Self) -> Result<(), E>,
2759    {
2760        // subqueries of type HirRelationExpr might be wrapped in
2761        // Exists or Select variants within HirScalarExpr trees
2762        // attached at the current node, and we want to visit them as well
2763        VisitChildren::try_visit_children(self, |expr: &HirScalarExpr| {
2764            expr.try_visit_direct_subqueries(&mut f)
2765        })?;
2766
2767        use HirRelationExpr::*;
2768        match self {
2769            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2770            Let {
2771                name: _,
2772                id: _,
2773                value,
2774                body,
2775            } => {
2776                f(value)?;
2777                f(body)?;
2778            }
2779            LetRec {
2780                limit: _,
2781                bindings,
2782                body,
2783            } => {
2784                for (_, _, value, _) in bindings.iter() {
2785                    f(value)?;
2786                }
2787                f(body)?;
2788            }
2789            Project { input, outputs: _ } => f(input)?,
2790            Map { input, scalars: _ } => {
2791                f(input)?;
2792            }
2793            CallTable { func: _, exprs: _ } => (),
2794            Filter {
2795                input,
2796                predicates: _,
2797            } => {
2798                f(input)?;
2799            }
2800            Join {
2801                left,
2802                right,
2803                on: _,
2804                kind: _,
2805            } => {
2806                f(left)?;
2807                f(right)?;
2808            }
2809            Reduce {
2810                input,
2811                group_key: _,
2812                aggregates: _,
2813                expected_group_size: _,
2814            } => {
2815                f(input)?;
2816            }
2817            Distinct { input }
2818            | TopK {
2819                input,
2820                group_key: _,
2821                order_key: _,
2822                limit: _,
2823                offset: _,
2824                expected_group_size: _,
2825            }
2826            | Negate { input }
2827            | Threshold { input } => {
2828                f(input)?;
2829            }
2830            Union { base, inputs } => {
2831                f(base)?;
2832                for input in inputs {
2833                    f(input)?;
2834                }
2835            }
2836        }
2837        Ok(())
2838    }
2839
2840    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
2841    where
2842        F: FnMut(&mut Self) -> Result<(), E>,
2843    {
2844        // subqueries of type HirRelationExpr might be wrapped in
2845        // Exists or Select variants within HirScalarExpr trees
2846        // attached at the current node, and we want to visit them as well
2847        VisitChildren::try_visit_mut_children(self, |expr: &mut HirScalarExpr| {
2848            expr.try_visit_direct_subqueries_mut(&mut f)
2849        })?;
2850
2851        use HirRelationExpr::*;
2852        match self {
2853            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2854            Let {
2855                name: _,
2856                id: _,
2857                value,
2858                body,
2859            } => {
2860                f(value)?;
2861                f(body)?;
2862            }
2863            LetRec {
2864                limit: _,
2865                bindings,
2866                body,
2867            } => {
2868                for (_, _, value, _) in bindings.iter_mut() {
2869                    f(value)?;
2870                }
2871                f(body)?;
2872            }
2873            Project { input, outputs: _ } => f(input)?,
2874            Map { input, scalars: _ } => {
2875                f(input)?;
2876            }
2877            CallTable { func: _, exprs: _ } => (),
2878            Filter {
2879                input,
2880                predicates: _,
2881            } => {
2882                f(input)?;
2883            }
2884            Join {
2885                left,
2886                right,
2887                on: _,
2888                kind: _,
2889            } => {
2890                f(left)?;
2891                f(right)?;
2892            }
2893            Reduce {
2894                input,
2895                group_key: _,
2896                aggregates: _,
2897                expected_group_size: _,
2898            } => {
2899                f(input)?;
2900            }
2901            Distinct { input }
2902            | TopK {
2903                input,
2904                group_key: _,
2905                order_key: _,
2906                limit: _,
2907                offset: _,
2908                expected_group_size: _,
2909            }
2910            | Negate { input }
2911            | Threshold { input } => {
2912                f(input)?;
2913            }
2914            Union { base, inputs } => {
2915                f(base)?;
2916                for input in inputs {
2917                    f(input)?;
2918                }
2919            }
2920        }
2921        Ok(())
2922    }
2923
2924    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a Self>
2925    where
2926        Self: 'a,
2927    {
2928        // we visit subqueries _first_, then the input
2929        let mut v: Vec<&HirRelationExpr> = vec![];
2930        use HirRelationExpr::*;
2931        match self {
2932            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2933            Let {
2934                name: _,
2935                id: _,
2936                value,
2937                body,
2938            } => {
2939                v.push(&*value);
2940                v.push(&*body);
2941            }
2942            LetRec {
2943                limit: _,
2944                bindings,
2945                body,
2946            } => {
2947                v.extend(bindings.iter().map(|(_, _, value, _)| value));
2948                v.push(&*body);
2949            }
2950            Map { input, scalars }
2951            | Filter {
2952                input,
2953                predicates: scalars,
2954            } => {
2955                for scalar in scalars {
2956                    v.append(&mut scalar.direct_subqueries());
2957                }
2958                v.push(&*input);
2959            }
2960            Reduce {
2961                input,
2962                group_key: _,
2963                aggregates,
2964                expected_group_size: _,
2965            } => {
2966                for agg in aggregates {
2967                    v.append(&mut agg.expr.direct_subqueries());
2968                }
2969                v.push(&*input);
2970            }
2971            TopK {
2972                input,
2973                group_key: _,
2974                order_key: _,
2975                limit,
2976                offset,
2977                expected_group_size: _,
2978            } => {
2979                if let Some(limit) = limit {
2980                    v.append(&mut limit.direct_subqueries());
2981                }
2982                v.append(&mut offset.direct_subqueries());
2983                v.push(&*input);
2984            }
2985            Project { input, outputs: _ }
2986            | Distinct { input }
2987            | Negate { input }
2988            | Threshold { input } => v.push(&*input),
2989            CallTable { func: _, exprs } => v.extend(
2990                exprs
2991                    .iter()
2992                    .map(|scalar| scalar.direct_subqueries())
2993                    .flatten(),
2994            ),
2995            Join {
2996                left,
2997                right,
2998                on,
2999                kind: _,
3000            } => {
3001                v.append(&mut on.direct_subqueries());
3002                v.push(&*left);
3003                v.push(&*right);
3004            }
3005            Union { base, inputs } => {
3006                v.push(&*base);
3007                v.extend(inputs.iter());
3008            }
3009        }
3010
3011        v.into_iter()
3012    }
3013
3014    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut Self>
3015    where
3016        Self: 'a,
3017    {
3018        // we visit subqueries _first_, then the input
3019        let mut v = vec![];
3020        use HirRelationExpr::*;
3021        match self {
3022            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
3023            Let {
3024                name: _,
3025                id: _,
3026                value,
3027                body,
3028            } => {
3029                v.push(&mut **value);
3030                v.push(&mut **body);
3031            }
3032            LetRec {
3033                limit: _,
3034                bindings,
3035                body,
3036            } => {
3037                v.extend(bindings.iter_mut().map(|(_, _, value, _)| value));
3038                v.push(&mut **body);
3039            }
3040            Map { input, scalars }
3041            | Filter {
3042                input,
3043                predicates: scalars,
3044            } => {
3045                for scalar in scalars {
3046                    v.append(&mut scalar.direct_subqueries_mut());
3047                }
3048                v.push(&mut **input);
3049            }
3050            Reduce {
3051                input,
3052                group_key: _,
3053                aggregates,
3054                expected_group_size: _,
3055            } => {
3056                for agg in aggregates {
3057                    v.append(&mut agg.expr.direct_subqueries_mut());
3058                }
3059                v.push(&mut **input);
3060            }
3061            TopK {
3062                input,
3063                group_key: _,
3064                order_key: _,
3065                limit,
3066                offset,
3067                expected_group_size: _,
3068            } => {
3069                if let Some(limit) = limit {
3070                    v.append(&mut limit.direct_subqueries_mut());
3071                }
3072                v.append(&mut offset.direct_subqueries_mut());
3073                v.push(&mut **input);
3074            }
3075            Project { input, outputs: _ }
3076            | Distinct { input }
3077            | Negate { input }
3078            | Threshold { input } => v.push(&mut **input),
3079            CallTable { func: _, exprs } => v.extend(
3080                exprs
3081                    .iter_mut()
3082                    .map(|scalar| scalar.direct_subqueries_mut())
3083                    .flatten(),
3084            ),
3085            Join {
3086                left,
3087                right,
3088                on,
3089                kind: _,
3090            } => {
3091                v.append(&mut on.direct_subqueries_mut());
3092                v.push(&mut **left);
3093                v.push(&mut **right);
3094            }
3095            Union { base, inputs } => {
3096                v.push(&mut **base);
3097                v.extend(inputs.iter_mut());
3098            }
3099        }
3100
3101        v.into_iter()
3102    }
3103}
3104
3105/// Yields the scalars directly attached to relation nodes (e.g. `Map.scalars`,
3106/// `Filter.predicates`, `Join.on`, `Reduce` aggregate args, `TopK.{limit,
3107/// offset}`, `CallTable.exprs`); does not descend into them.
3108impl VisitChildren<HirScalarExpr> for HirRelationExpr {
3109    fn visit_children<F>(&self, mut f: F)
3110    where
3111        F: FnMut(&HirScalarExpr),
3112    {
3113        use HirRelationExpr::*;
3114        match self {
3115            Constant { rows: _, typ: _ }
3116            | Get { id: _, typ: _ }
3117            | Let {
3118                name: _,
3119                id: _,
3120                value: _,
3121                body: _,
3122            }
3123            | LetRec {
3124                limit: _,
3125                bindings: _,
3126                body: _,
3127            }
3128            | Project {
3129                input: _,
3130                outputs: _,
3131            } => (),
3132            Map { input: _, scalars } => {
3133                for scalar in scalars {
3134                    f(scalar);
3135                }
3136            }
3137            CallTable { func: _, exprs } => {
3138                for expr in exprs {
3139                    f(expr);
3140                }
3141            }
3142            Filter {
3143                input: _,
3144                predicates,
3145            } => {
3146                for predicate in predicates {
3147                    f(predicate);
3148                }
3149            }
3150            Join {
3151                left: _,
3152                right: _,
3153                on,
3154                kind: _,
3155            } => f(on),
3156            Reduce {
3157                input: _,
3158                group_key: _,
3159                aggregates,
3160                expected_group_size: _,
3161            } => {
3162                for aggregate in aggregates {
3163                    f(aggregate.expr.as_ref());
3164                }
3165            }
3166            TopK {
3167                input: _,
3168                group_key: _,
3169                order_key: _,
3170                limit,
3171                offset,
3172                expected_group_size: _,
3173            } => {
3174                if let Some(limit) = limit {
3175                    f(limit)
3176                }
3177                f(offset)
3178            }
3179            Distinct { input: _ }
3180            | Negate { input: _ }
3181            | Threshold { input: _ }
3182            | Union { base: _, inputs: _ } => (),
3183        }
3184    }
3185
3186    fn visit_mut_children<F>(&mut self, mut f: F)
3187    where
3188        F: FnMut(&mut HirScalarExpr),
3189    {
3190        use HirRelationExpr::*;
3191        match self {
3192            Constant { rows: _, typ: _ }
3193            | Get { id: _, typ: _ }
3194            | Let {
3195                name: _,
3196                id: _,
3197                value: _,
3198                body: _,
3199            }
3200            | LetRec {
3201                limit: _,
3202                bindings: _,
3203                body: _,
3204            }
3205            | Project {
3206                input: _,
3207                outputs: _,
3208            } => (),
3209            Map { input: _, scalars } => {
3210                for scalar in scalars {
3211                    f(scalar);
3212                }
3213            }
3214            CallTable { func: _, exprs } => {
3215                for expr in exprs {
3216                    f(expr);
3217                }
3218            }
3219            Filter {
3220                input: _,
3221                predicates,
3222            } => {
3223                for predicate in predicates {
3224                    f(predicate);
3225                }
3226            }
3227            Join {
3228                left: _,
3229                right: _,
3230                on,
3231                kind: _,
3232            } => f(on),
3233            Reduce {
3234                input: _,
3235                group_key: _,
3236                aggregates,
3237                expected_group_size: _,
3238            } => {
3239                for aggregate in aggregates {
3240                    f(aggregate.expr.as_mut());
3241                }
3242            }
3243            TopK {
3244                input: _,
3245                group_key: _,
3246                order_key: _,
3247                limit,
3248                offset,
3249                expected_group_size: _,
3250            } => {
3251                if let Some(limit) = limit {
3252                    f(limit)
3253                }
3254                f(offset)
3255            }
3256            Distinct { input: _ }
3257            | Negate { input: _ }
3258            | Threshold { input: _ }
3259            | Union { base: _, inputs: _ } => (),
3260        }
3261    }
3262
3263    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
3264    where
3265        F: FnMut(&HirScalarExpr) -> Result<(), E>,
3266    {
3267        use HirRelationExpr::*;
3268        match self {
3269            Constant { rows: _, typ: _ }
3270            | Get { id: _, typ: _ }
3271            | Let {
3272                name: _,
3273                id: _,
3274                value: _,
3275                body: _,
3276            }
3277            | LetRec {
3278                limit: _,
3279                bindings: _,
3280                body: _,
3281            }
3282            | Project {
3283                input: _,
3284                outputs: _,
3285            } => (),
3286            Map { input: _, scalars } => {
3287                for scalar in scalars {
3288                    f(scalar)?;
3289                }
3290            }
3291            CallTable { func: _, exprs } => {
3292                for expr in exprs {
3293                    f(expr)?;
3294                }
3295            }
3296            Filter {
3297                input: _,
3298                predicates,
3299            } => {
3300                for predicate in predicates {
3301                    f(predicate)?;
3302                }
3303            }
3304            Join {
3305                left: _,
3306                right: _,
3307                on,
3308                kind: _,
3309            } => f(on)?,
3310            Reduce {
3311                input: _,
3312                group_key: _,
3313                aggregates,
3314                expected_group_size: _,
3315            } => {
3316                for aggregate in aggregates {
3317                    f(aggregate.expr.as_ref())?;
3318                }
3319            }
3320            TopK {
3321                input: _,
3322                group_key: _,
3323                order_key: _,
3324                limit,
3325                offset,
3326                expected_group_size: _,
3327            } => {
3328                if let Some(limit) = limit {
3329                    f(limit)?
3330                }
3331                f(offset)?
3332            }
3333            Distinct { input: _ }
3334            | Negate { input: _ }
3335            | Threshold { input: _ }
3336            | Union { base: _, inputs: _ } => (),
3337        }
3338        Ok(())
3339    }
3340
3341    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
3342    where
3343        F: FnMut(&mut HirScalarExpr) -> Result<(), E>,
3344    {
3345        use HirRelationExpr::*;
3346        match self {
3347            Constant { rows: _, typ: _ }
3348            | Get { id: _, typ: _ }
3349            | Let {
3350                name: _,
3351                id: _,
3352                value: _,
3353                body: _,
3354            }
3355            | LetRec {
3356                limit: _,
3357                bindings: _,
3358                body: _,
3359            }
3360            | Project {
3361                input: _,
3362                outputs: _,
3363            } => (),
3364            Map { input: _, scalars } => {
3365                for scalar in scalars {
3366                    f(scalar)?;
3367                }
3368            }
3369            CallTable { func: _, exprs } => {
3370                for expr in exprs {
3371                    f(expr)?;
3372                }
3373            }
3374            Filter {
3375                input: _,
3376                predicates,
3377            } => {
3378                for predicate in predicates {
3379                    f(predicate)?;
3380                }
3381            }
3382            Join {
3383                left: _,
3384                right: _,
3385                on,
3386                kind: _,
3387            } => f(on)?,
3388            Reduce {
3389                input: _,
3390                group_key: _,
3391                aggregates,
3392                expected_group_size: _,
3393            } => {
3394                for aggregate in aggregates {
3395                    f(aggregate.expr.as_mut())?;
3396                }
3397            }
3398            TopK {
3399                input: _,
3400                group_key: _,
3401                order_key: _,
3402                limit,
3403                offset,
3404                expected_group_size: _,
3405            } => {
3406                if let Some(limit) = limit {
3407                    f(limit)?
3408                }
3409                f(offset)?
3410            }
3411            Distinct { input: _ }
3412            | Negate { input: _ }
3413            | Threshold { input: _ }
3414            | Union { base: _, inputs: _ } => (),
3415        }
3416        Ok(())
3417    }
3418
3419    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a HirScalarExpr>
3420    where
3421        HirScalarExpr: 'a,
3422    {
3423        use HirRelationExpr::*;
3424        match self {
3425            Constant { rows: _, typ: _ }
3426            | Get { id: _, typ: _ }
3427            | Let {
3428                name: _,
3429                id: _,
3430                value: _,
3431                body: _,
3432            }
3433            | LetRec {
3434                limit: _,
3435                bindings: _,
3436                body: _,
3437            }
3438            | Project {
3439                input: _,
3440                outputs: _,
3441            }
3442            | Distinct { input: _ }
3443            | Negate { input: _ }
3444            | Threshold { input: _ }
3445            | Union { base: _, inputs: _ } => vec![],
3446            Map { input: _, scalars }
3447            | CallTable {
3448                func: _,
3449                exprs: scalars,
3450            }
3451            | Filter {
3452                input: _,
3453                predicates: scalars,
3454            } => scalars.iter().collect(),
3455            Join {
3456                left: _,
3457                right: _,
3458                on,
3459                kind: _,
3460            } => vec![on],
3461            Reduce {
3462                input: _,
3463                group_key: _,
3464                aggregates,
3465                expected_group_size: _,
3466            } => aggregates.iter().map(|agg| &*agg.expr).collect(),
3467            TopK {
3468                input: _,
3469                group_key: _,
3470                order_key: _,
3471                limit,
3472                offset,
3473                expected_group_size: _,
3474            } => limit.iter().chain(std::iter::once(offset)).collect(),
3475        }
3476        .into_iter()
3477    }
3478
3479    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut HirScalarExpr>
3480    where
3481        HirScalarExpr: 'a,
3482    {
3483        use HirRelationExpr::*;
3484        match self {
3485            Constant { rows: _, typ: _ }
3486            | Get { id: _, typ: _ }
3487            | Let {
3488                name: _,
3489                id: _,
3490                value: _,
3491                body: _,
3492            }
3493            | LetRec {
3494                limit: _,
3495                bindings: _,
3496                body: _,
3497            }
3498            | Project {
3499                input: _,
3500                outputs: _,
3501            }
3502            | Distinct { input: _ }
3503            | Negate { input: _ }
3504            | Threshold { input: _ }
3505            | Union { base: _, inputs: _ } => vec![],
3506            Map { input: _, scalars }
3507            | CallTable {
3508                func: _,
3509                exprs: scalars,
3510            }
3511            | Filter {
3512                input: _,
3513                predicates: scalars,
3514            } => scalars.iter_mut().collect(),
3515            Join {
3516                left: _,
3517                right: _,
3518                on,
3519                kind: _,
3520            } => vec![on],
3521            Reduce {
3522                input: _,
3523                group_key: _,
3524                aggregates,
3525                expected_group_size: _,
3526            } => aggregates.iter_mut().map(|agg| &mut *agg.expr).collect(),
3527            TopK {
3528                input: _,
3529                group_key: _,
3530                order_key: _,
3531                limit,
3532                offset,
3533                expected_group_size: _,
3534            } => limit.iter_mut().chain(std::iter::once(offset)).collect(),
3535        }
3536        .into_iter()
3537    }
3538}
3539
3540impl HirScalarExpr {
3541    pub fn name(&self) -> Option<Arc<str>> {
3542        use HirScalarExpr::*;
3543        match self {
3544            Column(_, name)
3545            | Parameter(_, name)
3546            | Literal(_, _, name)
3547            | CallUnmaterializable(_, name)
3548            | CallUnary { name, .. }
3549            | CallBinary { name, .. }
3550            | CallVariadic { name, .. }
3551            | If { name, .. }
3552            | Exists(_, name)
3553            | Select(_, name)
3554            | Windowing(_, name) => name.0.clone(),
3555        }
3556    }
3557
3558    /// Visit every subquery, without descending into subqueries.
3559    pub fn visit_direct_subqueries<F>(&self, mut f: F)
3560    where
3561        F: FnMut(&HirRelationExpr),
3562    {
3563        self.visit_post(&mut |e| {
3564            VisitChildren::<HirRelationExpr>::visit_children(e, &mut f);
3565        });
3566    }
3567
3568    /// Mutable counterpart of [`HirScalarExpr::visit_direct_subqueries`].
3569    pub fn visit_direct_subqueries_mut<F>(&mut self, mut f: F)
3570    where
3571        F: FnMut(&mut HirRelationExpr),
3572    {
3573        self.visit_mut_post(&mut |e| {
3574            VisitChildren::<HirRelationExpr>::visit_mut_children(e, &mut f);
3575        });
3576    }
3577
3578    /// Fallible counterpart of [`HirScalarExpr::visit_direct_subqueries`].
3579    pub fn try_visit_direct_subqueries<F, E>(&self, mut f: F) -> Result<(), E>
3580    where
3581        F: FnMut(&HirRelationExpr) -> Result<(), E>,
3582    {
3583        self.try_visit_post(&mut |e| {
3584            VisitChildren::<HirRelationExpr>::try_visit_children(e, &mut f)
3585        })
3586    }
3587
3588    /// Fallible mutable counterpart of [`HirScalarExpr::visit_direct_subqueries`].
3589    pub fn try_visit_direct_subqueries_mut<F, E>(&mut self, mut f: F) -> Result<(), E>
3590    where
3591        F: FnMut(&mut HirRelationExpr) -> Result<(), E>,
3592    {
3593        self.try_visit_mut_post(&mut |e| {
3594            VisitChildren::<HirRelationExpr>::try_visit_mut_children(e, &mut f)
3595        })
3596    }
3597
3598    /// Replaces parameter references in the expression with the corresponding datum from `params`.
3599    /// Additionally, it simplifies OFFSET clauses to constants after parameter binding, and checks
3600    /// them for non-negativity.
3601    ///
3602    /// This handles subqueries nested inside `self` by calling back into
3603    /// [`HirRelationExpr::bind_parameters_and_simplify_offset`] on each direct subquery; that
3604    /// relation-level function in turn calls back here for the scalar expressions it holds, so
3605    /// the two functions corecursively cover the entire HIR tree.
3606    pub fn bind_parameters_and_simplify_offset(
3607        &mut self,
3608        scx: &StatementContext,
3609        lifetime: QueryLifetime,
3610        params: &Params,
3611    ) -> Result<(), PlanError> {
3612        // First, rewrite each `Parameter` node to a literal. This walks only the scalar tree;
3613        // it does not yet descend into subqueries.
3614        self.try_visit_mut_post(&mut |e: &mut HirScalarExpr| {
3615            if let HirScalarExpr::Parameter(n, name) = e {
3616                let datum = match params.datums.iter().nth(*n - 1) {
3617                    None => return Err(PlanError::UnknownParameter(*n)),
3618                    Some(datum) => datum,
3619                };
3620                let scalar_type = &params.execute_types[*n - 1];
3621                let row = Row::pack([datum]);
3622                let column_type = scalar_type.clone().nullable(datum.is_null());
3623
3624                let name = if let Some(name) = &name.0 {
3625                    Some(Arc::clone(name))
3626                } else {
3627                    Some(Arc::from(format!("${n}")))
3628                };
3629
3630                let qcx = QueryContext::root(scx, lifetime);
3631                let ecx = execute_expr_context(&qcx);
3632
3633                *e = plan_cast(
3634                    &ecx,
3635                    *EXECUTE_CAST_CONTEXT,
3636                    HirScalarExpr::Literal(row, column_type, TreatAsEqual(name)),
3637                    &params.expected_types[*n - 1],
3638                )
3639                .expect("checked in plan_params");
3640            }
3641            Ok(())
3642        })?;
3643        // Then descend into any subqueries; the relation-side `bind_parameters_and_simplify_offset`
3644        // handles corecursion back into scalars.
3645        self.try_visit_direct_subqueries_mut(|r: &mut HirRelationExpr| {
3646            r.bind_parameters_and_simplify_offset(scx, lifetime, params)
3647        })
3648    }
3649
3650    /// Like [`HirScalarExpr::bind_parameters_and_simplify_offset`], except that parameters are
3651    /// replaced with the corresponding expression fragment from `params` rather
3652    /// than a datum.
3653    ///
3654    /// Specifically, the parameter `$1` will be replaced with `params[0]`, the
3655    /// parameter `$2` will be replaced with `params[1]`, and so on. Parameters
3656    /// in `self` that refer to invalid indices of `params` will cause a panic.
3657    ///
3658    /// Column references in parameters will be corrected to account for the
3659    /// depth at which they are spliced.
3660    pub fn splice_parameters(&mut self, params: &[HirScalarExpr], depth: usize) {
3661        #[allow(deprecated)]
3662        let _ = self.visit_recursively_mut(depth, &mut |depth: usize,
3663                                                        e: &mut HirScalarExpr|
3664         -> Result<(), ()> {
3665            if let HirScalarExpr::Parameter(i, _name) = e {
3666                *e = params[*i - 1].clone();
3667                // Correct any column references in the parameter expression for
3668                // its new depth.
3669                e.visit_columns_mut(0, &mut |d: usize, col: &mut ColumnRef| {
3670                    if col.level >= d {
3671                        col.level += depth
3672                    }
3673                });
3674            }
3675            Ok(())
3676        });
3677    }
3678
3679    /// Whether the expression contains an [`UnmaterializableFunc::MzNow`] call.
3680    pub fn contains_temporal(&self) -> bool {
3681        let mut contains = false;
3682        self.visit_post(&mut |e| {
3683            if let Self::CallUnmaterializable(UnmaterializableFunc::MzNow, _name) = e {
3684                contains = true;
3685            }
3686        });
3687        contains
3688    }
3689
3690    /// Whether the expression contains any [`UnmaterializableFunc`] call.
3691    pub fn contains_unmaterializable(&self) -> bool {
3692        let mut contains = false;
3693        self.visit_post(&mut |e| {
3694            if let Self::CallUnmaterializable(_, _) = e {
3695                contains = true;
3696            }
3697        });
3698        contains
3699    }
3700
3701    /// Whether the expression contains any [`UnmaterializableFunc`] call other than
3702    /// [`UnmaterializableFunc::MzNow`].
3703    pub fn contains_unmaterializable_except_temporal(&self) -> bool {
3704        let mut contains = false;
3705        self.visit_post(&mut |e| {
3706            if let Self::CallUnmaterializable(f, _) = e {
3707                if *f != UnmaterializableFunc::MzNow {
3708                    contains = true;
3709                }
3710            }
3711        });
3712        contains
3713    }
3714
3715    /// Constructs an unnamed column reference in the current scope.
3716    /// Use [`HirScalarExpr::named_column`] when a name is known.
3717    /// Use [`HirScalarExpr::unnamed_column`] for a `ColumnRef`.
3718    pub fn column(index: usize) -> HirScalarExpr {
3719        HirScalarExpr::Column(
3720            ColumnRef {
3721                level: 0,
3722                column: index,
3723            },
3724            TreatAsEqual(None),
3725        )
3726    }
3727
3728    /// Constructs an unnamed column reference.
3729    pub fn unnamed_column(cr: ColumnRef) -> HirScalarExpr {
3730        HirScalarExpr::Column(cr, TreatAsEqual(None))
3731    }
3732
3733    /// Constructs a named column reference.
3734    /// Names are interned by a `NameManager`.
3735    pub fn named_column(cr: ColumnRef, name: Arc<str>) -> HirScalarExpr {
3736        HirScalarExpr::Column(cr, TreatAsEqual(Some(name)))
3737    }
3738
3739    pub fn parameter(n: usize) -> HirScalarExpr {
3740        HirScalarExpr::Parameter(n, TreatAsEqual(None))
3741    }
3742
3743    pub fn literal(datum: Datum, scalar_type: SqlScalarType) -> HirScalarExpr {
3744        let col_type = scalar_type.nullable(datum.is_null());
3745        soft_assert_or_log!(datum.is_instance_of_sql(&col_type), "type is correct");
3746        let row = Row::pack([datum]);
3747        HirScalarExpr::Literal(row, col_type, TreatAsEqual(None))
3748    }
3749
3750    pub fn literal_true() -> HirScalarExpr {
3751        HirScalarExpr::literal(Datum::True, SqlScalarType::Bool)
3752    }
3753
3754    pub fn literal_false() -> HirScalarExpr {
3755        HirScalarExpr::literal(Datum::False, SqlScalarType::Bool)
3756    }
3757
3758    pub fn literal_null(scalar_type: SqlScalarType) -> HirScalarExpr {
3759        HirScalarExpr::literal(Datum::Null, scalar_type)
3760    }
3761
3762    pub fn literal_1d_array(
3763        datums: Vec<Datum>,
3764        element_scalar_type: SqlScalarType,
3765    ) -> Result<HirScalarExpr, PlanError> {
3766        let scalar_type = match element_scalar_type {
3767            SqlScalarType::Array(_) => {
3768                sql_bail!("cannot build array from array type");
3769            }
3770            typ => SqlScalarType::Array(Box::new(typ)).nullable(false),
3771        };
3772
3773        let mut row = Row::default();
3774        row.packer()
3775            .try_push_array(
3776                &[ArrayDimension {
3777                    lower_bound: 1,
3778                    length: datums.len(),
3779                }],
3780                datums,
3781            )
3782            .expect("array constructed to be valid");
3783
3784        Ok(HirScalarExpr::Literal(row, scalar_type, TreatAsEqual(None)))
3785    }
3786
3787    pub fn as_literal(&self) -> Option<Datum<'_>> {
3788        if let HirScalarExpr::Literal(row, _column_type, _name) = self {
3789            Some(row.unpack_first())
3790        } else {
3791            None
3792        }
3793    }
3794
3795    pub fn is_literal_true(&self) -> bool {
3796        Some(Datum::True) == self.as_literal()
3797    }
3798
3799    pub fn is_literal_false(&self) -> bool {
3800        Some(Datum::False) == self.as_literal()
3801    }
3802
3803    pub fn is_literal_null(&self) -> bool {
3804        Some(Datum::Null) == self.as_literal()
3805    }
3806
3807    /// Return true iff `self` consists only of literals, materializable function calls, and
3808    /// if-else statements.
3809    pub fn is_constant(&self) -> bool {
3810        let mut worklist = vec![self];
3811        while let Some(expr) = worklist.pop() {
3812            match expr {
3813                Self::Literal(..) => {
3814                    // leaf node, do nothing
3815                }
3816                Self::CallUnary { expr, .. } => {
3817                    worklist.push(expr);
3818                }
3819                Self::CallBinary {
3820                    func: _,
3821                    expr1,
3822                    expr2,
3823                    name: _,
3824                } => {
3825                    worklist.push(expr1);
3826                    worklist.push(expr2);
3827                }
3828                Self::CallVariadic {
3829                    func: _,
3830                    exprs,
3831                    name: _,
3832                } => {
3833                    worklist.extend(exprs.iter());
3834                }
3835                // (CallUnmaterializable is not allowed)
3836                Self::If {
3837                    cond,
3838                    then,
3839                    els,
3840                    name: _,
3841                } => {
3842                    worklist.push(cond);
3843                    worklist.push(then);
3844                    worklist.push(els);
3845                }
3846                _ => {
3847                    return false; // Any other node makes `self` non-constant.
3848                }
3849            }
3850        }
3851        true
3852    }
3853
3854    pub fn call_unary(self, func: UnaryFunc) -> Self {
3855        HirScalarExpr::CallUnary {
3856            func,
3857            expr: Box::new(self),
3858            name: NameMetadata::default(),
3859        }
3860    }
3861
3862    pub fn call_binary<B: Into<BinaryFunc>>(self, other: Self, func: B) -> Self {
3863        HirScalarExpr::CallBinary {
3864            func: func.into(),
3865            expr1: Box::new(self),
3866            expr2: Box::new(other),
3867            name: NameMetadata::default(),
3868        }
3869    }
3870
3871    pub fn call_unmaterializable(func: UnmaterializableFunc) -> Self {
3872        HirScalarExpr::CallUnmaterializable(func, NameMetadata::default())
3873    }
3874
3875    pub fn call_variadic<V: Into<VariadicFunc>>(func: V, exprs: Vec<Self>) -> Self {
3876        HirScalarExpr::CallVariadic {
3877            func: func.into(),
3878            exprs,
3879            name: NameMetadata::default(),
3880        }
3881    }
3882
3883    pub fn if_then_else(cond: Self, then: Self, els: Self) -> Self {
3884        HirScalarExpr::If {
3885            cond: Box::new(cond),
3886            then: Box::new(then),
3887            els: Box::new(els),
3888            name: NameMetadata::default(),
3889        }
3890    }
3891
3892    pub fn windowing(expr: WindowExpr) -> Self {
3893        HirScalarExpr::Windowing(expr, TreatAsEqual(None))
3894    }
3895
3896    pub fn or(self, other: Self) -> Self {
3897        HirScalarExpr::call_variadic(Or, vec![self, other])
3898    }
3899
3900    pub fn and(self, other: Self) -> Self {
3901        HirScalarExpr::call_variadic(And, vec![self, other])
3902    }
3903
3904    pub fn not(self) -> Self {
3905        self.call_unary(UnaryFunc::Not(func::Not))
3906    }
3907
3908    pub fn call_is_null(self) -> Self {
3909        self.call_unary(UnaryFunc::IsNull(func::IsNull))
3910    }
3911
3912    /// Calls AND with the given arguments. Simplifies if 0 or 1 args.
3913    pub fn variadic_and(mut args: Vec<HirScalarExpr>) -> HirScalarExpr {
3914        match args.len() {
3915            0 => HirScalarExpr::literal_true(), // Same as unit_of_and_or, but that's MirScalarExpr
3916            1 => args.swap_remove(0),
3917            _ => HirScalarExpr::call_variadic(And, args),
3918        }
3919    }
3920
3921    /// Calls OR with the given arguments. Simplifies if 0 or 1 args.
3922    pub fn variadic_or(mut args: Vec<HirScalarExpr>) -> HirScalarExpr {
3923        match args.len() {
3924            0 => HirScalarExpr::literal_false(), // Same as unit_of_and_or, but that's MirScalarExpr
3925            1 => args.swap_remove(0),
3926            _ => HirScalarExpr::call_variadic(Or, args),
3927        }
3928    }
3929
3930    pub fn take(&mut self) -> Self {
3931        mem::replace(self, HirScalarExpr::literal_null(SqlScalarType::String))
3932    }
3933
3934    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
3935    /// Visits the column references in this scalar expression.
3936    ///
3937    /// The `depth` argument should indicate the subquery nesting depth of the expression,
3938    /// which will be incremented with each subquery entered and presented to the supplied
3939    /// function `f`.
3940    pub fn visit_columns<F>(&self, depth: usize, f: &mut F)
3941    where
3942        F: FnMut(usize, &ColumnRef),
3943    {
3944        #[allow(deprecated)]
3945        let _ = self.visit_recursively(depth, &mut |depth: usize,
3946                                                    e: &HirScalarExpr|
3947         -> Result<(), ()> {
3948            if let HirScalarExpr::Column(col, _name) = e {
3949                f(depth, col)
3950            }
3951            Ok(())
3952        });
3953    }
3954
3955    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
3956    /// Like `visit_columns`, but permits mutating the column references.
3957    pub fn visit_columns_mut<F>(&mut self, depth: usize, f: &mut F)
3958    where
3959        F: FnMut(usize, &mut ColumnRef),
3960    {
3961        #[allow(deprecated)]
3962        let _ = self.visit_recursively_mut(depth, &mut |depth: usize,
3963                                                        e: &mut HirScalarExpr|
3964         -> Result<(), ()> {
3965            if let HirScalarExpr::Column(col, _name) = e {
3966                f(depth, col)
3967            }
3968            Ok(())
3969        });
3970    }
3971
3972    /// Visits those column references in this scalar expression that refer to the root
3973    /// level. These include column references that are at the root level, as well as column
3974    /// references that are at a deeper subquery nesting depth, but refer back to the root level.
3975    /// (Note that even if `self` is embedded inside a larger expression, we consider the
3976    /// "root level" to be `self`'s level.)
3977    pub fn visit_columns_referring_to_root_level<F>(&self, f: &mut F)
3978    where
3979        F: FnMut(usize),
3980    {
3981        #[allow(deprecated)]
3982        let _ = self.visit_recursively(0, &mut |depth: usize,
3983                                                e: &HirScalarExpr|
3984         -> Result<(), ()> {
3985            if let HirScalarExpr::Column(col, _name) = e {
3986                if col.level == depth {
3987                    f(col.column)
3988                }
3989            }
3990            Ok(())
3991        });
3992    }
3993
3994    /// Like `visit_columns_referring_to_root_level`, but permits mutating the column references.
3995    pub fn visit_columns_referring_to_root_level_mut<F>(&mut self, f: &mut F)
3996    where
3997        F: FnMut(&mut usize),
3998    {
3999        #[allow(deprecated)]
4000        let _ = self.visit_recursively_mut(0, &mut |depth: usize,
4001                                                    e: &mut HirScalarExpr|
4002         -> Result<(), ()> {
4003            if let HirScalarExpr::Column(col, _name) = e {
4004                if col.level == depth {
4005                    f(&mut col.column)
4006                }
4007            }
4008            Ok(())
4009        });
4010    }
4011
4012    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
4013    /// Like `visit` but it enters the subqueries visiting the scalar expressions contained
4014    /// in them. It takes the current depth of the expression and increases it when
4015    /// entering a subquery.
4016    pub fn visit_recursively<F, E>(&self, depth: usize, f: &mut F) -> Result<(), E>
4017    where
4018        F: FnMut(usize, &HirScalarExpr) -> Result<(), E>,
4019    {
4020        match self {
4021            HirScalarExpr::Literal(..)
4022            | HirScalarExpr::Parameter(..)
4023            | HirScalarExpr::CallUnmaterializable(..)
4024            | HirScalarExpr::Column(..) => (),
4025            HirScalarExpr::CallUnary { expr, .. } => expr.visit_recursively(depth, f)?,
4026            HirScalarExpr::CallBinary { expr1, expr2, .. } => {
4027                expr1.visit_recursively(depth, f)?;
4028                expr2.visit_recursively(depth, f)?;
4029            }
4030            HirScalarExpr::CallVariadic { exprs, .. } => {
4031                for expr in exprs {
4032                    expr.visit_recursively(depth, f)?;
4033                }
4034            }
4035            HirScalarExpr::If {
4036                cond,
4037                then,
4038                els,
4039                name: _,
4040            } => {
4041                cond.visit_recursively(depth, f)?;
4042                then.visit_recursively(depth, f)?;
4043                els.visit_recursively(depth, f)?;
4044            }
4045            HirScalarExpr::Exists(expr, _name) | HirScalarExpr::Select(expr, _name) => {
4046                #[allow(deprecated)]
4047                expr.visit_scalar_expressions(depth + 1, &mut |e, depth| {
4048                    e.visit_recursively(depth, f)
4049                })?;
4050            }
4051            HirScalarExpr::Windowing(expr, _name) => {
4052                expr.visit_expressions(&mut |e| e.visit_recursively(depth, f))?;
4053            }
4054        }
4055        f(depth, self)
4056    }
4057
4058    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
4059    /// Like `visit_recursively`, but permits mutating the scalar expressions.
4060    pub fn visit_recursively_mut<F, E>(&mut self, depth: usize, f: &mut F) -> Result<(), E>
4061    where
4062        F: FnMut(usize, &mut HirScalarExpr) -> Result<(), E>,
4063    {
4064        match self {
4065            HirScalarExpr::Literal(..)
4066            | HirScalarExpr::Parameter(..)
4067            | HirScalarExpr::CallUnmaterializable(..)
4068            | HirScalarExpr::Column(..) => (),
4069            HirScalarExpr::CallUnary { expr, .. } => expr.visit_recursively_mut(depth, f)?,
4070            HirScalarExpr::CallBinary { expr1, expr2, .. } => {
4071                expr1.visit_recursively_mut(depth, f)?;
4072                expr2.visit_recursively_mut(depth, f)?;
4073            }
4074            HirScalarExpr::CallVariadic { exprs, .. } => {
4075                for expr in exprs {
4076                    expr.visit_recursively_mut(depth, f)?;
4077                }
4078            }
4079            HirScalarExpr::If {
4080                cond,
4081                then,
4082                els,
4083                name: _,
4084            } => {
4085                cond.visit_recursively_mut(depth, f)?;
4086                then.visit_recursively_mut(depth, f)?;
4087                els.visit_recursively_mut(depth, f)?;
4088            }
4089            HirScalarExpr::Exists(expr, _name) | HirScalarExpr::Select(expr, _name) => {
4090                #[allow(deprecated)]
4091                expr.visit_scalar_expressions_mut(depth + 1, &mut |e, depth| {
4092                    e.visit_recursively_mut(depth, f)
4093                })?;
4094            }
4095            HirScalarExpr::Windowing(expr, _name) => {
4096                expr.visit_expressions_mut(&mut |e| e.visit_recursively_mut(depth, f))?;
4097            }
4098        }
4099        f(depth, self)
4100    }
4101
4102    /// Attempts to simplify self into a literal.
4103    ///
4104    /// Returns None if self is not constant and therefore can't be simplified to a literal, or if
4105    /// an evaluation error occurs during simplification, or if self contains
4106    /// - a subquery
4107    /// - a column reference
4108    /// - a parameter
4109    /// - a window function call
4110    fn simplify_to_literal(self) -> Option<Row> {
4111        let mut expr = self
4112            .lower_uncorrelated(crate::plan::lowering::Config::default())
4113            .ok()?;
4114        // `reduce` is called without column types, so it panics on a column reference.
4115        if expr.contains_column() {
4116            return None;
4117        }
4118        // Using MIR evaluation with repr types is fine here: the
4119        // result is an untyped Row, so any intermediate type
4120        // canonicalization is discarded.
4121        expr.reduce(&[]);
4122        match expr {
4123            mz_expr::MirScalarExpr::Literal(Ok(row), _) => Some(row),
4124            _ => None,
4125        }
4126    }
4127
4128    /// Simplifies self into a literal. If this is not possible (e.g., because self is not constant
4129    /// or an evaluation error occurs during simplification), it returns
4130    /// [`PlanError::ConstantExpressionSimplificationFailed`].
4131    ///
4132    /// The returned error is an _internal_ error if the expression contains
4133    /// - a subquery
4134    /// - a column reference to an outer level
4135    /// - a parameter
4136    /// - a window function call
4137    ///
4138    /// TODO: use this everywhere instead of `simplify_to_literal`, so that we don't hide the error
4139    /// msg.
4140    fn simplify_to_literal_with_result(self) -> Result<Row, PlanError> {
4141        let mut expr = self
4142            .lower_uncorrelated(crate::plan::lowering::Config::default())
4143            .map_err(|err| {
4144                PlanError::ConstantExpressionSimplificationFailed(err.to_string_with_causes())
4145            })?;
4146        // `reduce` is called without column types, so it panics on a column reference.
4147        if expr.contains_column() {
4148            return Err(PlanError::ConstantExpressionSimplificationFailed(
4149                "Not a constant".to_string(),
4150            ));
4151        }
4152        // Using MIR evaluation with repr types is fine here: the
4153        // result is an untyped Row, so any intermediate type
4154        // canonicalization is discarded.
4155        expr.reduce(&[]);
4156        match expr {
4157            mz_expr::MirScalarExpr::Literal(Ok(row), _) => Ok(row),
4158            mz_expr::MirScalarExpr::Literal(Err(err), _) => Err(
4159                PlanError::ConstantExpressionSimplificationFailed(err.to_string_with_causes()),
4160            ),
4161            _ => Err(PlanError::ConstantExpressionSimplificationFailed(
4162                "Not a constant".to_string(),
4163            )),
4164        }
4165    }
4166
4167    /// Attempts to simplify this expression to a literal 64-bit integer.
4168    ///
4169    /// Returns `None` if this expression cannot be simplified, e.g. because it
4170    /// contains non-literal values.
4171    ///
4172    /// # Panics
4173    ///
4174    /// Panics if this expression does not have type [`SqlScalarType::Int64`].
4175    pub fn into_literal_int64(self) -> Option<i64> {
4176        self.simplify_to_literal().and_then(|row| {
4177            let datum = row.unpack_first();
4178            if datum.is_null() {
4179                None
4180            } else {
4181                Some(datum.unwrap_int64())
4182            }
4183        })
4184    }
4185
4186    /// Attempts to simplify this expression to a literal string.
4187    ///
4188    /// Returns `None` if this expression cannot be simplified, e.g. because it
4189    /// contains non-literal values.
4190    ///
4191    /// # Panics
4192    ///
4193    /// Panics if this expression does not have type [`SqlScalarType::String`].
4194    pub fn into_literal_string(self) -> Option<String> {
4195        self.simplify_to_literal().and_then(|row| {
4196            let datum = row.unpack_first();
4197            if datum.is_null() {
4198                None
4199            } else {
4200                Some(datum.unwrap_str().to_owned())
4201            }
4202        })
4203    }
4204
4205    /// Attempts to simplify this expression to a literal MzTimestamp.
4206    ///
4207    /// Returns `None` if the expression simplifies to `null` or if the expression cannot be
4208    /// simplified, e.g. because it contains non-literal values or a cast fails.
4209    ///
4210    /// TODO: Make this (and the other similar fns above) return Result, so that we can show the
4211    /// error when it fails. (E.g., there can be non-trivial cast errors.)
4212    /// See `try_into_literal_int64` as an example.
4213    ///
4214    /// # Panics
4215    ///
4216    /// Panics if this expression does not have type [`SqlScalarType::MzTimestamp`].
4217    pub fn into_literal_mz_timestamp(self) -> Option<Timestamp> {
4218        self.simplify_to_literal().and_then(|row| {
4219            let datum = row.unpack_first();
4220            if datum.is_null() {
4221                None
4222            } else {
4223                Some(datum.unwrap_mz_timestamp())
4224            }
4225        })
4226    }
4227
4228    /// Attempts to simplify this expression of [`SqlScalarType::Int64`] to a literal Int64 and
4229    /// returns it as an i64.
4230    ///
4231    /// Returns `PlanError::ConstantExpressionSimplificationFailed` if
4232    /// - it's not a constant expression (as determined by `is_constant`)
4233    /// - evaluates to null
4234    /// - an EvalError occurs during evaluation (e.g., a cast fails)
4235    ///
4236    /// # Panics
4237    ///
4238    /// Panics if this expression does not have type [`SqlScalarType::Int64`].
4239    pub fn try_into_literal_int64(self) -> Result<i64, PlanError> {
4240        match self.clone().try_into_nullable_literal_int64()? {
4241            Some(value) => Ok(value),
4242            None => Err(PlanError::ConstantExpressionSimplificationFailed(format!(
4243                "Expected an expression that evaluates to a non-null value, got {}",
4244                self
4245            ))),
4246        }
4247    }
4248
4249    /// Like [`try_into_literal_int64`](Self::try_into_literal_int64), but an expression that
4250    /// evaluates to null is `Ok(None)` instead of an error.
4251    pub fn try_into_nullable_literal_int64(self) -> Result<Option<i64>, PlanError> {
4252        // TODO: add the `is_constant` check also to all the other into_literal_... (by adding it to
4253        // `simplify_to_literal`), but those should be just soft_asserts at first that it doesn't
4254        // actually happen that it's weaker than `reduce`, and then add them for real after 1 week.
4255        // (Without the is_constant check, lower_uncorrelated's preconditions spill out to be
4256        // preconditions also of all the other into_literal_... functions.)
4257        if !self.is_constant() {
4258            return Err(PlanError::ConstantExpressionSimplificationFailed(format!(
4259                "Expected a constant expression, got {}",
4260                self
4261            )));
4262        }
4263        self.simplify_to_literal_with_result().map(|row| {
4264            let datum = row.unpack_first();
4265            if datum.is_null() {
4266                None
4267            } else {
4268                Some(datum.unwrap_int64())
4269            }
4270        })
4271    }
4272
4273    pub fn contains_parameters(&self) -> bool {
4274        let mut contains_parameters = false;
4275        #[allow(deprecated)]
4276        let _ = self.visit_recursively(0, &mut |_depth: usize,
4277                                                expr: &HirScalarExpr|
4278         -> Result<(), ()> {
4279            if let HirScalarExpr::Parameter(..) = expr {
4280                contains_parameters = true;
4281            }
4282            Ok(())
4283        });
4284        contains_parameters
4285    }
4286
4287    fn direct_subqueries(&self) -> Vec<&HirRelationExpr> {
4288        let mut subqueries: Vec<&HirRelationExpr> = vec![];
4289
4290        let mut worklist = vec![self];
4291        while let Some(elt) = worklist.pop() {
4292            match elt {
4293                HirScalarExpr::Column(_, _)
4294                | HirScalarExpr::Parameter(_, _)
4295                | HirScalarExpr::Literal(_, _, _)
4296                | HirScalarExpr::CallUnmaterializable(_, _) => (),
4297                HirScalarExpr::CallUnary {
4298                    func: _,
4299                    expr,
4300                    name: _,
4301                } => worklist.push(&*expr),
4302                HirScalarExpr::CallBinary {
4303                    func: _,
4304                    expr1,
4305                    expr2,
4306                    name: _name,
4307                } => {
4308                    // Push in reverse so children pop (and are visited) left-to-right.
4309                    worklist.push(&*expr2);
4310                    worklist.push(&*expr1);
4311                }
4312                HirScalarExpr::CallVariadic {
4313                    func: _,
4314                    exprs,
4315                    name: _name,
4316                } => {
4317                    worklist.extend(exprs.iter().rev());
4318                }
4319                HirScalarExpr::If {
4320                    cond,
4321                    then,
4322                    els,
4323                    name: _,
4324                } => {
4325                    worklist.push(&*els);
4326                    worklist.push(&*then);
4327                    worklist.push(&*cond);
4328                }
4329                HirScalarExpr::Exists(hir, _) | HirScalarExpr::Select(hir, _) => {
4330                    subqueries.push(&*hir);
4331                }
4332                HirScalarExpr::Windowing(
4333                    WindowExpr {
4334                        func,
4335                        partition_by,
4336                        order_by,
4337                    },
4338                    _,
4339                ) => {
4340                    // Push in reverse so children pop (and are visited) left-to-right:
4341                    // func args, then partition_by, then order_by.
4342                    worklist.extend(order_by.iter().rev());
4343                    worklist.extend(partition_by.iter().rev());
4344                    match func {
4345                        WindowExprType::Scalar(_) => (),
4346                        WindowExprType::Value(val) => worklist.push(&*val.args),
4347                        WindowExprType::Aggregate(agg) => worklist.push(&*agg.aggregate_expr.expr),
4348                    }
4349                }
4350            }
4351        }
4352
4353        subqueries
4354    }
4355
4356    fn direct_subqueries_mut(&mut self) -> Vec<&mut HirRelationExpr> {
4357        let mut subqueries: Vec<&mut HirRelationExpr> = vec![];
4358
4359        let mut worklist = vec![self];
4360        while let Some(elt) = worklist.pop() {
4361            match elt {
4362                HirScalarExpr::Column(_, _)
4363                | HirScalarExpr::Parameter(_, _)
4364                | HirScalarExpr::Literal(_, _, _)
4365                | HirScalarExpr::CallUnmaterializable(_, _) => (),
4366                HirScalarExpr::CallUnary {
4367                    func: _,
4368                    expr,
4369                    name: _,
4370                } => worklist.push(&mut **expr),
4371                HirScalarExpr::CallBinary {
4372                    func: _,
4373                    expr1,
4374                    expr2,
4375                    name: _name,
4376                } => {
4377                    // Push in reverse so children pop (and are visited) left-to-right.
4378                    worklist.push(&mut **expr2);
4379                    worklist.push(&mut **expr1);
4380                }
4381                HirScalarExpr::CallVariadic {
4382                    func: _,
4383                    exprs,
4384                    name: _name,
4385                } => {
4386                    worklist.extend(exprs.iter_mut().rev());
4387                }
4388                HirScalarExpr::If {
4389                    cond,
4390                    then,
4391                    els,
4392                    name: _,
4393                } => {
4394                    worklist.push(&mut **els);
4395                    worklist.push(&mut **then);
4396                    worklist.push(&mut **cond);
4397                }
4398                HirScalarExpr::Exists(hir, _) | HirScalarExpr::Select(hir, _) => {
4399                    subqueries.push(&mut **hir);
4400                }
4401                HirScalarExpr::Windowing(
4402                    WindowExpr {
4403                        func,
4404                        partition_by,
4405                        order_by,
4406                    },
4407                    _,
4408                ) => {
4409                    // Push in reverse so children pop (and are visited) left-to-right:
4410                    // func args, then partition_by, then order_by.
4411                    worklist.extend(order_by.iter_mut().rev());
4412                    worklist.extend(partition_by.iter_mut().rev());
4413                    match func {
4414                        WindowExprType::Scalar(_) => (),
4415                        WindowExprType::Value(val) => worklist.push(&mut val.args),
4416                        WindowExprType::Aggregate(agg) => {
4417                            worklist.push(&mut agg.aggregate_expr.expr)
4418                        }
4419                    }
4420                }
4421            }
4422        }
4423
4424        subqueries
4425    }
4426}
4427
4428/// Yields the direct scalar children of `self`. Stops at `Exists` / `Select`:
4429/// scalars inside subquery bodies are not surfaced. The asymmetry with
4430/// `VisitChildren<Self> for HirRelationExpr` (which does see through scalars
4431/// into subqueries) is what avoids the mutual recursion warned about on the
4432/// [`VisitChildren`] trait.
4433impl VisitChildren<Self> for HirScalarExpr {
4434    fn visit_children<F>(&self, mut f: F)
4435    where
4436        F: FnMut(&Self),
4437    {
4438        use HirScalarExpr::*;
4439        match self {
4440            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => (),
4441            CallUnary { expr, .. } => f(expr),
4442            CallBinary { expr1, expr2, .. } => {
4443                f(expr1);
4444                f(expr2);
4445            }
4446            CallVariadic { exprs, .. } => {
4447                for expr in exprs {
4448                    f(expr);
4449                }
4450            }
4451            If {
4452                cond,
4453                then,
4454                els,
4455                name: _,
4456            } => {
4457                f(cond);
4458                f(then);
4459                f(els);
4460            }
4461            Exists(..) | Select(..) => (),
4462            Windowing(expr, _name) => expr.visit_children(f),
4463        }
4464    }
4465
4466    fn visit_mut_children<F>(&mut self, mut f: F)
4467    where
4468        F: FnMut(&mut Self),
4469    {
4470        use HirScalarExpr::*;
4471        match self {
4472            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => (),
4473            CallUnary { expr, .. } => f(expr),
4474            CallBinary { expr1, expr2, .. } => {
4475                f(expr1);
4476                f(expr2);
4477            }
4478            CallVariadic { exprs, .. } => {
4479                for expr in exprs {
4480                    f(expr);
4481                }
4482            }
4483            If {
4484                cond,
4485                then,
4486                els,
4487                name: _,
4488            } => {
4489                f(cond);
4490                f(then);
4491                f(els);
4492            }
4493            Exists(..) | Select(..) => (),
4494            Windowing(expr, _name) => expr.visit_mut_children(f),
4495        }
4496    }
4497
4498    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
4499    where
4500        F: FnMut(&Self) -> Result<(), E>,
4501    {
4502        use HirScalarExpr::*;
4503        match self {
4504            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => (),
4505            CallUnary { expr, .. } => f(expr)?,
4506            CallBinary { expr1, expr2, .. } => {
4507                f(expr1)?;
4508                f(expr2)?;
4509            }
4510            CallVariadic { exprs, .. } => {
4511                for expr in exprs {
4512                    f(expr)?;
4513                }
4514            }
4515            If {
4516                cond,
4517                then,
4518                els,
4519                name: _,
4520            } => {
4521                f(cond)?;
4522                f(then)?;
4523                f(els)?;
4524            }
4525            Exists(..) | Select(..) => (),
4526            Windowing(expr, _name) => expr.try_visit_children(f)?,
4527        }
4528        Ok(())
4529    }
4530
4531    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
4532    where
4533        F: FnMut(&mut Self) -> Result<(), E>,
4534    {
4535        use HirScalarExpr::*;
4536        match self {
4537            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => (),
4538            CallUnary { expr, .. } => f(expr)?,
4539            CallBinary { expr1, expr2, .. } => {
4540                f(expr1)?;
4541                f(expr2)?;
4542            }
4543            CallVariadic { exprs, .. } => {
4544                for expr in exprs {
4545                    f(expr)?;
4546                }
4547            }
4548            If {
4549                cond,
4550                then,
4551                els,
4552                name: _,
4553            } => {
4554                f(cond)?;
4555                f(then)?;
4556                f(els)?;
4557            }
4558            Exists(..) | Select(..) => (),
4559            Windowing(expr, _name) => expr.try_visit_mut_children(f)?,
4560        }
4561        Ok(())
4562    }
4563
4564    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a Self>
4565    where
4566        Self: 'a,
4567    {
4568        use HirScalarExpr::*;
4569        let v: Vec<&Self> = match self {
4570            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => vec![],
4571            CallUnary { expr, .. } => vec![&*expr],
4572            CallBinary { expr1, expr2, .. } => {
4573                vec![&*expr1, &*expr2]
4574            }
4575            CallVariadic { exprs, .. } => exprs.iter().collect(),
4576            If {
4577                cond,
4578                then,
4579                els,
4580                name: _,
4581            } => {
4582                vec![&*cond, &*then, &*els]
4583            }
4584            Exists(..) | Select(..) => vec![],
4585            Windowing(expr, _name) => expr.children().collect(),
4586        };
4587        v.into_iter()
4588    }
4589
4590    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut Self>
4591    where
4592        Self: 'a,
4593    {
4594        use HirScalarExpr::*;
4595        let v: Vec<&mut Self> = match self {
4596            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => vec![],
4597            CallUnary { expr, .. } => vec![&mut **expr],
4598            CallBinary { expr1, expr2, .. } => {
4599                vec![&mut **expr1, &mut **expr2]
4600            }
4601            CallVariadic { exprs, .. } => exprs.iter_mut().collect(),
4602            If {
4603                cond,
4604                then,
4605                els,
4606                name: _,
4607            } => {
4608                vec![&mut **cond, &mut **then, &mut **els]
4609            }
4610            Exists(..) | Select(..) => vec![],
4611            Windowing(expr, _name) => expr.children_mut().collect(),
4612        };
4613        v.into_iter()
4614    }
4615}
4616
4617/// Yields the immediate `HirRelationExpr` children of `self` (the bodies of
4618/// `Exists` / `Select`); does not descend into them.
4619impl VisitChildren<HirRelationExpr> for HirScalarExpr {
4620    fn visit_children<F>(&self, mut f: F)
4621    where
4622        F: FnMut(&HirRelationExpr),
4623    {
4624        use HirScalarExpr::*;
4625        match self {
4626            Column(..)
4627            | Parameter(..)
4628            | Literal(..)
4629            | CallUnmaterializable(..)
4630            | CallUnary { .. }
4631            | CallBinary { .. }
4632            | CallVariadic { .. }
4633            | If { .. }
4634            | Windowing(..) => (),
4635            Exists(expr, _name) | Select(expr, _name) => f(expr),
4636        }
4637    }
4638
4639    fn visit_mut_children<F>(&mut self, mut f: F)
4640    where
4641        F: FnMut(&mut HirRelationExpr),
4642    {
4643        use HirScalarExpr::*;
4644        match self {
4645            Column(..)
4646            | Parameter(..)
4647            | Literal(..)
4648            | CallUnmaterializable(..)
4649            | CallUnary { .. }
4650            | CallBinary { .. }
4651            | CallVariadic { .. }
4652            | If { .. }
4653            | Windowing(..) => (),
4654            Exists(expr, _name) | Select(expr, _name) => f(expr),
4655        }
4656    }
4657
4658    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
4659    where
4660        F: FnMut(&HirRelationExpr) -> Result<(), E>,
4661    {
4662        use HirScalarExpr::*;
4663        match self {
4664            Column(..)
4665            | Parameter(..)
4666            | Literal(..)
4667            | CallUnmaterializable(..)
4668            | CallUnary { .. }
4669            | CallBinary { .. }
4670            | CallVariadic { .. }
4671            | If { .. }
4672            | Windowing(..) => (),
4673            Exists(expr, _name) | Select(expr, _name) => f(expr)?,
4674        }
4675        Ok(())
4676    }
4677
4678    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
4679    where
4680        F: FnMut(&mut HirRelationExpr) -> Result<(), E>,
4681    {
4682        use HirScalarExpr::*;
4683        match self {
4684            Column(..)
4685            | Parameter(..)
4686            | Literal(..)
4687            | CallUnmaterializable(..)
4688            | CallUnary { .. }
4689            | CallBinary { .. }
4690            | CallVariadic { .. }
4691            | If { .. }
4692            | Windowing(..) => (),
4693            Exists(expr, _name) | Select(expr, _name) => f(expr)?,
4694        }
4695        Ok(())
4696    }
4697
4698    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a HirRelationExpr>
4699    where
4700        HirRelationExpr: 'a,
4701    {
4702        let mut child: Option<&HirRelationExpr> = None;
4703        use HirScalarExpr::*;
4704        match self {
4705            Column(..)
4706            | Parameter(..)
4707            | Literal(..)
4708            | CallUnmaterializable(..)
4709            | CallUnary { .. }
4710            | CallBinary { .. }
4711            | CallVariadic { .. }
4712            | If { .. }
4713            | Windowing(..) => (),
4714            Exists(expr, _name) | Select(expr, _name) => child = Some(&*expr),
4715        }
4716
4717        child.into_iter()
4718    }
4719
4720    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut HirRelationExpr>
4721    where
4722        HirRelationExpr: 'a,
4723    {
4724        let mut child: Option<&mut HirRelationExpr> = None;
4725        use HirScalarExpr::*;
4726        match self {
4727            Column(..)
4728            | Parameter(..)
4729            | Literal(..)
4730            | CallUnmaterializable(..)
4731            | CallUnary { .. }
4732            | CallBinary { .. }
4733            | CallVariadic { .. }
4734            | If { .. }
4735            | Windowing(..) => (),
4736            Exists(expr, _name) | Select(expr, _name) => child = Some(&mut **expr),
4737        }
4738
4739        child.into_iter()
4740    }
4741}
4742
4743impl AbstractExpr for HirScalarExpr {
4744    type Type = SqlColumnType;
4745
4746    fn typ(
4747        &self,
4748        outers: &[SqlRelationType],
4749        inner: &SqlRelationType,
4750        params: &BTreeMap<usize, SqlScalarType>,
4751    ) -> Self::Type {
4752        stack::maybe_grow(|| match self {
4753            HirScalarExpr::Column(ColumnRef { level, column }, _name) => {
4754                if *level == 0 {
4755                    inner.column_types[*column].clone()
4756                } else {
4757                    outers[*level - 1].column_types[*column].clone()
4758                }
4759            }
4760            HirScalarExpr::Parameter(n, _name) => params[n].clone().nullable(true),
4761            HirScalarExpr::Literal(_, typ, _name) => typ.clone(),
4762            HirScalarExpr::CallUnmaterializable(func, _name) => func.output_sql_type(),
4763            HirScalarExpr::CallUnary {
4764                expr,
4765                func,
4766                name: _,
4767            } => func.output_sql_type(expr.typ(outers, inner, params)),
4768            HirScalarExpr::CallBinary {
4769                expr1,
4770                expr2,
4771                func,
4772                name: _,
4773            } => func.output_sql_type(&[
4774                expr1.typ(outers, inner, params),
4775                expr2.typ(outers, inner, params),
4776            ]),
4777            HirScalarExpr::CallVariadic {
4778                exprs,
4779                func,
4780                name: _,
4781            } => func.output_sql_type(exprs.iter().map(|e| e.typ(outers, inner, params)).collect()),
4782            HirScalarExpr::If {
4783                cond: _,
4784                then,
4785                els,
4786                name: _,
4787            } => {
4788                let then_type = then.typ(outers, inner, params);
4789                let else_type = els.typ(outers, inner, params);
4790                then_type.sql_union(&else_type).unwrap() // HIR deliberately not using `union`
4791            }
4792            HirScalarExpr::Exists(_, _name) => SqlScalarType::Bool.nullable(true),
4793            HirScalarExpr::Select(expr, _name) => {
4794                let mut outers = outers.to_vec();
4795                outers.insert(0, inner.clone());
4796                expr.typ(&outers, params)
4797                    .column_types
4798                    .into_element()
4799                    .nullable(true)
4800            }
4801            HirScalarExpr::Windowing(expr, _name) => expr.func.typ(outers, inner, params),
4802        })
4803    }
4804}
4805
4806impl AggregateExpr {
4807    pub fn typ(
4808        &self,
4809        outers: &[SqlRelationType],
4810        inner: &SqlRelationType,
4811        params: &BTreeMap<usize, SqlScalarType>,
4812    ) -> SqlColumnType {
4813        self.func
4814            .output_sql_type(self.expr.typ(outers, inner, params))
4815    }
4816
4817    /// Returns whether the expression is COUNT(*) or not.  Note that
4818    /// when we define the count builtin in sql::func, we convert
4819    /// COUNT(*) to COUNT(true), making it indistinguishable from
4820    /// literal COUNT(true), but we prefer to consider this as the
4821    /// former.
4822    ///
4823    /// (MIR has the same `is_count_asterisk`.)
4824    pub fn is_count_asterisk(&self) -> bool {
4825        self.func == AggregateFunc::Count && self.expr.is_literal_true() && !self.distinct
4826    }
4827}