@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; }
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()); } }
/** * Returns the type the row which results when two relations are joined. * * <p>The resulting row type consists of the system fields (if any), followed by the fields of the * left type, followed by the fields of the right type. The field name list, if present, overrides * the original names of the fields. * * @param typeFactory Type factory * @param leftType Type of left input to join * @param rightType Type of right input to join * @param fieldNameList If not null, overrides the original names of the fields * @param systemFieldList List of system fields that will be prefixed to output row type; * typically empty but must not be null * @return type of row which results when two relations are joined */ public static RelDataType createJoinType( RelDataTypeFactory typeFactory, RelDataType leftType, RelDataType rightType, List<String> fieldNameList, List<RelDataTypeField> systemFieldList) { assert (fieldNameList == null) || (fieldNameList.size() == (systemFieldList.size() + leftType.getFieldCount() + rightType.getFieldCount())); List<String> nameList = new ArrayList<>(); final List<RelDataType> typeList = new ArrayList<>(); // Use a set to keep track of the field names; this is needed // to ensure that the contains() call to check for name uniqueness // runs in constant time; otherwise, if the number of fields is large, // doing a contains() on a list can be expensive. final Set<String> uniqueNameList = typeFactory.getTypeSystem().isSchemaCaseSensitive() ? new HashSet<String>() : new TreeSet<>(String.CASE_INSENSITIVE_ORDER); addFields(systemFieldList, typeList, nameList, uniqueNameList); addFields(leftType.getFieldList(), typeList, nameList, uniqueNameList); if (rightType != null) { addFields(rightType.getFieldList(), typeList, nameList, uniqueNameList); } if (fieldNameList != null) { assert fieldNameList.size() == nameList.size(); nameList = fieldNameList; } return typeFactory.createStructType(typeList, nameList); }
/** * Creates a relational expression that projects the given fields of the input. * * <p>Optimizes if the fields are the identity projection. * * @param relBuilder RelBuilder * @param child Input relational expression * @param posList Source of each projected field * @return Relational expression that projects given fields */ public static RelNode createProject( final RelBuilder relBuilder, final RelNode child, final List<Integer> posList) { RelDataType rowType = child.getRowType(); final List<String> fieldNames = rowType.getFieldNames(); final RexBuilder rexBuilder = child.getCluster().getRexBuilder(); return createProject( child, new AbstractList<RexNode>() { public int size() { return posList.size(); } public RexNode get(int index) { final int pos = posList.get(index); return rexBuilder.makeInputRef(child, pos); } }, new AbstractList<String>() { public int size() { return posList.size(); } public String get(int index) { final int pos = posList.get(index); return fieldNames.get(pos); } }, true, relBuilder); }
protected DrillRel addRenamedProject(DrillRel rel, RelDataType validatedRowType) { RelDataType t = rel.getRowType(); RexBuilder b = rel.getCluster().getRexBuilder(); List<RexNode> projections = Lists.newArrayList(); int projectCount = t.getFieldList().size(); for (int i = 0; i < projectCount; i++) { projections.add(b.makeInputRef(rel, i)); } final List<String> fieldNames2 = SqlValidatorUtil.uniquify(validatedRowType.getFieldNames(), SqlValidatorUtil.F_SUGGESTER2); RelDataType newRowType = RexUtil.createStructType(rel.getCluster().getTypeFactory(), projections, fieldNames2); DrillProjectRel topProj = DrillProjectRel.create(rel.getCluster(), rel.getTraitSet(), rel, projections, newRowType); // Add a final non-trivial Project to get the validatedRowType, if child is not project. if (rel instanceof Project && DrillRelOptUtil.isTrivialProject(topProj, true)) { return rel; } else { return topProj; } }
/** * Creates an expression accessing a given named field from a record. * * <p>NOTE: Be careful choosing the value of {@code caseSensitive}. If the field name was supplied * by an end-user (e.g. as a column alias in SQL), use your session's case-sensitivity setting. * Only hard-code {@code true} if you are sure that the field name is internally generated. * Hard-coding {@code false} is almost certainly wrong. * * @param expr Expression yielding a record * @param fieldName Name of field in record * @param caseSensitive Whether match is case-sensitive * @return Expression accessing a given named field */ public RexNode makeFieldAccess(RexNode expr, String fieldName, boolean caseSensitive) { final RelDataType type = expr.getType(); final RelDataTypeField field = type.getField(fieldName, caseSensitive, false); if (field == null) { throw Util.newInternal("Type '" + type + "' has no field '" + fieldName + "'"); } return makeFieldAccessInternal(expr, field); }
/** * Creates an expression accessing a field with a given ordinal from a record. * * @param expr Expression yielding a record * @param i Ordinal of field * @return Expression accessing given field */ public RexNode makeFieldAccess(RexNode expr, int i) { final RelDataType type = expr.getType(); final List<RelDataTypeField> fields = type.getFieldList(); if ((i < 0) || (i >= fields.size())) { throw Util.newInternal("Field ordinal " + i + " is invalid for " + " type '" + type + "'"); } return makeFieldAccessInternal(expr, fields.get(i)); }
/** * Makes an expression which converts a value of type T to a value of type T NOT NULL, or throws * if the value is NULL. If the expression is already NOT NULL, does nothing. */ public RexNode makeNotNullCast(RexNode expr) { RelDataType type = expr.getType(); if (!type.isNullable()) { return expr; } RelDataType typeNotNull = getTypeFactory().createTypeWithNullability(type, false); return new RexCall(typeNotNull, SqlStdOperatorTable.CAST, ImmutableList.of(expr)); }
/** * 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); }
/** * 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; } }
/** * Derives the list of column names suitable for NATURAL JOIN. These are the columns that occur * exactly once on each side of the join. * * @param leftRowType Row type of left input to the join * @param rightRowType Row type of right input to the join * @return List of columns that occur once on each side */ public static List<String> deriveNaturalJoinColumnList( RelDataType leftRowType, RelDataType rightRowType) { final List<String> naturalColumnNames = new ArrayList<>(); final List<String> leftNames = leftRowType.getFieldNames(); final List<String> rightNames = rightRowType.getFieldNames(); for (String name : leftNames) { if ((Collections.frequency(leftNames, name) == 1) && (Collections.frequency(rightNames, name) == 1)) { naturalColumnNames.add(name); } } return naturalColumnNames; }
public static RelDataType createTypeFromProjection( RelDataType type, List<String> columnNameList, RelDataTypeFactory typeFactory, boolean caseSensitive) { // If the names in columnNameList and type have case-sensitive differences, // the resulting type will use those from type. These are presumably more // canonical. final List<RelDataTypeField> fields = new ArrayList<>(columnNameList.size()); for (String name : columnNameList) { RelDataTypeField field = type.getField(name, caseSensitive, false); fields.add(type.getFieldList().get(field.getIndex())); } return typeFactory.createStructType(fields); }
/** * 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; } }
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; }
/** * 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); }
/** Ensures that a type's nullability matches a value's nullability. */ public RelDataType matchNullability(RelDataType type, RexNode value) { boolean typeNullability = type.isNullable(); boolean valueNullability = value.getType().isNullable(); if (typeNullability != valueNullability) { return getTypeFactory().createTypeWithNullability(type, valueNullability); } return type; }
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 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()))); }
public RelDataType inferReturnType(SqlOperatorBinding opBinding) { RelDataType type = opBinding.getOperandType(0); if (type.isStruct()) { type = type.getFieldList().get(0).getType(); } assert type instanceof ArraySqlType || type instanceof MultisetSqlType; if (withOrdinality) { final RelDataTypeFactory.FieldInfoBuilder builder = opBinding.getTypeFactory().builder(); if (type.getComponentType().isStruct()) { builder.addAll(type.getComponentType().getFieldList()); } else { builder.add(SqlUtil.deriveAliasFromOrdinal(0), type.getComponentType()); } return builder.add(ORDINALITY_COLUMN_NAME, SqlTypeName.INTEGER).build(); } else { return type.getComponentType(); } }
/** * 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; } }
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; }
private SyntheticRecordType(RelDataType relType, String name) { this.relType = relType; this.name = name; assert relType == null || Util.isDistinct(relType.getFieldNames()) : "field names not distinct: " + relType; }
/** * Variant of {@link #trimFields(RelNode, ImmutableBitSet, Set)} for {@link * org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveMultiJoin}. */ public TrimResult trimFields( HiveMultiJoin join, ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields) { final int fieldCount = join.getRowType().getFieldCount(); final RexNode conditionExpr = join.getCondition(); // Add in fields used in the condition. final Set<RelDataTypeField> combinedInputExtraFields = new LinkedHashSet<RelDataTypeField>(extraFields); RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder(combinedInputExtraFields); inputFinder.inputBitSet.addAll(fieldsUsed); conditionExpr.accept(inputFinder); final ImmutableBitSet fieldsUsedPlus = inputFinder.inputBitSet.build(); int inputStartPos = 0; int changeCount = 0; int newFieldCount = 0; List<RelNode> newInputs = new ArrayList<RelNode>(); List<Mapping> inputMappings = new ArrayList<Mapping>(); for (RelNode input : join.getInputs()) { final RelDataType inputRowType = input.getRowType(); final int inputFieldCount = inputRowType.getFieldCount(); // Compute required mapping. ImmutableBitSet.Builder inputFieldsUsed = ImmutableBitSet.builder(); for (int bit : fieldsUsedPlus) { if (bit >= inputStartPos && bit < inputStartPos + inputFieldCount) { inputFieldsUsed.set(bit - inputStartPos); } } Set<RelDataTypeField> inputExtraFields = Collections.<RelDataTypeField>emptySet(); TrimResult trimResult = trimChild(join, input, inputFieldsUsed.build(), inputExtraFields); newInputs.add(trimResult.left); if (trimResult.left != input) { ++changeCount; } final Mapping inputMapping = trimResult.right; inputMappings.add(inputMapping); // Move offset to point to start of next input. inputStartPos += inputFieldCount; newFieldCount += inputMapping.getTargetCount(); } Mapping mapping = Mappings.create(MappingType.INVERSE_SURJECTION, fieldCount, newFieldCount); int offset = 0; int newOffset = 0; for (int i = 0; i < inputMappings.size(); i++) { Mapping inputMapping = inputMappings.get(i); for (IntPair pair : inputMapping) { mapping.set(pair.source + offset, pair.target + newOffset); } offset += inputMapping.getSourceCount(); newOffset += inputMapping.getTargetCount(); } if (changeCount == 0 && mapping.isIdentity()) { return new TrimResult(join, Mappings.createIdentity(fieldCount)); } // Build new join. final RexVisitor<RexNode> shuttle = new RexPermuteInputsShuttle(mapping, newInputs.toArray(new RelNode[newInputs.size()])); RexNode newConditionExpr = conditionExpr.accept(shuttle); final RelDataType newRowType = RelOptUtil.permute(join.getCluster().getTypeFactory(), join.getRowType(), mapping); final RelNode newJoin = new HiveMultiJoin( join.getCluster(), newInputs, newConditionExpr, newRowType, join.getJoinInputs(), join.getJoinTypes(), join.getJoinFilters()); return new TrimResult(newJoin, mapping); }
/** * 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()); } }
/** * Looks up a field with a given name, returning null if not found. * * @param caseSensitive Whether match is case-sensitive * @param rowType Row type * @param columnName Field name * @return Field, or null if not found */ public static RelDataTypeField lookupField( boolean caseSensitive, final RelDataType rowType, String columnName) { return rowType.getField(columnName, caseSensitive, false); }
/** * 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); }
/** * Creates a list of {@link org.apache.calcite.rex.RexInputRef} expressions, projecting the fields * of a given record type. */ public List<RexInputRef> identityProjects(final RelDataType rowType) { return Lists.transform(rowType.getFieldList(), TO_INPUT_REF); }
/** * Creates a reference to all the fields in the row. * * <p>For example, if the input row has type <code>T{f0,f1,f2,f3,f4}</code> then <code> * makeRangeReference(T{f0,f1,f2,f3,f4}, S{f3,f4}, 3)</code> is an expression which yields the * last 2 fields. * * @param type Type of the resulting range record. * @param offset Index of first field. * @param nullable Whether the record is nullable. */ public RexRangeRef makeRangeReference(RelDataType type, int offset, boolean nullable) { if (nullable && !type.isNullable()) { type = typeFactory.createTypeWithNullability(type, nullable); } return new RexRangeRef(type, offset); }