"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); } } } };