Skip to main content

activecube_rs/compiler/
ir.rs

1/// SQL binding value — database-agnostic representation.
2#[derive(Debug, Clone)]
3pub enum SqlValue {
4    String(String),
5    Int(i64),
6    Float(f64),
7    Bool(bool),
8}
9
10/// Intermediate representation of a compiled GraphQL cube query.
11#[derive(Debug, Clone)]
12pub struct QueryIR {
13    pub cube: String,
14    pub schema: String,
15    pub table: String,
16    pub selects: Vec<SelectExpr>,
17    pub filters: FilterNode,
18    pub having: FilterNode,
19    pub group_by: Vec<String>,
20    pub order_by: Vec<OrderExpr>,
21    pub limit: u32,
22    pub offset: u32,
23    /// ClickHouse `LIMIT n BY col1, col2` — per-group row limit without aggregation.
24    pub limit_by: Option<LimitByExpr>,
25    /// When true, append FINAL after FROM for ReplacingMergeTree tables.
26    pub use_final: bool,
27}
28
29#[derive(Debug, Clone)]
30pub enum SelectExpr {
31    Column {
32        column: String,
33        alias: Option<String>,
34    },
35    Aggregate {
36        function: String,
37        column: String,
38        alias: String,
39        condition: Option<String>,
40    },
41}
42
43#[derive(Debug, Clone)]
44pub enum FilterNode {
45    And(Vec<FilterNode>),
46    Or(Vec<FilterNode>),
47    Condition {
48        column: String,
49        op: CompareOp,
50        value: SqlValue,
51    },
52    Empty,
53}
54
55#[derive(Debug, Clone)]
56pub enum CompareOp {
57    Eq,
58    Ne,
59    Gt,
60    Ge,
61    Lt,
62    Le,
63    Like,
64    In,
65    NotIn,
66    Includes,
67    IsNull,
68    IsNotNull,
69}
70
71impl CompareOp {
72    pub fn sql_op(&self) -> &'static str {
73        match self {
74            CompareOp::Eq => "=",
75            CompareOp::Ne => "!=",
76            CompareOp::Gt => ">",
77            CompareOp::Ge => ">=",
78            CompareOp::Lt => "<",
79            CompareOp::Le => "<=",
80            CompareOp::Like => "LIKE",
81            CompareOp::In => "IN",
82            CompareOp::NotIn => "NOT IN",
83            CompareOp::Includes => "LIKE",
84            CompareOp::IsNull => "IS NULL",
85            CompareOp::IsNotNull => "IS NOT NULL",
86        }
87    }
88
89    pub fn is_unary(&self) -> bool {
90        matches!(self, CompareOp::IsNull | CompareOp::IsNotNull)
91    }
92}
93
94#[derive(Debug, Clone)]
95pub struct OrderExpr {
96    pub column: String,
97    pub descending: bool,
98}
99
100#[derive(Debug, Clone)]
101pub struct LimitByExpr {
102    pub count: u32,
103    pub offset: u32,
104    pub columns: Vec<String>,
105}
106
107impl FilterNode {
108    pub fn is_empty(&self) -> bool {
109        matches!(self, FilterNode::Empty)
110    }
111}