private IndexSearchDescriptor buildIndexSearchDescriptor(OCommandContext ctx, OIndex<?> index, OAndBlock block, OClass clazz) {
    List<String> indexFields = index.getDefinition().getFields();
    OBinaryCondition keyCondition = new OBinaryCondition(-1);
    OIdentifier key = new OIdentifier("key");
    keyCondition.setLeft(new OExpression(key));
    boolean allowsRange = allowsRangeQueries(index);
    boolean found = false;

    OAndBlock blockCopy = block.copy();
    Iterator<OBooleanExpression> blockIterator;

    OAndBlock indexKeyValue = new OAndBlock(-1);
    IndexSearchDescriptor result = new IndexSearchDescriptor();
    result.idx = index;
    result.keyCondition = indexKeyValue;
    for (String indexField : indexFields) {
      blockIterator = blockCopy.getSubBlocks().iterator();
      boolean breakHere = false;
      boolean indexFieldFound = false;
      while (blockIterator.hasNext()) {
        OBooleanExpression singleExp = blockIterator.next();
        if (singleExp instanceof OBinaryCondition) {
          OExpression left = ((OBinaryCondition) singleExp).getLeft();
          if (left.isBaseIdentifier()) {
            String fieldName = left.getDefaultAlias().getStringValue();
            if (indexField.equals(fieldName)) {
              OBinaryCompareOperator operator = ((OBinaryCondition) singleExp).getOperator();
              if (!((OBinaryCondition) singleExp).getRight().isEarlyCalculated(ctx)) {
                continue; //this cannot be used because the value depends on single record
              }
              if (operator instanceof OEqualsCompareOperator) {
                found = true;
                indexFieldFound = true;
                OBinaryCondition condition = new OBinaryCondition(-1);
                condition.setLeft(left);
                condition.setOperator(operator);
                condition.setRight(((OBinaryCondition) singleExp).getRight().copy());
                indexKeyValue.getSubBlocks().add(condition);
                blockIterator.remove();
                break;
              } else if (operator instanceof OContainsKeyOperator && isMap(clazz, indexField) && isIndexByKey(index, indexField)) {
                found = true;
                indexFieldFound = true;
                OBinaryCondition condition = new OBinaryCondition(-1);
                condition.setLeft(left);
                condition.setOperator(operator);
                condition.setRight(((OBinaryCondition) singleExp).getRight().copy());
                indexKeyValue.getSubBlocks().add(condition);
                blockIterator.remove();
                break;
              } else if (allowsRange && operator.isRangeOperator()) {
                found = true;
                indexFieldFound = true;
                breakHere = true;//this is last element, no other fields can be added to the key because this is a range condition
                OBinaryCondition condition = new OBinaryCondition(-1);
                condition.setLeft(left);
                condition.setOperator(operator);
                condition.setRight(((OBinaryCondition) singleExp).getRight().copy());
                indexKeyValue.getSubBlocks().add(condition);
                blockIterator.remove();
                //look for the opposite condition, on the same field, for range queries (the other side of the range)
                while (blockIterator.hasNext()) {
                  OBooleanExpression next = blockIterator.next();
                  if (createsRangeWith((OBinaryCondition) singleExp, next)) {
                    result.additionalRangeCondition = (OBinaryCondition) next;
                    blockIterator.remove();
                    break;
                  }
                }
                break;
              }
            }
          }
        } else if (singleExp instanceof OContainsValueCondition && ((OContainsValueCondition) singleExp).getExpression() != null
            && isMap(clazz, indexField) && isIndexByValue(index, indexField)) {
          OExpression left = ((OContainsValueCondition) singleExp).getLeft();
          if (left.isBaseIdentifier()) {
            String fieldName = left.getDefaultAlias().getStringValue();
            if (indexField.equals(fieldName)) {
              found = true;
              indexFieldFound = true;
              OBinaryCondition condition = new OBinaryCondition(-1);
              condition.setLeft(left);
              condition.setOperator(new OContainsValueOperator(-1));
              condition.setRight(((OContainsValueCondition) singleExp).getExpression().copy());
              indexKeyValue.getSubBlocks().add(condition);
              blockIterator.remove();
              break;
            }
          }
        } else if (singleExp instanceof OContainsAnyCondition) {
          OExpression left = ((OContainsAnyCondition) singleExp).getLeft();
          if (left.isBaseIdentifier()) {
            String fieldName = left.getDefaultAlias().getStringValue();
            if (indexField.equals(fieldName)) {
              if (!((OContainsAnyCondition) singleExp).getRight().isEarlyCalculated(ctx)) {
                continue; //this cannot be used because the value depends on single record
              }
              found = true;
              indexFieldFound = true;
              OContainsAnyCondition condition = new OContainsAnyCondition(-1);
              condition.setLeft(left);
              condition.setRight(((OContainsAnyCondition) singleExp).getRight().copy());
              indexKeyValue.getSubBlocks().add(condition);
              blockIterator.remove();
              break;
            }
          }
        } else if (singleExp instanceof OInCondition) {
          OExpression left = ((OInCondition) singleExp).getLeft();
          if (left.isBaseIdentifier()) {
            String fieldName = left.getDefaultAlias().getStringValue();
            if (indexField.equals(fieldName)) {
              if (((OInCondition) singleExp).getRightMathExpression() != null) {

                if (!((OInCondition) singleExp).getRightMathExpression().isEarlyCalculated(ctx)) {
                  continue; //this cannot be used because the value depends on single record
                }
                found = true;
                indexFieldFound = true;
                OInCondition condition = new OInCondition(-1);
                condition.setLeft(left);
                condition.setRightMathExpression(((OInCondition) singleExp).getRightMathExpression().copy());
                indexKeyValue.getSubBlocks().add(condition);
                blockIterator.remove();
                break;
              } else if (((OInCondition) singleExp).getRightParam() != null) {
                found = true;
                indexFieldFound = true;
                OInCondition condition = new OInCondition(-1);
                condition.setLeft(left);
                condition.setRightParam(((OInCondition) singleExp).getRightParam().copy());
                indexKeyValue.getSubBlocks().add(condition);
                blockIterator.remove();
                break;
              }
            }
          }
        }
      }
      if (breakHere || !indexFieldFound) {
        break;
      }
    }

    if (result.keyCondition.getSubBlocks().size() < index.getDefinition().getFields().size() && !index
        .supportsOrderedIterations()) {
      //hash indexes do not support partial key match
      return null;
    }

    if (found) {
      result.remainingCondition = blockCopy;
      return result;
    }
    return null;
  }
private IndexSearchDescriptor buildIndexSearchDescriptor(OCommandContext ctx, OIndex<?> index, OAndBlock block, OClass clazz) {
    List<String> indexFields = index.getDefinition().getFields();
    OBinaryCondition keyCondition = new OBinaryCondition(-1);
    OIdentifier key = new OIdentifier("key");
    keyCondition.setLeft(new OExpression(key));
    boolean allowsRange = allowsRangeQueries(index);
    boolean found = false;

    OAndBlock blockCopy = block.copy();
    Iterator<OBooleanExpression> blockIterator;

    OAndBlock indexKeyValue = new OAndBlock(-1);
    IndexSearchDescriptor result = new IndexSearchDescriptor();
    result.idx = index;
    result.keyCondition = indexKeyValue;
    for (String indexField : indexFields) {
      blockIterator = blockCopy.getSubBlocks().iterator();
      boolean breakHere = false;
      boolean indexFieldFound = false;
      while (blockIterator.hasNext()) {
        OBooleanExpression singleExp = blockIterator.next();
        if (singleExp instanceof OBinaryCondition) {
          OExpression left = ((OBinaryCondition) singleExp).getLeft();
          if (left.isBaseIdentifier()) {
            String fieldName = left.getDefaultAlias().getStringValue();
            if (indexField.equals(fieldName)) {
              OBinaryCompareOperator operator = ((OBinaryCondition) singleExp).getOperator();
              if (!((OBinaryCondition) singleExp).getRight().isEarlyCalculated(ctx)) {
                continue; 
              }
              if (operator instanceof OEqualsCompareOperator) {
                found = true;
                indexFieldFound = true;
                OBinaryCondition condition = new OBinaryCondition(-1);
                condition.setLeft(left);
                condition.setOperator(operator);
                condition.setRight(((OBinaryCondition) singleExp).getRight().copy());
                indexKeyValue.getSubBlocks().add(condition);
                blockIterator.remove();
                break;
              } else if (operator instanceof OContainsKeyOperator && isMap(clazz, indexField) && isIndexByKey(index, indexField)) {
                found = true;
                indexFieldFound = true;
                OBinaryCondition condition = new OBinaryCondition(-1);
                condition.setLeft(left);
                condition.setOperator(operator);
                condition.setRight(((OBinaryCondition) singleExp).getRight().copy());
                indexKeyValue.getSubBlocks().add(condition);
                blockIterator.remove();
                break;
              } else if (allowsRange && operator.isRangeOperator()) {
                found = true;
                indexFieldFound = true;
                breakHere = true;
                OBinaryCondition condition = new OBinaryCondition(-1);
                condition.setLeft(left);
                condition.setOperator(operator);
                condition.setRight(((OBinaryCondition) singleExp).getRight().copy());
                indexKeyValue.getSubBlocks().add(condition);
                blockIterator.remove();
                
                while (blockIterator.hasNext()) {
                  OBooleanExpression next = blockIterator.next();
                  if (createsRangeWith((OBinaryCondition) singleExp, next)) {
                    result.additionalRangeCondition = (OBinaryCondition) next;
                    blockIterator.remove();
                    break;
                  }
                }
                break;
              }
            }
          }
        } else if (singleExp instanceof OContainsValueCondition && ((OContainsValueCondition) singleExp).getExpression() != null
            && isMap(clazz, indexField) && isIndexByValue(index, indexField)) {
          OExpression left = ((OContainsValueCondition) singleExp).getLeft();
          if (left.isBaseIdentifier()) {
            String fieldName = left.getDefaultAlias().getStringValue();
            if (indexField.equals(fieldName)) {
              found = true;
              indexFieldFound = true;
              OBinaryCondition condition = new OBinaryCondition(-1);
              condition.setLeft(left);
              condition.setOperator(new OContainsValueOperator(-1));
              condition.setRight(((OContainsValueCondition) singleExp).getExpression().copy());
              indexKeyValue.getSubBlocks().add(condition);
              blockIterator.remove();
              break;
            }
          }
        } else if (singleExp instanceof OContainsAnyCondition) {
          OExpression left = ((OContainsAnyCondition) singleExp).getLeft();
          if (left.isBaseIdentifier()) {
            String fieldName = left.getDefaultAlias().getStringValue();
            if (indexField.equals(fieldName)) {
              if (!((OContainsAnyCondition) singleExp).getRight().isEarlyCalculated(ctx)) {
                continue; 
              }
              found = true;
              indexFieldFound = true;
              OContainsAnyCondition condition = new OContainsAnyCondition(-1);
              condition.setLeft(left);
              condition.setRight(((OContainsAnyCondition) singleExp).getRight().copy());
              indexKeyValue.getSubBlocks().add(condition);
              blockIterator.remove();
              break;
            }
          }
        } else if (singleExp instanceof OInCondition) {
          OExpression left = ((OInCondition) singleExp).getLeft();
          if (left.isBaseIdentifier()) {
            String fieldName = left.getDefaultAlias().getStringValue();
            if (indexField.equals(fieldName)) {
              if (((OInCondition) singleExp).getRightMathExpression() != null) {

                if (!((OInCondition) singleExp).getRightMathExpression().isEarlyCalculated(ctx)) {
                  continue; 
                }
                found = true;
                indexFieldFound = true;
                OInCondition condition = new OInCondition(-1);
                condition.setLeft(left);
                condition.setRightMathExpression(((OInCondition) singleExp).getRightMathExpression().copy());
                indexKeyValue.getSubBlocks().add(condition);
                blockIterator.remove();
                break;
              } else if (((OInCondition) singleExp).getRightParam() != null) {
                found = true;
                indexFieldFound = true;
                OInCondition condition = new OInCondition(-1);
                condition.setLeft(left);
                condition.setRightParam(((OInCondition) singleExp).getRightParam().copy());
                indexKeyValue.getSubBlocks().add(condition);
                blockIterator.remove();
                break;
              }
            }
          }
        }
      }
      if (breakHere || !indexFieldFound) {
        break;
      }
    }

    if (result.keyCondition.getSubBlocks().size() < index.getDefinition().getFields().size() && !index
        .supportsOrderedIterations()) {
      
      return null;
    }

    if (found) {
      result.remainingCondition = blockCopy;
      return result;
    }
    return null;
  }
private IndexSearchDescriptor buildIndexSearchDescriptor ( OCommandContext ctx , OIndex < ? > index , OAndBlock block , OClass clazz ) { List < String > indexFields = index . getDefinition ( ) . getFields ( ) ; OBinaryCondition keyCondition = new OBinaryCondition ( - 1 ) ; OIdentifier key = new OIdentifier ( "key" ) ; keyCondition . setLeft ( new OExpression ( key ) ) ; boolean allowsRange = allowsRangeQueries ( index ) ; boolean found = false ; OAndBlock blockCopy = block . copy ( ) ; Iterator < OBooleanExpression > blockIterator ; OAndBlock indexKeyValue = new OAndBlock ( - 1 ) ; IndexSearchDescriptor result = new IndexSearchDescriptor ( ) ; result . idx = index ; result . keyCondition = indexKeyValue ; for ( String indexField : indexFields ) { blockIterator = blockCopy . getSubBlocks ( ) . iterator ( ) ; boolean breakHere = false ; boolean indexFieldFound = false ; while ( blockIterator . hasNext ( ) ) { OBooleanExpression singleExp = blockIterator . next ( ) ; if ( singleExp instanceof OBinaryCondition ) { OExpression left = ( ( OBinaryCondition ) singleExp ) . getLeft ( ) ; if ( left . isBaseIdentifier ( ) ) { String fieldName = left . getDefaultAlias ( ) . getStringValue ( ) ; if ( indexField . equals ( fieldName ) ) { OBinaryCompareOperator operator = ( ( OBinaryCondition ) singleExp ) . getOperator ( ) ; if ( ! ( ( OBinaryCondition ) singleExp ) . getRight ( ) . isEarlyCalculated ( ctx ) ) { continue ; //this cannot be used because the value depends on single record } if ( operator instanceof OEqualsCompareOperator ) { found = true ; indexFieldFound = true ; OBinaryCondition condition = new OBinaryCondition ( - 1 ) ; condition . setLeft ( left ) ; condition . setOperator ( operator ) ; condition . setRight ( ( ( OBinaryCondition ) singleExp ) . getRight ( ) . copy ( ) ) ; indexKeyValue . getSubBlocks ( ) . add ( condition ) ; blockIterator . remove ( ) ; break ; } else if ( operator instanceof OContainsKeyOperator && isMap ( clazz , indexField ) && isIndexByKey ( index , indexField ) ) { found = true ; indexFieldFound = true ; OBinaryCondition condition = new OBinaryCondition ( - 1 ) ; condition . setLeft ( left ) ; condition . setOperator ( operator ) ; condition . setRight ( ( ( OBinaryCondition ) singleExp ) . getRight ( ) . copy ( ) ) ; indexKeyValue . getSubBlocks ( ) . add ( condition ) ; blockIterator . remove ( ) ; break ; } else if ( allowsRange && operator . isRangeOperator ( ) ) { found = true ; indexFieldFound = true ; breakHere = true ; //this is last element, no other fields can be added to the key because this is a range condition OBinaryCondition condition = new OBinaryCondition ( - 1 ) ; condition . setLeft ( left ) ; condition . setOperator ( operator ) ; condition . setRight ( ( ( OBinaryCondition ) singleExp ) . getRight ( ) . copy ( ) ) ; indexKeyValue . getSubBlocks ( ) . add ( condition ) ; blockIterator . remove ( ) ; //look for the opposite condition, on the same field, for range queries (the other side of the range) while ( blockIterator . hasNext ( ) ) { OBooleanExpression next = blockIterator . next ( ) ; if ( createsRangeWith ( ( OBinaryCondition ) singleExp , next ) ) { result . additionalRangeCondition = ( OBinaryCondition ) next ; blockIterator . remove ( ) ; break ; } } break ; } } } } else if ( singleExp instanceof OContainsValueCondition && ( ( OContainsValueCondition ) singleExp ) . getExpression ( ) != null && isMap ( clazz , indexField ) && isIndexByValue ( index , indexField ) ) { OExpression left = ( ( OContainsValueCondition ) singleExp ) . getLeft ( ) ; if ( left . isBaseIdentifier ( ) ) { String fieldName = left . getDefaultAlias ( ) . getStringValue ( ) ; if ( indexField . equals ( fieldName ) ) { found = true ; indexFieldFound = true ; OBinaryCondition condition = new OBinaryCondition ( - 1 ) ; condition . setLeft ( left ) ; condition . setOperator ( new OContainsValueOperator ( - 1 ) ) ; condition . setRight ( ( ( OContainsValueCondition ) singleExp ) . getExpression ( ) . copy ( ) ) ; indexKeyValue . getSubBlocks ( ) . add ( condition ) ; blockIterator . remove ( ) ; break ; } } } else if ( singleExp instanceof OContainsAnyCondition ) { OExpression left = ( ( OContainsAnyCondition ) singleExp ) . getLeft ( ) ; if ( left . isBaseIdentifier ( ) ) { String fieldName = left . getDefaultAlias ( ) . getStringValue ( ) ; if ( indexField . equals ( fieldName ) ) { if ( ! ( ( OContainsAnyCondition ) singleExp ) . getRight ( ) . isEarlyCalculated ( ctx ) ) { continue ; //this cannot be used because the value depends on single record } found = true ; indexFieldFound = true ; OContainsAnyCondition condition = new OContainsAnyCondition ( - 1 ) ; condition . setLeft ( left ) ; condition . setRight ( ( ( OContainsAnyCondition ) singleExp ) . getRight ( ) . copy ( ) ) ; indexKeyValue . getSubBlocks ( ) . add ( condition ) ; blockIterator . remove ( ) ; break ; } } } else if ( singleExp instanceof OInCondition ) { OExpression left = ( ( OInCondition ) singleExp ) . getLeft ( ) ; if ( left . isBaseIdentifier ( ) ) { String fieldName = left . getDefaultAlias ( ) . getStringValue ( ) ; if ( indexField . equals ( fieldName ) ) { if ( ( ( OInCondition ) singleExp ) . getRightMathExpression ( ) != null ) { if ( ! ( ( OInCondition ) singleExp ) . getRightMathExpression ( ) . isEarlyCalculated ( ctx ) ) { continue ; //this cannot be used because the value depends on single record } found = true ; indexFieldFound = true ; OInCondition condition = new OInCondition ( - 1 ) ; condition . setLeft ( left ) ; condition . setRightMathExpression ( ( ( OInCondition ) singleExp ) . getRightMathExpression ( ) . copy ( ) ) ; indexKeyValue . getSubBlocks ( ) . add ( condition ) ; blockIterator . remove ( ) ; break ; } else if ( ( ( OInCondition ) singleExp ) . getRightParam ( ) != null ) { found = true ; indexFieldFound = true ; OInCondition condition = new OInCondition ( - 1 ) ; condition . setLeft ( left ) ; condition . setRightParam ( ( ( OInCondition ) singleExp ) . getRightParam ( ) . copy ( ) ) ; indexKeyValue . getSubBlocks ( ) . add ( condition ) ; blockIterator . remove ( ) ; break ; } } } } } if ( breakHere || ! indexFieldFound ) { break ; } } if ( result . keyCondition . getSubBlocks ( ) . size ( ) < index . getDefinition ( ) . getFields ( ) . size ( ) && ! index . supportsOrderedIterations ( ) ) { //hash indexes do not support partial key match return null ; } if ( found ) { result . remainingCondition = blockCopy ; return result ; } return null ; }
given an index and a flat AND block, returns a descriptor on how to process it with an index (index, index key and additional
filters to apply after index fetch

@param ctx
@param index
@param block
@param clazz

@return
given an index and a flat AND block returns a descriptor on how to process it with an index ( index index key and additional filters to apply after index fetch