Skip to content

Commit 86c5ab1

Browse files
committed
chore(tesseract): Refactoring of time shift without time dimension logic
1 parent 5f5d936 commit 86c5ab1

File tree

6 files changed

+79
-22
lines changed

6 files changed

+79
-22
lines changed

rust/cubesqlplanner/cubesqlplanner/src/logical_plan/multistage/leaf_measure.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use crate::logical_plan::*;
22
use crate::planner::planners::multi_stage::TimeShiftState;
3-
use crate::planner::sql_evaluator::MemberSymbol;
3+
use crate::planner::sql_evaluator::{DimensionTimeShift, MemberSymbol};
4+
use std::collections::HashMap;
45
use std::rc::Rc;
56

67
pub struct MultiStageLeafMeasure {
78
pub measure: Rc<MemberSymbol>,
89
pub render_measure_as_state: bool, //Render measure as state, for example hll state for count_approx
910
pub render_measure_for_ungrouped: bool,
10-
pub time_shifts: TimeShiftState,
11+
pub time_shifts: HashMap<String, DimensionTimeShift>,
1112
pub query: Rc<Query>,
1213
}
1314

@@ -22,13 +23,10 @@ impl PrettyPrint for MultiStageLeafMeasure {
2223
if self.render_measure_for_ungrouped {
2324
result.println("render_measure_for_ungrouped: true", &state);
2425
}
25-
if !self.time_shifts.dimensions_shifts.is_empty() {
26+
if !self.time_shifts.is_empty() {
2627
result.println("time_shifts:", &state);
2728
let details_state = state.new_level();
28-
if let Some(common) = &self.time_shifts.common_time_shift {
29-
result.println(&format!("- common: {}", common.to_sql()), &details_state);
30-
}
31-
for (_, time_shift) in self.time_shifts.dimensions_shifts.iter() {
29+
for (_, time_shift) in self.time_shifts.iter() {
3230
result.println(
3331
&format!(
3432
"- {}: {}",

rust/cubesqlplanner/cubesqlplanner/src/physical_plan_builder/builder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::planner::planners::multi_stage::TimeShiftState;
55
use crate::planner::query_properties::OrderByItem;
66
use crate::planner::query_tools::QueryTools;
77
use crate::planner::sql_evaluator::sql_nodes::SqlNodesFactory;
8+
use crate::planner::sql_evaluator::DimensionTimeShift;
89
use crate::planner::sql_evaluator::MemberSymbol;
910
use crate::planner::sql_evaluator::ReferencesBuilder;
1011
use crate::planner::sql_templates::PlanSqlTemplates;
@@ -24,7 +25,7 @@ struct PhysicalPlanBuilderContext {
2425
pub alias_prefix: Option<String>,
2526
pub render_measure_as_state: bool, //Render measure as state, for example hll state for count_approx
2627
pub render_measure_for_ungrouped: bool,
27-
pub time_shifts: TimeShiftState,
28+
pub time_shifts: HashMap<String, DimensionTimeShift>,
2829
pub original_sql_pre_aggregations: HashMap<String, String>,
2930
}
3031

rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multi_stage/applied_state.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,57 @@ impl MultiStageAppliedState {
104104
&self.time_shifts
105105
}
106106

107+
pub fn resolved_time_shifts(&self) -> HashMap<String, DimensionTimeShift> {
108+
let mut resolved_time_shifts = self.time_shifts.dimensions_shifts.clone();
109+
if let Some(common) = &self.time_shifts.common_time_shift {
110+
for member in self.all_time_members() {
111+
if let Some(exists) = resolved_time_shifts.get_mut(&member.full_name()) {
112+
exists.interval += common;
113+
} else {
114+
let time_shift = DimensionTimeShift {
115+
interval: common.clone(),
116+
dimension: member.clone(),
117+
};
118+
resolved_time_shifts.insert(member.full_name(), time_shift);
119+
}
120+
}
121+
}
122+
resolved_time_shifts
123+
}
124+
125+
fn all_time_members(&self) -> Vec<Rc<MemberSymbol>> {
126+
let mut filter_symbols = self.all_dimensions_symbols();
127+
for filter_item in self
128+
.time_dimensions_filters
129+
.iter()
130+
.chain(self.dimensions_filters.iter())
131+
.chain(self.segments.iter())
132+
{
133+
filter_item.find_all_member_evaluators(&mut filter_symbols);
134+
}
135+
136+
let time_symbols = filter_symbols
137+
.into_iter()
138+
.filter_map(|m| {
139+
let symbol = if let Ok(time_dim) = m.as_time_dimension() {
140+
time_dim.base_symbol().clone().resolve_reference_chain()
141+
} else {
142+
m.resolve_reference_chain()
143+
};
144+
if let Ok(dim) = symbol.as_dimension() {
145+
if dim.dimension_type() == "time" {
146+
Some(symbol)
147+
} else {
148+
None
149+
}
150+
} else {
151+
None
152+
}
153+
})
154+
.collect_vec();
155+
time_symbols
156+
}
157+
107158
pub fn time_dimensions_filters(&self) -> &Vec<FilterItem> {
108159
&self.time_dimensions_filters
109160
}
@@ -122,6 +173,14 @@ impl MultiStageAppliedState {
122173
.collect()
123174
}
124175

176+
pub fn all_dimensions_symbols(&self) -> Vec<Rc<MemberSymbol>> {
177+
self.time_dimensions
178+
.iter()
179+
.map(|d| d.member_evaluator().clone())
180+
.chain(self.dimensions.iter().map(|d| d.member_evaluator().clone()))
181+
.collect()
182+
}
183+
125184
pub fn dimensions_filters(&self) -> &Vec<FilterItem> {
126185
&self.dimensions_filters
127186
}

rust/cubesqlplanner/cubesqlplanner/src/planner/planners/multi_stage/member_query_planner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ impl MultiStageMemberQueryPlanner {
301301
measure: member_node.clone(),
302302
query,
303303
render_measure_as_state: self.description.member().has_aggregates_on_top(),
304-
time_shifts: self.description.state().time_shifts().clone(),
304+
time_shifts: self.description.state().resolved_time_shifts(),
305305
render_measure_for_ungrouped: self.description.member().is_ungrupped(),
306306
};
307307
let result = LogicalMultiStageMember {

rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/factory.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ use super::{
77
};
88
use crate::plan::schema::QualifiedColumnName;
99
use crate::planner::planners::multi_stage::TimeShiftState;
10+
use crate::planner::sql_evaluator::DimensionTimeShift;
1011
use std::collections::{HashMap, HashSet};
1112
use std::rc::Rc;
1213

1314
#[derive(Clone)]
1415
pub struct SqlNodesFactory {
15-
time_shifts: TimeShiftState,
16+
time_shifts: HashMap<String, DimensionTimeShift>,
1617
ungrouped: bool,
1718
ungrouped_measure: bool,
1819
count_approx_as_state: bool,
@@ -33,7 +34,7 @@ pub struct SqlNodesFactory {
3334
impl SqlNodesFactory {
3435
pub fn new() -> Self {
3536
Self {
36-
time_shifts: TimeShiftState::default(),
37+
time_shifts: HashMap::new(),
3738
ungrouped: false,
3839
ungrouped_measure: false,
3940
count_approx_as_state: false,
@@ -52,7 +53,7 @@ impl SqlNodesFactory {
5253
}
5354
}
5455

55-
pub fn set_time_shifts(&mut self, time_shifts: TimeShiftState) {
56+
pub fn set_time_shifts(&mut self, time_shifts: HashMap<String, DimensionTimeShift>) {
5657
self.time_shifts = time_shifts;
5758
}
5859

rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/sql_nodes/time_shift.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
use super::SqlNode;
22
use crate::planner::planners::multi_stage::TimeShiftState;
33
use crate::planner::query_tools::QueryTools;
4+
use crate::planner::sql_evaluator::DimensionTimeShift;
45
use crate::planner::sql_evaluator::MemberSymbol;
56
use crate::planner::sql_evaluator::SqlEvaluatorVisitor;
67
use crate::planner::sql_templates::PlanSqlTemplates;
78
use crate::planner::SqlInterval;
89
use cubenativeutils::CubeError;
910
use std::any::Any;
11+
use std::collections::HashMap;
1012
use std::rc::Rc;
1113

1214
pub struct TimeShiftSqlNode {
13-
shifts: TimeShiftState,
15+
shifts: HashMap<String, DimensionTimeShift>,
1416
input: Rc<dyn SqlNode>,
1517
}
1618

1719
impl TimeShiftSqlNode {
18-
pub fn new(shifts: TimeShiftState, input: Rc<dyn SqlNode>) -> Rc<Self> {
20+
pub fn new(shifts: HashMap<String, DimensionTimeShift>, input: Rc<dyn SqlNode>) -> Rc<Self> {
1921
Rc::new(Self { shifts, input })
2022
}
2123

@@ -43,16 +45,12 @@ impl SqlNode for TimeShiftSqlNode {
4345
let res = match node.as_ref() {
4446
MemberSymbol::Dimension(ev) => {
4547
if !ev.is_reference() && ev.dimension_type() == "time" {
46-
let mut interval = self.shifts.common_time_shift.clone().unwrap_or_default();
47-
if let Some(shift) = self.shifts.dimensions_shifts.get(&ev.full_name()) {
48-
interval += &shift.interval;
49-
}
50-
if interval == SqlInterval::default() {
51-
input
52-
} else {
53-
let shift = interval.to_sql();
48+
if let Some(shift) = self.shifts.get(&ev.full_name()) {
49+
let shift = shift.interval.to_sql();
5450
let res = templates.add_timestamp_interval(input, shift)?;
5551
format!("({})", res)
52+
} else {
53+
input
5654
}
5755
} else {
5856
input

0 commit comments

Comments
 (0)