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    MinNumeric,
1313    MinInt16,
1314    MinInt32,
1315    MinInt64,
1316    MinUInt16,
1317    MinUInt32,
1318    MinUInt64,
1319    MinMzTimestamp,
1320    MinFloat32,
1321    MinFloat64,
1322    MinBool,
1323    MinString,
1324    MinDate,
1325    MinTimestamp,
1326    MinTimestampTz,
1327    MinInterval,
1328    MinTime,
1329    SumInt16,
1330    SumInt32,
1331    SumInt64,
1332    SumUInt16,
1333    SumUInt32,
1334    SumUInt64,
1335    SumFloat32,
1336    SumFloat64,
1337    SumNumeric,
1338    Count,
1339    Any,
1340    All,
1341    /// Accumulates `Datum::List`s whose first element is a JSON-typed `Datum`s
1342    /// into a JSON list. The other elements are columns used by `order_by`.
1343    ///
1344    /// WARNING: Unlike the `jsonb_agg` function that is exposed by the SQL
1345    /// layer, this function filters out `Datum::Null`, for consistency with
1346    /// the other aggregate functions.
1347    JsonbAgg {
1348        order_by: Vec<ColumnOrder>,
1349    },
1350    /// Zips `Datum::List`s whose first element is a JSON-typed `Datum`s into a
1351    /// JSON map. The other elements are columns used by `order_by`.
1352    JsonbObjectAgg {
1353        order_by: Vec<ColumnOrder>,
1354    },
1355    /// Zips a `Datum::List` whose first element is a `Datum::List` guaranteed
1356    /// to be non-empty and whose len % 2 == 0 into a `Datum::Map`. The other
1357    /// elements are columns used by `order_by`.
1358    MapAgg {
1359        order_by: Vec<ColumnOrder>,
1360        value_type: SqlScalarType,
1361    },
1362    /// Accumulates `Datum::List`s whose first element is a `Datum::Array` into a
1363    /// single `Datum::Array`. The other elements are columns used by `order_by`.
1364    ArrayConcat {
1365        order_by: Vec<ColumnOrder>,
1366    },
1367    /// Accumulates `Datum::List`s whose first element is a `Datum::List` into a
1368    /// single `Datum::List`. The other elements are columns used by `order_by`.
1369    ListConcat {
1370        order_by: Vec<ColumnOrder>,
1371    },
1372    StringAgg {
1373        order_by: Vec<ColumnOrder>,
1374    },
1375    /// A bundle of fused window aggregations: its input is a record, whose each
1376    /// component will be the input to one of the `AggregateFunc`s.
1377    ///
1378    /// Importantly, this aggregation can only be present inside a `WindowExpr`,
1379    /// more specifically an `AggregateWindowExpr`.
1380    FusedWindowAgg {
1381        funcs: Vec<AggregateFunc>,
1382    },
1383    /// Accumulates any number of `Datum::Dummy`s into `Datum::Dummy`.
1384    ///
1385    /// Useful for removing an expensive aggregation while maintaining the shape
1386    /// of a reduce operator.
1387    Dummy,
1388}
1389
1390impl AggregateFunc {
1391    /// Converts the `sql::AggregateFunc` to a corresponding `mz_expr::AggregateFunc`.
1392    pub fn into_expr(self) -> mz_expr::AggregateFunc {
1393        match self {
1394            AggregateFunc::MaxNumeric => mz_expr::AggregateFunc::MaxNumeric,
1395            AggregateFunc::MaxInt16 => mz_expr::AggregateFunc::MaxInt16,
1396            AggregateFunc::MaxInt32 => mz_expr::AggregateFunc::MaxInt32,
1397            AggregateFunc::MaxInt64 => mz_expr::AggregateFunc::MaxInt64,
1398            AggregateFunc::MaxUInt16 => mz_expr::AggregateFunc::MaxUInt16,
1399            AggregateFunc::MaxUInt32 => mz_expr::AggregateFunc::MaxUInt32,
1400            AggregateFunc::MaxUInt64 => mz_expr::AggregateFunc::MaxUInt64,
1401            AggregateFunc::MaxMzTimestamp => mz_expr::AggregateFunc::MaxMzTimestamp,
1402            AggregateFunc::MaxFloat32 => mz_expr::AggregateFunc::MaxFloat32,
1403            AggregateFunc::MaxFloat64 => mz_expr::AggregateFunc::MaxFloat64,
1404            AggregateFunc::MaxBool => mz_expr::AggregateFunc::MaxBool,
1405            AggregateFunc::MaxString => mz_expr::AggregateFunc::MaxString,
1406            AggregateFunc::MaxDate => mz_expr::AggregateFunc::MaxDate,
1407            AggregateFunc::MaxTimestamp => mz_expr::AggregateFunc::MaxTimestamp,
1408            AggregateFunc::MaxTimestampTz => mz_expr::AggregateFunc::MaxTimestampTz,
1409            AggregateFunc::MaxInterval => mz_expr::AggregateFunc::MaxInterval,
1410            AggregateFunc::MaxTime => mz_expr::AggregateFunc::MaxTime,
1411            AggregateFunc::MinNumeric => mz_expr::AggregateFunc::MinNumeric,
1412            AggregateFunc::MinInt16 => mz_expr::AggregateFunc::MinInt16,
1413            AggregateFunc::MinInt32 => mz_expr::AggregateFunc::MinInt32,
1414            AggregateFunc::MinInt64 => mz_expr::AggregateFunc::MinInt64,
1415            AggregateFunc::MinUInt16 => mz_expr::AggregateFunc::MinUInt16,
1416            AggregateFunc::MinUInt32 => mz_expr::AggregateFunc::MinUInt32,
1417            AggregateFunc::MinUInt64 => mz_expr::AggregateFunc::MinUInt64,
1418            AggregateFunc::MinMzTimestamp => mz_expr::AggregateFunc::MinMzTimestamp,
1419            AggregateFunc::MinFloat32 => mz_expr::AggregateFunc::MinFloat32,
1420            AggregateFunc::MinFloat64 => mz_expr::AggregateFunc::MinFloat64,
1421            AggregateFunc::MinBool => mz_expr::AggregateFunc::MinBool,
1422            AggregateFunc::MinString => mz_expr::AggregateFunc::MinString,
1423            AggregateFunc::MinDate => mz_expr::AggregateFunc::MinDate,
1424            AggregateFunc::MinTimestamp => mz_expr::AggregateFunc::MinTimestamp,
1425            AggregateFunc::MinTimestampTz => mz_expr::AggregateFunc::MinTimestampTz,
1426            AggregateFunc::MinInterval => mz_expr::AggregateFunc::MinInterval,
1427            AggregateFunc::MinTime => mz_expr::AggregateFunc::MinTime,
1428            AggregateFunc::SumInt16 => mz_expr::AggregateFunc::SumInt16,
1429            AggregateFunc::SumInt32 => mz_expr::AggregateFunc::SumInt32,
1430            AggregateFunc::SumInt64 => mz_expr::AggregateFunc::SumInt64,
1431            AggregateFunc::SumUInt16 => mz_expr::AggregateFunc::SumUInt16,
1432            AggregateFunc::SumUInt32 => mz_expr::AggregateFunc::SumUInt32,
1433            AggregateFunc::SumUInt64 => mz_expr::AggregateFunc::SumUInt64,
1434            AggregateFunc::SumFloat32 => mz_expr::AggregateFunc::SumFloat32,
1435            AggregateFunc::SumFloat64 => mz_expr::AggregateFunc::SumFloat64,
1436            AggregateFunc::SumNumeric => mz_expr::AggregateFunc::SumNumeric,
1437            AggregateFunc::Count => mz_expr::AggregateFunc::Count,
1438            AggregateFunc::Any => mz_expr::AggregateFunc::Any,
1439            AggregateFunc::All => mz_expr::AggregateFunc::All,
1440            AggregateFunc::JsonbAgg { order_by } => mz_expr::AggregateFunc::JsonbAgg { order_by },
1441            AggregateFunc::JsonbObjectAgg { order_by } => {
1442                mz_expr::AggregateFunc::JsonbObjectAgg { order_by }
1443            }
1444            AggregateFunc::MapAgg {
1445                order_by,
1446                value_type,
1447            } => mz_expr::AggregateFunc::MapAgg {
1448                order_by,
1449                value_type,
1450            },
1451            AggregateFunc::ArrayConcat { order_by } => {
1452                mz_expr::AggregateFunc::ArrayConcat { order_by }
1453            }
1454            AggregateFunc::ListConcat { order_by } => {
1455                mz_expr::AggregateFunc::ListConcat { order_by }
1456            }
1457            AggregateFunc::StringAgg { order_by } => mz_expr::AggregateFunc::StringAgg { order_by },
1458            // `AggregateFunc::FusedWindowAgg` should be specially handled in
1459            // `AggregateWindowExpr::into_expr`.
1460            AggregateFunc::FusedWindowAgg { funcs: _ } => {
1461                panic!("into_expr called on FusedWindowAgg")
1462            }
1463            AggregateFunc::Dummy => mz_expr::AggregateFunc::Dummy,
1464        }
1465    }
1466
1467    /// Returns a datum whose inclusion in the aggregation will not change its
1468    /// result.
1469    ///
1470    /// # Panics
1471    ///
1472    /// Panics if called on a `FusedWindowAgg`.
1473    pub fn identity_datum(&self) -> Datum<'static> {
1474        match self {
1475            AggregateFunc::Any => Datum::False,
1476            AggregateFunc::All => Datum::True,
1477            AggregateFunc::Dummy => Datum::Dummy,
1478            AggregateFunc::ArrayConcat { .. } => Datum::empty_array(),
1479            AggregateFunc::ListConcat { .. } => Datum::empty_list(),
1480            AggregateFunc::MaxNumeric
1481            | AggregateFunc::MaxInt16
1482            | AggregateFunc::MaxInt32
1483            | AggregateFunc::MaxInt64
1484            | AggregateFunc::MaxUInt16
1485            | AggregateFunc::MaxUInt32
1486            | AggregateFunc::MaxUInt64
1487            | AggregateFunc::MaxMzTimestamp
1488            | AggregateFunc::MaxFloat32
1489            | AggregateFunc::MaxFloat64
1490            | AggregateFunc::MaxBool
1491            | AggregateFunc::MaxString
1492            | AggregateFunc::MaxDate
1493            | AggregateFunc::MaxTimestamp
1494            | AggregateFunc::MaxTimestampTz
1495            | AggregateFunc::MaxInterval
1496            | AggregateFunc::MaxTime
1497            | AggregateFunc::MinNumeric
1498            | AggregateFunc::MinInt16
1499            | AggregateFunc::MinInt32
1500            | AggregateFunc::MinInt64
1501            | AggregateFunc::MinUInt16
1502            | AggregateFunc::MinUInt32
1503            | AggregateFunc::MinUInt64
1504            | AggregateFunc::MinMzTimestamp
1505            | AggregateFunc::MinFloat32
1506            | AggregateFunc::MinFloat64
1507            | AggregateFunc::MinBool
1508            | AggregateFunc::MinString
1509            | AggregateFunc::MinDate
1510            | AggregateFunc::MinTimestamp
1511            | AggregateFunc::MinTimestampTz
1512            | AggregateFunc::MinInterval
1513            | AggregateFunc::MinTime
1514            | AggregateFunc::SumInt16
1515            | AggregateFunc::SumInt32
1516            | AggregateFunc::SumInt64
1517            | AggregateFunc::SumUInt16
1518            | AggregateFunc::SumUInt32
1519            | AggregateFunc::SumUInt64
1520            | AggregateFunc::SumFloat32
1521            | AggregateFunc::SumFloat64
1522            | AggregateFunc::SumNumeric
1523            | AggregateFunc::Count
1524            | AggregateFunc::JsonbAgg { .. }
1525            | AggregateFunc::JsonbObjectAgg { .. }
1526            | AggregateFunc::MapAgg { .. }
1527            | AggregateFunc::StringAgg { .. } => Datum::Null,
1528            AggregateFunc::FusedWindowAgg { funcs: _ } => {
1529                // `identity_datum` is used only in HIR planning, and `FusedWindowAgg` can't occur
1530                // in HIR planning, because it is introduced only during HIR transformation.
1531                //
1532                // The implementation could be something like the following, except that we need to
1533                // return a `Datum<'static>`, so we can't actually dynamically compute this.
1534                // ```
1535                // let temp_storage = RowArena::new();
1536                // temp_storage.make_datum(|packer| packer.push_list(funcs.iter().map(|f| f.identity_datum())))
1537                // ```
1538                panic!("FusedWindowAgg doesn't have an identity_datum")
1539            }
1540        }
1541    }
1542
1543    /// The output column type for the result of an aggregation.
1544    ///
1545    /// The output column type also contains nullability information, which
1546    /// is (without further information) true for aggregations that are not
1547    /// counts.
1548    pub fn output_sql_type(&self, input_type: SqlColumnType) -> SqlColumnType {
1549        let scalar_type = match self {
1550            AggregateFunc::Count => SqlScalarType::Int64,
1551            AggregateFunc::Any => SqlScalarType::Bool,
1552            AggregateFunc::All => SqlScalarType::Bool,
1553            AggregateFunc::JsonbAgg { .. } => SqlScalarType::Jsonb,
1554            AggregateFunc::JsonbObjectAgg { .. } => SqlScalarType::Jsonb,
1555            AggregateFunc::StringAgg { .. } => SqlScalarType::String,
1556            AggregateFunc::SumInt16 | AggregateFunc::SumInt32 => SqlScalarType::Int64,
1557            AggregateFunc::SumInt64 => SqlScalarType::Numeric {
1558                max_scale: Some(NumericMaxScale::ZERO),
1559            },
1560            AggregateFunc::SumUInt16 | AggregateFunc::SumUInt32 => SqlScalarType::UInt64,
1561            AggregateFunc::SumUInt64 => SqlScalarType::Numeric {
1562                max_scale: Some(NumericMaxScale::ZERO),
1563            },
1564            AggregateFunc::MapAgg { value_type, .. } => SqlScalarType::Map {
1565                value_type: Box::new(value_type.clone()),
1566                custom_id: None,
1567            },
1568            AggregateFunc::ArrayConcat { .. } | AggregateFunc::ListConcat { .. } => {
1569                match input_type.scalar_type {
1570                    // The input is wrapped in a Record if there's an ORDER BY, so extract it out.
1571                    SqlScalarType::Record { fields, .. } => fields[0].1.scalar_type.clone(),
1572                    _ => unreachable!(),
1573                }
1574            }
1575            AggregateFunc::MaxNumeric
1576            | AggregateFunc::MaxInt16
1577            | AggregateFunc::MaxInt32
1578            | AggregateFunc::MaxInt64
1579            | AggregateFunc::MaxUInt16
1580            | AggregateFunc::MaxUInt32
1581            | AggregateFunc::MaxUInt64
1582            | AggregateFunc::MaxMzTimestamp
1583            | AggregateFunc::MaxFloat32
1584            | AggregateFunc::MaxFloat64
1585            | AggregateFunc::MaxBool
1586            | AggregateFunc::MaxString
1587            | AggregateFunc::MaxDate
1588            | AggregateFunc::MaxTimestamp
1589            | AggregateFunc::MaxTimestampTz
1590            | AggregateFunc::MaxInterval
1591            | AggregateFunc::MaxTime
1592            | AggregateFunc::MinNumeric
1593            | AggregateFunc::MinInt16
1594            | AggregateFunc::MinInt32
1595            | AggregateFunc::MinInt64
1596            | AggregateFunc::MinUInt16
1597            | AggregateFunc::MinUInt32
1598            | AggregateFunc::MinUInt64
1599            | AggregateFunc::MinMzTimestamp
1600            | AggregateFunc::MinFloat32
1601            | AggregateFunc::MinFloat64
1602            | AggregateFunc::MinBool
1603            | AggregateFunc::MinString
1604            | AggregateFunc::MinDate
1605            | AggregateFunc::MinTimestamp
1606            | AggregateFunc::MinTimestampTz
1607            | AggregateFunc::MinInterval
1608            | AggregateFunc::MinTime
1609            | AggregateFunc::SumFloat32
1610            | AggregateFunc::SumFloat64
1611            | AggregateFunc::SumNumeric
1612            | AggregateFunc::Dummy => input_type.scalar_type,
1613            AggregateFunc::FusedWindowAgg { funcs } => {
1614                let input_types = input_type.scalar_type.unwrap_record_element_column_type();
1615                SqlScalarType::Record {
1616                    fields: funcs
1617                        .iter()
1618                        .zip_eq(input_types)
1619                        .map(|(f, t)| (ColumnName::from(""), f.output_sql_type(t.clone())))
1620                        .collect(),
1621                    custom_id: None,
1622                }
1623            }
1624        };
1625        // max/min/sum return null on empty sets
1626        let nullable = !matches!(self, AggregateFunc::Count);
1627        scalar_type.nullable(nullable)
1628    }
1629
1630    pub fn is_order_sensitive(&self) -> bool {
1631        use AggregateFunc::*;
1632        matches!(
1633            self,
1634            JsonbAgg { .. }
1635                | JsonbObjectAgg { .. }
1636                | MapAgg { .. }
1637                | ArrayConcat { .. }
1638                | ListConcat { .. }
1639                | StringAgg { .. }
1640        )
1641    }
1642}
1643
1644impl HirRelationExpr {
1645    /// Gets the SQL type of a self-contained, top-level expression.
1646    pub fn top_level_typ(&self) -> SqlRelationType {
1647        self.typ(&[], &BTreeMap::new())
1648    }
1649
1650    /// Gets the SQL type of the expression.
1651    ///
1652    /// `outers` gives types for outer relations.
1653    /// `params` gives types for parameters.
1654    pub fn typ(
1655        &self,
1656        outers: &[SqlRelationType],
1657        params: &BTreeMap<usize, SqlScalarType>,
1658    ) -> SqlRelationType {
1659        stack::maybe_grow(|| match self {
1660            HirRelationExpr::Constant { typ, .. } => typ.clone(),
1661            HirRelationExpr::Get { typ, .. } => typ.clone(),
1662            HirRelationExpr::Let { body, .. } => body.typ(outers, params),
1663            HirRelationExpr::LetRec { body, .. } => body.typ(outers, params),
1664            HirRelationExpr::Project { input, outputs } => {
1665                let input_typ = input.typ(outers, params);
1666                SqlRelationType::new(
1667                    outputs
1668                        .iter()
1669                        .map(|&i| input_typ.column_types[i].clone())
1670                        .collect(),
1671                )
1672            }
1673            HirRelationExpr::Map { input, scalars } => {
1674                let mut typ = input.typ(outers, params);
1675                for scalar in scalars {
1676                    typ.column_types.push(scalar.typ(outers, &typ, params));
1677                }
1678                typ
1679            }
1680            HirRelationExpr::CallTable { func, exprs: _ } => func.output_sql_type(),
1681            HirRelationExpr::Filter { input, .. } | HirRelationExpr::TopK { input, .. } => {
1682                input.typ(outers, params)
1683            }
1684            HirRelationExpr::Join {
1685                left, right, kind, ..
1686            } => {
1687                let left_nullable = matches!(kind, JoinKind::RightOuter | JoinKind::FullOuter);
1688                let right_nullable =
1689                    matches!(kind, JoinKind::LeftOuter { .. } | JoinKind::FullOuter);
1690                let lt = left.typ(outers, params).column_types.into_iter().map(|t| {
1691                    let nullable = t.nullable || left_nullable;
1692                    t.nullable(nullable)
1693                });
1694                let mut outers = outers.to_vec();
1695                outers.insert(0, SqlRelationType::new(lt.clone().collect()));
1696                let rt = right
1697                    .typ(&outers, params)
1698                    .column_types
1699                    .into_iter()
1700                    .map(|t| {
1701                        let nullable = t.nullable || right_nullable;
1702                        t.nullable(nullable)
1703                    });
1704                SqlRelationType::new(lt.chain(rt).collect())
1705            }
1706            HirRelationExpr::Reduce {
1707                input,
1708                group_key,
1709                aggregates,
1710                expected_group_size: _,
1711            } => {
1712                let input_typ = input.typ(outers, params);
1713                let mut column_types = group_key
1714                    .iter()
1715                    .map(|&i| input_typ.column_types[i].clone())
1716                    .collect::<Vec<_>>();
1717                for agg in aggregates {
1718                    column_types.push(agg.typ(outers, &input_typ, params));
1719                }
1720                // TODO(frank): add primary key information.
1721                SqlRelationType::new(column_types)
1722            }
1723            // TODO(frank): check for removal; add primary key information.
1724            HirRelationExpr::Distinct { input }
1725            | HirRelationExpr::Negate { input }
1726            | HirRelationExpr::Threshold { input } => input.typ(outers, params),
1727            HirRelationExpr::Union { base, inputs } => {
1728                let mut base_cols = base.typ(outers, params).column_types;
1729                for input in inputs {
1730                    for (base_col, col) in base_cols
1731                        .iter_mut()
1732                        .zip_eq(input.typ(outers, params).column_types)
1733                    {
1734                        *base_col = base_col.sql_union(&col).unwrap(); // HIR deliberately not using `union`
1735                    }
1736                }
1737                SqlRelationType::new(base_cols)
1738            }
1739        })
1740    }
1741
1742    pub fn arity(&self) -> usize {
1743        match self {
1744            HirRelationExpr::Constant { typ, .. } => typ.column_types.len(),
1745            HirRelationExpr::Get { typ, .. } => typ.column_types.len(),
1746            HirRelationExpr::Let { body, .. } => body.arity(),
1747            HirRelationExpr::LetRec { body, .. } => body.arity(),
1748            HirRelationExpr::Project { outputs, .. } => outputs.len(),
1749            HirRelationExpr::Map { input, scalars } => input.arity() + scalars.len(),
1750            HirRelationExpr::CallTable { func, exprs: _ } => func.output_arity(),
1751            HirRelationExpr::Filter { input, .. }
1752            | HirRelationExpr::TopK { input, .. }
1753            | HirRelationExpr::Distinct { input }
1754            | HirRelationExpr::Negate { input }
1755            | HirRelationExpr::Threshold { input } => input.arity(),
1756            HirRelationExpr::Join { left, right, .. } => left.arity() + right.arity(),
1757            HirRelationExpr::Union { base, .. } => base.arity(),
1758            HirRelationExpr::Reduce {
1759                group_key,
1760                aggregates,
1761                ..
1762            } => group_key.len() + aggregates.len(),
1763        }
1764    }
1765
1766    /// The number of relation nodes in this expression.
1767    ///
1768    /// Relations reached through scalar subqueries are included. The scalar
1769    /// nodes themselves are not, so a large predicate over a small input still
1770    /// counts as small. This is a structural size for comparing two
1771    /// expressions against each other, not a cost estimate.
1772    pub fn relation_node_count(&self) -> usize {
1773        let mut count = 0;
1774        self.visit_post(&mut |_| count += 1);
1775        count
1776    }
1777
1778    /// If self is a constant, return the value and the type, otherwise `None`.
1779    pub fn as_const(&self) -> Option<(&Vec<Row>, &SqlRelationType)> {
1780        match self {
1781            Self::Constant { rows, typ } => Some((rows, typ)),
1782            _ => None,
1783        }
1784    }
1785
1786    /// Reports whether this expression contains a column reference to its
1787    /// direct parent scope.
1788    pub fn is_correlated(&self) -> bool {
1789        let mut correlated = false;
1790        #[allow(deprecated)]
1791        self.visit_columns(0, &mut |depth, col| {
1792            if col.level > depth && col.level - depth == 1 {
1793                correlated = true;
1794            }
1795        });
1796        correlated
1797    }
1798
1799    pub fn is_join_identity(&self) -> bool {
1800        match self {
1801            HirRelationExpr::Constant { rows, .. } => rows.len() == 1 && self.arity() == 0,
1802            _ => false,
1803        }
1804    }
1805
1806    pub fn project(self, outputs: Vec<usize>) -> Self {
1807        if outputs.iter().copied().eq(0..self.arity()) {
1808            // The projection is trivial. Suppress it.
1809            self
1810        } else {
1811            HirRelationExpr::Project {
1812                input: Box::new(self),
1813                outputs,
1814            }
1815        }
1816    }
1817
1818    pub fn map(mut self, scalars: Vec<HirScalarExpr>) -> Self {
1819        if scalars.is_empty() {
1820            // The map is trivial. Suppress it.
1821            self
1822        } else if let HirRelationExpr::Map {
1823            scalars: old_scalars,
1824            input: _,
1825        } = &mut self
1826        {
1827            // Map applied to a map. Fuse the maps.
1828            old_scalars.extend(scalars);
1829            self
1830        } else {
1831            HirRelationExpr::Map {
1832                input: Box::new(self),
1833                scalars,
1834            }
1835        }
1836    }
1837
1838    pub fn filter(mut self, mut preds: Vec<HirScalarExpr>) -> Self {
1839        if let HirRelationExpr::Filter {
1840            input: _,
1841            predicates,
1842        } = &mut self
1843        {
1844            predicates.extend(preds);
1845            predicates.sort();
1846            predicates.dedup();
1847            self
1848        } else {
1849            preds.sort();
1850            preds.dedup();
1851            HirRelationExpr::Filter {
1852                input: Box::new(self),
1853                predicates: preds,
1854            }
1855        }
1856    }
1857
1858    pub fn reduce(
1859        self,
1860        group_key: Vec<usize>,
1861        aggregates: Vec<AggregateExpr>,
1862        expected_group_size: Option<u64>,
1863    ) -> Self {
1864        HirRelationExpr::Reduce {
1865            input: Box::new(self),
1866            group_key,
1867            aggregates,
1868            expected_group_size,
1869        }
1870    }
1871
1872    pub fn top_k(
1873        self,
1874        group_key: Vec<usize>,
1875        order_key: Vec<ColumnOrder>,
1876        limit: Option<HirScalarExpr>,
1877        offset: HirScalarExpr,
1878        expected_group_size: Option<u64>,
1879    ) -> Self {
1880        HirRelationExpr::TopK {
1881            input: Box::new(self),
1882            group_key,
1883            order_key,
1884            limit,
1885            offset,
1886            expected_group_size,
1887        }
1888    }
1889
1890    pub fn negate(self) -> Self {
1891        if let HirRelationExpr::Negate { input } = self {
1892            *input
1893        } else {
1894            HirRelationExpr::Negate {
1895                input: Box::new(self),
1896            }
1897        }
1898    }
1899
1900    pub fn distinct(self) -> Self {
1901        if let HirRelationExpr::Distinct { .. } = self {
1902            self
1903        } else {
1904            HirRelationExpr::Distinct {
1905                input: Box::new(self),
1906            }
1907        }
1908    }
1909
1910    pub fn threshold(self) -> Self {
1911        if let HirRelationExpr::Threshold { .. } = self {
1912            self
1913        } else {
1914            HirRelationExpr::Threshold {
1915                input: Box::new(self),
1916            }
1917        }
1918    }
1919
1920    pub fn union(self, other: Self) -> Self {
1921        let mut terms = Vec::new();
1922        if let HirRelationExpr::Union { base, inputs } = self {
1923            terms.push(*base);
1924            terms.extend(inputs);
1925        } else {
1926            terms.push(self);
1927        }
1928        if let HirRelationExpr::Union { base, inputs } = other {
1929            terms.push(*base);
1930            terms.extend(inputs);
1931        } else {
1932            terms.push(other);
1933        }
1934        HirRelationExpr::Union {
1935            base: Box::new(terms.remove(0)),
1936            inputs: terms,
1937        }
1938    }
1939
1940    pub fn exists(self) -> HirScalarExpr {
1941        HirScalarExpr::Exists(Box::new(self), NameMetadata::default())
1942    }
1943
1944    pub fn select(self) -> HirScalarExpr {
1945        HirScalarExpr::Select(Box::new(self), NameMetadata::default())
1946    }
1947
1948    pub fn join(
1949        self,
1950        mut right: HirRelationExpr,
1951        on: HirScalarExpr,
1952        kind: JoinKind,
1953    ) -> HirRelationExpr {
1954        if self.is_join_identity()
1955            && !right.is_correlated()
1956            && on == HirScalarExpr::literal_true()
1957            && kind.can_elide_identity_left_join()
1958        {
1959            // The join can be elided, but we need to adjust column references
1960            // on the right-hand side to account for the removal of the scope
1961            // introduced by the join.
1962            #[allow(deprecated)]
1963            right.visit_columns_mut(0, &mut |depth, col| {
1964                if col.level > depth {
1965                    col.level -= 1;
1966                }
1967            });
1968            right
1969        } else if right.is_join_identity()
1970            && on == HirScalarExpr::literal_true()
1971            && kind.can_elide_identity_right_join()
1972        {
1973            self
1974        } else {
1975            HirRelationExpr::Join {
1976                left: Box::new(self),
1977                right: Box::new(right),
1978                on,
1979                kind,
1980            }
1981        }
1982    }
1983
1984    pub fn take(&mut self) -> HirRelationExpr {
1985        mem::replace(
1986            self,
1987            HirRelationExpr::constant(vec![], SqlRelationType::new(Vec::new())),
1988        )
1989    }
1990
1991    #[deprecated = "Use `Visit::visit_post`."]
1992    pub fn visit<'a, F>(&'a self, depth: usize, f: &mut F)
1993    where
1994        F: FnMut(&'a Self, usize),
1995    {
1996        #[allow(deprecated)]
1997        let _ = self.visit_fallible(depth, &mut |e: &HirRelationExpr,
1998                                                 depth: usize|
1999         -> Result<(), ()> {
2000            f(e, depth);
2001            Ok(())
2002        });
2003    }
2004
2005    #[deprecated = "Use `Visit::try_visit_post`."]
2006    pub fn visit_fallible<'a, F, E>(&'a self, depth: usize, f: &mut F) -> Result<(), E>
2007    where
2008        F: FnMut(&'a Self, usize) -> Result<(), E>,
2009    {
2010        #[allow(deprecated)]
2011        // Grow the stack: this recurses over the relation tree, whose depth is
2012        // user-controlled (e.g. a long JOIN chain or a chain of CTEs).
2013        stack::maybe_grow(|| {
2014            self.visit1(depth, |e: &HirRelationExpr, depth: usize| {
2015                e.visit_fallible(depth, f)
2016            })
2017        })?;
2018        f(self, depth)
2019    }
2020
2021    /// WARNING: `VisitChildren<HirRelationExpr>::try_visit_children` is NOT a
2022    /// drop-in replacement: in addition to the relation children visited here,
2023    /// it also descends into every subquery (`Exists`/`Select`) reachable
2024    /// through `self`'s scalar children — at any depth of scalar nesting.
2025    #[deprecated = "Use `VisitChildren<HirRelationExpr>::try_visit_children` instead."]
2026    pub fn visit1<'a, F, E>(&'a self, depth: usize, mut f: F) -> Result<(), E>
2027    where
2028        F: FnMut(&'a Self, usize) -> Result<(), E>,
2029    {
2030        match self {
2031            HirRelationExpr::Constant { .. }
2032            | HirRelationExpr::Get { .. }
2033            | HirRelationExpr::CallTable { .. } => (),
2034            HirRelationExpr::Let { body, value, .. } => {
2035                f(value, depth)?;
2036                f(body, depth)?;
2037            }
2038            HirRelationExpr::LetRec {
2039                limit: _,
2040                bindings,
2041                body,
2042            } => {
2043                for (_, _, value, _) in bindings.iter() {
2044                    f(value, depth)?;
2045                }
2046                f(body, depth)?;
2047            }
2048            HirRelationExpr::Project { input, .. } => {
2049                f(input, depth)?;
2050            }
2051            HirRelationExpr::Map { input, .. } => {
2052                f(input, depth)?;
2053            }
2054            HirRelationExpr::Filter { input, .. } => {
2055                f(input, depth)?;
2056            }
2057            HirRelationExpr::Join { left, right, .. } => {
2058                f(left, depth)?;
2059                f(right, depth + 1)?;
2060            }
2061            HirRelationExpr::Reduce { input, .. } => {
2062                f(input, depth)?;
2063            }
2064            HirRelationExpr::Distinct { input } => {
2065                f(input, depth)?;
2066            }
2067            HirRelationExpr::TopK { input, .. } => {
2068                f(input, depth)?;
2069            }
2070            HirRelationExpr::Negate { input } => {
2071                f(input, depth)?;
2072            }
2073            HirRelationExpr::Threshold { input } => {
2074                f(input, depth)?;
2075            }
2076            HirRelationExpr::Union { base, inputs } => {
2077                f(base, depth)?;
2078                for input in inputs {
2079                    f(input, depth)?;
2080                }
2081            }
2082        }
2083        Ok(())
2084    }
2085
2086    #[deprecated = "Use `Visit::visit_mut_post` instead."]
2087    pub fn visit_mut<F>(&mut self, depth: usize, f: &mut F)
2088    where
2089        F: FnMut(&mut Self, usize),
2090    {
2091        #[allow(deprecated)]
2092        let _ = self.visit_mut_fallible(depth, &mut |e: &mut HirRelationExpr,
2093                                                     depth: usize|
2094         -> Result<(), ()> {
2095            f(e, depth);
2096            Ok(())
2097        });
2098    }
2099
2100    #[deprecated = "Use `Visit::try_visit_mut_post` instead."]
2101    pub fn visit_mut_fallible<F, E>(&mut self, depth: usize, f: &mut F) -> Result<(), E>
2102    where
2103        F: FnMut(&mut Self, usize) -> Result<(), E>,
2104    {
2105        #[allow(deprecated)]
2106        // Grow the stack: this recurses over the relation tree, whose depth is
2107        // user-controlled (e.g. a long JOIN chain or a chain of CTEs).
2108        stack::maybe_grow(|| {
2109            self.visit1_mut(depth, |e: &mut HirRelationExpr, depth: usize| {
2110                e.visit_mut_fallible(depth, f)
2111            })
2112        })?;
2113        f(self, depth)
2114    }
2115
2116    /// WARNING: `VisitChildren<HirRelationExpr>::try_visit_mut_children` is NOT a
2117    /// drop-in replacement: in addition to the relation children visited here,
2118    /// it also descends into every subquery (`Exists`/`Select`) reachable
2119    /// through `self`'s scalar children — at any depth of scalar nesting.
2120    #[deprecated = "Use `VisitChildren<HirRelationExpr>::try_visit_mut_children` instead."]
2121    pub fn visit1_mut<'a, F, E>(&'a mut self, depth: usize, mut f: F) -> Result<(), E>
2122    where
2123        F: FnMut(&'a mut Self, usize) -> Result<(), E>,
2124    {
2125        match self {
2126            HirRelationExpr::Constant { .. }
2127            | HirRelationExpr::Get { .. }
2128            | HirRelationExpr::CallTable { .. } => (),
2129            HirRelationExpr::Let { body, value, .. } => {
2130                f(value, depth)?;
2131                f(body, depth)?;
2132            }
2133            HirRelationExpr::LetRec {
2134                limit: _,
2135                bindings,
2136                body,
2137            } => {
2138                for (_, _, value, _) in bindings.iter_mut() {
2139                    f(value, depth)?;
2140                }
2141                f(body, depth)?;
2142            }
2143            HirRelationExpr::Project { input, .. } => {
2144                f(input, depth)?;
2145            }
2146            HirRelationExpr::Map { input, .. } => {
2147                f(input, depth)?;
2148            }
2149            HirRelationExpr::Filter { input, .. } => {
2150                f(input, depth)?;
2151            }
2152            HirRelationExpr::Join { left, right, .. } => {
2153                f(left, depth)?;
2154                f(right, depth + 1)?;
2155            }
2156            HirRelationExpr::Reduce { input, .. } => {
2157                f(input, depth)?;
2158            }
2159            HirRelationExpr::Distinct { input } => {
2160                f(input, depth)?;
2161            }
2162            HirRelationExpr::TopK { input, .. } => {
2163                f(input, depth)?;
2164            }
2165            HirRelationExpr::Negate { input } => {
2166                f(input, depth)?;
2167            }
2168            HirRelationExpr::Threshold { input } => {
2169                f(input, depth)?;
2170            }
2171            HirRelationExpr::Union { base, inputs } => {
2172                f(base, depth)?;
2173                for input in inputs {
2174                    f(input, depth)?;
2175                }
2176            }
2177        }
2178        Ok(())
2179    }
2180
2181    #[deprecated = "Use a combination of `Visit` and `VisitChildren` methods."]
2182    /// Visits all scalar expressions directly held by relation nodes within the sub-tree of `self`.
2183    ///
2184    /// Note: this does NOT descend into subqueries that may appear inside the visited
2185    /// `HirScalarExpr`s (i.e., `HirScalarExpr::Exists` / `HirScalarExpr::Select`). The closure
2186    /// `f` is invoked once per top-level scalar expression attached to a relation node, and it
2187    /// is the closure's responsibility to recurse into any subqueries if desired.
2188    ///
2189    /// The `depth` argument is just a seed: it is the value passed to `f` for scalar expressions
2190    /// at the root of `self`, and it is incremented by 1 when descending into the RHS of a
2191    /// `Join` node (the only place this function increments it). It does NOT control or limit
2192    /// recursion; passing `0` is the usual choice.
2193    pub fn visit_scalar_expressions<F, E>(&self, depth: usize, f: &mut F) -> Result<(), E>
2194    where
2195        F: FnMut(&HirScalarExpr, usize) -> Result<(), E>,
2196    {
2197        #[allow(deprecated)]
2198        self.visit_fallible(depth, &mut |e: &HirRelationExpr,
2199                                         depth: usize|
2200         -> Result<(), E> {
2201            match e {
2202                HirRelationExpr::Join { on, .. } => {
2203                    f(on, depth)?;
2204                }
2205                HirRelationExpr::Map { scalars, .. } => {
2206                    for scalar in scalars {
2207                        f(scalar, depth)?;
2208                    }
2209                }
2210                HirRelationExpr::CallTable { exprs, .. } => {
2211                    for expr in exprs {
2212                        f(expr, depth)?;
2213                    }
2214                }
2215                HirRelationExpr::Filter { predicates, .. } => {
2216                    for predicate in predicates {
2217                        f(predicate, depth)?;
2218                    }
2219                }
2220                HirRelationExpr::Reduce { aggregates, .. } => {
2221                    for aggregate in aggregates {
2222                        f(&aggregate.expr, depth)?;
2223                    }
2224                }
2225                HirRelationExpr::TopK { limit, offset, .. } => {
2226                    if let Some(limit) = limit {
2227                        f(limit, depth)?;
2228                    }
2229                    f(offset, depth)?;
2230                }
2231                HirRelationExpr::Union { .. }
2232                | HirRelationExpr::Let { .. }
2233                | HirRelationExpr::LetRec { .. }
2234                | HirRelationExpr::Project { .. }
2235                | HirRelationExpr::Distinct { .. }
2236                | HirRelationExpr::Negate { .. }
2237                | HirRelationExpr::Threshold { .. }
2238                | HirRelationExpr::Constant { .. }
2239                | HirRelationExpr::Get { .. } => (),
2240            }
2241            Ok(())
2242        })
2243    }
2244
2245    #[deprecated = "Use a combination of `Visit` and `VisitChildren` methods."]
2246    /// Like `visit_scalar_expressions`, but permits mutating the expressions.
2247    ///
2248    /// In particular, this also does NOT descend into subqueries inside the visited scalar
2249    /// expressions, and `depth` is just a seed for the value passed to `f` (see
2250    /// [`HirRelationExpr::visit_scalar_expressions`]).
2251    pub fn visit_scalar_expressions_mut<F, E>(&mut self, depth: usize, f: &mut F) -> Result<(), E>
2252    where
2253        F: FnMut(&mut HirScalarExpr, usize) -> Result<(), E>,
2254    {
2255        #[allow(deprecated)]
2256        self.visit_mut_fallible(depth, &mut |e: &mut HirRelationExpr,
2257                                             depth: usize|
2258         -> Result<(), E> {
2259            match e {
2260                HirRelationExpr::Join { on, .. } => {
2261                    f(on, depth)?;
2262                }
2263                HirRelationExpr::Map { scalars, .. } => {
2264                    for scalar in scalars.iter_mut() {
2265                        f(scalar, depth)?;
2266                    }
2267                }
2268                HirRelationExpr::CallTable { exprs, .. } => {
2269                    for expr in exprs.iter_mut() {
2270                        f(expr, depth)?;
2271                    }
2272                }
2273                HirRelationExpr::Filter { predicates, .. } => {
2274                    for predicate in predicates.iter_mut() {
2275                        f(predicate, depth)?;
2276                    }
2277                }
2278                HirRelationExpr::Reduce { aggregates, .. } => {
2279                    for aggregate in aggregates.iter_mut() {
2280                        f(&mut aggregate.expr, depth)?;
2281                    }
2282                }
2283                HirRelationExpr::TopK { limit, offset, .. } => {
2284                    if let Some(limit) = limit {
2285                        f(limit, depth)?;
2286                    }
2287                    f(offset, depth)?;
2288                }
2289                HirRelationExpr::Union { .. }
2290                | HirRelationExpr::Let { .. }
2291                | HirRelationExpr::LetRec { .. }
2292                | HirRelationExpr::Project { .. }
2293                | HirRelationExpr::Distinct { .. }
2294                | HirRelationExpr::Negate { .. }
2295                | HirRelationExpr::Threshold { .. }
2296                | HirRelationExpr::Constant { .. }
2297                | HirRelationExpr::Get { .. } => (),
2298            }
2299            Ok(())
2300        })
2301    }
2302
2303    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
2304    /// Visits the column references in this relation expression.
2305    ///
2306    /// The `depth` argument should indicate the subquery nesting depth of the expression,
2307    /// which will be incremented when entering the RHS of a join or a subquery and
2308    /// presented to the supplied function `f`.
2309    pub fn visit_columns<F>(&self, depth: usize, f: &mut F)
2310    where
2311        F: FnMut(usize, &ColumnRef),
2312    {
2313        #[allow(deprecated)]
2314        let _ = self.visit_scalar_expressions(depth, &mut |e: &HirScalarExpr,
2315                                                           depth: usize|
2316         -> Result<(), ()> {
2317            e.visit_columns(depth, f);
2318            Ok(())
2319        });
2320    }
2321
2322    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
2323    /// Like `visit_columns`, but permits mutating the column references.
2324    pub fn visit_columns_mut<F>(&mut self, depth: usize, f: &mut F)
2325    where
2326        F: FnMut(usize, &mut ColumnRef),
2327    {
2328        #[allow(deprecated)]
2329        let _ = self.visit_scalar_expressions_mut(depth, &mut |e: &mut HirScalarExpr,
2330                                                               depth: usize|
2331         -> Result<(), ()> {
2332            e.visit_columns_mut(depth, f);
2333            Ok(())
2334        });
2335    }
2336
2337    /// Replaces parameter references in the expression with the corresponding datum from `params`.
2338    /// Additionally, it simplifies OFFSET clauses to constants after parameter binding, and checks
2339    /// them for non-negativity.
2340    ///
2341    /// This walks the entire `HirRelationExpr` tree, including subqueries nested inside scalar
2342    /// expressions: `visit_scalar_expressions_mut` covers the scalar expressions held directly
2343    /// by relation nodes, and the corecursive call into
2344    /// [`HirScalarExpr::bind_parameters_and_simplify_offset`] (made by the closure below) is
2345    /// what descends into subqueries occurring inside those scalar expressions.
2346    pub fn bind_parameters_and_simplify_offset(
2347        &mut self,
2348        scx: &StatementContext,
2349        lifetime: QueryLifetime,
2350        params: &Params,
2351    ) -> Result<(), PlanError> {
2352        #[allow(deprecated)]
2353        self.visit_scalar_expressions_mut(0, &mut |e: &mut HirScalarExpr, _: usize| {
2354            e.bind_parameters_and_simplify_offset(scx, lifetime, params)
2355        })?;
2356
2357        // OFFSET clauses in `expr` should become constants with the above binding of parameters.
2358        // Let's check this and simplify them to literals.
2359        self.try_visit_mut_pre(&mut |expr| {
2360            if let HirRelationExpr::TopK { offset, .. } = expr {
2361                let offset_value = offset_into_value(offset.take())?;
2362                *offset = HirScalarExpr::literal(Datum::Int64(offset_value), SqlScalarType::Int64);
2363            }
2364            Ok::<(), PlanError>(())
2365        })
2366        // (We don't need to simplify LIMIT clauses in `expr`, because we can handle non-constant
2367        // expressions there. If they happen to be simplifiable to literals, then the optimizer will do
2368        // so later.)
2369    }
2370
2371    pub fn contains_parameters(&self) -> Result<bool, PlanError> {
2372        let mut contains_parameters = false;
2373        #[allow(deprecated)]
2374        self.visit_scalar_expressions(0, &mut |e: &HirScalarExpr, _: usize| {
2375            if e.contains_parameters() {
2376                contains_parameters = true;
2377            }
2378            Ok::<(), PlanError>(())
2379        })?;
2380        Ok(contains_parameters)
2381    }
2382
2383    /// See the documentation for [`HirScalarExpr::splice_parameters`].
2384    pub fn splice_parameters(&mut self, params: &[HirScalarExpr], depth: usize) {
2385        #[allow(deprecated)]
2386        let _ = self.visit_scalar_expressions_mut(depth, &mut |e: &mut HirScalarExpr,
2387                                                               depth: usize|
2388         -> Result<(), ()> {
2389            e.splice_parameters(params, depth);
2390            Ok(())
2391        });
2392    }
2393
2394    /// Constructs a constant collection from specific rows and schema.
2395    pub fn constant(rows: Vec<Vec<Datum>>, typ: SqlRelationType) -> Self {
2396        let rows = rows
2397            .into_iter()
2398            .map(move |datums| Row::pack_slice(&datums))
2399            .collect();
2400        HirRelationExpr::Constant { rows, typ }
2401    }
2402
2403    /// A `RowSetFinishing` can only be directly applied to the result of a one-shot select.
2404    /// This function is concerned with maintained queries, e.g., an index or materialized view.
2405    /// Instead of directly applying the given `RowSetFinishing`, it converts the `RowSetFinishing`
2406    /// to a `TopK`, which it then places at the top of `self`. Additionally, it turns the given
2407    /// finishing into a trivial finishing.
2408    pub fn finish_maintained(
2409        &mut self,
2410        finishing: &mut RowSetFinishing<HirScalarExpr, HirScalarExpr>,
2411        group_size_hints: GroupSizeHints,
2412    ) {
2413        if !HirRelationExpr::is_trivial_row_set_finishing_hir(finishing, self.arity()) {
2414            let old_finishing = mem::replace(
2415                finishing,
2416                HirRelationExpr::trivial_row_set_finishing_hir(finishing.project.len()),
2417            );
2418            *self = HirRelationExpr::top_k(
2419                std::mem::replace(
2420                    self,
2421                    HirRelationExpr::Constant {
2422                        rows: vec![],
2423                        typ: SqlRelationType::new(Vec::new()),
2424                    },
2425                ),
2426                vec![],
2427                old_finishing.order_by,
2428                old_finishing.limit,
2429                old_finishing.offset,
2430                group_size_hints.limit_input_group_size,
2431            )
2432            .project(old_finishing.project);
2433        }
2434    }
2435
2436    /// Returns a trivial finishing, i.e., that does nothing to the result set.
2437    ///
2438    /// (There is also `RowSetFinishing::trivial`, but that is specialized for when the O generic
2439    /// parameter is not an HirScalarExpr anymore.)
2440    pub fn trivial_row_set_finishing_hir(
2441        arity: usize,
2442    ) -> RowSetFinishing<HirScalarExpr, HirScalarExpr> {
2443        RowSetFinishing {
2444            order_by: Vec::new(),
2445            limit: None,
2446            offset: HirScalarExpr::literal(Datum::Int64(0), SqlScalarType::Int64),
2447            project: (0..arity).collect(),
2448        }
2449    }
2450
2451    /// True if the finishing does nothing to any result set.
2452    ///
2453    /// (There is also `RowSetFinishing::is_trivial`, but that is specialized for when the O generic
2454    /// parameter is not an HirScalarExpr anymore.)
2455    pub fn is_trivial_row_set_finishing_hir(
2456        rsf: &RowSetFinishing<HirScalarExpr, HirScalarExpr>,
2457        arity: usize,
2458    ) -> bool {
2459        rsf.limit.is_none()
2460            && rsf.order_by.is_empty()
2461            && rsf
2462                .offset
2463                .clone()
2464                .try_into_literal_int64()
2465                .is_ok_and(|o| o == 0)
2466            && rsf.project.iter().copied().eq(0..arity)
2467    }
2468
2469    /// The HirRelationExpr is considered potentially expensive if and only if
2470    /// at least one of the following conditions is true:
2471    ///
2472    ///  - It contains at least one HirScalarExpr with a function call.
2473    ///  - It contains at least one CallTable or a Reduce operator.
2474    ///  - We run into a RecursionLimitError while analyzing the expression.
2475    ///
2476    /// !!!WARNING!!!: this method has an MirRelationExpr counterpart. The two
2477    /// should be kept in sync w.r.t. HIR ⇒ MIR lowering!
2478    pub fn could_run_expensive_function(&self) -> bool {
2479        let mut result = false;
2480        self.visit_pre(&mut |e: &HirRelationExpr| {
2481            use HirRelationExpr::*;
2482            use HirScalarExpr::*;
2483
2484            e.visit_children(|scalar: &HirScalarExpr| {
2485                scalar.visit_pre(&mut |scalar: &HirScalarExpr| {
2486                    result |= match scalar {
2487                        Column(..)
2488                        | Literal(..)
2489                        | CallUnmaterializable(..)
2490                        | If { .. }
2491                        | Parameter(..)
2492                        | Select(..)
2493                        | Exists(..) => false,
2494                        // Function calls are considered expensive
2495                        CallUnary { .. }
2496                        | CallBinary { .. }
2497                        | CallVariadic { .. }
2498                        | Windowing(..) => true,
2499                    };
2500                })
2501            });
2502
2503            // CallTable has a table function; Reduce has an aggregate function.
2504            // Other constructs use MirScalarExpr to run a function
2505            result |= matches!(e, CallTable { .. } | Reduce { .. });
2506        });
2507
2508        result
2509    }
2510
2511    /// Whether the expression contains an [`UnmaterializableFunc::MzNow`] call.
2512    pub fn contains_temporal(&self) -> bool {
2513        let mut contains = false;
2514        self.visit_post(&mut |expr| {
2515            expr.visit_children(|expr: &HirScalarExpr| {
2516                contains = contains || expr.contains_temporal()
2517            })
2518        });
2519        contains
2520    }
2521
2522    /// Whether the expression contains any [`UnmaterializableFunc`] call.
2523    pub fn contains_unmaterializable(&self) -> bool {
2524        let mut contains = false;
2525        self.visit_post(&mut |expr| {
2526            expr.visit_children(|expr: &HirScalarExpr| {
2527                contains = contains || expr.contains_unmaterializable()
2528            })
2529        });
2530        contains
2531    }
2532
2533    /// Whether the expression contains any [`UnmaterializableFunc`] call other than
2534    /// [`UnmaterializableFunc::MzNow`].
2535    pub fn contains_unmaterializable_except_temporal(&self) -> bool {
2536        let mut contains = false;
2537        self.visit_post(&mut |expr| {
2538            expr.visit_children(|expr: &HirScalarExpr| {
2539                contains = contains || expr.contains_unmaterializable_except_temporal()
2540            })
2541        });
2542        contains
2543    }
2544}
2545
2546impl CollectionPlan for HirRelationExpr {
2547    /// Collects the global collections that this HIR expression directly depends on, i.e., that it
2548    /// has a `Get` for. (It does _not_ traverse view definitions transitively.)
2549    /// (It does explore inside subqueries.)
2550    ///
2551    /// !!!WARNING!!!: this method has an MirRelationExpr counterpart. The two
2552    /// should be kept in sync w.r.t. HIR ⇒ MIR lowering!
2553    fn depends_on_into(&self, out: &mut BTreeSet<GlobalId>) {
2554        if let Self::Get {
2555            id: Id::Global(id), ..
2556        } = self
2557        {
2558            out.insert(*id);
2559        }
2560        self.visit_children(|expr: &HirRelationExpr| expr.depends_on_into(out))
2561    }
2562}
2563
2564/// In addition to direct relation children of `self`, this also yields every
2565/// subquery (`Exists` / `Select`) reachable through `self`'s scalar children,
2566/// at any depth of scalar nesting. This is the asymmetry warned about on the
2567/// [`VisitChildren`] trait; the matching impl on `HirScalarExpr` deliberately
2568/// does not do the symmetric thing, to avoid mutual recursion.
2569impl VisitChildren<Self> for HirRelationExpr {
2570    fn visit_children<F>(&self, mut f: F)
2571    where
2572        F: FnMut(&Self),
2573    {
2574        // subqueries of type HirRelationExpr might be wrapped in
2575        // Exists or Select variants within HirScalarExpr trees
2576        // attached at the current node, and we want to visit them as well
2577        VisitChildren::visit_children(self, |expr: &HirScalarExpr| {
2578            expr.visit_direct_subqueries(&mut f);
2579        });
2580
2581        use HirRelationExpr::*;
2582        match self {
2583            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2584            Let {
2585                name: _,
2586                id: _,
2587                value,
2588                body,
2589            } => {
2590                f(value);
2591                f(body);
2592            }
2593            LetRec {
2594                limit: _,
2595                bindings,
2596                body,
2597            } => {
2598                for (_, _, value, _) in bindings.iter() {
2599                    f(value);
2600                }
2601                f(body);
2602            }
2603            Project { input, outputs: _ } => f(input),
2604            Map { input, scalars: _ } => {
2605                f(input);
2606            }
2607            CallTable { func: _, exprs: _ } => (),
2608            Filter {
2609                input,
2610                predicates: _,
2611            } => {
2612                f(input);
2613            }
2614            Join {
2615                left,
2616                right,
2617                on: _,
2618                kind: _,
2619            } => {
2620                f(left);
2621                f(right);
2622            }
2623            Reduce {
2624                input,
2625                group_key: _,
2626                aggregates: _,
2627                expected_group_size: _,
2628            } => {
2629                f(input);
2630            }
2631            Distinct { input }
2632            | TopK {
2633                input,
2634                group_key: _,
2635                order_key: _,
2636                limit: _,
2637                offset: _,
2638                expected_group_size: _,
2639            }
2640            | Negate { input }
2641            | Threshold { input } => {
2642                f(input);
2643            }
2644            Union { base, inputs } => {
2645                f(base);
2646                for input in inputs {
2647                    f(input);
2648                }
2649            }
2650        }
2651    }
2652
2653    fn visit_mut_children<F>(&mut self, mut f: F)
2654    where
2655        F: FnMut(&mut Self),
2656    {
2657        // subqueries of type HirRelationExpr might be wrapped in
2658        // Exists or Select variants within HirScalarExpr trees
2659        // attached at the current node, and we want to visit them as well
2660        VisitChildren::visit_mut_children(self, |expr: &mut HirScalarExpr| {
2661            expr.visit_direct_subqueries_mut(&mut f);
2662        });
2663
2664        use HirRelationExpr::*;
2665        match self {
2666            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2667            Let {
2668                name: _,
2669                id: _,
2670                value,
2671                body,
2672            } => {
2673                f(value);
2674                f(body);
2675            }
2676            LetRec {
2677                limit: _,
2678                bindings,
2679                body,
2680            } => {
2681                for (_, _, value, _) in bindings.iter_mut() {
2682                    f(value);
2683                }
2684                f(body);
2685            }
2686            Project { input, outputs: _ } => f(input),
2687            Map { input, scalars: _ } => {
2688                f(input);
2689            }
2690            CallTable { func: _, exprs: _ } => (),
2691            Filter {
2692                input,
2693                predicates: _,
2694            } => {
2695                f(input);
2696            }
2697            Join {
2698                left,
2699                right,
2700                on: _,
2701                kind: _,
2702            } => {
2703                f(left);
2704                f(right);
2705            }
2706            Reduce {
2707                input,
2708                group_key: _,
2709                aggregates: _,
2710                expected_group_size: _,
2711            } => {
2712                f(input);
2713            }
2714            Distinct { input }
2715            | TopK {
2716                input,
2717                group_key: _,
2718                order_key: _,
2719                limit: _,
2720                offset: _,
2721                expected_group_size: _,
2722            }
2723            | Negate { input }
2724            | Threshold { input } => {
2725                f(input);
2726            }
2727            Union { base, inputs } => {
2728                f(base);
2729                for input in inputs {
2730                    f(input);
2731                }
2732            }
2733        }
2734    }
2735
2736    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
2737    where
2738        F: FnMut(&Self) -> Result<(), E>,
2739    {
2740        // subqueries of type HirRelationExpr might be wrapped in
2741        // Exists or Select variants within HirScalarExpr trees
2742        // attached at the current node, and we want to visit them as well
2743        VisitChildren::try_visit_children(self, |expr: &HirScalarExpr| {
2744            expr.try_visit_direct_subqueries(&mut f)
2745        })?;
2746
2747        use HirRelationExpr::*;
2748        match self {
2749            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2750            Let {
2751                name: _,
2752                id: _,
2753                value,
2754                body,
2755            } => {
2756                f(value)?;
2757                f(body)?;
2758            }
2759            LetRec {
2760                limit: _,
2761                bindings,
2762                body,
2763            } => {
2764                for (_, _, value, _) in bindings.iter() {
2765                    f(value)?;
2766                }
2767                f(body)?;
2768            }
2769            Project { input, outputs: _ } => f(input)?,
2770            Map { input, scalars: _ } => {
2771                f(input)?;
2772            }
2773            CallTable { func: _, exprs: _ } => (),
2774            Filter {
2775                input,
2776                predicates: _,
2777            } => {
2778                f(input)?;
2779            }
2780            Join {
2781                left,
2782                right,
2783                on: _,
2784                kind: _,
2785            } => {
2786                f(left)?;
2787                f(right)?;
2788            }
2789            Reduce {
2790                input,
2791                group_key: _,
2792                aggregates: _,
2793                expected_group_size: _,
2794            } => {
2795                f(input)?;
2796            }
2797            Distinct { input }
2798            | TopK {
2799                input,
2800                group_key: _,
2801                order_key: _,
2802                limit: _,
2803                offset: _,
2804                expected_group_size: _,
2805            }
2806            | Negate { input }
2807            | Threshold { input } => {
2808                f(input)?;
2809            }
2810            Union { base, inputs } => {
2811                f(base)?;
2812                for input in inputs {
2813                    f(input)?;
2814                }
2815            }
2816        }
2817        Ok(())
2818    }
2819
2820    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
2821    where
2822        F: FnMut(&mut Self) -> Result<(), E>,
2823    {
2824        // subqueries of type HirRelationExpr might be wrapped in
2825        // Exists or Select variants within HirScalarExpr trees
2826        // attached at the current node, and we want to visit them as well
2827        VisitChildren::try_visit_mut_children(self, |expr: &mut HirScalarExpr| {
2828            expr.try_visit_direct_subqueries_mut(&mut f)
2829        })?;
2830
2831        use HirRelationExpr::*;
2832        match self {
2833            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2834            Let {
2835                name: _,
2836                id: _,
2837                value,
2838                body,
2839            } => {
2840                f(value)?;
2841                f(body)?;
2842            }
2843            LetRec {
2844                limit: _,
2845                bindings,
2846                body,
2847            } => {
2848                for (_, _, value, _) in bindings.iter_mut() {
2849                    f(value)?;
2850                }
2851                f(body)?;
2852            }
2853            Project { input, outputs: _ } => f(input)?,
2854            Map { input, scalars: _ } => {
2855                f(input)?;
2856            }
2857            CallTable { func: _, exprs: _ } => (),
2858            Filter {
2859                input,
2860                predicates: _,
2861            } => {
2862                f(input)?;
2863            }
2864            Join {
2865                left,
2866                right,
2867                on: _,
2868                kind: _,
2869            } => {
2870                f(left)?;
2871                f(right)?;
2872            }
2873            Reduce {
2874                input,
2875                group_key: _,
2876                aggregates: _,
2877                expected_group_size: _,
2878            } => {
2879                f(input)?;
2880            }
2881            Distinct { input }
2882            | TopK {
2883                input,
2884                group_key: _,
2885                order_key: _,
2886                limit: _,
2887                offset: _,
2888                expected_group_size: _,
2889            }
2890            | Negate { input }
2891            | Threshold { input } => {
2892                f(input)?;
2893            }
2894            Union { base, inputs } => {
2895                f(base)?;
2896                for input in inputs {
2897                    f(input)?;
2898                }
2899            }
2900        }
2901        Ok(())
2902    }
2903
2904    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a Self>
2905    where
2906        Self: 'a,
2907    {
2908        // we visit subqueries _first_, then the input
2909        let mut v: Vec<&HirRelationExpr> = vec![];
2910        use HirRelationExpr::*;
2911        match self {
2912            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2913            Let {
2914                name: _,
2915                id: _,
2916                value,
2917                body,
2918            } => {
2919                v.push(&*value);
2920                v.push(&*body);
2921            }
2922            LetRec {
2923                limit: _,
2924                bindings,
2925                body,
2926            } => {
2927                v.extend(bindings.iter().map(|(_, _, value, _)| value));
2928                v.push(&*body);
2929            }
2930            Map { input, scalars }
2931            | Filter {
2932                input,
2933                predicates: scalars,
2934            } => {
2935                for scalar in scalars {
2936                    v.append(&mut scalar.direct_subqueries());
2937                }
2938                v.push(&*input);
2939            }
2940            Reduce {
2941                input,
2942                group_key: _,
2943                aggregates,
2944                expected_group_size: _,
2945            } => {
2946                for agg in aggregates {
2947                    v.append(&mut agg.expr.direct_subqueries());
2948                }
2949                v.push(&*input);
2950            }
2951            TopK {
2952                input,
2953                group_key: _,
2954                order_key: _,
2955                limit,
2956                offset,
2957                expected_group_size: _,
2958            } => {
2959                if let Some(limit) = limit {
2960                    v.append(&mut limit.direct_subqueries());
2961                }
2962                v.append(&mut offset.direct_subqueries());
2963                v.push(&*input);
2964            }
2965            Project { input, outputs: _ }
2966            | Distinct { input }
2967            | Negate { input }
2968            | Threshold { input } => v.push(&*input),
2969            CallTable { func: _, exprs } => v.extend(
2970                exprs
2971                    .iter()
2972                    .map(|scalar| scalar.direct_subqueries())
2973                    .flatten(),
2974            ),
2975            Join {
2976                left,
2977                right,
2978                on,
2979                kind: _,
2980            } => {
2981                v.append(&mut on.direct_subqueries());
2982                v.push(&*left);
2983                v.push(&*right);
2984            }
2985            Union { base, inputs } => {
2986                v.push(&*base);
2987                v.extend(inputs.iter());
2988            }
2989        }
2990
2991        v.into_iter()
2992    }
2993
2994    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut Self>
2995    where
2996        Self: 'a,
2997    {
2998        // we visit subqueries _first_, then the input
2999        let mut v = vec![];
3000        use HirRelationExpr::*;
3001        match self {
3002            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
3003            Let {
3004                name: _,
3005                id: _,
3006                value,
3007                body,
3008            } => {
3009                v.push(&mut **value);
3010                v.push(&mut **body);
3011            }
3012            LetRec {
3013                limit: _,
3014                bindings,
3015                body,
3016            } => {
3017                v.extend(bindings.iter_mut().map(|(_, _, value, _)| value));
3018                v.push(&mut **body);
3019            }
3020            Map { input, scalars }
3021            | Filter {
3022                input,
3023                predicates: scalars,
3024            } => {
3025                for scalar in scalars {
3026                    v.append(&mut scalar.direct_subqueries_mut());
3027                }
3028                v.push(&mut **input);
3029            }
3030            Reduce {
3031                input,
3032                group_key: _,
3033                aggregates,
3034                expected_group_size: _,
3035            } => {
3036                for agg in aggregates {
3037                    v.append(&mut agg.expr.direct_subqueries_mut());
3038                }
3039                v.push(&mut **input);
3040            }
3041            TopK {
3042                input,
3043                group_key: _,
3044                order_key: _,
3045                limit,
3046                offset,
3047                expected_group_size: _,
3048            } => {
3049                if let Some(limit) = limit {
3050                    v.append(&mut limit.direct_subqueries_mut());
3051                }
3052                v.append(&mut offset.direct_subqueries_mut());
3053                v.push(&mut **input);
3054            }
3055            Project { input, outputs: _ }
3056            | Distinct { input }
3057            | Negate { input }
3058            | Threshold { input } => v.push(&mut **input),
3059            CallTable { func: _, exprs } => v.extend(
3060                exprs
3061                    .iter_mut()
3062                    .map(|scalar| scalar.direct_subqueries_mut())
3063                    .flatten(),
3064            ),
3065            Join {
3066                left,
3067                right,
3068                on,
3069                kind: _,
3070            } => {
3071                v.append(&mut on.direct_subqueries_mut());
3072                v.push(&mut **left);
3073                v.push(&mut **right);
3074            }
3075            Union { base, inputs } => {
3076                v.push(&mut **base);
3077                v.extend(inputs.iter_mut());
3078            }
3079        }
3080
3081        v.into_iter()
3082    }
3083}
3084
3085/// Yields the scalars directly attached to relation nodes (e.g. `Map.scalars`,
3086/// `Filter.predicates`, `Join.on`, `Reduce` aggregate args, `TopK.{limit,
3087/// offset}`, `CallTable.exprs`); does not descend into them.
3088impl VisitChildren<HirScalarExpr> for HirRelationExpr {
3089    fn visit_children<F>(&self, mut f: F)
3090    where
3091        F: FnMut(&HirScalarExpr),
3092    {
3093        use HirRelationExpr::*;
3094        match self {
3095            Constant { rows: _, typ: _ }
3096            | Get { id: _, typ: _ }
3097            | Let {
3098                name: _,
3099                id: _,
3100                value: _,
3101                body: _,
3102            }
3103            | LetRec {
3104                limit: _,
3105                bindings: _,
3106                body: _,
3107            }
3108            | Project {
3109                input: _,
3110                outputs: _,
3111            } => (),
3112            Map { input: _, scalars } => {
3113                for scalar in scalars {
3114                    f(scalar);
3115                }
3116            }
3117            CallTable { func: _, exprs } => {
3118                for expr in exprs {
3119                    f(expr);
3120                }
3121            }
3122            Filter {
3123                input: _,
3124                predicates,
3125            } => {
3126                for predicate in predicates {
3127                    f(predicate);
3128                }
3129            }
3130            Join {
3131                left: _,
3132                right: _,
3133                on,
3134                kind: _,
3135            } => f(on),
3136            Reduce {
3137                input: _,
3138                group_key: _,
3139                aggregates,
3140                expected_group_size: _,
3141            } => {
3142                for aggregate in aggregates {
3143                    f(aggregate.expr.as_ref());
3144                }
3145            }
3146            TopK {
3147                input: _,
3148                group_key: _,
3149                order_key: _,
3150                limit,
3151                offset,
3152                expected_group_size: _,
3153            } => {
3154                if let Some(limit) = limit {
3155                    f(limit)
3156                }
3157                f(offset)
3158            }
3159            Distinct { input: _ }
3160            | Negate { input: _ }
3161            | Threshold { input: _ }
3162            | Union { base: _, inputs: _ } => (),
3163        }
3164    }
3165
3166    fn visit_mut_children<F>(&mut self, mut f: F)
3167    where
3168        F: FnMut(&mut HirScalarExpr),
3169    {
3170        use HirRelationExpr::*;
3171        match self {
3172            Constant { rows: _, typ: _ }
3173            | Get { id: _, typ: _ }
3174            | Let {
3175                name: _,
3176                id: _,
3177                value: _,
3178                body: _,
3179            }
3180            | LetRec {
3181                limit: _,
3182                bindings: _,
3183                body: _,
3184            }
3185            | Project {
3186                input: _,
3187                outputs: _,
3188            } => (),
3189            Map { input: _, scalars } => {
3190                for scalar in scalars {
3191                    f(scalar);
3192                }
3193            }
3194            CallTable { func: _, exprs } => {
3195                for expr in exprs {
3196                    f(expr);
3197                }
3198            }
3199            Filter {
3200                input: _,
3201                predicates,
3202            } => {
3203                for predicate in predicates {
3204                    f(predicate);
3205                }
3206            }
3207            Join {
3208                left: _,
3209                right: _,
3210                on,
3211                kind: _,
3212            } => f(on),
3213            Reduce {
3214                input: _,
3215                group_key: _,
3216                aggregates,
3217                expected_group_size: _,
3218            } => {
3219                for aggregate in aggregates {
3220                    f(aggregate.expr.as_mut());
3221                }
3222            }
3223            TopK {
3224                input: _,
3225                group_key: _,
3226                order_key: _,
3227                limit,
3228                offset,
3229                expected_group_size: _,
3230            } => {
3231                if let Some(limit) = limit {
3232                    f(limit)
3233                }
3234                f(offset)
3235            }
3236            Distinct { input: _ }
3237            | Negate { input: _ }
3238            | Threshold { input: _ }
3239            | Union { base: _, inputs: _ } => (),
3240        }
3241    }
3242
3243    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
3244    where
3245        F: FnMut(&HirScalarExpr) -> Result<(), E>,
3246    {
3247        use HirRelationExpr::*;
3248        match self {
3249            Constant { rows: _, typ: _ }
3250            | Get { id: _, typ: _ }
3251            | Let {
3252                name: _,
3253                id: _,
3254                value: _,
3255                body: _,
3256            }
3257            | LetRec {
3258                limit: _,
3259                bindings: _,
3260                body: _,
3261            }
3262            | Project {
3263                input: _,
3264                outputs: _,
3265            } => (),
3266            Map { input: _, scalars } => {
3267                for scalar in scalars {
3268                    f(scalar)?;
3269                }
3270            }
3271            CallTable { func: _, exprs } => {
3272                for expr in exprs {
3273                    f(expr)?;
3274                }
3275            }
3276            Filter {
3277                input: _,
3278                predicates,
3279            } => {
3280                for predicate in predicates {
3281                    f(predicate)?;
3282                }
3283            }
3284            Join {
3285                left: _,
3286                right: _,
3287                on,
3288                kind: _,
3289            } => f(on)?,
3290            Reduce {
3291                input: _,
3292                group_key: _,
3293                aggregates,
3294                expected_group_size: _,
3295            } => {
3296                for aggregate in aggregates {
3297                    f(aggregate.expr.as_ref())?;
3298                }
3299            }
3300            TopK {
3301                input: _,
3302                group_key: _,
3303                order_key: _,
3304                limit,
3305                offset,
3306                expected_group_size: _,
3307            } => {
3308                if let Some(limit) = limit {
3309                    f(limit)?
3310                }
3311                f(offset)?
3312            }
3313            Distinct { input: _ }
3314            | Negate { input: _ }
3315            | Threshold { input: _ }
3316            | Union { base: _, inputs: _ } => (),
3317        }
3318        Ok(())
3319    }
3320
3321    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
3322    where
3323        F: FnMut(&mut HirScalarExpr) -> Result<(), E>,
3324    {
3325        use HirRelationExpr::*;
3326        match self {
3327            Constant { rows: _, typ: _ }
3328            | Get { id: _, typ: _ }
3329            | Let {
3330                name: _,
3331                id: _,
3332                value: _,
3333                body: _,
3334            }
3335            | LetRec {
3336                limit: _,
3337                bindings: _,
3338                body: _,
3339            }
3340            | Project {
3341                input: _,
3342                outputs: _,
3343            } => (),
3344            Map { input: _, scalars } => {
3345                for scalar in scalars {
3346                    f(scalar)?;
3347                }
3348            }
3349            CallTable { func: _, exprs } => {
3350                for expr in exprs {
3351                    f(expr)?;
3352                }
3353            }
3354            Filter {
3355                input: _,
3356                predicates,
3357            } => {
3358                for predicate in predicates {
3359                    f(predicate)?;
3360                }
3361            }
3362            Join {
3363                left: _,
3364                right: _,
3365                on,
3366                kind: _,
3367            } => f(on)?,
3368            Reduce {
3369                input: _,
3370                group_key: _,
3371                aggregates,
3372                expected_group_size: _,
3373            } => {
3374                for aggregate in aggregates {
3375                    f(aggregate.expr.as_mut())?;
3376                }
3377            }
3378            TopK {
3379                input: _,
3380                group_key: _,
3381                order_key: _,
3382                limit,
3383                offset,
3384                expected_group_size: _,
3385            } => {
3386                if let Some(limit) = limit {
3387                    f(limit)?
3388                }
3389                f(offset)?
3390            }
3391            Distinct { input: _ }
3392            | Negate { input: _ }
3393            | Threshold { input: _ }
3394            | Union { base: _, inputs: _ } => (),
3395        }
3396        Ok(())
3397    }
3398
3399    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a HirScalarExpr>
3400    where
3401        HirScalarExpr: 'a,
3402    {
3403        use HirRelationExpr::*;
3404        match self {
3405            Constant { rows: _, typ: _ }
3406            | Get { id: _, typ: _ }
3407            | Let {
3408                name: _,
3409                id: _,
3410                value: _,
3411                body: _,
3412            }
3413            | LetRec {
3414                limit: _,
3415                bindings: _,
3416                body: _,
3417            }
3418            | Project {
3419                input: _,
3420                outputs: _,
3421            }
3422            | Distinct { input: _ }
3423            | Negate { input: _ }
3424            | Threshold { input: _ }
3425            | Union { base: _, inputs: _ } => vec![],
3426            Map { input: _, scalars }
3427            | CallTable {
3428                func: _,
3429                exprs: scalars,
3430            }
3431            | Filter {
3432                input: _,
3433                predicates: scalars,
3434            } => scalars.iter().collect(),
3435            Join {
3436                left: _,
3437                right: _,
3438                on,
3439                kind: _,
3440            } => vec![on],
3441            Reduce {
3442                input: _,
3443                group_key: _,
3444                aggregates,
3445                expected_group_size: _,
3446            } => aggregates.iter().map(|agg| &*agg.expr).collect(),
3447            TopK {
3448                input: _,
3449                group_key: _,
3450                order_key: _,
3451                limit,
3452                offset,
3453                expected_group_size: _,
3454            } => limit.iter().chain(std::iter::once(offset)).collect(),
3455        }
3456        .into_iter()
3457    }
3458
3459    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut HirScalarExpr>
3460    where
3461        HirScalarExpr: 'a,
3462    {
3463        use HirRelationExpr::*;
3464        match self {
3465            Constant { rows: _, typ: _ }
3466            | Get { id: _, typ: _ }
3467            | Let {
3468                name: _,
3469                id: _,
3470                value: _,
3471                body: _,
3472            }
3473            | LetRec {
3474                limit: _,
3475                bindings: _,
3476                body: _,
3477            }
3478            | Project {
3479                input: _,
3480                outputs: _,
3481            }
3482            | Distinct { input: _ }
3483            | Negate { input: _ }
3484            | Threshold { input: _ }
3485            | Union { base: _, inputs: _ } => vec![],
3486            Map { input: _, scalars }
3487            | CallTable {
3488                func: _,
3489                exprs: scalars,
3490            }
3491            | Filter {
3492                input: _,
3493                predicates: scalars,
3494            } => scalars.iter_mut().collect(),
3495            Join {
3496                left: _,
3497                right: _,
3498                on,
3499                kind: _,
3500            } => vec![on],
3501            Reduce {
3502                input: _,
3503                group_key: _,
3504                aggregates,
3505                expected_group_size: _,
3506            } => aggregates.iter_mut().map(|agg| &mut *agg.expr).collect(),
3507            TopK {
3508                input: _,
3509                group_key: _,
3510                order_key: _,
3511                limit,
3512                offset,
3513                expected_group_size: _,
3514            } => limit.iter_mut().chain(std::iter::once(offset)).collect(),
3515        }
3516        .into_iter()
3517    }
3518}
3519
3520impl HirScalarExpr {
3521    pub fn name(&self) -> Option<Arc<str>> {
3522        use HirScalarExpr::*;
3523        match self {
3524            Column(_, name)
3525            | Parameter(_, name)
3526            | Literal(_, _, name)
3527            | CallUnmaterializable(_, name)
3528            | CallUnary { name, .. }
3529            | CallBinary { name, .. }
3530            | CallVariadic { name, .. }
3531            | If { name, .. }
3532            | Exists(_, name)
3533            | Select(_, name)
3534            | Windowing(_, name) => name.0.clone(),
3535        }
3536    }
3537
3538    /// Visit every subquery, without descending into subqueries.
3539    pub fn visit_direct_subqueries<F>(&self, mut f: F)
3540    where
3541        F: FnMut(&HirRelationExpr),
3542    {
3543        self.visit_post(&mut |e| {
3544            VisitChildren::<HirRelationExpr>::visit_children(e, &mut f);
3545        });
3546    }
3547
3548    /// Mutable counterpart of [`HirScalarExpr::visit_direct_subqueries`].
3549    pub fn visit_direct_subqueries_mut<F>(&mut self, mut f: F)
3550    where
3551        F: FnMut(&mut HirRelationExpr),
3552    {
3553        self.visit_mut_post(&mut |e| {
3554            VisitChildren::<HirRelationExpr>::visit_mut_children(e, &mut f);
3555        });
3556    }
3557
3558    /// Fallible counterpart of [`HirScalarExpr::visit_direct_subqueries`].
3559    pub fn try_visit_direct_subqueries<F, E>(&self, mut f: F) -> Result<(), E>
3560    where
3561        F: FnMut(&HirRelationExpr) -> Result<(), E>,
3562    {
3563        self.try_visit_post(&mut |e| {
3564            VisitChildren::<HirRelationExpr>::try_visit_children(e, &mut f)
3565        })
3566    }
3567
3568    /// Fallible mutable counterpart of [`HirScalarExpr::visit_direct_subqueries`].
3569    pub fn try_visit_direct_subqueries_mut<F, E>(&mut self, mut f: F) -> Result<(), E>
3570    where
3571        F: FnMut(&mut HirRelationExpr) -> Result<(), E>,
3572    {
3573        self.try_visit_mut_post(&mut |e| {
3574            VisitChildren::<HirRelationExpr>::try_visit_mut_children(e, &mut f)
3575        })
3576    }
3577
3578    /// Replaces parameter references in the expression with the corresponding datum from `params`.
3579    /// Additionally, it simplifies OFFSET clauses to constants after parameter binding, and checks
3580    /// them for non-negativity.
3581    ///
3582    /// This handles subqueries nested inside `self` by calling back into
3583    /// [`HirRelationExpr::bind_parameters_and_simplify_offset`] on each direct subquery; that
3584    /// relation-level function in turn calls back here for the scalar expressions it holds, so
3585    /// the two functions corecursively cover the entire HIR tree.
3586    pub fn bind_parameters_and_simplify_offset(
3587        &mut self,
3588        scx: &StatementContext,
3589        lifetime: QueryLifetime,
3590        params: &Params,
3591    ) -> Result<(), PlanError> {
3592        // First, rewrite each `Parameter` node to a literal. This walks only the scalar tree;
3593        // it does not yet descend into subqueries.
3594        self.try_visit_mut_post(&mut |e: &mut HirScalarExpr| {
3595            if let HirScalarExpr::Parameter(n, name) = e {
3596                let datum = match params.datums.iter().nth(*n - 1) {
3597                    None => return Err(PlanError::UnknownParameter(*n)),
3598                    Some(datum) => datum,
3599                };
3600                let scalar_type = &params.execute_types[*n - 1];
3601                let row = Row::pack([datum]);
3602                let column_type = scalar_type.clone().nullable(datum.is_null());
3603
3604                let name = if let Some(name) = &name.0 {
3605                    Some(Arc::clone(name))
3606                } else {
3607                    Some(Arc::from(format!("${n}")))
3608                };
3609
3610                let qcx = QueryContext::root(scx, lifetime);
3611                let ecx = execute_expr_context(&qcx);
3612
3613                *e = plan_cast(
3614                    &ecx,
3615                    *EXECUTE_CAST_CONTEXT,
3616                    HirScalarExpr::Literal(row, column_type, TreatAsEqual(name)),
3617                    &params.expected_types[*n - 1],
3618                )
3619                .expect("checked in plan_params");
3620            }
3621            Ok(())
3622        })?;
3623        // Then descend into any subqueries; the relation-side `bind_parameters_and_simplify_offset`
3624        // handles corecursion back into scalars.
3625        self.try_visit_direct_subqueries_mut(|r: &mut HirRelationExpr| {
3626            r.bind_parameters_and_simplify_offset(scx, lifetime, params)
3627        })
3628    }
3629
3630    /// Like [`HirScalarExpr::bind_parameters_and_simplify_offset`], except that parameters are
3631    /// replaced with the corresponding expression fragment from `params` rather
3632    /// than a datum.
3633    ///
3634    /// Specifically, the parameter `$1` will be replaced with `params[0]`, the
3635    /// parameter `$2` will be replaced with `params[1]`, and so on. Parameters
3636    /// in `self` that refer to invalid indices of `params` will cause a panic.
3637    ///
3638    /// Column references in parameters will be corrected to account for the
3639    /// depth at which they are spliced.
3640    pub fn splice_parameters(&mut self, params: &[HirScalarExpr], depth: usize) {
3641        #[allow(deprecated)]
3642        let _ = self.visit_recursively_mut(depth, &mut |depth: usize,
3643                                                        e: &mut HirScalarExpr|
3644         -> Result<(), ()> {
3645            if let HirScalarExpr::Parameter(i, _name) = e {
3646                *e = params[*i - 1].clone();
3647                // Correct any column references in the parameter expression for
3648                // its new depth.
3649                e.visit_columns_mut(0, &mut |d: usize, col: &mut ColumnRef| {
3650                    if col.level >= d {
3651                        col.level += depth
3652                    }
3653                });
3654            }
3655            Ok(())
3656        });
3657    }
3658
3659    /// Whether the expression contains an [`UnmaterializableFunc::MzNow`] call.
3660    pub fn contains_temporal(&self) -> bool {
3661        let mut contains = false;
3662        self.visit_post(&mut |e| {
3663            if let Self::CallUnmaterializable(UnmaterializableFunc::MzNow, _name) = e {
3664                contains = true;
3665            }
3666        });
3667        contains
3668    }
3669
3670    /// Whether the expression contains any [`UnmaterializableFunc`] call.
3671    pub fn contains_unmaterializable(&self) -> bool {
3672        let mut contains = false;
3673        self.visit_post(&mut |e| {
3674            if let Self::CallUnmaterializable(_, _) = e {
3675                contains = true;
3676            }
3677        });
3678        contains
3679    }
3680
3681    /// Whether the expression contains any [`UnmaterializableFunc`] call other than
3682    /// [`UnmaterializableFunc::MzNow`].
3683    pub fn contains_unmaterializable_except_temporal(&self) -> bool {
3684        let mut contains = false;
3685        self.visit_post(&mut |e| {
3686            if let Self::CallUnmaterializable(f, _) = e {
3687                if *f != UnmaterializableFunc::MzNow {
3688                    contains = true;
3689                }
3690            }
3691        });
3692        contains
3693    }
3694
3695    /// Constructs an unnamed column reference in the current scope.
3696    /// Use [`HirScalarExpr::named_column`] when a name is known.
3697    /// Use [`HirScalarExpr::unnamed_column`] for a `ColumnRef`.
3698    pub fn column(index: usize) -> HirScalarExpr {
3699        HirScalarExpr::Column(
3700            ColumnRef {
3701                level: 0,
3702                column: index,
3703            },
3704            TreatAsEqual(None),
3705        )
3706    }
3707
3708    /// Constructs an unnamed column reference.
3709    pub fn unnamed_column(cr: ColumnRef) -> HirScalarExpr {
3710        HirScalarExpr::Column(cr, TreatAsEqual(None))
3711    }
3712
3713    /// Constructs a named column reference.
3714    /// Names are interned by a `NameManager`.
3715    pub fn named_column(cr: ColumnRef, name: Arc<str>) -> HirScalarExpr {
3716        HirScalarExpr::Column(cr, TreatAsEqual(Some(name)))
3717    }
3718
3719    pub fn parameter(n: usize) -> HirScalarExpr {
3720        HirScalarExpr::Parameter(n, TreatAsEqual(None))
3721    }
3722
3723    pub fn literal(datum: Datum, scalar_type: SqlScalarType) -> HirScalarExpr {
3724        let col_type = scalar_type.nullable(datum.is_null());
3725        soft_assert_or_log!(datum.is_instance_of_sql(&col_type), "type is correct");
3726        let row = Row::pack([datum]);
3727        HirScalarExpr::Literal(row, col_type, TreatAsEqual(None))
3728    }
3729
3730    pub fn literal_true() -> HirScalarExpr {
3731        HirScalarExpr::literal(Datum::True, SqlScalarType::Bool)
3732    }
3733
3734    pub fn literal_false() -> HirScalarExpr {
3735        HirScalarExpr::literal(Datum::False, SqlScalarType::Bool)
3736    }
3737
3738    pub fn literal_null(scalar_type: SqlScalarType) -> HirScalarExpr {
3739        HirScalarExpr::literal(Datum::Null, scalar_type)
3740    }
3741
3742    pub fn literal_1d_array(
3743        datums: Vec<Datum>,
3744        element_scalar_type: SqlScalarType,
3745    ) -> Result<HirScalarExpr, PlanError> {
3746        let scalar_type = match element_scalar_type {
3747            SqlScalarType::Array(_) => {
3748                sql_bail!("cannot build array from array type");
3749            }
3750            typ => SqlScalarType::Array(Box::new(typ)).nullable(false),
3751        };
3752
3753        let mut row = Row::default();
3754        row.packer()
3755            .try_push_array(
3756                &[ArrayDimension {
3757                    lower_bound: 1,
3758                    length: datums.len(),
3759                }],
3760                datums,
3761            )
3762            .expect("array constructed to be valid");
3763
3764        Ok(HirScalarExpr::Literal(row, scalar_type, TreatAsEqual(None)))
3765    }
3766
3767    pub fn as_literal(&self) -> Option<Datum<'_>> {
3768        if let HirScalarExpr::Literal(row, _column_type, _name) = self {
3769            Some(row.unpack_first())
3770        } else {
3771            None
3772        }
3773    }
3774
3775    pub fn is_literal_true(&self) -> bool {
3776        Some(Datum::True) == self.as_literal()
3777    }
3778
3779    pub fn is_literal_false(&self) -> bool {
3780        Some(Datum::False) == self.as_literal()
3781    }
3782
3783    pub fn is_literal_null(&self) -> bool {
3784        Some(Datum::Null) == self.as_literal()
3785    }
3786
3787    /// Return true iff `self` consists only of literals, materializable function calls, and
3788    /// if-else statements.
3789    pub fn is_constant(&self) -> bool {
3790        let mut worklist = vec![self];
3791        while let Some(expr) = worklist.pop() {
3792            match expr {
3793                Self::Literal(..) => {
3794                    // leaf node, do nothing
3795                }
3796                Self::CallUnary { expr, .. } => {
3797                    worklist.push(expr);
3798                }
3799                Self::CallBinary {
3800                    func: _,
3801                    expr1,
3802                    expr2,
3803                    name: _,
3804                } => {
3805                    worklist.push(expr1);
3806                    worklist.push(expr2);
3807                }
3808                Self::CallVariadic {
3809                    func: _,
3810                    exprs,
3811                    name: _,
3812                } => {
3813                    worklist.extend(exprs.iter());
3814                }
3815                // (CallUnmaterializable is not allowed)
3816                Self::If {
3817                    cond,
3818                    then,
3819                    els,
3820                    name: _,
3821                } => {
3822                    worklist.push(cond);
3823                    worklist.push(then);
3824                    worklist.push(els);
3825                }
3826                _ => {
3827                    return false; // Any other node makes `self` non-constant.
3828                }
3829            }
3830        }
3831        true
3832    }
3833
3834    pub fn call_unary(self, func: UnaryFunc) -> Self {
3835        HirScalarExpr::CallUnary {
3836            func,
3837            expr: Box::new(self),
3838            name: NameMetadata::default(),
3839        }
3840    }
3841
3842    pub fn call_binary<B: Into<BinaryFunc>>(self, other: Self, func: B) -> Self {
3843        HirScalarExpr::CallBinary {
3844            func: func.into(),
3845            expr1: Box::new(self),
3846            expr2: Box::new(other),
3847            name: NameMetadata::default(),
3848        }
3849    }
3850
3851    pub fn call_unmaterializable(func: UnmaterializableFunc) -> Self {
3852        HirScalarExpr::CallUnmaterializable(func, NameMetadata::default())
3853    }
3854
3855    pub fn call_variadic<V: Into<VariadicFunc>>(func: V, exprs: Vec<Self>) -> Self {
3856        HirScalarExpr::CallVariadic {
3857            func: func.into(),
3858            exprs,
3859            name: NameMetadata::default(),
3860        }
3861    }
3862
3863    pub fn if_then_else(cond: Self, then: Self, els: Self) -> Self {
3864        HirScalarExpr::If {
3865            cond: Box::new(cond),
3866            then: Box::new(then),
3867            els: Box::new(els),
3868            name: NameMetadata::default(),
3869        }
3870    }
3871
3872    pub fn windowing(expr: WindowExpr) -> Self {
3873        HirScalarExpr::Windowing(expr, TreatAsEqual(None))
3874    }
3875
3876    pub fn or(self, other: Self) -> Self {
3877        HirScalarExpr::call_variadic(Or, vec![self, other])
3878    }
3879
3880    pub fn and(self, other: Self) -> Self {
3881        HirScalarExpr::call_variadic(And, vec![self, other])
3882    }
3883
3884    pub fn not(self) -> Self {
3885        self.call_unary(UnaryFunc::Not(func::Not))
3886    }
3887
3888    pub fn call_is_null(self) -> Self {
3889        self.call_unary(UnaryFunc::IsNull(func::IsNull))
3890    }
3891
3892    /// Calls AND with the given arguments. Simplifies if 0 or 1 args.
3893    pub fn variadic_and(mut args: Vec<HirScalarExpr>) -> HirScalarExpr {
3894        match args.len() {
3895            0 => HirScalarExpr::literal_true(), // Same as unit_of_and_or, but that's MirScalarExpr
3896            1 => args.swap_remove(0),
3897            _ => HirScalarExpr::call_variadic(And, args),
3898        }
3899    }
3900
3901    /// Calls OR with the given arguments. Simplifies if 0 or 1 args.
3902    pub fn variadic_or(mut args: Vec<HirScalarExpr>) -> HirScalarExpr {
3903        match args.len() {
3904            0 => HirScalarExpr::literal_false(), // Same as unit_of_and_or, but that's MirScalarExpr
3905            1 => args.swap_remove(0),
3906            _ => HirScalarExpr::call_variadic(Or, args),
3907        }
3908    }
3909
3910    pub fn take(&mut self) -> Self {
3911        mem::replace(self, HirScalarExpr::literal_null(SqlScalarType::String))
3912    }
3913
3914    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
3915    /// Visits the column references in this scalar expression.
3916    ///
3917    /// The `depth` argument should indicate the subquery nesting depth of the expression,
3918    /// which will be incremented with each subquery entered and presented to the supplied
3919    /// function `f`.
3920    pub fn visit_columns<F>(&self, depth: usize, f: &mut F)
3921    where
3922        F: FnMut(usize, &ColumnRef),
3923    {
3924        #[allow(deprecated)]
3925        let _ = self.visit_recursively(depth, &mut |depth: usize,
3926                                                    e: &HirScalarExpr|
3927         -> Result<(), ()> {
3928            if let HirScalarExpr::Column(col, _name) = e {
3929                f(depth, col)
3930            }
3931            Ok(())
3932        });
3933    }
3934
3935    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
3936    /// Like `visit_columns`, but permits mutating the column references.
3937    pub fn visit_columns_mut<F>(&mut self, depth: usize, f: &mut F)
3938    where
3939        F: FnMut(usize, &mut ColumnRef),
3940    {
3941        #[allow(deprecated)]
3942        let _ = self.visit_recursively_mut(depth, &mut |depth: usize,
3943                                                        e: &mut HirScalarExpr|
3944         -> Result<(), ()> {
3945            if let HirScalarExpr::Column(col, _name) = e {
3946                f(depth, col)
3947            }
3948            Ok(())
3949        });
3950    }
3951
3952    /// Visits those column references in this scalar expression that refer to the root
3953    /// level. These include column references that are at the root level, as well as column
3954    /// references that are at a deeper subquery nesting depth, but refer back to the root level.
3955    /// (Note that even if `self` is embedded inside a larger expression, we consider the
3956    /// "root level" to be `self`'s level.)
3957    pub fn visit_columns_referring_to_root_level<F>(&self, f: &mut F)
3958    where
3959        F: FnMut(usize),
3960    {
3961        #[allow(deprecated)]
3962        let _ = self.visit_recursively(0, &mut |depth: usize,
3963                                                e: &HirScalarExpr|
3964         -> Result<(), ()> {
3965            if let HirScalarExpr::Column(col, _name) = e {
3966                if col.level == depth {
3967                    f(col.column)
3968                }
3969            }
3970            Ok(())
3971        });
3972    }
3973
3974    /// Like `visit_columns_referring_to_root_level`, but permits mutating the column references.
3975    pub fn visit_columns_referring_to_root_level_mut<F>(&mut self, f: &mut F)
3976    where
3977        F: FnMut(&mut usize),
3978    {
3979        #[allow(deprecated)]
3980        let _ = self.visit_recursively_mut(0, &mut |depth: usize,
3981                                                    e: &mut HirScalarExpr|
3982         -> Result<(), ()> {
3983            if let HirScalarExpr::Column(col, _name) = e {
3984                if col.level == depth {
3985                    f(&mut col.column)
3986                }
3987            }
3988            Ok(())
3989        });
3990    }
3991
3992    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
3993    /// Like `visit` but it enters the subqueries visiting the scalar expressions contained
3994    /// in them. It takes the current depth of the expression and increases it when
3995    /// entering a subquery.
3996    pub fn visit_recursively<F, E>(&self, depth: usize, f: &mut F) -> Result<(), E>
3997    where
3998        F: FnMut(usize, &HirScalarExpr) -> Result<(), E>,
3999    {
4000        match self {
4001            HirScalarExpr::Literal(..)
4002            | HirScalarExpr::Parameter(..)
4003            | HirScalarExpr::CallUnmaterializable(..)
4004            | HirScalarExpr::Column(..) => (),
4005            HirScalarExpr::CallUnary { expr, .. } => expr.visit_recursively(depth, f)?,
4006            HirScalarExpr::CallBinary { expr1, expr2, .. } => {
4007                expr1.visit_recursively(depth, f)?;
4008                expr2.visit_recursively(depth, f)?;
4009            }
4010            HirScalarExpr::CallVariadic { exprs, .. } => {
4011                for expr in exprs {
4012                    expr.visit_recursively(depth, f)?;
4013                }
4014            }
4015            HirScalarExpr::If {
4016                cond,
4017                then,
4018                els,
4019                name: _,
4020            } => {
4021                cond.visit_recursively(depth, f)?;
4022                then.visit_recursively(depth, f)?;
4023                els.visit_recursively(depth, f)?;
4024            }
4025            HirScalarExpr::Exists(expr, _name) | HirScalarExpr::Select(expr, _name) => {
4026                #[allow(deprecated)]
4027                expr.visit_scalar_expressions(depth + 1, &mut |e, depth| {
4028                    e.visit_recursively(depth, f)
4029                })?;
4030            }
4031            HirScalarExpr::Windowing(expr, _name) => {
4032                expr.visit_expressions(&mut |e| e.visit_recursively(depth, f))?;
4033            }
4034        }
4035        f(depth, self)
4036    }
4037
4038    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
4039    /// Like `visit_recursively`, but permits mutating the scalar expressions.
4040    pub fn visit_recursively_mut<F, E>(&mut self, depth: usize, f: &mut F) -> Result<(), E>
4041    where
4042        F: FnMut(usize, &mut HirScalarExpr) -> Result<(), E>,
4043    {
4044        match self {
4045            HirScalarExpr::Literal(..)
4046            | HirScalarExpr::Parameter(..)
4047            | HirScalarExpr::CallUnmaterializable(..)
4048            | HirScalarExpr::Column(..) => (),
4049            HirScalarExpr::CallUnary { expr, .. } => expr.visit_recursively_mut(depth, f)?,
4050            HirScalarExpr::CallBinary { expr1, expr2, .. } => {
4051                expr1.visit_recursively_mut(depth, f)?;
4052                expr2.visit_recursively_mut(depth, f)?;
4053            }
4054            HirScalarExpr::CallVariadic { exprs, .. } => {
4055                for expr in exprs {
4056                    expr.visit_recursively_mut(depth, f)?;
4057                }
4058            }
4059            HirScalarExpr::If {
4060                cond,
4061                then,
4062                els,
4063                name: _,
4064            } => {
4065                cond.visit_recursively_mut(depth, f)?;
4066                then.visit_recursively_mut(depth, f)?;
4067                els.visit_recursively_mut(depth, f)?;
4068            }
4069            HirScalarExpr::Exists(expr, _name) | HirScalarExpr::Select(expr, _name) => {
4070                #[allow(deprecated)]
4071                expr.visit_scalar_expressions_mut(depth + 1, &mut |e, depth| {
4072                    e.visit_recursively_mut(depth, f)
4073                })?;
4074            }
4075            HirScalarExpr::Windowing(expr, _name) => {
4076                expr.visit_expressions_mut(&mut |e| e.visit_recursively_mut(depth, f))?;
4077            }
4078        }
4079        f(depth, self)
4080    }
4081
4082    /// Attempts to simplify self into a literal.
4083    ///
4084    /// Returns None if self is not constant and therefore can't be simplified to a literal, or if
4085    /// an evaluation error occurs during simplification, or if self contains
4086    /// - a subquery
4087    /// - a column reference to an outer level
4088    /// - a parameter
4089    /// - a window function call
4090    fn simplify_to_literal(self) -> Option<Row> {
4091        let mut expr = self
4092            .lower_uncorrelated(crate::plan::lowering::Config::default())
4093            .ok()?;
4094        // Using MIR evaluation with repr types is fine here: the
4095        // result is an untyped Row, so any intermediate type
4096        // canonicalization is discarded.
4097        expr.reduce(&[]);
4098        match expr {
4099            mz_expr::MirScalarExpr::Literal(Ok(row), _) => Some(row),
4100            _ => None,
4101        }
4102    }
4103
4104    /// Simplifies self into a literal. If this is not possible (e.g., because self is not constant
4105    /// or an evaluation error occurs during simplification), it returns
4106    /// [`PlanError::ConstantExpressionSimplificationFailed`].
4107    ///
4108    /// The returned error is an _internal_ error if the expression contains
4109    /// - a subquery
4110    /// - a column reference to an outer level
4111    /// - a parameter
4112    /// - a window function call
4113    ///
4114    /// TODO: use this everywhere instead of `simplify_to_literal`, so that we don't hide the error
4115    /// msg.
4116    fn simplify_to_literal_with_result(self) -> Result<Row, PlanError> {
4117        let mut expr = self
4118            .lower_uncorrelated(crate::plan::lowering::Config::default())
4119            .map_err(|err| {
4120                PlanError::ConstantExpressionSimplificationFailed(err.to_string_with_causes())
4121            })?;
4122        // Using MIR evaluation with repr types is fine here: the
4123        // result is an untyped Row, so any intermediate type
4124        // canonicalization is discarded.
4125        expr.reduce(&[]);
4126        match expr {
4127            mz_expr::MirScalarExpr::Literal(Ok(row), _) => Ok(row),
4128            mz_expr::MirScalarExpr::Literal(Err(err), _) => Err(
4129                PlanError::ConstantExpressionSimplificationFailed(err.to_string_with_causes()),
4130            ),
4131            _ => Err(PlanError::ConstantExpressionSimplificationFailed(
4132                "Not a constant".to_string(),
4133            )),
4134        }
4135    }
4136
4137    /// Attempts to simplify this expression to a literal 64-bit integer.
4138    ///
4139    /// Returns `None` if this expression cannot be simplified, e.g. because it
4140    /// contains non-literal values.
4141    ///
4142    /// # Panics
4143    ///
4144    /// Panics if this expression does not have type [`SqlScalarType::Int64`].
4145    pub fn into_literal_int64(self) -> Option<i64> {
4146        self.simplify_to_literal().and_then(|row| {
4147            let datum = row.unpack_first();
4148            if datum.is_null() {
4149                None
4150            } else {
4151                Some(datum.unwrap_int64())
4152            }
4153        })
4154    }
4155
4156    /// Attempts to simplify this expression to a literal string.
4157    ///
4158    /// Returns `None` if this expression cannot be simplified, e.g. because it
4159    /// contains non-literal values.
4160    ///
4161    /// # Panics
4162    ///
4163    /// Panics if this expression does not have type [`SqlScalarType::String`].
4164    pub fn into_literal_string(self) -> Option<String> {
4165        self.simplify_to_literal().and_then(|row| {
4166            let datum = row.unpack_first();
4167            if datum.is_null() {
4168                None
4169            } else {
4170                Some(datum.unwrap_str().to_owned())
4171            }
4172        })
4173    }
4174
4175    /// Attempts to simplify this expression to a literal MzTimestamp.
4176    ///
4177    /// Returns `None` if the expression simplifies to `null` or if the expression cannot be
4178    /// simplified, e.g. because it contains non-literal values or a cast fails.
4179    ///
4180    /// TODO: Make this (and the other similar fns above) return Result, so that we can show the
4181    /// error when it fails. (E.g., there can be non-trivial cast errors.)
4182    /// See `try_into_literal_int64` as an example.
4183    ///
4184    /// # Panics
4185    ///
4186    /// Panics if this expression does not have type [`SqlScalarType::MzTimestamp`].
4187    pub fn into_literal_mz_timestamp(self) -> Option<Timestamp> {
4188        self.simplify_to_literal().and_then(|row| {
4189            let datum = row.unpack_first();
4190            if datum.is_null() {
4191                None
4192            } else {
4193                Some(datum.unwrap_mz_timestamp())
4194            }
4195        })
4196    }
4197
4198    /// Attempts to simplify this expression of [`SqlScalarType::Int64`] to a literal Int64 and
4199    /// returns it as an i64.
4200    ///
4201    /// Returns `PlanError::ConstantExpressionSimplificationFailed` if
4202    /// - it's not a constant expression (as determined by `is_constant`)
4203    /// - evaluates to null
4204    /// - an EvalError occurs during evaluation (e.g., a cast fails)
4205    ///
4206    /// # Panics
4207    ///
4208    /// Panics if this expression does not have type [`SqlScalarType::Int64`].
4209    pub fn try_into_literal_int64(self) -> Result<i64, PlanError> {
4210        match self.clone().try_into_nullable_literal_int64()? {
4211            Some(value) => Ok(value),
4212            None => Err(PlanError::ConstantExpressionSimplificationFailed(format!(
4213                "Expected an expression that evaluates to a non-null value, got {}",
4214                self
4215            ))),
4216        }
4217    }
4218
4219    /// Like [`try_into_literal_int64`](Self::try_into_literal_int64), but an expression that
4220    /// evaluates to null is `Ok(None)` instead of an error.
4221    pub fn try_into_nullable_literal_int64(self) -> Result<Option<i64>, PlanError> {
4222        // TODO: add the `is_constant` check also to all the other into_literal_... (by adding it to
4223        // `simplify_to_literal`), but those should be just soft_asserts at first that it doesn't
4224        // actually happen that it's weaker than `reduce`, and then add them for real after 1 week.
4225        // (Without the is_constant check, lower_uncorrelated's preconditions spill out to be
4226        // preconditions also of all the other into_literal_... functions.)
4227        if !self.is_constant() {
4228            return Err(PlanError::ConstantExpressionSimplificationFailed(format!(
4229                "Expected a constant expression, got {}",
4230                self
4231            )));
4232        }
4233        self.simplify_to_literal_with_result().map(|row| {
4234            let datum = row.unpack_first();
4235            if datum.is_null() {
4236                None
4237            } else {
4238                Some(datum.unwrap_int64())
4239            }
4240        })
4241    }
4242
4243    pub fn contains_parameters(&self) -> bool {
4244        let mut contains_parameters = false;
4245        #[allow(deprecated)]
4246        let _ = self.visit_recursively(0, &mut |_depth: usize,
4247                                                expr: &HirScalarExpr|
4248         -> Result<(), ()> {
4249            if let HirScalarExpr::Parameter(..) = expr {
4250                contains_parameters = true;
4251            }
4252            Ok(())
4253        });
4254        contains_parameters
4255    }
4256
4257    fn direct_subqueries(&self) -> Vec<&HirRelationExpr> {
4258        let mut subqueries: Vec<&HirRelationExpr> = vec![];
4259
4260        let mut worklist = vec![self];
4261        while let Some(elt) = worklist.pop() {
4262            match elt {
4263                HirScalarExpr::Column(_, _)
4264                | HirScalarExpr::Parameter(_, _)
4265                | HirScalarExpr::Literal(_, _, _)
4266                | HirScalarExpr::CallUnmaterializable(_, _) => (),
4267                HirScalarExpr::CallUnary {
4268                    func: _,
4269                    expr,
4270                    name: _,
4271                } => worklist.push(&*expr),
4272                HirScalarExpr::CallBinary {
4273                    func: _,
4274                    expr1,
4275                    expr2,
4276                    name: _name,
4277                } => {
4278                    // Push in reverse so children pop (and are visited) left-to-right.
4279                    worklist.push(&*expr2);
4280                    worklist.push(&*expr1);
4281                }
4282                HirScalarExpr::CallVariadic {
4283                    func: _,
4284                    exprs,
4285                    name: _name,
4286                } => {
4287                    worklist.extend(exprs.iter().rev());
4288                }
4289                HirScalarExpr::If {
4290                    cond,
4291                    then,
4292                    els,
4293                    name: _,
4294                } => {
4295                    worklist.push(&*els);
4296                    worklist.push(&*then);
4297                    worklist.push(&*cond);
4298                }
4299                HirScalarExpr::Exists(hir, _) | HirScalarExpr::Select(hir, _) => {
4300                    subqueries.push(&*hir);
4301                }
4302                HirScalarExpr::Windowing(
4303                    WindowExpr {
4304                        func,
4305                        partition_by,
4306                        order_by,
4307                    },
4308                    _,
4309                ) => {
4310                    // Push in reverse so children pop (and are visited) left-to-right:
4311                    // func args, then partition_by, then order_by.
4312                    worklist.extend(order_by.iter().rev());
4313                    worklist.extend(partition_by.iter().rev());
4314                    match func {
4315                        WindowExprType::Scalar(_) => (),
4316                        WindowExprType::Value(val) => worklist.push(&*val.args),
4317                        WindowExprType::Aggregate(agg) => worklist.push(&*agg.aggregate_expr.expr),
4318                    }
4319                }
4320            }
4321        }
4322
4323        subqueries
4324    }
4325
4326    fn direct_subqueries_mut(&mut self) -> Vec<&mut HirRelationExpr> {
4327        let mut subqueries: Vec<&mut HirRelationExpr> = vec![];
4328
4329        let mut worklist = vec![self];
4330        while let Some(elt) = worklist.pop() {
4331            match elt {
4332                HirScalarExpr::Column(_, _)
4333                | HirScalarExpr::Parameter(_, _)
4334                | HirScalarExpr::Literal(_, _, _)
4335                | HirScalarExpr::CallUnmaterializable(_, _) => (),
4336                HirScalarExpr::CallUnary {
4337                    func: _,
4338                    expr,
4339                    name: _,
4340                } => worklist.push(&mut **expr),
4341                HirScalarExpr::CallBinary {
4342                    func: _,
4343                    expr1,
4344                    expr2,
4345                    name: _name,
4346                } => {
4347                    // Push in reverse so children pop (and are visited) left-to-right.
4348                    worklist.push(&mut **expr2);
4349                    worklist.push(&mut **expr1);
4350                }
4351                HirScalarExpr::CallVariadic {
4352                    func: _,
4353                    exprs,
4354                    name: _name,
4355                } => {
4356                    worklist.extend(exprs.iter_mut().rev());
4357                }
4358                HirScalarExpr::If {
4359                    cond,
4360                    then,
4361                    els,
4362                    name: _,
4363                } => {
4364                    worklist.push(&mut **els);
4365                    worklist.push(&mut **then);
4366                    worklist.push(&mut **cond);
4367                }
4368                HirScalarExpr::Exists(hir, _) | HirScalarExpr::Select(hir, _) => {
4369                    subqueries.push(&mut **hir);
4370                }
4371                HirScalarExpr::Windowing(
4372                    WindowExpr {
4373                        func,
4374                        partition_by,
4375                        order_by,
4376                    },
4377                    _,
4378                ) => {
4379                    // Push in reverse so children pop (and are visited) left-to-right:
4380                    // func args, then partition_by, then order_by.
4381                    worklist.extend(order_by.iter_mut().rev());
4382                    worklist.extend(partition_by.iter_mut().rev());
4383                    match func {
4384                        WindowExprType::Scalar(_) => (),
4385                        WindowExprType::Value(val) => worklist.push(&mut val.args),
4386                        WindowExprType::Aggregate(agg) => {
4387                            worklist.push(&mut agg.aggregate_expr.expr)
4388                        }
4389                    }
4390                }
4391            }
4392        }
4393
4394        subqueries
4395    }
4396}
4397
4398/// Yields the direct scalar children of `self`. Stops at `Exists` / `Select`:
4399/// scalars inside subquery bodies are not surfaced. The asymmetry with
4400/// `VisitChildren<Self> for HirRelationExpr` (which does see through scalars
4401/// into subqueries) is what avoids the mutual recursion warned about on the
4402/// [`VisitChildren`] trait.
4403impl VisitChildren<Self> for HirScalarExpr {
4404    fn visit_children<F>(&self, mut f: F)
4405    where
4406        F: FnMut(&Self),
4407    {
4408        use HirScalarExpr::*;
4409        match self {
4410            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => (),
4411            CallUnary { expr, .. } => f(expr),
4412            CallBinary { expr1, expr2, .. } => {
4413                f(expr1);
4414                f(expr2);
4415            }
4416            CallVariadic { exprs, .. } => {
4417                for expr in exprs {
4418                    f(expr);
4419                }
4420            }
4421            If {
4422                cond,
4423                then,
4424                els,
4425                name: _,
4426            } => {
4427                f(cond);
4428                f(then);
4429                f(els);
4430            }
4431            Exists(..) | Select(..) => (),
4432            Windowing(expr, _name) => expr.visit_children(f),
4433        }
4434    }
4435
4436    fn visit_mut_children<F>(&mut self, mut f: F)
4437    where
4438        F: FnMut(&mut Self),
4439    {
4440        use HirScalarExpr::*;
4441        match self {
4442            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => (),
4443            CallUnary { expr, .. } => f(expr),
4444            CallBinary { expr1, expr2, .. } => {
4445                f(expr1);
4446                f(expr2);
4447            }
4448            CallVariadic { exprs, .. } => {
4449                for expr in exprs {
4450                    f(expr);
4451                }
4452            }
4453            If {
4454                cond,
4455                then,
4456                els,
4457                name: _,
4458            } => {
4459                f(cond);
4460                f(then);
4461                f(els);
4462            }
4463            Exists(..) | Select(..) => (),
4464            Windowing(expr, _name) => expr.visit_mut_children(f),
4465        }
4466    }
4467
4468    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
4469    where
4470        F: FnMut(&Self) -> Result<(), E>,
4471    {
4472        use HirScalarExpr::*;
4473        match self {
4474            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => (),
4475            CallUnary { expr, .. } => f(expr)?,
4476            CallBinary { expr1, expr2, .. } => {
4477                f(expr1)?;
4478                f(expr2)?;
4479            }
4480            CallVariadic { exprs, .. } => {
4481                for expr in exprs {
4482                    f(expr)?;
4483                }
4484            }
4485            If {
4486                cond,
4487                then,
4488                els,
4489                name: _,
4490            } => {
4491                f(cond)?;
4492                f(then)?;
4493                f(els)?;
4494            }
4495            Exists(..) | Select(..) => (),
4496            Windowing(expr, _name) => expr.try_visit_children(f)?,
4497        }
4498        Ok(())
4499    }
4500
4501    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
4502    where
4503        F: FnMut(&mut Self) -> Result<(), E>,
4504    {
4505        use HirScalarExpr::*;
4506        match self {
4507            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => (),
4508            CallUnary { expr, .. } => f(expr)?,
4509            CallBinary { expr1, expr2, .. } => {
4510                f(expr1)?;
4511                f(expr2)?;
4512            }
4513            CallVariadic { exprs, .. } => {
4514                for expr in exprs {
4515                    f(expr)?;
4516                }
4517            }
4518            If {
4519                cond,
4520                then,
4521                els,
4522                name: _,
4523            } => {
4524                f(cond)?;
4525                f(then)?;
4526                f(els)?;
4527            }
4528            Exists(..) | Select(..) => (),
4529            Windowing(expr, _name) => expr.try_visit_mut_children(f)?,
4530        }
4531        Ok(())
4532    }
4533
4534    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a Self>
4535    where
4536        Self: 'a,
4537    {
4538        use HirScalarExpr::*;
4539        let v: Vec<&Self> = match self {
4540            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => vec![],
4541            CallUnary { expr, .. } => vec![&*expr],
4542            CallBinary { expr1, expr2, .. } => {
4543                vec![&*expr1, &*expr2]
4544            }
4545            CallVariadic { exprs, .. } => exprs.iter().collect(),
4546            If {
4547                cond,
4548                then,
4549                els,
4550                name: _,
4551            } => {
4552                vec![&*cond, &*then, &*els]
4553            }
4554            Exists(..) | Select(..) => vec![],
4555            Windowing(expr, _name) => expr.children().collect(),
4556        };
4557        v.into_iter()
4558    }
4559
4560    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut Self>
4561    where
4562        Self: 'a,
4563    {
4564        use HirScalarExpr::*;
4565        let v: Vec<&mut Self> = match self {
4566            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => vec![],
4567            CallUnary { expr, .. } => vec![&mut **expr],
4568            CallBinary { expr1, expr2, .. } => {
4569                vec![&mut **expr1, &mut **expr2]
4570            }
4571            CallVariadic { exprs, .. } => exprs.iter_mut().collect(),
4572            If {
4573                cond,
4574                then,
4575                els,
4576                name: _,
4577            } => {
4578                vec![&mut **cond, &mut **then, &mut **els]
4579            }
4580            Exists(..) | Select(..) => vec![],
4581            Windowing(expr, _name) => expr.children_mut().collect(),
4582        };
4583        v.into_iter()
4584    }
4585}
4586
4587/// Yields the immediate `HirRelationExpr` children of `self` (the bodies of
4588/// `Exists` / `Select`); does not descend into them.
4589impl VisitChildren<HirRelationExpr> for HirScalarExpr {
4590    fn visit_children<F>(&self, mut f: F)
4591    where
4592        F: FnMut(&HirRelationExpr),
4593    {
4594        use HirScalarExpr::*;
4595        match self {
4596            Column(..)
4597            | Parameter(..)
4598            | Literal(..)
4599            | CallUnmaterializable(..)
4600            | CallUnary { .. }
4601            | CallBinary { .. }
4602            | CallVariadic { .. }
4603            | If { .. }
4604            | Windowing(..) => (),
4605            Exists(expr, _name) | Select(expr, _name) => f(expr),
4606        }
4607    }
4608
4609    fn visit_mut_children<F>(&mut self, mut f: F)
4610    where
4611        F: FnMut(&mut HirRelationExpr),
4612    {
4613        use HirScalarExpr::*;
4614        match self {
4615            Column(..)
4616            | Parameter(..)
4617            | Literal(..)
4618            | CallUnmaterializable(..)
4619            | CallUnary { .. }
4620            | CallBinary { .. }
4621            | CallVariadic { .. }
4622            | If { .. }
4623            | Windowing(..) => (),
4624            Exists(expr, _name) | Select(expr, _name) => f(expr),
4625        }
4626    }
4627
4628    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
4629    where
4630        F: FnMut(&HirRelationExpr) -> Result<(), E>,
4631    {
4632        use HirScalarExpr::*;
4633        match self {
4634            Column(..)
4635            | Parameter(..)
4636            | Literal(..)
4637            | CallUnmaterializable(..)
4638            | CallUnary { .. }
4639            | CallBinary { .. }
4640            | CallVariadic { .. }
4641            | If { .. }
4642            | Windowing(..) => (),
4643            Exists(expr, _name) | Select(expr, _name) => f(expr)?,
4644        }
4645        Ok(())
4646    }
4647
4648    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
4649    where
4650        F: FnMut(&mut HirRelationExpr) -> Result<(), E>,
4651    {
4652        use HirScalarExpr::*;
4653        match self {
4654            Column(..)
4655            | Parameter(..)
4656            | Literal(..)
4657            | CallUnmaterializable(..)
4658            | CallUnary { .. }
4659            | CallBinary { .. }
4660            | CallVariadic { .. }
4661            | If { .. }
4662            | Windowing(..) => (),
4663            Exists(expr, _name) | Select(expr, _name) => f(expr)?,
4664        }
4665        Ok(())
4666    }
4667
4668    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a HirRelationExpr>
4669    where
4670        HirRelationExpr: 'a,
4671    {
4672        let mut child: Option<&HirRelationExpr> = None;
4673        use HirScalarExpr::*;
4674        match self {
4675            Column(..)
4676            | Parameter(..)
4677            | Literal(..)
4678            | CallUnmaterializable(..)
4679            | CallUnary { .. }
4680            | CallBinary { .. }
4681            | CallVariadic { .. }
4682            | If { .. }
4683            | Windowing(..) => (),
4684            Exists(expr, _name) | Select(expr, _name) => child = Some(&*expr),
4685        }
4686
4687        child.into_iter()
4688    }
4689
4690    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut HirRelationExpr>
4691    where
4692        HirRelationExpr: 'a,
4693    {
4694        let mut child: Option<&mut HirRelationExpr> = None;
4695        use HirScalarExpr::*;
4696        match self {
4697            Column(..)
4698            | Parameter(..)
4699            | Literal(..)
4700            | CallUnmaterializable(..)
4701            | CallUnary { .. }
4702            | CallBinary { .. }
4703            | CallVariadic { .. }
4704            | If { .. }
4705            | Windowing(..) => (),
4706            Exists(expr, _name) | Select(expr, _name) => child = Some(&mut **expr),
4707        }
4708
4709        child.into_iter()
4710    }
4711}
4712
4713impl AbstractExpr for HirScalarExpr {
4714    type Type = SqlColumnType;
4715
4716    fn typ(
4717        &self,
4718        outers: &[SqlRelationType],
4719        inner: &SqlRelationType,
4720        params: &BTreeMap<usize, SqlScalarType>,
4721    ) -> Self::Type {
4722        stack::maybe_grow(|| match self {
4723            HirScalarExpr::Column(ColumnRef { level, column }, _name) => {
4724                if *level == 0 {
4725                    inner.column_types[*column].clone()
4726                } else {
4727                    outers[*level - 1].column_types[*column].clone()
4728                }
4729            }
4730            HirScalarExpr::Parameter(n, _name) => params[n].clone().nullable(true),
4731            HirScalarExpr::Literal(_, typ, _name) => typ.clone(),
4732            HirScalarExpr::CallUnmaterializable(func, _name) => func.output_sql_type(),
4733            HirScalarExpr::CallUnary {
4734                expr,
4735                func,
4736                name: _,
4737            } => func.output_sql_type(expr.typ(outers, inner, params)),
4738            HirScalarExpr::CallBinary {
4739                expr1,
4740                expr2,
4741                func,
4742                name: _,
4743            } => func.output_sql_type(&[
4744                expr1.typ(outers, inner, params),
4745                expr2.typ(outers, inner, params),
4746            ]),
4747            HirScalarExpr::CallVariadic {
4748                exprs,
4749                func,
4750                name: _,
4751            } => func.output_sql_type(exprs.iter().map(|e| e.typ(outers, inner, params)).collect()),
4752            HirScalarExpr::If {
4753                cond: _,
4754                then,
4755                els,
4756                name: _,
4757            } => {
4758                let then_type = then.typ(outers, inner, params);
4759                let else_type = els.typ(outers, inner, params);
4760                then_type.sql_union(&else_type).unwrap() // HIR deliberately not using `union`
4761            }
4762            HirScalarExpr::Exists(_, _name) => SqlScalarType::Bool.nullable(true),
4763            HirScalarExpr::Select(expr, _name) => {
4764                let mut outers = outers.to_vec();
4765                outers.insert(0, inner.clone());
4766                expr.typ(&outers, params)
4767                    .column_types
4768                    .into_element()
4769                    .nullable(true)
4770            }
4771            HirScalarExpr::Windowing(expr, _name) => expr.func.typ(outers, inner, params),
4772        })
4773    }
4774}
4775
4776impl AggregateExpr {
4777    pub fn typ(
4778        &self,
4779        outers: &[SqlRelationType],
4780        inner: &SqlRelationType,
4781        params: &BTreeMap<usize, SqlScalarType>,
4782    ) -> SqlColumnType {
4783        self.func
4784            .output_sql_type(self.expr.typ(outers, inner, params))
4785    }
4786
4787    /// Returns whether the expression is COUNT(*) or not.  Note that
4788    /// when we define the count builtin in sql::func, we convert
4789    /// COUNT(*) to COUNT(true), making it indistinguishable from
4790    /// literal COUNT(true), but we prefer to consider this as the
4791    /// former.
4792    ///
4793    /// (MIR has the same `is_count_asterisk`.)
4794    pub fn is_count_asterisk(&self) -> bool {
4795        self.func == AggregateFunc::Count && self.expr.is_literal_true() && !self.distinct
4796    }
4797}