diff --git a/lib/JsonqlCompiler.js b/lib/JsonqlCompiler.js index 9eace8a1a..e3bdd923c 100644 --- a/lib/JsonqlCompiler.js +++ b/lib/JsonqlCompiler.js @@ -207,7 +207,7 @@ function () { value: function compileFrom(from) { var aliases = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var ctes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - var fields, left, onSql, ref, right, subexpr, subquery; // TODO check that alias is not repeated in from + var fields, frag, left, onSql, ref, right, subexpr, subquery; // TODO check that alias is not repeated in from switch (from.type) { case "table": @@ -238,14 +238,21 @@ function () { _.extend(aliases, right.aliases); // Compile on - onSql = this.compileExpr(from.on, aliases, ctes); + onSql = from.on ? this.compileExpr(from.on, aliases, ctes) : void 0; - if ((ref = from.kind) !== 'inner' && ref !== 'left' && ref !== 'right') { + if ((ref = from.kind) !== 'inner' && ref !== 'left' && ref !== 'right' && ref !== 'full' && ref !== 'cross') { throw new Error("Unsupported join kind ".concat(from.kind)); } // Combine - return new SqlFragment("(").append(left).append(" " + from.kind + " join ").append(right).append(" on ").append(onSql).append(")"); + frag = new SqlFragment("(").append(left).append(" " + from.kind + " join ").append(right); + + if (onSql) { + frag.append(" on ").append(onSql); + } + + frag.append(")"); + return frag; case "subquery": // Validate alias diff --git a/lib/index.d.ts b/lib/index.d.ts index e6aa00607..88bd17de1 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -40,9 +40,9 @@ export interface JsonQLJoinFrom { type: "join", left: JsonQLFrom right: JsonQLFrom - kind: "inner" | "left" | "right" + kind: "inner" | "left" | "right" | "full" | "cross" /** Expression to join on */ - on: JsonQLExpr + on?: JsonQLExpr } export interface JsonQLTableFrom { diff --git a/src/JsonqlCompiler.coffee b/src/JsonqlCompiler.coffee index 4e671921e..02682c374 100644 --- a/src/JsonqlCompiler.coffee +++ b/src/JsonqlCompiler.coffee @@ -179,20 +179,27 @@ module.exports = class JsonqlCompiler _.extend(aliases, left.aliases) _.extend(aliases, right.aliases) + # Ensure that on is present for non-cross + if from.kind != "cross" and not from.on? + throw new Error("Missing on clause for non-cross join") + # Compile on - onSql = @compileExpr(from.on, aliases, ctes) + onSql = if from.on then @compileExpr(from.on, aliases, ctes) - if from.kind not in ['inner', 'left', 'right'] + if from.kind not in ['inner', 'left', 'right', 'full', 'cross'] throw new Error("Unsupported join kind #{from.kind}") # Combine - return new SqlFragment("(") + frag = new SqlFragment("(") .append(left) .append(" " + from.kind + " join ") .append(right) - .append(" on ") - .append(onSql) - .append(")") + if onSql + frag.append(" on ").append(onSql) + + frag.append(")") + + return frag when "subquery" # Validate alias diff --git a/src/index.d.ts b/src/index.d.ts index e6aa00607..88bd17de1 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -40,9 +40,9 @@ export interface JsonQLJoinFrom { type: "join", left: JsonQLFrom right: JsonQLFrom - kind: "inner" | "left" | "right" + kind: "inner" | "left" | "right" | "full" | "cross" /** Expression to join on */ - on: JsonQLExpr + on?: JsonQLExpr } export interface JsonQLTableFrom { diff --git a/test/JsonqlCompilerTests.coffee b/test/JsonqlCompilerTests.coffee index f8f6a7790..3c4d8aef4 100644 --- a/test/JsonqlCompilerTests.coffee +++ b/test/JsonqlCompilerTests.coffee @@ -381,6 +381,17 @@ describe "JsonqlCompiler", -> # Maps alias to table assert.deepEqual aliases, { "abc1": "abc", "def1": "def" } + it 'compiles cross join', -> + aliases = {} + result = @compiler.compileFrom({ + type: "join" + left: { type: "table", table: "abc", alias: "abc1" } + right: { type: "table", table: "def", alias: "def1" } + kind: "cross" + }, aliases) + assert.equal result.sql, '(ABC as "a_abc1" cross join DEF as "a_def1")' + assert.deepEqual result.params, [] + it 'prevents duplicate aliases', -> assert.throws () => @compiler.compileFrom({