private List < IndexedQueryAnalyzer < S > . Result > splitIntoSubResults ( Filter < S > filter , OrderingList < S > ordering , QueryHints hints ) throws SupportException , RepositoryException { // Required for split to work. Filter < S > dnfFilter = filter . disjunctiveNormalForm ( ) ; Splitter splitter = new Splitter ( ordering , hints ) ; RepositoryException e = dnfFilter . accept ( splitter , null ) ; if ( e != null ) { throw e ; } List < IndexedQueryAnalyzer < S > . Result > subResults = splitter . mSubResults ; // Check if any sub-result handles nothing. If so, a full scan is the // best option for the entire query and all sub-results merge into a // single sub-result. Any sub-results which filter anything and contain // a join property in the filter are exempt from the merge. This is // because fewer joins are read than if a full scan is performed for // the entire query. The resulting union has both a full scan and an // index scan. IndexedQueryAnalyzer < S > . Result full = null ; for ( IndexedQueryAnalyzer < S > . Result result : subResults ) { if ( ! result . handlesAnything ( ) ) { full = result ; break ; } if ( ! result . getCompositeScore ( ) . getFilteringScore ( ) . hasAnyMatches ( ) ) { if ( full == null ) { // This index is used only for its ordering, and it will be // tentatively selected as the "full scan". If a result is // found doesn't use an index for anything, then it becomes // the "full scan" index. full = result ; } } } if ( full == null ) { // Okay, no full scan needed. return subResults ; } List < IndexedQueryAnalyzer < S > . Result > mergedResults = new ArrayList < IndexedQueryAnalyzer < S > . Result > ( ) ; for ( IndexedQueryAnalyzer < S > . Result result : subResults ) { if ( result == full ) { // Add after everything has been merged into it. continue ; } boolean exempt = result . getCompositeScore ( ) . getFilteringScore ( ) . hasAnyMatches ( ) ; if ( exempt ) { // Must also have a join in the filter to be exempt. List < PropertyFilter < S >> subFilters = PropertyFilterList . get ( result . getFilter ( ) ) ; joinCheck : { for ( PropertyFilter < S > subFilter : subFilters ) { if ( subFilter . getChainedProperty ( ) . getChainCount ( ) > 0 ) { // A chain implies a join was followed, so result is exempt. break joinCheck ; } } // No joins found, result is not exempt from merging into full scan. exempt = false ; } } if ( exempt ) { mergedResults . add ( result ) ; } else { full = full . mergeRemainderFilter ( result . getFilter ( ) ) ; } } if ( mergedResults . size ( ) == 0 ) { // Nothing was exempt. Rather than return a result with a dnf // filter, return full scan with a simpler reduced filter. full = full . withRemainderFilter ( filter . reduce ( ) ) ; } mergedResults . add ( full ) ; return mergedResults ; }
Splits the filter into sub - results and possibly merges them .