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        self.visit1(depth, |e: &HirRelationExpr, depth: usize| {
2012            e.visit_fallible(depth, f)
2013        })?;
2014        f(self, depth)
2015    }
2016
2017    /// WARNING: `VisitChildren<HirRelationExpr>::try_visit_children` is NOT a
2018    /// drop-in replacement: in addition to the relation children visited here,
2019    /// it also descends into every subquery (`Exists`/`Select`) reachable
2020    /// through `self`'s scalar children — at any depth of scalar nesting.
2021    #[deprecated = "Use `VisitChildren<HirRelationExpr>::try_visit_children` instead."]
2022    pub fn visit1<'a, F, E>(&'a self, depth: usize, mut f: F) -> Result<(), E>
2023    where
2024        F: FnMut(&'a Self, usize) -> Result<(), E>,
2025    {
2026        match self {
2027            HirRelationExpr::Constant { .. }
2028            | HirRelationExpr::Get { .. }
2029            | HirRelationExpr::CallTable { .. } => (),
2030            HirRelationExpr::Let { body, value, .. } => {
2031                f(value, depth)?;
2032                f(body, depth)?;
2033            }
2034            HirRelationExpr::LetRec {
2035                limit: _,
2036                bindings,
2037                body,
2038            } => {
2039                for (_, _, value, _) in bindings.iter() {
2040                    f(value, depth)?;
2041                }
2042                f(body, depth)?;
2043            }
2044            HirRelationExpr::Project { input, .. } => {
2045                f(input, depth)?;
2046            }
2047            HirRelationExpr::Map { input, .. } => {
2048                f(input, depth)?;
2049            }
2050            HirRelationExpr::Filter { input, .. } => {
2051                f(input, depth)?;
2052            }
2053            HirRelationExpr::Join { left, right, .. } => {
2054                f(left, depth)?;
2055                f(right, depth + 1)?;
2056            }
2057            HirRelationExpr::Reduce { input, .. } => {
2058                f(input, depth)?;
2059            }
2060            HirRelationExpr::Distinct { input } => {
2061                f(input, depth)?;
2062            }
2063            HirRelationExpr::TopK { input, .. } => {
2064                f(input, depth)?;
2065            }
2066            HirRelationExpr::Negate { input } => {
2067                f(input, depth)?;
2068            }
2069            HirRelationExpr::Threshold { input } => {
2070                f(input, depth)?;
2071            }
2072            HirRelationExpr::Union { base, inputs } => {
2073                f(base, depth)?;
2074                for input in inputs {
2075                    f(input, depth)?;
2076                }
2077            }
2078        }
2079        Ok(())
2080    }
2081
2082    #[deprecated = "Use `Visit::visit_mut_post` instead."]
2083    pub fn visit_mut<F>(&mut self, depth: usize, f: &mut F)
2084    where
2085        F: FnMut(&mut Self, usize),
2086    {
2087        #[allow(deprecated)]
2088        let _ = self.visit_mut_fallible(depth, &mut |e: &mut HirRelationExpr,
2089                                                     depth: usize|
2090         -> Result<(), ()> {
2091            f(e, depth);
2092            Ok(())
2093        });
2094    }
2095
2096    #[deprecated = "Use `Visit::try_visit_mut_post` instead."]
2097    pub fn visit_mut_fallible<F, E>(&mut self, depth: usize, f: &mut F) -> Result<(), E>
2098    where
2099        F: FnMut(&mut Self, usize) -> Result<(), E>,
2100    {
2101        #[allow(deprecated)]
2102        self.visit1_mut(depth, |e: &mut HirRelationExpr, depth: usize| {
2103            e.visit_mut_fallible(depth, f)
2104        })?;
2105        f(self, depth)
2106    }
2107
2108    /// WARNING: `VisitChildren<HirRelationExpr>::try_visit_mut_children` is NOT a
2109    /// drop-in replacement: in addition to the relation children visited here,
2110    /// it also descends into every subquery (`Exists`/`Select`) reachable
2111    /// through `self`'s scalar children — at any depth of scalar nesting.
2112    #[deprecated = "Use `VisitChildren<HirRelationExpr>::try_visit_mut_children` instead."]
2113    pub fn visit1_mut<'a, F, E>(&'a mut self, depth: usize, mut f: F) -> Result<(), E>
2114    where
2115        F: FnMut(&'a mut Self, usize) -> Result<(), E>,
2116    {
2117        match self {
2118            HirRelationExpr::Constant { .. }
2119            | HirRelationExpr::Get { .. }
2120            | HirRelationExpr::CallTable { .. } => (),
2121            HirRelationExpr::Let { body, value, .. } => {
2122                f(value, depth)?;
2123                f(body, depth)?;
2124            }
2125            HirRelationExpr::LetRec {
2126                limit: _,
2127                bindings,
2128                body,
2129            } => {
2130                for (_, _, value, _) in bindings.iter_mut() {
2131                    f(value, depth)?;
2132                }
2133                f(body, depth)?;
2134            }
2135            HirRelationExpr::Project { input, .. } => {
2136                f(input, depth)?;
2137            }
2138            HirRelationExpr::Map { input, .. } => {
2139                f(input, depth)?;
2140            }
2141            HirRelationExpr::Filter { input, .. } => {
2142                f(input, depth)?;
2143            }
2144            HirRelationExpr::Join { left, right, .. } => {
2145                f(left, depth)?;
2146                f(right, depth + 1)?;
2147            }
2148            HirRelationExpr::Reduce { input, .. } => {
2149                f(input, depth)?;
2150            }
2151            HirRelationExpr::Distinct { input } => {
2152                f(input, depth)?;
2153            }
2154            HirRelationExpr::TopK { input, .. } => {
2155                f(input, depth)?;
2156            }
2157            HirRelationExpr::Negate { input } => {
2158                f(input, depth)?;
2159            }
2160            HirRelationExpr::Threshold { input } => {
2161                f(input, depth)?;
2162            }
2163            HirRelationExpr::Union { base, inputs } => {
2164                f(base, depth)?;
2165                for input in inputs {
2166                    f(input, depth)?;
2167                }
2168            }
2169        }
2170        Ok(())
2171    }
2172
2173    #[deprecated = "Use a combination of `Visit` and `VisitChildren` methods."]
2174    /// Visits all scalar expressions directly held by relation nodes within the sub-tree of `self`.
2175    ///
2176    /// Note: this does NOT descend into subqueries that may appear inside the visited
2177    /// `HirScalarExpr`s (i.e., `HirScalarExpr::Exists` / `HirScalarExpr::Select`). The closure
2178    /// `f` is invoked once per top-level scalar expression attached to a relation node, and it
2179    /// is the closure's responsibility to recurse into any subqueries if desired.
2180    ///
2181    /// The `depth` argument is just a seed: it is the value passed to `f` for scalar expressions
2182    /// at the root of `self`, and it is incremented by 1 when descending into the RHS of a
2183    /// `Join` node (the only place this function increments it). It does NOT control or limit
2184    /// recursion; passing `0` is the usual choice.
2185    pub fn visit_scalar_expressions<F, E>(&self, depth: usize, f: &mut F) -> Result<(), E>
2186    where
2187        F: FnMut(&HirScalarExpr, usize) -> Result<(), E>,
2188    {
2189        #[allow(deprecated)]
2190        self.visit_fallible(depth, &mut |e: &HirRelationExpr,
2191                                         depth: usize|
2192         -> Result<(), E> {
2193            match e {
2194                HirRelationExpr::Join { on, .. } => {
2195                    f(on, depth)?;
2196                }
2197                HirRelationExpr::Map { scalars, .. } => {
2198                    for scalar in scalars {
2199                        f(scalar, depth)?;
2200                    }
2201                }
2202                HirRelationExpr::CallTable { exprs, .. } => {
2203                    for expr in exprs {
2204                        f(expr, depth)?;
2205                    }
2206                }
2207                HirRelationExpr::Filter { predicates, .. } => {
2208                    for predicate in predicates {
2209                        f(predicate, depth)?;
2210                    }
2211                }
2212                HirRelationExpr::Reduce { aggregates, .. } => {
2213                    for aggregate in aggregates {
2214                        f(&aggregate.expr, depth)?;
2215                    }
2216                }
2217                HirRelationExpr::TopK { limit, offset, .. } => {
2218                    if let Some(limit) = limit {
2219                        f(limit, depth)?;
2220                    }
2221                    f(offset, depth)?;
2222                }
2223                HirRelationExpr::Union { .. }
2224                | HirRelationExpr::Let { .. }
2225                | HirRelationExpr::LetRec { .. }
2226                | HirRelationExpr::Project { .. }
2227                | HirRelationExpr::Distinct { .. }
2228                | HirRelationExpr::Negate { .. }
2229                | HirRelationExpr::Threshold { .. }
2230                | HirRelationExpr::Constant { .. }
2231                | HirRelationExpr::Get { .. } => (),
2232            }
2233            Ok(())
2234        })
2235    }
2236
2237    #[deprecated = "Use a combination of `Visit` and `VisitChildren` methods."]
2238    /// Like `visit_scalar_expressions`, but permits mutating the expressions.
2239    ///
2240    /// In particular, this also does NOT descend into subqueries inside the visited scalar
2241    /// expressions, and `depth` is just a seed for the value passed to `f` (see
2242    /// [`HirRelationExpr::visit_scalar_expressions`]).
2243    pub fn visit_scalar_expressions_mut<F, E>(&mut self, depth: usize, f: &mut F) -> Result<(), E>
2244    where
2245        F: FnMut(&mut HirScalarExpr, usize) -> Result<(), E>,
2246    {
2247        #[allow(deprecated)]
2248        self.visit_mut_fallible(depth, &mut |e: &mut HirRelationExpr,
2249                                             depth: usize|
2250         -> Result<(), E> {
2251            match e {
2252                HirRelationExpr::Join { on, .. } => {
2253                    f(on, depth)?;
2254                }
2255                HirRelationExpr::Map { scalars, .. } => {
2256                    for scalar in scalars.iter_mut() {
2257                        f(scalar, depth)?;
2258                    }
2259                }
2260                HirRelationExpr::CallTable { exprs, .. } => {
2261                    for expr in exprs.iter_mut() {
2262                        f(expr, depth)?;
2263                    }
2264                }
2265                HirRelationExpr::Filter { predicates, .. } => {
2266                    for predicate in predicates.iter_mut() {
2267                        f(predicate, depth)?;
2268                    }
2269                }
2270                HirRelationExpr::Reduce { aggregates, .. } => {
2271                    for aggregate in aggregates.iter_mut() {
2272                        f(&mut aggregate.expr, depth)?;
2273                    }
2274                }
2275                HirRelationExpr::TopK { limit, offset, .. } => {
2276                    if let Some(limit) = limit {
2277                        f(limit, depth)?;
2278                    }
2279                    f(offset, depth)?;
2280                }
2281                HirRelationExpr::Union { .. }
2282                | HirRelationExpr::Let { .. }
2283                | HirRelationExpr::LetRec { .. }
2284                | HirRelationExpr::Project { .. }
2285                | HirRelationExpr::Distinct { .. }
2286                | HirRelationExpr::Negate { .. }
2287                | HirRelationExpr::Threshold { .. }
2288                | HirRelationExpr::Constant { .. }
2289                | HirRelationExpr::Get { .. } => (),
2290            }
2291            Ok(())
2292        })
2293    }
2294
2295    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
2296    /// Visits the column references in this relation expression.
2297    ///
2298    /// The `depth` argument should indicate the subquery nesting depth of the expression,
2299    /// which will be incremented when entering the RHS of a join or a subquery and
2300    /// presented to the supplied function `f`.
2301    pub fn visit_columns<F>(&self, depth: usize, f: &mut F)
2302    where
2303        F: FnMut(usize, &ColumnRef),
2304    {
2305        #[allow(deprecated)]
2306        let _ = self.visit_scalar_expressions(depth, &mut |e: &HirScalarExpr,
2307                                                           depth: usize|
2308         -> Result<(), ()> {
2309            e.visit_columns(depth, f);
2310            Ok(())
2311        });
2312    }
2313
2314    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
2315    /// Like `visit_columns`, but permits mutating the column references.
2316    pub fn visit_columns_mut<F>(&mut self, depth: usize, f: &mut F)
2317    where
2318        F: FnMut(usize, &mut ColumnRef),
2319    {
2320        #[allow(deprecated)]
2321        let _ = self.visit_scalar_expressions_mut(depth, &mut |e: &mut HirScalarExpr,
2322                                                               depth: usize|
2323         -> Result<(), ()> {
2324            e.visit_columns_mut(depth, f);
2325            Ok(())
2326        });
2327    }
2328
2329    /// Replaces parameter references in the expression with the corresponding datum from `params`.
2330    /// Additionally, it simplifies OFFSET clauses to constants after parameter binding, and checks
2331    /// them for non-negativity.
2332    ///
2333    /// This walks the entire `HirRelationExpr` tree, including subqueries nested inside scalar
2334    /// expressions: `visit_scalar_expressions_mut` covers the scalar expressions held directly
2335    /// by relation nodes, and the corecursive call into
2336    /// [`HirScalarExpr::bind_parameters_and_simplify_offset`] (made by the closure below) is
2337    /// what descends into subqueries occurring inside those scalar expressions.
2338    pub fn bind_parameters_and_simplify_offset(
2339        &mut self,
2340        scx: &StatementContext,
2341        lifetime: QueryLifetime,
2342        params: &Params,
2343    ) -> Result<(), PlanError> {
2344        #[allow(deprecated)]
2345        self.visit_scalar_expressions_mut(0, &mut |e: &mut HirScalarExpr, _: usize| {
2346            e.bind_parameters_and_simplify_offset(scx, lifetime, params)
2347        })?;
2348
2349        // OFFSET clauses in `expr` should become constants with the above binding of parameters.
2350        // Let's check this and simplify them to literals.
2351        self.try_visit_mut_pre(&mut |expr| {
2352            if let HirRelationExpr::TopK { offset, .. } = expr {
2353                let offset_value = offset_into_value(offset.take())?;
2354                *offset = HirScalarExpr::literal(Datum::Int64(offset_value), SqlScalarType::Int64);
2355            }
2356            Ok::<(), PlanError>(())
2357        })
2358        // (We don't need to simplify LIMIT clauses in `expr`, because we can handle non-constant
2359        // expressions there. If they happen to be simplifiable to literals, then the optimizer will do
2360        // so later.)
2361    }
2362
2363    pub fn contains_parameters(&self) -> Result<bool, PlanError> {
2364        let mut contains_parameters = false;
2365        #[allow(deprecated)]
2366        self.visit_scalar_expressions(0, &mut |e: &HirScalarExpr, _: usize| {
2367            if e.contains_parameters() {
2368                contains_parameters = true;
2369            }
2370            Ok::<(), PlanError>(())
2371        })?;
2372        Ok(contains_parameters)
2373    }
2374
2375    /// See the documentation for [`HirScalarExpr::splice_parameters`].
2376    pub fn splice_parameters(&mut self, params: &[HirScalarExpr], depth: usize) {
2377        #[allow(deprecated)]
2378        let _ = self.visit_scalar_expressions_mut(depth, &mut |e: &mut HirScalarExpr,
2379                                                               depth: usize|
2380         -> Result<(), ()> {
2381            e.splice_parameters(params, depth);
2382            Ok(())
2383        });
2384    }
2385
2386    /// Constructs a constant collection from specific rows and schema.
2387    pub fn constant(rows: Vec<Vec<Datum>>, typ: SqlRelationType) -> Self {
2388        let rows = rows
2389            .into_iter()
2390            .map(move |datums| Row::pack_slice(&datums))
2391            .collect();
2392        HirRelationExpr::Constant { rows, typ }
2393    }
2394
2395    /// A `RowSetFinishing` can only be directly applied to the result of a one-shot select.
2396    /// This function is concerned with maintained queries, e.g., an index or materialized view.
2397    /// Instead of directly applying the given `RowSetFinishing`, it converts the `RowSetFinishing`
2398    /// to a `TopK`, which it then places at the top of `self`. Additionally, it turns the given
2399    /// finishing into a trivial finishing.
2400    pub fn finish_maintained(
2401        &mut self,
2402        finishing: &mut RowSetFinishing<HirScalarExpr, HirScalarExpr>,
2403        group_size_hints: GroupSizeHints,
2404    ) {
2405        if !HirRelationExpr::is_trivial_row_set_finishing_hir(finishing, self.arity()) {
2406            let old_finishing = mem::replace(
2407                finishing,
2408                HirRelationExpr::trivial_row_set_finishing_hir(finishing.project.len()),
2409            );
2410            *self = HirRelationExpr::top_k(
2411                std::mem::replace(
2412                    self,
2413                    HirRelationExpr::Constant {
2414                        rows: vec![],
2415                        typ: SqlRelationType::new(Vec::new()),
2416                    },
2417                ),
2418                vec![],
2419                old_finishing.order_by,
2420                old_finishing.limit,
2421                old_finishing.offset,
2422                group_size_hints.limit_input_group_size,
2423            )
2424            .project(old_finishing.project);
2425        }
2426    }
2427
2428    /// Returns a trivial finishing, i.e., that does nothing to the result set.
2429    ///
2430    /// (There is also `RowSetFinishing::trivial`, but that is specialized for when the O generic
2431    /// parameter is not an HirScalarExpr anymore.)
2432    pub fn trivial_row_set_finishing_hir(
2433        arity: usize,
2434    ) -> RowSetFinishing<HirScalarExpr, HirScalarExpr> {
2435        RowSetFinishing {
2436            order_by: Vec::new(),
2437            limit: None,
2438            offset: HirScalarExpr::literal(Datum::Int64(0), SqlScalarType::Int64),
2439            project: (0..arity).collect(),
2440        }
2441    }
2442
2443    /// True if the finishing does nothing to any result set.
2444    ///
2445    /// (There is also `RowSetFinishing::is_trivial`, but that is specialized for when the O generic
2446    /// parameter is not an HirScalarExpr anymore.)
2447    pub fn is_trivial_row_set_finishing_hir(
2448        rsf: &RowSetFinishing<HirScalarExpr, HirScalarExpr>,
2449        arity: usize,
2450    ) -> bool {
2451        rsf.limit.is_none()
2452            && rsf.order_by.is_empty()
2453            && rsf
2454                .offset
2455                .clone()
2456                .try_into_literal_int64()
2457                .is_ok_and(|o| o == 0)
2458            && rsf.project.iter().copied().eq(0..arity)
2459    }
2460
2461    /// The HirRelationExpr is considered potentially expensive if and only if
2462    /// at least one of the following conditions is true:
2463    ///
2464    ///  - It contains at least one HirScalarExpr with a function call.
2465    ///  - It contains at least one CallTable or a Reduce operator.
2466    ///  - We run into a RecursionLimitError while analyzing the expression.
2467    ///
2468    /// !!!WARNING!!!: this method has an MirRelationExpr counterpart. The two
2469    /// should be kept in sync w.r.t. HIR ⇒ MIR lowering!
2470    pub fn could_run_expensive_function(&self) -> bool {
2471        let mut result = false;
2472        self.visit_pre(&mut |e: &HirRelationExpr| {
2473            use HirRelationExpr::*;
2474            use HirScalarExpr::*;
2475
2476            e.visit_children(|scalar: &HirScalarExpr| {
2477                scalar.visit_pre(&mut |scalar: &HirScalarExpr| {
2478                    result |= match scalar {
2479                        Column(..)
2480                        | Literal(..)
2481                        | CallUnmaterializable(..)
2482                        | If { .. }
2483                        | Parameter(..)
2484                        | Select(..)
2485                        | Exists(..) => false,
2486                        // Function calls are considered expensive
2487                        CallUnary { .. }
2488                        | CallBinary { .. }
2489                        | CallVariadic { .. }
2490                        | Windowing(..) => true,
2491                    };
2492                })
2493            });
2494
2495            // CallTable has a table function; Reduce has an aggregate function.
2496            // Other constructs use MirScalarExpr to run a function
2497            result |= matches!(e, CallTable { .. } | Reduce { .. });
2498        });
2499
2500        result
2501    }
2502
2503    /// Whether the expression contains an [`UnmaterializableFunc::MzNow`] call.
2504    pub fn contains_temporal(&self) -> bool {
2505        let mut contains = false;
2506        self.visit_post(&mut |expr| {
2507            expr.visit_children(|expr: &HirScalarExpr| {
2508                contains = contains || expr.contains_temporal()
2509            })
2510        });
2511        contains
2512    }
2513
2514    /// Whether the expression contains any [`UnmaterializableFunc`] call.
2515    pub fn contains_unmaterializable(&self) -> bool {
2516        let mut contains = false;
2517        self.visit_post(&mut |expr| {
2518            expr.visit_children(|expr: &HirScalarExpr| {
2519                contains = contains || expr.contains_unmaterializable()
2520            })
2521        });
2522        contains
2523    }
2524
2525    /// Whether the expression contains any [`UnmaterializableFunc`] call other than
2526    /// [`UnmaterializableFunc::MzNow`].
2527    pub fn contains_unmaterializable_except_temporal(&self) -> bool {
2528        let mut contains = false;
2529        self.visit_post(&mut |expr| {
2530            expr.visit_children(|expr: &HirScalarExpr| {
2531                contains = contains || expr.contains_unmaterializable_except_temporal()
2532            })
2533        });
2534        contains
2535    }
2536}
2537
2538impl CollectionPlan for HirRelationExpr {
2539    /// Collects the global collections that this HIR expression directly depends on, i.e., that it
2540    /// has a `Get` for. (It does _not_ traverse view definitions transitively.)
2541    /// (It does explore inside subqueries.)
2542    ///
2543    /// !!!WARNING!!!: this method has an MirRelationExpr counterpart. The two
2544    /// should be kept in sync w.r.t. HIR ⇒ MIR lowering!
2545    fn depends_on_into(&self, out: &mut BTreeSet<GlobalId>) {
2546        if let Self::Get {
2547            id: Id::Global(id), ..
2548        } = self
2549        {
2550            out.insert(*id);
2551        }
2552        self.visit_children(|expr: &HirRelationExpr| expr.depends_on_into(out))
2553    }
2554}
2555
2556/// In addition to direct relation children of `self`, this also yields every
2557/// subquery (`Exists` / `Select`) reachable through `self`'s scalar children,
2558/// at any depth of scalar nesting. This is the asymmetry warned about on the
2559/// [`VisitChildren`] trait; the matching impl on `HirScalarExpr` deliberately
2560/// does not do the symmetric thing, to avoid mutual recursion.
2561impl VisitChildren<Self> for HirRelationExpr {
2562    fn visit_children<F>(&self, mut f: F)
2563    where
2564        F: FnMut(&Self),
2565    {
2566        // subqueries of type HirRelationExpr might be wrapped in
2567        // Exists or Select variants within HirScalarExpr trees
2568        // attached at the current node, and we want to visit them as well
2569        VisitChildren::visit_children(self, |expr: &HirScalarExpr| {
2570            expr.visit_direct_subqueries(&mut f);
2571        });
2572
2573        use HirRelationExpr::*;
2574        match self {
2575            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2576            Let {
2577                name: _,
2578                id: _,
2579                value,
2580                body,
2581            } => {
2582                f(value);
2583                f(body);
2584            }
2585            LetRec {
2586                limit: _,
2587                bindings,
2588                body,
2589            } => {
2590                for (_, _, value, _) in bindings.iter() {
2591                    f(value);
2592                }
2593                f(body);
2594            }
2595            Project { input, outputs: _ } => f(input),
2596            Map { input, scalars: _ } => {
2597                f(input);
2598            }
2599            CallTable { func: _, exprs: _ } => (),
2600            Filter {
2601                input,
2602                predicates: _,
2603            } => {
2604                f(input);
2605            }
2606            Join {
2607                left,
2608                right,
2609                on: _,
2610                kind: _,
2611            } => {
2612                f(left);
2613                f(right);
2614            }
2615            Reduce {
2616                input,
2617                group_key: _,
2618                aggregates: _,
2619                expected_group_size: _,
2620            } => {
2621                f(input);
2622            }
2623            Distinct { input }
2624            | TopK {
2625                input,
2626                group_key: _,
2627                order_key: _,
2628                limit: _,
2629                offset: _,
2630                expected_group_size: _,
2631            }
2632            | Negate { input }
2633            | Threshold { input } => {
2634                f(input);
2635            }
2636            Union { base, inputs } => {
2637                f(base);
2638                for input in inputs {
2639                    f(input);
2640                }
2641            }
2642        }
2643    }
2644
2645    fn visit_mut_children<F>(&mut self, mut f: F)
2646    where
2647        F: FnMut(&mut Self),
2648    {
2649        // subqueries of type HirRelationExpr might be wrapped in
2650        // Exists or Select variants within HirScalarExpr trees
2651        // attached at the current node, and we want to visit them as well
2652        VisitChildren::visit_mut_children(self, |expr: &mut HirScalarExpr| {
2653            expr.visit_direct_subqueries_mut(&mut f);
2654        });
2655
2656        use HirRelationExpr::*;
2657        match self {
2658            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2659            Let {
2660                name: _,
2661                id: _,
2662                value,
2663                body,
2664            } => {
2665                f(value);
2666                f(body);
2667            }
2668            LetRec {
2669                limit: _,
2670                bindings,
2671                body,
2672            } => {
2673                for (_, _, value, _) in bindings.iter_mut() {
2674                    f(value);
2675                }
2676                f(body);
2677            }
2678            Project { input, outputs: _ } => f(input),
2679            Map { input, scalars: _ } => {
2680                f(input);
2681            }
2682            CallTable { func: _, exprs: _ } => (),
2683            Filter {
2684                input,
2685                predicates: _,
2686            } => {
2687                f(input);
2688            }
2689            Join {
2690                left,
2691                right,
2692                on: _,
2693                kind: _,
2694            } => {
2695                f(left);
2696                f(right);
2697            }
2698            Reduce {
2699                input,
2700                group_key: _,
2701                aggregates: _,
2702                expected_group_size: _,
2703            } => {
2704                f(input);
2705            }
2706            Distinct { input }
2707            | TopK {
2708                input,
2709                group_key: _,
2710                order_key: _,
2711                limit: _,
2712                offset: _,
2713                expected_group_size: _,
2714            }
2715            | Negate { input }
2716            | Threshold { input } => {
2717                f(input);
2718            }
2719            Union { base, inputs } => {
2720                f(base);
2721                for input in inputs {
2722                    f(input);
2723                }
2724            }
2725        }
2726    }
2727
2728    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
2729    where
2730        F: FnMut(&Self) -> Result<(), E>,
2731    {
2732        // subqueries of type HirRelationExpr might be wrapped in
2733        // Exists or Select variants within HirScalarExpr trees
2734        // attached at the current node, and we want to visit them as well
2735        VisitChildren::try_visit_children(self, |expr: &HirScalarExpr| {
2736            expr.try_visit_direct_subqueries(&mut f)
2737        })?;
2738
2739        use HirRelationExpr::*;
2740        match self {
2741            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2742            Let {
2743                name: _,
2744                id: _,
2745                value,
2746                body,
2747            } => {
2748                f(value)?;
2749                f(body)?;
2750            }
2751            LetRec {
2752                limit: _,
2753                bindings,
2754                body,
2755            } => {
2756                for (_, _, value, _) in bindings.iter() {
2757                    f(value)?;
2758                }
2759                f(body)?;
2760            }
2761            Project { input, outputs: _ } => f(input)?,
2762            Map { input, scalars: _ } => {
2763                f(input)?;
2764            }
2765            CallTable { func: _, exprs: _ } => (),
2766            Filter {
2767                input,
2768                predicates: _,
2769            } => {
2770                f(input)?;
2771            }
2772            Join {
2773                left,
2774                right,
2775                on: _,
2776                kind: _,
2777            } => {
2778                f(left)?;
2779                f(right)?;
2780            }
2781            Reduce {
2782                input,
2783                group_key: _,
2784                aggregates: _,
2785                expected_group_size: _,
2786            } => {
2787                f(input)?;
2788            }
2789            Distinct { input }
2790            | TopK {
2791                input,
2792                group_key: _,
2793                order_key: _,
2794                limit: _,
2795                offset: _,
2796                expected_group_size: _,
2797            }
2798            | Negate { input }
2799            | Threshold { input } => {
2800                f(input)?;
2801            }
2802            Union { base, inputs } => {
2803                f(base)?;
2804                for input in inputs {
2805                    f(input)?;
2806                }
2807            }
2808        }
2809        Ok(())
2810    }
2811
2812    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
2813    where
2814        F: FnMut(&mut Self) -> Result<(), E>,
2815    {
2816        // subqueries of type HirRelationExpr might be wrapped in
2817        // Exists or Select variants within HirScalarExpr trees
2818        // attached at the current node, and we want to visit them as well
2819        VisitChildren::try_visit_mut_children(self, |expr: &mut HirScalarExpr| {
2820            expr.try_visit_direct_subqueries_mut(&mut f)
2821        })?;
2822
2823        use HirRelationExpr::*;
2824        match self {
2825            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2826            Let {
2827                name: _,
2828                id: _,
2829                value,
2830                body,
2831            } => {
2832                f(value)?;
2833                f(body)?;
2834            }
2835            LetRec {
2836                limit: _,
2837                bindings,
2838                body,
2839            } => {
2840                for (_, _, value, _) in bindings.iter_mut() {
2841                    f(value)?;
2842                }
2843                f(body)?;
2844            }
2845            Project { input, outputs: _ } => f(input)?,
2846            Map { input, scalars: _ } => {
2847                f(input)?;
2848            }
2849            CallTable { func: _, exprs: _ } => (),
2850            Filter {
2851                input,
2852                predicates: _,
2853            } => {
2854                f(input)?;
2855            }
2856            Join {
2857                left,
2858                right,
2859                on: _,
2860                kind: _,
2861            } => {
2862                f(left)?;
2863                f(right)?;
2864            }
2865            Reduce {
2866                input,
2867                group_key: _,
2868                aggregates: _,
2869                expected_group_size: _,
2870            } => {
2871                f(input)?;
2872            }
2873            Distinct { input }
2874            | TopK {
2875                input,
2876                group_key: _,
2877                order_key: _,
2878                limit: _,
2879                offset: _,
2880                expected_group_size: _,
2881            }
2882            | Negate { input }
2883            | Threshold { input } => {
2884                f(input)?;
2885            }
2886            Union { base, inputs } => {
2887                f(base)?;
2888                for input in inputs {
2889                    f(input)?;
2890                }
2891            }
2892        }
2893        Ok(())
2894    }
2895
2896    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a Self>
2897    where
2898        Self: 'a,
2899    {
2900        // we visit subqueries _first_, then the input
2901        let mut v: Vec<&HirRelationExpr> = vec![];
2902        use HirRelationExpr::*;
2903        match self {
2904            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2905            Let {
2906                name: _,
2907                id: _,
2908                value,
2909                body,
2910            } => {
2911                v.push(&*value);
2912                v.push(&*body);
2913            }
2914            LetRec {
2915                limit: _,
2916                bindings,
2917                body,
2918            } => {
2919                v.extend(bindings.iter().map(|(_, _, value, _)| value));
2920                v.push(&*body);
2921            }
2922            Map { input, scalars }
2923            | Filter {
2924                input,
2925                predicates: scalars,
2926            } => {
2927                for scalar in scalars {
2928                    v.append(&mut scalar.direct_subqueries());
2929                }
2930                v.push(&*input);
2931            }
2932            Reduce {
2933                input,
2934                group_key: _,
2935                aggregates,
2936                expected_group_size: _,
2937            } => {
2938                for agg in aggregates {
2939                    v.append(&mut agg.expr.direct_subqueries());
2940                }
2941                v.push(&*input);
2942            }
2943            TopK {
2944                input,
2945                group_key: _,
2946                order_key: _,
2947                limit,
2948                offset,
2949                expected_group_size: _,
2950            } => {
2951                if let Some(limit) = limit {
2952                    v.append(&mut limit.direct_subqueries());
2953                }
2954                v.append(&mut offset.direct_subqueries());
2955                v.push(&*input);
2956            }
2957            Project { input, outputs: _ }
2958            | Distinct { input }
2959            | Negate { input }
2960            | Threshold { input } => v.push(&*input),
2961            CallTable { func: _, exprs } => v.extend(
2962                exprs
2963                    .iter()
2964                    .map(|scalar| scalar.direct_subqueries())
2965                    .flatten(),
2966            ),
2967            Join {
2968                left,
2969                right,
2970                on,
2971                kind: _,
2972            } => {
2973                v.append(&mut on.direct_subqueries());
2974                v.push(&*left);
2975                v.push(&*right);
2976            }
2977            Union { base, inputs } => {
2978                v.push(&*base);
2979                v.extend(inputs.iter());
2980            }
2981        }
2982
2983        v.into_iter()
2984    }
2985
2986    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut Self>
2987    where
2988        Self: 'a,
2989    {
2990        // we visit subqueries _first_, then the input
2991        let mut v = vec![];
2992        use HirRelationExpr::*;
2993        match self {
2994            Constant { rows: _, typ: _ } | Get { id: _, typ: _ } => (),
2995            Let {
2996                name: _,
2997                id: _,
2998                value,
2999                body,
3000            } => {
3001                v.push(&mut **value);
3002                v.push(&mut **body);
3003            }
3004            LetRec {
3005                limit: _,
3006                bindings,
3007                body,
3008            } => {
3009                v.extend(bindings.iter_mut().map(|(_, _, value, _)| value));
3010                v.push(&mut **body);
3011            }
3012            Map { input, scalars }
3013            | Filter {
3014                input,
3015                predicates: scalars,
3016            } => {
3017                for scalar in scalars {
3018                    v.append(&mut scalar.direct_subqueries_mut());
3019                }
3020                v.push(&mut **input);
3021            }
3022            Reduce {
3023                input,
3024                group_key: _,
3025                aggregates,
3026                expected_group_size: _,
3027            } => {
3028                for agg in aggregates {
3029                    v.append(&mut agg.expr.direct_subqueries_mut());
3030                }
3031                v.push(&mut **input);
3032            }
3033            TopK {
3034                input,
3035                group_key: _,
3036                order_key: _,
3037                limit,
3038                offset,
3039                expected_group_size: _,
3040            } => {
3041                if let Some(limit) = limit {
3042                    v.append(&mut limit.direct_subqueries_mut());
3043                }
3044                v.append(&mut offset.direct_subqueries_mut());
3045                v.push(&mut **input);
3046            }
3047            Project { input, outputs: _ }
3048            | Distinct { input }
3049            | Negate { input }
3050            | Threshold { input } => v.push(&mut **input),
3051            CallTable { func: _, exprs } => v.extend(
3052                exprs
3053                    .iter_mut()
3054                    .map(|scalar| scalar.direct_subqueries_mut())
3055                    .flatten(),
3056            ),
3057            Join {
3058                left,
3059                right,
3060                on,
3061                kind: _,
3062            } => {
3063                v.append(&mut on.direct_subqueries_mut());
3064                v.push(&mut **left);
3065                v.push(&mut **right);
3066            }
3067            Union { base, inputs } => {
3068                v.push(&mut **base);
3069                v.extend(inputs.iter_mut());
3070            }
3071        }
3072
3073        v.into_iter()
3074    }
3075}
3076
3077/// Yields the scalars directly attached to relation nodes (e.g. `Map.scalars`,
3078/// `Filter.predicates`, `Join.on`, `Reduce` aggregate args, `TopK.{limit,
3079/// offset}`, `CallTable.exprs`); does not descend into them.
3080impl VisitChildren<HirScalarExpr> for HirRelationExpr {
3081    fn visit_children<F>(&self, mut f: F)
3082    where
3083        F: FnMut(&HirScalarExpr),
3084    {
3085        use HirRelationExpr::*;
3086        match self {
3087            Constant { rows: _, typ: _ }
3088            | Get { id: _, typ: _ }
3089            | Let {
3090                name: _,
3091                id: _,
3092                value: _,
3093                body: _,
3094            }
3095            | LetRec {
3096                limit: _,
3097                bindings: _,
3098                body: _,
3099            }
3100            | Project {
3101                input: _,
3102                outputs: _,
3103            } => (),
3104            Map { input: _, scalars } => {
3105                for scalar in scalars {
3106                    f(scalar);
3107                }
3108            }
3109            CallTable { func: _, exprs } => {
3110                for expr in exprs {
3111                    f(expr);
3112                }
3113            }
3114            Filter {
3115                input: _,
3116                predicates,
3117            } => {
3118                for predicate in predicates {
3119                    f(predicate);
3120                }
3121            }
3122            Join {
3123                left: _,
3124                right: _,
3125                on,
3126                kind: _,
3127            } => f(on),
3128            Reduce {
3129                input: _,
3130                group_key: _,
3131                aggregates,
3132                expected_group_size: _,
3133            } => {
3134                for aggregate in aggregates {
3135                    f(aggregate.expr.as_ref());
3136                }
3137            }
3138            TopK {
3139                input: _,
3140                group_key: _,
3141                order_key: _,
3142                limit,
3143                offset,
3144                expected_group_size: _,
3145            } => {
3146                if let Some(limit) = limit {
3147                    f(limit)
3148                }
3149                f(offset)
3150            }
3151            Distinct { input: _ }
3152            | Negate { input: _ }
3153            | Threshold { input: _ }
3154            | Union { base: _, inputs: _ } => (),
3155        }
3156    }
3157
3158    fn visit_mut_children<F>(&mut self, mut f: F)
3159    where
3160        F: FnMut(&mut HirScalarExpr),
3161    {
3162        use HirRelationExpr::*;
3163        match self {
3164            Constant { rows: _, typ: _ }
3165            | Get { id: _, typ: _ }
3166            | Let {
3167                name: _,
3168                id: _,
3169                value: _,
3170                body: _,
3171            }
3172            | LetRec {
3173                limit: _,
3174                bindings: _,
3175                body: _,
3176            }
3177            | Project {
3178                input: _,
3179                outputs: _,
3180            } => (),
3181            Map { input: _, scalars } => {
3182                for scalar in scalars {
3183                    f(scalar);
3184                }
3185            }
3186            CallTable { func: _, exprs } => {
3187                for expr in exprs {
3188                    f(expr);
3189                }
3190            }
3191            Filter {
3192                input: _,
3193                predicates,
3194            } => {
3195                for predicate in predicates {
3196                    f(predicate);
3197                }
3198            }
3199            Join {
3200                left: _,
3201                right: _,
3202                on,
3203                kind: _,
3204            } => f(on),
3205            Reduce {
3206                input: _,
3207                group_key: _,
3208                aggregates,
3209                expected_group_size: _,
3210            } => {
3211                for aggregate in aggregates {
3212                    f(aggregate.expr.as_mut());
3213                }
3214            }
3215            TopK {
3216                input: _,
3217                group_key: _,
3218                order_key: _,
3219                limit,
3220                offset,
3221                expected_group_size: _,
3222            } => {
3223                if let Some(limit) = limit {
3224                    f(limit)
3225                }
3226                f(offset)
3227            }
3228            Distinct { input: _ }
3229            | Negate { input: _ }
3230            | Threshold { input: _ }
3231            | Union { base: _, inputs: _ } => (),
3232        }
3233    }
3234
3235    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
3236    where
3237        F: FnMut(&HirScalarExpr) -> Result<(), E>,
3238    {
3239        use HirRelationExpr::*;
3240        match self {
3241            Constant { rows: _, typ: _ }
3242            | Get { id: _, typ: _ }
3243            | Let {
3244                name: _,
3245                id: _,
3246                value: _,
3247                body: _,
3248            }
3249            | LetRec {
3250                limit: _,
3251                bindings: _,
3252                body: _,
3253            }
3254            | Project {
3255                input: _,
3256                outputs: _,
3257            } => (),
3258            Map { input: _, scalars } => {
3259                for scalar in scalars {
3260                    f(scalar)?;
3261                }
3262            }
3263            CallTable { func: _, exprs } => {
3264                for expr in exprs {
3265                    f(expr)?;
3266                }
3267            }
3268            Filter {
3269                input: _,
3270                predicates,
3271            } => {
3272                for predicate in predicates {
3273                    f(predicate)?;
3274                }
3275            }
3276            Join {
3277                left: _,
3278                right: _,
3279                on,
3280                kind: _,
3281            } => f(on)?,
3282            Reduce {
3283                input: _,
3284                group_key: _,
3285                aggregates,
3286                expected_group_size: _,
3287            } => {
3288                for aggregate in aggregates {
3289                    f(aggregate.expr.as_ref())?;
3290                }
3291            }
3292            TopK {
3293                input: _,
3294                group_key: _,
3295                order_key: _,
3296                limit,
3297                offset,
3298                expected_group_size: _,
3299            } => {
3300                if let Some(limit) = limit {
3301                    f(limit)?
3302                }
3303                f(offset)?
3304            }
3305            Distinct { input: _ }
3306            | Negate { input: _ }
3307            | Threshold { input: _ }
3308            | Union { base: _, inputs: _ } => (),
3309        }
3310        Ok(())
3311    }
3312
3313    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
3314    where
3315        F: FnMut(&mut HirScalarExpr) -> Result<(), E>,
3316    {
3317        use HirRelationExpr::*;
3318        match self {
3319            Constant { rows: _, typ: _ }
3320            | Get { id: _, typ: _ }
3321            | Let {
3322                name: _,
3323                id: _,
3324                value: _,
3325                body: _,
3326            }
3327            | LetRec {
3328                limit: _,
3329                bindings: _,
3330                body: _,
3331            }
3332            | Project {
3333                input: _,
3334                outputs: _,
3335            } => (),
3336            Map { input: _, scalars } => {
3337                for scalar in scalars {
3338                    f(scalar)?;
3339                }
3340            }
3341            CallTable { func: _, exprs } => {
3342                for expr in exprs {
3343                    f(expr)?;
3344                }
3345            }
3346            Filter {
3347                input: _,
3348                predicates,
3349            } => {
3350                for predicate in predicates {
3351                    f(predicate)?;
3352                }
3353            }
3354            Join {
3355                left: _,
3356                right: _,
3357                on,
3358                kind: _,
3359            } => f(on)?,
3360            Reduce {
3361                input: _,
3362                group_key: _,
3363                aggregates,
3364                expected_group_size: _,
3365            } => {
3366                for aggregate in aggregates {
3367                    f(aggregate.expr.as_mut())?;
3368                }
3369            }
3370            TopK {
3371                input: _,
3372                group_key: _,
3373                order_key: _,
3374                limit,
3375                offset,
3376                expected_group_size: _,
3377            } => {
3378                if let Some(limit) = limit {
3379                    f(limit)?
3380                }
3381                f(offset)?
3382            }
3383            Distinct { input: _ }
3384            | Negate { input: _ }
3385            | Threshold { input: _ }
3386            | Union { base: _, inputs: _ } => (),
3387        }
3388        Ok(())
3389    }
3390
3391    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a HirScalarExpr>
3392    where
3393        HirScalarExpr: 'a,
3394    {
3395        use HirRelationExpr::*;
3396        match self {
3397            Constant { rows: _, typ: _ }
3398            | Get { id: _, typ: _ }
3399            | Let {
3400                name: _,
3401                id: _,
3402                value: _,
3403                body: _,
3404            }
3405            | LetRec {
3406                limit: _,
3407                bindings: _,
3408                body: _,
3409            }
3410            | Project {
3411                input: _,
3412                outputs: _,
3413            }
3414            | Distinct { input: _ }
3415            | Negate { input: _ }
3416            | Threshold { input: _ }
3417            | Union { base: _, inputs: _ } => vec![],
3418            Map { input: _, scalars }
3419            | CallTable {
3420                func: _,
3421                exprs: scalars,
3422            }
3423            | Filter {
3424                input: _,
3425                predicates: scalars,
3426            } => scalars.iter().collect(),
3427            Join {
3428                left: _,
3429                right: _,
3430                on,
3431                kind: _,
3432            } => vec![on],
3433            Reduce {
3434                input: _,
3435                group_key: _,
3436                aggregates,
3437                expected_group_size: _,
3438            } => aggregates.iter().map(|agg| &*agg.expr).collect(),
3439            TopK {
3440                input: _,
3441                group_key: _,
3442                order_key: _,
3443                limit,
3444                offset,
3445                expected_group_size: _,
3446            } => limit.iter().chain(std::iter::once(offset)).collect(),
3447        }
3448        .into_iter()
3449    }
3450
3451    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut HirScalarExpr>
3452    where
3453        HirScalarExpr: 'a,
3454    {
3455        use HirRelationExpr::*;
3456        match self {
3457            Constant { rows: _, typ: _ }
3458            | Get { id: _, typ: _ }
3459            | Let {
3460                name: _,
3461                id: _,
3462                value: _,
3463                body: _,
3464            }
3465            | LetRec {
3466                limit: _,
3467                bindings: _,
3468                body: _,
3469            }
3470            | Project {
3471                input: _,
3472                outputs: _,
3473            }
3474            | Distinct { input: _ }
3475            | Negate { input: _ }
3476            | Threshold { input: _ }
3477            | Union { base: _, inputs: _ } => vec![],
3478            Map { input: _, scalars }
3479            | CallTable {
3480                func: _,
3481                exprs: scalars,
3482            }
3483            | Filter {
3484                input: _,
3485                predicates: scalars,
3486            } => scalars.iter_mut().collect(),
3487            Join {
3488                left: _,
3489                right: _,
3490                on,
3491                kind: _,
3492            } => vec![on],
3493            Reduce {
3494                input: _,
3495                group_key: _,
3496                aggregates,
3497                expected_group_size: _,
3498            } => aggregates.iter_mut().map(|agg| &mut *agg.expr).collect(),
3499            TopK {
3500                input: _,
3501                group_key: _,
3502                order_key: _,
3503                limit,
3504                offset,
3505                expected_group_size: _,
3506            } => limit.iter_mut().chain(std::iter::once(offset)).collect(),
3507        }
3508        .into_iter()
3509    }
3510}
3511
3512impl HirScalarExpr {
3513    pub fn name(&self) -> Option<Arc<str>> {
3514        use HirScalarExpr::*;
3515        match self {
3516            Column(_, name)
3517            | Parameter(_, name)
3518            | Literal(_, _, name)
3519            | CallUnmaterializable(_, name)
3520            | CallUnary { name, .. }
3521            | CallBinary { name, .. }
3522            | CallVariadic { name, .. }
3523            | If { name, .. }
3524            | Exists(_, name)
3525            | Select(_, name)
3526            | Windowing(_, name) => name.0.clone(),
3527        }
3528    }
3529
3530    /// Visit every subquery, without descending into subqueries.
3531    pub fn visit_direct_subqueries<F>(&self, mut f: F)
3532    where
3533        F: FnMut(&HirRelationExpr),
3534    {
3535        self.visit_post(&mut |e| {
3536            VisitChildren::<HirRelationExpr>::visit_children(e, &mut f);
3537        });
3538    }
3539
3540    /// Mutable counterpart of [`HirScalarExpr::visit_direct_subqueries`].
3541    pub fn visit_direct_subqueries_mut<F>(&mut self, mut f: F)
3542    where
3543        F: FnMut(&mut HirRelationExpr),
3544    {
3545        self.visit_mut_post(&mut |e| {
3546            VisitChildren::<HirRelationExpr>::visit_mut_children(e, &mut f);
3547        });
3548    }
3549
3550    /// Fallible counterpart of [`HirScalarExpr::visit_direct_subqueries`].
3551    pub fn try_visit_direct_subqueries<F, E>(&self, mut f: F) -> Result<(), E>
3552    where
3553        F: FnMut(&HirRelationExpr) -> Result<(), E>,
3554    {
3555        self.try_visit_post(&mut |e| {
3556            VisitChildren::<HirRelationExpr>::try_visit_children(e, &mut f)
3557        })
3558    }
3559
3560    /// Fallible mutable counterpart of [`HirScalarExpr::visit_direct_subqueries`].
3561    pub fn try_visit_direct_subqueries_mut<F, E>(&mut self, mut f: F) -> Result<(), E>
3562    where
3563        F: FnMut(&mut HirRelationExpr) -> Result<(), E>,
3564    {
3565        self.try_visit_mut_post(&mut |e| {
3566            VisitChildren::<HirRelationExpr>::try_visit_mut_children(e, &mut f)
3567        })
3568    }
3569
3570    /// Replaces parameter references in the expression with the corresponding datum from `params`.
3571    /// Additionally, it simplifies OFFSET clauses to constants after parameter binding, and checks
3572    /// them for non-negativity.
3573    ///
3574    /// This handles subqueries nested inside `self` by calling back into
3575    /// [`HirRelationExpr::bind_parameters_and_simplify_offset`] on each direct subquery; that
3576    /// relation-level function in turn calls back here for the scalar expressions it holds, so
3577    /// the two functions corecursively cover the entire HIR tree.
3578    pub fn bind_parameters_and_simplify_offset(
3579        &mut self,
3580        scx: &StatementContext,
3581        lifetime: QueryLifetime,
3582        params: &Params,
3583    ) -> Result<(), PlanError> {
3584        // First, rewrite each `Parameter` node to a literal. This walks only the scalar tree;
3585        // it does not yet descend into subqueries.
3586        self.try_visit_mut_post(&mut |e: &mut HirScalarExpr| {
3587            if let HirScalarExpr::Parameter(n, name) = e {
3588                let datum = match params.datums.iter().nth(*n - 1) {
3589                    None => return Err(PlanError::UnknownParameter(*n)),
3590                    Some(datum) => datum,
3591                };
3592                let scalar_type = &params.execute_types[*n - 1];
3593                let row = Row::pack([datum]);
3594                let column_type = scalar_type.clone().nullable(datum.is_null());
3595
3596                let name = if let Some(name) = &name.0 {
3597                    Some(Arc::clone(name))
3598                } else {
3599                    Some(Arc::from(format!("${n}")))
3600                };
3601
3602                let qcx = QueryContext::root(scx, lifetime);
3603                let ecx = execute_expr_context(&qcx);
3604
3605                *e = plan_cast(
3606                    &ecx,
3607                    *EXECUTE_CAST_CONTEXT,
3608                    HirScalarExpr::Literal(row, column_type, TreatAsEqual(name)),
3609                    &params.expected_types[*n - 1],
3610                )
3611                .expect("checked in plan_params");
3612            }
3613            Ok(())
3614        })?;
3615        // Then descend into any subqueries; the relation-side `bind_parameters_and_simplify_offset`
3616        // handles corecursion back into scalars.
3617        self.try_visit_direct_subqueries_mut(|r: &mut HirRelationExpr| {
3618            r.bind_parameters_and_simplify_offset(scx, lifetime, params)
3619        })
3620    }
3621
3622    /// Like [`HirScalarExpr::bind_parameters_and_simplify_offset`], except that parameters are
3623    /// replaced with the corresponding expression fragment from `params` rather
3624    /// than a datum.
3625    ///
3626    /// Specifically, the parameter `$1` will be replaced with `params[0]`, the
3627    /// parameter `$2` will be replaced with `params[1]`, and so on. Parameters
3628    /// in `self` that refer to invalid indices of `params` will cause a panic.
3629    ///
3630    /// Column references in parameters will be corrected to account for the
3631    /// depth at which they are spliced.
3632    pub fn splice_parameters(&mut self, params: &[HirScalarExpr], depth: usize) {
3633        #[allow(deprecated)]
3634        let _ = self.visit_recursively_mut(depth, &mut |depth: usize,
3635                                                        e: &mut HirScalarExpr|
3636         -> Result<(), ()> {
3637            if let HirScalarExpr::Parameter(i, _name) = e {
3638                *e = params[*i - 1].clone();
3639                // Correct any column references in the parameter expression for
3640                // its new depth.
3641                e.visit_columns_mut(0, &mut |d: usize, col: &mut ColumnRef| {
3642                    if col.level >= d {
3643                        col.level += depth
3644                    }
3645                });
3646            }
3647            Ok(())
3648        });
3649    }
3650
3651    /// Whether the expression contains an [`UnmaterializableFunc::MzNow`] call.
3652    pub fn contains_temporal(&self) -> bool {
3653        let mut contains = false;
3654        self.visit_post(&mut |e| {
3655            if let Self::CallUnmaterializable(UnmaterializableFunc::MzNow, _name) = e {
3656                contains = true;
3657            }
3658        });
3659        contains
3660    }
3661
3662    /// Whether the expression contains any [`UnmaterializableFunc`] call.
3663    pub fn contains_unmaterializable(&self) -> bool {
3664        let mut contains = false;
3665        self.visit_post(&mut |e| {
3666            if let Self::CallUnmaterializable(_, _) = e {
3667                contains = true;
3668            }
3669        });
3670        contains
3671    }
3672
3673    /// Whether the expression contains any [`UnmaterializableFunc`] call other than
3674    /// [`UnmaterializableFunc::MzNow`].
3675    pub fn contains_unmaterializable_except_temporal(&self) -> bool {
3676        let mut contains = false;
3677        self.visit_post(&mut |e| {
3678            if let Self::CallUnmaterializable(f, _) = e {
3679                if *f != UnmaterializableFunc::MzNow {
3680                    contains = true;
3681                }
3682            }
3683        });
3684        contains
3685    }
3686
3687    /// Constructs an unnamed column reference in the current scope.
3688    /// Use [`HirScalarExpr::named_column`] when a name is known.
3689    /// Use [`HirScalarExpr::unnamed_column`] for a `ColumnRef`.
3690    pub fn column(index: usize) -> HirScalarExpr {
3691        HirScalarExpr::Column(
3692            ColumnRef {
3693                level: 0,
3694                column: index,
3695            },
3696            TreatAsEqual(None),
3697        )
3698    }
3699
3700    /// Constructs an unnamed column reference.
3701    pub fn unnamed_column(cr: ColumnRef) -> HirScalarExpr {
3702        HirScalarExpr::Column(cr, TreatAsEqual(None))
3703    }
3704
3705    /// Constructs a named column reference.
3706    /// Names are interned by a `NameManager`.
3707    pub fn named_column(cr: ColumnRef, name: Arc<str>) -> HirScalarExpr {
3708        HirScalarExpr::Column(cr, TreatAsEqual(Some(name)))
3709    }
3710
3711    pub fn parameter(n: usize) -> HirScalarExpr {
3712        HirScalarExpr::Parameter(n, TreatAsEqual(None))
3713    }
3714
3715    pub fn literal(datum: Datum, scalar_type: SqlScalarType) -> HirScalarExpr {
3716        let col_type = scalar_type.nullable(datum.is_null());
3717        soft_assert_or_log!(datum.is_instance_of_sql(&col_type), "type is correct");
3718        let row = Row::pack([datum]);
3719        HirScalarExpr::Literal(row, col_type, TreatAsEqual(None))
3720    }
3721
3722    pub fn literal_true() -> HirScalarExpr {
3723        HirScalarExpr::literal(Datum::True, SqlScalarType::Bool)
3724    }
3725
3726    pub fn literal_false() -> HirScalarExpr {
3727        HirScalarExpr::literal(Datum::False, SqlScalarType::Bool)
3728    }
3729
3730    pub fn literal_null(scalar_type: SqlScalarType) -> HirScalarExpr {
3731        HirScalarExpr::literal(Datum::Null, scalar_type)
3732    }
3733
3734    pub fn literal_1d_array(
3735        datums: Vec<Datum>,
3736        element_scalar_type: SqlScalarType,
3737    ) -> Result<HirScalarExpr, PlanError> {
3738        let scalar_type = match element_scalar_type {
3739            SqlScalarType::Array(_) => {
3740                sql_bail!("cannot build array from array type");
3741            }
3742            typ => SqlScalarType::Array(Box::new(typ)).nullable(false),
3743        };
3744
3745        let mut row = Row::default();
3746        row.packer()
3747            .try_push_array(
3748                &[ArrayDimension {
3749                    lower_bound: 1,
3750                    length: datums.len(),
3751                }],
3752                datums,
3753            )
3754            .expect("array constructed to be valid");
3755
3756        Ok(HirScalarExpr::Literal(row, scalar_type, TreatAsEqual(None)))
3757    }
3758
3759    pub fn as_literal(&self) -> Option<Datum<'_>> {
3760        if let HirScalarExpr::Literal(row, _column_type, _name) = self {
3761            Some(row.unpack_first())
3762        } else {
3763            None
3764        }
3765    }
3766
3767    pub fn is_literal_true(&self) -> bool {
3768        Some(Datum::True) == self.as_literal()
3769    }
3770
3771    pub fn is_literal_false(&self) -> bool {
3772        Some(Datum::False) == self.as_literal()
3773    }
3774
3775    pub fn is_literal_null(&self) -> bool {
3776        Some(Datum::Null) == self.as_literal()
3777    }
3778
3779    /// Return true iff `self` consists only of literals, materializable function calls, and
3780    /// if-else statements.
3781    pub fn is_constant(&self) -> bool {
3782        let mut worklist = vec![self];
3783        while let Some(expr) = worklist.pop() {
3784            match expr {
3785                Self::Literal(..) => {
3786                    // leaf node, do nothing
3787                }
3788                Self::CallUnary { expr, .. } => {
3789                    worklist.push(expr);
3790                }
3791                Self::CallBinary {
3792                    func: _,
3793                    expr1,
3794                    expr2,
3795                    name: _,
3796                } => {
3797                    worklist.push(expr1);
3798                    worklist.push(expr2);
3799                }
3800                Self::CallVariadic {
3801                    func: _,
3802                    exprs,
3803                    name: _,
3804                } => {
3805                    worklist.extend(exprs.iter());
3806                }
3807                // (CallUnmaterializable is not allowed)
3808                Self::If {
3809                    cond,
3810                    then,
3811                    els,
3812                    name: _,
3813                } => {
3814                    worklist.push(cond);
3815                    worklist.push(then);
3816                    worklist.push(els);
3817                }
3818                _ => {
3819                    return false; // Any other node makes `self` non-constant.
3820                }
3821            }
3822        }
3823        true
3824    }
3825
3826    pub fn call_unary(self, func: UnaryFunc) -> Self {
3827        HirScalarExpr::CallUnary {
3828            func,
3829            expr: Box::new(self),
3830            name: NameMetadata::default(),
3831        }
3832    }
3833
3834    pub fn call_binary<B: Into<BinaryFunc>>(self, other: Self, func: B) -> Self {
3835        HirScalarExpr::CallBinary {
3836            func: func.into(),
3837            expr1: Box::new(self),
3838            expr2: Box::new(other),
3839            name: NameMetadata::default(),
3840        }
3841    }
3842
3843    pub fn call_unmaterializable(func: UnmaterializableFunc) -> Self {
3844        HirScalarExpr::CallUnmaterializable(func, NameMetadata::default())
3845    }
3846
3847    pub fn call_variadic<V: Into<VariadicFunc>>(func: V, exprs: Vec<Self>) -> Self {
3848        HirScalarExpr::CallVariadic {
3849            func: func.into(),
3850            exprs,
3851            name: NameMetadata::default(),
3852        }
3853    }
3854
3855    pub fn if_then_else(cond: Self, then: Self, els: Self) -> Self {
3856        HirScalarExpr::If {
3857            cond: Box::new(cond),
3858            then: Box::new(then),
3859            els: Box::new(els),
3860            name: NameMetadata::default(),
3861        }
3862    }
3863
3864    pub fn windowing(expr: WindowExpr) -> Self {
3865        HirScalarExpr::Windowing(expr, TreatAsEqual(None))
3866    }
3867
3868    pub fn or(self, other: Self) -> Self {
3869        HirScalarExpr::call_variadic(Or, vec![self, other])
3870    }
3871
3872    pub fn and(self, other: Self) -> Self {
3873        HirScalarExpr::call_variadic(And, vec![self, other])
3874    }
3875
3876    pub fn not(self) -> Self {
3877        self.call_unary(UnaryFunc::Not(func::Not))
3878    }
3879
3880    pub fn call_is_null(self) -> Self {
3881        self.call_unary(UnaryFunc::IsNull(func::IsNull))
3882    }
3883
3884    /// Calls AND with the given arguments. Simplifies if 0 or 1 args.
3885    pub fn variadic_and(mut args: Vec<HirScalarExpr>) -> HirScalarExpr {
3886        match args.len() {
3887            0 => HirScalarExpr::literal_true(), // Same as unit_of_and_or, but that's MirScalarExpr
3888            1 => args.swap_remove(0),
3889            _ => HirScalarExpr::call_variadic(And, args),
3890        }
3891    }
3892
3893    /// Calls OR with the given arguments. Simplifies if 0 or 1 args.
3894    pub fn variadic_or(mut args: Vec<HirScalarExpr>) -> HirScalarExpr {
3895        match args.len() {
3896            0 => HirScalarExpr::literal_false(), // Same as unit_of_and_or, but that's MirScalarExpr
3897            1 => args.swap_remove(0),
3898            _ => HirScalarExpr::call_variadic(Or, args),
3899        }
3900    }
3901
3902    pub fn take(&mut self) -> Self {
3903        mem::replace(self, HirScalarExpr::literal_null(SqlScalarType::String))
3904    }
3905
3906    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
3907    /// Visits the column references in this scalar expression.
3908    ///
3909    /// The `depth` argument should indicate the subquery nesting depth of the expression,
3910    /// which will be incremented with each subquery entered and presented to the supplied
3911    /// function `f`.
3912    pub fn visit_columns<F>(&self, depth: usize, f: &mut F)
3913    where
3914        F: FnMut(usize, &ColumnRef),
3915    {
3916        #[allow(deprecated)]
3917        let _ = self.visit_recursively(depth, &mut |depth: usize,
3918                                                    e: &HirScalarExpr|
3919         -> Result<(), ()> {
3920            if let HirScalarExpr::Column(col, _name) = e {
3921                f(depth, col)
3922            }
3923            Ok(())
3924        });
3925    }
3926
3927    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
3928    /// Like `visit_columns`, but permits mutating the column references.
3929    pub fn visit_columns_mut<F>(&mut self, depth: usize, f: &mut F)
3930    where
3931        F: FnMut(usize, &mut ColumnRef),
3932    {
3933        #[allow(deprecated)]
3934        let _ = self.visit_recursively_mut(depth, &mut |depth: usize,
3935                                                        e: &mut HirScalarExpr|
3936         -> Result<(), ()> {
3937            if let HirScalarExpr::Column(col, _name) = e {
3938                f(depth, col)
3939            }
3940            Ok(())
3941        });
3942    }
3943
3944    /// Visits those column references in this scalar expression that refer to the root
3945    /// level. These include column references that are at the root level, as well as column
3946    /// references that are at a deeper subquery nesting depth, but refer back to the root level.
3947    /// (Note that even if `self` is embedded inside a larger expression, we consider the
3948    /// "root level" to be `self`'s level.)
3949    pub fn visit_columns_referring_to_root_level<F>(&self, f: &mut F)
3950    where
3951        F: FnMut(usize),
3952    {
3953        #[allow(deprecated)]
3954        let _ = self.visit_recursively(0, &mut |depth: usize,
3955                                                e: &HirScalarExpr|
3956         -> Result<(), ()> {
3957            if let HirScalarExpr::Column(col, _name) = e {
3958                if col.level == depth {
3959                    f(col.column)
3960                }
3961            }
3962            Ok(())
3963        });
3964    }
3965
3966    /// Like `visit_columns_referring_to_root_level`, but permits mutating the column references.
3967    pub fn visit_columns_referring_to_root_level_mut<F>(&mut self, f: &mut F)
3968    where
3969        F: FnMut(&mut usize),
3970    {
3971        #[allow(deprecated)]
3972        let _ = self.visit_recursively_mut(0, &mut |depth: usize,
3973                                                    e: &mut HirScalarExpr|
3974         -> Result<(), ()> {
3975            if let HirScalarExpr::Column(col, _name) = e {
3976                if col.level == depth {
3977                    f(&mut col.column)
3978                }
3979            }
3980            Ok(())
3981        });
3982    }
3983
3984    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
3985    /// Like `visit` but it enters the subqueries visiting the scalar expressions contained
3986    /// in them. It takes the current depth of the expression and increases it when
3987    /// entering a subquery.
3988    pub fn visit_recursively<F, E>(&self, depth: usize, f: &mut F) -> Result<(), E>
3989    where
3990        F: FnMut(usize, &HirScalarExpr) -> Result<(), E>,
3991    {
3992        match self {
3993            HirScalarExpr::Literal(..)
3994            | HirScalarExpr::Parameter(..)
3995            | HirScalarExpr::CallUnmaterializable(..)
3996            | HirScalarExpr::Column(..) => (),
3997            HirScalarExpr::CallUnary { expr, .. } => expr.visit_recursively(depth, f)?,
3998            HirScalarExpr::CallBinary { expr1, expr2, .. } => {
3999                expr1.visit_recursively(depth, f)?;
4000                expr2.visit_recursively(depth, f)?;
4001            }
4002            HirScalarExpr::CallVariadic { exprs, .. } => {
4003                for expr in exprs {
4004                    expr.visit_recursively(depth, f)?;
4005                }
4006            }
4007            HirScalarExpr::If {
4008                cond,
4009                then,
4010                els,
4011                name: _,
4012            } => {
4013                cond.visit_recursively(depth, f)?;
4014                then.visit_recursively(depth, f)?;
4015                els.visit_recursively(depth, f)?;
4016            }
4017            HirScalarExpr::Exists(expr, _name) | HirScalarExpr::Select(expr, _name) => {
4018                #[allow(deprecated)]
4019                expr.visit_scalar_expressions(depth + 1, &mut |e, depth| {
4020                    e.visit_recursively(depth, f)
4021                })?;
4022            }
4023            HirScalarExpr::Windowing(expr, _name) => {
4024                expr.visit_expressions(&mut |e| e.visit_recursively(depth, f))?;
4025            }
4026        }
4027        f(depth, self)
4028    }
4029
4030    #[deprecated = "Redefine this based on the `Visit` and `VisitChildren` methods."]
4031    /// Like `visit_recursively`, but permits mutating the scalar expressions.
4032    pub fn visit_recursively_mut<F, E>(&mut self, depth: usize, f: &mut F) -> Result<(), E>
4033    where
4034        F: FnMut(usize, &mut HirScalarExpr) -> Result<(), E>,
4035    {
4036        match self {
4037            HirScalarExpr::Literal(..)
4038            | HirScalarExpr::Parameter(..)
4039            | HirScalarExpr::CallUnmaterializable(..)
4040            | HirScalarExpr::Column(..) => (),
4041            HirScalarExpr::CallUnary { expr, .. } => expr.visit_recursively_mut(depth, f)?,
4042            HirScalarExpr::CallBinary { expr1, expr2, .. } => {
4043                expr1.visit_recursively_mut(depth, f)?;
4044                expr2.visit_recursively_mut(depth, f)?;
4045            }
4046            HirScalarExpr::CallVariadic { exprs, .. } => {
4047                for expr in exprs {
4048                    expr.visit_recursively_mut(depth, f)?;
4049                }
4050            }
4051            HirScalarExpr::If {
4052                cond,
4053                then,
4054                els,
4055                name: _,
4056            } => {
4057                cond.visit_recursively_mut(depth, f)?;
4058                then.visit_recursively_mut(depth, f)?;
4059                els.visit_recursively_mut(depth, f)?;
4060            }
4061            HirScalarExpr::Exists(expr, _name) | HirScalarExpr::Select(expr, _name) => {
4062                #[allow(deprecated)]
4063                expr.visit_scalar_expressions_mut(depth + 1, &mut |e, depth| {
4064                    e.visit_recursively_mut(depth, f)
4065                })?;
4066            }
4067            HirScalarExpr::Windowing(expr, _name) => {
4068                expr.visit_expressions_mut(&mut |e| e.visit_recursively_mut(depth, f))?;
4069            }
4070        }
4071        f(depth, self)
4072    }
4073
4074    /// Attempts to simplify self into a literal.
4075    ///
4076    /// Returns None if self is not constant and therefore can't be simplified to a literal, or if
4077    /// an evaluation error occurs during simplification, or if self contains
4078    /// - a subquery
4079    /// - a column reference to an outer level
4080    /// - a parameter
4081    /// - a window function call
4082    fn simplify_to_literal(self) -> Option<Row> {
4083        let mut expr = self
4084            .lower_uncorrelated(crate::plan::lowering::Config::default())
4085            .ok()?;
4086        // Using MIR evaluation with repr types is fine here: the
4087        // result is an untyped Row, so any intermediate type
4088        // canonicalization is discarded.
4089        expr.reduce(&[]);
4090        match expr {
4091            mz_expr::MirScalarExpr::Literal(Ok(row), _) => Some(row),
4092            _ => None,
4093        }
4094    }
4095
4096    /// Simplifies self into a literal. If this is not possible (e.g., because self is not constant
4097    /// or an evaluation error occurs during simplification), it returns
4098    /// [`PlanError::ConstantExpressionSimplificationFailed`].
4099    ///
4100    /// The returned error is an _internal_ error if the expression contains
4101    /// - a subquery
4102    /// - a column reference to an outer level
4103    /// - a parameter
4104    /// - a window function call
4105    ///
4106    /// TODO: use this everywhere instead of `simplify_to_literal`, so that we don't hide the error
4107    /// msg.
4108    fn simplify_to_literal_with_result(self) -> Result<Row, PlanError> {
4109        let mut expr = self
4110            .lower_uncorrelated(crate::plan::lowering::Config::default())
4111            .map_err(|err| {
4112                PlanError::ConstantExpressionSimplificationFailed(err.to_string_with_causes())
4113            })?;
4114        // Using MIR evaluation with repr types is fine here: the
4115        // result is an untyped Row, so any intermediate type
4116        // canonicalization is discarded.
4117        expr.reduce(&[]);
4118        match expr {
4119            mz_expr::MirScalarExpr::Literal(Ok(row), _) => Ok(row),
4120            mz_expr::MirScalarExpr::Literal(Err(err), _) => Err(
4121                PlanError::ConstantExpressionSimplificationFailed(err.to_string_with_causes()),
4122            ),
4123            _ => Err(PlanError::ConstantExpressionSimplificationFailed(
4124                "Not a constant".to_string(),
4125            )),
4126        }
4127    }
4128
4129    /// Attempts to simplify this expression to a literal 64-bit integer.
4130    ///
4131    /// Returns `None` if this expression cannot be simplified, e.g. because it
4132    /// contains non-literal values.
4133    ///
4134    /// # Panics
4135    ///
4136    /// Panics if this expression does not have type [`SqlScalarType::Int64`].
4137    pub fn into_literal_int64(self) -> Option<i64> {
4138        self.simplify_to_literal().and_then(|row| {
4139            let datum = row.unpack_first();
4140            if datum.is_null() {
4141                None
4142            } else {
4143                Some(datum.unwrap_int64())
4144            }
4145        })
4146    }
4147
4148    /// Attempts to simplify this expression to a literal string.
4149    ///
4150    /// Returns `None` if this expression cannot be simplified, e.g. because it
4151    /// contains non-literal values.
4152    ///
4153    /// # Panics
4154    ///
4155    /// Panics if this expression does not have type [`SqlScalarType::String`].
4156    pub fn into_literal_string(self) -> Option<String> {
4157        self.simplify_to_literal().and_then(|row| {
4158            let datum = row.unpack_first();
4159            if datum.is_null() {
4160                None
4161            } else {
4162                Some(datum.unwrap_str().to_owned())
4163            }
4164        })
4165    }
4166
4167    /// Attempts to simplify this expression to a literal MzTimestamp.
4168    ///
4169    /// Returns `None` if the expression simplifies to `null` or if the expression cannot be
4170    /// simplified, e.g. because it contains non-literal values or a cast fails.
4171    ///
4172    /// TODO: Make this (and the other similar fns above) return Result, so that we can show the
4173    /// error when it fails. (E.g., there can be non-trivial cast errors.)
4174    /// See `try_into_literal_int64` as an example.
4175    ///
4176    /// # Panics
4177    ///
4178    /// Panics if this expression does not have type [`SqlScalarType::MzTimestamp`].
4179    pub fn into_literal_mz_timestamp(self) -> Option<Timestamp> {
4180        self.simplify_to_literal().and_then(|row| {
4181            let datum = row.unpack_first();
4182            if datum.is_null() {
4183                None
4184            } else {
4185                Some(datum.unwrap_mz_timestamp())
4186            }
4187        })
4188    }
4189
4190    /// Attempts to simplify this expression of [`SqlScalarType::Int64`] to a literal Int64 and
4191    /// returns it as an i64.
4192    ///
4193    /// Returns `PlanError::ConstantExpressionSimplificationFailed` if
4194    /// - it's not a constant expression (as determined by `is_constant`)
4195    /// - evaluates to null
4196    /// - an EvalError occurs during evaluation (e.g., a cast fails)
4197    ///
4198    /// # Panics
4199    ///
4200    /// Panics if this expression does not have type [`SqlScalarType::Int64`].
4201    pub fn try_into_literal_int64(self) -> Result<i64, PlanError> {
4202        // TODO: add the `is_constant` check also to all the other into_literal_... (by adding it to
4203        // `simplify_to_literal`), but those should be just soft_asserts at first that it doesn't
4204        // actually happen that it's weaker than `reduce`, and then add them for real after 1 week.
4205        // (Without the is_constant check, lower_uncorrelated's preconditions spill out to be
4206        // preconditions also of all the other into_literal_... functions.)
4207        if !self.is_constant() {
4208            return Err(PlanError::ConstantExpressionSimplificationFailed(format!(
4209                "Expected a constant expression, got {}",
4210                self
4211            )));
4212        }
4213        self.clone()
4214            .simplify_to_literal_with_result()
4215            .and_then(|row| {
4216                let datum = row.unpack_first();
4217                if datum.is_null() {
4218                    Err(PlanError::ConstantExpressionSimplificationFailed(format!(
4219                        "Expected an expression that evaluates to a non-null value, got {}",
4220                        self
4221                    )))
4222                } else {
4223                    Ok(datum.unwrap_int64())
4224                }
4225            })
4226    }
4227
4228    pub fn contains_parameters(&self) -> bool {
4229        let mut contains_parameters = false;
4230        #[allow(deprecated)]
4231        let _ = self.visit_recursively(0, &mut |_depth: usize,
4232                                                expr: &HirScalarExpr|
4233         -> Result<(), ()> {
4234            if let HirScalarExpr::Parameter(..) = expr {
4235                contains_parameters = true;
4236            }
4237            Ok(())
4238        });
4239        contains_parameters
4240    }
4241
4242    fn direct_subqueries(&self) -> Vec<&HirRelationExpr> {
4243        let mut subqueries: Vec<&HirRelationExpr> = vec![];
4244
4245        let mut worklist = vec![self];
4246        while let Some(elt) = worklist.pop() {
4247            match elt {
4248                HirScalarExpr::Column(_, _)
4249                | HirScalarExpr::Parameter(_, _)
4250                | HirScalarExpr::Literal(_, _, _)
4251                | HirScalarExpr::CallUnmaterializable(_, _) => (),
4252                HirScalarExpr::CallUnary {
4253                    func: _,
4254                    expr,
4255                    name: _,
4256                } => worklist.push(&*expr),
4257                HirScalarExpr::CallBinary {
4258                    func: _,
4259                    expr1,
4260                    expr2,
4261                    name: _name,
4262                } => {
4263                    // Push in reverse so children pop (and are visited) left-to-right.
4264                    worklist.push(&*expr2);
4265                    worklist.push(&*expr1);
4266                }
4267                HirScalarExpr::CallVariadic {
4268                    func: _,
4269                    exprs,
4270                    name: _name,
4271                } => {
4272                    worklist.extend(exprs.iter().rev());
4273                }
4274                HirScalarExpr::If {
4275                    cond,
4276                    then,
4277                    els,
4278                    name: _,
4279                } => {
4280                    worklist.push(&*els);
4281                    worklist.push(&*then);
4282                    worklist.push(&*cond);
4283                }
4284                HirScalarExpr::Exists(hir, _) | HirScalarExpr::Select(hir, _) => {
4285                    subqueries.push(&*hir);
4286                }
4287                HirScalarExpr::Windowing(
4288                    WindowExpr {
4289                        func,
4290                        partition_by,
4291                        order_by,
4292                    },
4293                    _,
4294                ) => {
4295                    // Push in reverse so children pop (and are visited) left-to-right:
4296                    // func args, then partition_by, then order_by.
4297                    worklist.extend(order_by.iter().rev());
4298                    worklist.extend(partition_by.iter().rev());
4299                    match func {
4300                        WindowExprType::Scalar(_) => (),
4301                        WindowExprType::Value(val) => worklist.push(&*val.args),
4302                        WindowExprType::Aggregate(agg) => worklist.push(&*agg.aggregate_expr.expr),
4303                    }
4304                }
4305            }
4306        }
4307
4308        subqueries
4309    }
4310
4311    fn direct_subqueries_mut(&mut self) -> Vec<&mut HirRelationExpr> {
4312        let mut subqueries: Vec<&mut HirRelationExpr> = vec![];
4313
4314        let mut worklist = vec![self];
4315        while let Some(elt) = worklist.pop() {
4316            match elt {
4317                HirScalarExpr::Column(_, _)
4318                | HirScalarExpr::Parameter(_, _)
4319                | HirScalarExpr::Literal(_, _, _)
4320                | HirScalarExpr::CallUnmaterializable(_, _) => (),
4321                HirScalarExpr::CallUnary {
4322                    func: _,
4323                    expr,
4324                    name: _,
4325                } => worklist.push(&mut **expr),
4326                HirScalarExpr::CallBinary {
4327                    func: _,
4328                    expr1,
4329                    expr2,
4330                    name: _name,
4331                } => {
4332                    // Push in reverse so children pop (and are visited) left-to-right.
4333                    worklist.push(&mut **expr2);
4334                    worklist.push(&mut **expr1);
4335                }
4336                HirScalarExpr::CallVariadic {
4337                    func: _,
4338                    exprs,
4339                    name: _name,
4340                } => {
4341                    worklist.extend(exprs.iter_mut().rev());
4342                }
4343                HirScalarExpr::If {
4344                    cond,
4345                    then,
4346                    els,
4347                    name: _,
4348                } => {
4349                    worklist.push(&mut **els);
4350                    worklist.push(&mut **then);
4351                    worklist.push(&mut **cond);
4352                }
4353                HirScalarExpr::Exists(hir, _) | HirScalarExpr::Select(hir, _) => {
4354                    subqueries.push(&mut **hir);
4355                }
4356                HirScalarExpr::Windowing(
4357                    WindowExpr {
4358                        func,
4359                        partition_by,
4360                        order_by,
4361                    },
4362                    _,
4363                ) => {
4364                    // Push in reverse so children pop (and are visited) left-to-right:
4365                    // func args, then partition_by, then order_by.
4366                    worklist.extend(order_by.iter_mut().rev());
4367                    worklist.extend(partition_by.iter_mut().rev());
4368                    match func {
4369                        WindowExprType::Scalar(_) => (),
4370                        WindowExprType::Value(val) => worklist.push(&mut val.args),
4371                        WindowExprType::Aggregate(agg) => {
4372                            worklist.push(&mut agg.aggregate_expr.expr)
4373                        }
4374                    }
4375                }
4376            }
4377        }
4378
4379        subqueries
4380    }
4381}
4382
4383/// Yields the direct scalar children of `self`. Stops at `Exists` / `Select`:
4384/// scalars inside subquery bodies are not surfaced. The asymmetry with
4385/// `VisitChildren<Self> for HirRelationExpr` (which does see through scalars
4386/// into subqueries) is what avoids the mutual recursion warned about on the
4387/// [`VisitChildren`] trait.
4388impl VisitChildren<Self> for HirScalarExpr {
4389    fn visit_children<F>(&self, mut f: F)
4390    where
4391        F: FnMut(&Self),
4392    {
4393        use HirScalarExpr::*;
4394        match self {
4395            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => (),
4396            CallUnary { expr, .. } => f(expr),
4397            CallBinary { expr1, expr2, .. } => {
4398                f(expr1);
4399                f(expr2);
4400            }
4401            CallVariadic { exprs, .. } => {
4402                for expr in exprs {
4403                    f(expr);
4404                }
4405            }
4406            If {
4407                cond,
4408                then,
4409                els,
4410                name: _,
4411            } => {
4412                f(cond);
4413                f(then);
4414                f(els);
4415            }
4416            Exists(..) | Select(..) => (),
4417            Windowing(expr, _name) => expr.visit_children(f),
4418        }
4419    }
4420
4421    fn visit_mut_children<F>(&mut self, mut f: F)
4422    where
4423        F: FnMut(&mut Self),
4424    {
4425        use HirScalarExpr::*;
4426        match self {
4427            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => (),
4428            CallUnary { expr, .. } => f(expr),
4429            CallBinary { expr1, expr2, .. } => {
4430                f(expr1);
4431                f(expr2);
4432            }
4433            CallVariadic { exprs, .. } => {
4434                for expr in exprs {
4435                    f(expr);
4436                }
4437            }
4438            If {
4439                cond,
4440                then,
4441                els,
4442                name: _,
4443            } => {
4444                f(cond);
4445                f(then);
4446                f(els);
4447            }
4448            Exists(..) | Select(..) => (),
4449            Windowing(expr, _name) => expr.visit_mut_children(f),
4450        }
4451    }
4452
4453    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
4454    where
4455        F: FnMut(&Self) -> Result<(), E>,
4456    {
4457        use HirScalarExpr::*;
4458        match self {
4459            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => (),
4460            CallUnary { expr, .. } => f(expr)?,
4461            CallBinary { expr1, expr2, .. } => {
4462                f(expr1)?;
4463                f(expr2)?;
4464            }
4465            CallVariadic { exprs, .. } => {
4466                for expr in exprs {
4467                    f(expr)?;
4468                }
4469            }
4470            If {
4471                cond,
4472                then,
4473                els,
4474                name: _,
4475            } => {
4476                f(cond)?;
4477                f(then)?;
4478                f(els)?;
4479            }
4480            Exists(..) | Select(..) => (),
4481            Windowing(expr, _name) => expr.try_visit_children(f)?,
4482        }
4483        Ok(())
4484    }
4485
4486    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
4487    where
4488        F: FnMut(&mut Self) -> Result<(), E>,
4489    {
4490        use HirScalarExpr::*;
4491        match self {
4492            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => (),
4493            CallUnary { expr, .. } => f(expr)?,
4494            CallBinary { expr1, expr2, .. } => {
4495                f(expr1)?;
4496                f(expr2)?;
4497            }
4498            CallVariadic { exprs, .. } => {
4499                for expr in exprs {
4500                    f(expr)?;
4501                }
4502            }
4503            If {
4504                cond,
4505                then,
4506                els,
4507                name: _,
4508            } => {
4509                f(cond)?;
4510                f(then)?;
4511                f(els)?;
4512            }
4513            Exists(..) | Select(..) => (),
4514            Windowing(expr, _name) => expr.try_visit_mut_children(f)?,
4515        }
4516        Ok(())
4517    }
4518
4519    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a Self>
4520    where
4521        Self: 'a,
4522    {
4523        use HirScalarExpr::*;
4524        let v: Vec<&Self> = match self {
4525            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => vec![],
4526            CallUnary { expr, .. } => vec![&*expr],
4527            CallBinary { expr1, expr2, .. } => {
4528                vec![&*expr1, &*expr2]
4529            }
4530            CallVariadic { exprs, .. } => exprs.iter().collect(),
4531            If {
4532                cond,
4533                then,
4534                els,
4535                name: _,
4536            } => {
4537                vec![&*cond, &*then, &*els]
4538            }
4539            Exists(..) | Select(..) => vec![],
4540            Windowing(expr, _name) => expr.children().collect(),
4541        };
4542        v.into_iter()
4543    }
4544
4545    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut Self>
4546    where
4547        Self: 'a,
4548    {
4549        use HirScalarExpr::*;
4550        let v: Vec<&mut Self> = match self {
4551            Column(..) | Parameter(..) | Literal(..) | CallUnmaterializable(..) => vec![],
4552            CallUnary { expr, .. } => vec![&mut **expr],
4553            CallBinary { expr1, expr2, .. } => {
4554                vec![&mut **expr1, &mut **expr2]
4555            }
4556            CallVariadic { exprs, .. } => exprs.iter_mut().collect(),
4557            If {
4558                cond,
4559                then,
4560                els,
4561                name: _,
4562            } => {
4563                vec![&mut **cond, &mut **then, &mut **els]
4564            }
4565            Exists(..) | Select(..) => vec![],
4566            Windowing(expr, _name) => expr.children_mut().collect(),
4567        };
4568        v.into_iter()
4569    }
4570}
4571
4572/// Yields the immediate `HirRelationExpr` children of `self` (the bodies of
4573/// `Exists` / `Select`); does not descend into them.
4574impl VisitChildren<HirRelationExpr> for HirScalarExpr {
4575    fn visit_children<F>(&self, mut f: F)
4576    where
4577        F: FnMut(&HirRelationExpr),
4578    {
4579        use HirScalarExpr::*;
4580        match self {
4581            Column(..)
4582            | Parameter(..)
4583            | Literal(..)
4584            | CallUnmaterializable(..)
4585            | CallUnary { .. }
4586            | CallBinary { .. }
4587            | CallVariadic { .. }
4588            | If { .. }
4589            | Windowing(..) => (),
4590            Exists(expr, _name) | Select(expr, _name) => f(expr),
4591        }
4592    }
4593
4594    fn visit_mut_children<F>(&mut self, mut f: F)
4595    where
4596        F: FnMut(&mut HirRelationExpr),
4597    {
4598        use HirScalarExpr::*;
4599        match self {
4600            Column(..)
4601            | Parameter(..)
4602            | Literal(..)
4603            | CallUnmaterializable(..)
4604            | CallUnary { .. }
4605            | CallBinary { .. }
4606            | CallVariadic { .. }
4607            | If { .. }
4608            | Windowing(..) => (),
4609            Exists(expr, _name) | Select(expr, _name) => f(expr),
4610        }
4611    }
4612
4613    fn try_visit_children<F, E>(&self, mut f: F) -> Result<(), E>
4614    where
4615        F: FnMut(&HirRelationExpr) -> Result<(), E>,
4616    {
4617        use HirScalarExpr::*;
4618        match self {
4619            Column(..)
4620            | Parameter(..)
4621            | Literal(..)
4622            | CallUnmaterializable(..)
4623            | CallUnary { .. }
4624            | CallBinary { .. }
4625            | CallVariadic { .. }
4626            | If { .. }
4627            | Windowing(..) => (),
4628            Exists(expr, _name) | Select(expr, _name) => f(expr)?,
4629        }
4630        Ok(())
4631    }
4632
4633    fn try_visit_mut_children<F, E>(&mut self, mut f: F) -> Result<(), E>
4634    where
4635        F: FnMut(&mut HirRelationExpr) -> Result<(), E>,
4636    {
4637        use HirScalarExpr::*;
4638        match self {
4639            Column(..)
4640            | Parameter(..)
4641            | Literal(..)
4642            | CallUnmaterializable(..)
4643            | CallUnary { .. }
4644            | CallBinary { .. }
4645            | CallVariadic { .. }
4646            | If { .. }
4647            | Windowing(..) => (),
4648            Exists(expr, _name) | Select(expr, _name) => f(expr)?,
4649        }
4650        Ok(())
4651    }
4652
4653    fn children<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a HirRelationExpr>
4654    where
4655        HirRelationExpr: 'a,
4656    {
4657        let mut child: Option<&HirRelationExpr> = None;
4658        use HirScalarExpr::*;
4659        match self {
4660            Column(..)
4661            | Parameter(..)
4662            | Literal(..)
4663            | CallUnmaterializable(..)
4664            | CallUnary { .. }
4665            | CallBinary { .. }
4666            | CallVariadic { .. }
4667            | If { .. }
4668            | Windowing(..) => (),
4669            Exists(expr, _name) | Select(expr, _name) => child = Some(&*expr),
4670        }
4671
4672        child.into_iter()
4673    }
4674
4675    fn children_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut HirRelationExpr>
4676    where
4677        HirRelationExpr: 'a,
4678    {
4679        let mut child: Option<&mut HirRelationExpr> = None;
4680        use HirScalarExpr::*;
4681        match self {
4682            Column(..)
4683            | Parameter(..)
4684            | Literal(..)
4685            | CallUnmaterializable(..)
4686            | CallUnary { .. }
4687            | CallBinary { .. }
4688            | CallVariadic { .. }
4689            | If { .. }
4690            | Windowing(..) => (),
4691            Exists(expr, _name) | Select(expr, _name) => child = Some(&mut **expr),
4692        }
4693
4694        child.into_iter()
4695    }
4696}
4697
4698impl AbstractExpr for HirScalarExpr {
4699    type Type = SqlColumnType;
4700
4701    fn typ(
4702        &self,
4703        outers: &[SqlRelationType],
4704        inner: &SqlRelationType,
4705        params: &BTreeMap<usize, SqlScalarType>,
4706    ) -> Self::Type {
4707        stack::maybe_grow(|| match self {
4708            HirScalarExpr::Column(ColumnRef { level, column }, _name) => {
4709                if *level == 0 {
4710                    inner.column_types[*column].clone()
4711                } else {
4712                    outers[*level - 1].column_types[*column].clone()
4713                }
4714            }
4715            HirScalarExpr::Parameter(n, _name) => params[n].clone().nullable(true),
4716            HirScalarExpr::Literal(_, typ, _name) => typ.clone(),
4717            HirScalarExpr::CallUnmaterializable(func, _name) => func.output_sql_type(),
4718            HirScalarExpr::CallUnary {
4719                expr,
4720                func,
4721                name: _,
4722            } => func.output_sql_type(expr.typ(outers, inner, params)),
4723            HirScalarExpr::CallBinary {
4724                expr1,
4725                expr2,
4726                func,
4727                name: _,
4728            } => func.output_sql_type(&[
4729                expr1.typ(outers, inner, params),
4730                expr2.typ(outers, inner, params),
4731            ]),
4732            HirScalarExpr::CallVariadic {
4733                exprs,
4734                func,
4735                name: _,
4736            } => func.output_sql_type(exprs.iter().map(|e| e.typ(outers, inner, params)).collect()),
4737            HirScalarExpr::If {
4738                cond: _,
4739                then,
4740                els,
4741                name: _,
4742            } => {
4743                let then_type = then.typ(outers, inner, params);
4744                let else_type = els.typ(outers, inner, params);
4745                then_type.sql_union(&else_type).unwrap() // HIR deliberately not using `union`
4746            }
4747            HirScalarExpr::Exists(_, _name) => SqlScalarType::Bool.nullable(true),
4748            HirScalarExpr::Select(expr, _name) => {
4749                let mut outers = outers.to_vec();
4750                outers.insert(0, inner.clone());
4751                expr.typ(&outers, params)
4752                    .column_types
4753                    .into_element()
4754                    .nullable(true)
4755            }
4756            HirScalarExpr::Windowing(expr, _name) => expr.func.typ(outers, inner, params),
4757        })
4758    }
4759}
4760
4761impl AggregateExpr {
4762    pub fn typ(
4763        &self,
4764        outers: &[SqlRelationType],
4765        inner: &SqlRelationType,
4766        params: &BTreeMap<usize, SqlScalarType>,
4767    ) -> SqlColumnType {
4768        self.func
4769            .output_sql_type(self.expr.typ(outers, inner, params))
4770    }
4771
4772    /// Returns whether the expression is COUNT(*) or not.  Note that
4773    /// when we define the count builtin in sql::func, we convert
4774    /// COUNT(*) to COUNT(true), making it indistinguishable from
4775    /// literal COUNT(true), but we prefer to consider this as the
4776    /// former.
4777    ///
4778    /// (MIR has the same `is_count_asterisk`.)
4779    pub fn is_count_asterisk(&self) -> bool {
4780        self.func == AggregateFunc::Count && self.expr.is_literal_true() && !self.distinct
4781    }
4782}