blob: 9e6540d6c30c809347ed808d15a714ccaff0b912 [file] [log] [blame]
/*=========================================================================
* 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;
}
}