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