Skip to content

Commit 8a62e77

Browse files
committed
fix(tesseract): Don't generate COALESCE with single argument
1 parent 0e95f18 commit 8a62e77

File tree

3 files changed

+60
-12
lines changed

3 files changed

+60
-12
lines changed

packages/cubejs-schema-compiler/test/integration/postgres/sql-generation.test.ts

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -714,8 +714,6 @@ SELECT 1 AS revenue, cast('2024-01-01' AS timestamp) as time UNION ALL
714714
await compiler.compile();
715715
const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, q);
716716

717-
// console.log(query.buildSqlAndParams());
718-
719717
const res = await dbRunner.testQuery(query.buildSqlAndParams());
720718
console.log(JSON.stringify(res));
721719

@@ -3379,6 +3377,45 @@ SELECT 1 AS revenue, cast('2024-01-01' AS timestamp) as time UNION ALL
33793377
});
33803378
});
33813379

3380+
it('don\'t use COALESCE with single argument', async () => {
3381+
if (!getEnv('nativeSqlPlanner')) {
3382+
return;
3383+
}
3384+
await compiler.compile();
3385+
3386+
const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, {
3387+
measures: [
3388+
'visitors.visitor_revenue'
3389+
],
3390+
dimensions: [
3391+
'visitors.source'
3392+
],
3393+
timeDimensions: [],
3394+
timezone: 'America/Los_Angeles',
3395+
filters: [{
3396+
dimension: 'visitor_checkins.source',
3397+
operator: 'equals',
3398+
values: ['google']
3399+
}],
3400+
order: [{
3401+
id: 'visitors.source'
3402+
}]
3403+
});
3404+
const queryAndParams = query.buildSqlAndParams();
3405+
console.log(queryAndParams);
3406+
expect(queryAndParams[0]).not.toContain('COALESCE');
3407+
3408+
return dbRunner.testQuery(queryAndParams).then(res => {
3409+
console.log(JSON.stringify(res));
3410+
expect(res).toEqual(
3411+
[{
3412+
visitors__source: 'some',
3413+
visitors__visitor_revenue: '100'
3414+
}]
3415+
);
3416+
});
3417+
});
3418+
33823419
it('expression cube name cache', async () => {
33833420
await runQueryTest(
33843421
{

rust/cubesqlplanner/cubesqlplanner/src/plan/builder/select.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::plan::{
66
use crate::plan::expression::FunctionExpression;
77
use crate::planner::sql_evaluator::sql_nodes::SqlNodesFactory;
88
use crate::planner::{BaseMember, VisitorContext};
9+
use cubenativeutils::CubeError;
910
use std::collections::HashMap;
1011
use std::rc::Rc;
1112

@@ -79,21 +80,30 @@ impl SelectBuilder {
7980
member: &Rc<dyn BaseMember>,
8081
references: Vec<QualifiedColumnName>,
8182
alias: Option<String>,
82-
) {
83+
) -> Result<(), CubeError> {
8384
let alias = if let Some(alias) = alias {
8485
alias
8586
} else {
8687
member.alias_name()
8788
};
8889

89-
let expr = Expr::Function(FunctionExpression {
90-
function: "COALESCE".to_string(),
91-
arguments: references
92-
.into_iter()
93-
// TODO unwrap
94-
.map(|r| Expr::Reference(r))
95-
.collect(),
96-
});
90+
let expr = if references.len() > 1 {
91+
Expr::Function(FunctionExpression {
92+
function: "COALESCE".to_string(),
93+
arguments: references
94+
.into_iter()
95+
// TODO unwrap
96+
.map(|r| Expr::Reference(r))
97+
.collect(),
98+
})
99+
} else if references.len() == 1 {
100+
Expr::Reference(references[0].clone())
101+
} else {
102+
return Err(CubeError::internal(
103+
"Cannot add coalesce projection without references".to_string(),
104+
));
105+
};
106+
97107
let aliased_expr = AliasedExpr {
98108
expr,
99109
alias: alias.clone(),
@@ -102,6 +112,7 @@ impl SelectBuilder {
102112
self.projection_columns.push(aliased_expr);
103113
self.result_schema
104114
.add_column(SchemaColumn::new(alias.clone(), Some(member.full_name())));
115+
Ok(())
105116
}
106117

107118
pub fn set_filter(&mut self, filter: Option<Filter>) {

rust/cubesqlplanner/cubesqlplanner/src/planner/planners/full_key_query_aggregate_planner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ impl FullKeyAggregateQueryPlanner {
127127
.collect::<Result<Vec<_>, _>>()?;
128128
let alias = references_builder
129129
.resolve_alias_for_member(&member.full_name(), &dimensions_source);
130-
select_builder.add_projection_coalesce_member(member, references, alias);
130+
select_builder.add_projection_coalesce_member(member, references, alias)?;
131131
}
132132

133133
for member in BaseMemberHelper::iter_as_base_member(&outer_measures) {

0 commit comments

Comments
 (0)