@Test
 public void testConvertNull() throws Exception {
   SyntheticField field = mock(SyntheticField.class);
   when(field.getType()).thenReturn((Class) SimpleBaseDomain.class);
   String[] tags = new String[] {"a", "b", "c"};
   assertThat(typeConverter.convert(null, field, null, tags)).isNull();
 }
Пример #2
0
  @Test
  public void lambdaScope() throws Exception {

    final int num1 = 1; // final
    TypeConverter<String, Integer> converter = (f) -> Integer.valueOf(f) + num1;
    final Integer r1 = converter.convert("5");
    assert r1 == 6;

    final int num2 = 1; // implicit final
    TypeConverter<String, Integer> converter2 = (f) -> Integer.valueOf(f) + num2;
    final Integer r2 = converter2.convert("5");
    assert r2 == 6;

    // num2 += 2; compile error

  }
Пример #3
0
 @Test
 public void functionalInterface() throws Exception {
   //        TypeConverter<String, Integer> converter = (from) -> Integer.valueOf(from); // Case 1
   TypeConverter<String, Integer> converter = Integer::valueOf; // Case 2
   final Integer v = converter.convert("123");
   assert v == 123;
 }
  @Test
  public void testConvert() throws Exception {
    SimpleBaseTo source = new SimpleBaseTo();
    SyntheticField field = mock(SyntheticField.class);
    when(field.getType()).thenReturn((Class) SimpleBaseDomain.class);
    String[] tags = new String[] {"a", "b", "c"};
    typeConverter.convert(source, field, null, tags);

    verify(jTransfo).convertTo(source, SimpleBaseDomain.class, tags);
  }
Пример #5
0
 /** Convert para to special type and keep it */
 public Controller keepPara(Class type, String name) {
   String[] values = request.getParameterValues(name);
   if (values != null) {
     if (values.length == 1)
       try {
         request.setAttribute(name, TypeConverter.convert(type, values[0]));
       } catch (ParseException e) {
       }
     else request.setAttribute(name, values);
   }
   return this;
 }
Пример #6
0
  private RexNode handleExplicitCast(ExprNodeGenericFuncDesc func, List<RexNode> childRexNodeLst)
      throws CalciteSemanticException {
    RexNode castExpr = null;

    if (childRexNodeLst != null && childRexNodeLst.size() == 1) {
      GenericUDF udf = func.getGenericUDF();
      if ((udf instanceof GenericUDFToChar)
          || (udf instanceof GenericUDFToVarchar)
          || (udf instanceof GenericUDFToDecimal)
          || (udf instanceof GenericUDFToDate)
          || (udf instanceof GenericUDFToBinary)
          || castExprUsingUDFBridge(udf)) {
        castExpr =
            cluster
                .getRexBuilder()
                .makeAbstractCast(
                    TypeConverter.convert(func.getTypeInfo(), cluster.getTypeFactory()),
                    childRexNodeLst.get(0));
      }
    }

    return castExpr;
  }
Пример #7
0
 private RexNode createNullLiteral(ExprNodeDesc expr) throws CalciteSemanticException {
   return cluster
       .getRexBuilder()
       .makeNullLiteral(
           TypeConverter.convert(expr.getTypeInfo(), cluster.getTypeFactory()).getSqlTypeName());
 }
Пример #8
0
  protected RexNode convert(ExprNodeConstantDesc literal) throws CalciteSemanticException {
    RexBuilder rexBuilder = cluster.getRexBuilder();
    RelDataTypeFactory dtFactory = rexBuilder.getTypeFactory();
    PrimitiveTypeInfo hiveType = (PrimitiveTypeInfo) literal.getTypeInfo();
    RelDataType calciteDataType = TypeConverter.convert(hiveType, dtFactory);

    PrimitiveCategory hiveTypeCategory = hiveType.getPrimitiveCategory();

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

    RexNode calciteLiteral = null;
    // 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;
        // TODO: is Decimal an exact numeric or approximate numeric?
      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);
        }
        BigDecimal bd = (BigDecimal) value;
        BigInteger unscaled = bd.unscaledValue();
        if (unscaled.compareTo(MIN_LONG_BI) >= 0 && unscaled.compareTo(MAX_LONG_BI) <= 0) {
          calciteLiteral = rexBuilder.makeExactLiteral(bd);
        } else {
          // CBO doesn't support unlimited precision decimals. In practice, this
          // will work...
          // An alternative would be to throw CboSemanticException and fall back
          // to no CBO.
          RelDataType relType =
              cluster
                  .getTypeFactory()
                  .createSqlType(SqlTypeName.DECIMAL, bd.scale(), unscaled.toString().length());
          calciteLiteral = rexBuilder.makeExactLiteral(bd, relType);
        }
        break;
      case FLOAT:
        calciteLiteral =
            rexBuilder.makeApproxLiteral(new BigDecimal((Float) value), calciteDataType);
        break;
      case DOUBLE:
        calciteLiteral =
            rexBuilder.makeApproxLiteral(new BigDecimal((Double) value), calciteDataType);
        break;
      case CHAR:
        if (value instanceof HiveChar) {
          value = ((HiveChar) value).getValue();
        }
        calciteLiteral = rexBuilder.makeCharLiteral(asUnicodeString((String) value));
        break;
      case VARCHAR:
        if (value instanceof HiveVarchar) {
          value = ((HiveVarchar) value).getValue();
        }
        calciteLiteral = rexBuilder.makeCharLiteral(asUnicodeString((String) value));
        break;
      case STRING:
        calciteLiteral = rexBuilder.makeCharLiteral(asUnicodeString((String) value));
        break;
      case DATE:
        Calendar cal = new GregorianCalendar();
        cal.setTime((Date) value);
        calciteLiteral = rexBuilder.makeDateLiteral(cal);
        break;
      case TIMESTAMP:
        Calendar c = null;
        if (value instanceof Calendar) {
          c = (Calendar) value;
        } else {
          c = Calendar.getInstance();
          c.setTimeInMillis(((Timestamp) value).getTime());
        }
        calciteLiteral = rexBuilder.makeTimestampLiteral(c, RelDataType.PRECISION_NOT_SPECIFIED);
        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.DAY, TimeUnit.SECOND, new SqlParserPos(1, 1)));
        break;
      case VOID:
        calciteLiteral =
            cluster
                .getRexBuilder()
                .makeLiteral(null, cluster.getTypeFactory().createSqlType(SqlTypeName.NULL), true);
        break;
      case BINARY:
      case UNKNOWN:
      default:
        throw new RuntimeException("UnSupported Literal");
    }

    return calciteLiteral;
  }
Пример #9
0
  private RexNode convert(final ExprNodeGenericFuncDesc func) throws SemanticException {
    ExprNodeDesc tmpExprNode;
    RexNode tmpRN;

    List<RexNode> childRexNodeLst = new LinkedList<RexNode>();
    Builder<RelDataType> argTypeBldr = ImmutableList.<RelDataType>builder();

    // TODO: 1) Expand to other functions as needed 2) What about types other than primitive.
    TypeInfo tgtDT = null;
    GenericUDF tgtUdf = func.getGenericUDF();

    boolean isNumeric =
        (tgtUdf instanceof GenericUDFBaseBinary
            && func.getTypeInfo().getCategory() == Category.PRIMITIVE
            && (PrimitiveGrouping.NUMERIC_GROUP
                == PrimitiveObjectInspectorUtils.getPrimitiveGrouping(
                    ((PrimitiveTypeInfo) func.getTypeInfo()).getPrimitiveCategory())));
    boolean isCompare = !isNumeric && tgtUdf instanceof GenericUDFBaseCompare;

    if (isNumeric) {
      tgtDT = func.getTypeInfo();

      assert func.getChildren().size() == 2;
      // TODO: checking 2 children is useless, compare already does that.
    } else if (isCompare && (func.getChildren().size() == 2)) {
      tgtDT =
          FunctionRegistry.getCommonClassForComparison(
              func.getChildren().get(0).getTypeInfo(), func.getChildren().get(1).getTypeInfo());
    }

    for (ExprNodeDesc childExpr : func.getChildren()) {
      tmpExprNode = childExpr;
      if (tgtDT != null
          && TypeInfoUtils.isConversionRequiredForComparison(tgtDT, childExpr.getTypeInfo())) {
        if (isCompare) {
          // For compare, we will convert requisite children
          tmpExprNode = ParseUtils.createConversionCast(childExpr, (PrimitiveTypeInfo) tgtDT);
        } else if (isNumeric) {
          // For numeric, we'll do minimum necessary cast - if we cast to the type
          // of expression, bad things will happen.
          PrimitiveTypeInfo minArgType = ExprNodeDescUtils.deriveMinArgumentCast(childExpr, tgtDT);
          tmpExprNode = ParseUtils.createConversionCast(childExpr, minArgType);
        } else {
          throw new AssertionError("Unexpected " + tgtDT + " - not a numeric op or compare");
        }
      }
      argTypeBldr.add(TypeConverter.convert(tmpExprNode.getTypeInfo(), cluster.getTypeFactory()));
      tmpRN = convert(tmpExprNode);
      childRexNodeLst.add(tmpRN);
    }

    // See if this is an explicit cast.
    RexNode expr = null;
    RelDataType retType = null;
    expr = handleExplicitCast(func, childRexNodeLst);

    if (expr == null) {
      // This is not a cast; process the function.
      retType = TypeConverter.convert(func.getTypeInfo(), cluster.getTypeFactory());
      SqlOperator calciteOp =
          SqlFunctionConverter.getCalciteOperator(
              func.getFuncText(), func.getGenericUDF(), argTypeBldr.build(), retType);
      expr = cluster.getRexBuilder().makeCall(calciteOp, childRexNodeLst);
    } else {
      retType = expr.getType();
    }

    // TODO: Cast Function in Calcite have a bug where it infer type on cast throws
    // an exception
    if (flattenExpr
        && (expr instanceof RexCall)
        && !(((RexCall) expr).getOperator() instanceof SqlCastFunction)) {
      RexCall call = (RexCall) expr;
      expr =
          cluster
              .getRexBuilder()
              .makeCall(
                  retType,
                  call.getOperator(),
                  RexUtil.flatten(call.getOperands(), call.getOperator()));
    }

    return expr;
  }