boolean addToIndexConditions(Expression e) {

      if (opType == OpTypes.EQUAL || opType == OpTypes.IS_NULL) {
        if (indexedColumnCount < rangeIndex.getColumnCount()) {
          if (rangeIndex.getColumns()[indexedColumnCount] == e.getLeftNode().getColumnIndex()) {
            indexCond[indexedColumnCount] = e;

            indexedColumnCount++;

            opType = e.opType;
            opTypeEnd = OpTypes.MAX;

            return true;
          }
        }
      }

      return false;
    }
    private boolean addToIndexEndConditions(Expression e) {

      if (opType == OpTypes.EQUAL || opType == OpTypes.IS_NULL) {
        if (indexedColumnCount < rangeIndex.getColumnCount()) {
          if (rangeIndex.getColumns()[indexedColumnCount] == e.getLeftNode().getColumnIndex()) {
            Expression condition = ExpressionLogical.newNotNullCondition(e.getLeftNode());

            indexCond[indexedColumnCount] = condition;
            indexEndCond[indexedColumnCount] = e;
            indexEndCondition = ExpressionLogical.andExpressions(indexEndCondition, e);
            opType = OpTypes.NOT;
            opTypes[indexedColumnCount] = OpTypes.NOT;
            opTypeEnd = e.opType;
            opTypesEnd[indexedColumnCount] = e.opType;

            indexedColumnCount++;

            return true;
          }
        }
      }

      return false;
    }
    /**
     * @param exprList list of expressions
     * @param index Index to use
     * @param colCount number of columns searched
     */
    void addIndexCondition(Expression[] exprList, Index index, int colCount) {

      int indexColCount = index.getColumnCount();

      rangeIndex = index;
      indexCond = new Expression[indexColCount];
      indexEndCond = new Expression[indexColCount];
      opTypes = new int[indexColCount];
      opTypesEnd = new int[indexColCount];
      opType = exprList[0].opType;
      opTypes[0] = exprList[0].opType;

      switch (opType) {
        case OpTypes.NOT:
          indexCond = exprList;
          opTypeEnd = OpTypes.MAX;
          opTypesEnd[0] = OpTypes.MAX;
          break;

        case OpTypes.GREATER:
        case OpTypes.GREATER_EQUAL:
        case OpTypes.GREATER_EQUAL_PRE:
          indexCond = exprList;

          if (exprList[0].getType() == OpTypes.GREATER_EQUAL_PRE) {
            indexEndCond[0] = indexEndCondition = exprList[0].nodes[2];
          }

          opTypeEnd = OpTypes.MAX;
          opTypesEnd[0] = OpTypes.MAX;
          break;

        case OpTypes.SMALLER:
        case OpTypes.SMALLER_EQUAL:
          {
            Expression e = exprList[0].getLeftNode();

            e = new ExpressionLogical(OpTypes.IS_NULL, e);
            e = new ExpressionLogical(OpTypes.NOT, e);
            indexCond[0] = e;
            indexEndCond[0] = indexEndCondition = exprList[0];
            opTypeEnd = opType;
            opTypesEnd[0] = opType;
            opType = OpTypes.NOT;
            opTypes[0] = OpTypes.NOT;

            break;
          }
        case OpTypes.IS_NULL:
        case OpTypes.EQUAL:
          {
            indexCond = exprList;

            for (int i = 0; i < colCount; i++) {
              Expression e = exprList[i];

              indexEndCond[i] = e;
              indexEndCondition = ExpressionLogical.andExpressions(indexEndCondition, e);
              opType = e.opType;
              opTypes[0] = e.opType;
              opTypesEnd[0] = e.opType;
            }

            opTypeEnd = opType;

            break;
          }
        default:
          Error.runtimeError(ErrorCode.U_S0500, "RangeVariable");
      }

      indexedColumnCount = colCount;
      hasIndex = true;
    }
    void addCondition(Expression e) {

      if (e == null) {
        return;
      }

      if (e instanceof ExpressionLogical) {
        if (((ExpressionLogical) e).isTerminal) {
          terminalCondition = e;
        }
      }

      nonIndexCondition = ExpressionLogical.andExpressions(nonIndexCondition, e);

      if (Expression.EXPR_FALSE.equals(nonIndexCondition)) {
        isFalse = true;
      }

      if (rangeIndex == null || rangeIndex.getColumnCount() == 0) {
        return;
      }

      if (indexedColumnCount == 0) {
        return;
      }

      if (e.getIndexableExpression(rangeVar) == null) {
        return;
      }

      int colIndex = e.getLeftNode().getColumnIndex();
      int[] indexCols = rangeIndex.getColumns();

      switch (e.getType()) {
        case OpTypes.GREATER:
        case OpTypes.GREATER_EQUAL:
        case OpTypes.GREATER_EQUAL_PRE:
          {

            // replaces existing condition
            if (opType == OpTypes.NOT) {
              if (indexCols[indexedColumnCount - 1] == colIndex) {
                nonIndexCondition =
                    ExpressionLogical.andExpressions(
                        nonIndexCondition, indexCond[indexedColumnCount - 1]);
                indexCond[indexedColumnCount - 1] = e;
                opType = e.opType;
                opTypes[indexedColumnCount - 1] = e.opType;

                if (e.getType() == OpTypes.GREATER_EQUAL_PRE && indexedColumnCount == 1) {
                  indexEndCond[indexedColumnCount - 1] =
                      ExpressionLogical.andExpressions(
                          indexEndCond[indexedColumnCount - 1], e.nodes[2]);
                }
              }
            } else {
              addToIndexConditions(e);
            }

            break;
          }
        case OpTypes.SMALLER:
        case OpTypes.SMALLER_EQUAL:
          {
            if (opType == OpTypes.GREATER
                || opType == OpTypes.GREATER_EQUAL
                || opType == OpTypes.GREATER_EQUAL_PRE
                || opType == OpTypes.NOT) {
              if (opTypeEnd != OpTypes.MAX) {
                break;
              }

              if (indexCols[indexedColumnCount - 1] == colIndex) {
                indexEndCond[indexedColumnCount - 1] = e;
                indexEndCondition = ExpressionLogical.andExpressions(indexEndCondition, e);
                opTypeEnd = e.opType;
                opTypesEnd[indexedColumnCount - 1] = e.opType;
              }
            } else {
              addToIndexEndConditions(e);
            }

            break;
          }
        default:
      }
    }