Search in sources :

Example 1 with ImmutableIntList

use of org.apache.calcite.util.ImmutableIntList in project hive by apache.

the class HiveSemiJoinRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    LOG.debug("Matched HiveSemiJoinRule");
    final Project project = call.rel(0);
    final Join join = call.rel(1);
    final RelNode left = call.rel(2);
    final Aggregate aggregate = call.rel(3);
    final RelOptCluster cluster = join.getCluster();
    final RexBuilder rexBuilder = cluster.getRexBuilder();
    final ImmutableBitSet bits = RelOptUtil.InputFinder.bits(project.getProjects(), null);
    final ImmutableBitSet rightBits = ImmutableBitSet.range(left.getRowType().getFieldCount(), join.getRowType().getFieldCount());
    if (bits.intersects(rightBits)) {
        return;
    }
    final JoinInfo joinInfo = join.analyzeCondition();
    if (!joinInfo.rightSet().equals(ImmutableBitSet.range(aggregate.getGroupCount()))) {
        // By the way, neither a super-set nor a sub-set would work.
        return;
    }
    if (join.getJoinType() == JoinRelType.LEFT) {
        // since for LEFT join we are only interested in rows from LEFT we can get rid of right side
        call.transformTo(call.builder().push(left).project(project.getProjects(), project.getRowType().getFieldNames()).build());
        return;
    }
    if (join.getJoinType() != JoinRelType.INNER) {
        return;
    }
    if (!joinInfo.isEqui()) {
        return;
    }
    LOG.debug("All conditions matched for HiveSemiJoinRule. Going to apply transformation.");
    final List<Integer> newRightKeyBuilder = Lists.newArrayList();
    final List<Integer> aggregateKeys = aggregate.getGroupSet().asList();
    for (int key : joinInfo.rightKeys) {
        newRightKeyBuilder.add(aggregateKeys.get(key));
    }
    final ImmutableIntList newRightKeys = ImmutableIntList.copyOf(newRightKeyBuilder);
    final RelNode newRight = aggregate.getInput();
    final RexNode newCondition = RelOptUtil.createEquiJoinCondition(left, joinInfo.leftKeys, newRight, newRightKeys, rexBuilder);
    RelNode semi = null;
    // is not expected further down the pipeline. see jira for more details
    if (aggregate.getInput() instanceof HepRelVertex && ((HepRelVertex) aggregate.getInput()).getCurrentRel() instanceof Join) {
        Join rightJoin = (Join) (((HepRelVertex) aggregate.getInput()).getCurrentRel());
        List<RexNode> projects = new ArrayList<>();
        for (int i = 0; i < rightJoin.getRowType().getFieldCount(); i++) {
            projects.add(rexBuilder.makeInputRef(rightJoin, i));
        }
        RelNode topProject = call.builder().push(rightJoin).project(projects, rightJoin.getRowType().getFieldNames(), true).build();
        semi = call.builder().push(left).push(topProject).semiJoin(newCondition).build();
    } else {
        semi = call.builder().push(left).push(aggregate.getInput()).semiJoin(newCondition).build();
    }
    call.transformTo(call.builder().push(semi).project(project.getProjects(), project.getRowType().getFieldNames()).build());
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ArrayList(java.util.ArrayList) Join(org.apache.calcite.rel.core.Join) JoinInfo(org.apache.calcite.rel.core.JoinInfo) Project(org.apache.calcite.rel.core.Project) HepRelVertex(org.apache.calcite.plan.hep.HepRelVertex) RelNode(org.apache.calcite.rel.RelNode) RexBuilder(org.apache.calcite.rex.RexBuilder) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) Aggregate(org.apache.calcite.rel.core.Aggregate) RexNode(org.apache.calcite.rex.RexNode)

Example 2 with ImmutableIntList

use of org.apache.calcite.util.ImmutableIntList in project calcite by apache.

the class TableScanNode method createProjectableFilterable.

private static TableScanNode createProjectableFilterable(Compiler compiler, TableScan rel, ImmutableList<RexNode> filters, ImmutableIntList projects, ProjectableFilterableTable pfTable) {
    final DataContext root = compiler.getDataContext();
    final ImmutableIntList originalProjects = projects;
    for (; ; ) {
        final List<RexNode> mutableFilters = Lists.newArrayList(filters);
        final int[] projectInts;
        if (projects == null || projects.equals(TableScan.identity(rel.getTable()))) {
            projectInts = null;
        } else {
            projectInts = projects.toIntArray();
        }
        final Enumerable<Object[]> enumerable1 = pfTable.scan(root, mutableFilters, projectInts);
        for (RexNode filter : mutableFilters) {
            if (!filters.contains(filter)) {
                throw RESOURCE.filterableTableInventedFilter(filter.toString()).ex();
            }
        }
        final ImmutableBitSet usedFields = RelOptUtil.InputFinder.bits(mutableFilters, null);
        if (projects != null) {
            int changeCount = 0;
            for (int usedField : usedFields) {
                if (!projects.contains(usedField)) {
                    // A field that is not projected is used in a filter that the
                    // table rejected. We won't be able to apply the filter later.
                    // Try again without any projects.
                    projects = ImmutableIntList.copyOf(Iterables.concat(projects, ImmutableList.of(usedField)));
                    ++changeCount;
                }
            }
            if (changeCount > 0) {
                continue;
            }
        }
        final Enumerable<Row> rowEnumerable = Enumerables.toRow(enumerable1);
        final ImmutableIntList rejectedProjects;
        if (Objects.equals(projects, originalProjects)) {
            rejectedProjects = null;
        } else {
            // We projected extra columns because they were needed in filters. Now
            // project the leading columns.
            rejectedProjects = ImmutableIntList.identity(originalProjects.size());
        }
        return createEnumerable(compiler, rel, rowEnumerable, projects, mutableFilters, rejectedProjects);
    }
}
Also used : DataContext(org.apache.calcite.DataContext) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) RexNode(org.apache.calcite.rex.RexNode)

Example 3 with ImmutableIntList

use of org.apache.calcite.util.ImmutableIntList in project calcite by apache.

the class ModifiableViewTable method extend.

/**
 * Extends the underlying table and returns a new view with updated row-type
 * and column-mapping.
 *
 * <p>The type factory is used to perform some scratch calculations, viz the
 * type mapping, but the "real" row-type will be assigned later, when the
 * table has been bound to the statement's type factory. The is important,
 * because adding types to type factories that do not belong to a statement
 * could potentially leak memory.
 *
 * @param extendedColumns Extended fields
 * @param typeFactory Type factory
 */
public final ModifiableViewTable extend(List<RelDataTypeField> extendedColumns, RelDataTypeFactory typeFactory) {
    final ExtensibleTable underlying = unwrap(ExtensibleTable.class);
    assert underlying != null;
    final RelDataTypeFactory.Builder builder = typeFactory.builder();
    final RelDataType rowType = getRowType(typeFactory);
    for (RelDataTypeField column : rowType.getFieldList()) {
        builder.add(column);
    }
    for (RelDataTypeField column : extendedColumns) {
        builder.add(column);
    }
    // The characteristics of the new view.
    final RelDataType newRowType = builder.build();
    final ImmutableIntList newColumnMapping = getNewColumnMapping(underlying, getColumnMapping(), extendedColumns, typeFactory);
    // Extend the underlying table with only the fields that
    // duplicate column names in neither the view nor the base table.
    final List<RelDataTypeField> underlyingColumns = underlying.getRowType(typeFactory).getFieldList();
    final List<RelDataTypeField> columnsOfExtendedBaseTable = RelOptUtil.deduplicateColumns(underlyingColumns, extendedColumns);
    final List<RelDataTypeField> extendColumnsOfBaseTable = columnsOfExtendedBaseTable.subList(underlyingColumns.size(), columnsOfExtendedBaseTable.size());
    final Table extendedTable = underlying.extend(extendColumnsOfBaseTable);
    return extend(extendedTable, RelDataTypeImpl.proto(newRowType), newColumnMapping);
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelOptTable(org.apache.calcite.plan.RelOptTable) Table(org.apache.calcite.schema.Table) ExtensibleTable(org.apache.calcite.schema.ExtensibleTable) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RelDataType(org.apache.calcite.rel.type.RelDataType) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) ExtensibleTable(org.apache.calcite.schema.ExtensibleTable)

Example 4 with ImmutableIntList

use of org.apache.calcite.util.ImmutableIntList in project calcite by apache.

the class JoinToMultiJoinRule method onMatch.

// ~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
    final Join origJoin = call.rel(0);
    final RelNode left = call.rel(1);
    final RelNode right = call.rel(2);
    // combine the children MultiJoin inputs into an array of inputs
    // for the new MultiJoin
    final List<ImmutableBitSet> projFieldsList = Lists.newArrayList();
    final List<int[]> joinFieldRefCountsList = Lists.newArrayList();
    final List<RelNode> newInputs = combineInputs(origJoin, left, right, projFieldsList, joinFieldRefCountsList);
    // combine the outer join information from the left and right
    // inputs, and include the outer join information from the current
    // join, if it's a left/right outer join
    final List<Pair<JoinRelType, RexNode>> joinSpecs = Lists.newArrayList();
    combineOuterJoins(origJoin, newInputs, left, right, joinSpecs);
    // pull up the join filters from the children MultiJoinRels and
    // combine them with the join filter associated with this LogicalJoin to
    // form the join filter for the new MultiJoin
    List<RexNode> newJoinFilters = combineJoinFilters(origJoin, left, right);
    // add on the join field reference counts for the join condition
    // associated with this LogicalJoin
    final ImmutableMap<Integer, ImmutableIntList> newJoinFieldRefCountsMap = addOnJoinFieldRefCounts(newInputs, origJoin.getRowType().getFieldCount(), origJoin.getCondition(), joinFieldRefCountsList);
    List<RexNode> newPostJoinFilters = combinePostJoinFilters(origJoin, left, right);
    final RexBuilder rexBuilder = origJoin.getCluster().getRexBuilder();
    RelNode multiJoin = new MultiJoin(origJoin.getCluster(), newInputs, RexUtil.composeConjunction(rexBuilder, newJoinFilters, false), origJoin.getRowType(), origJoin.getJoinType() == JoinRelType.FULL, Pair.right(joinSpecs), Pair.left(joinSpecs), projFieldsList, newJoinFieldRefCountsMap, RexUtil.composeConjunction(rexBuilder, newPostJoinFilters, true));
    call.transformTo(multiJoin);
}
Also used : ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) Join(org.apache.calcite.rel.core.Join) LogicalJoin(org.apache.calcite.rel.logical.LogicalJoin) RelNode(org.apache.calcite.rel.RelNode) RexBuilder(org.apache.calcite.rex.RexBuilder) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) Pair(org.apache.calcite.util.Pair) RexNode(org.apache.calcite.rex.RexNode)

Example 5 with ImmutableIntList

use of org.apache.calcite.util.ImmutableIntList in project calcite by apache.

the class LoptOptimizeJoinRule method createReplacementSemiJoin.

/**
 * In the event that a dimension table does not need to be joined because of
 * a semijoin, this method creates a join tree that consists of a projection
 * on top of an existing join tree. The existing join tree must contain the
 * fact table in the semijoin that allows the dimension table to be removed.
 *
 * <p>The projection created on top of the join tree mimics a join of the
 * fact and dimension tables. In order for the dimension table to have been
 * removed, the only fields referenced from the dimension table are its
 * dimension keys. Therefore, we can replace these dimension fields with the
 * fields corresponding to the semijoin keys from the fact table in the
 * projection.
 *
 * @param multiJoin join factors being optimized
 * @param semiJoinOpt optimal semijoins for each factor
 * @param factTree existing join tree containing the fact table
 * @param dimIdx dimension table factor id
 * @param filtersToAdd filters remaining to be added; filters added to the
 * new join tree are removed from the list
 *
 * @return created join tree or null if the corresponding fact table has not
 * been joined in yet
 */
private LoptJoinTree createReplacementSemiJoin(RelBuilder relBuilder, LoptMultiJoin multiJoin, LoptSemiJoinOptimizer semiJoinOpt, LoptJoinTree factTree, int dimIdx, List<RexNode> filtersToAdd) {
    // don't bother trying to create the replacement join just yet
    if (factTree == null) {
        return null;
    }
    int factIdx = multiJoin.getJoinRemovalFactor(dimIdx);
    final List<Integer> joinOrder = factTree.getTreeOrder();
    assert joinOrder.contains(factIdx);
    // figure out the position of the fact table in the current jointree
    int adjustment = 0;
    for (Integer factor : joinOrder) {
        if (factor == factIdx) {
            break;
        }
        adjustment += multiJoin.getNumFieldsInJoinFactor(factor);
    }
    // map the dimension keys to the corresponding keys from the fact
    // table, based on the fact table's position in the current jointree
    List<RelDataTypeField> dimFields = multiJoin.getJoinFactor(dimIdx).getRowType().getFieldList();
    int nDimFields = dimFields.size();
    Integer[] replacementKeys = new Integer[nDimFields];
    SemiJoin semiJoin = multiJoin.getJoinRemovalSemiJoin(dimIdx);
    ImmutableIntList dimKeys = semiJoin.getRightKeys();
    ImmutableIntList factKeys = semiJoin.getLeftKeys();
    for (int i = 0; i < dimKeys.size(); i++) {
        replacementKeys[dimKeys.get(i)] = factKeys.get(i) + adjustment;
    }
    return createReplacementJoin(relBuilder, multiJoin, semiJoinOpt, factTree, factIdx, dimIdx, dimKeys, replacementKeys, filtersToAdd);
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) SemiJoin(org.apache.calcite.rel.core.SemiJoin) ImmutableIntList(org.apache.calcite.util.ImmutableIntList)

Aggregations

ImmutableIntList (org.apache.calcite.util.ImmutableIntList)17 RexNode (org.apache.calcite.rex.RexNode)11 RexBuilder (org.apache.calcite.rex.RexBuilder)6 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)6 ArrayList (java.util.ArrayList)5 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)5 RelNode (org.apache.calcite.rel.RelNode)4 Join (org.apache.calcite.rel.core.Join)4 RelOptCluster (org.apache.calcite.plan.RelOptCluster)3 JoinInfo (org.apache.calcite.rel.core.JoinInfo)3 RelDataType (org.apache.calcite.rel.type.RelDataType)3 ImmutableList (com.google.common.collect.ImmutableList)2 Bindables (org.apache.calcite.interpreter.Bindables)2 RelOptTable (org.apache.calcite.plan.RelOptTable)2 HepRelVertex (org.apache.calcite.plan.hep.HepRelVertex)2 RelCollation (org.apache.calcite.rel.RelCollation)2 SemiJoin (org.apache.calcite.rel.core.SemiJoin)2 RelMetadataQuery (org.apache.calcite.rel.metadata.RelMetadataQuery)2 Pair (org.apache.calcite.util.Pair)2 HashMap (java.util.HashMap)1