| /*========================================================================= |
| * 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 Jan 27, 2008 |
| */ |
| package com.gemstone.gemfire.cache.query.internal; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| |
| import com.gemstone.gemfire.cache.query.AmbiguousNameException; |
| import com.gemstone.gemfire.cache.query.FunctionDomainException; |
| import com.gemstone.gemfire.cache.query.Index; |
| import com.gemstone.gemfire.cache.query.NameResolutionException; |
| import com.gemstone.gemfire.cache.query.QueryInvocationTargetException; |
| import com.gemstone.gemfire.cache.query.QueryService; |
| import com.gemstone.gemfire.cache.query.SelectResults; |
| import com.gemstone.gemfire.cache.query.TypeMismatchException; |
| import com.gemstone.gemfire.internal.i18n.LocalizedStrings; |
| import com.gemstone.gemfire.cache.query.internal.parse.OQLLexerTokenTypes; |
| import com.gemstone.gemfire.cache.query.internal.types.StructTypeImpl; |
| import com.gemstone.gemfire.cache.query.internal.types.TypeUtils; |
| import com.gemstone.gemfire.cache.query.types.ObjectType; |
| import com.gemstone.gemfire.cache.query.types.StructType; |
| |
| /** |
| * This structure contains all the filter evaluatable CompiledComparision |
| * conditions which are using identical index. Presently this Object will be |
| * formed only if the junction is an AND and will either be a part of a |
| * GroupJunction or can be a stand alone Junction. In case it is a stand alone |
| * Junction, then it can possibly have a not null Iter Operand, so that it can |
| * be evaluated along with the expansion/truncation of index result. |
| * |
| * @author asif |
| */ |
| public class RangeJunction extends AbstractGroupOrRangeJunction { |
| private final static int RANGE_SIZE_ESTIMATE = 3; |
| //moved to AbstractGroupOrRangeJunction |
| //private CompiledValue iterOperands; |
| |
| RangeJunction(int operator, RuntimeIterator[] indpndntItr, |
| boolean isCompleteExpansion, CompiledValue[] operands) { |
| super(operator, indpndntItr, isCompleteExpansion, operands); |
| |
| } |
| void addUnevaluatedFilterOperands(List unevaluatedFilterOps) { |
| throw new UnsupportedOperationException("This method should not have been invoked"); |
| } |
| // moved to AbstractGroupOrRangeJunction |
| /* void addIterOperands(CompiledValue iterOps) { |
| this.iterOperands = iterOps; |
| }*/ |
| private RangeJunction(AbstractGroupOrRangeJunction oldGJ, |
| boolean completeExpansion, RuntimeIterator indpnds[], CompiledValue iterOp) { |
| super(oldGJ, completeExpansion, indpnds, iterOp); |
| } |
| |
| @Override |
| AbstractGroupOrRangeJunction recreateFromOld(boolean completeExpansion, |
| RuntimeIterator indpnds[], CompiledValue iterOp) { |
| return new RangeJunction(this, completeExpansion, indpnds, iterOp); |
| } |
| |
| @Override |
| AbstractGroupOrRangeJunction createNewOfSameType(int operator, |
| RuntimeIterator[] indpndntItr, boolean isCompleteExpansion, |
| CompiledValue[] operands) { |
| return new RangeJunction(operator, indpndntItr, isCompleteExpansion, |
| operands); |
| } |
| |
| @Override |
| public PlanInfo getPlanInfo(ExecutionContext context) |
| throws FunctionDomainException, TypeMismatchException, |
| NameResolutionException, QueryInvocationTargetException { |
| /* |
| * This function would be called only if the RangeJunction is a part of |
| * GroupJunction.It would be invoked in the organized operands method of |
| * GroupJunction. In such case it is guaranteed that all the operands are |
| * the filter operand using the same index. In such case there is zero |
| * possibility o first iterator being either an iter operand or a constant. |
| * As those types of Operands would be part of Group Junction |
| */ |
| return this._operands[0].getPlanInfo(context); |
| } |
| |
| public boolean isConditioningNeededForIndex(RuntimeIterator independentIter, ExecutionContext context, boolean completeExpnsNeeded) throws AmbiguousNameException, TypeMismatchException, NameResolutionException { |
| return true; |
| } |
| |
| public int getOperator() { |
| return LITERAL_and; |
| } |
| |
| public boolean isBetterFilter(Filter comparedTo, ExecutionContext context, final int thisSize) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException |
| { |
| //If the current filter is equality & comparedTo filter is also equality based , then |
| // return the one with lower size estimate is better |
| boolean isThisBetter = true; |
| |
| //Go with the lowest cost when hint is used. |
| if (context instanceof QueryExecutionContext && ((QueryExecutionContext)context).hasHints()) { |
| return thisSize <= comparedTo.getSizeEstimate(context); |
| } |
| |
| int thatOperator = comparedTo.getOperator() ; |
| switch(thatOperator) { |
| case TOK_EQ: |
| isThisBetter = false; |
| break; |
| case TOK_NE: |
| case TOK_NE_ALT: |
| //Give preference to Range |
| break; |
| case LITERAL_and: |
| //Asif: What to do? Let current be the better one for the want of better estimation |
| break; |
| case TOK_LE: |
| case TOK_LT: |
| case TOK_GE: |
| case TOK_GT: |
| //Give preference to this rather than single condition inequalities as a rangejunction |
| //would possibly be bounded resulting in lesser values |
| break; |
| default : |
| throw new IllegalArgumentException("The operator type ="+ thatOperator + " is unknown"); |
| } |
| |
| return isThisBetter; |
| } |
| |
| /** |
| * Segregates the operands of the RangeJunction into iter evaluatable and |
| * filter evaluatable. |
| */ |
| @Override |
| OrganizedOperands organizeOperands(ExecutionContext context) |
| throws FunctionDomainException, TypeMismatchException, |
| NameResolutionException, QueryInvocationTargetException { |
| // get the list of operands to evaluate, |
| // and evaluate operands that can use indexes first |
| if (getOperator() == LITERAL_and) { |
| return organizeOperandsForAndJunction(context); |
| } |
| else { |
| throw new IllegalStateException( |
| LocalizedStrings.RangeJunction_IN_THE_CASE_OF_AN_OR_JUNCTION_A_RANGEJUNCTION_SHOULD_NOT_BE_FORMED_FOR_NOW.toLocalizedString()); |
| } |
| } |
| |
| // TODO:Asif: Currently the condition a!= null AND a =3, would be evalauted |
| // via intersection. This needs to be optmized, but since it is not |
| // common use case as != null is a not required operand , for the time being |
| // ignoring the optmization. |
| /** |
| * For the filter evaluatable conditions , it creates the appropriate |
| * JunctionEvaluator ( NotEqualConditionEvaluator or SingleCondnEvaluator or |
| * DoubleCondnRangeJunctionEvaluator ). The junction Evaluator itself is |
| * filter evaluatable. The operands which are of type != null , == null , != |
| * undefined, == undefined are left as it is & are not combined into a |
| * Junction Evaluator. Thus the organized operand of RangeJunction may created |
| * atmost one Condition Evaluator, will retain the operands containing null |
| * ,undefined conditions. In case there is a equality condition , then it may |
| * result in a filter having just that condition assuming other conditions |
| * satisfy the equality. In case it turns out that the conditions are mutually |
| * exclusive then the organized operand would just contain a single filter |
| * evaluatable CompiledLiteral (false) ( indicating empty resultset). |
| */ |
| private OrganizedOperands organizeOperandsForAndJunction( |
| ExecutionContext context) throws AmbiguousNameException, |
| FunctionDomainException, TypeMismatchException, NameResolutionException, |
| QueryInvocationTargetException { |
| List evalOperands = new ArrayList(_operands.length); |
| int evalCount = 0; |
| int lessCondnOp = -1; |
| int greaterCondnOp = -1; |
| CompiledComparison lessCondnOperand = null; |
| CompiledComparison greaterCondnOperand = null; |
| CompiledComparison equalCondnOperand = null; |
| Object equalCondKey = null; |
| Object lessCondnKey = null; |
| Object greaterCondnKey = null; |
| boolean emptyResults = false; |
| Set notEqualTypeKeys = null; |
| boolean possibleRangeFilter = false; |
| IndexInfo indxInfo = null; |
| for (int i = 0; i < _operands.length; i++) { |
| CompiledValue operand = _operands[i]; |
| if (operand.getPlanInfo(context).evalAsFilter) { |
| Indexable cc = (Indexable)operand; |
| if (indxInfo == null) { |
| indxInfo = cc.getIndexInfo(context)[0]; |
| } |
| // TODO: Asif :Try to ensure that a CompiledUndefined never |
| // goes in the RangeJunction. That means modify the |
| // CompiledJunction code to avoid CompiledUndefined's inclusion |
| // That way we can ensure that CompiledComparison only become part |
| // of RangeJunction |
| if (!cc.isRangeEvaluatable()) { |
| evalCount++; |
| evalOperands.add(0, _operands[i]); |
| continue; |
| } |
| CompiledValue ccKey = ((CompiledComparison)cc).getKey(context); |
| Object evaluatedCCKey = ccKey.evaluate(context); |
| int operator = ((CompiledComparison)cc).reflectOnOperator(ccKey); |
| if (evaluatedCCKey == null) { |
| evalCount++; |
| evalOperands.add(0, _operands[i]); |
| continue; |
| } |
| if (equalCondnOperand != null) { |
| emptyResults = !isConditionSatisfied(equalCondKey, evaluatedCCKey, |
| operator); |
| if (emptyResults) { |
| break; |
| } |
| else { |
| continue; |
| } |
| } |
| |
| switch (operator) { |
| case TOK_EQ: |
| possibleRangeFilter = false; |
| equalCondnOperand = (CompiledComparison)cc; |
| equalCondKey = evaluatedCCKey; |
| break; |
| case TOK_NE: |
| case TOK_NE_ALT: |
| possibleRangeFilter = true; |
| if (notEqualTypeKeys == null) { |
| notEqualTypeKeys = new HashSet(_operands.length); |
| } |
| evaluatedCCKey = TypeUtils.indexKeyFor(evaluatedCCKey); |
| notEqualTypeKeys.add(evaluatedCCKey); |
| break; |
| case TOK_GE: |
| case TOK_GT: |
| possibleRangeFilter = true; |
| if (greaterCondnOperand == null) { |
| greaterCondnOperand = (CompiledComparison)cc; |
| greaterCondnKey = evaluatedCCKey; |
| greaterCondnOp = operator; |
| } |
| else { |
| if (isConditionSatisfied(evaluatedCCKey, greaterCondnKey, |
| greaterCondnOp)) { |
| greaterCondnKey = evaluatedCCKey; |
| greaterCondnOperand = (CompiledComparison)cc; |
| greaterCondnOp = operator; |
| } |
| } |
| break; |
| case TOK_LE: |
| case TOK_LT: |
| // Asif: if there exists a previous equal Operand & current |
| // condition's value is greater than the equal operand's value, it |
| // will be empty results |
| possibleRangeFilter = true; |
| if (lessCondnOperand == null) { |
| lessCondnOperand = (CompiledComparison)cc; |
| lessCondnKey = evaluatedCCKey; |
| lessCondnOp = operator; |
| } |
| else { |
| if (isConditionSatisfied(evaluatedCCKey, lessCondnKey, lessCondnOp)) { |
| lessCondnKey = evaluatedCCKey; |
| lessCondnOperand = (CompiledComparison)cc; |
| lessCondnOp = operator; |
| } |
| } |
| break; |
| } |
| |
| } |
| else if (!_operands[i].isDependentOnCurrentScope(context)) { |
| // TODO: Asif :Remove this Assert & else if condition after successful |
| // testing of the build |
| Support |
| .assertionFailed("An independentoperand should not ever be present as operand inside a GroupJunction as it should always be present only in CompiledJunction"); |
| } |
| else { |
| evalOperands.add(_operands[i]); |
| } |
| } |
| if (!emptyResults) { |
| Filter filter = null; |
| if (equalCondnOperand != null) { |
| // Check if any of the preceding inequality operands, that have not been |
| // checked against the equality operand , are not able to satisfy the |
| // equality. |
| if (lessCondnOperand != null |
| && !this.isConditionSatisfied(equalCondKey, lessCondnKey, |
| lessCondnOp)) { |
| emptyResults = true; |
| } |
| else if (greaterCondnOperand != null |
| && !this.isConditionSatisfied(equalCondKey, greaterCondnKey, |
| greaterCondnOp)) { |
| emptyResults = true; |
| } |
| else if (notEqualTypeKeys != null) { |
| Iterator itr = notEqualTypeKeys.iterator(); |
| while (itr.hasNext() && !emptyResults) { |
| emptyResults = !this.isConditionSatisfied(equalCondKey, itr.next(), |
| OQLLexerTokenTypes.TOK_NE); |
| } |
| } |
| if (!emptyResults) { |
| filter = equalCondnOperand; |
| } |
| } |
| else if (possibleRangeFilter) { |
| if (lessCondnOperand != null && greaterCondnOperand != null) { |
| emptyResults = !checkForRangeBoundednessAndTrimNotEqualKeyset( |
| notEqualTypeKeys, lessCondnKey, lessCondnOp, greaterCondnKey, |
| greaterCondnOp); |
| if (!emptyResults) { |
| filter = new DoubleCondnRangeJunctionEvaluator(lessCondnOp, |
| lessCondnKey, greaterCondnOp, greaterCondnKey, |
| (notEqualTypeKeys == null || notEqualTypeKeys.isEmpty()) ? null |
| : notEqualTypeKeys, indxInfo); |
| } |
| } |
| else if (greaterCondnOperand != null) { |
| filter = generateSingleCondnEvaluatorIfRequired(notEqualTypeKeys, |
| greaterCondnOperand, greaterCondnOp, greaterCondnKey, indxInfo); |
| } |
| else if (lessCondnOperand != null) { |
| filter = generateSingleCondnEvaluatorIfRequired(notEqualTypeKeys, |
| lessCondnOperand, lessCondnOp, lessCondnKey, indxInfo); |
| } |
| else { |
| assert notEqualTypeKeys != null && !notEqualTypeKeys.isEmpty(); |
| // TODO:Asif Ideally if there is a single NotEqualKey we should |
| // not create NotEqualCondnEvaluator instead just add the |
| // CompiledComparison |
| // operand to the eval operands list. But since we do retain the |
| // operand |
| // correponding to the NotEqualKey in this function , we are creating |
| // the NotEqualCondnEvaluator |
| filter = new NotEqualConditionEvaluator(notEqualTypeKeys, indxInfo); |
| } |
| |
| } |
| if (emptyResults) { |
| evalOperands.clear(); |
| evalCount = 1; |
| evalOperands.add(new CompiledLiteral(Boolean.FALSE)); |
| } |
| else if (filter != null) { |
| evalCount++; |
| evalOperands.add(0, filter); |
| } |
| } |
| else { |
| // Asif: Create a new CompiledLiteral with boolean false |
| evalOperands.clear(); |
| evalCount = 1; |
| evalOperands.add(new CompiledLiteral(Boolean.FALSE)); |
| } |
| |
| //If no hints were provided, we continue with our single index solution |
| if (!(context instanceof QueryExecutionContext) || !((QueryExecutionContext)context).hasMultiHints()) { |
| // At the end check if the unevaluatedIterOperand |
| // are null or not. This could be the case only if at top level |
| // GroupJunction is formed having multiple RangeJunctions & other |
| // iter operands & then only one RangeJunction is treated as filter |
| // rest all as iter operands. In that case , the only iter operand is |
| // that which is added externally to RangeJunction. If the top |
| // level was a RangeJunction then the iter operands would have been |
| // part of it at the time of creation of RangeJunction & we would not have |
| // to add it externally. |
| if(getIterOperands() != null) { |
| // Commented the assert for CompiledLike which creates 2 or 3 CompiledComparisons |
| // for the same operand. The protGetPlanInfo in CompiledLike could return evalAsFilter |
| // as true the first time and false the next time for the same operand. |
| // Hence the evalOperands could contain CompiledComparisons more than number of indexes. |
| |
| //Support.Assert(evalOperands.size() == evalCount); |
| evalOperands.add(getIterOperands()); |
| } |
| } |
| return createOrganizedOperandsObject(evalCount, evalOperands); |
| |
| } |
| |
| /** |
| * Checks if key1 operator key2 is true or not. The operator could be =, != , <, >,<=,>= |
| * |
| * @param key1 |
| * @param key2 |
| * @param operator |
| * @return boolean true if the condition is satisfied else false |
| * @throws TypeMismatchException |
| */ |
| private boolean isConditionSatisfied(Object key1, Object key2, int operator) |
| throws TypeMismatchException { |
| return ((Boolean)TypeUtils.compare(key1, key2, operator)).booleanValue(); |
| } |
| |
| /** |
| * Checks if the Range junction containing less & greater type of inequalities |
| * has a lower and upper bound , in the sense that they do not represent a |
| * mutually exclusive condition like a> 10 and a <9 etc. If the condition is |
| * bounded in nature, it further checks if the not equal type keys fall in the |
| * bounded range , else it removes it from the Not Equal Keys set |
| * |
| * @param notEqualKeys |
| * Set containing keys of operands having 'Not Equal' (!=) type |
| * conditions |
| * @param lessCondnKey |
| * Key of the 'Less' condition operand |
| * @param lessOperator |
| * Type of 'less' operator ( < or <=) |
| * @param greaterCondnKey |
| * Key of the 'greater' condition operand |
| * @param greaterCondnOp |
| * Type of 'greater' operator ( > or >=) |
| * @return boolean true if the nature is bounded else false ( unbounded ) |
| * @throws TypeMismatchException |
| */ |
| private boolean checkForRangeBoundednessAndTrimNotEqualKeyset( |
| Set notEqualKeys, Object lessCondnKey, int lessOperator, |
| Object greaterCondnKey, int greaterCondnOp) throws TypeMismatchException { |
| // First check if the range is bounded or (unbounded and mutually |
| // exclusive). |
| // If it is unbounded immediately return a false |
| if (isConditionSatisfied(greaterCondnKey, lessCondnKey, lessOperator) |
| && isConditionSatisfied(lessCondnKey, greaterCondnKey, greaterCondnOp)) { |
| // Nowremove those not equal conditions which do not satisfy the range |
| if (notEqualKeys != null) { |
| Iterator itr = notEqualKeys.iterator(); |
| Object neKey = null; |
| while (itr.hasNext()) { |
| neKey = itr.next(); |
| if (!this |
| .isConditionSatisfied(neKey, greaterCondnKey, greaterCondnOp) |
| || !this.isConditionSatisfied(neKey, lessCondnKey, lessOperator)) { |
| itr.remove(); |
| } |
| } |
| } |
| return true; |
| } |
| else { |
| return false; |
| } |
| } |
| |
| /** |
| * Creates a Filter of type SingleCondnEvaluator if there exists atleast one |
| * key of type "NOT EQUAL" which satisfies the 'less' or 'greater' type |
| * operand. Otherwise the Filter is nothing but the CompiledComparison |
| * representing the 'less' or 'greater' inequality |
| * |
| * @param notEqualKeys |
| * Set containing NotEqual type Keys |
| * @param operand |
| * CompiledValue representing the 'Less' or 'Greater' operand |
| * @param operator |
| * Type of 'Less' or 'Greater' operand |
| * @param condnKey |
| * The Key corresponding to the Operand representing the 'Less' |
| * or 'Greater' inequality |
| * @param indxInfo |
| * The IndexInfo object for this RangeJunction |
| * @return Filter object of type CompiledComparison or |
| * RangeJunction.SingleCondnEvaluator object |
| * @throws TypeMismatchException |
| */ |
| private Filter generateSingleCondnEvaluatorIfRequired(Set notEqualKeys, |
| CompiledValue operand, int operator, Object condnKey, IndexInfo indxInfo) |
| throws TypeMismatchException { |
| Filter rangeFilter; |
| if (notEqualKeys != null) { |
| // Eliminate all the not equal keys which will never be satisfied by |
| // the given greater condn |
| Iterator itr = notEqualKeys.iterator(); |
| while (itr.hasNext()) { |
| Object neKey = itr.next(); |
| if (!((Boolean)TypeUtils.compare(neKey, condnKey, operator)) |
| .booleanValue()) { |
| itr.remove(); |
| } |
| } |
| if (notEqualKeys.isEmpty()) { |
| notEqualKeys = null; |
| } |
| } |
| rangeFilter = (notEqualKeys != null) ? new SingleCondnEvaluator(operator, |
| condnKey, notEqualKeys, indxInfo) : (Filter)operand; |
| return rangeFilter; |
| } |
| |
| public Object evaluate(ExecutionContext context) |
| throws FunctionDomainException, TypeMismatchException, |
| NameResolutionException, QueryInvocationTargetException { |
| Object r = _operands[0].evaluate(context); // UNDEFINED, null, or a |
| // Boolean |
| |
| // if it's false and the op in this case will always be AND so return |
| // false immediately |
| if (r instanceof Boolean && !((Boolean) r).booleanValue()) |
| return r; |
| if (r == null || r == QueryService.UNDEFINED) |
| r = QueryService.UNDEFINED; // keep going to see if we hit a |
| // short-circuiting truth value |
| else if (!(r instanceof Boolean)) |
| throw new TypeMismatchException( |
| "LITERAL_and/LITERAL_or operands must be of type boolean, not type '" |
| + r.getClass().getName() + "'"); |
| for (int i = 1; i < _operands.length; i++) { |
| Object ri = _operands[i].evaluate(context); // UNDEFINED, null, or |
| // Boolean |
| if (ri instanceof Boolean && !((Boolean) ri).booleanValue()) |
| return ri; |
| if (ri == null || ri == QueryService.UNDEFINED |
| || r == QueryService.UNDEFINED) { |
| r = QueryService.UNDEFINED; |
| continue; // keep going to see if we hit a short-circuiting |
| // truth value |
| } else if (!(ri instanceof Boolean)) |
| throw new TypeMismatchException( |
| "LITERAL_and/LITERAL_or operands must be of type boolean, not type '" |
| + ri.getClass().getName() + "'"); |
| // now do the actual and |
| |
| r = new Boolean(((Boolean) r).booleanValue() |
| && ((Boolean) ri).booleanValue()); |
| |
| } |
| return r; |
| } |
| |
| @Override |
| public int getType() { |
| return LITERAL_and; |
| } |
| |
| @Override |
| public void visitNodes(NodeVisitor visitor) { |
| Support.assertionFailed("Should not have come here"); |
| } |
| |
| public int getSizeEstimate(ExecutionContext context) |
| { |
| //TODO:Asif:Try to estimate better |
| return RANGE_SIZE_ESTIMATE; |
| } |
| |
| /* |
| * private organizeOperandsForORJunction() { |
| * } |
| */ |
| /** |
| * Test method which checks if the Filter operand is of type |
| * SingleCondnEvaluator |
| */ |
| static boolean isInstanceOfSingleCondnEvaluator(Object o) { |
| return o instanceof RangeJunction.SingleCondnEvaluator; |
| } |
| |
| /** |
| * Test method which checks if the Filter operand is of type |
| * NotEqualConditionEvaluator |
| */ |
| static boolean isInstanceOfNotEqualConditionEvaluator(Object o) { |
| return o instanceof RangeJunction.NotEqualConditionEvaluator; |
| } |
| |
| /** |
| * Test method which checks if the Filter operand is of type |
| * DoubleCondnRangeJunctionEvaluator |
| */ |
| static boolean isInstanceOfDoubleCondnRangeJunctionEvaluator(Object o) { |
| return o instanceof RangeJunction.DoubleCondnRangeJunctionEvaluator; |
| } |
| |
| /** |
| * Test function which retrieves the "NOT EQUAL KEYS" |
| * |
| * @param o |
| * Object of type NotEqualConditionEvaluator from which the set |
| * containing the keys for removal need to be retrieved |
| * @return Unmodifiable Set containing the keys for removal |
| */ |
| static Set getKeysToBeRemoved(Object o) { |
| if (o instanceof NotEqualConditionEvaluator) { |
| if (((NotEqualConditionEvaluator)o).notEqualTypeKeys == null) { |
| return null; |
| } |
| return Collections |
| .unmodifiableSet(((NotEqualConditionEvaluator)o).notEqualTypeKeys); |
| } |
| else { |
| throw new IllegalStateException( |
| LocalizedStrings. |
| RangeJunction_THE_OBJECT_IS_NOT_OF_TYPE_NOTEQUALCONDITIONEVALUATOR |
| .toLocalizedString()); |
| } |
| } |
| |
| /** |
| * Test function which retrieves the SingleCondnEvaluator operator |
| * |
| * @param o |
| * Object of type SingleCondnEvaluator from which the set |
| * containing the keys for removal need to be retrieved |
| * @return int indicating the operator |
| */ |
| static int getSingleCondnEvaluatorOperator(Object o) { |
| if (o instanceof SingleCondnEvaluator) { |
| return ((SingleCondnEvaluator)o).condnOp; |
| } |
| else { |
| throw new IllegalStateException( |
| LocalizedStrings. |
| RangeJunction_THE_OBJECT_IS_NOT_OF_TYPE_NOTEQUALCONDITIONEVALUATOR |
| .toLocalizedString()); |
| } |
| } |
| |
| /** |
| * Test function which retrieves the evaluated Key for a SingleCondnEvaluator |
| * operator |
| * |
| * @param o |
| * Object of type SingleCondnEvaluator from which the set |
| * containing the keys for removal need to be retrieved |
| * @return Object representing the evaluated Key |
| */ |
| static Object getSingleCondnEvaluatorKey(Object o) { |
| if (o instanceof SingleCondnEvaluator) { |
| return ((SingleCondnEvaluator)o).condnKey; |
| } |
| else { |
| throw new IllegalStateException( |
| LocalizedStrings. |
| RangeJunction_THE_OBJECT_IS_NOT_OF_TYPE_NOTEQUALCONDITIONEVALUATOR |
| .toLocalizedString()); |
| } |
| } |
| |
| /** |
| * Test function which retrieves the LESS type evaluated Key for a |
| * DoubleCondnEvaluator operator |
| * |
| * @param o |
| * Object of type DoubleCondnEvaluator |
| * @return Object representing the evaluated Key of Less Type |
| */ |
| static Object getDoubleCondnEvaluatorLESSKey(Object o) { |
| if (o instanceof DoubleCondnRangeJunctionEvaluator) { |
| return ((DoubleCondnRangeJunctionEvaluator)o).lessCondnKey; |
| } |
| else { |
| throw new IllegalStateException( |
| LocalizedStrings. |
| RangeJunction_THE_OBJECT_IS_NOT_OF_TYPE_NOTEQUALCONDITIONEVALUATOR |
| .toLocalizedString()); |
| } |
| } |
| |
| /** |
| * Test function which retrieves the GREATER type evaluated Key for a |
| * DoubleCondnEvaluator operator |
| * |
| * @param o |
| * Object of type DoubleCondnEvaluator |
| * @return Object representing the evaluated Key of GREATER Type |
| */ |
| static Object getDoubleCondnEvaluatorGreaterKey(Object o) { |
| if (o instanceof DoubleCondnRangeJunctionEvaluator) { |
| return ((DoubleCondnRangeJunctionEvaluator)o).greaterCondnKey; |
| } |
| else { |
| throw new IllegalStateException( |
| LocalizedStrings. |
| RangeJunction_THE_OBJECT_IS_NOT_OF_TYPE_NOTEQUALCONDITIONEVALUATOR |
| .toLocalizedString()); |
| } |
| } |
| |
| /** |
| * Test function which retrieves the operator of Less Type |
| * |
| * @param o |
| * Object of type DoubleCondnEvaluator |
| * @return int indicating the operator of less Type |
| */ |
| static int getDoubleCondnEvaluatorOperatorOfLessType(Object o) { |
| if (o instanceof DoubleCondnRangeJunctionEvaluator) { |
| return ((DoubleCondnRangeJunctionEvaluator)o).lessCondnOp; |
| } |
| else { |
| throw new IllegalStateException( |
| LocalizedStrings. |
| RangeJunction_THE_OBJECT_IS_NOT_OF_TYPE_NOTEQUALCONDITIONEVALUATOR |
| .toLocalizedString()); |
| } |
| } |
| |
| /** |
| * Test function which retrieves the operator of GREATER Type |
| * |
| * @param o |
| * Object of type DoubleCondnEvaluator |
| * @return int indicating the operator of less Type |
| */ |
| static int getDoubleCondnEvaluatorOperatorOfGreaterType(Object o) { |
| if (o instanceof DoubleCondnRangeJunctionEvaluator) { |
| return ((DoubleCondnRangeJunctionEvaluator)o).greaterCondnOp; |
| } |
| else { |
| throw new IllegalStateException( |
| LocalizedStrings. |
| RangeJunction_THE_OBJECT_IS_NOT_OF_TYPE_NOTEQUALCONDITIONEVALUATOR |
| .toLocalizedString()); |
| } |
| } |
| |
| /** |
| * Test function which retrieves the underlying Index for a |
| * NotEqualConditionEvaluator operator |
| * |
| * @param o |
| * Object of type NotEqualConditionEvaluator from which the |
| * index needs to be retrieved |
| * @return Index |
| */ |
| static Index getIndex(Object o) { |
| if (o instanceof NotEqualConditionEvaluator) { |
| return ((NotEqualConditionEvaluator)o).indxInfo._index; |
| } |
| else { |
| throw new IllegalStateException( |
| LocalizedStrings. |
| RangeJunction_THE_OBJECT_IS_NOT_OF_TYPE_NOTEQUALCONDITIONEVALUATOR |
| .toLocalizedString()); |
| } |
| } |
| |
| /** |
| * Filter Object created by the RangeJunction on invocation of its |
| * organizedOperands method. The object of this class will be created only if |
| * RangeJunction contains more than one 'NOT EQUAL' ( != ) type conditions ( |
| * apart from conditions having null or undefined as key). This class is also |
| * extended by SingleCondnEvaluator and DoubleCondnRangeJunctionEvaluator |
| * |
| * @author asif |
| * |
| */ |
| private static class NotEqualConditionEvaluator extends AbstractCompiledValue |
| implements Filter { |
| final Set notEqualTypeKeys; |
| |
| final IndexInfo indxInfo; |
| |
| /** |
| * |
| * @param notEqualTypeKeys |
| * java.utils.Set object containing the Keys of the 'NOT |
| * EQUAL' type conditions ( a != 3 and a !=5) For |
| * DoubleCondnRangeJunctionEvaluator , this may be null |
| * @param indxInfo |
| * The IndexInfo object corresponding to the RangeJunction |
| */ |
| NotEqualConditionEvaluator(Set notEqualTypeKeys, IndexInfo indxInfo) { |
| this.notEqualTypeKeys = notEqualTypeKeys; |
| this.indxInfo = indxInfo; |
| } |
| |
| @Override |
| public SelectResults filterEvaluate(ExecutionContext context, |
| SelectResults iterationLimit) throws FunctionDomainException, |
| TypeMismatchException, NameResolutionException, |
| QueryInvocationTargetException { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public SelectResults filterEvaluate(ExecutionContext context, |
| SelectResults iterationLimit, boolean completeExpansionNeeded, |
| CompiledValue iterOperands, RuntimeIterator[] indpndntItrs, boolean isIntersection,boolean conditioningNeeded, boolean evalProj) |
| throws FunctionDomainException, TypeMismatchException, |
| NameResolutionException, QueryInvocationTargetException { |
| ObjectType resultType = this.indxInfo._index.getResultSetType(); |
| int indexFieldsSize = -1; |
| SelectResults set = null; |
| Boolean orderByClause = (Boolean)context.cacheGet(CompiledValue.CAN_APPLY_ORDER_BY_AT_INDEX); |
| boolean useLinkedSet = false; |
| if(orderByClause != null && orderByClause.booleanValue()) { |
| List orderByAttrs = (List)context.cacheGet(CompiledValue.ORDERBY_ATTRIB); |
| useLinkedSet =orderByAttrs.size()==1; |
| } |
| |
| if (resultType instanceof StructType) { |
| if (context.getCache().getLogger().fineEnabled()) { |
| context.getCache().getLogger().fine( |
| "StructType resultType.class=" + resultType.getClass().getName()); |
| } |
| if (useLinkedSet) { |
| set = new LinkedStructSet((StructTypeImpl)resultType) ; |
| } else { |
| set = (SelectResults)new StructBag((StructTypeImpl)resultType, |
| context.getCachePerfStats()); |
| } |
| indexFieldsSize = ((StructTypeImpl)resultType).getFieldNames().length; |
| } |
| else { |
| if (context.getCache().getLogger().fineEnabled()) { |
| context.getCache().getLogger().fine( |
| "non-StructType resultType.class=" |
| + resultType.getClass().getName()); |
| } |
| if (useLinkedSet) { |
| set = new LinkedResultSet(resultType); |
| } else { |
| set = new ResultsBag(resultType, context.getCachePerfStats()); |
| } |
| indexFieldsSize = 1; |
| } |
| // actual index lookup |
| QueryObserver observer = QueryObserverHolder.getInstance(); |
| /* |
| * Asif : First obtain the match level of index resultset. If the match |
| * level happens to be zero , this implies that we just have to change the |
| * StructType ( again if only the Index resultset is a StructBag). If the |
| * match level is zero & expand to to top level flag is true & iff the |
| * total no. of iterators in current scope is greater than the no. of |
| * fields in StructBag , then only we need to do any expansion. |
| * |
| */ |
| try { |
| observer.beforeIndexLookup(this.indxInfo._index, |
| OQLLexerTokenTypes.TOK_NE, this.notEqualTypeKeys); |
| context.cachePut(CompiledValue.INDEX_INFO, this.indxInfo); |
| this.indxInfo._index.query(set, notEqualTypeKeys, context); |
| } |
| finally { |
| observer.afterIndexLookup(set); |
| } |
| return QueryUtils.getconditionedIndexResults(set, this.indxInfo, context, |
| indexFieldsSize, completeExpansionNeeded, iterOperands, indpndntItrs); |
| } |
| |
| @Override |
| public SelectResults auxFilterEvaluate(ExecutionContext context, |
| SelectResults intermediateResults) throws FunctionDomainException, |
| TypeMismatchException, NameResolutionException, |
| QueryInvocationTargetException { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public Object evaluate(ExecutionContext context) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException { |
| Object evaluatedPath = this.indxInfo._path.evaluate(context); |
| return evaluate(context,evaluatedPath); |
| } |
| |
| public boolean isConditioningNeededForIndex(RuntimeIterator independentIter, ExecutionContext context, boolean completeExpnsNeeded) throws AmbiguousNameException, TypeMismatchException, NameResolutionException { |
| return true; |
| } |
| |
| public Object evaluate(ExecutionContext context, Object evaluatedPath) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException { |
| Iterator itr = this.notEqualTypeKeys.iterator(); |
| while(itr.hasNext()) { |
| Object val = itr.next(); |
| Object result = TypeUtils.compare(evaluatedPath, val, TOK_NE); |
| if( result instanceof Boolean) { |
| if( !((Boolean)result).booleanValue()) { |
| return Boolean.FALSE; |
| } |
| }else { |
| throw new TypeMismatchException("NotEqualConditionEvaluator should evaluate to boolean type"); |
| } |
| } |
| return Boolean.TRUE; |
| |
| } |
| |
| public int getType() { |
| return NOTEQUALCONDITIONEVALUATOR; |
| } |
| public int getSizeEstimate(ExecutionContext context) { |
| return RANGE_SIZE_ESTIMATE; |
| } |
| @Override |
| public void visitNodes(NodeVisitor visitor) { |
| Support.assertionFailed("Should not have come here"); |
| } |
| |
| public int getOperator() |
| { |
| return LITERAL_and; |
| } |
| |
| public boolean isBetterFilter(Filter comparedTo, ExecutionContext context, int thisSize) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException |
| { |
| //If the current filter is equality & comparedTo filter is also equality based , then |
| // return the one with lower size estimate is better |
| boolean isThisBetter = true; |
| |
| int thatOperator = comparedTo.getOperator() ; |
| |
| //Go with the lowest cost when hint is used. |
| if (context instanceof QueryExecutionContext && ((QueryExecutionContext)context).hasHints()) { |
| return thisSize <= comparedTo.getSizeEstimate(context); |
| } |
| |
| switch(thatOperator) { |
| case TOK_EQ: |
| isThisBetter = false; |
| break; |
| case TOK_NE: |
| case TOK_NE_ALT: |
| //Give preference to Range |
| break; |
| default : |
| throw new IllegalArgumentException("The operator type ="+ thatOperator + " is unknown"); |
| } |
| |
| return isThisBetter; |
| } |
| |
| } |
| |
| /** |
| * Filter object of this type gets created if there exists atleast one "NOT |
| * EQUAL" type condition and a single condition containing an inequality of |
| * type 'Less' or 'Greater'. The Where clause may actually contain multiple |
| * 'Less' type inequality or multiple 'Greater' type inequality ( though not |
| * both 'Less' and 'Greater' together). The RangeJunction will identify the |
| * most specific inequality for the AND junction. Thus if something like a > 7 |
| * and a >=6 , will be sufficiently represented by a > 7 |
| * |
| * @author asif |
| * |
| */ |
| private static class SingleCondnEvaluator extends NotEqualConditionEvaluator { |
| protected int condnOp = -1; |
| |
| protected final Object condnKey; |
| |
| @Override |
| public SelectResults filterEvaluate(ExecutionContext context, |
| SelectResults iterationLimit) throws FunctionDomainException, |
| TypeMismatchException, NameResolutionException, |
| QueryInvocationTargetException { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * |
| * @param operator |
| * integer identifying the type of 'Less' or 'Greater' |
| * inequality |
| * @param key |
| * Object representing the Key for the inequality |
| * @param notEqualKeys |
| * Set containing the 'NOT EQUAL' Keys accompanying the |
| * 'Less' or 'Greater' inequality |
| * @param indxInfo |
| * The IndexInfo object corresponding to the RangeJunction |
| */ |
| SingleCondnEvaluator(int operator, Object key, Set notEqualKeys, |
| IndexInfo indxInfo) { |
| super(notEqualKeys, indxInfo); |
| this.condnOp = operator; |
| this.condnKey = key; |
| } |
| |
| @Override |
| public SelectResults filterEvaluate(ExecutionContext context, |
| SelectResults iterationLimit, boolean completeExpansionNeeded, |
| CompiledValue iterOperands, RuntimeIterator[] indpndntItrs, |
| boolean isIntersection,boolean conditioningNeeded, boolean evalProj) |
| throws FunctionDomainException, TypeMismatchException, |
| NameResolutionException, QueryInvocationTargetException { |
| ObjectType resultType = this.indxInfo._index.getResultSetType(); |
| int indexFieldsSize = -1; |
| SelectResults set = null; |
| Boolean orderByClause = (Boolean)context.cacheGet(CompiledValue.CAN_APPLY_ORDER_BY_AT_INDEX); |
| boolean useLinkedSet = false; |
| if(orderByClause != null && orderByClause.booleanValue()) { |
| List orderByAttrs = (List)context.cacheGet(CompiledValue.ORDERBY_ATTRIB); |
| useLinkedSet =orderByAttrs.size()==1; |
| } |
| if (resultType instanceof StructType) { |
| if (context.getCache().getLogger().fineEnabled()) { |
| context.getCache().getLogger().fine( |
| "StructType resultType.class=" + resultType.getClass().getName()); |
| } |
| if (useLinkedSet) { |
| set = new LinkedStructSet((StructTypeImpl)resultType); |
| } else { |
| set = (SelectResults)new StructBag((StructTypeImpl)resultType, |
| context.getCachePerfStats()); |
| } |
| indexFieldsSize = ((StructTypeImpl)resultType).getFieldNames().length; |
| } |
| else { |
| if (context.getCache().getLogger().fineEnabled()) { |
| context.getCache().getLogger().fine( |
| "non-StructType resultType.class=" |
| + resultType.getClass().getName()); |
| } |
| if (useLinkedSet) { |
| set = new LinkedResultSet(resultType); |
| } else { |
| set = new ResultsBag(resultType, context.getCachePerfStats()); |
| } |
| indexFieldsSize = 1; |
| } |
| // actual index lookup |
| QueryObserver observer = QueryObserverHolder.getInstance(); |
| /* |
| * Asif : First obtain the match level of index resultset. If the match |
| * level happens to be zero , this implies that we just have to change the |
| * StructType ( again if only the Index resultset is a StructBag). If the |
| * match level is zero & expand to to top level flag is true & iff the |
| * total no. of iterators in current scope is greater than the no. of |
| * fields in StructBag , then only we need to do any expansion. |
| * |
| */ |
| try { |
| observer.beforeIndexLookup(this.indxInfo._index, this.condnOp, |
| this.condnKey); |
| context.cachePut(CompiledValue.INDEX_INFO, this.indxInfo); |
| this.indxInfo._index.query(this.condnKey, this.condnOp, set, |
| notEqualTypeKeys, context); |
| } |
| finally { |
| observer.afterIndexLookup(set); |
| } |
| return QueryUtils.getconditionedIndexResults(set, this.indxInfo, context, |
| indexFieldsSize, completeExpansionNeeded, iterOperands, indpndntItrs); |
| |
| } |
| |
| public Object evaluate(ExecutionContext context) throws TypeMismatchException, FunctionDomainException, NameResolutionException, QueryInvocationTargetException { |
| Object evaluatedPath = this.indxInfo._path.evaluate(context); |
| Boolean result =(Boolean) super.evaluate(context,evaluatedPath); |
| if( result.booleanValue()) { |
| result = (Boolean)TypeUtils.compare(evaluatedPath, this.condnKey, this.condnOp); |
| } |
| return result; |
| } |
| |
| @Override |
| public int getType() { |
| return SINGLECONDNEVALUATOR; |
| } |
| |
| @Override |
| public void visitNodes(NodeVisitor visitor) { |
| Support.assertionFailed("Should not have come here"); |
| } |
| |
| @Override |
| public SelectResults auxFilterEvaluate(ExecutionContext context, |
| SelectResults intermediateResults) throws FunctionDomainException, |
| TypeMismatchException, NameResolutionException, |
| QueryInvocationTargetException { |
| throw new UnsupportedOperationException(); |
| } |
| } |
| |
| /** |
| * Filter object of this type gets created if there exists a bounded condition |
| * like a >7 and a > 8 and a< 10 and a <11. The RangeJunction will identify |
| * the most specific inequality of each type for the AND junction. Thus the |
| * conditions a > 8 and a <10 will be used to form the Object of this class. |
| * For this evaluator only, the notEqualTypeKeys present in its super class |
| * may be null ( if there is no 'NOT EQUAL' type condition satisfying the |
| * bounded condition) |
| * |
| * @author ashahid |
| * |
| */ |
| private static class DoubleCondnRangeJunctionEvaluator extends |
| NotEqualConditionEvaluator { |
| protected final int lessCondnOp; |
| |
| protected final int greaterCondnOp; |
| |
| protected final Object lessCondnKey; |
| |
| protected final Object greaterCondnKey; |
| |
| /** |
| * |
| * @param lessCondnOp |
| * integer identifying the upper bound ( < or <= ) |
| * @param lessCondnKey |
| * Object representing the Upper Bound Key |
| * @param greaterCondnOp |
| * integer identifying the lower bound ( > or >= ) |
| * @param greaterCondnKey |
| * Object representing the lower Bound Key |
| * @param notEqualTypeKeys |
| * Set containing the 'NOT EQUAL' Keys accompanying the |
| * 'Less' or 'Greater' inequality |
| * @param indexInfo |
| * The IndexInfo object corresponding to the RangeJunction |
| */ |
| DoubleCondnRangeJunctionEvaluator(int lessCondnOp, Object lessCondnKey, |
| int greaterCondnOp, Object greaterCondnKey, Set notEqualTypeKeys, |
| IndexInfo indexInfo) { |
| super(notEqualTypeKeys, indexInfo); |
| this.lessCondnOp = lessCondnOp; |
| this.lessCondnKey = lessCondnKey; |
| this.greaterCondnOp = greaterCondnOp; |
| this.greaterCondnKey = greaterCondnKey; |
| } |
| |
| @Override |
| public SelectResults filterEvaluate(ExecutionContext context, |
| SelectResults iterationLimit) throws FunctionDomainException, |
| TypeMismatchException, NameResolutionException, |
| QueryInvocationTargetException { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public SelectResults filterEvaluate(ExecutionContext context, |
| SelectResults iterationLimit, boolean completeExpansionNeeded, |
| CompiledValue iterOperands, RuntimeIterator[] indpndntItrs, |
| boolean isIntersection,boolean conditioningNeeded, boolean evalProj) |
| throws FunctionDomainException, TypeMismatchException, |
| NameResolutionException, QueryInvocationTargetException { |
| ObjectType resultType = this.indxInfo._index.getResultSetType(); |
| int indexFieldsSize = -1; |
| SelectResults set = null; |
| Boolean orderByClause = (Boolean)context.cacheGet(CompiledValue.CAN_APPLY_ORDER_BY_AT_INDEX); |
| boolean useLinkedSet = false; |
| if(orderByClause != null && orderByClause.booleanValue()) { |
| List orderByAttrs = (List)context.cacheGet(CompiledValue.ORDERBY_ATTRIB); |
| useLinkedSet =orderByAttrs.size()==1; |
| } |
| |
| if (resultType instanceof StructType) { |
| if (context.getCache().getLogger().fineEnabled()) { |
| context.getCache().getLogger().fine( |
| "StructType resultType.class=" + resultType.getClass().getName()); |
| } |
| if(useLinkedSet) { |
| set = new LinkedStructSet((StructTypeImpl)resultType); |
| }else { |
| set = new StructBag((StructTypeImpl)resultType, |
| context.getCachePerfStats()); |
| } |
| indexFieldsSize = ((StructTypeImpl)resultType).getFieldNames().length; |
| } |
| else { |
| if (context.getCache().getLogger().fineEnabled()) { |
| context.getCache().getLogger().fine( |
| "non-StructType resultType.class=" |
| + resultType.getClass().getName()); |
| } |
| if (useLinkedSet) { |
| set = new LinkedResultSet(resultType); |
| } else { |
| set = new ResultsBag(resultType, context.getCachePerfStats()); |
| } |
| indexFieldsSize = 1; |
| } |
| // actual index lookup |
| // Shobhit: Limit can not be applied at index level for RangeJunction as |
| // other conditions are applied after coming out of index query method. |
| context.cachePut(CompiledValue.CAN_APPLY_LIMIT_AT_INDEX, Boolean.FALSE); |
| QueryObserver observer = QueryObserverHolder.getInstance(); |
| /* |
| * Asif : First obtain the match level of index resultset. If the match |
| * level happens to be zero , this implies that we just have to change the |
| * StructType ( again if only the Index resultset is a StructBag). If the |
| * match level is zero & expand to to top level flag is true & iff the |
| * total no. of iterators in current scope is greater than the no. of |
| * fields in StructBag , then only we need to do any expansion. |
| * |
| */ |
| try { |
| observer.beforeIndexLookup(this.indxInfo._index, this.greaterCondnOp, |
| this.greaterCondnKey, this.lessCondnOp, this.lessCondnKey, |
| this.notEqualTypeKeys); |
| context.cachePut(CompiledValue.INDEX_INFO, this.indxInfo); |
| this.indxInfo._index.query(this.greaterCondnKey, this.greaterCondnOp, |
| this.lessCondnKey, this.lessCondnOp, set, notEqualTypeKeys, context); |
| } |
| finally { |
| observer.afterIndexLookup(set); |
| } |
| return QueryUtils.getconditionedIndexResults(set, this.indxInfo, context, |
| indexFieldsSize, completeExpansionNeeded, iterOperands, indpndntItrs); |
| |
| } |
| |
| @Override |
| public SelectResults auxFilterEvaluate(ExecutionContext context, |
| SelectResults intermediateResults) throws FunctionDomainException, |
| TypeMismatchException, NameResolutionException, |
| QueryInvocationTargetException { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public Object evaluate(ExecutionContext context) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException { |
| Object evaluatedPath = this.indxInfo._path.evaluate(context); |
| Boolean result =(Boolean) super.evaluate(context,evaluatedPath); |
| if( result.booleanValue()) { |
| result = (Boolean)TypeUtils.compare(evaluatedPath, this.lessCondnKey, this.lessCondnOp); |
| result = result.booleanValue() ? (Boolean)TypeUtils.compare(evaluatedPath, this.greaterCondnKey, this.greaterCondnOp):Boolean.FALSE; |
| } |
| return result; |
| } |
| |
| @Override |
| public int getType() { |
| return DOUBLECONDNRANGEJUNCTIONEVALUATOR; |
| } |
| |
| @Override |
| public void visitNodes(NodeVisitor visitor) { |
| Support.assertionFailed("Should not have come here"); |
| } |
| } |
| } |