/** * Creates a RexBuilder. * * @param typeFactory Type factory */ public RexBuilder(RelDataTypeFactory typeFactory) { this.typeFactory = typeFactory; this.booleanTrue = makeLiteral( Boolean.TRUE, typeFactory.createSqlType(SqlTypeName.BOOLEAN), SqlTypeName.BOOLEAN); this.booleanFalse = makeLiteral( Boolean.FALSE, typeFactory.createSqlType(SqlTypeName.BOOLEAN), SqlTypeName.BOOLEAN); this.charEmpty = makeLiteral( new NlsString("", null, null), typeFactory.createSqlType(SqlTypeName.CHAR, 0), SqlTypeName.CHAR); this.constantNull = makeLiteral(null, typeFactory.createSqlType(SqlTypeName.NULL), SqlTypeName.NULL); }
/** Creates a Timestamp literal. */ public RexLiteral makeTimestampLiteral(Calendar timestamp, int precision) { assert timestamp != null; return makeLiteral( timestamp, typeFactory.createSqlType(SqlTypeName.TIMESTAMP, precision), SqlTypeName.TIMESTAMP); }
/** Creates a double-precision literal. */ public RexLiteral makeApproxLiteral(BigDecimal bd) { // Validator should catch if underflow is allowed // If underflow is allowed, let underflow become zero if (bd.doubleValue() == 0) { bd = BigDecimal.ZERO; } return makeApproxLiteral(bd, typeFactory.createSqlType(SqlTypeName.DOUBLE)); }
/** Creates a numeric literal. */ public RexLiteral makeExactLiteral(BigDecimal bd) { RelDataType relType; int scale = bd.scale(); long l = bd.unscaledValue().longValue(); assert scale >= 0; assert scale <= typeFactory.getTypeSystem().getMaxNumericScale() : scale; assert BigDecimal.valueOf(l, scale).equals(bd); if (scale == 0) { if ((l >= Integer.MIN_VALUE) && (l <= Integer.MAX_VALUE)) { relType = typeFactory.createSqlType(SqlTypeName.INTEGER); } else { relType = typeFactory.createSqlType(SqlTypeName.BIGINT); } } else { int precision = bd.unscaledValue().toString().length(); relType = typeFactory.createSqlType(SqlTypeName.DECIMAL, scale, precision); } return makeExactLiteral(bd, relType); }
public RelDataType createSqlType(RelDataTypeFactory typeFactory) { BitString bitString; switch (typeName) { case NULL: case BOOLEAN: RelDataType ret = typeFactory.createSqlType(typeName); ret = typeFactory.createTypeWithNullability(ret, null == value); return ret; case BINARY: bitString = (BitString) value; int bitCount = bitString.getBitCount(); return typeFactory.createSqlType(SqlTypeName.BINARY, bitCount / 8); case CHAR: NlsString string = (NlsString) value; Charset charset = string.getCharset(); if (null == charset) { charset = typeFactory.getDefaultCharset(); } SqlCollation collation = string.getCollation(); if (null == collation) { collation = SqlCollation.COERCIBLE; } RelDataType type = typeFactory.createSqlType(SqlTypeName.CHAR, string.getValue().length()); type = typeFactory.createTypeWithCharsetAndCollation(type, charset, collation); return type; case INTERVAL_YEAR_MONTH: case INTERVAL_DAY_TIME: SqlIntervalLiteral.IntervalValue intervalValue = (SqlIntervalLiteral.IntervalValue) value; return typeFactory.createSqlIntervalType(intervalValue.getIntervalQualifier()); case SYMBOL: return typeFactory.createSqlType(SqlTypeName.SYMBOL); case INTEGER: // handled in derived class case TIME: // handled in derived class case VARCHAR: // should never happen case VARBINARY: // should never happen default: throw Util.needToImplement(toString() + ", operand=" + value); } }
/** * Creates a character string literal with type CHAR and default charset and collation. * * @param s String value * @return Character string literal */ protected RexLiteral makePreciseStringLiteral(String s) { assert s != null; if (s.equals("")) { return charEmpty; } else { return makeLiteral( new NlsString(s, null, null), typeFactory.createSqlType(SqlTypeName.CHAR, s.length()), SqlTypeName.CHAR); } }
@Override public AggregateCall other(RelDataTypeFactory typeFactory, AggregateCall e) { return AggregateCall.create( new HiveSqlCountAggFunction( isDistinct, returnTypeInference, operandTypeInference, operandTypeChecker), false, ImmutableIntList.of(), -1, typeFactory.createTypeWithNullability( typeFactory.createSqlType(SqlTypeName.BIGINT), true), "count"); }
private RelDataType guessType(Object value) { if (value == null) { return typeFactory.createSqlType(SqlTypeName.NULL); } if (value instanceof Float || value instanceof Double) { return typeFactory.createSqlType(SqlTypeName.DOUBLE); } if (value instanceof Number) { return typeFactory.createSqlType(SqlTypeName.BIGINT); } if (value instanceof Boolean) { return typeFactory.createSqlType(SqlTypeName.BOOLEAN); } if (value instanceof String) { return typeFactory.createSqlType(SqlTypeName.CHAR, ((String) value).length()); } if (value instanceof ByteString) { return typeFactory.createSqlType(SqlTypeName.BINARY, ((ByteString) value).length()); } throw new AssertionError("unknown type " + value.getClass()); }
/** Creates a Time literal. */ public RexLiteral makeTimeLiteral(Calendar time, int precision) { assert time != null; return makeLiteral( time, typeFactory.createSqlType(SqlTypeName.TIME, precision), SqlTypeName.TIME); }
/** Creates a Date literal. */ public RexLiteral makeDateLiteral(Calendar date) { assert date != null; return makeLiteral(date, typeFactory.createSqlType(SqlTypeName.DATE), SqlTypeName.DATE); }
/** Creates a byte array literal. */ public RexLiteral makeBinaryLiteral(ByteString byteString) { return makeLiteral( byteString, typeFactory.createSqlType(SqlTypeName.BINARY, byteString.length()), SqlTypeName.BINARY); }
/** * Creates a literal representing a flag. * * @param flag Flag value */ public RexLiteral makeFlag(Enum flag) { assert flag != null; return makeLiteral(flag, typeFactory.createSqlType(SqlTypeName.SYMBOL), SqlTypeName.SYMBOL); }
/** * Retrieves an interval or decimal node's integer representation * * @param node the interval or decimal value as an opaque type * @return an integer representation of the decimal value */ public RexNode decodeIntervalOrDecimal(RexNode node) { assert SqlTypeUtil.isDecimal(node.getType()) || SqlTypeUtil.isInterval(node.getType()); RelDataType bigintType = typeFactory.createSqlType(SqlTypeName.BIGINT); return makeReinterpretCast(matchNullability(bigintType, node), node, makeLiteral(false)); }
/** * Casts a decimal's integer representation to a decimal node. If the expression is not the * expected integer type, then it is casted first. * * <p>An overflow check may be requested to ensure the internal value does not exceed the maximum * value of the decimal type. * * @param value integer representation of decimal * @param type type integer will be reinterpreted as * @param checkOverflow indicates whether an overflow check is required when reinterpreting this * particular value as the decimal type. A check usually not required for arithmetic, but is * often required for rounding and explicit casts. * @return the integer reinterpreted as an opaque decimal type */ public RexNode encodeIntervalOrDecimal(RexNode value, RelDataType type, boolean checkOverflow) { RelDataType bigintType = typeFactory.createSqlType(SqlTypeName.BIGINT); RexNode cast = ensureType(bigintType, value, true); return makeReinterpretCast(type, cast, makeLiteral(checkOverflow)); }
/** * Creates a literal whose value is NULL, with a particular type. * * <p>The typing is necessary because RexNodes are strictly typed. For example, in the Rex world * the <code>NULL</code> parameter to <code> * SUBSTRING(NULL FROM 2 FOR 4)</code> must have a valid VARCHAR type so that the result type can * be determined. * * @param typeName Type to cast NULL to * @return NULL literal of given type */ public RexNode makeNullLiteral(SqlTypeName typeName) { RelDataType type = typeFactory.createTypeWithNullability(typeFactory.createSqlType(typeName), true); return makeCast(type, constantNull()); }
/** Creates a BIGINT literal. */ public RexLiteral makeBigintLiteral(BigDecimal bd) { RelDataType bigintType = typeFactory.createSqlType(SqlTypeName.BIGINT); return makeLiteral(bd, bigintType, SqlTypeName.DECIMAL); }
@Override public Prel visitProject(ProjectPrel project, Object unused) throws RelConversionException { // Apply the rule to the child RelNode originalInput = ((Prel) project.getInput(0)).accept(this, null); project = (ProjectPrel) project.copy(project.getTraitSet(), Lists.newArrayList(originalInput)); List<RexNode> exprList = new ArrayList<>(); List<RelDataTypeField> relDataTypes = new ArrayList(); List<RelDataTypeField> origRelDataTypes = new ArrayList(); int i = 0; final int lastColumnReferenced = PrelUtil.getLastUsedColumnReference(project.getProjects()); if (lastColumnReferenced == -1) { return project; } final int lastRexInput = lastColumnReferenced + 1; RexVisitorComplexExprSplitter exprSplitter = new RexVisitorComplexExprSplitter(factory, funcReg, lastRexInput); for (RexNode rex : project.getChildExps()) { origRelDataTypes.add(project.getRowType().getFieldList().get(i)); i++; exprList.add(rex.accept(exprSplitter)); } List<RexNode> complexExprs = exprSplitter.getComplexExprs(); if (complexExprs.size() == 1 && findTopComplexFunc(project.getChildExps()).size() == 1) { return project; } ProjectPrel childProject; List<RexNode> allExprs = new ArrayList(); int exprIndex = 0; List<String> fieldNames = originalInput.getRowType().getFieldNames(); for (int index = 0; index < lastRexInput; index++) { RexBuilder builder = new RexBuilder(factory); allExprs.add( builder.makeInputRef(new RelDataTypeDrillImpl(new RelDataTypeHolder(), factory), index)); if (fieldNames.get(index).contains(StarColumnHelper.STAR_COLUMN)) { relDataTypes.add( new RelDataTypeFieldImpl( fieldNames.get(index), allExprs.size(), factory.createSqlType(SqlTypeName.ANY))); } else { relDataTypes.add( new RelDataTypeFieldImpl( "EXPR$" + exprIndex, allExprs.size(), factory.createSqlType(SqlTypeName.ANY))); exprIndex++; } } RexNode currRexNode; int index = lastRexInput - 1; // if the projection expressions contained complex outputs, split them into their own individual // projects if (complexExprs.size() > 0) { while (complexExprs.size() > 0) { if (index >= lastRexInput) { allExprs.remove(allExprs.size() - 1); RexBuilder builder = new RexBuilder(factory); allExprs.add( builder.makeInputRef( new RelDataTypeDrillImpl(new RelDataTypeHolder(), factory), index)); } index++; exprIndex++; currRexNode = complexExprs.remove(0); allExprs.add(currRexNode); relDataTypes.add( new RelDataTypeFieldImpl( "EXPR$" + exprIndex, allExprs.size(), factory.createSqlType(SqlTypeName.ANY))); childProject = new ProjectPrel( project.getCluster(), project.getTraitSet(), originalInput, ImmutableList.copyOf(allExprs), new RelRecordType(relDataTypes)); originalInput = childProject; } // copied from above, find a better way to do this allExprs.remove(allExprs.size() - 1); RexBuilder builder = new RexBuilder(factory); allExprs.add( builder.makeInputRef(new RelDataTypeDrillImpl(new RelDataTypeHolder(), factory), index)); relDataTypes.add( new RelDataTypeFieldImpl( "EXPR$" + index, allExprs.size(), factory.createSqlType(SqlTypeName.ANY))); } return (Prel) project.copy( project.getTraitSet(), originalInput, exprList, new RelRecordType(origRelDataTypes)); }