diff --git a/packages/cubejs-backend-native/Cargo.lock b/packages/cubejs-backend-native/Cargo.lock index 965c9b834449b..1ef04d9bd3bdd 100644 --- a/packages/cubejs-backend-native/Cargo.lock +++ b/packages/cubejs-backend-native/Cargo.lock @@ -961,7 +961,7 @@ dependencies = [ "futures-util", "hashbrown 0.14.5", "indexmap 1.9.3", - "itertools 0.10.5", + "itertools 0.14.0", "log", "lru", "minijinja", @@ -2043,6 +2043,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" diff --git a/rust/cubenativeutils/Cargo.lock b/rust/cubenativeutils/Cargo.lock index ea0fc681e8e41..5b69e639621fa 100644 --- a/rust/cubenativeutils/Cargo.lock +++ b/rust/cubenativeutils/Cargo.lock @@ -690,7 +690,7 @@ dependencies = [ "futures-util", "hashbrown 0.14.5", "indexmap 1.9.3", - "itertools", + "itertools 0.14.0", "log", "lru", "minijinja", @@ -729,7 +729,7 @@ dependencies = [ "datafusion-physical-expr", "futures", "hashbrown 0.12.3", - "itertools", + "itertools 0.10.5", "lazy_static", "log", "num_cpus", @@ -1390,6 +1390,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" diff --git a/rust/cubesql/Cargo.lock b/rust/cubesql/Cargo.lock index b31652274001e..1225c50424add 100644 --- a/rust/cubesql/Cargo.lock +++ b/rust/cubesql/Cargo.lock @@ -579,7 +579,7 @@ dependencies = [ "ciborium", "clap", "criterion-plot", - "itertools", + "itertools 0.10.3", "lazy_static", "num-traits", "oorandom", @@ -600,7 +600,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools", + "itertools 0.10.3", ] [[package]] @@ -766,7 +766,7 @@ dependencies = [ "hashbrown 0.14.3", "indexmap 1.9.3", "insta", - "itertools", + "itertools 0.14.0", "log", "lru", "minijinja", @@ -853,7 +853,7 @@ dependencies = [ "datafusion-physical-expr", "futures", "hashbrown 0.12.1", - "itertools", + "itertools 0.10.3", "lazy_static", "log", "num_cpus", @@ -1539,6 +1539,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" diff --git a/rust/cubesql/cubesql/Cargo.toml b/rust/cubesql/cubesql/Cargo.toml index cdb2cb7ea23e2..d21b242522d9f 100644 --- a/rust/cubesql/cubesql/Cargo.toml +++ b/rust/cubesql/cubesql/Cargo.toml @@ -21,7 +21,7 @@ sqlparser = { git = 'https://github.com/cube-js/sqlparser-rs.git', rev = "6a54d2 base64 = "0.13.0" tokio = { version = "^1.35", features = ["full", "rt", "tracing"] } serde = { version = "^1.0", features = ["derive"] } -itertools = "0.10.2" +itertools = "0.14.0" serde_json = "^1.0" bytes = "1.2" futures = "0.3.23" diff --git a/rust/cubesql/cubesql/src/compile/rewrite/converter.rs b/rust/cubesql/cubesql/src/compile/rewrite/converter.rs index dc65029915143..d717f23f249f4 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/converter.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/converter.rs @@ -1551,14 +1551,13 @@ impl LanguageToLogicalPlanConverter { match_data_node!(node_by_id, measure_params[0], MeasureName); let expr = self.to_expr(measure_params[1])?; query_measures.push(measure.to_string()); - let data_type = self - .cube_context - .meta - .find_df_data_type(measure.to_string()) - .ok_or(CubeError::internal(format!( - "Can't find measure '{}'", - measure - )))?; + let data_type = + self.cube_context.meta.find_df_data_type(&measure).ok_or( + CubeError::internal(format!( + "Can't find measure '{}'", + measure + )), + )?; fields.push(( DFField::new( expr_relation(&expr), @@ -1608,14 +1607,13 @@ impl LanguageToLogicalPlanConverter { LogicalPlanLanguage::Dimension(params) => { let dimension = match_data_node!(node_by_id, params[0], DimensionName); let expr = self.to_expr(params[1])?; - let data_type = self - .cube_context - .meta - .find_df_data_type(dimension.to_string()) - .ok_or(CubeError::internal(format!( - "Can't find dimension '{}'", - dimension - )))?; + let data_type = + self.cube_context.meta.find_df_data_type(&dimension).ok_or( + CubeError::internal(format!( + "Can't find dimension '{}'", + dimension + )), + )?; query_dimensions.push(dimension.to_string()); fields.push(( DFField::new( @@ -1705,7 +1703,7 @@ impl LanguageToLogicalPlanConverter { if self .cube_context .meta - .is_synthetic_field(column.member_name().to_string()) + .is_synthetic_field(column.member_name()) { fields.push(( DFField::new( diff --git a/rust/cubesql/cubesql/src/compile/rewrite/cost.rs b/rust/cubesql/cubesql/src/compile/rewrite/cost.rs index b012588c370c0..5972d72619c1c 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/cost.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/cost.rs @@ -143,7 +143,7 @@ impl BestCubePlan { let time_dimensions_used_as_dimensions = match enode { LogicalPlanLanguage::DimensionName(DimensionName(name)) => { - if let Some(dimension) = self.meta_context.find_dimension_with_name(name.clone()) { + if let Some(dimension) = self.meta_context.find_dimension_with_name(name) { if dimension.is_time() { 1 } else { diff --git a/rust/cubesql/cubesql/src/compile/rewrite/rules/filters.rs b/rust/cubesql/cubesql/src/compile/rewrite/rules/filters.rs index 39774ce7458ca..2bf7cdfe8aa68 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/rules/filters.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/rules/filters.rs @@ -3730,15 +3730,15 @@ impl FilterRules { } } - fn filter_member_name( + fn filter_member_name<'meta>( egraph: &mut CubeEGraph, subst: &Subst, - meta_context: &Arc, + meta_context: &'meta MetaContext, alias_to_cube_var: Var, column_var: Var, members_var: Var, aliases: &Vec<(String, String)>, - ) -> Option<(String, V1CubeMeta)> { + ) -> Option<(String, &'meta V1CubeMeta)> { Self::filter_member_name_with_granularity( egraph, subst, @@ -3751,15 +3751,15 @@ impl FilterRules { .map(|(name, _, meta)| (name, meta)) } - fn filter_member_name_with_granularity( + fn filter_member_name_with_granularity<'meta>( egraph: &mut CubeEGraph, subst: &Subst, - meta_context: &Arc, + meta_context: &'meta MetaContext, alias_to_cube_var: Var, column_var: Var, members_var: Var, aliases: &Vec<(String, String)>, - ) -> Option<(String, Option, V1CubeMeta)> { + ) -> Option<(String, Option, &'meta V1CubeMeta)> { let alias_to_cubes: Vec<_> = var_iter!(egraph[subst[alias_to_cube_var]], FilterReplacerAliasToCube) .cloned() diff --git a/rust/cubesql/cubesql/src/compile/rewrite/rules/members.rs b/rust/cubesql/cubesql/src/compile/rewrite/rules/members.rs index a9452ce69be37..99b325901cede 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/rules/members.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/rules/members.rs @@ -2166,7 +2166,7 @@ impl MemberRules { .cloned() { if let Some(measure) = - meta_context.find_measure_with_name(measure_name.to_string()) + meta_context.find_measure_with_name(&measure_name) { let measure_cube_name = measure_name.split(".").next().unwrap(); if let Some(((_, cube_alias), _)) = alias_to_cube @@ -2205,7 +2205,7 @@ impl MemberRules { } if let Some(dimension) = - meta_context.find_dimension_with_name(measure_name.to_string()) + meta_context.find_dimension_with_name(&measure_name) { let alias_to_cube = alias_to_cube.clone(); subst.insert( @@ -2309,7 +2309,7 @@ impl MemberRules { call_agg_type, alias, measure_out_var, - cube_alias, + cube_alias.to_string(), subst[aggr_expr_var], alias_to_cube, disable_strict_agg_type_match, diff --git a/rust/cubesql/cubesql/src/compile/rewrite/rules/old_split.rs b/rust/cubesql/cubesql/src/compile/rewrite/rules/old_split.rs index b79d5325f8467..7cb019f19f793 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/rules/old_split.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/rules/old_split.rs @@ -4922,7 +4922,7 @@ impl OldSplitRules { // TODO unwrap let name = expr.name(&DFSchema::empty()).unwrap(); let column1 = Column { - relation: Some(alias), + relation: Some(alias.to_string()), name: name.to_string(), }; let alias = egraph.add(LogicalPlanLanguage::ColumnExprColumn( diff --git a/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/aggregate.rs b/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/aggregate.rs index d1cff7bfc5844..63155c173f3db 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/aggregate.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/aggregate.rs @@ -878,9 +878,7 @@ impl WrapperRules { &column.name, ) { - if let Some(measure) = - meta.find_measure_with_name(member.to_string()) - { + if let Some(measure) = meta.find_measure_with_name(member) { if call_agg_type.is_none() || measure.is_same_agg_type( call_agg_type.as_ref().unwrap(), diff --git a/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/column.rs b/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/column.rs index a3ce49c8b9c28..1b19e8da99e0c 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/column.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/column.rs @@ -214,7 +214,7 @@ impl WrapperRules { .data .find_member_by_alias(&column.name) { - if let Some(measure) = meta.find_measure_with_name(member.to_string()) { + if let Some(measure) = meta.find_measure_with_name(member) { if measure.agg_type != Some("number".to_string()) { return true; } diff --git a/rust/cubesql/cubesql/src/transport/ctx.rs b/rust/cubesql/cubesql/src/transport/ctx.rs index 321a7c349a9a1..997928730cde6 100644 --- a/rust/cubesql/cubesql/src/transport/ctx.rs +++ b/rust/cubesql/cubesql/src/transport/ctx.rs @@ -79,63 +79,53 @@ impl MetaContext { &self, alias_to_cube: &Vec<(String, String)>, ) -> Option> { - let data_sources = alias_to_cube + let data_source = alias_to_cube .iter() .map(|(_, c)| self.cube_to_data_source.get(c)) - .unique() - .collect::>>()?; - if data_sources.len() != 1 { - return None; - } - self.data_source_to_sql_generator - .get(data_sources[0].as_str()) - .cloned() - } + .all_equal_value(); - pub fn find_cube_with_name(&self, name: &str) -> Option { - for cube in self.cubes.iter() { - if cube.name.eq(&name) { - return Some(cube.clone()); - } - } + // Don't care for non-equal data sources, nor for missing cube_to_data_source keys + let data_source = data_source.ok()??; - None + self.data_source_to_sql_generator.get(data_source).cloned() } - pub fn find_cube_by_column( - &self, - alias_to_cube: &Vec<(String, String)>, + pub fn find_cube_with_name(&self, name: &str) -> Option<&CubeMeta> { + self.cubes.iter().find(|&cube| cube.name == name) + } + + pub fn find_cube_by_column<'meta, 'alias>( + &'meta self, + alias_to_cube: &'alias Vec<(String, String)>, column: &Column, - ) -> Option<(String, CubeMeta)> { + ) -> Option<(&'alias str, &'meta CubeMeta)> { (if let Some(rel) = column.relation.as_ref() { alias_to_cube.iter().find(|(a, _)| a == rel) } else { alias_to_cube.iter().find(|(_, c)| { if let Some(cube) = self.find_cube_with_name(c) { + // TODO replace cube.contains_member(&cube.member_name(...)) with searching by prepared column names cube.contains_member(&cube.member_name(&column.name)) } else { false } }) }) - .and_then(|(a, c)| { - self.find_cube_with_name(c) - .map(|cube| (a.to_string(), cube)) - }) + .and_then(|(a, c)| self.find_cube_with_name(c).map(|cube| (a.as_str(), cube))) } - pub fn find_cube_by_column_for_replacer( + pub fn find_cube_by_column_for_replacer<'alias>( &self, - alias_to_cube: &Vec<((String, String), String)>, + alias_to_cube: &'alias Vec<((String, String), String)>, column: &Column, - ) -> Vec<((String, String), CubeMeta)> { + ) -> Vec<((&'alias str, &'alias str), &CubeMeta)> { if let Some(rel) = column.relation.as_ref() { alias_to_cube .iter() .filter_map(|((old, new), c)| { if old == rel { self.find_cube_with_name(c) - .map(|cube| ((old.to_string(), new.to_string()), cube)) + .map(|cube| ((old.as_str(), new.as_str()), cube)) } else { None } @@ -146,8 +136,9 @@ impl MetaContext { .iter() .filter_map(|((old, new), c)| { if let Some(cube) = self.find_cube_with_name(c) { + // TODO replace cube.contains_member(&cube.member_name(...)) with searching by prepared column names if cube.contains_member(&cube.member_name(&column.name)) { - return Some(((old.to_string(), new.to_string()), cube)); + return Some(((old.as_str(), new.as_str()), cube)); } } @@ -157,33 +148,33 @@ impl MetaContext { } } - pub fn find_measure_with_name(&self, name: String) -> Option { - let cube_and_member_name = name.split(".").collect::>(); - if let Some(cube) = self.find_cube_with_name(cube_and_member_name[0]) { - cube.lookup_measure(cube_and_member_name[1]).cloned() - } else { - None - } + pub fn find_measure_with_name(&self, name: &str) -> Option<&CubeMetaMeasure> { + let mut cube_and_member_name = name.split("."); + let cube_name = cube_and_member_name.next()?; + let member_name = cube_and_member_name.next()?; + let cube = self.find_cube_with_name(cube_name)?; + cube.lookup_measure(member_name) } - pub fn find_dimension_with_name(&self, name: String) -> Option { - let cube_and_member_name = name.split(".").collect::>(); - if let Some(cube) = self.find_cube_with_name(cube_and_member_name[0]) { - cube.lookup_dimension(cube_and_member_name[1]).cloned() - } else { - None - } + pub fn find_dimension_with_name(&self, name: &str) -> Option<&CubeMetaDimension> { + let mut cube_and_member_name = name.split("."); + let cube_name = cube_and_member_name.next()?; + let member_name = cube_and_member_name.next()?; + let cube = self.find_cube_with_name(cube_name)?; + cube.lookup_dimension(member_name) } - pub fn is_synthetic_field(&self, name: String) -> bool { - let cube_and_member_name = name.split(".").collect::>(); - if cube_and_member_name.len() == 1 - && MetaContext::is_synthetic_field_name(cube_and_member_name[0]) - { - return true; - } - if let Some(_) = self.find_cube_with_name(cube_and_member_name[0]) { - MetaContext::is_synthetic_field_name(cube_and_member_name[1]) + pub fn is_synthetic_field(&self, name: &str) -> bool { + let mut cube_and_member_name = name.split("."); + let Some(cube_name) = cube_and_member_name.next() else { + return false; + }; + let Some(member_name) = cube_and_member_name.next() else { + return MetaContext::is_synthetic_field_name(cube_name); + }; + + if self.find_cube_with_name(cube_name).is_some() { + MetaContext::is_synthetic_field_name(member_name) } else { false } @@ -193,22 +184,24 @@ impl MetaContext { field_name == "__user" || field_name == "__cubeJoinField" } - pub fn find_df_data_type(&self, member_name: String) -> Option { - self.find_cube_with_name(member_name.split(".").next()?)? - .df_data_type(member_name.as_str()) + pub fn find_df_data_type(&self, member_name: &str) -> Option { + let (cube_name, _) = member_name.split_once(".")?; + + self.find_cube_with_name(cube_name)? + .df_data_type(member_name) } - pub fn find_cube_table_with_oid(&self, oid: u32) -> Option { - self.tables.iter().find(|table| table.oid == oid).cloned() + pub fn find_cube_table_with_oid(&self, oid: u32) -> Option<&CubeMetaTable> { + self.tables.iter().find(|table| table.oid == oid) } - pub fn find_cube_table_with_name(&self, name: String) -> Option { - self.tables.iter().find(|table| table.name == name).cloned() + pub fn find_cube_table_with_name(&self, name: &str) -> Option<&CubeMetaTable> { + self.tables.iter().find(|table| table.name == name) } - pub fn cube_has_join(&self, cube_name: &str, join_name: String) -> bool { + pub fn cube_has_join(&self, cube_name: &str, join_name: &str) -> bool { if let Some(cube) = self.find_cube_with_name(cube_name) { - if let Some(joins) = cube.joins { + if let Some(joins) = &cube.joins { return joins.iter().any(|j| j.name == join_name); } } @@ -262,7 +255,7 @@ mod tests { _ => panic!("wrong oid!"), } - match test_context.find_cube_table_with_name("test2".to_string()) { + match test_context.find_cube_table_with_name("test2") { Some(table) => assert_eq!(18005, table.oid), _ => panic!("wrong name!"), } diff --git a/rust/cubesqlplanner/Cargo.lock b/rust/cubesqlplanner/Cargo.lock index c57ded0ad36e7..57ad25a738967 100644 --- a/rust/cubesqlplanner/Cargo.lock +++ b/rust/cubesqlplanner/Cargo.lock @@ -722,7 +722,7 @@ dependencies = [ "futures-util", "hashbrown 0.14.5", "indexmap 1.9.3", - "itertools", + "itertools 0.14.0", "log", "lru", "minijinja", @@ -757,7 +757,7 @@ dependencies = [ "cubeclient", "cubenativeutils", "datafusion", - "itertools", + "itertools 0.10.5", "lazy_static", "minijinja", "nativebridge", @@ -783,7 +783,7 @@ dependencies = [ "datafusion-physical-expr", "futures", "hashbrown 0.12.3", - "itertools", + "itertools 0.10.5", "lazy_static", "log", "num_cpus", @@ -1444,6 +1444,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -1708,7 +1717,7 @@ dependencies = [ "Inflector", "async-trait", "byteorder", - "itertools", + "itertools 0.10.5", "proc-macro2", "quote", "syn 1.0.109",