diff --git a/lib/JsonqlCompiler.js b/lib/JsonqlCompiler.js index 03dcb7c44..d26707b4c 100644 --- a/lib/JsonqlCompiler.js +++ b/lib/JsonqlCompiler.js @@ -359,12 +359,12 @@ module.exports = JsonqlCompiler = /*#__PURE__*/function () { if ((ref = (0, _typeof2["default"])(expr)) === "number" || ref === "string" || ref === "boolean") { - return this.compileLiteral(expr); + return new SqlFragment("?", [expr]); } switch (expr.type) { case "literal": - return this.compileLiteral(expr.value); + return new SqlFragment("?", [expr.value]); case "op": return this.compileOpExpr(expr, aliases, ctes); @@ -688,25 +688,6 @@ module.exports = JsonqlCompiler = /*#__PURE__*/function () { throw new Error("Invalid alias '".concat(alias, "'")); } } - }, { - key: "compileLiteral", - value: function compileLiteral(value) { - // Postgres gives errors if the parameter type is unknown at times. e.g. sum(?) fails. - // To avoid, always cast value - if (typeof value === "number") { - return new SqlFragment("(?::numeric)", [value]); - } - - if (typeof value === "string") { - return new SqlFragment("(?::text)", [value]); - } - - if (typeof value === "boolean") { - return new SqlFragment("(?::boolean)", [value]); - } - - return new SqlFragment("?", [value]); - } }]); return JsonqlCompiler; }(); diff --git a/src/JsonqlCompiler.coffee b/src/JsonqlCompiler.coffee index c2a745064..5437f78eb 100644 --- a/src/JsonqlCompiler.coffee +++ b/src/JsonqlCompiler.coffee @@ -284,11 +284,11 @@ module.exports = class JsonqlCompiler # Literals if typeof(expr) in ["number", "string", "boolean"] - return @compileLiteral(expr) + return new SqlFragment("?", [expr]) switch expr.type when "literal" - return @compileLiteral(expr.value) + return new SqlFragment("?", [expr.value]) when "op" return @compileOpExpr(expr, aliases, ctes) when "field" @@ -583,17 +583,5 @@ module.exports = class JsonqlCompiler if not alias.match(/^[_a-zA-Z][a-zA-Z_0-9. :]*$/) throw new Error("Invalid alias '#{alias}'") - compileLiteral: (value) -> - # Postgres gives errors if the parameter type is unknown at times. e.g. sum(?) fails. - # To avoid, always cast value - if typeof(value) == "number" - return new SqlFragment("(?::numeric)", [value]) - if typeof(value) == "string" - return new SqlFragment("(?::text)", [value]) - if typeof(value) == "boolean" - return new SqlFragment("(?::boolean)", [value]) - - return new SqlFragment("?", [value]) - isInt = (x) -> return typeof(x)=='number' and (x%1) == 0 diff --git a/test/JsonqlCompilerTests.coffee b/test/JsonqlCompilerTests.coffee index 17a121de1..3c4d8aef4 100644 --- a/test/JsonqlCompilerTests.coffee +++ b/test/JsonqlCompilerTests.coffee @@ -29,7 +29,7 @@ describe "JsonqlCompiler", -> } compiled = @compiler.compileQuery(query) - assert.equal compiled.sql, 'select (?::numeric) as "x" from ABC as "a_abc1"' + assert.equal compiled.sql, 'select ? as "x" from ABC as "a_abc1"' assert.deepEqual compiled.params, [4] it 'compiles distinct query', -> @@ -43,7 +43,7 @@ describe "JsonqlCompiler", -> } compiled = @compiler.compileQuery(query) - assert.equal compiled.sql, 'select distinct (?::numeric) as "x" from ABC as "a_abc1"' + assert.equal compiled.sql, 'select distinct ? as "x" from ABC as "a_abc1"' assert.deepEqual compiled.params, [4] it 'compiles query with null select', -> @@ -83,7 +83,7 @@ describe "JsonqlCompiler", -> } compiled = @compiler.compileQuery(query) - assert.equal compiled.sql, 'select a_abc1.P as "x" from ABC as "a_abc1" where (a_abc1.Q > (?::numeric))' + assert.equal compiled.sql, 'select a_abc1.P as "x" from ABC as "a_abc1" where (a_abc1.Q > ?)' assert.deepEqual compiled.params, [5] it 'compiles query with groupBy ordinals', -> @@ -182,7 +182,7 @@ describe "JsonqlCompiler", -> } compiled = @compiler.compileQuery(query) - assert.equal compiled.sql, 'select (?::numeric) as "x" from ABC as "a_abc1" limit ?' + assert.equal compiled.sql, 'select ? as "x" from ABC as "a_abc1" limit ?' assert.deepEqual compiled.params, [4, 10] it 'compiles query with offset', -> @@ -196,7 +196,7 @@ describe "JsonqlCompiler", -> } compiled = @compiler.compileQuery(query) - assert.equal compiled.sql, 'select (?::numeric) as "x" from ABC as "a_abc1" offset ?' + assert.equal compiled.sql, 'select ? as "x" from ABC as "a_abc1" offset ?' assert.deepEqual compiled.params, [4, 10] it 'compiles query with subquery query', -> @@ -217,7 +217,7 @@ describe "JsonqlCompiler", -> } compiled = @compiler.compileQuery(query) - assert.equal compiled.sql, 'select a_abc1."q" as "x" from (select (?::numeric) as "q" from XYZ as "a_xyz1") as "a_abc1"' + assert.equal compiled.sql, 'select a_abc1."q" as "x" from (select ? as "q" from XYZ as "a_xyz1") as "a_abc1"' assert.deepEqual compiled.params, [5] it 'compiles query with subexpression', -> @@ -262,7 +262,7 @@ describe "JsonqlCompiler", -> } compiled = @compiler.compileQuery(query) - assert.equal compiled.sql, 'with "a_wq" as (select (?::numeric) as "q" from XYZ as "a_xyz1") select a_abc1."q" as "x" from a_wq as "a_abc1"' + assert.equal compiled.sql, 'with "a_wq" as (select ? as "q" from XYZ as "a_xyz1") select a_abc1."q" as "x" from a_wq as "a_abc1"' assert.deepEqual compiled.params, [5] it 'compiles union all query', -> @@ -288,7 +288,7 @@ describe "JsonqlCompiler", -> } compiled = @compiler.compileQuery(query) - assert.equal compiled.sql, '(select (?::numeric) as "x" from ABC as "a_abc1") union all (select (?::numeric) as "x" from ABC as "a_abc1")' + assert.equal compiled.sql, '(select ? as "x" from ABC as "a_abc1") union all (select ? as "x" from ABC as "a_abc1")' assert.deepEqual compiled.params, [4, 5] it "compiles reused alias", -> @@ -433,13 +433,13 @@ describe "JsonqlCompiler", -> assert.deepEqual fr.params, params it 'literal', -> - @testExpr({ type: "literal", value: "abc" }, "(?::text)", ["abc"]) + @testExpr({ type: "literal", value: "abc" }, "?", ["abc"]) it 'JSON literals', -> - @testExpr("abc", "(?::text)", ["abc"]) - @testExpr(2.3, "(?::numeric)", [2.3]) - @testExpr(true, "(?::boolean)", [true]) - @testExpr(false, "(?::boolean)", [false]) + @testExpr("abc", "?", ["abc"]) + @testExpr(2.3, "?", [2.3]) + @testExpr(true, "?", [true]) + @testExpr(false, "?", [false]) it 'null', -> @testExpr(null, "null", []) @@ -451,7 +451,7 @@ describe "JsonqlCompiler", -> describe "case", -> it "does input case", -> @testExpr({ type: "case", input: @a, cases: [{ when: @b, then: @c }]}, - "case (?::numeric) when (?::numeric) then (?::numeric) end", [1, 2, 3] + "case ? when ? then ? end", [1, 2, 3] ) it "does multiple case with else", -> @@ -459,98 +459,98 @@ describe "JsonqlCompiler", -> { when: @a, then: @b } { when: @c, then: @d } ], else: @e }, - "case when (?::numeric) then (?::numeric) when (?::numeric) then (?::numeric) else (?::numeric) end", [1, 2, 3, 4, 5] + "case when ? then ? when ? then ? else ? end", [1, 2, 3, 4, 5] ) describe "ops", -> it '> < >= <= = <>', -> - @testExpr({ type: "op", op: ">", exprs: [@a, @b] }, "((?::numeric) > (?::numeric))", [1, 2]) - @testExpr({ type: "op", op: "<", exprs: [@a, @b] }, "((?::numeric) < (?::numeric))", [1, 2]) - @testExpr({ type: "op", op: ">=", exprs: [@a, @b] }, "((?::numeric) >= (?::numeric))", [1, 2]) - @testExpr({ type: "op", op: "<=", exprs: [@a, @b] }, "((?::numeric) <= (?::numeric))", [1, 2]) - @testExpr({ type: "op", op: "=", exprs: [@a, @b] }, "((?::numeric) = (?::numeric))", [1, 2]) - @testExpr({ type: "op", op: "<>", exprs: [@a, @b] }, "((?::numeric) <> (?::numeric))", [1, 2]) + @testExpr({ type: "op", op: ">", exprs: [@a, @b] }, "(? > ?)", [1, 2]) + @testExpr({ type: "op", op: "<", exprs: [@a, @b] }, "(? < ?)", [1, 2]) + @testExpr({ type: "op", op: ">=", exprs: [@a, @b] }, "(? >= ?)", [1, 2]) + @testExpr({ type: "op", op: "<=", exprs: [@a, @b] }, "(? <= ?)", [1, 2]) + @testExpr({ type: "op", op: "=", exprs: [@a, @b] }, "(? = ?)", [1, 2]) + @testExpr({ type: "op", op: "<>", exprs: [@a, @b] }, "(? <> ?)", [1, 2]) it 'and', -> @testExpr({ type: "op", op: "and", exprs: [] }, "", []) - @testExpr({ type: "op", op: "and", exprs: [@a] }, "(?::numeric)", [1]) - @testExpr({ type: "op", op: "and", exprs: [@a, @b, @c] }, "((?::numeric) and (?::numeric) and (?::numeric))", [1, 2, 3]) - @testExpr({ type: "op", op: "and", exprs: [{ type: "op", op: "and", exprs: [] }, { type: "op", op: "and", exprs: [@a] }] }, "(?::numeric)", [1]) + @testExpr({ type: "op", op: "and", exprs: [@a] }, "?", [1]) + @testExpr({ type: "op", op: "and", exprs: [@a, @b, @c] }, "(? and ? and ?)", [1, 2, 3]) + @testExpr({ type: "op", op: "and", exprs: [{ type: "op", op: "and", exprs: [] }, { type: "op", op: "and", exprs: [@a] }] }, "?", [1]) it 'or', -> @testExpr({ type: "op", op: "or", exprs: [] }, "", []) - @testExpr({ type: "op", op: "or", exprs: [@a] }, "(?::numeric)", [1]) - @testExpr({ type: "op", op: "or", exprs: [@a, @b, @c] }, "((?::numeric) or (?::numeric) or (?::numeric))", [1, 2, 3]) + @testExpr({ type: "op", op: "or", exprs: [@a] }, "?", [1]) + @testExpr({ type: "op", op: "or", exprs: [@a, @b, @c] }, "(? or ? or ?)", [1, 2, 3]) it 'not', -> - @testExpr({ type: "op", op: "not", exprs: [@a] }, "(not (?::numeric))", [1]) + @testExpr({ type: "op", op: "not", exprs: [@a] }, "(not ?)", [1]) it 'is null', -> - @testExpr({ type: "op", op: "is null", exprs: [@a] }, "((?::numeric) is null)", [1]) + @testExpr({ type: "op", op: "is null", exprs: [@a] }, "(? is null)", [1]) it 'is not null', -> - @testExpr({ type: "op", op: "is not null", exprs: [@a] }, "((?::numeric) is not null)", [1]) + @testExpr({ type: "op", op: "is not null", exprs: [@a] }, "(? is not null)", [1]) it 'in', -> - @testExpr({ type: "op", op: "in", exprs: [@a, @b] }, "((?::numeric) in (?::numeric))", [1, 2]) + @testExpr({ type: "op", op: "in", exprs: [@a, @b] }, "(? in ?)", [1, 2]) it '+ - *', -> - @testExpr({ type: "op", op: "+", exprs: [@a, @b] }, "((?::numeric) + (?::numeric))", [1, 2]) - @testExpr({ type: "op", op: "-", exprs: [@a, @b] }, "((?::numeric) - (?::numeric))", [1, 2]) - @testExpr({ type: "op", op: "*", exprs: [@a, @b] }, "((?::numeric) * (?::numeric))", [1, 2]) - @testExpr({ type: "op", op: "+", exprs: [@a, @b, @c] }, "((?::numeric) + (?::numeric) + (?::numeric))", [1, 2, 3]) - @testExpr({ type: "op", op: "-", exprs: [@a, @b, @c] }, "((?::numeric) - (?::numeric) - (?::numeric))", [1, 2, 3]) - @testExpr({ type: "op", op: "*", exprs: [@a, @b, @c] }, "((?::numeric) * (?::numeric) * (?::numeric))", [1, 2, 3]) + @testExpr({ type: "op", op: "+", exprs: [@a, @b] }, "(? + ?)", [1, 2]) + @testExpr({ type: "op", op: "-", exprs: [@a, @b] }, "(? - ?)", [1, 2]) + @testExpr({ type: "op", op: "*", exprs: [@a, @b] }, "(? * ?)", [1, 2]) + @testExpr({ type: "op", op: "+", exprs: [@a, @b, @c] }, "(? + ? + ?)", [1, 2, 3]) + @testExpr({ type: "op", op: "-", exprs: [@a, @b, @c] }, "(? - ? - ?)", [1, 2, 3]) + @testExpr({ type: "op", op: "*", exprs: [@a, @b, @c] }, "(? * ? * ?)", [1, 2, 3]) it '/', -> - @testExpr({ type: "op", op: "/", exprs: [@a, @b] }, "((?::numeric) / (?::numeric))", [1, 2]) + @testExpr({ type: "op", op: "/", exprs: [@a, @b] }, "(? / ?)", [1, 2]) it '||', -> - @testExpr({ type: "op", op: "||", exprs: [@a, @b, @c] }, "((?::numeric) || (?::numeric) || (?::numeric))", [1, 2, 3]) + @testExpr({ type: "op", op: "||", exprs: [@a, @b, @c] }, "(? || ? || ?)", [1, 2, 3]) it '~ ~* like ilike', -> - @testExpr({ type: "op", op: "~", exprs: [@a, @b] }, "((?::numeric) ~ (?::numeric))", [1, 2]) - @testExpr({ type: "op", op: "~*", exprs: [@a, @b] }, "((?::numeric) ~* (?::numeric))", [1, 2]) - @testExpr({ type: "op", op: "like", exprs: [@a, @b] }, "((?::numeric) like (?::numeric))", [1, 2]) - @testExpr({ type: "op", op: "ilike", exprs: [@a, @b] }, "((?::numeric) ilike (?::numeric))", [1, 2]) + @testExpr({ type: "op", op: "~", exprs: [@a, @b] }, "(? ~ ?)", [1, 2]) + @testExpr({ type: "op", op: "~*", exprs: [@a, @b] }, "(? ~* ?)", [1, 2]) + @testExpr({ type: "op", op: "like", exprs: [@a, @b] }, "(? like ?)", [1, 2]) + @testExpr({ type: "op", op: "ilike", exprs: [@a, @b] }, "(? ilike ?)", [1, 2]) it '::text', -> - @testExpr({ type: "op", op: "::text", exprs: [@a] }, "((?::numeric)::text)", [1]) + @testExpr({ type: "op", op: "::text", exprs: [@a] }, "(?::text)", [1]) it '[]', -> - @testExpr({ type: "op", op: "[]", exprs: [@a, @b] }, "(((?::numeric))[(?::numeric)])", [1, 2]) + @testExpr({ type: "op", op: "[]", exprs: [@a, @b] }, "((?)[?])", [1, 2]) it '= any', -> arr = { type: "literal", value: ["x", "y"] } - @testExpr({ type: "op", op: "=", modifier: "any", exprs: [@a, arr] }, "((?::numeric) = any(?))", [1, ["x", "y"]]) + @testExpr({ type: "op", op: "=", modifier: "any", exprs: [@a, arr] }, "(? = any(?))", [1, ["x", "y"]]) it '->> #>>', -> - @testExpr({ type: "op", op: "->>", exprs: [@a, @b] }, "((?::numeric) ->> (?::numeric))", [1, 2]) - @testExpr({ type: "op", op: "#>>", exprs: [@a, @b] }, "((?::numeric) #>> (?::numeric))", [1, 2]) + @testExpr({ type: "op", op: "->>", exprs: [@a, @b] }, "(? ->> ?)", [1, 2]) + @testExpr({ type: "op", op: "#>>", exprs: [@a, @b] }, "(? #>> ?)", [1, 2]) it 'between', -> - @testExpr({ type: "op", op: "between", exprs: [@a, @b, @c] }, "((?::numeric) between (?::numeric) and (?::numeric))", [1, 2, 3]) + @testExpr({ type: "op", op: "between", exprs: [@a, @b, @c] }, "(? between ? and ?)", [1, 2, 3]) it 'aggregate expressions', -> - @testExpr({ type: "op", op: "avg", exprs: [@a] }, "avg((?::numeric))", [1]) - @testExpr({ type: "op", op: "min", exprs: [@a] }, "min((?::numeric))", [1]) - @testExpr({ type: "op", op: "max", exprs: [@a] }, "max((?::numeric))", [1]) - @testExpr({ type: "op", op: "sum", exprs: [@a] }, "sum((?::numeric))", [1]) - @testExpr({ type: "op", op: "count", exprs: [@a] }, "count((?::numeric))", [1]) - @testExpr({ type: "op", op: "stdev", exprs: [@a] }, "stdev((?::numeric))", [1]) - @testExpr({ type: "op", op: "stdevp", exprs: [@a] }, "stdevp((?::numeric))", [1]) - @testExpr({ type: "op", op: "var", exprs: [@a] }, "var((?::numeric))", [1]) - @testExpr({ type: "op", op: "varp", exprs: [@a] }, "varp((?::numeric))", [1]) + @testExpr({ type: "op", op: "avg", exprs: [@a] }, "avg(?)", [1]) + @testExpr({ type: "op", op: "min", exprs: [@a] }, "min(?)", [1]) + @testExpr({ type: "op", op: "max", exprs: [@a] }, "max(?)", [1]) + @testExpr({ type: "op", op: "sum", exprs: [@a] }, "sum(?)", [1]) + @testExpr({ type: "op", op: "count", exprs: [@a] }, "count(?)", [1]) + @testExpr({ type: "op", op: "stdev", exprs: [@a] }, "stdev(?)", [1]) + @testExpr({ type: "op", op: "stdevp", exprs: [@a] }, "stdevp(?)", [1]) + @testExpr({ type: "op", op: "var", exprs: [@a] }, "var(?)", [1]) + @testExpr({ type: "op", op: "varp", exprs: [@a] }, "varp(?)", [1]) @testExpr({ type: "op", op: "count", exprs: [] }, "count(*)", []) - @testExpr({ type: "op", op: "count", modifier: "distinct", exprs: [@a] }, "count(distinct (?::numeric))", [1]) - @testExpr({ type: "op", op: "unnest", exprs: [@a] }, "unnest((?::numeric))", [1]) + @testExpr({ type: "op", op: "count", modifier: "distinct", exprs: [@a] }, "count(distinct ?)", [1]) + @testExpr({ type: "op", op: "unnest", exprs: [@a] }, "unnest(?)", [1]) assert.throws () => - @testExpr({ type: "op", op: "xyz", exprs: [@a] }, "xyz((?::numeric))", [1]) + @testExpr({ type: "op", op: "xyz", exprs: [@a] }, "xyz(?)", [1]) it 'array_agg with orderBy', -> orderBy = [{ expr: { type: "field", tableAlias: "abc", column: "x" }, direction: "asc" }] expr = { type: "op", op: "array_agg", exprs: [@a], orderBy: orderBy } - @testExpr(expr, "array_agg((?::numeric) order by a_abc.X asc)", [1], { abc: "abc" }) + @testExpr(expr, "array_agg(? order by a_abc.X asc)", [1], { abc: "abc" }) it 'aggregate over with partitionBy', -> over = { partitionBy: [{ type: "field", tableAlias: "abc", column: "x" }] } @@ -578,17 +578,17 @@ describe "JsonqlCompiler", -> @testExpr({ type: "op", op: "exists", exprs:[ query - ] }, 'exists (select (?::numeric) as "x" from ABC as "a_abc1")', [4]) + ] }, 'exists (select ? as "x" from ABC as "a_abc1")', [4]) it 'interval', -> - @testExpr({ type: "op", op: "interval", exprs: [@str] }, "(interval (?::text))", ["xyz"]) + @testExpr({ type: "op", op: "interval", exprs: [@str] }, "(interval ?)", ["xyz"]) it 'at time zome', -> - @testExpr({ type: "op", op: "at time zone", exprs: [{ type: "op", op: "now", exprs: [] }, @str] }, "(now() at time zone (?::text))", ["xyz"]) + @testExpr({ type: "op", op: "at time zone", exprs: [{ type: "op", op: "now", exprs: [] }, @str] }, "(now() at time zone ?)", ["xyz"]) describe "scalar", -> it "simple scalar", -> - @testExpr({ type: "scalar", expr: @a, from: { type: "table", table: "abc", alias: "abc1" } }, '(select (?::numeric) from ABC as "a_abc1")', [1]) + @testExpr({ type: "scalar", expr: @a, from: { type: "table", table: "abc", alias: "abc1" } }, '(select ? from ABC as "a_abc1")', [1]) it "scalar with orderBy expr", -> @testExpr({ @@ -599,7 +599,7 @@ describe "JsonqlCompiler", -> expr: @b direction: "desc" }] - }, '(select (?::numeric) from ABC as "a_abc1" order by (?::numeric) desc)', [1,2]) + }, '(select ? from ABC as "a_abc1" order by ? desc)', [1,2]) it 'compiles scalar with withs', -> withQuery = { @@ -621,4 +621,4 @@ describe "JsonqlCompiler", -> expr: @b direction: "desc" }] - }, '(with "a_wq" as (select (?::numeric) as "q" from XYZ as "a_xyz1") select (?::numeric) from a_wq as "a_abc1" order by (?::numeric) desc)', [5,1,2]) + }, '(with "a_wq" as (select ? as "q" from XYZ as "a_xyz1") select ? from a_wq as "a_abc1" order by ? desc)', [5,1,2])