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