Java Code Examples for org.apache.calcite.sql.type.SqlTypeName#INTEGER

The following examples show how to use org.apache.calcite.sql.type.SqlTypeName#INTEGER . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: JethroDataSqlDialect.java    From Bats with Apache License 2.0 6 votes vote down vote up
private SqlTypeName parse(String strType) {
  switch (strType.toLowerCase(Locale.ROOT)) {
  case "bigint":
  case "long":
    return SqlTypeName.BIGINT;
  case "integer":
  case "int":
    return SqlTypeName.INTEGER;
  case "double":
    return SqlTypeName.DOUBLE;
  case "float":
    return SqlTypeName.FLOAT;
  case "string":
    return SqlTypeName.VARCHAR;
  case "timestamp":
    return SqlTypeName.TIMESTAMP;
  default:
    return SqlTypeName.ANY;
  }
}
 
Example 2
Source File: RexToTestCodeShuttle.java    From calcite with Apache License 2.0 6 votes vote down vote up
@Override public String visitLiteral(RexLiteral literal) {
  RelDataType type = literal.getType();

  if (type.getSqlTypeName() == SqlTypeName.BOOLEAN) {
    if (literal.isNull()) {
      return "nullBool";
    }
    return literal.toString() + "Literal";
  }
  if (type.getSqlTypeName() == SqlTypeName.INTEGER) {
    if (literal.isNull()) {
      return "nullInt";
    }
    return "literal(" + literal.getValue() + ")";
  }
  if (type.getSqlTypeName() == SqlTypeName.VARCHAR) {
    if (literal.isNull()) {
      return "nullVarchar";
    }
  }
  return "/*" + literal.getTypeName().getName() + "*/" + literal.toString();
}
 
Example 3
Source File: SqlNumericLiteral.java    From calcite with Apache License 2.0 6 votes vote down vote up
public RelDataType createSqlType(RelDataTypeFactory typeFactory) {
  if (isExact) {
    int scaleValue = scale.intValue();
    if (0 == scaleValue) {
      BigDecimal bd = (BigDecimal) value;
      SqlTypeName result;
      long l = bd.longValue();
      if ((l >= Integer.MIN_VALUE) && (l <= Integer.MAX_VALUE)) {
        result = SqlTypeName.INTEGER;
      } else {
        result = SqlTypeName.BIGINT;
      }
      return typeFactory.createSqlType(result);
    }

    // else we have a decimal
    return typeFactory.createSqlType(
        SqlTypeName.DECIMAL,
        prec.intValue(),
        scaleValue);
  }

  // else we have a a float, real or double.  make them all double for
  // now.
  return typeFactory.createSqlType(SqlTypeName.DOUBLE);
}
 
Example 4
Source File: JethroDataSqlDialect.java    From calcite with Apache License 2.0 6 votes vote down vote up
private SqlTypeName parse(String strType) {
  switch (strType.toLowerCase(Locale.ROOT)) {
  case "bigint":
  case "long":
    return SqlTypeName.BIGINT;
  case "integer":
  case "int":
    return SqlTypeName.INTEGER;
  case "double":
    return SqlTypeName.DOUBLE;
  case "float":
    return SqlTypeName.FLOAT;
  case "string":
    return SqlTypeName.VARCHAR;
  case "timestamp":
    return SqlTypeName.TIMESTAMP;
  default:
    return SqlTypeName.ANY;
  }
}
 
Example 5
Source File: ElasticsearchRules.java    From calcite with Apache License 2.0 6 votes vote down vote up
@Override public String visitCall(RexCall call) {
  final String name = isItemCall(call);
  if (name != null) {
    return name;
  }

  final List<String> strings = visitList(call.operands);

  if (call.getKind() == SqlKind.CAST) {
    return call.getOperands().get(0).accept(this);
  }

  if (call.getOperator() == SqlStdOperatorTable.ITEM) {
    final RexNode op1 = call.getOperands().get(1);
    if (op1 instanceof RexLiteral && op1.getType().getSqlTypeName() == SqlTypeName.INTEGER) {
      return stripQuotes(strings.get(0)) + "[" + ((RexLiteral) op1).getValue2() + "]";
    }
  }
  throw new IllegalArgumentException("Translation of " + call
      + " is not supported by ElasticsearchProject");
}
 
Example 6
Source File: GeodeRules.java    From calcite with Apache License 2.0 6 votes vote down vote up
@Override public String visitCall(RexCall call) {
  final List<String> strings = new ArrayList<>();
  visitList(call.operands, strings);
  if (call.getOperator() == SqlStdOperatorTable.ITEM) {
    final RexNode op1 = call.getOperands().get(1);
    if (op1 instanceof RexLiteral) {
      if (op1.getType().getSqlTypeName() == SqlTypeName.INTEGER) {
        return stripQuotes(strings.get(0)) + "[" + ((RexLiteral) op1).getValue2() + "]";
      } else if (op1.getType().getSqlTypeName() == SqlTypeName.CHAR) {
        return stripQuotes(strings.get(0)) + "." + ((RexLiteral) op1).getValue2();
      }
    }
  }

  return super.visitCall(call);
}
 
Example 7
Source File: SqlNumericLiteral.java    From Bats with Apache License 2.0 6 votes vote down vote up
public RelDataType createSqlType(RelDataTypeFactory typeFactory) {
  if (isExact) {
    int scaleValue = scale.intValue();
    if (0 == scaleValue) {
      BigDecimal bd = (BigDecimal) value;
      SqlTypeName result;
      long l = bd.longValue();
      if ((l >= Integer.MIN_VALUE) && (l <= Integer.MAX_VALUE)) {
        result = SqlTypeName.INTEGER;
      } else {
        result = SqlTypeName.BIGINT;
      }
      return typeFactory.createSqlType(result);
    }

    // else we have a decimal
    return typeFactory.createSqlType(
        SqlTypeName.DECIMAL,
        prec.intValue(),
        scaleValue);
  }

  // else we have a a float, real or double.  make them all double for
  // now.
  return typeFactory.createSqlType(SqlTypeName.DOUBLE);
}
 
Example 8
Source File: TypeInferenceUtils.java    From dremio-oss with Apache License 2.0 5 votes vote down vote up
@Override
public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
  final RelDataTypeFactory factory = opBinding.getTypeFactory();
  final SqlTypeName sqlTypeName = SqlTypeName.INTEGER;

  // We need to check only the first argument because
  // the second one is used to represent encoding type
  final boolean isNullable = opBinding.getOperandType(0).isNullable();
  return createCalciteTypeWithNullability(factory, sqlTypeName, isNullable, null);
}
 
Example 9
Source File: JoinTranslator.java    From samza with Apache License 2.0 5 votes vote down vote up
private void validateJoinKeyType(RexInputRef ref) {
  SqlTypeName sqlTypeName = ref.getType().getSqlTypeName();

  // Primitive types and ANY (for the record key) are supported in the key
  if (sqlTypeName != SqlTypeName.BOOLEAN && sqlTypeName != SqlTypeName.TINYINT && sqlTypeName != SqlTypeName.SMALLINT
      && sqlTypeName != SqlTypeName.INTEGER && sqlTypeName != SqlTypeName.CHAR && sqlTypeName != SqlTypeName.BIGINT
      && sqlTypeName != SqlTypeName.VARCHAR && sqlTypeName != SqlTypeName.DOUBLE && sqlTypeName != SqlTypeName.FLOAT
      && sqlTypeName != SqlTypeName.ANY && sqlTypeName != SqlTypeName.OTHER) {
    log.error("Unsupported key type " + sqlTypeName + " used in join condition.");
    throw new SamzaException("Unsupported key type used in join condition.");
  }
}
 
Example 10
Source File: SamzaSqlValidator.java    From samza with Apache License 2.0 5 votes vote down vote up
private boolean compareFieldTypes(RelDataType outputFieldType, SqlFieldSchema sqlFieldSchema,
    RelDataType selectQueryFieldType, RelSchemaProvider outputRelSchemaProvider) {

  SqlTypeName outputSqlType = outputFieldType.getSqlTypeName();
  SqlTypeName projectSqlType = selectQueryFieldType.getSqlTypeName();

  if (projectSqlType == SqlTypeName.ANY || outputSqlType == SqlTypeName.ANY) {
    return true;
  } else if (outputSqlType != SqlTypeName.ROW && outputSqlType == projectSqlType) {
    return true;
  }

  switch (outputSqlType) {
    case CHAR:
      return projectSqlType == SqlTypeName.VARCHAR;
    case VARCHAR:
      return projectSqlType == SqlTypeName.CHAR;
    case BIGINT:
      return projectSqlType == SqlTypeName.INTEGER;
    case INTEGER:
      return projectSqlType == SqlTypeName.BIGINT;
    case FLOAT:
      return projectSqlType == SqlTypeName.DOUBLE;
    case DOUBLE:
      return projectSqlType == SqlTypeName.FLOAT;
    case ROW:
      try {
        validateOutputRecords(sqlFieldSchema.getRowSchema(), (RelRecordType) outputFieldType,
            (RelRecordType) selectQueryFieldType, outputRelSchemaProvider);
      } catch (SamzaSqlValidatorException e) {
        LOG.error("A field in select query does not match with the output schema.", e);
        return false;
      }
      return true;
    default:
      return false;
  }
}
 
Example 11
Source File: Checker.java    From samza with Apache License 2.0 5 votes vote down vote up
/**
 * Converts the {@link SamzaSqlFieldType} to the calcite {@link SqlTypeName}.
 * @param samzaSqlFieldType the samza sql field type.
 * @return the converted calcite SqlTypeName.
 */
@VisibleForTesting
static SqlTypeName toCalciteSqlType(SamzaSqlFieldType samzaSqlFieldType) {
  switch (samzaSqlFieldType) {
    case ANY:
    case ROW:
      return SqlTypeName.ANY;
    case MAP:
      return SqlTypeName.MAP;
    case ARRAY:
      return SqlTypeName.ARRAY;
    case REAL:
      return SqlTypeName.REAL;
    case DOUBLE:
      return SqlTypeName.DOUBLE;
    case STRING:
      return SqlTypeName.VARCHAR;
    case INT16:
    case INT32:
      return SqlTypeName.INTEGER;
    case FLOAT:
      return SqlTypeName.FLOAT;
    case INT64:
      return SqlTypeName.BIGINT;
    case BOOLEAN:
      return SqlTypeName.BOOLEAN;
    case BYTES:
      return SqlTypeName.VARBINARY;
    default:
      String msg = String.format("Field Type %s is not supported", samzaSqlFieldType);
      LOG.error(msg);
      throw new SamzaException(msg);
  }
}
 
Example 12
Source File: TableEnv.java    From marble with Apache License 2.0 5 votes vote down vote up
protected SqlTypeName getSqlTypeNameForJdbcType(int jdbcType) {
  //FIX Calcite jdbc type converting bug
  SqlTypeName typeName = SqlTypeName.getNameForJdbcType(jdbcType);
  if (jdbcType == Types.LONGVARCHAR) {
    typeName = SqlTypeName.VARCHAR;
  }
  if (jdbcType == Types.SMALLINT || jdbcType == Types.TINYINT) {
    //the type of jdbc value is INTEGER when jdbcType is SMALLINT or TINYINT
    typeName = SqlTypeName.INTEGER;
  }
  return typeName;
}
 
Example 13
Source File: RexLiteralImpl.java    From Bats with Apache License 2.0 5 votes vote down vote up
/**
 * Computes if data type can be omitted from the digset.
 * <p>For instance, {@code 1:BIGINT} has to keep data type while {@code 1:INT}
 * should be represented as just {@code 1}.
 *
 * <p>Implementation assumption: this method should be fast. In fact might call
 * {@link NlsString#getValue()} which could decode the string, however we rely on the cache there.
 *
 * @see RexLiteral#computeDigest(RexDigestIncludeType)
 * @param value value of the literal
 * @param type type of the literal
 * @return NO_TYPE when type can be omitted, ALWAYS otherwise
 */
private static RexDigestIncludeType shouldIncludeType(Comparable value, RelDataType type) {
    if (type.isNullable()) {
        // This means "null literal", so we require a type for it
        // There might be exceptions like AND(null, true) which are handled by RexCall#computeDigest
        return RexDigestIncludeType.ALWAYS;
    }
    // The variable here simplifies debugging (one can set a breakpoint at return)
    // final ensures we set the value in all the branches, and it ensures the value is set just once
    final RexDigestIncludeType includeType;
    if (type.getSqlTypeName() == SqlTypeName.BOOLEAN || type.getSqlTypeName() == SqlTypeName.INTEGER
            || type.getSqlTypeName() == SqlTypeName.SYMBOL) {
        // We don't want false:BOOLEAN NOT NULL, so we don't print type information for
        // non-nullable BOOLEAN and INTEGER
        includeType = RexDigestIncludeType.NO_TYPE;
    } else if (type.getSqlTypeName() == SqlTypeName.CHAR && value instanceof NlsString) {
        NlsString nlsString = (NlsString) value;

        // Ignore type information for 'Bar':CHAR(3)
        if (((nlsString.getCharset() != null && type.getCharset().equals(nlsString.getCharset()))
                || (nlsString.getCharset() == null && SqlCollation.IMPLICIT.getCharset().equals(type.getCharset())))
                && nlsString.getCollation().equals(type.getCollation())
                && ((NlsString) value).getValue().length() == type.getPrecision()) {
            includeType = RexDigestIncludeType.NO_TYPE;
        } else {
            includeType = RexDigestIncludeType.ALWAYS;
        }
    } else if (type.getPrecision() == 0 && (type.getSqlTypeName() == SqlTypeName.TIME
            || type.getSqlTypeName() == SqlTypeName.TIMESTAMP || type.getSqlTypeName() == SqlTypeName.DATE)) {
        // Ignore type information for '12:23:20':TIME(0)
        // Note that '12:23:20':TIME WITH LOCAL TIME ZONE
        includeType = RexDigestIncludeType.NO_TYPE;
    } else {
        includeType = RexDigestIncludeType.ALWAYS;
    }
    return includeType;
}
 
Example 14
Source File: TypeInferenceUtils.java    From dremio-oss with Apache License 2.0 4 votes vote down vote up
@Override
public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
  final RelDataTypeFactory factory = opBinding.getTypeFactory();
  SqlTypeName typeToCastTo = null;
  if (opBinding instanceof SqlCallBinding) {
    SqlCallBinding sqlCallBinding = (SqlCallBinding) opBinding;
    if (sqlCallBinding.operand(1).getKind() == SqlKind.LITERAL) {
      String type = null;
      try {
        SqlLiteral sqlLiteral = (SqlLiteral) sqlCallBinding.operand(1);
        type = ((NlsString) sqlLiteral.getValue()).getValue();
        switch(type) {
          case "JSON":
            typeToCastTo = SqlTypeName.ANY;
            break;
          case "UTF8":
          case "UTF16":
            typeToCastTo = SqlTypeName.VARCHAR;
            break;
          case "BOOLEAN_BYTE":
            typeToCastTo = SqlTypeName.BOOLEAN;
            break;
          case "TINYINT_BE":
          case "TINYINT":
            typeToCastTo = SqlTypeName.TINYINT;
            break;
          case "SMALLINT_BE":
          case "SMALLINT":
            typeToCastTo = SqlTypeName.SMALLINT;
            break;
          case "INT_BE":
          case "INT":
          case "INT_HADOOPV":
            typeToCastTo = SqlTypeName.INTEGER;
            break;
          case "BIGINT_BE":
          case "BIGINT":
          case "BIGINT_HADOOPV":
            typeToCastTo = SqlTypeName.BIGINT;
            break;
          case "FLOAT":
            typeToCastTo = SqlTypeName.FLOAT;
            break;
          case "DOUBLE":
            typeToCastTo = SqlTypeName.DOUBLE;
            break;
          case "DATE_EPOCH_BE":
          case "DATE_EPOCH":
            typeToCastTo = SqlTypeName.DATE;
            break;
          case "TIME_EPOCH_BE":
          case "TIME_EPOCH":
            typeToCastTo = SqlTypeName.TIME;
            break;
          case "TIMESTAMP_EPOCH":
          case "TIMESTAMP_IMPALA":
            typeToCastTo = SqlTypeName.TIMESTAMP;
            break;
          default:
            typeToCastTo = SqlTypeName.ANY;
            break;
        }
      } catch (final ClassCastException e) {
        logger.debug("Failed to parse string for convert_from()");
      }
    }
  }

  if (typeToCastTo == null) {
    typeToCastTo = SqlTypeName.ANY;
  }
  return factory.createTypeWithNullability(
      factory.createSqlType(typeToCastTo),
      true);
}
 
Example 15
Source File: MongoRules.java    From calcite with Apache License 2.0 4 votes vote down vote up
@Override public String visitCall(RexCall call) {
  String name = isItem(call);
  if (name != null) {
    return "'$" + name + "'";
  }
  final List<String> strings = visitList(call.operands);
  if (call.getKind() == SqlKind.CAST) {
    return strings.get(0);
  }
  String stdOperator = MONGO_OPERATORS.get(call.getOperator());
  if (stdOperator != null) {
    return "{" + stdOperator + ": [" + Util.commaList(strings) + "]}";
  }
  if (call.getOperator() == SqlStdOperatorTable.ITEM) {
    final RexNode op1 = call.operands.get(1);
    if (op1 instanceof RexLiteral
        && op1.getType().getSqlTypeName() == SqlTypeName.INTEGER) {
      if (!Bug.CALCITE_194_FIXED) {
        return "'" + stripQuotes(strings.get(0)) + "["
            + ((RexLiteral) op1).getValue2() + "]'";
      }
      return strings.get(0) + "[" + strings.get(1) + "]";
    }
  }
  if (call.getOperator() == SqlStdOperatorTable.CASE) {
    StringBuilder sb = new StringBuilder();
    StringBuilder finish = new StringBuilder();
    // case(a, b, c)  -> $cond:[a, b, c]
    // case(a, b, c, d) -> $cond:[a, b, $cond:[c, d, null]]
    // case(a, b, c, d, e) -> $cond:[a, b, $cond:[c, d, e]]
    for (int i = 0; i < strings.size(); i += 2) {
      sb.append("{$cond:[");
      finish.append("]}");

      sb.append(strings.get(i));
      sb.append(',');
      sb.append(strings.get(i + 1));
      sb.append(',');
      if (i == strings.size() - 3) {
        sb.append(strings.get(i + 2));
        break;
      }
      if (i == strings.size() - 2) {
        sb.append("null");
        break;
      }
    }
    sb.append(finish);
    return sb.toString();
  }
  throw new IllegalArgumentException("Translation of " + call.toString()
      + " is not supported by MongoProject");
}
 
Example 16
Source File: StandardConvertletTable.java    From calcite with Apache License 2.0 4 votes vote down vote up
public RexNode convertCall(SqlRexContext cx, SqlCall call) {
  // TIMESTAMPDIFF(unit, t1, t2)
  //    => (t2 - t1) UNIT
  final RexBuilder rexBuilder = cx.getRexBuilder();
  final SqlLiteral unitLiteral = call.operand(0);
  TimeUnit unit = unitLiteral.symbolValue(TimeUnit.class);
  BigDecimal multiplier = BigDecimal.ONE;
  BigDecimal divider = BigDecimal.ONE;
  SqlTypeName sqlTypeName = unit == TimeUnit.NANOSECOND
      ? SqlTypeName.BIGINT
      : SqlTypeName.INTEGER;
  switch (unit) {
  case MICROSECOND:
  case MILLISECOND:
  case NANOSECOND:
  case WEEK:
    multiplier = BigDecimal.valueOf(DateTimeUtils.MILLIS_PER_SECOND);
    divider = unit.multiplier;
    unit = TimeUnit.SECOND;
    break;
  case QUARTER:
    divider = unit.multiplier;
    unit = TimeUnit.MONTH;
    break;
  }
  final SqlIntervalQualifier qualifier =
      new SqlIntervalQualifier(unit, null, SqlParserPos.ZERO);
  final RexNode op2 = cx.convertExpression(call.operand(2));
  final RexNode op1 = cx.convertExpression(call.operand(1));
  final RelDataType intervalType =
      cx.getTypeFactory().createTypeWithNullability(
          cx.getTypeFactory().createSqlIntervalType(qualifier),
          op1.getType().isNullable() || op2.getType().isNullable());
  final RexCall rexCall = (RexCall) rexBuilder.makeCall(
      intervalType, SqlStdOperatorTable.MINUS_DATE,
      ImmutableList.of(op2, op1));
  final RelDataType intType =
      cx.getTypeFactory().createTypeWithNullability(
          cx.getTypeFactory().createSqlType(sqlTypeName),
          SqlTypeUtil.containsNullable(rexCall.getType()));
  RexNode e = rexBuilder.makeCast(intType, rexCall);
  return rexBuilder.multiplyDivide(e, multiplier, divider);
}
 
Example 17
Source File: RexLiteral.java    From calcite with Apache License 2.0 4 votes vote down vote up
/**
 * Computes if data type can be omitted from the digset.
 * <p>For instance, {@code 1:BIGINT} has to keep data type while {@code 1:INT}
 * should be represented as just {@code 1}.
 *
 * <p>Implementation assumption: this method should be fast. In fact might call
 * {@link NlsString#getValue()} which could decode the string, however we rely on the cache there.
 *
 * @see RexLiteral#computeDigest(RexDigestIncludeType)
 * @param value value of the literal
 * @param type type of the literal
 * @return NO_TYPE when type can be omitted, ALWAYS otherwise
 */
private static RexDigestIncludeType shouldIncludeType(Comparable value, RelDataType type) {
  if (type.isNullable()) {
    // This means "null literal", so we require a type for it
    // There might be exceptions like AND(null, true) which are handled by RexCall#computeDigest
    return RexDigestIncludeType.ALWAYS;
  }
  // The variable here simplifies debugging (one can set a breakpoint at return)
  // final ensures we set the value in all the branches, and it ensures the value is set just once
  final RexDigestIncludeType includeType;
  if (type.getSqlTypeName() == SqlTypeName.BOOLEAN
      || type.getSqlTypeName() == SqlTypeName.INTEGER
      || type.getSqlTypeName() == SqlTypeName.SYMBOL) {
    // We don't want false:BOOLEAN NOT NULL, so we don't print type information for
    // non-nullable BOOLEAN and INTEGER
    includeType = RexDigestIncludeType.NO_TYPE;
  } else if (type.getSqlTypeName() == SqlTypeName.CHAR
          && value instanceof NlsString) {
    NlsString nlsString = (NlsString) value;

    // Ignore type information for 'Bar':CHAR(3)
    if ((
        (nlsString.getCharset() != null && type.getCharset().equals(nlsString.getCharset()))
        || (nlsString.getCharset() == null
        && SqlCollation.IMPLICIT.getCharset().equals(type.getCharset())))
        && nlsString.getCollation().equals(type.getCollation())
        && ((NlsString) value).getValue().length() == type.getPrecision()) {
      includeType = RexDigestIncludeType.NO_TYPE;
    } else {
      includeType = RexDigestIncludeType.ALWAYS;
    }
  } else if (type.getPrecision() == 0 && (
             type.getSqlTypeName() == SqlTypeName.TIME
          || type.getSqlTypeName() == SqlTypeName.TIMESTAMP
          || type.getSqlTypeName() == SqlTypeName.DATE)) {
    // Ignore type information for '12:23:20':TIME(0)
    // Note that '12:23:20':TIME WITH LOCAL TIME ZONE
    includeType = RexDigestIncludeType.NO_TYPE;
  } else {
    includeType = RexDigestIncludeType.ALWAYS;
  }
  return includeType;
}
 
Example 18
Source File: StandardConvertletTable.java    From Bats with Apache License 2.0 4 votes vote down vote up
public RexNode convertCall(SqlRexContext cx, SqlCall call) {
  // TIMESTAMPDIFF(unit, t1, t2)
  //    => (t2 - t1) UNIT
  final RexBuilder rexBuilder = cx.getRexBuilder();
  final SqlLiteral unitLiteral = call.operand(0);
  TimeUnit unit = unitLiteral.symbolValue(TimeUnit.class);
  BigDecimal multiplier = BigDecimal.ONE;
  BigDecimal divider = BigDecimal.ONE;
  SqlTypeName sqlTypeName = unit == TimeUnit.NANOSECOND
      ? SqlTypeName.BIGINT
      : SqlTypeName.INTEGER;
  switch (unit) {
  case MICROSECOND:
  case MILLISECOND:
  case NANOSECOND:
  case WEEK:
    multiplier = BigDecimal.valueOf(DateTimeUtils.MILLIS_PER_SECOND);
    divider = unit.multiplier;
    unit = TimeUnit.SECOND;
    break;
  case QUARTER:
    divider = unit.multiplier;
    unit = TimeUnit.MONTH;
    break;
  }
  final SqlIntervalQualifier qualifier =
      new SqlIntervalQualifier(unit, null, SqlParserPos.ZERO);
  final RexNode op2 = cx.convertExpression(call.operand(2));
  final RexNode op1 = cx.convertExpression(call.operand(1));
  final RelDataType intervalType =
      cx.getTypeFactory().createTypeWithNullability(
          cx.getTypeFactory().createSqlIntervalType(qualifier),
          op1.getType().isNullable() || op2.getType().isNullable());
  final RexCall rexCall = (RexCall) rexBuilder.makeCall(
      intervalType, SqlStdOperatorTable.MINUS_DATE,
      ImmutableList.of(op2, op1));
  final RelDataType intType =
      cx.getTypeFactory().createTypeWithNullability(
          cx.getTypeFactory().createSqlType(sqlTypeName),
          SqlTypeUtil.containsNullable(rexCall.getType()));
  RexNode e = rexBuilder.makeCast(intType, rexCall);
  return rexBuilder.multiplyDivide(e, multiplier, divider);
}