Search in sources :

Example 26 with Mapping

use of org.apache.calcite.util.mapping.Mapping in project hive by apache.

the class RelFieldTrimmer method trimFields.

/**
 * Variant of {@link #trimFields(RelNode, ImmutableBitSet, Set)} for
 * {@link org.apache.calcite.rel.core.Sort}.
 */
public TrimResult trimFields(Sort sort, ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields) {
    final RelDataType rowType = sort.getRowType();
    final int fieldCount = rowType.getFieldCount();
    final RelCollation collation = sort.getCollation();
    final RelNode input = sort.getInput();
    // We use the fields used by the consumer, plus any fields used as sort
    // keys.
    final ImmutableBitSet.Builder inputFieldsUsed = fieldsUsed.rebuild();
    for (RelFieldCollation field : collation.getFieldCollations()) {
        inputFieldsUsed.set(field.getFieldIndex());
    }
    // Create input with trimmed columns.
    final Set<RelDataTypeField> inputExtraFields = Collections.emptySet();
    TrimResult trimResult = trimChild(sort, input, inputFieldsUsed.build(), inputExtraFields);
    RelNode newInput = trimResult.left;
    final Mapping inputMapping = trimResult.right;
    // there's nothing we can do.
    if (newInput == input && inputMapping.isIdentity() && fieldsUsed.cardinality() == fieldCount) {
        return result(sort, Mappings.createIdentity(fieldCount));
    }
    // leave the Sort unchanged in case we have dynamic limits
    if (sort.offset instanceof RexDynamicParam || sort.fetch instanceof RexDynamicParam) {
        return result(sort, inputMapping);
    }
    final RelBuilder relBuilder = REL_BUILDER.get();
    relBuilder.push(newInput);
    final int offset = sort.offset == null ? 0 : RexLiteral.intValue(sort.offset);
    final int fetch = sort.fetch == null ? -1 : RexLiteral.intValue(sort.fetch);
    final ImmutableList<RexNode> fields = relBuilder.fields(RexUtil.apply(inputMapping, collation));
    relBuilder.sortLimit(offset, fetch, fields);
    // needs them for its condition.
    return result(relBuilder.build(), inputMapping);
}
Also used : RelBuilder(org.apache.calcite.tools.RelBuilder) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RelDataType(org.apache.calcite.rel.type.RelDataType) Mapping(org.apache.calcite.util.mapping.Mapping) RelCollation(org.apache.calcite.rel.RelCollation) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) RexDynamicParam(org.apache.calcite.rex.RexDynamicParam) RexNode(org.apache.calcite.rex.RexNode)

Example 27 with Mapping

use of org.apache.calcite.util.mapping.Mapping in project hive by apache.

the class RelFieldTrimmer method trimFields.

/**
 * Variant of {@link #trimFields(RelNode, ImmutableBitSet, Set)} for
 * {@link org.apache.calcite.rel.logical.LogicalProject}.
 */
public TrimResult trimFields(Project project, ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields) {
    final RelDataType rowType = project.getRowType();
    final int fieldCount = rowType.getFieldCount();
    final RelNode input = project.getInput();
    // Which fields are required from the input?
    final Set<RelDataTypeField> inputExtraFields = new LinkedHashSet<>(extraFields);
    RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder(inputExtraFields);
    for (Ord<RexNode> ord : Ord.zip(project.getProjects())) {
        if (fieldsUsed.get(ord.i)) {
            ord.e.accept(inputFinder);
        }
    }
    ImmutableBitSet inputFieldsUsed = inputFinder.build();
    // Create input with trimmed columns.
    TrimResult trimResult = trimChild(project, input, inputFieldsUsed, inputExtraFields);
    RelNode newInput = trimResult.left;
    final Mapping inputMapping = trimResult.right;
    // there's nothing we can do.
    if (newInput == input && fieldsUsed.cardinality() == fieldCount) {
        return result(project, Mappings.createIdentity(fieldCount));
    }
    // pretend that one field is used.
    if (fieldsUsed.cardinality() == 0) {
        return dummyProject(fieldCount, newInput);
    }
    // Build new project expressions, and populate the mapping.
    final List<RexNode> newProjects = new ArrayList<>();
    final RexVisitor<RexNode> shuttle = new RexPermuteInputsShuttle(inputMapping, newInput);
    final Mapping mapping = Mappings.create(MappingType.INVERSE_SURJECTION, fieldCount, fieldsUsed.cardinality());
    for (Ord<RexNode> ord : Ord.zip(project.getProjects())) {
        if (fieldsUsed.get(ord.i)) {
            mapping.set(ord.i, newProjects.size());
            RexNode newProjectExpr = ord.e.accept(shuttle);
            newProjects.add(newProjectExpr);
        }
    }
    final RelDataType newRowType = RelOptUtil.permute(project.getCluster().getTypeFactory(), rowType, mapping);
    final RelBuilder relBuilder = REL_BUILDER.get();
    relBuilder.push(newInput);
    relBuilder.project(newProjects, newRowType.getFieldNames());
    return result(relBuilder.build(), mapping);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) RelBuilder(org.apache.calcite.tools.RelBuilder) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RelOptUtil(org.apache.calcite.plan.RelOptUtil) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) Mapping(org.apache.calcite.util.mapping.Mapping) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RexPermuteInputsShuttle(org.apache.calcite.rex.RexPermuteInputsShuttle) RexNode(org.apache.calcite.rex.RexNode)

Example 28 with Mapping

use of org.apache.calcite.util.mapping.Mapping in project hive by apache.

the class RelFieldTrimmer method trimFields.

/**
 * Variant of {@link #trimFields(RelNode, ImmutableBitSet, Set)} for
 * {@link org.apache.calcite.rel.logical.LogicalTableModify}.
 */
public TrimResult trimFields(LogicalTableModify modifier, ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields) {
    // Ignore what consumer wants. We always project all columns.
    Util.discard(fieldsUsed);
    final RelDataType rowType = modifier.getRowType();
    final int fieldCount = rowType.getFieldCount();
    RelNode input = modifier.getInput();
    // We want all fields from the child.
    final int inputFieldCount = input.getRowType().getFieldCount();
    final ImmutableBitSet inputFieldsUsed = ImmutableBitSet.range(inputFieldCount);
    // Create input with trimmed columns.
    final Set<RelDataTypeField> inputExtraFields = Collections.emptySet();
    TrimResult trimResult = trimChild(modifier, input, inputFieldsUsed, inputExtraFields);
    RelNode newInput = trimResult.left;
    final Mapping inputMapping = trimResult.right;
    if (!inputMapping.isIdentity()) {
        // to permute them!
        throw new AssertionError("Expected identity mapping, got " + inputMapping);
    }
    LogicalTableModify newModifier = modifier;
    if (newInput != input) {
        newModifier = modifier.copy(modifier.getTraitSet(), Collections.singletonList(newInput));
    }
    assert newModifier.getClass() == modifier.getClass();
    // Always project all fields.
    Mapping mapping = Mappings.createIdentity(fieldCount);
    return result(newModifier, mapping);
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) LogicalTableModify(org.apache.calcite.rel.logical.LogicalTableModify) RelDataType(org.apache.calcite.rel.type.RelDataType) Mapping(org.apache.calcite.util.mapping.Mapping)

Example 29 with Mapping

use of org.apache.calcite.util.mapping.Mapping in project hive by apache.

the class RelFieldTrimmer method trimFields.

/**
 * Variant of {@link #trimFields(RelNode, ImmutableBitSet, Set)} for
 * {@link org.apache.calcite.rel.logical.LogicalTableScan}.
 */
public TrimResult trimFields(final TableScan tableAccessRel, ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields) {
    final int fieldCount = tableAccessRel.getRowType().getFieldCount();
    if (fieldsUsed.equals(ImmutableBitSet.range(fieldCount)) && extraFields.isEmpty()) {
        // then no need to introduce another RelNode
        return trimFields((RelNode) tableAccessRel, fieldsUsed, extraFields);
    }
    final RelNode newTableAccessRel = tableAccessRel.project(fieldsUsed, extraFields, REL_BUILDER.get());
    // pretend that one field is used.
    if (fieldsUsed.cardinality() == 0) {
        RelNode input = newTableAccessRel;
        if (input instanceof Project) {
            // The table has implemented the project in the obvious way - by
            // creating project with 0 fields. Strip it away, and create our own
            // project with one field.
            Project project = (Project) input;
            if (project.getRowType().getFieldCount() == 0) {
                input = project.getInput();
            }
        }
        return dummyProject(fieldCount, input);
    }
    final Mapping mapping = createMapping(fieldsUsed, fieldCount);
    return result(newTableAccessRel, mapping);
}
Also used : Project(org.apache.calcite.rel.core.Project) RelNode(org.apache.calcite.rel.RelNode) Mapping(org.apache.calcite.util.mapping.Mapping)

Example 30 with Mapping

use of org.apache.calcite.util.mapping.Mapping in project hive by apache.

the class HiveRelMdPredicates method getPredicates.

/**
 * Infers predicates for a project.
 *
 * <ol>
 * <li>create a mapping from input to projection. Map only positions that
 * directly reference an input column.
 * <li>Expressions that only contain above columns are retained in the
 * Project's pullExpressions list.
 * <li>For e.g. expression 'a + e = 9' below will not be pulled up because 'e'
 * is not in the projection list.
 *
 * <pre>
 * childPullUpExprs:      {a &gt; 7, b + c &lt; 10, a + e = 9}
 * projectionExprs:       {a, b, c, e / 2}
 * projectionPullupExprs: {a &gt; 7, b + c &lt; 10}
 * </pre>
 *
 * </ol>
 */
@Override
public RelOptPredicateList getPredicates(Project project, RelMetadataQuery mq) {
    RelNode child = project.getInput();
    final RexBuilder rexBuilder = project.getCluster().getRexBuilder();
    RelOptPredicateList childInfo = mq.getPulledUpPredicates(child);
    List<RexNode> projectPullUpPredicates = new ArrayList<RexNode>();
    HashMultimap<Integer, Integer> inpIndxToOutIndxMap = HashMultimap.create();
    ImmutableBitSet.Builder columnsMappedBuilder = ImmutableBitSet.builder();
    Mapping m = Mappings.create(MappingType.PARTIAL_FUNCTION, child.getRowType().getFieldCount(), project.getRowType().getFieldCount());
    for (Ord<RexNode> o : Ord.zip(project.getProjects())) {
        if (o.e instanceof RexInputRef) {
            int sIdx = ((RexInputRef) o.e).getIndex();
            m.set(sIdx, o.i);
            inpIndxToOutIndxMap.put(sIdx, o.i);
            columnsMappedBuilder.set(sIdx);
        }
    }
    // Go over childPullUpPredicates. If a predicate only contains columns in
    // 'columnsMapped' construct a new predicate based on mapping.
    final ImmutableBitSet columnsMapped = columnsMappedBuilder.build();
    for (RexNode r : childInfo.pulledUpPredicates) {
        ImmutableBitSet rCols = RelOptUtil.InputFinder.bits(r);
        if (columnsMapped.contains(rCols)) {
            r = r.accept(new RexPermuteInputsShuttle(m, child));
            projectPullUpPredicates.add(r);
        }
    }
    // Project can also generate constants. We need to include them.
    for (Ord<RexNode> expr : Ord.zip(project.getProjects())) {
        if (RexLiteral.isNullLiteral(expr.e)) {
            projectPullUpPredicates.add(rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, rexBuilder.makeInputRef(project, expr.i)));
        } else if (expr.e instanceof RexLiteral) {
            final RexLiteral literal = (RexLiteral) expr.e;
            projectPullUpPredicates.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexBuilder.makeInputRef(project, expr.i), literal));
        } else if (expr.e instanceof RexCall && HiveCalciteUtil.isDeterministicFuncOnLiterals(expr.e)) {
            // TODO: Move this to calcite
            projectPullUpPredicates.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexBuilder.makeInputRef(project, expr.i), expr.e));
        }
    }
    return RelOptPredicateList.of(rexBuilder, projectPullUpPredicates);
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ArrayList(java.util.ArrayList) Mapping(org.apache.calcite.util.mapping.Mapping) RexCall(org.apache.calcite.rex.RexCall) RelNode(org.apache.calcite.rel.RelNode) RelOptPredicateList(org.apache.calcite.plan.RelOptPredicateList) RexBuilder(org.apache.calcite.rex.RexBuilder) RexInputRef(org.apache.calcite.rex.RexInputRef) RexPermuteInputsShuttle(org.apache.calcite.rex.RexPermuteInputsShuttle) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

Mapping (org.apache.calcite.util.mapping.Mapping)44 RelNode (org.apache.calcite.rel.RelNode)36 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)29 RelDataType (org.apache.calcite.rel.type.RelDataType)26 RexNode (org.apache.calcite.rex.RexNode)25 ArrayList (java.util.ArrayList)22 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)20 RelBuilder (org.apache.calcite.tools.RelBuilder)15 RexPermuteInputsShuttle (org.apache.calcite.rex.RexPermuteInputsShuttle)13 RexBuilder (org.apache.calcite.rex.RexBuilder)11 RelOptUtil (org.apache.calcite.plan.RelOptUtil)9 LinkedHashSet (java.util.LinkedHashSet)8 AggregateCall (org.apache.calcite.rel.core.AggregateCall)8 Aggregate (org.apache.calcite.rel.core.Aggregate)6 Join (org.apache.calcite.rel.core.Join)6 RexInputRef (org.apache.calcite.rex.RexInputRef)6 RexLiteral (org.apache.calcite.rex.RexLiteral)6 Mappings (org.apache.calcite.util.mapping.Mappings)6 ImmutableList (com.google.common.collect.ImmutableList)5 HashMap (java.util.HashMap)5