"use strict" ;
const matchValue = require ( "match-value" ) ;
const operations = require ( "../operations" ) ;
const typeOf = require ( "../type-of" ) ;
const NoChange = require ( "./util/no-change" ) ;
const RemoveNode = require ( "./util/remove-node" ) ;
// FIXME: Generalize to all predicate lists?
function createHandler ( type ) {
let listOperation = matchValue . literal ( type , {
anyOfExpressions : operations . anyOf ,
allOfExpressions : operations . allOf ,
anyOfConditions : operations . anyOf ,
allOfConditions : operations . allOf ,
anyOfValues : operations . anyOf ,
allOfValues : operations . allOf ,
} ) ;
return function flattenPredicateList ( list ) {
if ( Array . isArray ( list . items ) ) {
let hasNestedPredicates = list . items . some ( ( item ) => typeOf ( item ) === type ) ;
let hasSingleItem = ( list . items . length === 1 ) ; // For unnecessary anyOf/allOf wrapping, which is also handled by this optimizer
let mustFlatten = hasNestedPredicates || hasSingleItem ;
if ( mustFlatten ) {
let actualItems = [ ] ;
function collectItemsRecursively ( node ) {
for ( let subItem of node . items ) {
if ( typeOf ( subItem ) === type ) {
collectItemsRecursively ( subItem ) ;
} else {
actualItems . push ( subItem ) ;
}
}
}
collectItemsRecursively ( list ) ;
if ( actualItems . length === 0 ) {
// FIXME: Do we want to log this as a warning? It *could* occur when items get eliminated by another optimizer, but it could also be the result of a bug...
console . warn ( "Encountered 0 actual items in predicate list" ) ;
return RemoveNode ;
} else if ( actualItems . length === 1 ) {
// Wrapping is pointless here.
return actualItems [ 0 ] ;
} else {
return listOperation ( actualItems ) ;
}
} else {
return NoChange ;
}
} else {
// Ignore placeholders, SQL fragments, etc.
return NoChange ;
}
} ;
}
module . exports = {
name : "flatten-predicate-lists" ,
category : [ "readability" ] ,
visitors : {
allOfExpressions : createHandler ( "allOfExpressions" ) ,
anyOfExpressions : createHandler ( "anyOfExpressions" ) ,
allOfConditions : createHandler ( "allOfConditions" ) ,
anyOfConditions : createHandler ( "anyOfConditions" ) ,
allOfValues : createHandler ( "allOfValues" ) ,
anyOfValues : createHandler ( "anyOfValues" ) ,
}
} ;