Пример #1
0
 /**
  * Replaces the operands of a call. The new operands' types must match the old operands' types.
  */
 public static RexCall replaceOperands(RexCall call, RexNode[] operands) {
   if (call.operands == operands) {
     return call;
   }
   for (int i = 0; i < operands.length; i++) {
     RelDataType oldType = call.operands[i].getType();
     RelDataType newType = operands[i].getType();
     if (!oldType.isNullable() && newType.isNullable()) {
       throw Util.newInternal("invalid nullability");
     }
     assert (oldType.toString().equals(newType.toString()));
   }
   return new RexCall(call.getType(), call.getOperator(), operands);
 }
Пример #2
0
 public String getFieldTypeName(int fieldOrdinal) {
   RelDataType type = getFieldNamedType(fieldOrdinal);
   SqlTypeName typeName = type.getSqlTypeName();
   if (typeName == null) {
     return type.toString();
   }
   switch (typeName) {
     case STRUCTURED:
     case DISTINCT:
       return type.getSqlIdentifier().toString();
     case INTERVAL_DAY_TIME:
     case INTERVAL_YEAR_MONTH:
       return type.toString();
   }
   return typeName.name();
 }
Пример #3
0
 public static void checkCharsetAndCollateConsistentIfCharType(RelDataType type) {
   // (every charset must have a default collation)
   if (SqlTypeUtil.inCharFamily(type)) {
     Charset strCharset = type.getCharset();
     Charset colCharset = type.getCollation().getCharset();
     assert null != strCharset;
     assert null != colCharset;
     if (!strCharset.equals(colCharset)) {
       if (false) {
         // todo: enable this checking when we have a charset to
         //   collation mapping
         throw new Error(
             type.toString()
                 + " was found to have charset '"
                 + strCharset.name()
                 + "' and a mismatched collation charset '"
                 + colCharset.name()
                 + "'");
       }
     }
   }
 }
    private Expression castToAssignableValueImpl() {
      if (requiresSpecializedCast()) {
        if (rhsType.isNullable() && (!SqlTypeUtil.isDecimal(rhsType))) {
          rhsExp = getValue(rhsType, rhsExp);
        }
        addStatement(
            new ExpressionStatement(
                new MethodCall(
                    lhsExp,
                    "cast",
                    new ExpressionList(rhsExp, Literal.makeLiteral(lhsType.getPrecision())))));
      } else {
        // Set current_date for casting time to timestamp. If
        // rhsType is null then we may have to be ready for anything.
        // But it will be null even for current_timestamp, so the
        // condition below seems a bit excessive.
        if ((lhsType.getSqlTypeName() == SqlTypeName.TIMESTAMP)
            && ((rhsType == null) || (rhsType.getSqlTypeName() == SqlTypeName.TIME))) {
          addStatement(
              new ExpressionStatement(
                  new MethodCall(lhsExp, "setCurrentDate", new ExpressionList(getCurrentDate()))));
        }
        addStatement(
            new ExpressionStatement(
                new MethodCall(
                    lhsExp, AssignableValue.ASSIGNMENT_METHOD_NAME, new ExpressionList(rhsExp))));
      }

      // Trim precision of datetime values.
      //
      if (((lhsType.getSqlTypeName() == SqlTypeName.TIMESTAMP)
          || (lhsType.getSqlTypeName() == SqlTypeName.TIME))) {
        if ((rhsType != null)
            // FIXME: JavaType(java.sql.Time) and
            // JavaType(java.sql.Timestamp) say they support precision
            // but do not.
            && !rhsType.toString().startsWith("JavaType(")
            && rhsType.getSqlTypeName().allowsPrec()
            && (lhsType.getPrecision() < rhsType.getPrecision())) {
          int lhsPrecision = lhsType.getPrecision();
          if (lhsPrecision == -1) {
            lhsPrecision = 0;
          }
          addStatement(
              new ExpressionStatement(
                  new MethodCall(
                      lhsExp,
                      SqlDateTimeWithoutTZ.ADJUST_PRECISION_METHOD_NAME,
                      new ExpressionList(Literal.makeLiteral(lhsPrecision)))));
        }
      }

      boolean mayNeedPadOrTruncate = false;
      if (SqlTypeUtil.inCharOrBinaryFamilies(lhsType) && !SqlTypeUtil.isLob(lhsType)) {
        mayNeedPadOrTruncate = true;
      }
      if (mayNeedPadOrTruncate) {
        // check overflow if it is datetime.
        // TODO: should check it at the run time.
        // so, it should be in the
        // cast(SqlDateTimeWithTZ, int precision);
        if ((rhsType != null) && (rhsType.getSqlTypeName() != null)) {
          SqlTypeName typeName = rhsType.getSqlTypeName();
          int precision = 0;
          switch (typeName) {
            case DATE:
              precision = 10;
              break;
            case TIME:
              precision = 8;
              break;
            case TIMESTAMP:
              precision = 19;
              break;
          }
          if ((precision != 0) && (precision > lhsType.getPrecision())) {
            addStatement(
                new IfStatement(
                    new BinaryExpression(
                        Literal.makeLiteral(precision),
                        BinaryExpression.GREATER,
                        Literal.makeLiteral(lhsType.getPrecision())),
                    getThrowStmtList()));
          }
        }
        if ((rhsType != null)
            && (rhsType.getFamily() == lhsType.getFamily())
            && !SqlTypeUtil.isLob(rhsType)) {
          // we may be able to skip pad/truncate based on
          // known facts about source and target precisions
          if (SqlTypeUtil.isBoundedVariableWidth(lhsType)) {
            if (lhsType.getPrecision() >= rhsType.getPrecision()) {
              // target precision is greater than source
              // precision, so truncation is impossible
              // and we can skip adjustment
              return lhsExp;
            }
          } else {
            if ((lhsType.getPrecision() == rhsType.getPrecision())
                && !SqlTypeUtil.isBoundedVariableWidth(rhsType)) {
              // source and target are both fixed-width, and
              // precisions are the same, so there's no adjustment
              // needed
              return lhsExp;
            }
          }
        }

        // determine target precision
        Expression precisionExp = Literal.makeLiteral(lhsType.getPrecision());

        // need to pad only for fixed width
        Expression needPadExp = Literal.makeLiteral(!SqlTypeUtil.isBoundedVariableWidth(lhsType));

        // pad character is 0 for binary, space for character
        Expression padByteExp;
        if (!SqlTypeUtil.inCharFamily(lhsType)) {
          padByteExp = new CastExpression(OJSystem.BYTE, Literal.makeLiteral(0));
        } else {
          padByteExp = new CastExpression(OJSystem.BYTE, Literal.makeLiteral(' '));
        }

        // generate the call to do the job
        addStatement(
            new ExpressionStatement(
                new MethodCall(
                    lhsExp,
                    BytePointer.ENFORCE_PRECISION_METHOD_NAME,
                    new ExpressionList(precisionExp, needPadExp, padByteExp))));
      }

      return lhsExp;
    }