use std::sync::Arc;
use super::{
AggregateFunction, AggregateSpec, DataType, EdgeNormalizeSpec, Expr, Field, LimitSpec, LiteralValue, NodeId,
Schema, SchemaRef, SortExpr, SortSpec,
};
#[derive(Debug, Clone, PartialEq)]
pub struct FilterNode {
pub input: NodeId,
pub predicate: Expr,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ProjectionNode {
pub input: NodeId,
pub outputs: Vec<ProjectionOutput>,
output_schema: SchemaRef,
}
impl ProjectionNode {
pub(crate) fn new(input: NodeId, outputs: Vec<ProjectionOutput>) -> Self {
let output_schema = projection_output_schema(&outputs);
Self { input, outputs, output_schema }
}
pub fn output_schema(&self) -> &SchemaRef {
&self.output_schema
}
pub fn expressions(&self) -> impl Iterator<Item = &Expr> {
self.outputs.iter().map(|output| &output.expr)
}
pub fn output_fields(&self) -> impl Iterator<Item = &Field> {
self.outputs.iter().map(|output| &output.field)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ProjectionOutput {
pub expr: Expr,
pub field: Field,
}
impl ProjectionOutput {
pub fn new(expr: Expr, field: Field) -> Self {
Self { expr, field }
}
}
fn projection_output_schema(outputs: &[ProjectionOutput]) -> SchemaRef {
Arc::new(Schema::new(outputs.iter().map(|output| output.field.clone()).collect::<Vec<_>>()))
}
#[derive(Debug, Clone, PartialEq)]
pub struct AggregateNode {
pub input: NodeId,
pub spec: AggregateSpec,
}
#[derive(Debug, Clone, PartialEq)]
pub struct WindowNode {
pub input: NodeId,
pub spec: WindowSpec,
}
#[derive(Debug, Clone, PartialEq)]
pub struct WindowSpec {
pub partition_by: Vec<Expr>,
pub order_by: Vec<SortExpr>,
pub functions: Vec<WindowFunction>,
}
impl WindowSpec {
pub fn new(partition_by: Vec<Expr>, order_by: Vec<SortExpr>, functions: Vec<WindowFunction>) -> Self {
Self { partition_by, order_by, functions }
}
pub(crate) fn counts_rows_in_input_order(&self) -> bool {
self.functions.iter().any(|function| match function {
WindowFunction::Rank { .. } => !self.order_by.is_empty(),
WindowFunction::RowNumber { .. } => !self.order_by.is_empty() || !self.partition_by.is_empty(),
_ => false,
})
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum WindowFunction {
Aggregate {
function: AggregateFunction,
expr: Expr,
output: Field,
frame: WindowFrame,
},
Rank {
output: Field,
},
RowNumber {
output: Field,
},
LagLead {
expr: Expr,
offset: u32,
default: Option<LiteralValue>,
output: Field,
direction: ShiftDirection,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ShiftDirection {
Lag,
Lead,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WindowFrame {
WholePartition,
RowsUnboundedPrecedingToCurrent,
}
impl WindowFunction {
pub fn aggregate(function: AggregateFunction, expr: Expr, output: Field) -> Self {
Self::Aggregate { function, expr, output, frame: WindowFrame::WholePartition }
}
pub fn cumulative_aggregate(function: AggregateFunction, expr: Expr, output: Field) -> Self {
Self::Aggregate { function, expr, output, frame: WindowFrame::RowsUnboundedPrecedingToCurrent }
}
pub fn rank(alias: impl Into<String>) -> Self {
Self::Rank { output: Field::new(alias, DataType::UInt64, false) }
}
pub fn row_number(alias: impl Into<String>) -> Self {
Self::RowNumber { output: Field::new(alias, DataType::UInt64, false) }
}
pub fn row_number_i64(alias: impl Into<String>) -> Self {
Self::RowNumber { output: Field::new(alias, DataType::Int64, false) }
}
pub fn row_number_i32(alias: impl Into<String>) -> Self {
Self::RowNumber { output: Field::new(alias, DataType::Int32, false) }
}
pub fn lag(expr: Expr, offset: u32, default: Option<LiteralValue>, output: Field) -> Self {
Self::LagLead { expr, offset, default, output, direction: ShiftDirection::Lag }
}
pub fn lead(expr: Expr, offset: u32, default: Option<LiteralValue>, output: Field) -> Self {
Self::LagLead { expr, offset, default, output, direction: ShiftDirection::Lead }
}
pub fn output(&self) -> &Field {
match self {
Self::Aggregate { output, .. }
| Self::Rank { output }
| Self::RowNumber { output }
| Self::LagLead { output, .. } => output,
}
}
pub fn alias(&self) -> &str {
self.output().name()
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SortNode {
pub input: NodeId,
pub spec: SortSpec,
}
#[derive(Debug, Clone, PartialEq)]
pub struct LimitNode {
pub input: NodeId,
pub spec: LimitSpec,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UnionNode {
pub inputs: Vec<NodeId>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct EdgeNormalizeNode {
pub input: NodeId,
pub spec: EdgeNormalizeSpec,
}