1use linkrs_core::types::expr::SubqueryBody;
2use linkrs_core::types::operators::{BinaryOperator, UnaryOperator};
3use linkrs_core::types::semantic::ValueType;
4use linkrs_core::DataType;
5use linkrs_core::Value;
6
7use super::stmt::BoundStatement;
8use crate::binder::query_graph::QueryGraph;
9
10#[derive(Debug, Clone)]
15pub enum BoundExpression {
16 Literal(Value, DataType),
18
19 Variable(String, DataType),
21
22 Property {
24 object: Box<BoundExpression>,
25 property: String,
26 value_type: DataType,
27 },
28
29 StructField {
31 base: Box<BoundExpression>,
32 field: String,
33 return_type: DataType,
34 },
35
36 BinaryOp {
38 left: Box<BoundExpression>,
39 op: BinaryOperator,
40 right: Box<BoundExpression>,
41 return_type: DataType,
42 },
43
44 UnaryOp {
46 op: UnaryOperator,
47 operand: Box<BoundExpression>,
48 return_type: DataType,
49 },
50
51 Function(BoundFunctionCall),
53
54 Aggregate(BoundAggregateCall),
56
57 ParameterRef(String, DataType),
59
60 SessionVariable(String, DataType),
63
64 Subquery {
66 query: Box<BoundStatement>,
67 original_body: Option<Box<SubqueryBody>>,
68 },
69
70 Cast {
72 expr: Box<BoundExpression>,
73 target_type: DataType,
74 },
75
76 List(Vec<BoundExpression>, DataType),
78
79 Map(Vec<(String, BoundExpression)>, DataType),
81
82 Case {
84 expr: Option<Box<BoundExpression>>,
85 when_then: Vec<(BoundExpression, BoundExpression)>,
86 else_expr: Option<Box<BoundExpression>>,
87 return_type: DataType,
88 },
89
90 Exists {
92 query: Box<BoundStatement>,
93 original_body: Option<Box<SubqueryBody>>,
94 },
95
96 Pattern(QueryGraph),
98
99 Label(String),
101
102 TagProperty {
104 tag_name: String,
105 property: String,
106 value_type: DataType,
107 },
108
109 EdgeProperty {
111 edge_name: String,
112 property: String,
113 value_type: DataType,
114 },
115
116 Predicate {
118 func: String,
119 args: Vec<BoundExpression>,
120 return_type: DataType,
121 },
122
123 Subscript {
125 collection: Box<BoundExpression>,
126 index: Box<BoundExpression>,
127 return_type: DataType,
128 },
129
130 WindowFunction {
132 name: String,
133 args: Vec<BoundExpression>,
134 over_partition_by: Vec<BoundExpression>,
135 over_order_by: Vec<BoundExpression>,
136 over_order_desc: Vec<bool>,
137 return_type: DataType,
138 },
139
140 In {
142 expr: Box<BoundExpression>,
143 subquery: Box<BoundStatement>,
144 negated: bool,
145 original_body: Option<Box<SubqueryBody>>,
146 },
147
148 CountSubquery {
150 query: Box<BoundStatement>,
151 original_body: Option<Box<SubqueryBody>>,
152 },
153
154 Lambda {
156 params: Vec<String>,
157 body: Box<BoundExpression>,
158 },
159
160 Path(Vec<BoundExpression>, DataType),
162
163 ListComprehension {
165 variable: String,
166 source: Box<BoundExpression>,
167 filter: Option<Box<BoundExpression>>,
168 map: Option<Box<BoundExpression>>,
169 return_type: DataType,
170 },
171
172 Reduce {
174 accumulator: String,
175 initial: Box<BoundExpression>,
176 variable: String,
177 source: Box<BoundExpression>,
178 mapping: Box<BoundExpression>,
179 return_type: DataType,
180 },
181
182 PathBuild(Vec<BoundExpression>, DataType),
184
185 Vector(Vec<f32>),
187}
188
189#[derive(Debug, Clone)]
191pub struct BoundFunctionCall {
192 pub name: String,
193 pub args: Vec<BoundExpression>,
194 pub return_type: ValueType,
195}
196
197#[derive(Debug, Clone)]
199pub struct BoundAggregateCall {
200 pub function_name: String,
201 pub arguments: Vec<BoundExpression>,
202 pub distinct: bool,
203 pub alias: Option<String>,
204 pub return_type: ValueType,
205}
206
207impl BoundExpression {
208 pub fn return_type(&self) -> DataType {
210 match self {
211 Self::Literal(_, dt) => dt.clone(),
212 Self::Variable(_, dt) => dt.clone(),
213 Self::Property { value_type, .. } => value_type.clone(),
214 Self::StructField { return_type, .. } => return_type.clone(),
215 Self::BinaryOp { return_type, .. } => return_type.clone(),
216 Self::UnaryOp { return_type, .. } => return_type.clone(),
217 Self::Function(f) => f.return_type.to_data_type(),
218 Self::Aggregate(a) => a.return_type.to_data_type(),
219 Self::ParameterRef(_, dt) => dt.clone(),
220 Self::SessionVariable(_, _) => DataType::Unknown,
221 Self::Subquery { .. } => DataType::Unknown,
222 Self::Cast { target_type, .. } => target_type.clone(),
223 Self::List(_, dt) => dt.clone(),
224 Self::Map(_, dt) => dt.clone(),
225 Self::Case { return_type, .. } => return_type.clone(),
226 Self::Exists { .. } => DataType::Bool,
227 Self::Pattern(_) => DataType::Path,
228 Self::Label(_) => DataType::String,
229 Self::TagProperty { value_type, .. } => value_type.clone(),
230 Self::EdgeProperty { value_type, .. } => value_type.clone(),
231 Self::Predicate { return_type, .. } => return_type.clone(),
232 Self::Subscript { return_type, .. } => return_type.clone(),
233 Self::WindowFunction { return_type, .. } => return_type.clone(),
234 Self::In { .. } => DataType::Bool,
235 Self::CountSubquery { .. } => DataType::Int,
236 Self::Lambda { .. } => DataType::Unknown,
237 Self::Path(_, dt) => dt.clone(),
238 Self::ListComprehension { return_type, .. } => return_type.clone(),
239 Self::Reduce { return_type, .. } => return_type.clone(),
240 Self::PathBuild(_, dt) => dt.clone(),
241 Self::Vector(v) => DataType::VectorDense(v.len()),
242 }
243 }
244
245 pub fn value_type(&self) -> ValueType {
247 ValueType::from_data_type(&self.return_type())
248 }
249}