Skip to content

Commit af07865

Browse files
committed
feat: Basic query rewrites
1 parent af92970 commit af07865

File tree

17 files changed

+2507
-6
lines changed

17 files changed

+2507
-6
lines changed

packages/cubejs-schema-compiler/adapter/BaseQuery.js

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const BaseFilter = require('./BaseFilter');
1111
const BaseTimeDimension = require('./BaseTimeDimension');
1212
const ParamAllocator = require('./ParamAllocator');
1313
const PreAggregations = require('./PreAggregations');
14+
const SqlParser = require('../parser/SqlParser');
1415

1516
const DEFAULT_PREAGGREGATIONS_SCHEMA = `stb_pre_aggregations`;
1617

@@ -335,7 +336,10 @@ class BaseQuery {
335336

336337
simpleQuery() {
337338
// eslint-disable-next-line prefer-template
338-
return `${this.commonQuery()} ${this.baseWhere(this.allFilters)}` +
339+
const inlineWhereConditions = [];
340+
const commonQuery = this.rewriteInlineWhere(() => this.commonQuery(), inlineWhereConditions);
341+
const inlineFilters = inlineWhereConditions.map(f => ({ filterToWhere: () => f }));
342+
return `${commonQuery} ${this.baseWhere(this.allFilters.concat(inlineFilters))}` +
339343
this.groupByClause() +
340344
this.baseHaving(this.measureFilters) +
341345
this.orderBy() +
@@ -619,13 +623,33 @@ class BaseQuery {
619623
return this.joinQuery(this.join, this.collectFromMembers(false, this.collectSubQueryDimensionsFor.bind(this)));
620624
}
621625

626+
rewriteInlineCubeSql(cube) {
627+
const sql = this.cubeSql(cube);
628+
const parser = new SqlParser(sql);
629+
const cubeAlias = this.cubeAlias(cube);
630+
if (
631+
this.safeEvaluateSymbolContext().inlineWhereConditions &&
632+
this.cubeEvaluator.cubeFromPath(cube).rewriteQueries &&
633+
parser.isSimpleAsteriskQuery()
634+
) {
635+
this.safeEvaluateSymbolContext().inlineWhereConditions.push(parser.extractWhereConditions(cubeAlias));
636+
return [parser.extractTableFrom(), cubeAlias];
637+
} else {
638+
return [sql, cubeAlias];
639+
}
640+
}
641+
622642
joinQuery(join, subQueryDimensions) {
623643
const joins = join.joins.map(
624-
j => `LEFT JOIN ${this.cubeSql(j.originalTo)} ${this.asSyntaxJoin} ${this.cubeAlias(j.originalTo)}
625-
ON ${this.evaluateSql(j.originalFrom, j.join.sql)}`
644+
j => {
645+
const [cubeSql, cubeAlias] = this.rewriteInlineCubeSql(j.originalTo);
646+
return `LEFT JOIN ${cubeSql} ${this.asSyntaxJoin} ${cubeAlias}
647+
ON ${this.evaluateSql(j.originalFrom, j.join.sql)}`;
648+
}
626649
).concat(subQueryDimensions.map(d => this.subQueryJoin(d)));
627650

628-
return `${this.cubeSql(join.root)} ${this.asSyntaxJoin} ${this.cubeAlias(join.root)}\n${joins.join("\n")}`;
651+
const [cubeSql, cubeAlias] = this.rewriteInlineCubeSql(join.root);
652+
return `${cubeSql} ${this.asSyntaxJoin} ${cubeAlias}\n${joins.join("\n")}`;
629653
}
630654

631655
subQueryJoin(dimension) {
@@ -877,6 +901,14 @@ class BaseQuery {
877901
return R.uniq(context.subQueryDimensions);
878902
}
879903

904+
rewriteInlineWhere(fn, inlineWhereConditions) {
905+
const context = { inlineWhereConditions };
906+
return this.evaluateSymbolSqlWithContext(
907+
fn,
908+
context
909+
);
910+
}
911+
880912
groupByClause() {
881913
if (this.ungrouped) {
882914
return '';

packages/cubejs-schema-compiler/compiler/CubeValidator.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ const cubeSchema = Joi.object().keys({
107107
sqlAlias: Joi.string(),
108108
dataSource: Joi.string(),
109109
description: Joi.string(),
110+
rewriteQueries: Joi.boolean(),
110111
joins: Joi.object().pattern(identifierRegex, Joi.object().keys({
111112
sql: Joi.func().required(),
112113
relationship: Joi.any().valid('hasMany', 'belongsTo', 'hasOne').required()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
cd parser && antlr -Dlanguage=JavaScript GenericSql.g4

packages/cubejs-schema-compiler/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414
"scripts": {
1515
"test": "mocha",
16-
"lint": "eslint adapter/*.js compiler/*.js extensions/*.js scaffolding/*.js"
16+
"lint": "eslint adapter/*.js compiler/*.js extensions/*.js scaffolding/*.js parser/SqlParser.js"
1717
},
1818
"dependencies": {
1919
"@babel/generator": "^7.4.0",
@@ -23,6 +23,7 @@
2323
"@babel/traverse": "^7.4.0",
2424
"@babel/types": "^7.4.0",
2525
"@hapi/joi": "^15.1.1",
26+
"antlr4": "^4.8.0",
2627
"humps": "^2.0.1",
2728
"inflection": "^1.12.0",
2829
"moment-range": "^4.0.1",
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
grammar GenericSql;
2+
3+
statement:
4+
query EOF | '(' query ')' EOF;
5+
6+
query:
7+
SELECT selectFields
8+
FROM from=fromTables
9+
(WHERE where=boolExp)?;
10+
11+
fromTables:
12+
aliasField;
13+
14+
selectFields:
15+
(field (',' field)*);
16+
17+
field:
18+
aliasField | ASTERISK;
19+
20+
aliasField:
21+
idPath (AS? identifier)?;
22+
23+
boolExp:
24+
exp |
25+
exp AND exp |
26+
exp OR exp |
27+
NOT exp
28+
;
29+
30+
exp:
31+
exp binaryOperator exp |
32+
exp unaryOperator |
33+
idPath |
34+
identifier '(' (exp (',' exp)*) ')' |
35+
CAST '(' exp AS identifier ')' |
36+
STRING |
37+
numeric |
38+
identifier |
39+
INDEXED_PARAM |
40+
'(' exp ')'
41+
;
42+
43+
numeric:
44+
DIGIT+ ('.' DIGIT+)? |
45+
'.' DIGIT+;
46+
47+
binaryOperator:
48+
LT | LTE | GT | GTE | EQUALS | NOT_EQUALS;
49+
50+
unaryOperator:
51+
IS NULL | IS NOT NULL;
52+
53+
idPath:
54+
identifier ('.' identifier)*;
55+
56+
identifier:
57+
ID |
58+
QUOTED_ID;
59+
60+
SELECT: 'SELECT';
61+
ASTERISK: '*';
62+
FROM: 'FROM';
63+
WHERE: 'WHERE';
64+
AND: 'AND';
65+
OR: 'OR';
66+
NOT: 'NOT';
67+
AS: 'AS';
68+
LT: '<';
69+
LTE: '<=';
70+
GT: '>';
71+
GTE: '>=';
72+
EQUALS: '=';
73+
NOT_EQUALS: '<>' | '!=';
74+
IS: 'IS';
75+
NULL: 'NULL';
76+
CAST: 'CAST';
77+
78+
INDEXED_PARAM: '$' [0-9]+ '$';
79+
ID: [A-Z_@] [A-Z_@0-9]*;
80+
DIGIT: [0-9];
81+
QUOTED_ID: ('"' (~'"')* '"') | ('`' (~'`')* '`');
82+
STRING: ('\'' (~ '\'' | '\'\'')* '\'');
83+
84+
85+
WHITESPACE: [ \t\r\n] -> channel(HIDDEN);
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
token literal names:
2+
null
3+
'('
4+
')'
5+
','
6+
'.'
7+
'SELECT'
8+
'*'
9+
'FROM'
10+
'WHERE'
11+
'AND'
12+
'OR'
13+
'NOT'
14+
'AS'
15+
'<'
16+
'<='
17+
'>'
18+
'>='
19+
'='
20+
null
21+
'IS'
22+
'NULL'
23+
'CAST'
24+
null
25+
null
26+
null
27+
null
28+
null
29+
null
30+
31+
token symbolic names:
32+
null
33+
null
34+
null
35+
null
36+
null
37+
SELECT
38+
ASTERISK
39+
FROM
40+
WHERE
41+
AND
42+
OR
43+
NOT
44+
AS
45+
LT
46+
LTE
47+
GT
48+
GTE
49+
EQUALS
50+
NOT_EQUALS
51+
IS
52+
NULL
53+
CAST
54+
INDEXED_PARAM
55+
ID
56+
DIGIT
57+
QUOTED_ID
58+
STRING
59+
WHITESPACE
60+
61+
rule names:
62+
statement
63+
query
64+
fromTables
65+
selectFields
66+
field
67+
aliasField
68+
boolExp
69+
exp
70+
numeric
71+
binaryOperator
72+
unaryOperator
73+
idPath
74+
identifier
75+
76+
77+
atn:
78+
[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 29, 163, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 5, 2, 37, 10, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 45, 10, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 7, 5, 52, 10, 5, 12, 5, 14, 5, 55, 11, 5, 3, 6, 3, 6, 5, 6, 59, 10, 6, 3, 7, 3, 7, 5, 7, 63, 10, 7, 3, 7, 5, 7, 66, 10, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 79, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 7, 9, 88, 10, 9, 12, 9, 14, 9, 91, 11, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 5, 9, 110, 10, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 7, 9, 118, 10, 9, 12, 9, 14, 9, 121, 11, 9, 3, 10, 6, 10, 124, 10, 10, 13, 10, 14, 10, 125, 3, 10, 3, 10, 6, 10, 130, 10, 10, 13, 10, 14, 10, 131, 5, 10, 134, 10, 10, 3, 10, 3, 10, 6, 10, 138, 10, 10, 13, 10, 14, 10, 139, 5, 10, 142, 10, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 5, 12, 151, 10, 12, 3, 13, 3, 13, 3, 13, 7, 13, 156, 10, 13, 12, 13, 14, 13, 159, 11, 13, 3, 14, 3, 14, 3, 14, 2, 3, 16, 15, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 2, 4, 3, 2, 15, 20, 4, 2, 25, 25, 27, 27, 2, 175, 2, 36, 3, 2, 2, 2, 4, 38, 3, 2, 2, 2, 6, 46, 3, 2, 2, 2, 8, 48, 3, 2, 2, 2, 10, 58, 3, 2, 2, 2, 12, 60, 3, 2, 2, 2, 14, 78, 3, 2, 2, 2, 16, 109, 3, 2, 2, 2, 18, 141, 3, 2, 2, 2, 20, 143, 3, 2, 2, 2, 22, 150, 3, 2, 2, 2, 24, 152, 3, 2, 2, 2, 26, 160, 3, 2, 2, 2, 28, 29, 5, 4, 3, 2, 29, 30, 7, 2, 2, 3, 30, 37, 3, 2, 2, 2, 31, 32, 7, 3, 2, 2, 32, 33, 5, 4, 3, 2, 33, 34, 7, 4, 2, 2, 34, 35, 7, 2, 2, 3, 35, 37, 3, 2, 2, 2, 36, 28, 3, 2, 2, 2, 36, 31, 3, 2, 2, 2, 37, 3, 3, 2, 2, 2, 38, 39, 7, 7, 2, 2, 39, 40, 5, 8, 5, 2, 40, 41, 7, 9, 2, 2, 41, 44, 5, 6, 4, 2, 42, 43, 7, 10, 2, 2, 43, 45, 5, 14, 8, 2, 44, 42, 3, 2, 2, 2, 44, 45, 3, 2, 2, 2, 45, 5, 3, 2, 2, 2, 46, 47, 5, 12, 7, 2, 47, 7, 3, 2, 2, 2, 48, 53, 5, 10, 6, 2, 49, 50, 7, 5, 2, 2, 50, 52, 5, 10, 6, 2, 51, 49, 3, 2, 2, 2, 52, 55, 3, 2, 2, 2, 53, 51, 3, 2, 2, 2, 53, 54, 3, 2, 2, 2, 54, 9, 3, 2, 2, 2, 55, 53, 3, 2, 2, 2, 56, 59, 5, 12, 7, 2, 57, 59, 7, 8, 2, 2, 58, 56, 3, 2, 2, 2, 58, 57, 3, 2, 2, 2, 59, 11, 3, 2, 2, 2, 60, 65, 5, 24, 13, 2, 61, 63, 7, 14, 2, 2, 62, 61, 3, 2, 2, 2, 62, 63, 3, 2, 2, 2, 63, 64, 3, 2, 2, 2, 64, 66, 5, 26, 14, 2, 65, 62, 3, 2, 2, 2, 65, 66, 3, 2, 2, 2, 66, 13, 3, 2, 2, 2, 67, 79, 5, 16, 9, 2, 68, 69, 5, 16, 9, 2, 69, 70, 7, 11, 2, 2, 70, 71, 5, 16, 9, 2, 71, 79, 3, 2, 2, 2, 72, 73, 5, 16, 9, 2, 73, 74, 7, 12, 2, 2, 74, 75, 5, 16, 9, 2, 75, 79, 3, 2, 2, 2, 76, 77, 7, 13, 2, 2, 77, 79, 5, 16, 9, 2, 78, 67, 3, 2, 2, 2, 78, 68, 3, 2, 2, 2, 78, 72, 3, 2, 2, 2, 78, 76, 3, 2, 2, 2, 79, 15, 3, 2, 2, 2, 80, 81, 8, 9, 1, 2, 81, 110, 5, 24, 13, 2, 82, 83, 5, 26, 14, 2, 83, 84, 7, 3, 2, 2, 84, 89, 5, 16, 9, 2, 85, 86, 7, 5, 2, 2, 86, 88, 5, 16, 9, 2, 87, 85, 3, 2, 2, 2, 88, 91, 3, 2, 2, 2, 89, 87, 3, 2, 2, 2, 89, 90, 3, 2, 2, 2, 90, 92, 3, 2, 2, 2, 91, 89, 3, 2, 2, 2, 92, 93, 7, 4, 2, 2, 93, 110, 3, 2, 2, 2, 94, 95, 7, 23, 2, 2, 95, 96, 7, 3, 2, 2, 96, 97, 5, 16, 9, 2, 97, 98, 7, 14, 2, 2, 98, 99, 5, 26, 14, 2, 99, 100, 7, 4, 2, 2, 100, 110, 3, 2, 2, 2, 101, 110, 7, 28, 2, 2, 102, 110, 5, 18, 10, 2, 103, 110, 5, 26, 14, 2, 104, 110, 7, 24, 2, 2, 105, 106, 7, 3, 2, 2, 106, 107, 5, 16, 9, 2, 107, 108, 7, 4, 2, 2, 108, 110, 3, 2, 2, 2, 109, 80, 3, 2, 2, 2, 109, 82, 3, 2, 2, 2, 109, 94, 3, 2, 2, 2, 109, 101, 3, 2, 2, 2, 109, 102, 3, 2, 2, 2, 109, 103, 3, 2, 2, 2, 109, 104, 3, 2, 2, 2, 109, 105, 3, 2, 2, 2, 110, 119, 3, 2, 2, 2, 111, 112, 12, 12, 2, 2, 112, 113, 5, 20, 11, 2, 113, 114, 5, 16, 9, 13, 114, 118, 3, 2, 2, 2, 115, 116, 12, 11, 2, 2, 116, 118, 5, 22, 12, 2, 117, 111, 3, 2, 2, 2, 117, 115, 3, 2, 2, 2, 118, 121, 3, 2, 2, 2, 119, 117, 3, 2, 2, 2, 119, 120, 3, 2, 2, 2, 120, 17, 3, 2, 2, 2, 121, 119, 3, 2, 2, 2, 122, 124, 7, 26, 2, 2, 123, 122, 3, 2, 2, 2, 124, 125, 3, 2, 2, 2, 125, 123, 3, 2, 2, 2, 125, 126, 3, 2, 2, 2, 126, 133, 3, 2, 2, 2, 127, 129, 7, 6, 2, 2, 128, 130, 7, 26, 2, 2, 129, 128, 3, 2, 2, 2, 130, 131, 3, 2, 2, 2, 131, 129, 3, 2, 2, 2, 131, 132, 3, 2, 2, 2, 132, 134, 3, 2, 2, 2, 133, 127, 3, 2, 2, 2, 133, 134, 3, 2, 2, 2, 134, 142, 3, 2, 2, 2, 135, 137, 7, 6, 2, 2, 136, 138, 7, 26, 2, 2, 137, 136, 3, 2, 2, 2, 138, 139, 3, 2, 2, 2, 139, 137, 3, 2, 2, 2, 139, 140, 3, 2, 2, 2, 140, 142, 3, 2, 2, 2, 141, 123, 3, 2, 2, 2, 141, 135, 3, 2, 2, 2, 142, 19, 3, 2, 2, 2, 143, 144, 9, 2, 2, 2, 144, 21, 3, 2, 2, 2, 145, 146, 7, 21, 2, 2, 146, 151, 7, 22, 2, 2, 147, 148, 7, 21, 2, 2, 148, 149, 7, 13, 2, 2, 149, 151, 7, 22, 2, 2, 150, 145, 3, 2, 2, 2, 150, 147, 3, 2, 2, 2, 151, 23, 3, 2, 2, 2, 152, 157, 5, 26, 14, 2, 153, 154, 7, 6, 2, 2, 154, 156, 5, 26, 14, 2, 155, 153, 3, 2, 2, 2, 156, 159, 3, 2, 2, 2, 157, 155, 3, 2, 2, 2, 157, 158, 3, 2, 2, 2, 158, 25, 3, 2, 2, 2, 159, 157, 3, 2, 2, 2, 160, 161, 9, 3, 2, 2, 161, 27, 3, 2, 2, 2, 20, 36, 44, 53, 58, 62, 65, 78, 89, 109, 117, 119, 125, 131, 133, 139, 141, 150, 157]
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
T__0=1
2+
T__1=2
3+
T__2=3
4+
T__3=4
5+
SELECT=5
6+
ASTERISK=6
7+
FROM=7
8+
WHERE=8
9+
AND=9
10+
OR=10
11+
NOT=11
12+
AS=12
13+
LT=13
14+
LTE=14
15+
GT=15
16+
GTE=16
17+
EQUALS=17
18+
NOT_EQUALS=18
19+
IS=19
20+
NULL=20
21+
CAST=21
22+
INDEXED_PARAM=22
23+
ID=23
24+
DIGIT=24
25+
QUOTED_ID=25
26+
STRING=26
27+
WHITESPACE=27
28+
'('=1
29+
')'=2
30+
','=3
31+
'.'=4
32+
'SELECT'=5
33+
'*'=6
34+
'FROM'=7
35+
'WHERE'=8
36+
'AND'=9
37+
'OR'=10
38+
'NOT'=11
39+
'AS'=12
40+
'<'=13
41+
'<='=14
42+
'>'=15
43+
'>='=16
44+
'='=17
45+
'IS'=19
46+
'NULL'=20
47+
'CAST'=21

0 commit comments

Comments
 (0)