blob: 2d64a01b4b8a4c7d391731bacf533093215b2b2c [file] [log] [blame]
/*=========================================================================
* Copyright Copyright (c) 2000-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
* more patents listed at http://www.pivotal.io/patents.
* $Id: AbstractCompiledValue.java,v 1.1 2005/01/27 06:26:33 vaibhav Exp $
*=========================================================================
*/
package com.gemstone.gemfire.cache.query.internal;
import java.util.*;
import com.gemstone.gemfire.cache.query.*;
import com.gemstone.gemfire.cache.query.types.*;
import com.gemstone.gemfire.cache.query.internal.parse.OQLLexerTokenTypes;
import com.gemstone.gemfire.cache.query.internal.types.StructTypeImpl;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
//import com.gemstone.gemfire.cache.query.internal.types.TypeUtils;
/**
* Class Description
*
* @version $Revision: 1.1 $
* @author ericz
* @author asif
*/
public abstract class AbstractCompiledValue implements CompiledValue, Filter,
OQLLexerTokenTypes {
ObjectType typecast = null;
public ObjectType getTypecast() {
return this.typecast;
}
// used for typecasts
void setTypecast(ObjectType objectType) {
this.typecast = objectType;
}
/** Default impl returns null as N/A */
public List getPathOnIterator(RuntimeIterator itr, ExecutionContext context)
throws TypeMismatchException, AmbiguousNameException {
return null;
}
/**
* Asif : This function has a meaningful implementaion only in
* CompiledComparison & Compiled Undefined
*/
public SelectResults filterEvaluate(ExecutionContext context,
SelectResults iterationLimit, boolean completeExpansionNeeded,
CompiledValue iterOperands, RuntimeIterator[] indpndntItrs, boolean isIntersection, boolean conditioningNeeded, boolean evalProj)
throws FunctionDomainException, TypeMismatchException,
NameResolutionException, QueryInvocationTargetException {
Support
.assertionFailed("This method should not have invoked as CompieldComparison & CompiledUndefined are the only classes on which this invocation should have occured ");
return null;
}
// determine whether should evaluate as filters, and what indexes will
// be used
// default is true for evalAsFilter if independent of iterator, otherwise
// calls protGetPlanInfo (which defaults to false for evalAsFilter)
public PlanInfo getPlanInfo(ExecutionContext context)
throws FunctionDomainException, TypeMismatchException,
NameResolutionException, QueryInvocationTargetException {
PlanInfo planInfo;
//RuntimeIterator itr = context.getCurrentIterator();
//Support.Assert(itr != null);
if (!isDependentOnCurrentScope(context)) {
// Asif :If the current junction or CompliedComparison
// happens to be independent , then its basic nature to be
// evaluatable as Filter depends upon its boolean value.
// If the operand is part of a Junction , then if it evaluates
// to false, it can always support filterEvaluatable. But if it
// evaluates to true, its nature is not to support filterEvaluatable
// The gist being that if an independent operand evaluates to
// false & if the junction is AND , the whole junction can be
// filter evaluatable. But if it evaluates to true, then by itself
// it cannot make junction filterEvaluatable, but if there exists
// any other operand which had an index or is independent ( with value
// as false), then the current operand can get AuxFilterEvaluated
// along with the other auxFilterEvaluatable operand.
// But if it is an OR junction , a true value would mean that the
// Junction cannot be evaluated as filter , but if it is false then
// junction can be evaluated as a filter , provided all the operands
// are also filterEvaluatable.
planInfo = new PlanInfo();
Object result = evaluate(context);
if (!(result instanceof Boolean))
throw new TypeMismatchException(LocalizedStrings.AbstractCompiledValue_BOOLEAN_VALUE_EXPECTED_NOT_TYPE_0.toLocalizedString(result.getClass().getName()));
boolean b = ((Boolean) result).booleanValue();
planInfo.evalAsFilter = !b;
return planInfo;
}
planInfo = protGetPlanInfo(context);
return planInfo;
}
public Set computeDependencies(ExecutionContext context)
throws TypeMismatchException, AmbiguousNameException,
NameResolutionException {
// default implementation has no dependencies
// override in subclasses to add dependencies
return Collections.EMPTY_SET;
}
public boolean isDependentOnIterator(RuntimeIterator itr,
ExecutionContext context) {
return context.isDependentOn(this, itr);
}
/**
* Return true if this value is dependent on any iterator in the current scope
*/
public boolean isDependentOnCurrentScope(ExecutionContext context) {
return context.isDependentOnCurrentScope(this);
}
// Invariant: the receiver is dependent on the current iterator.
protected PlanInfo protGetPlanInfo(ExecutionContext context)
throws FunctionDomainException, TypeMismatchException,
NameResolutionException, QueryInvocationTargetException {
return new PlanInfo(); // default behavior
}
// Utility methods
/**
* return operator used when terms are reversed, maintaining the semantics e.g
* salary < 100000 swapped to 100000 > salary, salary >= 100000 swapped to
* 100000 <= salary or salary = 100000 swapped to salary = 100000
*/
protected int reflectOperator(int op) {
switch (op) {
case TOK_EQ:
return TOK_EQ;
case TOK_NE:
return TOK_NE;
case TOK_LT:
return TOK_GT;
case TOK_GE:
return TOK_LE;
case TOK_LE:
return TOK_GE;
case TOK_GT:
return TOK_LT;
default:
Support.assertionFailed("unknown operator: " + op);
throw new Error("this line of code can never be executed");
}
}
/**
* return operator to invert the value of the result. e.g. salary < 100000
* will become salary >= 100000 or salary = 100000 becomes salary != 100000
*/
protected int inverseOperator(int op) {
switch (op) {
case LITERAL_and:
return LITERAL_or;
case LITERAL_or:
return LITERAL_and;
case TOK_EQ:
return TOK_NE;
case TOK_NE:
return TOK_EQ;
case TOK_LT:
return TOK_GE;
case TOK_GE:
return TOK_LT;
case TOK_LE:
return TOK_GT;
case TOK_GT:
return TOK_LE;
default:
Support.assertionFailed("unknown operator: " + op);
throw new Error("this line of code can never be executed");
}
}
/**
* this is a lower level filter evaluation call. Most Filters do nothing
* different here than a normal filterEvaluate. This is here for benefit of
* nested CompiledJunctions: filterEvaluate is called first, then
* auxFilterEvaluate is called on the operands that have been organized to be
* filters
*
* @see CompiledJunction#filterEvaluate
*/
public SelectResults auxFilterEvaluate(ExecutionContext context,
SelectResults intermediateResults) throws FunctionDomainException,
TypeMismatchException, NameResolutionException,
QueryInvocationTargetException {
return filterEvaluate(context, intermediateResults);
}
public SelectResults filterEvaluate(ExecutionContext context,
SelectResults intermediateResults) throws FunctionDomainException,
TypeMismatchException, NameResolutionException,
QueryInvocationTargetException {
// for the general case of filter evaluation, most compiled values
// can only be evaluated in this way if they are independent of the current
// iterator,
// This method is also only applicable in places where a boolean value is
// expected.
//RuntimeIterator itr = context.getCurrentIterator();
//Support.Assert(itr != null);
// if it is possible for the following assertion to be false,
// then this method as well as protGetPlanInfo must be overridden
Support.Assert(!isDependentOnCurrentScope(context));
Object result = evaluate(context);
if (result == null || result == QueryService.UNDEFINED)
return new ResultsBag(intermediateResults.getCollectionType()
.getElementType(), 0, context.getCachePerfStats());
if (!(result instanceof Boolean))
throw new TypeMismatchException(LocalizedStrings.AbstractCompiledValue_BOOLEAN_VALUE_EXPECTED_NOT_TYPE_0.toLocalizedString(result.getClass().getName()));
boolean b = ((Boolean) result).booleanValue();
//Asif : Boolean true, means the cartesian of all the RuntimeIterators
// indicated by null value. A false means an empty ResultSet
if (b) {
return null;
}
else {
//Asif : We need to return either an empty ResultSet or an empty
// StructSet based
// on the number of iterators in the current scope.
SelectResults emptySet = null;
List iterators = context.getCurrentIterators();
int len = iterators.size();
if (len == 1) {
ObjectType elementType = ((RuntimeIterator) iterators.get(0))
.getElementType();
emptySet = context.isDistinct() ? new ResultsSet(elementType) :
new ResultsBag(elementType, 0, context.getCachePerfStats());
}
else {
String fieldNames[] = new String[len];
ObjectType fieldTypes[] = new ObjectType[len];
for (int i = 0; i < len; i++) {
RuntimeIterator iter = (RuntimeIterator) iterators.get(i);
fieldNames[i] = iter.getInternalId();
fieldTypes[i] = iter.getElementType();
}
emptySet = context.isDistinct() ? new StructSet(new StructTypeImpl(fieldNames, fieldTypes))
:new StructBag(0, new StructTypeImpl(fieldNames, fieldTypes), context.getCachePerfStats());
}
return emptySet;
}
}
// This function needs to be appropriately overridden in the derived classes
public void generateCanonicalizedExpression(StringBuffer clauseBuffer,
ExecutionContext context) throws AmbiguousNameException,
TypeMismatchException, NameResolutionException {
clauseBuffer.insert(0, System.currentTimeMillis());
clauseBuffer.insert(0, this.getClass());
clauseBuffer.insert(0, '.');
}
public void getRegionsInQuery(Set regionsInQuery, Object[] parameters) {
for (Iterator itr = getChildren().iterator(); itr.hasNext(); ) {
CompiledValue v = (CompiledValue)itr.next();
if (v == null) {
throw new NullPointerException(LocalizedStrings.AbstractCompiledValue_GOT_NULL_AS_A_CHILD_FROM_0.toLocalizedString(this));
}
v.getRegionsInQuery(regionsInQuery, parameters);
}
}
/** Get the CompiledValues that this owns */
public List getChildren() {
return Collections.EMPTY_LIST;
}
public int getSizeEstimate(ExecutionContext context)throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
throw new UnsupportedOperationException("This method should not have been invoked");
}
public void visitNodes(NodeVisitor visitor) {
visitor.visit(this);
for (Iterator itr = getChildren().iterator(); itr.hasNext(); ) {
if (!visitor.visit((CompiledValue)itr.next())) {
break;
}
}
}
public boolean isProjectionEvaluationAPossibility(ExecutionContext context) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException
{
throw new UnsupportedOperationException("This method should not have been invoked");
}
public boolean isLimitApplicableAtIndexLevel(ExecutionContext context) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
throw new UnsupportedOperationException("This method should not have been invoked");
}
public boolean isOrderByApplicableAtIndexLevel(ExecutionContext context, String canonicalizedOrderByClause) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
throw new UnsupportedOperationException("This method should not have been invoked");
}
public boolean isConditioningNeededForIndex(RuntimeIterator independentIter, ExecutionContext context, boolean completeExpnsNeeded) throws AmbiguousNameException, TypeMismatchException, NameResolutionException {
throw new UnsupportedOperationException("This method should not have been invoked");
}
public int getOperator() {
throw new UnsupportedOperationException("This method should not have been invoked");
}
public boolean isBetterFilter(Filter comparedTo, ExecutionContext context, int thisSize) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
throw new UnsupportedOperationException("This method should not have been invoked");
}
public CompiledValue getReceiver() {
throw new UnsupportedOperationException("This method should not have been invoked");
}
}