use serde::{Deserialize, Serialize};
use crate::{
compiler::{
aggregation::{OrderByClause, OrderDirection},
fact_table::FactTableMetadata,
},
db::where_clause::WhereClause,
error::{FraiseQLError, Result},
};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct WindowRequest {
pub table_name: String,
pub select: Vec<WindowSelectColumn>,
pub windows: Vec<WindowFunctionRequest>,
pub where_clause: Option<WhereClause>,
pub order_by: Vec<WindowOrderBy>,
pub limit: Option<u32>,
pub offset: Option<u32>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
#[non_exhaustive]
pub enum WindowSelectColumn {
Measure {
name: String,
alias: String,
},
Dimension {
path: String,
alias: String,
},
Filter {
name: String,
alias: String,
},
}
impl WindowSelectColumn {
#[must_use]
pub fn alias(&self) -> &str {
match self {
Self::Measure { alias, .. }
| Self::Dimension { alias, .. }
| Self::Filter { alias, .. } => alias,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WindowFunctionRequest {
pub function: WindowFunctionSpec,
pub alias: String,
pub partition_by: Vec<PartitionByColumn>,
pub order_by: Vec<WindowOrderBy>,
pub frame: Option<WindowFrame>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
#[non_exhaustive]
pub enum WindowFunctionSpec {
RowNumber,
Rank,
DenseRank,
Ntile {
n: u32,
},
PercentRank,
CumeDist,
Lag {
field: String,
offset: i32,
default: Option<serde_json::Value>,
},
Lead {
field: String,
offset: i32,
default: Option<serde_json::Value>,
},
FirstValue {
field: String,
},
LastValue {
field: String,
},
NthValue {
field: String,
n: u32,
},
RunningSum {
measure: String,
},
RunningAvg {
measure: String,
},
RunningCount,
RunningCountField {
field: String,
},
RunningMin {
measure: String,
},
RunningMax {
measure: String,
},
RunningStddev {
measure: String,
},
RunningVariance {
measure: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
#[non_exhaustive]
pub enum PartitionByColumn {
Dimension {
path: String,
},
Filter {
name: String,
},
Measure {
name: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WindowOrderBy {
pub field: String,
pub direction: OrderDirection,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WindowExecutionPlan {
pub table: String,
pub select: Vec<SelectColumn>,
pub windows: Vec<WindowFunction>,
pub where_clause: Option<WhereClause>,
pub order_by: Vec<OrderByClause>,
pub limit: Option<u32>,
pub offset: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SelectColumn {
pub expression: String,
pub alias: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WindowFunction {
pub function: WindowFunctionType,
pub alias: String,
pub partition_by: Vec<String>,
pub order_by: Vec<OrderByClause>,
pub frame: Option<WindowFrame>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
#[non_exhaustive]
pub enum WindowFunctionType {
RowNumber,
Rank,
DenseRank,
Ntile {
n: u32,
},
PercentRank,
CumeDist,
Lag {
field: String,
offset: i32,
default: Option<serde_json::Value>,
},
Lead {
field: String,
offset: i32,
default: Option<serde_json::Value>,
},
FirstValue {
field: String,
},
LastValue {
field: String,
},
NthValue {
field: String,
n: u32,
},
Sum {
field: String,
},
Avg {
field: String,
},
Count {
field: Option<String>,
},
Min {
field: String,
},
Max {
field: String,
},
Stddev {
field: String,
},
Variance {
field: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WindowFrame {
pub frame_type: FrameType,
pub start: FrameBoundary,
pub end: FrameBoundary,
pub exclusion: Option<FrameExclusion>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[non_exhaustive]
pub enum FrameType {
Rows,
Range,
Groups,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
#[non_exhaustive]
pub enum FrameBoundary {
UnboundedPreceding,
NPreceding {
n: u32,
},
CurrentRow,
NFollowing {
n: u32,
},
UnboundedFollowing,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum FrameExclusion {
CurrentRow,
Group,
Ties,
NoOthers,
}
mod codegen;
mod planner;
pub use self::{codegen::WindowPlanner, planner::WindowFunctionPlanner};
#[cfg(test)]
mod tests;