1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use crate::stmt::ExprArg;
use super::{Expr, Projection};
/// Projects a field or element from a base expression.
///
/// A [projection] extracts a nested value from a record, tuple, or other
/// composite type using a path of field indices.
///
/// # Examples
///
/// ```text
/// project(record, [0]) // extracts the first field
/// project(record, [1, 2]) // extracts field 1, then field 2
/// ```
///
/// [projection]: https://en.wikipedia.org/wiki/Projection_(relational_algebra)
#[derive(Debug, Clone, PartialEq)]
pub struct ExprProject {
/// The expression to project from.
pub base: Box<Expr>,
/// The path specifying which field(s) to extract.
pub projection: Projection,
}
impl Expr {
/// Creates a projection expression that extracts a field from `base`
/// using the given projection path.
pub fn project(base: impl Into<Self>, projection: impl Into<Projection>) -> Self {
ExprProject {
base: Box::new(base.into()),
projection: projection.into(),
}
.into()
}
/// Shorthand for `Expr::project(Expr::arg(expr_arg), projection)`.
pub fn arg_project(expr_arg: impl Into<ExprArg>, projection: impl Into<Projection>) -> Self {
Self::project(Self::arg(expr_arg), projection)
}
/// Returns `true` if this expression is a projection.
pub fn is_project(&self) -> bool {
matches!(self, Self::Project(..))
}
/// Returns a reference to the inner [`ExprProject`] if this is a
/// projection, or `None` otherwise.
pub fn as_project(&self) -> Option<&ExprProject> {
match self {
Self::Project(expr_project) => Some(expr_project),
_ => None,
}
}
/// Returns a reference to the inner [`ExprProject`].
///
/// # Panics
///
/// Panics if `self` is not `Expr::Project`.
#[track_caller]
pub fn as_project_unwrap(&self) -> &ExprProject {
self.as_project()
.unwrap_or_else(|| panic!("expected Expr::Project; actual={self:#?}"))
}
}
impl ExprProject {}
impl From<ExprProject> for Expr {
fn from(value: ExprProject) -> Self {
Self::Project(value)
}
}