datafusion_physical_expr_common/
sort_expr.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Sort expressions
19
20use crate::physical_expr::{fmt_sql, PhysicalExpr};
21use std::fmt;
22use std::fmt::{Display, Formatter};
23use std::hash::{Hash, Hasher};
24use std::ops::{Deref, Index, Range, RangeFrom, RangeTo};
25use std::sync::{Arc, LazyLock};
26use std::vec::IntoIter;
27
28use arrow::compute::kernels::sort::{SortColumn, SortOptions};
29use arrow::datatypes::Schema;
30use arrow::record_batch::RecordBatch;
31use datafusion_common::Result;
32use datafusion_expr_common::columnar_value::ColumnarValue;
33use itertools::Itertools;
34
35/// Represents Sort operation for a column in a RecordBatch
36///
37/// Example:
38/// ```
39/// # use std::any::Any;
40/// # use std::fmt::{Display, Formatter};
41/// # use std::hash::Hasher;
42/// # use std::sync::Arc;
43/// # use arrow::array::RecordBatch;
44/// # use datafusion_common::Result;
45/// # use arrow::compute::SortOptions;
46/// # use arrow::datatypes::{DataType, Schema};
47/// # use datafusion_expr_common::columnar_value::ColumnarValue;
48/// # use datafusion_physical_expr_common::physical_expr::PhysicalExpr;
49/// # use datafusion_physical_expr_common::sort_expr::PhysicalSortExpr;
50/// # // this crate doesn't have a physical expression implementation
51/// # // so make a really simple one
52/// # #[derive(Clone, Debug, PartialEq, Eq, Hash)]
53/// # struct MyPhysicalExpr;
54/// # impl PhysicalExpr for MyPhysicalExpr {
55/// #  fn as_any(&self) -> &dyn Any {todo!() }
56/// #  fn data_type(&self, input_schema: &Schema) -> Result<DataType> {todo!()}
57/// #  fn nullable(&self, input_schema: &Schema) -> Result<bool> {todo!() }
58/// #  fn evaluate(&self, batch: &RecordBatch) -> Result<ColumnarValue> {todo!() }
59/// #  fn children(&self) -> Vec<&Arc<dyn PhysicalExpr>> {todo!()}
60/// #  fn with_new_children(self: Arc<Self>, children: Vec<Arc<dyn PhysicalExpr>>) -> Result<Arc<dyn PhysicalExpr>> {todo!()}
61/// # fn fmt_sql(&self, f: &mut Formatter<'_>) -> std::fmt::Result { todo!() }
62/// # }
63/// # impl Display for MyPhysicalExpr {
64/// #    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "a") }
65/// # }
66/// # fn col(name: &str) -> Arc<dyn PhysicalExpr> { Arc::new(MyPhysicalExpr) }
67/// // Sort by a ASC
68/// let options = SortOptions::default();
69/// let sort_expr = PhysicalSortExpr::new(col("a"), options);
70/// assert_eq!(sort_expr.to_string(), "a ASC");
71///
72/// // Sort by a DESC NULLS LAST
73/// let sort_expr = PhysicalSortExpr::new_default(col("a"))
74///   .desc()
75///   .nulls_last();
76/// assert_eq!(sort_expr.to_string(), "a DESC NULLS LAST");
77/// ```
78#[derive(Clone, Debug)]
79pub struct PhysicalSortExpr {
80    /// Physical expression representing the column to sort
81    pub expr: Arc<dyn PhysicalExpr>,
82    /// Option to specify how the given column should be sorted
83    pub options: SortOptions,
84}
85
86impl PhysicalSortExpr {
87    /// Create a new PhysicalSortExpr
88    pub fn new(expr: Arc<dyn PhysicalExpr>, options: SortOptions) -> Self {
89        Self { expr, options }
90    }
91
92    /// Create a new PhysicalSortExpr with default [`SortOptions`]
93    pub fn new_default(expr: Arc<dyn PhysicalExpr>) -> Self {
94        Self::new(expr, SortOptions::default())
95    }
96
97    /// Set the sort sort options to ASC
98    pub fn asc(mut self) -> Self {
99        self.options.descending = false;
100        self
101    }
102
103    /// Set the sort sort options to DESC
104    pub fn desc(mut self) -> Self {
105        self.options.descending = true;
106        self
107    }
108
109    /// Set the sort sort options to NULLS FIRST
110    pub fn nulls_first(mut self) -> Self {
111        self.options.nulls_first = true;
112        self
113    }
114
115    /// Set the sort sort options to NULLS LAST
116    pub fn nulls_last(mut self) -> Self {
117        self.options.nulls_first = false;
118        self
119    }
120
121    /// Like [`PhysicalExpr::fmt_sql`] prints a [`PhysicalSortExpr`] in a SQL-like format.
122    pub fn fmt_sql(&self, f: &mut Formatter) -> fmt::Result {
123        write!(
124            f,
125            "{} {}",
126            fmt_sql(self.expr.as_ref()),
127            to_str(&self.options)
128        )
129    }
130}
131
132/// Access the PhysicalSortExpr as a PhysicalExpr
133impl AsRef<dyn PhysicalExpr> for PhysicalSortExpr {
134    fn as_ref(&self) -> &(dyn PhysicalExpr + 'static) {
135        self.expr.as_ref()
136    }
137}
138
139impl PartialEq for PhysicalSortExpr {
140    fn eq(&self, other: &PhysicalSortExpr) -> bool {
141        self.options == other.options && self.expr.eq(&other.expr)
142    }
143}
144
145impl Eq for PhysicalSortExpr {}
146
147impl Hash for PhysicalSortExpr {
148    fn hash<H: Hasher>(&self, state: &mut H) {
149        self.expr.hash(state);
150        self.options.hash(state);
151    }
152}
153
154impl Display for PhysicalSortExpr {
155    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
156        write!(f, "{} {}", self.expr, to_str(&self.options))
157    }
158}
159
160impl PhysicalSortExpr {
161    /// evaluate the sort expression into SortColumn that can be passed into arrow sort kernel
162    pub fn evaluate_to_sort_column(&self, batch: &RecordBatch) -> Result<SortColumn> {
163        let value_to_sort = self.expr.evaluate(batch)?;
164        let array_to_sort = match value_to_sort {
165            ColumnarValue::Array(array) => array,
166            ColumnarValue::Scalar(scalar) => scalar.to_array_of_size(batch.num_rows())?,
167        };
168        Ok(SortColumn {
169            values: array_to_sort,
170            options: Some(self.options),
171        })
172    }
173
174    /// Checks whether this sort expression satisfies the given `requirement`.
175    /// If sort options are unspecified in `requirement`, only expressions are
176    /// compared for inequality.
177    pub fn satisfy(
178        &self,
179        requirement: &PhysicalSortRequirement,
180        schema: &Schema,
181    ) -> bool {
182        // If the column is not nullable, NULLS FIRST/LAST is not important.
183        let nullable = self.expr.nullable(schema).unwrap_or(true);
184        self.expr.eq(&requirement.expr)
185            && if nullable {
186                requirement.options.is_none_or(|opts| self.options == opts)
187            } else {
188                requirement
189                    .options
190                    .is_none_or(|opts| self.options.descending == opts.descending)
191            }
192    }
193}
194
195/// Represents sort requirement associated with a plan
196///
197/// If the requirement includes [`SortOptions`] then both the
198/// expression *and* the sort options must match.
199///
200/// If the requirement does not include [`SortOptions`]) then only the
201/// expressions must match.
202///
203/// # Examples
204///
205/// With sort options (`A`, `DESC NULLS FIRST`):
206/// * `ORDER BY A DESC NULLS FIRST` matches
207/// * `ORDER BY A ASC  NULLS FIRST` does not match (`ASC` vs `DESC`)
208/// * `ORDER BY B DESC NULLS FIRST` does not match (different expr)
209///
210/// Without sort options (`A`, None):
211/// * `ORDER BY A DESC NULLS FIRST` matches
212/// * `ORDER BY A ASC  NULLS FIRST` matches (`ASC` and `NULL` options ignored)
213/// * `ORDER BY B DESC NULLS FIRST` does not match  (different expr)
214#[derive(Clone, Debug)]
215pub struct PhysicalSortRequirement {
216    /// Physical expression representing the column to sort
217    pub expr: Arc<dyn PhysicalExpr>,
218    /// Option to specify how the given column should be sorted.
219    /// If unspecified, there are no constraints on sort options.
220    pub options: Option<SortOptions>,
221}
222
223impl From<PhysicalSortRequirement> for PhysicalSortExpr {
224    /// If options is `None`, the default sort options `ASC, NULLS LAST` is used.
225    ///
226    /// The default is picked to be consistent with
227    /// PostgreSQL: <https://www.postgresql.org/docs/current/queries-order.html>
228    fn from(value: PhysicalSortRequirement) -> Self {
229        let options = value.options.unwrap_or(SortOptions {
230            descending: false,
231            nulls_first: false,
232        });
233        PhysicalSortExpr::new(value.expr, options)
234    }
235}
236
237impl From<PhysicalSortExpr> for PhysicalSortRequirement {
238    fn from(value: PhysicalSortExpr) -> Self {
239        PhysicalSortRequirement::new(value.expr, Some(value.options))
240    }
241}
242
243impl PartialEq for PhysicalSortRequirement {
244    fn eq(&self, other: &PhysicalSortRequirement) -> bool {
245        self.options == other.options && self.expr.eq(&other.expr)
246    }
247}
248
249impl Display for PhysicalSortRequirement {
250    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
251        let opts_string = self.options.as_ref().map_or("NA", to_str);
252        write!(f, "{} {}", self.expr, opts_string)
253    }
254}
255
256/// Writes a list of [`PhysicalSortRequirement`]s to a `std::fmt::Formatter`.
257///
258/// Example output: `[a + 1, b]`
259pub fn format_physical_sort_requirement_list(
260    exprs: &[PhysicalSortRequirement],
261) -> impl Display + '_ {
262    struct DisplayWrapper<'a>(&'a [PhysicalSortRequirement]);
263    impl Display for DisplayWrapper<'_> {
264        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
265            let mut iter = self.0.iter();
266            write!(f, "[")?;
267            if let Some(expr) = iter.next() {
268                write!(f, "{}", expr)?;
269            }
270            for expr in iter {
271                write!(f, ", {}", expr)?;
272            }
273            write!(f, "]")?;
274            Ok(())
275        }
276    }
277    DisplayWrapper(exprs)
278}
279
280impl PhysicalSortRequirement {
281    /// Creates a new requirement.
282    ///
283    /// If `options` is `Some(..)`, creates an `exact` requirement,
284    /// which must match both `options` and `expr`.
285    ///
286    /// If `options` is `None`, Creates a new `expr_only` requirement,
287    /// which must match only `expr`.
288    ///
289    /// See [`PhysicalSortRequirement`] for examples.
290    pub fn new(expr: Arc<dyn PhysicalExpr>, options: Option<SortOptions>) -> Self {
291        Self { expr, options }
292    }
293
294    /// Replace the required expression for this requirement with the new one
295    pub fn with_expr(mut self, expr: Arc<dyn PhysicalExpr>) -> Self {
296        self.expr = expr;
297        self
298    }
299
300    /// Returns whether this requirement is equal or more specific than `other`.
301    pub fn compatible(&self, other: &PhysicalSortRequirement) -> bool {
302        self.expr.eq(&other.expr)
303            && other
304                .options
305                .is_none_or(|other_opts| self.options == Some(other_opts))
306    }
307
308    #[deprecated(since = "43.0.0", note = "use  LexRequirement::from_lex_ordering")]
309    pub fn from_sort_exprs<'a>(
310        ordering: impl IntoIterator<Item = &'a PhysicalSortExpr>,
311    ) -> LexRequirement {
312        let ordering = ordering.into_iter().cloned().collect();
313        LexRequirement::from_lex_ordering(ordering)
314    }
315    #[deprecated(since = "43.0.0", note = "use  LexOrdering::from_lex_requirement")]
316    pub fn to_sort_exprs(
317        requirements: impl IntoIterator<Item = PhysicalSortRequirement>,
318    ) -> LexOrdering {
319        let requirements = requirements.into_iter().collect();
320        LexOrdering::from_lex_requirement(requirements)
321    }
322}
323
324/// Returns the SQL string representation of the given [SortOptions] object.
325#[inline]
326fn to_str(options: &SortOptions) -> &str {
327    match (options.descending, options.nulls_first) {
328        (true, true) => "DESC",
329        (true, false) => "DESC NULLS LAST",
330        (false, true) => "ASC",
331        (false, false) => "ASC NULLS LAST",
332    }
333}
334
335///`LexOrdering` contains a `Vec<PhysicalSortExpr>`, which represents
336/// a lexicographical ordering.
337///
338/// For example, `vec![a ASC, b DESC]` represents a lexicographical ordering
339/// that first sorts by column `a` in ascending order, then by column `b` in
340/// descending order.
341#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
342pub struct LexOrdering {
343    inner: Vec<PhysicalSortExpr>,
344}
345
346impl AsRef<LexOrdering> for LexOrdering {
347    fn as_ref(&self) -> &LexOrdering {
348        self
349    }
350}
351
352impl LexOrdering {
353    /// Creates a new [`LexOrdering`] from a vector
354    pub fn new(inner: Vec<PhysicalSortExpr>) -> Self {
355        Self { inner }
356    }
357
358    /// Return an empty LexOrdering (no expressions)
359    pub fn empty() -> &'static LexOrdering {
360        static EMPTY_ORDER: LazyLock<LexOrdering> = LazyLock::new(LexOrdering::default);
361        &EMPTY_ORDER
362    }
363
364    /// Returns the number of elements that can be stored in the LexOrdering
365    /// without reallocating.
366    pub fn capacity(&self) -> usize {
367        self.inner.capacity()
368    }
369
370    /// Clears the LexOrdering, removing all elements.
371    pub fn clear(&mut self) {
372        self.inner.clear()
373    }
374
375    /// Takes ownership of the actual vector of `PhysicalSortExpr`s in the LexOrdering.
376    pub fn take_exprs(self) -> Vec<PhysicalSortExpr> {
377        self.inner
378    }
379
380    /// Returns `true` if the LexOrdering contains `expr`
381    pub fn contains(&self, expr: &PhysicalSortExpr) -> bool {
382        self.inner.contains(expr)
383    }
384
385    /// Add all elements from `iter` to the LexOrdering.
386    pub fn extend<I: IntoIterator<Item = PhysicalSortExpr>>(&mut self, iter: I) {
387        self.inner.extend(iter)
388    }
389
390    /// Remove all elements from the LexOrdering where `f` evaluates to `false`.
391    pub fn retain<F>(&mut self, f: F)
392    where
393        F: FnMut(&PhysicalSortExpr) -> bool,
394    {
395        self.inner.retain(f)
396    }
397
398    /// Returns `true` if the LexOrdering contains no elements.
399    pub fn is_empty(&self) -> bool {
400        self.inner.is_empty()
401    }
402
403    /// Returns an iterator over each `&PhysicalSortExpr` in the LexOrdering.
404    pub fn iter(&self) -> core::slice::Iter<PhysicalSortExpr> {
405        self.inner.iter()
406    }
407
408    /// Returns the number of elements in the LexOrdering.
409    pub fn len(&self) -> usize {
410        self.inner.len()
411    }
412
413    /// Removes the last element from the LexOrdering and returns it, or `None` if it is empty.
414    pub fn pop(&mut self) -> Option<PhysicalSortExpr> {
415        self.inner.pop()
416    }
417
418    /// Appends an element to the back of the LexOrdering.
419    pub fn push(&mut self, physical_sort_expr: PhysicalSortExpr) {
420        self.inner.push(physical_sort_expr)
421    }
422
423    /// Truncates the LexOrdering, keeping only the first `len` elements.
424    pub fn truncate(&mut self, len: usize) {
425        self.inner.truncate(len)
426    }
427
428    /// Merge the contents of `other` into `self`, removing duplicates.
429    pub fn merge(mut self, other: LexOrdering) -> Self {
430        self.inner = self.inner.into_iter().chain(other).unique().collect();
431        self
432    }
433
434    /// Converts a `LexRequirement` into a `LexOrdering`.
435    ///
436    /// This function converts [`PhysicalSortRequirement`] to [`PhysicalSortExpr`]
437    /// for each entry in the input.
438    ///
439    /// If the required ordering is `None` for an entry in `requirement`, the
440    /// default ordering `ASC, NULLS LAST` is used (see
441    /// [`PhysicalSortExpr::from`]).
442    pub fn from_lex_requirement(requirement: LexRequirement) -> LexOrdering {
443        requirement
444            .into_iter()
445            .map(PhysicalSortExpr::from)
446            .collect()
447    }
448
449    /// Collapse a `LexOrdering` into a new duplicate-free `LexOrdering` based on expression.
450    ///
451    /// This function filters  duplicate entries that have same physical
452    /// expression inside, ignoring [`SortOptions`]. For example:
453    ///
454    /// `vec![a ASC, a DESC]` collapses to `vec![a ASC]`.
455    pub fn collapse(self) -> Self {
456        let mut output = LexOrdering::default();
457        for item in self {
458            if !output.iter().any(|req| req.expr.eq(&item.expr)) {
459                output.push(item);
460            }
461        }
462        output
463    }
464
465    /// Transforms each `PhysicalSortExpr` in the `LexOrdering`
466    /// in place using the provided closure `f`.
467    pub fn transform<F>(&mut self, f: F)
468    where
469        F: FnMut(&mut PhysicalSortExpr),
470    {
471        self.inner.iter_mut().for_each(f);
472    }
473}
474
475impl From<Vec<PhysicalSortExpr>> for LexOrdering {
476    fn from(value: Vec<PhysicalSortExpr>) -> Self {
477        Self::new(value)
478    }
479}
480
481impl From<LexRequirement> for LexOrdering {
482    fn from(value: LexRequirement) -> Self {
483        Self::from_lex_requirement(value)
484    }
485}
486
487/// Convert a `LexOrdering` into a `Arc[<PhysicalSortExpr>]` for fast copies
488impl From<LexOrdering> for Arc<[PhysicalSortExpr]> {
489    fn from(value: LexOrdering) -> Self {
490        value.inner.into()
491    }
492}
493
494impl Deref for LexOrdering {
495    type Target = [PhysicalSortExpr];
496
497    fn deref(&self) -> &Self::Target {
498        self.inner.as_slice()
499    }
500}
501
502impl Display for LexOrdering {
503    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
504        let mut first = true;
505        for sort_expr in &self.inner {
506            if first {
507                first = false;
508            } else {
509                write!(f, ", ")?;
510            }
511            write!(f, "{}", sort_expr)?;
512        }
513        Ok(())
514    }
515}
516
517impl FromIterator<PhysicalSortExpr> for LexOrdering {
518    fn from_iter<T: IntoIterator<Item = PhysicalSortExpr>>(iter: T) -> Self {
519        let mut lex_ordering = LexOrdering::default();
520
521        for i in iter {
522            lex_ordering.push(i);
523        }
524
525        lex_ordering
526    }
527}
528
529impl Index<usize> for LexOrdering {
530    type Output = PhysicalSortExpr;
531
532    fn index(&self, index: usize) -> &Self::Output {
533        &self.inner[index]
534    }
535}
536
537impl Index<Range<usize>> for LexOrdering {
538    type Output = [PhysicalSortExpr];
539
540    fn index(&self, range: Range<usize>) -> &Self::Output {
541        &self.inner[range]
542    }
543}
544
545impl Index<RangeFrom<usize>> for LexOrdering {
546    type Output = [PhysicalSortExpr];
547
548    fn index(&self, range_from: RangeFrom<usize>) -> &Self::Output {
549        &self.inner[range_from]
550    }
551}
552
553impl Index<RangeTo<usize>> for LexOrdering {
554    type Output = [PhysicalSortExpr];
555
556    fn index(&self, range_to: RangeTo<usize>) -> &Self::Output {
557        &self.inner[range_to]
558    }
559}
560
561impl IntoIterator for LexOrdering {
562    type Item = PhysicalSortExpr;
563    type IntoIter = IntoIter<PhysicalSortExpr>;
564
565    fn into_iter(self) -> Self::IntoIter {
566        self.inner.into_iter()
567    }
568}
569
570///`LexOrderingRef` is an alias for the type &`[PhysicalSortExpr]`, which represents
571/// a reference to a lexicographical ordering.
572#[deprecated(since = "43.0.0", note = "use &LexOrdering instead")]
573pub type LexOrderingRef<'a> = &'a [PhysicalSortExpr];
574
575///`LexRequirement` is an struct containing a `Vec<PhysicalSortRequirement>`, which
576/// represents a lexicographical ordering requirement.
577#[derive(Debug, Default, Clone, PartialEq)]
578pub struct LexRequirement {
579    pub inner: Vec<PhysicalSortRequirement>,
580}
581
582impl LexRequirement {
583    pub fn new(inner: Vec<PhysicalSortRequirement>) -> Self {
584        Self { inner }
585    }
586
587    pub fn is_empty(&self) -> bool {
588        self.inner.is_empty()
589    }
590
591    pub fn iter(&self) -> impl Iterator<Item = &PhysicalSortRequirement> {
592        self.inner.iter()
593    }
594
595    pub fn push(&mut self, physical_sort_requirement: PhysicalSortRequirement) {
596        self.inner.push(physical_sort_requirement)
597    }
598
599    /// Create a new [`LexRequirement`] from a [`LexOrdering`]
600    ///
601    /// Returns [`LexRequirement`] that requires the exact
602    /// sort of the [`PhysicalSortExpr`]s in `ordering`
603    pub fn from_lex_ordering(ordering: LexOrdering) -> Self {
604        Self::new(
605            ordering
606                .into_iter()
607                .map(PhysicalSortRequirement::from)
608                .collect(),
609        )
610    }
611
612    /// Constructs a duplicate-free `LexOrderingReq` by filtering out
613    /// duplicate entries that have same physical expression inside.
614    ///
615    /// For example, `vec![a Some(ASC), a Some(DESC)]` collapses to `vec![a
616    /// Some(ASC)]`.
617    pub fn collapse(self) -> Self {
618        let mut output = Vec::<PhysicalSortRequirement>::new();
619        for item in self {
620            if !output.iter().any(|req| req.expr.eq(&item.expr)) {
621                output.push(item);
622            }
623        }
624        LexRequirement::new(output)
625    }
626}
627
628impl From<LexOrdering> for LexRequirement {
629    fn from(value: LexOrdering) -> Self {
630        Self::from_lex_ordering(value)
631    }
632}
633
634impl Deref for LexRequirement {
635    type Target = [PhysicalSortRequirement];
636
637    fn deref(&self) -> &Self::Target {
638        self.inner.as_slice()
639    }
640}
641
642impl FromIterator<PhysicalSortRequirement> for LexRequirement {
643    fn from_iter<T: IntoIterator<Item = PhysicalSortRequirement>>(iter: T) -> Self {
644        let mut lex_requirement = LexRequirement::new(vec![]);
645
646        for i in iter {
647            lex_requirement.inner.push(i);
648        }
649
650        lex_requirement
651    }
652}
653
654impl IntoIterator for LexRequirement {
655    type Item = PhysicalSortRequirement;
656    type IntoIter = IntoIter<Self::Item>;
657
658    fn into_iter(self) -> Self::IntoIter {
659        self.inner.into_iter()
660    }
661}
662
663impl<'a> IntoIterator for &'a LexOrdering {
664    type Item = &'a PhysicalSortExpr;
665    type IntoIter = std::slice::Iter<'a, PhysicalSortExpr>;
666
667    fn into_iter(self) -> Self::IntoIter {
668        self.inner.iter()
669    }
670}
671
672///`LexRequirementRef` is an alias for the type &`[PhysicalSortRequirement]`, which
673/// represents a reference to a lexicographical ordering requirement.
674/// #[deprecated(since = "43.0.0", note = "use &LexRequirement instead")]
675pub type LexRequirementRef<'a> = &'a [PhysicalSortRequirement];