WIP (only parameterize things in arrays that actually *can* be parameterized)

master
Sven Slootweg 4 years ago
parent b5d0ca7c53
commit f018f8a355

@ -43,29 +43,42 @@ try {
// left: "foo",
// condition: equals("bar")
// });
let niceNumbers = anyOf([ 1, 2, 3 ]);
query = select("projects", [
where({
// foo: anyOf([ "bar", not(not("baz")), anyOf([ "bar2", "baz2" ]), unsafeSQL("TRUE") ]),
// qux: anyOf([ 13, moreThan(42) ]),
complex: anyOf([
30,
40,
allOf([
moreThan(100),
lessThan(200),
lessThan(parameter("max"))
])
])
number_one: niceNumbers,
number_two: niceNumbers
}),
// where({ second: 2 }),
// where(not({
// thirdA: 3,
// thirdB: 3
// })),
// where(anyOf([ { foo: "bar" } ]))
where({
number_three: anyOf([ 42, column("number_one") ]),
number_four: 1337
})
]);
// query = select("projects", [
// where({
// // foo: anyOf([ "bar", not(not("baz")), anyOf([ "bar2", "baz2" ]), unsafeSQL("TRUE") ]),
// // qux: anyOf([ 13, moreThan(42) ]),
// complex: anyOf([
// 30,
// 40,
// allOf([
// moreThan(100),
// lessThan(200),
// lessThan(parameter("max"))
// ])
// ])
// }),
// // where({ second: 2 }),
// // where(not({
// // thirdA: 3,
// // thirdB: 3
// // })),
// // where(anyOf([ { foo: "bar" } ]))
// ]);
// query = select("projects", [
// onlyColumns([

@ -163,9 +163,12 @@ function $parenthesize(query) {
return $combine`(${query})`;
}
// FIXME: This is a bit hacky; we should probably have a `$parenthesizedHandle` or something instead...
let simpleColumnNameRegex = /^[a-z_]+(?:\.[a-z_]+)?$/;
function $maybeParenthesize($query) {
if ($query.query === "?") {
// We don't want to bloat the generated query with unnecessary parentheses, so we leave them out for things that only evaluated to placeholders anyway. Other simple cases may be added here in the future, though we're limited in what we can *safely and reliably* analyze from already-generated SQL output.
if ($query.query === "?" || simpleColumnNameRegex.test($query.query)) {
// We don't want to bloat the generated query with unnecessary parentheses, so we leave them out for things that only evaluated to placeholders or column names anyway. Other simple cases may be added here in the future, though we're limited in what we can *safely and reliably* analyze from already-generated SQL output.
return $query;
} else {
return $parenthesize($query);
@ -180,12 +183,10 @@ function $maybeParenthesizeAll(nodes) {
return nodes.map((node) => $maybeParenthesize(node));
}
function $arrayFrom(items) {
let containsSQLExpressions = Array.isArray(items) && items.some((item) => typeOf(item) === "sqlExpression");
function $arrayFrom(items, canBeParameterized) {
if (typeOf(items) === "placeholder") {
return $handle(items);
} else if (containsSQLExpressions) {
} else if (!canBeParameterized) {
// If the list contains SQL expressions, we cannot pass it in as a param at query time; we need to explicitly compile the expressions into the query
let $items = items.map((item) => $maybeParenthesize($handle(item)));
@ -288,7 +289,7 @@ let process = {
notExpression: function ({ expression }) {
return $combine`NOT (${$handle(expression)})`;
},
_arrayOf: function ({ listType, items }) {
_arrayOf: function ({ listType, items, canBeParameterized }) {
let $keyword = $object({
query: matchValue(listType, {
anyOf: "ANY",
@ -297,7 +298,7 @@ let process = {
});
// return $combine`${keyword}(${$maybeParenthesize($arrayFrom(items))})`;
return $combine`${$keyword}(${$arrayFrom(items)})`;
return $combine`${$keyword}(${$arrayFrom(items, canBeParameterized)})`;
},
anyOfExpressions: function ({ items }) {
if (items.length === 1) {

@ -4,6 +4,7 @@ const { validateOptions } = require("@validatem/core");
const required = require("@validatem/required");
const oneOf = require("@validatem/one-of");
const arrayOf = require("@validatem/array-of");
const isBoolean = require("@validatem/is-boolean");
const node = require("../ast-node");
@ -11,13 +12,15 @@ module.exports = function (operations) {
const isValueExpression = require("../validators/operations/is-value-expression")(operations);
return function _arrayOf(_options) {
let { type, items } = validateOptions(arguments, {
let { type, items, canBeParameterized } = validateOptions(arguments, {
type: [ required, oneOf([ "anyOf", "allOf" ]) ],
canBeParameterized: [ required, isBoolean ],
items: [ required, arrayOf(isValueExpression) ]
});
return node({
type: "_arrayOf",
canBeParameterized: canBeParameterized,
listType: type,
items: items
});

@ -7,8 +7,11 @@ const syncpipe = require("syncpipe");
const operations = require("../operations");
const internalOperations = require("../internal-operations");
const concat = require("../concat");
const typeOf = require("../type-of");
const NoChange = require("./util/no-change");
let parameterizableTypes = [ "literalValue", "placeholder" ];
// FIXME: Have some sort of internally-cacheable way to find nodes of a certain type? So that different optimizer visitors don't need to filter the list of clauses over and over again...
function leftIdentity(left) {
@ -94,6 +97,7 @@ function createHandler(type) {
return expressions[0];
} else {
let allValues = expressions.map((expression) => expression.condition.expression);
let canBeParameterized = allValues.every((value) => parameterizableTypes.includes(typeOf(value)));
return operations.expression({
left: expressions[0].left,
@ -101,6 +105,7 @@ function createHandler(type) {
type: conditionType,
expression: internalOperations._arrayOf({
type: internalArrayType,
canBeParameterized: canBeParameterized,
items: allValues
})
})

Loading…
Cancel
Save