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
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ export class MssqlQuery extends BaseQuery {
') AS {{ from_alias }}{% elif from_prepared %}\n' +
'FROM {{ from_prepared }}' +
'{% endif %}' +
'{% for join in joins %}\n{{ join }}{% endfor %}' +
'{% if filter %}\nWHERE {{ filter }}{% endif %}' +
'{% if group_by %}\nGROUP BY {{ group_by }}{% endif %}' +
'{% if having %}\nHAVING {{ having }}{% endif %}' +
Expand Down
5 changes: 3 additions & 2 deletions packages/cubejs-schema-compiler/test/unit/allDialects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ const ADAPTER_DIR = path.join(__dirname, '..', '..', 'src', 'adapter');
const MIN_DIALECTS = 10;

/**
* Every dialect, read off the adapter directory rather than listed by hand, so a dialect
* added later cannot quietly escape an invariant asserted over all of them.
* Every dialect in the schema-compiler adapter directory, discovered rather than listed
* by hand. Driver packages carry Query subclasses outside this scan; for a given template
* invariant the ones that matter are those redefining or deleting that template.
*
* Paired with its name, which is what a caller needs to report which dialect failed.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { allDialects } from './allDialects';

// The SQL API supplies already-rendered joins to statements/select; Tesseract folds
// joins into FROM instead. Guard the loop here because query snapshots do not cover it.
describe('statements/select', () => {
it.each(allDialects())('%s renders joins after both FROM branches and before WHERE', (_name, QueryClass) => {
Comment thread
davidda marked this conversation as resolved.
// These templates are defined unconditionally, so no compiled model is needed.
const { select } = QueryClass.prototype.sqlTemplates.call(Object.create(QueryClass.prototype)).statements;
const joins = /\{%-?\s*for\s+join\s+in\s+joins\s*-?%\}\s*\{\{-?\s*join\s*-?\}\}\s*\{%-?\s*endfor\s*-?%\}/;
const fromAlias = /\{\{-?\s*from_alias\s*-?\}\}\s*\{%-?\s*elif\s+from_prepared\s*-?%\}/;
const fromPrepared = /FROM\s+\{\{-?\s*from_prepared\s*-?\}\}\s*\{%-?\s*endif\s*-?%\}/;
Comment thread
davidda marked this conversation as resolved.
const filter = /\{%-?\s*if\s+filter\s*-?%\}\s*WHERE\b/;

expect(select).toMatch(joins);
expect(select).toMatch(fromAlias);
expect(select).toMatch(fromPrepared);
expect(select).toMatch(filter);

const fromEnd = select.match(fromPrepared)!;
const joinsEnd = select.match(joins)!;
expect(select.search(fromPrepared)).toBeGreaterThan(select.search(fromAlias));
expect(select.search(joins)).toBeGreaterThanOrEqual(fromEnd.index! + fromEnd[0].length);
expect(select.search(filter)).toBeGreaterThanOrEqual(joinsEnd.index! + joinsEnd[0].length);
});
});
Loading