public Type getJavaClass(RelDataType type) {
   if (type instanceof JavaType) {
     JavaType javaType = (JavaType) type;
     return javaType.getJavaClass();
   }
   if (type.isStruct() && type.getFieldCount() == 1) {
     return getJavaClass(type.getFieldList().get(0).getType());
   }
   if (type instanceof BasicSqlType || type instanceof IntervalSqlType) {
     switch (type.getSqlTypeName()) {
       case VARCHAR:
       case CHAR:
         return String.class;
       case DATE:
       case TIME:
       case INTEGER:
       case INTERVAL_YEAR_MONTH:
         return type.isNullable() ? Integer.class : int.class;
       case TIMESTAMP:
       case BIGINT:
       case INTERVAL_DAY_TIME:
         return type.isNullable() ? Long.class : long.class;
       case SMALLINT:
         return type.isNullable() ? Short.class : short.class;
       case TINYINT:
         return type.isNullable() ? Byte.class : byte.class;
       case DECIMAL:
         return BigDecimal.class;
       case BOOLEAN:
         return type.isNullable() ? Boolean.class : boolean.class;
       case DOUBLE:
       case FLOAT: // sic
         return type.isNullable() ? Double.class : double.class;
       case REAL:
         return type.isNullable() ? Float.class : float.class;
       case BINARY:
       case VARBINARY:
         return ByteString.class;
       case ARRAY:
         return Array.class;
       case ANY:
         return Object.class;
     }
   }
   switch (type.getSqlTypeName()) {
     case ROW:
       assert type instanceof RelRecordType;
       if (type instanceof JavaRecordType) {
         return ((JavaRecordType) type).clazz;
       } else {
         return createSyntheticType((RelRecordType) type);
       }
     case MAP:
       return Map.class;
     case ARRAY:
     case MULTISET:
       return List.class;
   }
   return null;
 }
예제 #2
0
 private static Comparable zeroValue(RelDataType type) {
   switch (type.getSqlTypeName()) {
     case CHAR:
       return new NlsString(Spaces.of(type.getPrecision()), null, null);
     case VARCHAR:
       return new NlsString("", null, null);
     case BINARY:
       return new ByteString(new byte[type.getPrecision()]);
     case VARBINARY:
       return ByteString.EMPTY;
     case TINYINT:
     case SMALLINT:
     case INTEGER:
     case BIGINT:
     case DECIMAL:
     case FLOAT:
     case REAL:
     case DOUBLE:
       return BigDecimal.ZERO;
     case BOOLEAN:
       return false;
     case TIME:
     case DATE:
     case TIMESTAMP:
       return DateTimeUtils.ZERO_CALENDAR;
     default:
       throw Util.unexpected(type.getSqlTypeName());
   }
 }
예제 #3
0
 /**
  * Creates a call to the CAST operator, expanding if possible.
  *
  * @param type Type to cast to
  * @param exp Expression being cast
  * @return Call to CAST operator
  */
 public RexNode makeCast(RelDataType type, RexNode exp) {
   final SqlTypeName sqlType = type.getSqlTypeName();
   if (exp instanceof RexLiteral) {
     RexLiteral literal = (RexLiteral) exp;
     Comparable value = literal.getValue();
     if (RexLiteral.valueMatchesType(value, sqlType, false)
         && (!(value instanceof NlsString)
             || (type.getPrecision() >= ((NlsString) value).getValue().length()))
         && (!(value instanceof ByteString)
             || (type.getPrecision() >= ((ByteString) value).length()))) {
       switch (literal.getTypeName()) {
         case CHAR:
           if (value instanceof NlsString) {
             value = ((NlsString) value).rtrim();
           }
           break;
         case TIMESTAMP:
         case TIME:
           final Calendar calendar = (Calendar) value;
           int scale = type.getScale();
           if (scale == RelDataType.SCALE_NOT_SPECIFIED) {
             scale = 0;
           }
           calendar.setTimeInMillis(
               SqlFunctions.round(
                   calendar.getTimeInMillis(), DateTimeUtils.powerX(10, 3 - scale)));
           break;
         case INTERVAL_DAY_TIME:
           BigDecimal value2 = (BigDecimal) value;
           final long multiplier =
               literal.getType().getIntervalQualifier().getStartUnit().multiplier;
           SqlTypeName typeName = type.getSqlTypeName();
           // Not all types are allowed for literals
           switch (typeName) {
             case INTEGER:
               typeName = SqlTypeName.BIGINT;
           }
           return makeLiteral(
               value2.divide(BigDecimal.valueOf(multiplier), 0, BigDecimal.ROUND_HALF_DOWN),
               type,
               typeName);
       }
       return makeLiteral(value, type, literal.getTypeName());
     }
   } else if (SqlTypeUtil.isInterval(type) && SqlTypeUtil.isExactNumeric(exp.getType())) {
     return makeCastExactToInterval(type, exp);
   } else if (SqlTypeUtil.isExactNumeric(type) && SqlTypeUtil.isInterval(exp.getType())) {
     return makeCastIntervalToExact(type, exp);
   } else if (sqlType == SqlTypeName.BOOLEAN && SqlTypeUtil.isExactNumeric(exp.getType())) {
     return makeCastExactToBoolean(type, exp);
   } else if (exp.getType().getSqlTypeName() == SqlTypeName.BOOLEAN
       && SqlTypeUtil.isExactNumeric(type)) {
     return makeCastBooleanToExact(type, exp);
   }
   return makeAbstractCast(type, exp);
 }
예제 #4
0
 /**
  * Estimates the average size (in bytes) of a value of a type.
  *
  * <p>Nulls count as 1 byte.
  */
 public double typeValueSize(RelDataType type, Comparable value) {
   if (value == null) {
     return 1d;
   }
   switch (type.getSqlTypeName()) {
     case BOOLEAN:
     case TINYINT:
       return 1d;
     case SMALLINT:
       return 2d;
     case INTEGER:
     case FLOAT:
     case REAL:
     case DATE:
     case TIME:
       return 4d;
     case BIGINT:
     case DOUBLE:
     case TIMESTAMP:
     case INTERVAL_DAY_TIME:
     case INTERVAL_YEAR_MONTH:
       return 8d;
     case BINARY:
     case VARBINARY:
       return ((ByteString) value).length();
     case CHAR:
     case VARCHAR:
       return ((NlsString) value).getValue().length() * BYTES_PER_CHARACTER;
     default:
       return 32;
   }
 }
예제 #5
0
 @Override
 public String visitLiteral(RexLiteral rexLiteral) {
   Object v = rexLiteral.getValue();
   RelDataType ty = rexLiteral.getType();
   switch (rexLiteral.getTypeName()) {
     case BOOLEAN:
       return v.toString();
     case CHAR:
       return CompilerUtil.escapeJavaString(((NlsString) v).getValue(), true);
     case NULL:
       return "((" + ((Class<?>) typeFactory.getJavaClass(ty)).getCanonicalName() + ")null)";
     case DOUBLE:
     case BIGINT:
     case DECIMAL:
       switch (ty.getSqlTypeName()) {
         case TINYINT:
         case SMALLINT:
         case INTEGER:
           return Long.toString(((BigDecimal) v).longValueExact());
         case BIGINT:
           return Long.toString(((BigDecimal) v).longValueExact()) + 'L';
         case DECIMAL:
         case FLOAT:
         case REAL:
         case DOUBLE:
           return Util.toScientificNotation((BigDecimal) v);
       }
       break;
     default:
       throw new UnsupportedOperationException();
   }
   return null;
 }
예제 #6
0
 /**
  * Converts the type of a value to comply with {@link
  * org.apache.calcite.rex.RexLiteral#valueMatchesType}.
  */
 private static Object clean(Object o, RelDataType type) {
   if (o == null) {
     return null;
   }
   final Calendar calendar;
   switch (type.getSqlTypeName()) {
     case TINYINT:
     case SMALLINT:
     case INTEGER:
     case BIGINT:
     case DECIMAL:
     case INTERVAL_YEAR_MONTH:
     case INTERVAL_DAY_TIME:
       if (o instanceof BigDecimal) {
         return o;
       }
       return new BigDecimal(((Number) o).longValue());
     case FLOAT:
     case REAL:
     case DOUBLE:
       if (o instanceof BigDecimal) {
         return o;
       }
       return new BigDecimal(((Number) o).doubleValue());
     case CHAR:
     case VARCHAR:
       if (o instanceof NlsString) {
         return o;
       }
       return new NlsString((String) o, type.getCharset().name(), type.getCollation());
     case TIME:
       if (o instanceof Calendar) {
         return o;
       }
       calendar = Calendar.getInstance(DateTimeUtils.GMT_ZONE);
       calendar.setTimeInMillis((Integer) o);
       return calendar;
     case DATE:
       if (o instanceof Calendar) {
         return o;
       }
       calendar = Calendar.getInstance(DateTimeUtils.GMT_ZONE);
       calendar.setTimeInMillis(0);
       calendar.add(Calendar.DAY_OF_YEAR, (Integer) o);
       return calendar;
     case TIMESTAMP:
       if (o instanceof Calendar) {
         return o;
       }
       calendar = Calendar.getInstance(DateTimeUtils.GMT_ZONE);
       calendar.setTimeInMillis((Long) o);
       return calendar;
     default:
       return o;
   }
 }
예제 #7
0
 /**
  * Internal method to create a call to a literal. Code outside this package should call one of the
  * type-specific methods such as {@link #makeDateLiteral(Calendar)}, {@link
  * #makeLiteral(boolean)}, {@link #makeLiteral(String)}.
  *
  * @param o Value of literal, must be appropriate for the type
  * @param type Type of literal
  * @param typeName SQL type of literal
  * @return Literal
  */
 protected RexLiteral makeLiteral(Comparable o, RelDataType type, SqlTypeName typeName) {
   // All literals except NULL have NOT NULL types.
   type = typeFactory.createTypeWithNullability(type, o == null);
   if (typeName == SqlTypeName.CHAR) {
     // Character literals must have a charset and collation. Populate
     // from the type if necessary.
     assert o instanceof NlsString;
     NlsString nlsString = (NlsString) o;
     if ((nlsString.getCollation() == null) || (nlsString.getCharset() == null)) {
       assert type.getSqlTypeName() == SqlTypeName.CHAR;
       assert type.getCharset().name() != null;
       assert type.getCollation() != null;
       o = new NlsString(nlsString.getValue(), type.getCharset().name(), type.getCollation());
     }
   }
   return new RexLiteral(o, type, typeName);
 }
 public RelDataType toSql(RelDataType type) {
   if (type instanceof RelRecordType) {
     return createStructType(
         Lists.transform(
             type.getFieldList(),
             new Function<RelDataTypeField, RelDataType>() {
               public RelDataType apply(RelDataTypeField a0) {
                 return toSql(a0.getType());
               }
             }),
         type.getFieldNames());
   }
   if (type instanceof JavaType) {
     return createTypeWithNullability(createSqlType(type.getSqlTypeName()), type.isNullable());
   }
   return type;
 }
예제 #9
0
 private RexNode makeCastBooleanToExact(RelDataType toType, RexNode exp) {
   final RexNode casted =
       makeCall(
           SqlStdOperatorTable.CASE,
           exp,
           makeExactLiteral(BigDecimal.ONE, toType),
           makeZeroLiteral(toType));
   if (!exp.getType().isNullable()) {
     return casted;
   }
   return makeCall(
       toType,
       SqlStdOperatorTable.CASE,
       ImmutableList.<RexNode>of(
           makeCall(SqlStdOperatorTable.IS_NOT_NULL, exp),
           casted,
           makeNullLiteral(toType.getSqlTypeName())));
 }
예제 #10
0
 /**
  * Estimates the average size (in bytes) of a value of a type.
  *
  * <p>We assume that the proportion of nulls is negligible, even if the type is nullable.
  */
 public Double averageTypeValueSize(RelDataType type) {
   switch (type.getSqlTypeName()) {
     case BOOLEAN:
     case TINYINT:
       return 1d;
     case SMALLINT:
       return 2d;
     case INTEGER:
     case REAL:
     case DECIMAL:
     case DATE:
     case TIME:
       return 4d;
     case BIGINT:
     case DOUBLE:
     case FLOAT: // sic
     case TIMESTAMP:
     case INTERVAL_DAY_TIME:
     case INTERVAL_YEAR_MONTH:
       return 8d;
     case BINARY:
       return (double) type.getPrecision();
     case VARBINARY:
       return Math.min((double) type.getPrecision(), 100d);
     case CHAR:
       return (double) type.getPrecision() * BYTES_PER_CHARACTER;
     case VARCHAR:
       // Even in large (say VARCHAR(2000)) columns most strings are small
       return Math.min((double) type.getPrecision() * BYTES_PER_CHARACTER, 100d);
     case ROW:
       Double average = 0.0;
       for (RelDataTypeField field : type.getFieldList()) {
         average += averageTypeValueSize(field.getType());
       }
       return average;
     default:
       return null;
   }
 }
예제 #11
0
 /**
  * Creates a literal of a given type. The value is assumed to be compatible with the type.
  *
  * @param value Value
  * @param type Type
  * @param allowCast Whether to allow a cast. If false, value is always a {@link RexLiteral} but
  *     may not be the exact type
  * @return Simple literal, or cast simple literal
  */
 public RexNode makeLiteral(Object value, RelDataType type, boolean allowCast) {
   if (value == null) {
     return makeCast(type, constantNull);
   }
   if (type.isNullable()) {
     final RelDataType typeNotNull = typeFactory.createTypeWithNullability(type, false);
     RexNode literalNotNull = makeLiteral(value, typeNotNull, allowCast);
     return makeAbstractCast(type, literalNotNull);
   }
   value = clean(value, type);
   RexLiteral literal;
   final List<RexNode> operands;
   switch (type.getSqlTypeName()) {
     case CHAR:
       return makeCharLiteral(padRight((NlsString) value, type.getPrecision()));
     case VARCHAR:
       literal = makeCharLiteral((NlsString) value);
       if (allowCast) {
         return makeCast(type, literal);
       } else {
         return literal;
       }
     case BINARY:
       return makeBinaryLiteral(padRight((ByteString) value, type.getPrecision()));
     case VARBINARY:
       literal = makeBinaryLiteral((ByteString) value);
       if (allowCast) {
         return makeCast(type, literal);
       } else {
         return literal;
       }
     case TINYINT:
     case SMALLINT:
     case INTEGER:
     case BIGINT:
     case DECIMAL:
       return makeExactLiteral((BigDecimal) value, type);
     case FLOAT:
     case REAL:
     case DOUBLE:
       return makeApproxLiteral((BigDecimal) value, type);
     case BOOLEAN:
       return (Boolean) value ? booleanTrue : booleanFalse;
     case TIME:
       return makeTimeLiteral((Calendar) value, type.getPrecision());
     case DATE:
       return makeDateLiteral((Calendar) value);
     case TIMESTAMP:
       return makeTimestampLiteral((Calendar) value, type.getPrecision());
     case INTERVAL_YEAR_MONTH:
     case INTERVAL_DAY_TIME:
       return makeIntervalLiteral((BigDecimal) value, type.getIntervalQualifier());
     case MAP:
       final MapSqlType mapType = (MapSqlType) type;
       @SuppressWarnings("unchecked")
       final Map<Object, Object> map = (Map) value;
       operands = new ArrayList<RexNode>();
       for (Map.Entry<Object, Object> entry : map.entrySet()) {
         operands.add(makeLiteral(entry.getKey(), mapType.getKeyType(), allowCast));
         operands.add(makeLiteral(entry.getValue(), mapType.getValueType(), allowCast));
       }
       return makeCall(SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, operands);
     case ARRAY:
       final ArraySqlType arrayType = (ArraySqlType) type;
       @SuppressWarnings("unchecked")
       final List<Object> listValue = (List) value;
       operands = new ArrayList<RexNode>();
       for (Object entry : listValue) {
         operands.add(makeLiteral(entry, arrayType.getComponentType(), allowCast));
       }
       return makeCall(SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR, operands);
     case ANY:
       return makeLiteral(value, guessType(value), allowCast);
     default:
       throw Util.unexpected(type.getSqlTypeName());
   }
 }
예제 #12
0
 /**
  * Creates an approximate numeric literal (double or float).
  *
  * @param bd literal value
  * @param type approximate numeric type
  * @return new literal
  */
 public RexLiteral makeApproxLiteral(BigDecimal bd, RelDataType type) {
   assert SqlTypeFamily.APPROXIMATE_NUMERIC.getTypeNames().contains(type.getSqlTypeName());
   return makeLiteral(bd, type, SqlTypeName.DOUBLE);
 }