protected RexNode convert(ExprNodeConstantDesc literal) throws CalciteSemanticException {
    final RelDataTypeFactory dtFactory = rexBuilder.getTypeFactory();
    final PrimitiveTypeInfo hiveType = (PrimitiveTypeInfo) literal.getTypeInfo();
    final RelDataType calciteDataType = TypeConverter.convert(hiveType, dtFactory);

    PrimitiveCategory hiveTypeCategory = hiveType.getPrimitiveCategory();

    ConstantObjectInspector coi = literal.getWritableObjectInspector();
    Object value = ObjectInspectorUtils.copyToStandardJavaObject(coi.getWritableConstantValue(),
        coi);

    RexNode calciteLiteral = null;
    // If value is null, the type should also be VOID.
    if (value == null) {
      hiveTypeCategory = PrimitiveCategory.VOID;
    }
    // TODO: Verify if we need to use ConstantObjectInspector to unwrap data
    switch (hiveTypeCategory) {
    case BOOLEAN:
      calciteLiteral = rexBuilder.makeLiteral(((Boolean) value).booleanValue());
      break;
    case BYTE:
      calciteLiteral = rexBuilder.makeExactLiteral(new BigDecimal((Byte) value), calciteDataType);
      break;
    case SHORT:
      calciteLiteral = rexBuilder.makeExactLiteral(new BigDecimal((Short) value), calciteDataType);
      break;
    case INT:
      calciteLiteral = rexBuilder.makeExactLiteral(new BigDecimal((Integer) value));
      break;
    case LONG:
      calciteLiteral = rexBuilder.makeBigintLiteral(new BigDecimal((Long) value));
      break;
    case DECIMAL:
      if (value instanceof HiveDecimal) {
        value = ((HiveDecimal) value).bigDecimalValue();
      } else if (value instanceof Decimal128) {
        value = ((Decimal128) value).toBigDecimal();
      }
      if (value == null) {
        // We have found an invalid decimal value while enforcing precision and
        // scale. Ideally,
        // we would replace it with null here, which is what Hive does. However,
        // we need to plumb
        // this thru up somehow, because otherwise having different expression
        // type in AST causes
        // the plan generation to fail after CBO, probably due to some residual
        // state in SA/QB.
        // For now, we will not run CBO in the presence of invalid decimal
        // literals.
        throw new CalciteSemanticException("Expression " + literal.getExprString()
            + " is not a valid decimal", UnsupportedFeature.Invalid_decimal);
        // TODO: return createNullLiteral(literal);
      }
      calciteLiteral = rexBuilder.makeExactLiteral((BigDecimal) value, calciteDataType);
      break;
    case FLOAT:
      calciteLiteral = rexBuilder.makeApproxLiteral(
          new BigDecimal(Float.toString((Float)value)), calciteDataType);
      break;
    case DOUBLE:
      // TODO: The best solution is to support NaN in expression reduction.
      if (Double.isNaN((Double) value)) {
        throw new CalciteSemanticException("NaN", UnsupportedFeature.Invalid_decimal);
      }
      calciteLiteral = rexBuilder.makeApproxLiteral(
          new BigDecimal(Double.toString((Double)value)), calciteDataType);
      break;
    case CHAR:
      if (value instanceof HiveChar) {
        value = ((HiveChar) value).getValue();
      }
      final int lengthChar = TypeInfoUtils.getCharacterLengthForType(hiveType);
      RelDataType charType = rexBuilder.getTypeFactory().createTypeWithCharsetAndCollation(
          rexBuilder.getTypeFactory().createSqlType(SqlTypeName.CHAR, lengthChar),
          Charset.forName(ConversionUtil.NATIVE_UTF16_CHARSET_NAME), SqlCollation.IMPLICIT);
      calciteLiteral = rexBuilder.makeLiteral(
          RexNodeExprFactory.makeHiveUnicodeString((String) value), charType, false);
      break;
    case VARCHAR:
      if (value instanceof HiveVarchar) {
        value = ((HiveVarchar) value).getValue();
      }
      final int lengthVarchar = TypeInfoUtils.getCharacterLengthForType(hiveType);
      RelDataType varcharType = rexBuilder.getTypeFactory().createTypeWithCharsetAndCollation(
          rexBuilder.getTypeFactory().createSqlType(SqlTypeName.VARCHAR, lengthVarchar),
          Charset.forName(ConversionUtil.NATIVE_UTF16_CHARSET_NAME), SqlCollation.IMPLICIT);
      calciteLiteral = rexBuilder.makeLiteral(
          RexNodeExprFactory.makeHiveUnicodeString((String) value), varcharType, true);
      break;
    case STRING:
      RelDataType stringType = rexBuilder.getTypeFactory().createTypeWithCharsetAndCollation(
          rexBuilder.getTypeFactory().createSqlType(SqlTypeName.VARCHAR, Integer.MAX_VALUE),
          Charset.forName(ConversionUtil.NATIVE_UTF16_CHARSET_NAME), SqlCollation.IMPLICIT);
      calciteLiteral = rexBuilder.makeLiteral(
          RexNodeExprFactory.makeHiveUnicodeString((String) value), stringType, true);
      break;
    case DATE:
      final Date date = (Date) value;
      calciteLiteral = rexBuilder.makeDateLiteral(
          DateString.fromDaysSinceEpoch(date.toEpochDay()));
      break;
    case TIMESTAMP:
      final TimestampString tsString;
      if (value instanceof Calendar) {
        tsString = TimestampString.fromCalendarFields((Calendar) value);
      } else {
        final Timestamp ts = (Timestamp) value;
        tsString = TimestampString.fromMillisSinceEpoch(ts.toEpochMilli()).withNanos(ts.getNanos());
      }
      // Must call makeLiteral, not makeTimestampLiteral
      // to have the RexBuilder.roundTime logic kick in
      calciteLiteral = rexBuilder.makeLiteral(
          tsString,
          rexBuilder.getTypeFactory().createSqlType(
              SqlTypeName.TIMESTAMP,
              rexBuilder.getTypeFactory().getTypeSystem().getDefaultPrecision(SqlTypeName.TIMESTAMP)),
          false);
      break;
    case TIMESTAMPLOCALTZ:
      final TimestampString tsLocalTZString;
      Instant i = ((TimestampTZ)value).getZonedDateTime().toInstant();
      tsLocalTZString = TimestampString
          .fromMillisSinceEpoch(i.toEpochMilli())
          .withNanos(i.getNano());
      calciteLiteral = rexBuilder.makeTimestampWithLocalTimeZoneLiteral(
          tsLocalTZString,
          rexBuilder.getTypeFactory().getTypeSystem().getDefaultPrecision(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE));
      break;
    case INTERVAL_YEAR_MONTH:
      // Calcite year-month literal value is months as BigDecimal
      BigDecimal totalMonths = BigDecimal.valueOf(((HiveIntervalYearMonth) value).getTotalMonths());
      calciteLiteral = rexBuilder.makeIntervalLiteral(totalMonths,
          new SqlIntervalQualifier(TimeUnit.YEAR, TimeUnit.MONTH, new SqlParserPos(1, 1)));
      break;
    case INTERVAL_DAY_TIME:
      // Calcite day-time interval is millis value as BigDecimal
      // Seconds converted to millis
      BigDecimal secsValueBd = BigDecimal
          .valueOf(((HiveIntervalDayTime) value).getTotalSeconds() * 1000);
      // Nanos converted to millis
      BigDecimal nanosValueBd = BigDecimal.valueOf(((HiveIntervalDayTime)
          value).getNanos(), 6);
      calciteLiteral =
          rexBuilder.makeIntervalLiteral(secsValueBd.add(nanosValueBd),
              new SqlIntervalQualifier(TimeUnit.MILLISECOND, null, new
                  SqlParserPos(1, 1)));
      break;
    case VOID:
      calciteLiteral = rexBuilder.makeLiteral(null, calciteDataType, true);
      break;
    case BINARY:
    case UNKNOWN:
    default:
      throw new RuntimeException("Unsupported Literal");
    }

    return calciteLiteral;
  }
The method tries to rewrite an the operands of an IN function call into
the operands for an OR function call.
For instance:
<pre>
(c) IN ( v1, v2, ...) =&gt; c=v1 || c=v2 || ...
Input: (c, v1, v2, ...)
Output: (c=v1, c=v2, ...)
</pre>
Or:
<pre>
(c,d) IN ( (v1,v2), (v3,v4), ...) =&gt; (c=v1 &amp;&amp; d=v2) || (c=v3 &amp;&amp; d=v4) || ...
Input: ((c,d), (v1,v2), (v3,v4), ...)
Output: (c=v1 &amp;&amp; d=v2, c=v3 &amp;&amp; d=v4, ...)
</pre>

Returns null if the transformation fails, e.g., when non-deterministic
calls are found in the expressions.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java