public void createSubs ( List < QueryTreeNode > subQueries ) { if ( ! isBranchIndexed ( ) ) { //nothing to do, stop searching this branch return ; } //If op=OR and if and sub-nodes are indexed, then we split. if ( LOG_OP . OR . equals ( op ) ) { //clone both branches (WHY ?) QueryTreeNode node1 ; if ( n1 != null ) { node1 = n1 ; } else { n1 = node1 = new QueryTreeNode ( null , t1 , null , null , null , false ) ; t1 = null ; } QueryTreeNode node2 ; if ( n2 != null ) { node2 = n2 . cloneBranch ( ) ; } else { n2 = node2 = new QueryTreeNode ( null , t2 , null , null , null , false ) ; t2 = null ; } //we remove the OR from the tree and assign the first clone/branch to any parent QueryTreeNode newTree ; if ( p != null ) { //remove local OR and replace with n1 if ( p . n1 == this ) { p . n1 = node1 ; p . t1 = null ; p . relateToChildren ( ) ; } else if ( p . n2 == this ) { p . n2 = node1 ; p . t2 = null ; p . relateToChildren ( ) ; } else { throw new IllegalStateException ( ) ; } //clone and replace with child number n2/t2 //newTree = cloneSingle(n2, t2, null, null); } else { //no parent. //still remove this one and replace it with the first sub-node //TODO should we use a set for faster removal? subQueries . remove ( this ) ; subQueries . add ( node1 ) ; if ( node1 != null ) { node1 . p = null ; } if ( node2 != null ) { node2 . p = null ; } } //now treat second branch and create a new parent for it, if necessary. if ( p != null ) { newTree = p . cloneTrunk ( node1 , node2 ) ; } else { newTree = node2 ; } //subQueriesCandidates.add(newTree.root()); newTree . createSubs ( subQueries ) ; subQueries . add ( newTree . root ( ) ) ; } //go into sub-nodes if ( n1 != null ) { n1 . createSubs ( subQueries ) ; } if ( n2 != null ) { n2 . createSubs ( subQueries ) ; } }
This method splits a query into multiple queries for every occurrence of OR . It walks down the query tree recursively always doubling the tree when encountering an OR in an indexed branch . A branch is indexed if one of it s terms references an indexed field .