public void unparse(
      SqlWriter writer,
      SqlCall call,
      int leftPrec,
      int rightPrec) {
    final SqlWriter.Frame frame =
        writer.startList(SqlWriter.FrameTypeEnum.create("BETWEEN"), "", "");
    call.operand(VALUE_OPERAND).unparse(writer, getLeftPrec(), 0);
    writer.sep(super.getName());

    // If the expression for the lower bound contains a call to an AND
    // operator, we need to wrap the expression in parentheses to prevent
    // the AND from associating with BETWEEN. For example, we should
    // unparse
    //    a BETWEEN b OR (c AND d) OR e AND f
    // as
    //    a BETWEEN (b OR c AND d) OR e) AND f
    // If it were unparsed as
    //    a BETWEEN b OR c AND d OR e AND f
    // then it would be interpreted as
    //    (a BETWEEN (b OR c) AND d) OR (e AND f)
    // which would be wrong.
    final SqlNode lower = call.operand(LOWER_OPERAND);
    final SqlNode upper = call.operand(UPPER_OPERAND);
    int lowerPrec = new AndFinder().containsAnd(lower) ? 100 : 0;
    lower.unparse(writer, lowerPrec, lowerPrec);
    writer.sep("AND");
    upper.unparse(writer, 0, getRightPrec());
    writer.endList(frame);
  }
Operand type-inference strategy where an unknown operand type is derived
from the first operand with a known type, but the first operand is a boolean.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/reloperators/HiveBetween.java