use linkrs_core::types::expr::SubqueryBody;
use linkrs_core::types::operators::{BinaryOperator, UnaryOperator};
use linkrs_core::types::semantic::ValueType;
use linkrs_core::DataType;
use linkrs_core::Value;
use super::stmt::BoundStatement;
use crate::binder::query_graph::QueryGraph;
#[derive(Debug, Clone)]
pub enum BoundExpression {
Literal(Value, DataType),
Variable(String, DataType),
Property {
object: Box<BoundExpression>,
property: String,
value_type: DataType,
},
StructField {
base: Box<BoundExpression>,
field: String,
return_type: DataType,
},
BinaryOp {
left: Box<BoundExpression>,
op: BinaryOperator,
right: Box<BoundExpression>,
return_type: DataType,
},
UnaryOp {
op: UnaryOperator,
operand: Box<BoundExpression>,
return_type: DataType,
},
Function(BoundFunctionCall),
Aggregate(BoundAggregateCall),
ParameterRef(String, DataType),
SessionVariable(String, DataType),
Subquery {
query: Box<BoundStatement>,
original_body: Option<Box<SubqueryBody>>,
},
Cast {
expr: Box<BoundExpression>,
target_type: DataType,
},
List(Vec<BoundExpression>, DataType),
Map(Vec<(String, BoundExpression)>, DataType),
Case {
expr: Option<Box<BoundExpression>>,
when_then: Vec<(BoundExpression, BoundExpression)>,
else_expr: Option<Box<BoundExpression>>,
return_type: DataType,
},
Exists {
query: Box<BoundStatement>,
original_body: Option<Box<SubqueryBody>>,
},
Pattern(QueryGraph),
Label(String),
TagProperty {
tag_name: String,
property: String,
value_type: DataType,
},
EdgeProperty {
edge_name: String,
property: String,
value_type: DataType,
},
Predicate {
func: String,
args: Vec<BoundExpression>,
return_type: DataType,
},
Subscript {
collection: Box<BoundExpression>,
index: Box<BoundExpression>,
return_type: DataType,
},
WindowFunction {
name: String,
args: Vec<BoundExpression>,
over_partition_by: Vec<BoundExpression>,
over_order_by: Vec<BoundExpression>,
over_order_desc: Vec<bool>,
return_type: DataType,
},
In {
expr: Box<BoundExpression>,
subquery: Box<BoundStatement>,
negated: bool,
original_body: Option<Box<SubqueryBody>>,
},
CountSubquery {
query: Box<BoundStatement>,
original_body: Option<Box<SubqueryBody>>,
},
Lambda {
params: Vec<String>,
body: Box<BoundExpression>,
},
Path(Vec<BoundExpression>, DataType),
ListComprehension {
variable: String,
source: Box<BoundExpression>,
filter: Option<Box<BoundExpression>>,
map: Option<Box<BoundExpression>>,
return_type: DataType,
},
Reduce {
accumulator: String,
initial: Box<BoundExpression>,
variable: String,
source: Box<BoundExpression>,
mapping: Box<BoundExpression>,
return_type: DataType,
},
PathBuild(Vec<BoundExpression>, DataType),
Vector(Vec<f32>),
}
#[derive(Debug, Clone)]
pub struct BoundFunctionCall {
pub name: String,
pub args: Vec<BoundExpression>,
pub return_type: ValueType,
}
#[derive(Debug, Clone)]
pub struct BoundAggregateCall {
pub function_name: String,
pub arguments: Vec<BoundExpression>,
pub distinct: bool,
pub alias: Option<String>,
pub return_type: ValueType,
}
impl BoundExpression {
pub fn return_type(&self) -> DataType {
match self {
Self::Literal(_, dt) => dt.clone(),
Self::Variable(_, dt) => dt.clone(),
Self::Property { value_type, .. } => value_type.clone(),
Self::StructField { return_type, .. } => return_type.clone(),
Self::BinaryOp { return_type, .. } => return_type.clone(),
Self::UnaryOp { return_type, .. } => return_type.clone(),
Self::Function(f) => f.return_type.to_data_type(),
Self::Aggregate(a) => a.return_type.to_data_type(),
Self::ParameterRef(_, dt) => dt.clone(),
Self::SessionVariable(_, _) => DataType::Unknown,
Self::Subquery { .. } => DataType::Unknown,
Self::Cast { target_type, .. } => target_type.clone(),
Self::List(_, dt) => dt.clone(),
Self::Map(_, dt) => dt.clone(),
Self::Case { return_type, .. } => return_type.clone(),
Self::Exists { .. } => DataType::Bool,
Self::Pattern(_) => DataType::Path,
Self::Label(_) => DataType::String,
Self::TagProperty { value_type, .. } => value_type.clone(),
Self::EdgeProperty { value_type, .. } => value_type.clone(),
Self::Predicate { return_type, .. } => return_type.clone(),
Self::Subscript { return_type, .. } => return_type.clone(),
Self::WindowFunction { return_type, .. } => return_type.clone(),
Self::In { .. } => DataType::Bool,
Self::CountSubquery { .. } => DataType::Int,
Self::Lambda { .. } => DataType::Unknown,
Self::Path(_, dt) => dt.clone(),
Self::ListComprehension { return_type, .. } => return_type.clone(),
Self::Reduce { return_type, .. } => return_type.clone(),
Self::PathBuild(_, dt) => dt.clone(),
Self::Vector(v) => DataType::VectorDense(v.len()),
}
}
pub fn value_type(&self) -> ValueType {
ValueType::from_data_type(&self.return_type())
}
}