Skip to main content

fraiseql_cli/schema/intermediate/
analytics.rs

1//! Fact table/aggregate structs: `IntermediateFactTable`, `IntermediateMeasure`,
2//! `IntermediateDimensions`, `IntermediateDimensionPath`, `IntermediateFilter`,
3//! `IntermediateAggregateQuery`.
4
5use std::collections::HashMap;
6
7use serde::{Deserialize, Serialize};
8
9// =============================================================================
10// Analytics Definitions
11// =============================================================================
12
13/// Fact table definition in intermediate format (Analytics)
14#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
15pub struct IntermediateFactTable {
16    /// Name of the fact table
17    pub table_name:               String,
18    /// Measure columns (numeric aggregates)
19    pub measures:                 Vec<IntermediateMeasure>,
20    /// Dimension metadata
21    pub dimensions:               IntermediateDimensions,
22    /// Denormalized filter columns
23    pub denormalized_filters:     Vec<IntermediateFilter>,
24    /// Maps JSONB measure paths to flat SQL column names for pre-aggregated views
25    #[serde(default)]
26    pub native_measures:          HashMap<String, String>,
27    /// Maps deep JSONB dimension paths to flat SQL column names for GROUP BY
28    #[serde(default)]
29    pub native_dimension_mapping: HashMap<String, String>,
30}
31
32/// Measure column definition
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
34pub struct IntermediateMeasure {
35    /// Measure column name
36    pub name:     String,
37    /// SQL data type of the measure
38    pub sql_type: String,
39    /// Whether the column can be NULL
40    pub nullable: bool,
41}
42
43/// Dimensions metadata
44#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
45pub struct IntermediateDimensions {
46    /// Dimension name
47    pub name:  String,
48    /// Paths to dimension fields within JSONB
49    pub paths: Vec<IntermediateDimensionPath>,
50}
51
52/// Dimension path within JSONB
53#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
54pub struct IntermediateDimensionPath {
55    /// Path name identifier
56    pub name:      String,
57    /// JSON path (accepts both "`json_path`" and "path" for cross-language compat)
58    #[serde(alias = "path")]
59    pub json_path: String,
60    /// Data type (accepts both "`data_type`" and "type" for cross-language compat)
61    #[serde(alias = "type")]
62    pub data_type: String,
63}
64
65/// Denormalized filter column
66#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
67pub struct IntermediateFilter {
68    /// Filter column name
69    pub name:     String,
70    /// SQL data type of the filter
71    pub sql_type: String,
72    /// Whether this column should be indexed
73    pub indexed:  bool,
74}
75
76/// Aggregate query definition (Analytics)
77#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
78pub struct IntermediateAggregateQuery {
79    /// Aggregate query name
80    pub name:            String,
81    /// Fact table to aggregate from
82    pub fact_table:      String,
83    /// Automatically generate GROUP BY clauses
84    pub auto_group_by:   bool,
85    /// Automatically generate aggregate functions
86    pub auto_aggregates: bool,
87    /// Optional description
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub description:     Option<String>,
90}