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
use crate::schema::app::VariantId;
use super::Expr;
/// Selects a variant of an embedded enum value.
///
/// Evaluates to the payload of `base` when it holds `variant`: the record of
/// the variant's fields, in declaration order, without the discriminant.
/// Projections applied to it index that record with the variant's local
/// field positions, so `project(variant(owner, Human), [1])` is the second
/// field of `Owner::Human`, whatever the enum's storage layout.
///
/// The selection carries no check of its own. A predicate over a selection
/// must also require the variant; statement normalization in the engine
/// conjoins an [`is_variant`](Expr::is_variant) check for every selection a
/// predicate's operands reach. Lowering resolves the selection to the
/// variant's column expressions and the guard to a discriminant comparison;
/// the node never reaches a driver.
///
/// # Examples
///
/// ```text
/// variant(owner, Owner::Human) // the Human payload
/// project(variant(owner, Owner::Human), [0]) // its first field
/// ```
#[derive(Debug, Clone, PartialEq)]
pub struct ExprVariant {
/// Expression evaluating to an enum value.
pub base: Box<Expr>,
/// The variant whose payload is selected.
pub variant: VariantId,
}
impl Expr {
/// Creates a variant selection: the payload of `base` as `variant`.
pub fn variant(base: impl Into<Self>, variant: VariantId) -> Self {
ExprVariant {
base: Box::new(base.into()),
variant,
}
.into()
}
/// Returns a reference to the inner [`ExprVariant`] if this is a variant
/// selection, or `None` otherwise.
pub fn as_variant(&self) -> Option<&ExprVariant> {
match self {
Self::Variant(expr_variant) => Some(expr_variant),
_ => None,
}
}
}
impl From<ExprVariant> for Expr {
fn from(value: ExprVariant) -> Self {
Self::Variant(value)
}
}