All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gemstone.gemfire.cache.query.internal.CompiledUndefined Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License. You
 * may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License. See accompanying
 * LICENSE file.
 */
package com.gemstone.gemfire.cache.query.internal;

import java.util.*;
import com.gemstone.gemfire.cache.query.*;
import com.gemstone.gemfire.cache.query.internal.IndexInfo;
import com.gemstone.gemfire.cache.query.internal.index.IndexData;
import com.gemstone.gemfire.cache.query.internal.index.IndexProtocol;
import com.gemstone.gemfire.cache.query.internal.index.IndexUtils;
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;

/**
 * Predefined function for identity of the UNDEFINED literal
 * 
 * @version $Revision: 1.2 $
 * @author ericz
 * @author asif
 */
public class CompiledUndefined extends AbstractCompiledValue implements
    Negatable , Indexable {

  private CompiledValue _value;
  private boolean _is_defined;

  public CompiledUndefined(CompiledValue value, boolean is_defined) {
    _value = value;
    _is_defined = is_defined;
  }

  @Override
  public List getChildren() {
    return Collections.singletonList(this._value);
  }
  
  public int getType() {
    return FUNCTION;
  }

  public Object evaluate(ExecutionContext context)
      throws FunctionDomainException, TypeMismatchException,
      NameResolutionException, QueryInvocationTargetException {
    boolean b = _value.evaluate(context) == QueryService.UNDEFINED;
    return Boolean.valueOf(_is_defined ? !b : b);
  }

  /**
   * Asif : Evaluates as a filter taking advantage of indexes if appropriate.
   * This function has a meaningful implementation only in CompiledComparison &
   * CompiledUndefined . It is unsupported in other classes. The additional
   * parameters which it takes are a boolean which is used to indicate whether
   * the index result set needs to be expanded to the top level or not. The
   * second is a CompiledValue representing the operands which are only iter
   * evaluatable. The CompiledValue passed will be null except if a
   * GroupJunction has only one filter evaluatable condition & rest are iter
   * operands. In such cases , the iter operands will be evaluated while
   * expanding/cutting down the index resultset
   * 
   * @return SelectResults
   */
  @Override
  public SelectResults filterEvaluate(ExecutionContext context,
      SelectResults intermediateResults, boolean completeExpansionNeeded,
      CompiledValue iterOperands, RuntimeIterator[] indpndntItrs, boolean isIntersection, boolean conditioningNeeded, boolean evaluateProjAttrib)
      throws FunctionDomainException, TypeMismatchException,
      NameResolutionException, QueryInvocationTargetException {
    //  this method is called if we are independent of the iterator,
    // or if we can use an index.
    // if we are independent, then we should not have been here in the first
    // place
    Support
        .Assert(
            this._value.isDependentOnCurrentScope(context),
            "For a condition which does not depend on any RuntimeIterator of current scope , we should not have been in this function");
    IndexInfo idxInfo[] = getIndexInfo(context);
    ObjectType resultType = idxInfo[0]._index.getResultSetType();
    int indexFieldsSize = -1;
    SelectResults set = null;
    if (resultType instanceof StructType) {
      set = (SelectResults) new StructBag((StructTypeImpl)resultType,
                                          context.getCachePerfStats());
      indexFieldsSize = ((StructTypeImpl) resultType).getFieldNames().length;
    }
    else {
      set = new ResultsBag(resultType, context.getCachePerfStats());
      indexFieldsSize = 1;
    }
    int op = _is_defined ? TOK_NE : TOK_EQ;
    Object key = QueryService.UNDEFINED;
    QueryObserver observer = QueryObserverHolder.getInstance();
    try {
      observer.beforeIndexLookup(idxInfo[0]._index, op, key);
      context.cachePut(CompiledValue.INDEX_INFO, idxInfo[0]);
      idxInfo[0]._index.query(key, op, set,context);
    }
    finally {
      observer.afterIndexLookup(set);
    }
    return QueryUtils.getconditionedIndexResults(set, idxInfo[0], context,
        indexFieldsSize, completeExpansionNeeded, iterOperands, indpndntItrs);
  }

  public int getSizeEstimate(ExecutionContext context)
      throws FunctionDomainException, TypeMismatchException,
      NameResolutionException, QueryInvocationTargetException
  {
    IndexInfo[] idxInfo = getIndexInfo(context);
    assert idxInfo.length == 1;
    int op = _is_defined ? TOK_NE : TOK_EQ;
    return idxInfo[0]._index.getSizeEstimate(QueryService.UNDEFINED, op,
        idxInfo[0]._matchLevel);
  }
  
  public int getOperator() {
    return _is_defined ? TOK_NE : TOK_EQ;
  }

  /**
   * evaluate as a filter, producing an intermediate result set. This may
   * require iteration if there is no index available. Asif :The boolean true
   * implies that CompiledComparsion when existing on its own always requires a
   * Complete expansion to top level iterators. This flag can get toggled to
   * false only from inside a GroupJunction
   * 
   * 

param intermediateResults if this parameter is provided, and we have to * iterate, then iterate over this result set instead of the entire * base collection. */ @Override public SelectResults filterEvaluate(ExecutionContext context, SelectResults iterationLimit) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException { return filterEvaluate(context, iterationLimit, true/* Complete Expansion needed */, null, null, true,isConditioningNeededForIndex(null, context, true), false); } /* * Asif : This function should never get invoked as now if a CompiledJunction * or GroupJunction contains a single filterable CompiledUndefined, it should * directly call filterEvaluate rather than auxFilterEvalutae. Overriding this * function just for ensuring that auxFilterEvaluate is not being called by * mistake. */ @Override public SelectResults auxFilterEvaluate(ExecutionContext context, SelectResults intermediateResults) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException { Support .assertionFailed(" This auxFilterEvaluate of CompiledComparison should never have got invoked."); return null; } @Override public Set computeDependencies(ExecutionContext context) throws TypeMismatchException, AmbiguousNameException, NameResolutionException { return context.addDependencies(this, this._value .computeDependencies(context)); } public void negate() { _is_defined = !_is_defined; } // Invariant: the receiver is dependent on the current iterator. @Override protected PlanInfo protGetPlanInfo(ExecutionContext context) throws TypeMismatchException, AmbiguousNameException, NameResolutionException { PlanInfo result = new PlanInfo(); IndexInfo[] indexInfo = getIndexInfo(context); if (indexInfo == null) return result; Support .Assert( indexInfo.length == 1, "For a CompiledUndefined we cannot have a join of two indexes. There should be only a single index to use"); result.indexes.add(indexInfo[0]._index); result.evalAsFilter = true; return result; } public IndexInfo[] getIndexInfo(ExecutionContext context) throws TypeMismatchException, AmbiguousNameException, NameResolutionException { IndexInfo[] indexInfo = privGetIndexInfo(context); if (indexInfo != null) { if (indexInfo == NO_INDEXES_IDENTIFIER) { return null; } else { return indexInfo; } } if (!IndexUtils.indexesEnabled) return null; //TODO:Asif : Check if the condition is such that Primary Key Index is used // & its key is DEFINED //, then are we returning all the values of the region ? // & that if the key is UNDEFINED are we returning an empty set.? IndexData indexData = QueryUtils.getAvailableIndexIfAny(this._value, context, _is_defined ? TOK_NE : TOK_EQ); IndexProtocol index = null; IndexInfo[] newIndexInfo = null; if (indexData != null) { index = indexData.getIndex(); } if (index != null && index.isValid()) { newIndexInfo = new IndexInfo[1]; /* Pass the Key as null as the key is not of type CompiledValue( but of type QueryService.UNDEFINED)*/ newIndexInfo[0] = new IndexInfo(null, this._value, index, indexData.getMatchLevel(), indexData.getMapping(), _is_defined ? TOK_NE : TOK_EQ); } if (newIndexInfo != null) { privSetIndexInfo(newIndexInfo, context); } else { privSetIndexInfo(NO_INDEXES_IDENTIFIER, context); } return newIndexInfo; } @Override public void generateCanonicalizedExpression(StringBuffer clauseBuffer, ExecutionContext context) throws AmbiguousNameException, TypeMismatchException, NameResolutionException { clauseBuffer.insert(0, ')'); _value.generateCanonicalizedExpression(clauseBuffer, context); if (_is_defined) clauseBuffer.insert(0, "IS_DEFINED("); else clauseBuffer.insert(0, "IS_UNDEFINED("); } //_indexInfo is a transient field // if this is just faulted in then can be null private IndexInfo[] privGetIndexInfo(ExecutionContext context) { return (IndexInfo[]) context.cacheGet(this); } private void privSetIndexInfo(IndexInfo[] indexInfo, ExecutionContext context) { context.cachePut(this, indexInfo); } public boolean isRangeEvaluatable() { return false; } public boolean isProjectionEvaluationAPossibility(ExecutionContext context) { return true; } //TODO:Asif: This should ideally be treated like CompiledComparison in terms evaluation of // iter operands etc public boolean isConditioningNeededForIndex(RuntimeIterator independentIter, ExecutionContext context, boolean completeExpnsNeeded) throws AmbiguousNameException, TypeMismatchException, NameResolutionException { return true; } 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 thisOperator = this.getOperator(); int thatSize = comparedTo.getSizeEstimate(context); int thatOperator = comparedTo.getOperator() ; switch(thatOperator) { case TOK_EQ: case TOK_NE: case TOK_NE_ALT: isThisBetter = thisSize <= thatSize; break; case LITERAL_and: //This is possible only in case of RangeJunction if(thisOperator== TOK_NE || thisOperator == TOK_NE_ALT ) { //Asif: Give preference to range as I am assuming that range will fetch less data // as compared to NOT EQUALs isThisBetter = false; } break; case TOK_LE: case TOK_LT: case TOK_GE: case TOK_GT: //Give preference to this rather than that as this is more deterministic break; default : throw new IllegalArgumentException("The operator type ="+ thatOperator + " is unknown"); } return isThisBetter; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy