// implement RelDataType public RelDataTypeField getField(String fieldName, boolean caseSensitive) { for (RelDataTypeField field : fieldList) { if (Util.match(caseSensitive, field.getName(), fieldName)) { return field; } } // Extra field if (fieldList.size() > 0) { final RelDataTypeField lastField = Iterables.getLast(fieldList); if (lastField.getName().equals("_extra")) { return new RelDataTypeFieldImpl(fieldName, -1, lastField.getType()); } } return null; }
/** * Creates a relational expression which permutes the output fields of a relational expression * according to a permutation. * * <p>Optimizations: * * <ul> * <li>If the relational expression is a {@link CalcRel} or {@link ProjectRel} which is already * acting as a permutation, combines the new permutation with the old; * <li>If the permutation is the identity, returns the original relational expression. * </ul> * * <p>If a permutation is combined with its inverse, these optimizations would combine to remove * them both. * * @param rel Relational expression * @param permutation Permutation to apply to fields * @param fieldNames Field names; if null, or if a particular entry is null, the name of the * permuted field is used * @return relational expression which permutes its input fields */ public static RelNode permute(RelNode rel, Permutation permutation, List<String> fieldNames) { if (permutation.isIdentity()) { return rel; } if (rel instanceof CalcRel) { CalcRel calcRel = (CalcRel) rel; Permutation permutation1 = calcRel.getProgram().getPermutation(); if (permutation1 != null) { Permutation permutation2 = permutation.product(permutation1); return permute(rel, permutation2, null); } } if (rel instanceof ProjectRel) { Permutation permutation1 = ((ProjectRel) rel).getPermutation(); if (permutation1 != null) { Permutation permutation2 = permutation.product(permutation1); return permute(rel, permutation2, null); } } final List<RelDataType> outputTypeList = new ArrayList<RelDataType>(); final List<String> outputNameList = new ArrayList<String>(); final List<RexNode> exprList = new ArrayList<RexNode>(); final List<RexLocalRef> projectRefList = new ArrayList<RexLocalRef>(); final List<RelDataTypeField> fields = rel.getRowType().getFieldList(); for (int i = 0; i < permutation.getTargetCount(); i++) { int target = permutation.getTarget(i); final RelDataTypeField targetField = fields.get(target); outputTypeList.add(targetField.getType()); outputNameList.add( ((fieldNames == null) || (fieldNames.size() <= i) || (fieldNames.get(i) == null)) ? targetField.getName() : fieldNames.get(i)); exprList.add(rel.getCluster().getRexBuilder().makeInputRef(fields.get(i).getType(), i)); final int source = permutation.getSource(i); projectRefList.add(new RexLocalRef(source, fields.get(source).getType())); } final RexProgram program = new RexProgram( rel.getRowType(), exprList, projectRefList, null, rel.getCluster().getTypeFactory().createStructType(outputTypeList, outputNameList)); return new CalcRel( rel.getCluster(), rel.getTraitSet(), rel, program.getOutputRowType(), program, Collections.<RelCollation>emptyList()); }
private static List<RelCollation> deduceMonotonicity(Prepare.PreparingTable table) { final List<RelCollation> collationList = new ArrayList<RelCollation>(); // Deduce which fields the table is sorted on. int i = -1; for (RelDataTypeField field : table.getRowType().getFieldList()) { ++i; final SqlMonotonicity monotonicity = table.getMonotonicity(field.getName()); if (monotonicity != SqlMonotonicity.NotMonotonic) { final RelFieldCollation.Direction direction = monotonicity.isDecreasing() ? RelFieldCollation.Direction.Descending : RelFieldCollation.Direction.Ascending; collationList.add( RelCollationImpl.of( new RelFieldCollation(i, direction, RelFieldCollation.NullDirection.UNSPECIFIED))); } } return collationList; }
/** * Creates a relational expression which projects the output fields of a relational expression * according to a partial mapping. * * <p>A partial mapping is weaker than a permutation: every target has one source, but a source * may have 0, 1 or more than one targets. Usually the result will have fewer fields than the * source, unless some source fields are projected multiple times. * * <p>This method could optimize the result as {@link #permute} does, but does not at present. * * @param rel Relational expression * @param mapping Mapping from source fields to target fields. The mapping type must obey the * constaints {@link MappingType#isMandatorySource()} and {@link * MappingType#isSingleSource()}, as does {@link MappingType#InverseFunction}. * @param fieldNames Field names; if null, or if a particular entry is null, the name of the * permuted field is used * @return relational expression which projects a subset of the input fields */ public static RelNode projectMapping(RelNode rel, Mapping mapping, List<String> fieldNames) { assert mapping.getMappingType().isSingleSource(); assert mapping.getMappingType().isMandatorySource(); if (mapping.isIdentity()) { return rel; } final List<RelDataType> outputTypeList = new ArrayList<RelDataType>(); final List<String> outputNameList = new ArrayList<String>(); final List<RexNode> exprList = new ArrayList<RexNode>(); final List<RexLocalRef> projectRefList = new ArrayList<RexLocalRef>(); final List<RelDataTypeField> fields = rel.getRowType().getFieldList(); for (int i = 0; i < fields.size(); i++) { final RelDataTypeField field = fields.get(i); exprList.add(rel.getCluster().getRexBuilder().makeInputRef(field.getType(), i)); } for (int i = 0; i < mapping.getTargetCount(); i++) { int source = mapping.getSource(i); final RelDataTypeField sourceField = fields.get(source); outputTypeList.add(sourceField.getType()); outputNameList.add( ((fieldNames == null) || (fieldNames.size() <= i) || (fieldNames.get(i) == null)) ? sourceField.getName() : fieldNames.get(i)); projectRefList.add(new RexLocalRef(source, sourceField.getType())); } final RexProgram program = new RexProgram( rel.getRowType(), exprList, projectRefList, null, rel.getCluster().getTypeFactory().createStructType(outputTypeList, outputNameList)); return new CalcRel( rel.getCluster(), rel.getTraitSet(), rel, program.getOutputRowType(), program, Collections.<RelCollation>emptyList()); }
private List<RelCollation> deduceMonotonicity(SqlValidatorTable table) { final RelDataType rowType = table.getRowType(); final List<RelCollation> collationList = new ArrayList<RelCollation>(); // Deduce which fields the table is sorted on. int i = -1; for (RelDataTypeField field : rowType.getFieldList()) { ++i; final SqlMonotonicity monotonicity = table.getMonotonicity(field.getName()); if (monotonicity != SqlMonotonicity.NOT_MONOTONIC) { final RelFieldCollation.Direction direction = monotonicity.isDecreasing() ? RelFieldCollation.Direction.DESCENDING : RelFieldCollation.Direction.ASCENDING; collationList.add( RelCollationImpl.of( new RelFieldCollation( i, direction, RelFieldCollation.NullDirection.UNSPECIFIED))); } } return collationList; }