core/src/main/java/com/orientechnologies/orient/core/sql/executor/OSelectExecutionPlanner.java
private IndexSearchDescriptor buildIndexSearchDescriptorForFulltext(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 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 OContainsTextCondition) {
          OExpression left = ((OContainsTextCondition) singleExp).getLeft();
          if (left.isBaseIdentifier()) {
            String fieldName = left.getDefaultAlias().getStringValue();
            if (indexField.equals(fieldName)) {
              found = true;
              indexFieldFound = true;
              OContainsTextCondition condition = new OContainsTextCondition(-1);
              condition.setLeft(left);
              condition.setRight(((OContainsTextCondition) singleExp).getRight().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 buildIndexSearchDescriptorForFulltext(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 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 OContainsTextCondition) {
          OExpression left = ((OContainsTextCondition) singleExp).getLeft();
          if (left.isBaseIdentifier()) {
            String fieldName = left.getDefaultAlias().getStringValue();
            if (indexField.equals(fieldName)) {
              found = true;
              indexFieldFound = true;
              OContainsTextCondition condition = new OContainsTextCondition(-1);
              condition.setLeft(left);
              condition.setRight(((OContainsTextCondition) singleExp).getRight().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 a full text 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