| /*========================================================================= |
| * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved. |
| * This product is protected by U.S. and international copyright |
| * and intellectual property laws. Pivotal products are covered by |
| * one or more patents listed at http://www.pivotal.io/patents. |
| *========================================================================= |
| */ |
| /* |
| * Created on Oct 25, 2005 |
| */ |
| package com.gemstone.gemfire.cache.query.internal; |
| |
| import java.util.*; |
| import com.gemstone.gemfire.cache.query.FunctionDomainException; |
| import com.gemstone.gemfire.cache.query.NameResolutionException; |
| import com.gemstone.gemfire.cache.query.QueryInvocationTargetException; |
| import com.gemstone.gemfire.cache.query.SelectResults; |
| import com.gemstone.gemfire.cache.query.TypeMismatchException; |
| import com.gemstone.gemfire.cache.query.internal.parse.OQLLexerTokenTypes; |
| import com.gemstone.gemfire.cache.query.internal.types.StructTypeImpl; |
| import com.gemstone.gemfire.cache.query.types.ObjectType; |
| import com.gemstone.gemfire.cache.query.types.StructType; |
| |
| /** |
| * An object of this class gets created during the organization of operands in a |
| * CompiledJunction. It gets created if there exists multiple filter evaluable |
| * conditions in where clause of the query with those conditions dependent on |
| * more than one group of independent iterators. Thus presence of more than one |
| * region in a query is a prerequisite for the creation of this object. However, |
| * actual creation will occur iff there exists more than one GroupJunction or |
| * more than one CompositeGroupJunction or a combination of one or more |
| * GroupJunctions & one or more CompositeGroupJunctions |
| * |
| * @author Asif |
| * @author kdeshpan |
| */ |
| public class AllGroupJunction extends AbstractCompiledValue implements Filter, |
| OQLLexerTokenTypes { |
| |
| private List abstractGroupOrRangeJunctions = null; |
| private int operator = 0; |
| private List iterOperands = null; |
| |
| AllGroupJunction(List abstractGroupOrRangeJunctions, int operator, List iterOperands) { |
| this.operator = operator; |
| this.abstractGroupOrRangeJunctions = abstractGroupOrRangeJunctions; |
| if (operator != LITERAL_and) { |
| Support.Assert(iterOperands.size() == 0, |
| "For OR Junction all operands need to be filterOperands"); |
| } |
| this.iterOperands = iterOperands; |
| } |
| |
| @Override |
| public List getChildren() { |
| List children = new ArrayList(); |
| children.addAll(this.abstractGroupOrRangeJunctions); |
| children.addAll(this.iterOperands); |
| return children; |
| } |
| |
| public Object evaluate(ExecutionContext context) { |
| Support.assertionFailed("Should not have come here"); |
| return null; |
| } |
| |
| public int getType() { |
| return ALLGROUPJUNCTION; |
| } |
| |
| @Override |
| public SelectResults filterEvaluate(ExecutionContext context, |
| SelectResults intermediateResults) throws FunctionDomainException, |
| TypeMismatchException, NameResolutionException, |
| QueryInvocationTargetException { |
| if (this.operator == LITERAL_and) { |
| return evaluateAndJunction(context); |
| } |
| else { |
| return evaluateOrJunction(context); |
| } |
| } |
| |
| /** |
| * Asif:Evaluates the individual GroupJunctions and CompositeGroupJunctions |
| * and does a cartesian of the results so obtained and simultaneously |
| * expanding it to the query from clause level as well as evaluating any iter |
| * evaluatable conditions. The evaluated result of an AllGroupJunction will |
| * always be of the query from clause level which can be ORed or ANDd with |
| * filter evaluatable subtree CompiledJunction |
| * |
| * @param context ExecutionContext object |
| * @return SelectResults |
| * @throws FunctionDomainException |
| * @throws TypeMismatchException |
| * @throws NameResolutionException |
| * @throws QueryInvocationTargetException |
| */ |
| // Asif : For doing the Cartesian first evaluate the result of all Group |
| // Junction. Doing Cartesian of all the Results together is better than doing |
| // in pair |
| private SelectResults evaluateAndJunction(ExecutionContext context) |
| throws FunctionDomainException, TypeMismatchException, |
| NameResolutionException, QueryInvocationTargetException { |
| int len = this.abstractGroupOrRangeJunctions.size(); |
| // Asif : Create an array of SelectResults for each of the GroupJunction |
| // For each Group Junction there will be a corresponding array of |
| // RuntimeIterators which will map to the fields of the ResultSet obtained |
| // from Group Junction. |
| SelectResults[] results = new SelectResults[len]; |
| List finalList = context.getCurrentIterators(); |
| List expansionList = new LinkedList(finalList); |
| RuntimeIterator[][] itrsForResultFields = new RuntimeIterator[len][]; |
| CompiledValue gj = null; |
| Iterator junctionItr = this.abstractGroupOrRangeJunctions.iterator(); |
| List grpItrs = null; |
| int j = 0; |
| RuntimeIterator tempItr = null; |
| while (junctionItr.hasNext()) { |
| gj = (CompiledValue) junctionItr.next(); |
| SelectResults filterResults = ((Filter) gj).filterEvaluate(context, null); |
| Support |
| .Assert(filterResults != null, "FilterResults cannot be null here"); |
| if (filterResults.isEmpty()) { |
| if (finalList.size() > 1) { |
| StructType type = QueryUtils |
| .createStructTypeForRuntimeIterators(finalList); |
| return QueryUtils.createStructCollection(context, type); |
| } |
| else { |
| ObjectType type = ((RuntimeIterator) finalList.iterator().next()) |
| .getElementType(); |
| if (type instanceof StructType) { |
| return QueryUtils.createStructCollection(context, (StructTypeImpl)type); |
| } |
| else { |
| return QueryUtils.createResultCollection(context, type); |
| } |
| } |
| } |
| else { |
| results[j] = filterResults; |
| grpItrs = (gj instanceof CompositeGroupJunction) ? QueryUtils |
| .getDependentItrChainForIndpndntItrs(((CompositeGroupJunction) gj) |
| .getIndependentIteratorsOfCJ(), context) |
| : context |
| .getCurrScopeDpndntItrsBasedOnSingleIndpndntItr(((AbstractGroupOrRangeJunction) gj) |
| .getIndependentIteratorForGroup()[0]); |
| itrsForResultFields[j] = new RuntimeIterator[grpItrs.size()]; |
| Iterator grpItr = grpItrs.iterator(); |
| int k = 0; |
| while (grpItr.hasNext()) { |
| tempItr = (RuntimeIterator) grpItr.next(); |
| itrsForResultFields[j][k++] = tempItr; |
| expansionList.remove(tempItr); |
| } |
| ++j; |
| } |
| } |
| SelectResults resultsSet = null; |
| // Asif : Do the Cartesian of the different group junction results. |
| CompiledValue iterOperandsToSend = null; |
| if (!iterOperands.isEmpty()) { |
| //TODO ASIF : Avoid creation of CompiledJunction by providing |
| // functionality in AllGroupJunction for evaluating condition |
| int size = iterOperands.size(); |
| CompiledValue cv[] = new CompiledValue[size]; |
| for (int k = 0; k < size; ++k) { |
| cv[k] = (CompiledValue) this.iterOperands.get(k); |
| } |
| if (cv.length == 1) { |
| iterOperandsToSend = cv[0]; |
| } |
| else { |
| iterOperandsToSend = new CompiledJunction(cv, this.operator); |
| } |
| } |
| QueryObserver observer = QueryObserverHolder.getInstance(); |
| observer |
| .beforeCartesianOfGroupJunctionsInAnAllGroupJunctionOfType_AND(results); |
| resultsSet = QueryUtils.cartesian(results, itrsForResultFields, |
| expansionList, finalList, context, iterOperandsToSend); |
| observer.afterCartesianOfGroupJunctionsInAnAllGroupJunctionOfType_AND(); |
| Support.Assert(resultsSet != null, |
| "ResultsSet obtained was NULL in AllGroupJunction"); |
| return resultsSet; |
| } |
| |
| /** |
| * Evaluates the individual GroupJunctions and CompositeGroupJunctions and |
| * expands the individual results so obtained to the query from clause |
| * iterator level ( i.e top level iterators). The expanded results so obtained |
| * are then merged (union) to get the ORed results.The evaluated result of an |
| * AllGroupJunction will always be of the query from clause iterator level |
| * (top level) which can be ORed or ANDd with filter evaluable subtree |
| * CompiledJunction. |
| * |
| * @param context ExecutionContext object |
| * @return SelectResults object |
| * @throws FunctionDomainException |
| * @throws TypeMismatchException |
| * @throws NameResolutionException |
| * @throws QueryInvocationTargetException |
| */ |
| private SelectResults evaluateOrJunction(ExecutionContext context) |
| throws FunctionDomainException, TypeMismatchException, |
| NameResolutionException, QueryInvocationTargetException { |
| // int len = this.abstractGroupOrRangeJunctions.size(); |
| // Asif : Create an array of SelectResults for each of the GroupJunction |
| // For each Group Junction there will be a corresponding array of |
| // RuntimeIterators which will map to the fields of the ResultSet obtained |
| // from Group Junction |
| SelectResults[] grpResults = new SelectResults[1]; |
| List finalList = context.getCurrentIterators(); |
| RuntimeIterator[][] itrsForResultFields = new RuntimeIterator[1][]; |
| CompiledValue gj = null; |
| Iterator junctionItr = this.abstractGroupOrRangeJunctions.iterator(); |
| List grpItrs = null; |
| RuntimeIterator tempItr = null; |
| SelectResults intermediateResults = null; |
| while (junctionItr.hasNext()) { |
| List expansionList = new LinkedList(finalList); |
| gj = (CompiledValue) junctionItr.next(); |
| grpResults[0] = ((Filter) gj).filterEvaluate(context, null); |
| grpItrs = (gj instanceof CompositeGroupJunction) ? QueryUtils |
| .getDependentItrChainForIndpndntItrs(((CompositeGroupJunction) gj) |
| .getIndependentIteratorsOfCJ(), context) : context |
| .getCurrScopeDpndntItrsBasedOnSingleIndpndntItr(((AbstractGroupOrRangeJunction) gj) |
| .getIndependentIteratorForGroup()[0]); |
| itrsForResultFields[0] = new RuntimeIterator[grpItrs.size()]; |
| Iterator grpItr = grpItrs.iterator(); |
| int k = 0; |
| while (grpItr.hasNext()) { |
| tempItr = (RuntimeIterator) grpItr.next(); |
| itrsForResultFields[0][k++] = tempItr; |
| expansionList.remove(tempItr); |
| } |
| SelectResults expandedResult = QueryUtils.cartesian(grpResults, |
| itrsForResultFields, expansionList, finalList, context, null/* |
| * Iter |
| * oprenad |
| * for OR |
| * Junction |
| * evaluation |
| * should |
| * be null |
| */); |
| intermediateResults = (intermediateResults == null) ? expandedResult |
| : QueryUtils.union(expandedResult, intermediateResults, context); |
| } |
| return intermediateResults; |
| } |
| |
| List getGroupOperands() { |
| // return unmodifiable copy |
| return Collections.unmodifiableList(this.abstractGroupOrRangeJunctions); |
| } |
| |
| List getIterOperands() { |
| // return unmodifiable copy |
| return Collections.unmodifiableList(this.iterOperands); |
| } |
| |
| public int getSizeEstimate(ExecutionContext context)throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException { |
| return 1; |
| } |
| } |