Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sqlplanner): Sql planner make some tests working #9036

Open
wants to merge 2 commits into
base: sql-planner-rolling-window
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 42 additions & 2 deletions packages/cubejs-schema-compiler/src/adapter/BaseQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,38 @@
}
}

buildSqlAndParamsTest(exportAnnotatedSql) {
if (!this.options.preAggregationQuery && !this.options.disableExternalPreAggregations && this.externalQueryClass) {
if (this.externalPreAggregationQuery()) { // TODO performance
return this.externalQuery().buildSqlAndParams(exportAnnotatedSql);
}
}
const js_res = this.compilers.compiler.withQuery(

Check failure on line 614 in packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

View workflow job for this annotation

GitHub Actions / lint

Identifier 'js_res' is not in camel case
this,
() => this.cacheValue(
['buildSqlAndParams', exportAnnotatedSql],
() => this.paramAllocator.buildSqlAndParams(
this.buildParamAnnotatedSql(),
exportAnnotatedSql,
this.shouldReuseParams
),
{ cache: this.queryCache }
)
);
console.log('js result: ', js_res[0]);

Check failure on line 626 in packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

View workflow job for this annotation

GitHub Actions / lint

Identifier 'js_res' is not in camel case
const rust = this.buildSqlAndParamsRust(exportAnnotatedSql);
console.log('rust result: ', rust[0]);
return js_res;

Check failure on line 629 in packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

View workflow job for this annotation

GitHub Actions / lint

Identifier 'js_res' is not in camel case
}

buildSqlAndParamsRust(exportAnnotatedSql) {

Check failure on line 632 in packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

View workflow job for this annotation

GitHub Actions / lint

Block must not be padded by blank lines


Check failure on line 634 in packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

View workflow job for this annotation

GitHub Actions / lint

More than 1 blank line not allowed
const order = this.options.order && R.pipe(
R.map((hash) => (!hash || !hash.id) ? null : hash),

Check failure on line 636 in packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

View workflow job for this annotation

GitHub Actions / lint

Arrow function used ambiguously with a conditional expression

Check failure on line 636 in packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

View workflow job for this annotation

GitHub Actions / lint

Multiple spaces found before '?'
R.reject(R.isNil),
)(this.options.order);

const queryParams = {
measures: this.options.measures,
dimensions: this.options.dimensions,
Expand All @@ -614,12 +645,13 @@
joinRoot: this.join.root,
joinGraph: this.joinGraph,
cubeEvaluator: this.cubeEvaluator,
order: this.options.order,
order: order,

Check failure on line 648 in packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

View workflow job for this annotation

GitHub Actions / lint

Expected property shorthand
filters: this.options.filters,
limit: this.options.limit ? this.options.limit.toString() : null,
rowLimit: this.options.rowLimit ? this.options.rowLimit.toString() : null,
offset: this.options.offset ? this.options.offset.toString() : null,
baseTools: this,
ungrouped: this.options.ungrouped

};
const res = nativeBuildSqlAndParams(queryParams);
Expand All @@ -628,6 +660,10 @@
return res;
}

getAllocatedParams() {
return this.paramAllocator.getParams()

Check failure on line 664 in packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

View workflow job for this annotation

GitHub Actions / lint

Missing semicolon
}

// FIXME helper for native generator, maybe should be moved entire to rust
generateTimeSeries(granularity, dateRange) {
return timeSeriesBase(granularity, dateRange);
Expand Down Expand Up @@ -806,6 +842,7 @@
} = this.fullKeyQueryAggregateMeasures();

if (!multipliedMeasures.length && !cumulativeMeasures.length && !multiStageMembers.length) {
console.log("!!!!! LLLOOOO!!!!");

Check failure on line 845 in packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

View workflow job for this annotation

GitHub Actions / lint

Expected indentation of 6 spaces but found 4
return this.simpleQuery();
}

Expand Down Expand Up @@ -1019,6 +1056,8 @@
const allMemberChildren = this.collectAllMemberChildren(context);
const memberToIsMultiStage = this.collectAllMultiStageMembers(allMemberChildren);

console.log("!!! measure to her ", measureToHierarchy);

const hasMultiStageMembers = (m) => {
if (memberToIsMultiStage[m]) {
return true;
Expand Down Expand Up @@ -3288,7 +3327,8 @@
gte: '{{ column }} >= {{ param }}',
lt: '{{ column }} < {{ param }}',
lte: '{{ column }} <= {{ param }}',
always_true: '1 == 1'
like_pattern: '{% if start_wild %}\'%\' || {% endif %}{{ value }}{% if end_wild %}|| \'%\'{% endif %}',
always_true: '1 = 1'

},
quotes: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ export class ParamAllocator {
return `$${paramIndex}$`;
}

public getParams() {
return this.params;
}

// eslint-disable-next-line no-unused-vars
protected paramPlaceHolder(paramIndex) {
return '?';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ describe('SQL Generation', () => {
}
});

it('having filter with operator OR', async () => {
it('having filter with operator OR 1', async () => {
await compiler.compile();

const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, {
Expand Down Expand Up @@ -486,7 +486,7 @@ describe('SQL Generation', () => {
}]
});

console.log(query.buildSqlAndParams());
console.log(query.buildSqlAndParamsTest());

return dbRunner.testQuery(query.buildSqlAndParams()).then(res => {
console.log(JSON.stringify(res));
Expand Down Expand Up @@ -648,7 +648,7 @@ describe('SQL Generation', () => {
});
});

it('where filter with operators OR & AND', async () => {
it('where filter with operators OR & AND 1', async () => {
await compiler.compile();

const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ describe('SQL Generation', () => {

console.log(query.buildSqlAndParams());

return dbRunner.testQuery(query.buildSqlAndParams()).then(res => {
return dbRunner.testQuery(query.buildSqlAndParamsTest()).then(res => {
console.log(JSON.stringify(res));
expect(res).toEqual(
[{ visitor_checkins__revenue_per_checkin: '50' }]
Expand Down Expand Up @@ -1721,7 +1721,7 @@ describe('SQL Generation', () => {
]));

it(
'contains filter',
'contains filter 1',
() => runQueryTest({
measures: [],
dimensions: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ pub struct BaseQueryOptionsStatic {
#[serde(rename = "rowLimit")]
pub row_limit: Option<String>,
pub offset: Option<String>,
pub ungrouped: Option<bool>,
}

#[nativebridge::native_bridge(BaseQueryOptionsStatic)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ pub trait BaseTools {
granularity: String,
date_range: Vec<String>,
) -> Result<Vec<Vec<String>>, CubeError>;
fn get_allocated_params(&self) -> Result<Vec<String>, CubeError>;
}
15 changes: 9 additions & 6 deletions rust/cubesqlplanner/cubesqlplanner/src/plan/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,16 @@ impl FilterItem {
.items
.iter()
.map(|itm| itm.to_sql(templates, context.clone(), schema.clone()))
.collect::<Result<Vec<_>, _>>()?;
let result = if items_sql.is_empty() {
templates.always_true()?
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.filter(|itm| !itm.is_empty())
.collect::<Vec<_>>();
if items_sql.is_empty() {
"".to_string()
} else {
items_sql.join(&operator)
};
format!("({})", result)
let result = items_sql.join(&operator);
format!("({})", result)
}
}
FilterItem::Item(item) => {
let sql = item.to_sql(context.clone(), schema)?;
Expand Down
12 changes: 9 additions & 3 deletions rust/cubesqlplanner/cubesqlplanner/src/planner/base_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,29 @@ impl<IT: InnerTypes> BaseQuery<IT> {
}

fn build_sql_and_params_impl(&self) -> Result<Select, CubeError> {
let nodes_factory = if self.request.ungrouped() {
SqlNodesFactory::new_ungroupped()
} else {
SqlNodesFactory::new()
};

if self.request.is_simple_query()? {
let planner = SimpleQueryPlanner::new(
self.query_tools.clone(),
self.request.clone(),
SqlNodesFactory::new(),
nodes_factory.clone(),
);
planner.plan()
} else {
let multiplied_measures_query_planner = MultipliedMeasuresQueryPlanner::new(
self.query_tools.clone(),
self.request.clone(),
SqlNodesFactory::new(),
nodes_factory.clone(),
);
let multi_stage_query_planner =
MultiStageQueryPlanner::new(self.query_tools.clone(), self.request.clone());
let full_key_aggregate_planner =
FullKeyAggregateQueryPlanner::new(self.request.clone(), SqlNodesFactory::new());
FullKeyAggregateQueryPlanner::new(self.request.clone(), nodes_factory.clone());
let mut subqueries = multiplied_measures_query_planner.plan_queries()?;
let (multi_stage_ctes, multi_stage_subqueries) =
multi_stage_query_planner.plan_queries()?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ impl BaseFilter {
FilterOperator::Gte => self.gte_where(&member_sql)?,
FilterOperator::Lt => self.lt_where(&member_sql)?,
FilterOperator::Lte => self.lte_where(&member_sql)?,
FilterOperator::Contains => self.contains_where(&member_sql)?,
FilterOperator::NotContains => self.not_contains_where(&member_sql)?,
FilterOperator::StartsWith => self.starts_with_where(&member_sql)?,
FilterOperator::NotStartsWith => self.not_starts_with_where(&member_sql)?,
FilterOperator::EndsWith => self.ends_with_where(&member_sql)?,
FilterOperator::NotEndsWith => self.not_ends_with_where(&member_sql)?,
};
Ok(res)
}
Expand Down Expand Up @@ -243,6 +249,58 @@ impl BaseFilter {
.lte(member_sql.to_string(), self.first_param()?)
}

fn contains_where(&self, member_sql: &str) -> Result<String, CubeError> {
self.like_or_where(member_sql, false, true, true)
}

fn not_contains_where(&self, member_sql: &str) -> Result<String, CubeError> {
self.like_or_where(member_sql, true, true, true)
}

fn starts_with_where(&self, member_sql: &str) -> Result<String, CubeError> {
self.like_or_where(member_sql, false, false, true)
}

fn not_starts_with_where(&self, member_sql: &str) -> Result<String, CubeError> {
self.like_or_where(member_sql, true, false, true)
}

fn ends_with_where(&self, member_sql: &str) -> Result<String, CubeError> {
self.like_or_where(member_sql, false, true, false)
}

fn not_ends_with_where(&self, member_sql: &str) -> Result<String, CubeError> {
self.like_or_where(member_sql, true, true, false)
}

fn like_or_where(
&self,
member_sql: &str,
not: bool,
start_wild: bool,
end_wild: bool,
) -> Result<String, CubeError> {
let values = self.filter_and_allocate_values();
let like_parts = values
.into_iter()
.map(|v| {
self.templates
.ilike(member_sql, &v, start_wild, end_wild, not)
})
.collect::<Result<Vec<_>, _>>()?;
let logical_symbol = if not { " AND " } else { " OR " };
let null_check = if self.is_need_null_chek(not) {
self.templates.or_is_null_check(member_sql.to_string())?
} else {
"".to_string()
};
Ok(format!(
"({}){}",
like_parts.join(logical_symbol),
null_check
))
}

fn allocate_date_params(&self) -> Result<(String, String), CubeError> {
if self.values.len() >= 2 {
let from = if let Some(from_str) = &self.values[0] {
Expand Down Expand Up @@ -345,13 +403,12 @@ impl BaseFilter {
}

fn allocate_param(&self, param: &str) -> String {
let index = self.query_tools.allocaate_param(param);
format!("${}$", index)
self.query_tools.allocate_param(param)
}

fn allocate_timestamp_param(&self, param: &str) -> String {
let index = self.query_tools.allocaate_param(param);
format!("${}$::timestamptz", index)
let placeholder = self.query_tools.allocate_param(param);
format!("{}::timestamptz", placeholder)
}

fn first_param(&self) -> Result<String, CubeError> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ pub enum FilterOperator {
Gte,
Lt,
Lte,
Contains,
NotContains,
StartsWith,
NotStartsWith,
NotEndsWith,
EndsWith,
}

impl FromStr for FilterOperator {
Expand All @@ -32,6 +38,12 @@ impl FromStr for FilterOperator {
"gte" => Ok(Self::Gte),
"lt" => Ok(Self::Lt),
"lte" => Ok(Self::Lte),
"contains" => Ok(Self::Contains),
"notcontains" => Ok(Self::NotContains),
"startswith" => Ok(Self::StartsWith),
"notstartswith" => Ok(Self::NotStartsWith),
"endswith" => Ok(Self::EndsWith),
"notendswith" => Ok(Self::NotEndsWith),

_ => Err(CubeError::user(format!("Unknown filter operator {}", s))),
}
Expand Down
Loading
Loading