Skip to content
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
16 changes: 16 additions & 0 deletions packages/cubejs-questdb-driver/src/QuestQuery.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import R from 'ramda';
import {
BaseFilter,
BaseQuery,
Expand Down Expand Up @@ -91,6 +92,21 @@ export class QuestQuery extends BaseQuery {
.join(' AND ');
}

public baseHaving(query: string, filters: BaseFilter[]) {
// QuestDB doesn't support HAVING syntax.
// `( <query> ) WHERE <filter>` should be used instead.

if (filters.length > 0) {
let filter = filters.map(t => t.filterToWhere()).filter(R.identity).map(f => `(${f})`).join(' AND ');
// Replace measures with their aliases in the filter.
this.measures.forEach((m) => {
filter = filter.replace(m.measureSql(), m.aliasName());
});
return `SELECT * FROM (${query}) WHERE ${filter}`;
}
return query;
}

public renderSqlMeasure(name: string, evaluateSql: string, symbol: any, cubeName: string, parentMeasure: string, orderBySql: string[]): string {
// QuestDB doesn't support COUNT(column_name) syntax.
// COUNT() or COUNT(*) should be used instead.
Expand Down
25 changes: 25 additions & 0 deletions packages/cubejs-questdb-driver/test/QuestQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,29 @@ describe('QuestQuery', () => {

expect(queryAndParams[0]).toContain('ILIKE \'%\' || $1 || \'%\'');
}));

it('test having filter',
() => compiler.compile().then(() => {
const query = new QuestQuery({ joinGraph, cubeEvaluator, compiler }, {
dimensions: ['visitors.name'],
measures: ['visitors.count'],
filters: [
{
member: 'visitors.count',
operator: 'gt',
values: ['42']
},
],
});

const queryAndParams = query.buildSqlAndParams();

const expected = 'SELECT * FROM (SELECT\n' +
' "visitors".name "visitors__name", count(*) "visitors__count"\n' +
' FROM\n' +
' visitors AS "visitors" GROUP BY "visitors__name") WHERE ("visitors__count" > $1) ORDER BY "visitors__count" DESC';
expect(queryAndParams[0]).toEqual(expected);
const expectedParams = ['42'];
expect(queryAndParams[1]).toEqual(expectedParams);
}));
});
10 changes: 5 additions & 5 deletions packages/cubejs-schema-compiler/src/adapter/BaseQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -1228,9 +1228,9 @@ export class BaseQuery {
if (this.multiStageQuery) {
return `${commonQuery} ${this.baseWhere(this.allFilters.concat(inlineWhereConditions))}`;
}
return `${commonQuery} ${this.baseWhere(this.allFilters.concat(inlineWhereConditions))}` +
this.groupByClause() +
this.baseHaving(this.measureFilters) +
const query = `${commonQuery} ${this.baseWhere(this.allFilters.concat(inlineWhereConditions))}` +
this.groupByClause();
return this.baseHaving(query, this.measureFilters) +
this.orderBy() +
this.groupByDimensionLimit();
}
Expand Down Expand Up @@ -1834,9 +1834,9 @@ export class BaseQuery {
return filterClause.length ? ` WHERE ${filterClause.join(' AND ')}` : '';
}

baseHaving(filters) {
baseHaving(query, filters) {
const filterClause = filters.map(t => t.filterToWhere()).filter(R.identity).map(f => `(${f})`);
return filterClause.length ? ` HAVING ${filterClause.join(' AND ')}` : '';
return filterClause.length ? query + ` HAVING ${filterClause.join(' AND ')}` : query;
}

timeStampInClientTz(dateParam) {
Expand Down
5 changes: 3 additions & 2 deletions packages/cubejs-schema-compiler/src/adapter/HiveQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ export class HiveQuery extends BaseQuery {
ungroupedAliases: R.fromPairs(this.forSelect().map((m: any) => [m.measure || m.dimension, m.aliasName()]))
}
);
return `SELECT ${select} FROM (${ungrouped}) AS ${this.escapeColumnName('hive_wrapper')}
${this.groupByClause()}${this.baseHaving(this.measureFilters)}${this.orderBy()}${this.groupByDimensionLimit()}`;
const query = `SELECT ${select} FROM (${ungrouped}) AS ${this.escapeColumnName('hive_wrapper')}
${this.groupByClause()}`;
return this.baseHaving(query, this.measureFilters) + this.orderBy() + this.groupByDimensionLimit();
}

public seriesSql(timeDimension) {
Expand Down
18 changes: 9 additions & 9 deletions packages/cubejs-schema-compiler/src/adapter/PreAggregations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1543,15 +1543,15 @@ export class PreAggregations {
};

return this.query.evaluateSymbolSqlWithContext(
// eslint-disable-next-line prefer-template
() => `SELECT ${this.query.selectAllDimensionsAndMeasures(measures)} FROM ${from} ${this.query.baseWhere(replacedFilters)}` +
this.query.groupByClause() +
(
isFullSimpleQuery ?
this.query.baseHaving(this.query.measureFilters) +
this.query.orderBy() +
this.query.groupByDimensionLimit() : ''
),
() => {
// eslint-disable-next-line prefer-template
const query = `SELECT ${this.query.selectAllDimensionsAndMeasures(measures)} FROM ${from} ${this.query.baseWhere(replacedFilters)}` +
this.query.groupByClause();
return isFullSimpleQuery ?
this.query.baseHaving(query, this.query.measureFilters) +
this.query.orderBy() +
this.query.groupByDimensionLimit() : query;
},
{
renderedReference,
rollupQuery: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { DbRunnerAbstract, DBRunnerContainerOptions } from './db-runner.abstract

export class QuestDBRunner extends DbRunnerAbstract {
public static startContainer(options: DBRunnerContainerOptions) {
const version = process.env.TEST_QUEST_DB_VERSION || options.version || '8.0.3';
const version = process.env.TEST_QUEST_DB_VERSION || options.version || '9.2.3';

const container = new GenericContainer(`questdb/questdb:${version}`)
.withExposedPorts(8812)
Expand Down
Loading