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

The following examples show how to use org.apache.calcite.sql.type.SqlTypeName#DATE . 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: DruidSqlCastConverter.java    From calcite with Apache License 2.0 7 votes vote down vote up
public static String dateTimeFormatString(final SqlTypeName sqlTypeName) {
  if (sqlTypeName == SqlTypeName.DATE) {
    return "yyyy-MM-dd";
  } else if (sqlTypeName == SqlTypeName.TIMESTAMP) {
    return "yyyy-MM-dd HH:mm:ss";
  } else if (sqlTypeName == SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE) {
    return "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
  } else {
    return null;
  }
}
 
Example 2
Source File: DruidJsonFilter.java    From calcite with Apache License 2.0 6 votes vote down vote up
/**
 * @param rexNode    rexNode to translate to Druid literal equivalante
 * @param rowType    rowType associated to rexNode
 * @param druidQuery druid Query
 *
 * @return non null string or null if it can not translate to valid Druid equivalent
 */
@Nullable
private static String toDruidLiteral(RexNode rexNode, RelDataType rowType,
    DruidQuery druidQuery) {
  final String val;
  final RexLiteral rhsLiteral = (RexLiteral) rexNode;
  if (SqlTypeName.NUMERIC_TYPES.contains(rhsLiteral.getTypeName())) {
    val = String.valueOf(RexLiteral.value(rhsLiteral));
  } else if (SqlTypeName.CHAR_TYPES.contains(rhsLiteral.getTypeName())) {
    val = String.valueOf(RexLiteral.stringValue(rhsLiteral));
  } else if (SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE == rhsLiteral.getTypeName()
      || SqlTypeName.TIMESTAMP == rhsLiteral.getTypeName()
      || SqlTypeName.DATE == rhsLiteral.getTypeName()) {
    Long millisSinceEpoch = DruidDateTimeUtils.literalValue(rexNode);
    if (millisSinceEpoch == null) {
      throw new AssertionError(
          "Cannot translate Literal" + rexNode + " of type "
              + rhsLiteral.getTypeName() + " to TimestampString");
    }
    val = DATE_FORMATTER.format(millisSinceEpoch);
  } else {
    // Don't know how to filter on this kind of literal.
    val = null;
  }
  return val;
}
 
Example 3
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 4
Source File: OperatorUtils.java    From attic-apex-malhar with Apache License 2.0 5 votes vote down vote up
/**
 * This method gives field name for POJO class for given {@link RelDataTypeField} object.
 *
 * @param field field object that needs to be converted to POJO class field name
 * @return Return field name from POJO class
 */
public static String getFieldName(RelDataTypeField field)
{
  SqlTypeName sqlTypeName = field.getType().getSqlTypeName();
  String name = getValidFieldName(field);

  name = (sqlTypeName == SqlTypeName.TIMESTAMP) ?
    (name + "Ms") :
    ((sqlTypeName == SqlTypeName.DATE) ? (name + "Sec") : name);

  return name;
}
 
Example 5
Source File: DruidSqlCastConverter.java    From calcite with Apache License 2.0 5 votes vote down vote up
private static String castCharToDateTime(
    TimeZone timeZone,
    String operand,
    final SqlTypeName toType, String format) {
  // Cast strings to date times by parsing them from SQL format.
  final String timestampExpression = DruidExpressions.functionCall(
      "timestamp_parse",
      ImmutableList.of(
          operand,
          DruidExpressions.stringLiteral(format),
          DruidExpressions.stringLiteral(timeZone.getID())));

  if (toType == SqlTypeName.DATE) {
    // case to date we need to floor to day first
    return DruidExpressions.applyTimestampFloor(
        timestampExpression,
        Period.days(1).toString(),
        "",
        timeZone);
  } else if (toType == SqlTypeName.TIMESTAMP
      || toType == SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE) {
    return timestampExpression;
  } else {
    throw new IllegalStateException(
        DruidQuery.format("Unsupported DateTime type[%s]", toType));
  }
}
 
Example 6
Source File: DruidQuery.java    From calcite with Apache License 2.0 5 votes vote down vote up
/** Check if it is needed to use UTC for DATE and TIMESTAMP types. **/
private static boolean needUtcTimeExtract(RexNode rexNode) {
  return rexNode.getType().getSqlTypeName() == SqlTypeName.DATE
      || rexNode.getType().getSqlTypeName() == SqlTypeName.TIMESTAMP
      || rexNode.getType().getSqlTypeName()
      == SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE;
}
 
Example 7
Source File: DruidDateTimeUtils.java    From calcite with Apache License 2.0 5 votes vote down vote up
/**
 * Infers granularity from a time unit.
 * It supports {@code FLOOR(<time> TO <timeunit>)}
 * and {@code EXTRACT(<timeunit> FROM <time>)}.
 * Returns null if it cannot be inferred.
 *
 * @param node the Rex node
 * @return the granularity, or null if it cannot be inferred
 */
@Nullable
public static Granularity extractGranularity(RexNode node, String timeZone) {
  final int valueIndex;
  final int flagIndex;

  if (TimeExtractionFunction.isValidTimeExtract(node)) {
    flagIndex = 0;
    valueIndex = 1;
  } else if (TimeExtractionFunction.isValidTimeFloor(node)) {
    valueIndex = 0;
    flagIndex = 1;
  } else {
    // We can only infer granularity from floor and extract.
    return null;
  }
  final RexCall call = (RexCall) node;
  final RexNode value = call.operands.get(valueIndex);
  final RexLiteral flag = (RexLiteral) call.operands.get(flagIndex);
  final TimeUnitRange timeUnit = (TimeUnitRange) flag.getValue();

  final RelDataType valueType = value.getType();
  if (valueType.getSqlTypeName() == SqlTypeName.DATE
      || valueType.getSqlTypeName() == SqlTypeName.TIMESTAMP) {
    // We use 'UTC' for date/timestamp type as Druid needs timezone information
    return Granularities.createGranularity(timeUnit, "UTC");
  } else if (valueType.getSqlTypeName() == SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE) {
    return Granularities.createGranularity(timeUnit, timeZone);
  }
  // Type not recognized
  return null;
}
 
Example 8
Source File: SqlDateLiteral.java    From Bats with Apache License 2.0 4 votes vote down vote up
SqlDateLiteral(DateString d, SqlParserPos pos) {
  super(d, false, SqlTypeName.DATE, 0, pos);
}
 
Example 9
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 10
Source File: DruidExpressions.java    From calcite with Apache License 2.0 4 votes vote down vote up
/**
 * Translates Calcite rexNode to Druid Expression when possible
 * @param rexNode rexNode to convert to a Druid Expression
 * @param inputRowType input row type of the rexNode to translate
 * @param druidRel Druid query
 *
 * @return Druid Expression or null when can not convert the RexNode
 */
@Nullable
public static String toDruidExpression(
    final RexNode rexNode,
    final RelDataType inputRowType,
    final DruidQuery druidRel) {
  SqlKind kind = rexNode.getKind();
  SqlTypeName sqlTypeName = rexNode.getType().getSqlTypeName();

  if (kind == SqlKind.INPUT_REF) {
    final RexInputRef ref = (RexInputRef) rexNode;
    final String columnName = inputRowType.getFieldNames().get(ref.getIndex());
    if (columnName == null) {
      return null;
    }
    if (druidRel.getDruidTable().timestampFieldName.equals(columnName)) {
      return DruidExpressions.fromColumn(DruidTable.DEFAULT_TIMESTAMP_COLUMN);
    }
    return DruidExpressions.fromColumn(columnName);
  }

  if (rexNode instanceof RexCall) {
    final SqlOperator operator = ((RexCall) rexNode).getOperator();
    final DruidSqlOperatorConverter conversion = druidRel.getOperatorConversionMap()
        .get(operator);
    if (conversion == null) {
      //unknown operator can not translate
      return null;
    } else {
      return conversion.toDruidExpression(rexNode, inputRowType, druidRel);
    }
  }
  if (kind == SqlKind.LITERAL) {
    // Translate literal.
    if (RexLiteral.isNullLiteral(rexNode)) {
      //case the filter/project might yield to unknown let Calcite deal with this for now
      return null;
    } else if (SqlTypeName.NUMERIC_TYPES.contains(sqlTypeName)) {
      return DruidExpressions.numberLiteral((Number) RexLiteral
          .value(rexNode));
    } else if (SqlTypeFamily.INTERVAL_DAY_TIME == sqlTypeName.getFamily()) {
      // Calcite represents DAY-TIME intervals in milliseconds.
      final long milliseconds = ((Number) RexLiteral.value(rexNode)).longValue();
      return DruidExpressions.numberLiteral(milliseconds);
    } else if (SqlTypeFamily.INTERVAL_YEAR_MONTH == sqlTypeName.getFamily()) {
      // Calcite represents YEAR-MONTH intervals in months.
      final long months = ((Number) RexLiteral.value(rexNode)).longValue();
      return DruidExpressions.numberLiteral(months);
    } else if (SqlTypeName.STRING_TYPES.contains(sqlTypeName)) {
      return
          DruidExpressions.stringLiteral(RexLiteral.stringValue(rexNode));
    } else if (SqlTypeName.DATE == sqlTypeName
        || SqlTypeName.TIMESTAMP == sqlTypeName
        || SqlTypeName.TIME_WITH_LOCAL_TIME_ZONE == sqlTypeName) {
      return DruidExpressions.numberLiteral(
          DruidDateTimeUtils.literalValue(rexNode));
    } else if (SqlTypeName.BOOLEAN == sqlTypeName) {
      return DruidExpressions.numberLiteral(RexLiteral.booleanValue(rexNode) ? 1 : 0);
    }
  }
  // Not Literal/InputRef/RexCall or unknown type?
  return null;
}
 
Example 11
Source File: DruidQuery.java    From calcite with Apache License 2.0 4 votes vote down vote up
/**
 * @param rexNode    leaf Input Ref to Druid Column
 * @param rowType    row type
 * @param druidQuery druid query
 *
 * @return {@link Pair} of Column name and Extraction Function on the top of the input ref or
 * {@link Pair of(null, null)} when can not translate to valid Druid column
 */
protected static Pair<String, ExtractionFunction> toDruidColumn(RexNode rexNode,
    RelDataType rowType, DruidQuery druidQuery) {
  final String columnName;
  final ExtractionFunction extractionFunction;
  final Granularity granularity;
  switch (rexNode.getKind()) {
  case INPUT_REF:
    columnName = extractColumnName(rexNode, rowType, druidQuery);
    if (needUtcTimeExtract(rexNode)) {
      extractionFunction = TimeExtractionFunction.createDefault(
          DateTimeUtils.UTC_ZONE.getID());
    } else {
      extractionFunction = null;
    }
    break;
  case EXTRACT:
    granularity = DruidDateTimeUtils
        .extractGranularity(rexNode, druidQuery.getConnectionConfig().timeZone());
    if (granularity == null) {
      // unknown Granularity
      return Pair.of(null, null);
    }
    if (!TimeExtractionFunction.isValidTimeExtract((RexCall) rexNode)) {
      return Pair.of(null, null);
    }
    RexNode extractValueNode = ((RexCall) rexNode).getOperands().get(1);
    if (extractValueNode.getType().getSqlTypeName() == SqlTypeName.DATE
        || extractValueNode.getType().getSqlTypeName() == SqlTypeName.TIMESTAMP) {
      // Use 'UTC' at the extraction level
      extractionFunction =
          TimeExtractionFunction.createExtractFromGranularity(
              granularity, DateTimeUtils.UTC_ZONE.getID());
      columnName = extractColumnName(extractValueNode, rowType, druidQuery);
    } else if (extractValueNode.getType().getSqlTypeName()
        == SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE) {
      // Use local time zone at the extraction level
      extractionFunction =
        TimeExtractionFunction.createExtractFromGranularity(
            granularity, druidQuery.getConnectionConfig().timeZone());
      columnName = extractColumnName(extractValueNode, rowType, druidQuery);
    } else {
      return Pair.of(null, null);
    }
    break;
  case FLOOR:
    granularity = DruidDateTimeUtils
        .extractGranularity(rexNode, druidQuery.getConnectionConfig().timeZone());
    if (granularity == null) {
      // unknown Granularity
      return Pair.of(null, null);
    }
    if (!TimeExtractionFunction.isValidTimeFloor((RexCall) rexNode)) {
      return Pair.of(null, null);
    }
    RexNode floorValueNode = ((RexCall) rexNode).getOperands().get(0);
    if (needUtcTimeExtract(floorValueNode)) {
      // Use 'UTC' at the extraction level, since all datetime types
      // are represented in 'UTC'
      extractionFunction =
          TimeExtractionFunction.createFloorFromGranularity(
              granularity, DateTimeUtils.UTC_ZONE.getID());
      columnName = extractColumnName(floorValueNode, rowType, druidQuery);
    } else {
      return Pair.of(null, null);
    }
    break;
  case CAST:
    // CASE we have a cast over InputRef. Check that cast is valid
    if (!isValidLeafCast(rexNode)) {
      return Pair.of(null, null);
    }
    RexNode operand0 = ((RexCall) rexNode).getOperands().get(0);
    columnName =
        extractColumnName(operand0, rowType, druidQuery);
    if (needUtcTimeExtract(rexNode)) {
      // CASE CAST to TIME/DATE need to make sure that we have valid extraction fn
      extractionFunction = TimeExtractionFunction.translateCastToTimeExtract(rexNode,
          TimeZone.getTimeZone(druidQuery.getConnectionConfig().timeZone()));
      if (extractionFunction == null) {
        // no extraction Function means cast is not valid thus bail out
        return Pair.of(null, null);
      }
    } else {
      extractionFunction = null;
    }
    break;
  default:
    return Pair.of(null, null);
  }
  return Pair.of(columnName, extractionFunction);
}
 
Example 12
Source File: RexImpTable.java    From calcite with Apache License 2.0 4 votes vote down vote up
@Override Expression implementSafe(final RexToLixTranslator translator,
    final RexCall call, final List<Expression> argValueList) {
  final RexNode operand0 = call.getOperands().get(0);
  Expression trop0 = argValueList.get(0);
  final SqlTypeName typeName1 =
      call.getOperands().get(1).getType().getSqlTypeName();
  Expression trop1 = argValueList.get(1);
  final SqlTypeName typeName = call.getType().getSqlTypeName();
  switch (operand0.getType().getSqlTypeName()) {
  case DATE:
    switch (typeName) {
    case TIMESTAMP:
      trop0 = Expressions.convert_(
          Expressions.multiply(trop0,
              Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)),
          long.class);
      break;
    default:
      switch (typeName1) {
      case INTERVAL_DAY:
      case INTERVAL_DAY_HOUR:
      case INTERVAL_DAY_MINUTE:
      case INTERVAL_DAY_SECOND:
      case INTERVAL_HOUR:
      case INTERVAL_HOUR_MINUTE:
      case INTERVAL_HOUR_SECOND:
      case INTERVAL_MINUTE:
      case INTERVAL_MINUTE_SECOND:
      case INTERVAL_SECOND:
        trop1 = Expressions.convert_(
            Expressions.divide(trop1,
                Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)),
            int.class);
      }
    }
    break;
  case TIME:
    trop1 = Expressions.convert_(trop1, int.class);
    break;
  }
  switch (typeName1) {
  case INTERVAL_YEAR:
  case INTERVAL_YEAR_MONTH:
  case INTERVAL_MONTH:
    switch (call.getKind()) {
    case MINUS:
      trop1 = Expressions.negate(trop1);
    }
    switch (typeName) {
    case TIME:
      return Expressions.convert_(trop0, long.class);
    default:
      final BuiltInMethod method =
          operand0.getType().getSqlTypeName() == SqlTypeName.TIMESTAMP
              ? BuiltInMethod.ADD_MONTHS
              : BuiltInMethod.ADD_MONTHS_INT;
      return Expressions.call(method.method, trop0, trop1);
    }

  case INTERVAL_DAY:
  case INTERVAL_DAY_HOUR:
  case INTERVAL_DAY_MINUTE:
  case INTERVAL_DAY_SECOND:
  case INTERVAL_HOUR:
  case INTERVAL_HOUR_MINUTE:
  case INTERVAL_HOUR_SECOND:
  case INTERVAL_MINUTE:
  case INTERVAL_MINUTE_SECOND:
  case INTERVAL_SECOND:
    switch (call.getKind()) {
    case MINUS:
      return normalize(typeName, Expressions.subtract(trop0, trop1));
    default:
      return normalize(typeName, Expressions.add(trop0, trop1));
    }

  default:
    switch (call.getKind()) {
    case MINUS:
      switch (typeName) {
      case INTERVAL_YEAR:
      case INTERVAL_YEAR_MONTH:
      case INTERVAL_MONTH:
        return Expressions.call(BuiltInMethod.SUBTRACT_MONTHS.method,
            trop0, trop1);
      }
      TimeUnit fromUnit =
          typeName1 == SqlTypeName.DATE ? TimeUnit.DAY : TimeUnit.MILLISECOND;
      TimeUnit toUnit = TimeUnit.MILLISECOND;
      return multiplyDivide(
          Expressions.convert_(Expressions.subtract(trop0, trop1),
              (Class) long.class),
          fromUnit.multiplier, toUnit.multiplier);
    default:
      throw new AssertionError(call);
    }
  }
}
 
Example 13
Source File: SqlDateLiteral.java    From calcite with Apache License 2.0 4 votes vote down vote up
SqlDateLiteral(DateString d, SqlParserPos pos) {
  super(d, false, SqlTypeName.DATE, 0, pos);
}
 
Example 14
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;
}