You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
raqb/src/optimizers/conditions-to-expressions.js

75 lines
2.5 KiB
JavaScript

"use strict";
const matchValue = require("match-value");
const operations = require("../operations");
const internalOperations = require("../internal-operations");
const typeOf = require("../type-of");
const unreachable = require("../unreachable");
const NoChange = require("./util/no-change");
// FIXME: anyOf(not(placeholder)) should be disallowed, but probably currently is allowed
// not(anyOf(placeholder)) is fine though
let unprocessableTypes = new Set([ "sqlExpression", "placeholder" ]);
module.exports = {
name: "conditions-to-expressions",
category: [ "normalization" ],
visitors: {
expression: (rootNode) => {
if (rootNode.condition.type === "condition") { // FIXME: typeOf
return NoChange;
} else {
// anyOfConditions, allOfConditions, notCondition
function convertNode(node) {
let listOperation = matchValue.literal(typeOf(node), {
anyOfConditions: operations.anyOf,
allOfConditions: operations.allOf,
notCondition: null,
condition: null
});
if (listOperation != null) {
if (Array.isArray(node.items)) {
return listOperation(node.items.map((item) => convertNode(item)));
} else if (unprocessableTypes.has(typeOf(node.items))) {
// Placeholders / unsafe SQL expressions are not representable as a series of expressions, as we don't know the value of them upfront. Therefore we immediately convert it to an internal ANY/ALL expression here, so that it doesn't accidentally get touched by anything else afterwards.
// FIXME: Check the relevance here of node.items.parameterizable for placeholders
return operations.expression({
left: rootNode.left,
condition: internalOperations._condition({
type: "equals",
expression: internalOperations._arrayOf({
type: matchValue(typeOf(node), {
anyOfConditions: "anyOf",
allOfConditions: "allOf"
}),
canBeParameterized: true,
items: node.items
})
})
});
} else {
unreachable("Condition item was not an array");
}
} else if (typeOf(node) === "notCondition") {
return operations.not(convertNode(node.condition));
} else if (typeOf(node) === "condition") {
return operations.expression({
left: rootNode.left,
condition: node
});
} else {
unreachable(`Encountered node type '${node.type}' within condition modifier`);
}
}
return convertNode(rootNode.condition);
}
}
}
};