1mod call_arguments;
10mod traversal;
11pub use call_arguments::{
12 analyze_expression_call_arguments, scalar_call_argument, scalar_call_arguments,
13 validate_scalar_call_arguments, ScalarCallArgument,
14};
15
16use crate::ast::{BinaryOp, ColumnType, FrameMode, FunctionBinding, InternalColumnRef, NullsOrder};
17use uqa_core::Value;
18
19pub type SubqueryId = usize;
21
22#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
23pub enum ScalarExpr {
24 Star,
25 QualifiedStar(String),
26 Default,
27 Column(String),
28 Position(usize),
30 InternalColumn(InternalColumnRef),
32 QualifiedColumn {
33 qualifier: String,
34 column: String,
35 },
36 Literal(Value),
37 TypedLiteral {
39 value: Value,
40 ty: String,
41 #[serde(default, skip_serializing_if = "Option::is_none")]
43 bound_type: Option<ColumnType>,
44 #[serde(default, skip_serializing_if = "Option::is_none")]
46 parameter_index: Option<usize>,
47 },
48 Param(usize),
49 Func {
50 name: String,
51 #[serde(default, skip_serializing_if = "Option::is_none")]
52 binding: Option<FunctionBinding>,
53 args: Vec<Self>,
54 distinct: bool,
55 order_by: Vec<ScalarOrder>,
56 filter: Option<Box<Self>>,
57 },
58 Array(Vec<Self>),
59 Row(Vec<Self>),
60 Binary {
61 op: BinaryOp,
62 lhs: Box<Self>,
63 rhs: Box<Self>,
64 },
65 UnaryMinus(Box<Self>),
66 Not(Box<Self>),
67 And(Vec<Self>),
68 Or(Vec<Self>),
69 IsNull {
70 expr: Box<Self>,
71 negated: bool,
72 },
73 Between {
74 expr: Box<Self>,
75 low: Box<Self>,
76 high: Box<Self>,
77 },
78 InList {
79 expr: Box<Self>,
80 list: Vec<Self>,
81 negated: bool,
82 },
83 WindowCall {
84 name: String,
85 args: Vec<Self>,
86 spec: ScalarWindowSpec,
87 },
88 Case {
89 base: Option<Box<Self>>,
90 when: Vec<(Self, Self)>,
91 else_branch: Option<Box<Self>>,
92 },
93 Cast {
94 expr: Box<Self>,
95 ty: String,
96 },
97 ScalarSubquery(SubqueryId),
98 Exists {
99 subquery: SubqueryId,
100 negated: bool,
101 },
102 InSubquery {
103 expr: Box<Self>,
104 subquery: SubqueryId,
105 negated: bool,
106 },
107}
108
109#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
110pub struct ScalarOrder {
111 pub expr: ScalarExpr,
112 pub descending: bool,
113 pub nulls: Option<NullsOrder>,
114}
115
116#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
117pub struct ScalarWindowSpec {
118 pub partition_by: Vec<ScalarExpr>,
119 pub order_by: Vec<ScalarOrder>,
120 pub frame: Option<ScalarWindowFrame>,
121}
122
123#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
124pub struct ScalarWindowFrame {
125 pub mode: FrameMode,
126 pub start: ScalarFrameBound,
127 pub end: ScalarFrameBound,
128}
129
130#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
131pub enum ScalarFrameBound {
132 UnboundedPreceding,
133 UnboundedFollowing,
134 CurrentRow,
135 Preceding(Box<ScalarExpr>),
136 Following(Box<ScalarExpr>),
137}
138
139impl ScalarExpr {
140 #[must_use]
141 pub fn qualified_column(qualifier: impl Into<String>, column: impl Into<String>) -> Self {
142 Self::QualifiedColumn {
143 qualifier: qualifier.into(),
144 column: column.into(),
145 }
146 }
147}