org.apache.calcite.util.ImmutableBitSet

Here are the examples of the java api org.apache.calcite.util.ImmutableBitSet taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

254 Examples 7

19 Source : StreamAggPrel.java
with Apache License 2.0
from zpochen

@Override
public Aggregate copy(RelTraitSet traitSet, RelNode input, boolean indicator, ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) {
    try {
        return new StreamAggPrel(getCluster(), traitSet, input, indicator, groupSet, groupSets, aggCalls, this.getOperatorPhase());
    } catch (InvalidRelException e) {
        throw new replacedertionError(e);
    }
}

19 Source : HashAggPrel.java
with Apache License 2.0
from zpochen

@Override
public Aggregate copy(RelTraitSet traitSet, RelNode input, boolean indicator, ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) {
    try {
        return new HashAggPrel(getCluster(), traitSet, input, indicator, groupSet, groupSets, aggCalls, this.getOperatorPhase());
    } catch (InvalidRelException e) {
        throw new replacedertionError(e);
    }
}

19 Source : DrillRelMdRowCount.java
with Apache License 2.0
from zpochen

@Override
public Double getRowCount(Aggregate rel, RelMetadataQuery mq) {
    ImmutableBitSet groupKey = ImmutableBitSet.range(rel.getGroupCount());
    if (groupKey.isEmpty()) {
        return 1.0;
    } else {
        return super.getRowCount(rel, mq);
    }
}

19 Source : DrillRelMdDistinctRowCount.java
with Apache License 2.0
from zpochen

@Override
public Double getDistinctRowCount(RelNode rel, RelMetadataQuery mq, ImmutableBitSet groupKey, RexNode predicate) {
    if (rel instanceof DrillScanRel) {
        return getDistinctRowCount((DrillScanRel) rel, groupKey, predicate);
    } else {
        return super.getDistinctRowCount(rel, mq, groupKey, predicate);
    }
}

19 Source : DrillRelMdDistinctRowCount.java
with Apache License 2.0
from zpochen

private Double getDistinctRowCount(DrillScanRel scan, ImmutableBitSet groupKey, RexNode predicate) {
    // Consistent with the estimation of Aggregate row count in RelMdRowCount : distinctRowCount = rowCount * 10%.
    return scan.getRows() * 0.1;
}

19 Source : CSVRelMdDistinctRowCount.java
with MIT License
from shezhiming

@Override
public Double getDistinctRowCount(RelNode rel, RelMetadataQuery mq, ImmutableBitSet groupKey, RexNode predicate) {
    // return getDistinctRowCount( rel, mq, groupKey, predicate);
    /*
         * For now use Calcite' default formulas for propagating NDVs up the Query
         * Tree.
         */
    return super.getDistinctRowCount(rel, mq, groupKey, predicate);
}

19 Source : MycatStatistic.java
with GNU General Public License v3.0
from MyCATApache

public boolean isKey(ImmutableBitSet columns) {
    return false;
}

19 Source : RelNodeConvertor.java
with GNU General Public License v3.0
from MyCATApache

private static List<GroupKey> getGroupItems(LogicalAggregate aggregate) {
    List<GroupKey> list = new ArrayList<>();
    List<String> fieldNames = aggregate.getInput().getRowType().getFieldNames();
    final ImmutableList<ImmutableBitSet> groupSets = aggregate.getGroupSets();
    for (ImmutableBitSet set : groupSets) {
        List<Expr> arrayList = new ArrayList<>();
        for (Integer integer : set) {
            arrayList.add(new Identifier(fieldNames.get(integer)));
        }
        list.add(new GroupKey(arrayList));
    }
    return list;
}

19 Source : MycatHashAggregate.java
with GNU General Public License v3.0
from MyCATApache

public static MycatHashAggregate create(RelTraitSet traitSet, RelNode input, ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) {
    traitSet = traitSet.replace(MycatConvention.INSTANCE);
    return new MycatHashAggregate(input.getCluster(), traitSet, input, groupSet, groupSets, aggCalls);
}

19 Source : MycatHashAggregate.java
with GNU General Public License v3.0
from MyCATApache

@Override
public MycatHashAggregate copy(RelTraitSet traitSet, RelNode input, ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) {
    return new MycatHashAggregate(getCluster(), traitSet, input, groupSet, groupSets, aggCalls);
}

19 Source : MycatCorrelate.java
with GNU General Public License v3.0
from MyCATApache

@Override
public Correlate copy(RelTraitSet traitSet, RelNode left, RelNode right, CorrelationId correlationId, ImmutableBitSet requiredColumns, JoinRelType joinType) {
    return new MycatCorrelate(getCluster(), traitSet.replace(MycatConvention.INSTANCE), left, right, correlationId, requiredColumns, joinType);
}

19 Source : MycatCorrelate.java
with GNU General Public License v3.0
from MyCATApache

public static MycatCorrelate create(RelTraitSet traitSet, RelNode left, RelNode right, CorrelationId correlationId, ImmutableBitSet requiredColumns, JoinRelType joinType) {
    RelOptCluster cluster = left.getCluster();
    RelMetadataQuery mq = cluster.getMetadataQuery();
    traitSet = traitSet.replace(MycatConvention.INSTANCE);
    traitSet = traitSet.replaceIfs(RelCollationTraitDef.INSTANCE, () -> RelMdCollation.enumerableCorrelate(mq, left, right, joinType));
    return new MycatCorrelate(cluster, traitSet, left, right, correlationId, requiredColumns, joinType);
}

19 Source : MycatBatchNestedLoopJoin.java
with GNU General Public License v3.0
from MyCATApache

/**
 * the right of input must be Lookup Executor
 */
public clreplaced MycatBatchNestedLoopJoin extends Join implements MycatRel {

    private final ImmutableBitSet requiredColumns;

    protected MycatBatchNestedLoopJoin(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode right, RexNode condition, Set<CorrelationId> variablesSet, ImmutableBitSet requiredColumns, JoinRelType joinType) {
        super(cluster, traits, ImmutableList.of(), left, right, condition, variablesSet, joinType);
        this.requiredColumns = requiredColumns;
    }

    @Override
    public ExplainWriter explain(ExplainWriter writer) {
        writer.name("MycatBatchNestedLoopJoin");
        writer.into();
        List<RelNode> inputs = getInputs();
        for (RelNode input : inputs) {
            ((MycatRel) input).explain(writer);
        }
        return writer.ret();
    }

    @Override
    public MycatBatchNestedLoopJoin copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode right, JoinRelType joinType, boolean semiJoinDone) {
        return new MycatBatchNestedLoopJoin(getCluster(), traitSet, left, right, condition, variablesSet, requiredColumns, joinType);
    }

    public static MycatBatchNestedLoopJoin create(RelNode left, RelNode right, RexNode condition, ImmutableBitSet requiredColumns, Set<CorrelationId> variablesSet, JoinRelType joinType) {
        final RelOptCluster cluster = left.getCluster();
        final RelMetadataQuery mq = cluster.getMetadataQuery();
        final RelTraitSet traitSet = cluster.traitSetOf(MycatConvention.INSTANCE).replaceIfs(RelCollationTraitDef.INSTANCE, () -> RelMdCollation.enumerableBatchNestedLoopJoin(mq, left, right, joinType));
        return new MycatBatchNestedLoopJoin(cluster, traitSet, left, right, condition, variablesSet, requiredColumns, joinType);
    }

    public ImmutableBitSet getRequiredColumns() {
        return requiredColumns;
    }
}

19 Source : MycatBatchNestedLoopJoin.java
with GNU General Public License v3.0
from MyCATApache

public static MycatBatchNestedLoopJoin create(RelNode left, RelNode right, RexNode condition, ImmutableBitSet requiredColumns, Set<CorrelationId> variablesSet, JoinRelType joinType) {
    final RelOptCluster cluster = left.getCluster();
    final RelMetadataQuery mq = cluster.getMetadataQuery();
    final RelTraitSet traitSet = cluster.traitSetOf(MycatConvention.INSTANCE).replaceIfs(RelCollationTraitDef.INSTANCE, () -> RelMdCollation.enumerableBatchNestedLoopJoin(mq, left, right, joinType));
    return new MycatBatchNestedLoopJoin(cluster, traitSet, left, right, condition, variablesSet, requiredColumns, joinType);
}

19 Source : Mappings.java
with Apache License 2.0
from lealone

/**
 * Applies a mapping to an {@code ImmutableBitSet}.
 *
 * <p>If the mapping does not affect the bit set, returns the original.
 * Never changes the original.
 *
 * @param mapping Mapping
 * @param bitSet  Bit set
 * @return Bit set with mapping applied
 */
public static ImmutableBitSet apply(Mapping mapping, ImmutableBitSet bitSet) {
    final ImmutableBitSet.Builder builder = ImmutableBitSet.builder();
    for (int source : bitSet) {
        final int target = mapping.getTarget(source);
        builder.set(target);
    }
    return builder.build(bitSet);
}

19 Source : RelFieldTrimmer.java
with Apache License 2.0
from lealone

protected Mapping createMapping(ImmutableBitSet fieldsUsed, int fieldCount) {
    final Mapping mapping = Mappings.create(MappingType.INVERSE_SURJECTION, fieldCount, fieldsUsed.cardinality());
    int i = 0;
    for (int field : fieldsUsed) {
        mapping.set(field, i++);
    }
    return mapping;
}

19 Source : RelFieldTrimmer.java
with Apache License 2.0
from lealone

/**
 * 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()) {
        // if there is nothing to project or if we are projecting everything
        // then no need to introduce another RelNode
        return trimFields((RelNode) tableAccessRel, fieldsUsed, extraFields);
    }
    final RelNode newTableAccessRel = tableAccessRel.project(fieldsUsed, extraFields, relBuilder);
    // Some parts of the system can't handle rows with zero fields, so
    // 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);
}

19 Source : AggregatingSelectScope.java
with Apache License 2.0
from lealone

private static boolean allContain(List<ImmutableBitSet> bitSets, int bit) {
    for (ImmutableBitSet bitSet : bitSets) {
        if (!bitSet.get(bit)) {
            return false;
        }
    }
    return true;
}

19 Source : PushProjector.java
with Apache License 2.0
from lealone

/**
 * PushProjector is a utility clreplaced used to perform operations used in push
 * projection rules.
 *
 * <p>Pushing is particularly interesting in the case of join, because there
 * are multiple inputs. Generally an expression can be pushed down to a
 * particular input if it depends upon no other inputs. If it can be pushed
 * down to both sides, it is pushed down to the left.
 *
 * <p>Sometimes an expression needs to be split before it can be pushed down.
 * To flag that an expression cannot be split, specify a rule that it must be
 * <dfn>preserved</dfn>. Such an expression will be pushed down intact to one
 * of the inputs, or not pushed down at all.</p>
 */
public clreplaced PushProjector {

    // ~ Instance fields --------------------------------------------------------
    private final Project origProj;

    private final RexNode origFilter;

    private final RelNode childRel;

    private final ExprCondition preserveExprCondition;

    private final RelBuilder relBuilder;

    /**
     * Original projection expressions
     */
    final List<RexNode> origProjExprs;

    /**
     * Fields from the RelNode that the projection is being pushed past
     */
    final List<RelDataTypeField> childFields;

    /**
     * Number of fields in the RelNode that the projection is being pushed past
     */
    final int nChildFields;

    /**
     * Bitmap containing the references in the original projection
     */
    final BitSet projRefs;

    /**
     * Bitmap containing the fields in the RelNode that the projection is being
     * pushed past, if the RelNode is not a join. If the RelNode is a join, then
     * the fields correspond to the left hand side of the join.
     */
    final ImmutableBitSet childBitmap;

    /**
     * Bitmap containing the fields in the right hand side of a join, in the
     * case where the projection is being pushed past a join. Not used
     * otherwise.
     */
    final ImmutableBitSet rightBitmap;

    /**
     * Bitmap containing the fields that should be strong, i.e. when preserving expressions
     * we can only preserve them if the expressions if it is null when these fields are null.
     */
    final ImmutableBitSet strongBitmap;

    /**
     * Number of fields in the RelNode that the projection is being pushed past,
     * if the RelNode is not a join. If the RelNode is a join, then this is the
     * number of fields in the left hand side of the join.
     *
     * <p>The idenreplacedy
     * {@code nChildFields == nSysFields + nFields + nFieldsRight}
     * holds. {@code nFields} does not include {@code nSysFields}.
     * The output of a join looks like this:
     *
     * <blockquote><pre>
     * | nSysFields | nFields | nFieldsRight |
     * </pre></blockquote>
     *
     * <p>The output of a single-input rel looks like this:
     *
     * <blockquote><pre>
     * | nSysFields | nFields |
     * </pre></blockquote>
     */
    final int nFields;

    /**
     * Number of fields in the right hand side of a join, in the case where the
     * projection is being pushed past a join. Always 0 otherwise.
     */
    final int nFieldsRight;

    /**
     * Number of system fields. System fields appear at the start of a join,
     * before the first field from the left input.
     */
    private final int nSysFields;

    /**
     * Expressions referenced in the projection/filter that should be preserved.
     * In the case where the projection is being pushed past a join, then the
     * list only contains the expressions corresponding to the left hand side of
     * the join.
     */
    final List<RexNode> childPreserveExprs;

    /**
     * Expressions referenced in the projection/filter that should be preserved,
     * corresponding to expressions on the right hand side of the join, if the
     * projection is being pushed past a join. Empty list otherwise.
     */
    final List<RexNode> rightPreserveExprs;

    /**
     * Number of system fields being projected.
     */
    int nSystemProject;

    /**
     * Number of fields being projected. In the case where the projection is
     * being pushed past a join, the number of fields being projected from the
     * left hand side of the join.
     */
    int nProject;

    /**
     * Number of fields being projected from the right hand side of a join, in
     * the case where the projection is being pushed past a join. 0 otherwise.
     */
    int nRightProject;

    /**
     * Rex builder used to create new expressions.
     */
    final RexBuilder rexBuilder;

    // ~ Constructors -----------------------------------------------------------
    /**
     * Creates a PushProjector object for pushing projects past a RelNode.
     *
     * @param origProj              the original projection that is being pushed;
     *                              may be null if the projection is implied as a
     *                              result of a projection having been trivially
     *                              removed
     * @param origFilter            the filter that the projection must also be
     *                              pushed past, if applicable
     * @param childRel              the RelNode that the projection is being
     *                              pushed past
     * @param preserveExprCondition condition for whether an expression should
     *                              be preserved in the projection
     */
    public PushProjector(Project origProj, RexNode origFilter, RelNode childRel, ExprCondition preserveExprCondition, RelBuilder relBuilder) {
        this.origProj = origProj;
        this.origFilter = origFilter;
        this.childRel = childRel;
        this.preserveExprCondition = preserveExprCondition;
        this.relBuilder = Objects.requireNonNull(relBuilder);
        if (origProj == null) {
            origProjExprs = ImmutableList.of();
        } else {
            origProjExprs = origProj.getProjects();
        }
        childFields = childRel.getRowType().getFieldList();
        nChildFields = childFields.size();
        projRefs = new BitSet(nChildFields);
        if (childRel instanceof Join) {
            Join joinRel = (Join) childRel;
            List<RelDataTypeField> leftFields = joinRel.getLeft().getRowType().getFieldList();
            List<RelDataTypeField> rightFields = joinRel.getRight().getRowType().getFieldList();
            nFields = leftFields.size();
            nFieldsRight = childRel instanceof SemiJoin ? 0 : rightFields.size();
            nSysFields = joinRel.getSystemFieldList().size();
            childBitmap = ImmutableBitSet.range(nSysFields, nFields + nSysFields);
            rightBitmap = ImmutableBitSet.range(nFields + nSysFields, nChildFields);
            switch(joinRel.getJoinType()) {
                case INNER:
                    strongBitmap = ImmutableBitSet.of();
                    break;
                case // All the left-input's columns must be strong
                RIGHT:
                    strongBitmap = ImmutableBitSet.range(nSysFields, nFields + nSysFields);
                    break;
                case // All the right-input's columns must be strong
                LEFT:
                    strongBitmap = ImmutableBitSet.range(nFields + nSysFields, nChildFields);
                    break;
                case FULL:
                default:
                    strongBitmap = ImmutableBitSet.range(nSysFields, nChildFields);
            }
        } else if (childRel instanceof Correlate) {
            Correlate corrRel = (Correlate) childRel;
            List<RelDataTypeField> leftFields = corrRel.getLeft().getRowType().getFieldList();
            List<RelDataTypeField> rightFields = corrRel.getRight().getRowType().getFieldList();
            nFields = leftFields.size();
            SemiJoinType joinType = corrRel.getJoinType();
            switch(joinType) {
                case SEMI:
                case ANTI:
                    nFieldsRight = 0;
                    break;
                default:
                    nFieldsRight = rightFields.size();
            }
            nSysFields = 0;
            childBitmap = ImmutableBitSet.range(0, nFields);
            rightBitmap = ImmutableBitSet.range(nFields, nChildFields);
            // Required columns need to be included in project
            projRefs.or(BitSets.of(corrRel.getRequiredColumns()));
            switch(joinType) {
                case INNER:
                    strongBitmap = ImmutableBitSet.of();
                    break;
                case ANTI:
                case // All the left-input's columns must be strong
                SEMI:
                    strongBitmap = ImmutableBitSet.range(0, nFields);
                    break;
                case // All the right-input's columns must be strong
                LEFT:
                    strongBitmap = ImmutableBitSet.range(nFields, nChildFields);
                    break;
                default:
                    strongBitmap = ImmutableBitSet.range(0, nChildFields);
            }
        } else {
            nFields = nChildFields;
            nFieldsRight = 0;
            childBitmap = ImmutableBitSet.range(nChildFields);
            rightBitmap = null;
            nSysFields = 0;
            strongBitmap = ImmutableBitSet.of();
        }
        replacedert nChildFields == nSysFields + nFields + nFieldsRight;
        childPreserveExprs = new ArrayList<>();
        rightPreserveExprs = new ArrayList<>();
        rexBuilder = childRel.getCluster().getRexBuilder();
    }

    // ~ Methods ----------------------------------------------------------------
    /**
     * Decomposes a projection to the input references referenced by a
     * projection and a filter, either of which is optional. If both are
     * provided, the filter is underneath the project.
     *
     * <p>Creates a projection containing all input references as well as
     * preserving any special expressions. Converts the original projection
     * and/or filter to reference the new projection. Then, finally puts on top,
     * a final projection corresponding to the original projection.
     *
     * @param defaultExpr expression to be used in the projection if no fields
     *                    or special columns are selected
     * @return the converted projection if it makes sense to push elements of
     * the projection; otherwise returns null
     */
    public RelNode convertProject(RexNode defaultExpr) {
        // locate all fields referenced in the projection and filter
        locateAllRefs();
        // if all columns are being selected (either explicitly in the
        // projection) or via a "select *", then there needs to be some
        // special expressions to preserve in the projection; otherwise,
        // there's no point in proceeding any further
        if (origProj == null) {
            if (childPreserveExprs.size() == 0) {
                return null;
            }
            // even though there is no projection, this is the same as
            // selecting all fields
            if (nChildFields > 0) {
                // Calling with nChildFields == 0 should be safe but hits
                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6222207
                projRefs.set(0, nChildFields);
            }
            nProject = nChildFields;
        } else if ((projRefs.cardinality() == nChildFields) && (childPreserveExprs.size() == 0)) {
            return null;
        }
        // if nothing is being selected from the underlying rel, just
        // project the default expression preplaceded in as a parameter or the
        // first column if there is no default expression
        if ((projRefs.cardinality() == 0) && (childPreserveExprs.size() == 0)) {
            if (defaultExpr != null) {
                childPreserveExprs.add(defaultExpr);
            } else if (nChildFields == 1) {
                return null;
            } else {
                projRefs.set(0);
                nProject = 1;
            }
        }
        // create a new projection referencing all fields referenced in
        // either the project or the filter
        RelNode newProject = createProjectRefsAndExprs(childRel, false, false);
        int[] adjustments = getAdjustments();
        // if a filter was preplaceded in, convert it to reference the projected
        // columns, placing it on top of the project just created
        RelNode projChild;
        if (origFilter != null) {
            RexNode newFilter = convertRefsAndExprs(origFilter, newProject.getRowType().getFieldList(), adjustments);
            relBuilder.push(newProject);
            relBuilder.filter(newFilter);
            projChild = relBuilder.build();
        } else {
            projChild = newProject;
        }
        // put the original project on top of the filter/project, converting
        // it to reference the modified projection list; otherwise, create
        // a projection that essentially selects all fields
        return createNewProject(projChild, adjustments);
    }

    /**
     * Locates all references found in either the projection expressions a
     * filter, as well as references to expressions that should be preserved.
     * Based on that, determines whether pushing the projection makes sense.
     *
     * @return true if all inputs from the child that the projection is being
     * pushed past are referenced in the projection/filter and no special
     * preserve expressions are referenced; in that case, it does not make sense
     * to push the projection
     */
    public boolean locateAllRefs() {
        RexUtil.apply(new InputSpecialOpFinder(projRefs, childBitmap, rightBitmap, strongBitmap, preserveExprCondition, childPreserveExprs, rightPreserveExprs), origProjExprs, origFilter);
        // The system fields of each child are always used by the join, even if
        // they are not projected out of it.
        projRefs.set(nSysFields, nSysFields + nSysFields, true);
        projRefs.set(nSysFields + nFields, nSysFields + nFields + nSysFields, true);
        // Count how many fields are projected.
        nSystemProject = 0;
        nProject = 0;
        nRightProject = 0;
        for (int bit : BitSets.toIter(projRefs)) {
            if (bit < nSysFields) {
                nSystemProject++;
            } else if (bit < nSysFields + nFields) {
                nProject++;
            } else {
                nRightProject++;
            }
        }
        replacedert nSystemProject + nProject + nRightProject == projRefs.cardinality();
        if ((childRel instanceof Join) || (childRel instanceof SetOp)) {
            // if nothing is projected from the children, arbitrarily project
            // the first columns; this is necessary since Fennel doesn't
            // handle 0-column projections
            if ((nProject == 0) && (childPreserveExprs.size() == 0)) {
                projRefs.set(0);
                nProject = 1;
            }
            if (childRel instanceof Join) {
                if ((nRightProject == 0) && (rightPreserveExprs.size() == 0)) {
                    projRefs.set(nFields);
                    nRightProject = 1;
                }
            }
        }
        // no need to push projections if all children fields are being
        // referenced and there are no special preserve expressions; note
        // that we need to do this check after we've handled the 0-column
        // project cases
        if (projRefs.cardinality() == nChildFields && childPreserveExprs.size() == 0 && rightPreserveExprs.size() == 0) {
            return true;
        }
        return false;
    }

    /**
     * Creates a projection based on the inputs specified in a bitmap and the
     * expressions that need to be preserved. The expressions are appended after
     * the input references.
     *
     * @param projChild child that the projection will be created on top of
     * @param adjust    if true, need to create new projection expressions;
     *                  otherwise, the existing ones are reused
     * @param rightSide if true, creating a projection for the right hand side
     *                  of a join
     * @return created projection
     */
    public Project createProjectRefsAndExprs(RelNode projChild, boolean adjust, boolean rightSide) {
        List<RexNode> preserveExprs;
        int nInputRefs;
        int offset;
        if (rightSide) {
            preserveExprs = rightPreserveExprs;
            nInputRefs = nRightProject;
            offset = nSysFields + nFields;
        } else {
            preserveExprs = childPreserveExprs;
            nInputRefs = nProject;
            offset = nSysFields;
        }
        int refIdx = offset - 1;
        List<Pair<RexNode, String>> newProjects = new ArrayList<>();
        List<RelDataTypeField> destFields = projChild.getRowType().getFieldList();
        // add on the input references
        for (int i = 0; i < nInputRefs; i++) {
            refIdx = projRefs.nextSetBit(refIdx + 1);
            replacedert refIdx >= 0;
            final RelDataTypeField destField = destFields.get(refIdx - offset);
            newProjects.add(Pair.of((RexNode) rexBuilder.makeInputRef(destField.getType(), refIdx - offset), destField.getName()));
        }
        // add on the expressions that need to be preserved, converting the
        // arguments to reference the projected columns (if necessary)
        int[] adjustments = {};
        if ((preserveExprs.size() > 0) && adjust) {
            adjustments = new int[childFields.size()];
            for (int idx = offset; idx < childFields.size(); idx++) {
                adjustments[idx] = -offset;
            }
        }
        for (RexNode projExpr : preserveExprs) {
            RexNode newExpr;
            if (adjust) {
                newExpr = projExpr.accept(new RelOptUtil.RexInputConverter(rexBuilder, childFields, destFields, adjustments));
            } else {
                newExpr = projExpr;
            }
            newProjects.add(Pair.of(newExpr, ((RexCall) projExpr).getOperator().getName()));
        }
        return (Project) relBuilder.push(projChild).projectNamed(Pair.left(newProjects), Pair.right(newProjects), true).build();
    }

    /**
     * Determines how much each input reference needs to be adjusted as a result
     * of projection
     *
     * @return array indicating how much each input needs to be adjusted by
     */
    public int[] getAdjustments() {
        int[] adjustments = new int[nChildFields];
        int newIdx = 0;
        int rightOffset = childPreserveExprs.size();
        for (int pos : BitSets.toIter(projRefs)) {
            adjustments[pos] = -(pos - newIdx);
            if (pos >= nSysFields + nFields) {
                adjustments[pos] += rightOffset;
            }
            newIdx++;
        }
        return adjustments;
    }

    /**
     * Clones an expression tree and walks through it, adjusting each
     * RexInputRef index by some amount, and converting expressions that need to
     * be preserved to field references.
     *
     * @param rex         the expression
     * @param destFields  fields that the new expressions will be referencing
     * @param adjustments the amount each input reference index needs to be
     *                    adjusted by
     * @return modified expression tree
     */
    public RexNode convertRefsAndExprs(RexNode rex, List<RelDataTypeField> destFields, int[] adjustments) {
        return rex.accept(new RefAndExprConverter(rexBuilder, childFields, destFields, adjustments, childPreserveExprs, nProject, rightPreserveExprs, nProject + childPreserveExprs.size() + nRightProject));
    }

    /**
     * Creates a new projection based on the original projection, adjusting all
     * input refs using an adjustment array preplaceded in. If there was no original
     * projection, create a new one that selects every field from the underlying
     * rel.
     *
     * <p>If the resulting projection would be trivial, return the child.
     *
     * @param projChild   child of the new project
     * @param adjustments array indicating how much each input reference should
     *                    be adjusted by
     * @return the created projection
     */
    public RelNode createNewProject(RelNode projChild, int[] adjustments) {
        final List<Pair<RexNode, String>> projects = new ArrayList<>();
        if (origProj != null) {
            for (Pair<RexNode, String> p : origProj.getNamedProjects()) {
                projects.add(Pair.of(convertRefsAndExprs(p.left, projChild.getRowType().getFieldList(), adjustments), p.right));
            }
        } else {
            for (Ord<RelDataTypeField> field : Ord.zip(childFields)) {
                projects.add(Pair.of((RexNode) rexBuilder.makeInputRef(field.e.getType(), field.i), field.e.getName()));
            }
        }
        return relBuilder.push(projChild).project(Pair.left(projects), Pair.right(projects)).build();
    }

    // ~ Inner Clreplacedes ----------------------------------------------------------
    /**
     * Visitor which builds a bitmap of the inputs used by an expressions, as
     * well as locating expressions corresponding to special operators.
     */
    private clreplaced InputSpecialOpFinder extends RexVisitorImpl<Void> {

        private final BitSet rexRefs;

        private final ImmutableBitSet leftFields;

        private final ImmutableBitSet rightFields;

        private final ImmutableBitSet strongFields;

        private final ExprCondition preserveExprCondition;

        private final List<RexNode> preserveLeft;

        private final List<RexNode> preserveRight;

        private final Strong strong;

        InputSpecialOpFinder(BitSet rexRefs, ImmutableBitSet leftFields, ImmutableBitSet rightFields, final ImmutableBitSet strongFields, ExprCondition preserveExprCondition, List<RexNode> preserveLeft, List<RexNode> preserveRight) {
            super(true);
            this.rexRefs = rexRefs;
            this.leftFields = leftFields;
            this.rightFields = rightFields;
            this.preserveExprCondition = preserveExprCondition;
            this.preserveLeft = preserveLeft;
            this.preserveRight = preserveRight;
            this.strongFields = strongFields;
            this.strong = Strong.of(strongFields);
        }

        public Void visitCall(RexCall call) {
            if (preserve(call)) {
                return null;
            }
            super.visitCall(call);
            return null;
        }

        private boolean isStrong(final ImmutableBitSet exprArgs, final RexNode call) {
            // If the expressions do not use any of the inputs that require output to be null,
            // no need to check.  Otherwise, check that the expression is null.
            // For example, in an "left outer join", we don't require that expressions
            // pushed down into the left input to be strong.  On the other hand,
            // expressions pushed into the right input must be.  In that case,
            // strongFields == right input fields.
            return !strongFields.intersects(exprArgs) || strong.isNull(call);
        }

        private boolean preserve(RexNode call) {
            if (preserveExprCondition.test(call)) {
                // if the arguments of the expression only reference the
                // left hand side, preserve it on the left; similarly, if
                // it only references expressions on the right
                final ImmutableBitSet exprArgs = RelOptUtil.InputFinder.bits(call);
                if (exprArgs.cardinality() > 0) {
                    if (leftFields.contains(exprArgs) && isStrong(exprArgs, call)) {
                        if (!preserveLeft.contains(call)) {
                            preserveLeft.add(call);
                        }
                        return true;
                    } else if (rightFields.contains(exprArgs) && isStrong(exprArgs, call)) {
                        replacedert preserveRight != null;
                        if (!preserveRight.contains(call)) {
                            preserveRight.add(call);
                        }
                        return true;
                    }
                }
            // if the expression arguments reference both the left and
            // right, fall through and don't attempt to preserve the
            // expression, but instead locate references and special
            // ops in the call operands
            }
            return false;
        }

        public Void visitInputRef(RexInputRef inputRef) {
            rexRefs.set(inputRef.getIndex());
            return null;
        }
    }

    /**
     * Walks an expression tree, replacing input refs with new values to reflect
     * projection and converting special expressions to field references.
     */
    private clreplaced RefAndExprConverter extends RelOptUtil.RexInputConverter {

        private final List<RexNode> preserveLeft;

        private final int firstLeftRef;

        private final List<RexNode> preserveRight;

        private final int firstRightRef;

        RefAndExprConverter(RexBuilder rexBuilder, List<RelDataTypeField> srcFields, List<RelDataTypeField> destFields, int[] adjustments, List<RexNode> preserveLeft, int firstLeftRef, List<RexNode> preserveRight, int firstRightRef) {
            super(rexBuilder, srcFields, destFields, adjustments);
            this.preserveLeft = preserveLeft;
            this.firstLeftRef = firstLeftRef;
            this.preserveRight = preserveRight;
            this.firstRightRef = firstRightRef;
        }

        public RexNode visitCall(RexCall call) {
            // if the expression corresponds to one that needs to be preserved,
            // convert it to a field reference; otherwise, convert the entire
            // expression
            int match = findExprInLists(call, preserveLeft, firstLeftRef, preserveRight, firstRightRef);
            if (match >= 0) {
                return rexBuilder.makeInputRef(destFields.get(match).getType(), match);
            }
            return super.visitCall(call);
        }

        /**
         * Looks for a matching RexNode from among two lists of RexNodes and
         * returns the offset into the list corresponding to the match, adjusted
         * by an amount, depending on whether the match was from the first or
         * second list.
         *
         * @param rex      RexNode that is being matched against
         * @param rexList1 first list of RexNodes
         * @param adjust1  adjustment if match occurred in first list
         * @param rexList2 second list of RexNodes
         * @param adjust2  adjustment if match occurred in the second list
         * @return index in the list corresponding to the matching RexNode; -1
         * if no match
         */
        private int findExprInLists(RexNode rex, List<RexNode> rexList1, int adjust1, List<RexNode> rexList2, int adjust2) {
            int match = rexList1.indexOf(rex);
            if (match >= 0) {
                return match + adjust1;
            }
            if (rexList2 != null) {
                match = rexList2.indexOf(rex);
                if (match >= 0) {
                    return match + adjust2;
                }
            }
            return -1;
        }
    }

    /**
     * A functor that replies true or false for a given expression.
     *
     * @see org.apache.calcite.rel.rules.PushProjector.OperatorExprCondition
     */
    public interface ExprCondition extends Predicate<RexNode> {

        /**
         * Evaluates a condition for a given expression.
         *
         * @param expr Expression
         * @return result of evaluating the condition
         */
        boolean test(RexNode expr);

        /**
         * Constant condition that replies {@code false} for all expressions.
         */
        ExprCondition FALSE = expr -> false;

        /**
         * Constant condition that replies {@code true} for all expressions.
         */
        ExprCondition TRUE = expr -> true;
    }

    /**
     * An expression condition that evaluates to true if the expression is
     * a call to one of a set of operators.
     */
    clreplaced OperatorExprCondition implements ExprCondition {

        private final Set<SqlOperator> operatorSet;

        /**
         * Creates an OperatorExprCondition.
         *
         * @param operatorSet Set of operators
         */
        OperatorExprCondition(Iterable<? extends SqlOperator> operatorSet) {
            this.operatorSet = ImmutableSet.copyOf(operatorSet);
        }

        public boolean test(RexNode expr) {
            return expr instanceof RexCall && operatorSet.contains(((RexCall) expr).getOperator());
        }
    }
}

19 Source : ProjectWindowTransposeRule.java
with Apache License 2.0
from lealone

private int getAdjustedIndex(final int initIndex, final ImmutableBitSet beReferred, final int windowInputColumn) {
    if (initIndex >= windowInputColumn) {
        return beReferred.cardinality() + (initIndex - windowInputColumn);
    } else {
        return beReferred.get(0, initIndex).cardinality();
    }
}

19 Source : LoptMultiJoin.java
with Apache License 2.0
from lealone

/**
 * Utility clreplaced that keeps track of the join factors that
 * make up a {@link MultiJoin}.
 */
public clreplaced LoptMultiJoin {

    // ~ Instance fields --------------------------------------------------------
    /**
     * The MultiJoin being optimized
     */
    MultiJoin multiJoin;

    /**
     * Join filters replacedociated with the MultiJoin, decomposed into a list.
     * Excludes left/right outer join filters.
     */
    private List<RexNode> joinFilters;

    /**
     * All join filters replacedociated with the MultiJoin, decomposed into a
     * list. Includes left/right outer join filters.
     */
    private List<RexNode> allJoinFilters;

    /**
     * Number of factors into the MultiJoin
     */
    private final int nJoinFactors;

    /**
     * Total number of fields in the MultiJoin
     */
    private int nTotalFields;

    /**
     * Original inputs into the MultiJoin
     */
    private final ImmutableList<RelNode> joinFactors;

    /**
     * If a join factor is null generating in a left or right outer join,
     * joinTypes indicates the join type corresponding to the factor. Otherwise,
     * it is set to INNER.
     */
    private final ImmutableList<JoinRelType> joinTypes;

    /**
     * If a join factor is null generating in a left or right outer join, the
     * bitmap contains the non-null generating factors that the null generating
     * factor is dependent upon
     */
    private final ImmutableBitSet[] outerJoinFactors;

    /**
     * Bitmap corresponding to the fields projected from each join factor, after
     * row scan processing has completed. This excludes fields referenced in
     * join conditions, unless the field appears in the final projection list.
     */
    private List<ImmutableBitSet> projFields;

    /**
     * Map containing reference counts of the fields referenced in join
     * conditions for each join factor. If a field is only required for a
     * semijoin, then it is removed from the reference count. (Hence the need
     * for reference counts instead of simply a bitmap.) The map is indexed by
     * the factor number.
     */
    private Map<Integer, int[]> joinFieldRefCountsMap;

    /**
     * For each join filter, replacedociates a bitmap indicating all factors
     * referenced by the filter
     */
    private Map<RexNode, ImmutableBitSet> factorsRefByJoinFilter;

    /**
     * For each join filter, replacedociates a bitmap indicating all fields
     * referenced by the filter
     */
    private Map<RexNode, ImmutableBitSet> fieldsRefByJoinFilter;

    /**
     * Starting RexInputRef index corresponding to each join factor
     */
    int[] joinStart;

    /**
     * Number of fields in each join factor
     */
    int[] nFieldsInJoinFactor;

    /**
     * Bitmap indicating which factors each factor references in join filters
     * that correspond to comparisons
     */
    ImmutableBitSet[] factorsRefByFactor;

    /**
     * Weights of each factor combination
     */
    int[][] factorWeights;

    /**
     * Type factory
     */
    final RelDataTypeFactory factory;

    /**
     * Indicates for each factor whether its join can be removed because it is
     * the dimension table in a semijoin. If it can be, the entry indicates the
     * factor id of the fact table (corresponding to the dimension table) in the
     * semijoin that allows the factor to be removed. If the factor cannot be
     * removed, the entry corresponding to the factor is null.
     */
    Integer[] joinRemovalFactors;

    /**
     * The semijoins that allow the join of a dimension table to be removed
     */
    SemiJoin[] joinRemovalSemiJoins;

    /**
     * Set of null-generating factors whose corresponding outer join can be
     * removed from the query plan
     */
    Set<Integer> removableOuterJoinFactors;

    /**
     * Map consisting of all pairs of self-joins where the self-join can be
     * removed because the join between the identical factors is an equality
     * join on the same set of unique keys. The map is keyed by either factor in
     * the self join.
     */
    Map<Integer, RemovableSelfJoin> removableSelfJoinPairs;

    // ~ Constructors -----------------------------------------------------------
    public LoptMultiJoin(MultiJoin multiJoin) {
        this.multiJoin = multiJoin;
        joinFactors = ImmutableList.copyOf(multiJoin.getInputs());
        nJoinFactors = joinFactors.size();
        projFields = multiJoin.getProjFields();
        joinFieldRefCountsMap = multiJoin.getCopyJoinFieldRefCountsMap();
        joinFilters = Lists.newArrayList(RelOptUtil.conjunctions(multiJoin.getJoinFilter()));
        allJoinFilters = new ArrayList<>(joinFilters);
        List<RexNode> outerJoinFilters = multiJoin.getOuterJoinConditions();
        for (int i = 0; i < nJoinFactors; i++) {
            allJoinFilters.addAll(RelOptUtil.conjunctions(outerJoinFilters.get(i)));
        }
        int start = 0;
        nTotalFields = multiJoin.getRowType().getFieldCount();
        joinStart = new int[nJoinFactors];
        nFieldsInJoinFactor = new int[nJoinFactors];
        for (int i = 0; i < nJoinFactors; i++) {
            joinStart[i] = start;
            nFieldsInJoinFactor[i] = joinFactors.get(i).getRowType().getFieldCount();
            start += nFieldsInJoinFactor[i];
        }
        // Extract outer join information from the join factors, including the type
        // of outer join and the factors that a null-generating factor is dependent
        // upon.
        joinTypes = ImmutableList.copyOf(multiJoin.getJoinTypes());
        List<RexNode> outerJoinConds = this.multiJoin.getOuterJoinConditions();
        outerJoinFactors = new ImmutableBitSet[nJoinFactors];
        for (int i = 0; i < nJoinFactors; i++) {
            if (outerJoinConds.get(i) != null) {
                // set a bitmap containing the factors referenced in the
                // ON condition of the outer join; mask off the factor
                // corresponding to the factor itself
                ImmutableBitSet dependentFactors = getJoinFilterFactorBitmap(outerJoinConds.get(i), false);
                dependentFactors = dependentFactors.clear(i);
                outerJoinFactors[i] = dependentFactors;
            }
        }
        // determine which join factors each join filter references
        setJoinFilterRefs();
        factory = multiJoin.getCluster().getTypeFactory();
        joinRemovalFactors = new Integer[nJoinFactors];
        joinRemovalSemiJoins = new SemiJoin[nJoinFactors];
        removableOuterJoinFactors = new HashSet<>();
        removableSelfJoinPairs = new HashMap<>();
    }

    // ~ Methods ----------------------------------------------------------------
    /**
     * @return the MultiJoin corresponding to this multijoin
     */
    public MultiJoin getMultiJoinRel() {
        return multiJoin;
    }

    /**
     * @return number of factors in this multijoin
     */
    public int getNumJoinFactors() {
        return nJoinFactors;
    }

    /**
     * @param factIdx factor to be returned
     *
     * @return factor corresponding to the factor index preplaceded in
     */
    public RelNode getJoinFactor(int factIdx) {
        return joinFactors.get(factIdx);
    }

    /**
     * @return total number of fields in the multijoin
     */
    public int getNumTotalFields() {
        return nTotalFields;
    }

    /**
     * @param factIdx desired factor
     *
     * @return number of fields in the specified factor
     */
    public int getNumFieldsInJoinFactor(int factIdx) {
        return nFieldsInJoinFactor[factIdx];
    }

    /**
     * @return all non-outer join filters in this multijoin
     */
    public List<RexNode> getJoinFilters() {
        return joinFilters;
    }

    /**
     * @param joinFilter filter for which information will be returned
     *
     * @return bitmap corresponding to the factors referenced within the
     * specified join filter
     */
    public ImmutableBitSet getFactorsRefByJoinFilter(RexNode joinFilter) {
        return factorsRefByJoinFilter.get(joinFilter);
    }

    /**
     * Returns array of fields contained within the multi-join
     */
    public List<RelDataTypeField> getMultiJoinFields() {
        return multiJoin.getRowType().getFieldList();
    }

    /**
     * @param joinFilter the filter for which information will be returned
     *
     * @return bitmap corresponding to the fields referenced by a join filter
     */
    public ImmutableBitSet getFieldsRefByJoinFilter(RexNode joinFilter) {
        return fieldsRefByJoinFilter.get(joinFilter);
    }

    /**
     * @return weights of the different factors relative to one another
     */
    public int[][] getFactorWeights() {
        return factorWeights;
    }

    /**
     * @param factIdx factor for which information will be returned
     *
     * @return bitmap corresponding to the factors referenced by the specified
     * factor in the various join filters that correspond to comparisons
     */
    public ImmutableBitSet getFactorsRefByFactor(int factIdx) {
        return factorsRefByFactor[factIdx];
    }

    /**
     * @param factIdx factor for which information will be returned
     *
     * @return starting offset within the multijoin for the specified factor
     */
    public int getJoinStart(int factIdx) {
        return joinStart[factIdx];
    }

    /**
     * @param factIdx factor for which information will be returned
     *
     * @return whether or not the factor corresponds to a null-generating factor
     * in a left or right outer join
     */
    public boolean isNullGenerating(int factIdx) {
        return joinTypes.get(factIdx) != JoinRelType.INNER;
    }

    /**
     * @param factIdx factor for which information will be returned
     *
     * @return bitmap containing the factors that a null generating factor is
     * dependent upon, if the factor is null generating in a left or right outer
     * join; otherwise null is returned
     */
    public ImmutableBitSet getOuterJoinFactors(int factIdx) {
        return outerJoinFactors[factIdx];
    }

    /**
     * @param factIdx factor for which information will be returned
     *
     * @return outer join conditions replacedociated with the specified null
     * generating factor
     */
    public RexNode getOuterJoinCond(int factIdx) {
        return multiJoin.getOuterJoinConditions().get(factIdx);
    }

    /**
     * @param factIdx factor for which information will be returned
     *
     * @return bitmap containing the fields that are projected from a factor
     */
    public ImmutableBitSet getProjFields(int factIdx) {
        return projFields.get(factIdx);
    }

    /**
     * @param factIdx factor for which information will be returned
     *
     * @return the join field reference counts for a factor
     */
    public int[] getJoinFieldRefCounts(int factIdx) {
        return joinFieldRefCountsMap.get(factIdx);
    }

    /**
     * @param dimIdx the dimension factor for which information will be returned
     *
     * @return the factor id of the fact table corresponding to a dimension
     * table in a semijoin, in the case where the join with the dimension table
     * can be removed
     */
    public Integer getJoinRemovalFactor(int dimIdx) {
        return joinRemovalFactors[dimIdx];
    }

    /**
     * @param dimIdx the dimension factor for which information will be returned
     *
     * @return the semijoin that allows the join of a dimension table to be
     * removed
     */
    public SemiJoin getJoinRemovalSemiJoin(int dimIdx) {
        return joinRemovalSemiJoins[dimIdx];
    }

    /**
     * Indicates that a dimension factor's join can be removed because of a
     * semijoin with a fact table.
     *
     * @param dimIdx id of the dimension factor
     * @param factIdx id of the fact factor
     */
    public void setJoinRemovalFactor(int dimIdx, int factIdx) {
        joinRemovalFactors[dimIdx] = factIdx;
    }

    /**
     * Indicates the semijoin that allows the join of a dimension table to be
     * removed
     *
     * @param dimIdx id of the dimension factor
     * @param semiJoin the semijoin
     */
    public void setJoinRemovalSemiJoin(int dimIdx, SemiJoin semiJoin) {
        joinRemovalSemiJoins[dimIdx] = semiJoin;
    }

    /**
     * Returns a bitmap representing the factors referenced in a join filter
     *
     * @param joinFilter the join filter
     * @param setFields if true, add the fields referenced by the join filter
     * into a map
     *
     * @return the bitmap containing the factor references
     */
    ImmutableBitSet getJoinFilterFactorBitmap(RexNode joinFilter, boolean setFields) {
        ImmutableBitSet fieldRefBitmap = fieldBitmap(joinFilter);
        if (setFields) {
            fieldsRefByJoinFilter.put(joinFilter, fieldRefBitmap);
        }
        return factorBitmap(fieldRefBitmap);
    }

    private ImmutableBitSet fieldBitmap(RexNode joinFilter) {
        final RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder();
        joinFilter.accept(inputFinder);
        return inputFinder.inputBitSet.build();
    }

    /**
     * Sets bitmaps indicating which factors and fields each join filter
     * references
     */
    private void setJoinFilterRefs() {
        fieldsRefByJoinFilter = new HashMap<>();
        factorsRefByJoinFilter = new HashMap<>();
        Lisreplacederator<RexNode> filterIter = allJoinFilters.lisreplacederator();
        while (filterIter.hasNext()) {
            RexNode joinFilter = filterIter.next();
            // ignore the literal filter; if necessary, we'll add it back
            // later
            if (joinFilter.isAlwaysTrue()) {
                filterIter.remove();
            }
            ImmutableBitSet factorRefBitmap = getJoinFilterFactorBitmap(joinFilter, true);
            factorsRefByJoinFilter.put(joinFilter, factorRefBitmap);
        }
    }

    /**
     * Sets the bitmap indicating which factors a filter references based on
     * which fields it references
     *
     * @param fieldRefBitmap bitmap representing fields referenced
     * @return bitmap representing factors referenced that will
     * be set by this method
     */
    private ImmutableBitSet factorBitmap(ImmutableBitSet fieldRefBitmap) {
        ImmutableBitSet.Builder factorRefBitmap = ImmutableBitSet.builder();
        for (int field : fieldRefBitmap) {
            int factor = findRef(field);
            factorRefBitmap.set(factor);
        }
        return factorRefBitmap.build();
    }

    /**
     * Determines the join factor corresponding to a RexInputRef
     *
     * @param rexInputRef rexInputRef index
     *
     * @return index corresponding to join factor
     */
    public int findRef(int rexInputRef) {
        for (int i = 0; i < nJoinFactors; i++) {
            if ((rexInputRef >= joinStart[i]) && (rexInputRef < (joinStart[i] + nFieldsInJoinFactor[i]))) {
                return i;
            }
        }
        throw new replacedertionError();
    }

    /**
     * Sets weighting for each combination of factors, depending on which join
     * filters reference which factors. Greater weight is given to equality
     * conditions. Also, sets bitmaps indicating which factors are referenced by
     * each factor within join filters that are comparisons.
     */
    public void setFactorWeights() {
        factorWeights = new int[nJoinFactors][nJoinFactors];
        factorsRefByFactor = new ImmutableBitSet[nJoinFactors];
        for (int i = 0; i < nJoinFactors; i++) {
            factorsRefByFactor[i] = ImmutableBitSet.of();
        }
        for (RexNode joinFilter : allJoinFilters) {
            ImmutableBitSet factorRefs = factorsRefByJoinFilter.get(joinFilter);
            // don't give weights to non-comparison expressions
            if (!(joinFilter instanceof RexCall)) {
                continue;
            }
            if (!joinFilter.isA(SqlKind.COMPARISON)) {
                continue;
            }
            // OR the factors referenced in this join filter into the
            // bitmaps corresponding to each of the factors; however,
            // exclude the bit corresponding to the factor itself
            for (int factor : factorRefs) {
                factorsRefByFactor[factor] = factorsRefByFactor[factor].rebuild().addAll(factorRefs).clear(factor).build();
            }
            if (factorRefs.cardinality() == 2) {
                int leftFactor = factorRefs.nextSetBit(0);
                int rightFactor = factorRefs.nextSetBit(leftFactor + 1);
                final RexCall call = (RexCall) joinFilter;
                ImmutableBitSet leftFields = fieldBitmap(call.getOperands().get(0));
                ImmutableBitSet leftBitmap = factorBitmap(leftFields);
                // filter contains only two factor references, one on each
                // side of the operator
                int weight;
                if (leftBitmap.cardinality() == 1) {
                    // give higher weight to equi-joins
                    switch(joinFilter.getKind()) {
                        case EQUALS:
                            weight = 3;
                            break;
                        default:
                            weight = 2;
                    }
                } else {
                    // cross product of two tables
                    weight = 1;
                }
                setFactorWeight(weight, leftFactor, rightFactor);
            } else {
                // multiple factor references -- set a weight for each
                // combination of factors referenced within the filter
                final List<Integer> list = ImmutableIntList.copyOf(factorRefs);
                for (int outer : list) {
                    for (int inner : list) {
                        if (outer != inner) {
                            setFactorWeight(1, outer, inner);
                        }
                    }
                }
            }
        }
    }

    /**
     * Sets an individual weight if the new weight is better than the current
     * one
     *
     * @param weight weight to be set
     * @param leftFactor index of left factor
     * @param rightFactor index of right factor
     */
    private void setFactorWeight(int weight, int leftFactor, int rightFactor) {
        if (factorWeights[leftFactor][rightFactor] < weight) {
            factorWeights[leftFactor][rightFactor] = weight;
            factorWeights[rightFactor][leftFactor] = weight;
        }
    }

    /**
     * Returns true if a join tree contains all factors required
     *
     * @param joinTree join tree to be examined
     * @param factorsNeeded bitmap of factors required
     *
     * @return true if join tree contains all required factors
     */
    public boolean hasAllFactors(LoptJoinTree joinTree, BitSet factorsNeeded) {
        return BitSets.contains(BitSets.of(joinTree.getTreeOrder()), factorsNeeded);
    }

    /**
     * Sets a bitmap indicating all child RelNodes in a join tree
     *
     * @param joinTree join tree to be examined
     * @param childFactors bitmap to be set
     */
    // to be removed before 2.0
    @Deprecated
    public void getChildFactors(LoptJoinTree joinTree, ImmutableBitSet.Builder childFactors) {
        for (int child : joinTree.getTreeOrder()) {
            childFactors.set(child);
        }
    }

    /**
     * Retrieves the fields corresponding to a join between a left and right
     * tree
     *
     * @param left left hand side of the join
     * @param right right hand side of the join
     *
     * @return fields of the join
     */
    public List<RelDataTypeField> getJoinFields(LoptJoinTree left, LoptJoinTree right) {
        RelDataType rowType = factory.createJoinType(left.getJoinTree().getRowType(), right.getJoinTree().getRowType());
        return rowType.getFieldList();
    }

    /**
     * Adds a join factor to the set of factors that can be removed because the
     * factor is the null generating factor in an outer join, its join keys are
     * unique, and the factor is not projected in the query
     *
     * @param factIdx join factor
     */
    public void addRemovableOuterJoinFactor(int factIdx) {
        removableOuterJoinFactors.add(factIdx);
    }

    /**
     * @param factIdx factor in question
     *
     * @return true if the factor corresponds to the null generating factor in
     * an outer join that can be removed
     */
    public boolean isRemovableOuterJoinFactor(int factIdx) {
        return removableOuterJoinFactors.contains(factIdx);
    }

    /**
     * Adds to a map that keeps track of removable self-join pairs.
     *
     * @param factor1 one of the factors in the self-join
     * @param factor2 the second factor in the self-join
     */
    public void addRemovableSelfJoinPair(int factor1, int factor2) {
        int leftFactor;
        int rightFactor;
        // Put the factor with more fields on the left so it will be
        // preserved after the self-join is removed.
        if (getNumFieldsInJoinFactor(factor1) > getNumFieldsInJoinFactor(factor2)) {
            leftFactor = factor1;
            rightFactor = factor2;
        } else {
            leftFactor = factor2;
            rightFactor = factor1;
        }
        // Compute a column mapping such that if a column from the right
        // factor is also referenced in the left factor, we will map the
        // right reference to the left to avoid redundant references.
        final Map<Integer, Integer> columnMapping = new HashMap<>();
        // First, locate the originating column for all simple column
        // references in the left factor.
        final RelNode left = getJoinFactor(leftFactor);
        final RelMetadataQuery mq = left.getCluster().getMetadataQuery();
        final Map<Integer, Integer> leftFactorColMapping = new HashMap<>();
        for (int i = 0; i < left.getRowType().getFieldCount(); i++) {
            final RelColumnOrigin colOrigin = mq.getColumnOrigin(left, i);
            if (colOrigin != null) {
                leftFactorColMapping.put(colOrigin.getOriginColumnOrdinal(), i);
            }
        }
        // Then, see if the right factor references any of the same columns
        // by locating their originating columns.  If there are matches,
        // then we want to store the corresponding offset into the left
        // factor.
        RelNode right = getJoinFactor(rightFactor);
        for (int i = 0; i < right.getRowType().getFieldCount(); i++) {
            final RelColumnOrigin colOrigin = mq.getColumnOrigin(right, i);
            if (colOrigin == null) {
                continue;
            }
            Integer leftOffset = leftFactorColMapping.get(colOrigin.getOriginColumnOrdinal());
            if (leftOffset == null) {
                continue;
            }
            columnMapping.put(i, leftOffset);
        }
        RemovableSelfJoin selfJoin = new RemovableSelfJoin(leftFactor, rightFactor, columnMapping);
        removableSelfJoinPairs.put(leftFactor, selfJoin);
        removableSelfJoinPairs.put(rightFactor, selfJoin);
    }

    /**
     * Returns the other factor in a self-join pair if the factor preplaceded in is
     * a factor in a removable self-join; otherwise, returns null.
     *
     * @param factIdx one of the factors in a self-join pair
     */
    public Integer getOtherSelfJoinFactor(int factIdx) {
        RemovableSelfJoin selfJoin = removableSelfJoinPairs.get(factIdx);
        if (selfJoin == null) {
            return null;
        } else if (selfJoin.getRightFactor() == factIdx) {
            return selfJoin.getLeftFactor();
        } else {
            return selfJoin.getRightFactor();
        }
    }

    /**
     * @param factIdx factor in a self-join
     *
     * @return true if the factor is the left factor in a self-join
     */
    public boolean isLeftFactorInRemovableSelfJoin(int factIdx) {
        RemovableSelfJoin selfJoin = removableSelfJoinPairs.get(factIdx);
        if (selfJoin == null) {
            return false;
        }
        return selfJoin.getLeftFactor() == factIdx;
    }

    /**
     * @param factIdx factor in a self-join
     *
     * @return true if the factor is the right factor in a self-join
     */
    public boolean isRightFactorInRemovableSelfJoin(int factIdx) {
        RemovableSelfJoin selfJoin = removableSelfJoinPairs.get(factIdx);
        if (selfJoin == null) {
            return false;
        }
        return selfJoin.getRightFactor() == factIdx;
    }

    /**
     * Determines whether there is a mapping from a column in the right factor
     * of a self-join to a column from the left factor. replacedumes that the right
     * factor is a part of a self-join.
     *
     * @param rightFactor the index of the right factor
     * @param rightOffset the column offset of the right factor
     *
     * @return the offset of the corresponding column in the left factor, if
     * such a column mapping exists; otherwise, null is returned
     */
    public Integer getRightColumnMapping(int rightFactor, int rightOffset) {
        RemovableSelfJoin selfJoin = removableSelfJoinPairs.get(rightFactor);
        replacedert selfJoin.getRightFactor() == rightFactor;
        return selfJoin.getColumnMapping().get(rightOffset);
    }

    public Edge createEdge(RexNode condition) {
        ImmutableBitSet fieldRefBitmap = fieldBitmap(condition);
        ImmutableBitSet factorRefBitmap = factorBitmap(fieldRefBitmap);
        return new Edge(condition, factorRefBitmap, fieldRefBitmap);
    }

    /**
     * Information about a join-condition.
     */
    static clreplaced Edge {

        final ImmutableBitSet factors;

        final ImmutableBitSet columns;

        final RexNode condition;

        Edge(RexNode condition, ImmutableBitSet factors, ImmutableBitSet columns) {
            this.condition = condition;
            this.factors = factors;
            this.columns = columns;
        }

        @Override
        public String toString() {
            return "Edge(condition: " + condition + ", factors: " + factors + ", columns: " + columns + ")";
        }
    }

    // ~ Inner Clreplacedes ----------------------------------------------------------
    /**
     * Utility clreplaced used to keep track of the factors in a removable self-join.
     * The right factor in the self-join is the one that will be removed.
     */
    private clreplaced RemovableSelfJoin {

        /**
         * The left factor in a removable self-join
         */
        private int leftFactor;

        /**
         * The right factor in a removable self-join, namely the factor that
         * will be removed
         */
        private int rightFactor;

        /**
         * A mapping that maps references to columns from the right factor to
         * columns in the left factor, if the column is referenced in both
         * factors
         */
        private Map<Integer, Integer> columnMapping;

        RemovableSelfJoin(int leftFactor, int rightFactor, Map<Integer, Integer> columnMapping) {
            this.leftFactor = leftFactor;
            this.rightFactor = rightFactor;
            this.columnMapping = columnMapping;
        }

        public int getLeftFactor() {
            return leftFactor;
        }

        public int getRightFactor() {
            return rightFactor;
        }

        public Map<Integer, Integer> getColumnMapping() {
            return columnMapping;
        }
    }
}

19 Source : LoptMultiJoin.java
with Apache License 2.0
from lealone

/**
 * Sets the bitmap indicating which factors a filter references based on
 * which fields it references
 *
 * @param fieldRefBitmap bitmap representing fields referenced
 * @return bitmap representing factors referenced that will
 * be set by this method
 */
private ImmutableBitSet factorBitmap(ImmutableBitSet fieldRefBitmap) {
    ImmutableBitSet.Builder factorRefBitmap = ImmutableBitSet.builder();
    for (int field : fieldRefBitmap) {
        int factor = findRef(field);
        factorRefBitmap.set(factor);
    }
    return factorRefBitmap.build();
}

19 Source : FilterAggregateTransposeRule.java
with Apache License 2.0
from lealone

// ~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
    final Filter filterRel = call.rel(0);
    final Aggregate aggRel = call.rel(1);
    final List<RexNode> conditions = RelOptUtil.conjunctions(filterRel.getCondition());
    final RexBuilder rexBuilder = filterRel.getCluster().getRexBuilder();
    final List<RelDataTypeField> origFields = aggRel.getRowType().getFieldList();
    final int[] adjustments = new int[origFields.size()];
    int j = 0;
    for (int i : aggRel.getGroupSet()) {
        adjustments[j] = i - j;
        j++;
    }
    final List<RexNode> pushedConditions = new ArrayList<>();
    final List<RexNode> remainingConditions = new ArrayList<>();
    for (RexNode condition : conditions) {
        ImmutableBitSet rCols = RelOptUtil.InputFinder.bits(condition);
        if (canPush(aggRel, rCols)) {
            pushedConditions.add(condition.accept(new RelOptUtil.RexInputConverter(rexBuilder, origFields, aggRel.getInput(0).getRowType().getFieldList(), adjustments)));
        } else {
            remainingConditions.add(condition);
        }
    }
    final RelBuilder builder = call.builder();
    RelNode rel = builder.push(aggRel.getInput()).filter(pushedConditions).build();
    if (rel == aggRel.getInput(0)) {
        return;
    }
    rel = aggRel.copy(aggRel.getTraitSet(), ImmutableList.of(rel));
    rel = builder.push(rel).filter(remainingConditions).build();
    call.transformTo(rel);
}

19 Source : FilterAggregateTransposeRule.java
with Apache License 2.0
from lealone

private boolean canPush(Aggregate aggregate, ImmutableBitSet rCols) {
    // If the filter references columns not in the group key, we cannot push
    final ImmutableBitSet groupKeys = ImmutableBitSet.range(0, aggregate.getGroupSet().cardinality());
    if (!groupKeys.contains(rCols)) {
        return false;
    }
    if (aggregate.getGroupType() != Group.SIMPLE) {
        // If grouping sets are used, the filter can be pushed if
        // the columns referenced in the predicate are present in
        // all the grouping sets.
        for (ImmutableBitSet groupingSet : aggregate.getGroupSets()) {
            if (!groupingSet.contains(rCols)) {
                return false;
            }
        }
    }
    return true;
}

19 Source : AggregateJoinTransposeRule.java
with Apache License 2.0
from lealone

/**
 * Computes the closure of a set of columns according to a given list of
 * constraints. Each 'x = y' constraint causes bit y to be set if bit x is
 * set, and vice versa.
 */
private static ImmutableBitSet keyColumns(ImmutableBitSet aggregateColumns, ImmutableList<RexNode> predicates) {
    SortedMap<Integer, BitSet> equivalence = new TreeMap<>();
    for (RexNode predicate : predicates) {
        populateEquivalences(equivalence, predicate);
    }
    ImmutableBitSet keyColumns = aggregateColumns;
    for (Integer aggregateColumn : aggregateColumns) {
        final BitSet bitSet = equivalence.get(aggregateColumn);
        if (bitSet != null) {
            keyColumns = keyColumns.union(bitSet);
        }
    }
    return keyColumns;
}

19 Source : AggregateExpandDistinctAggregatesRule.java
with Apache License 2.0
from lealone

private static int remap(ImmutableBitSet groupSet, int arg) {
    return arg < 0 ? -1 : groupSet.indexOf(arg);
}

19 Source : AggregateExpandDistinctAggregatesRule.java
with Apache License 2.0
from lealone

private static long groupValue(ImmutableBitSet fullGroupSet, ImmutableBitSet groupSet) {
    long v = 0;
    long x = 1L << (fullGroupSet.cardinality() - 1);
    replacedert fullGroupSet.contains(groupSet);
    for (int i : fullGroupSet) {
        if (!groupSet.get(i)) {
            v |= x;
        }
        x >>= 1;
    }
    return v;
}

19 Source : AggregateExpandDistinctAggregatesRule.java
with Apache License 2.0
from lealone

private static List<Integer> remap(ImmutableBitSet groupSet, List<Integer> argList) {
    ImmutableIntList list = ImmutableIntList.of();
    for (int arg : argList) {
        list = list.append(remap(groupSet, arg));
    }
    return list;
}

19 Source : AggregateExpandDistinctAggregatesRule.java
with Apache License 2.0
from lealone

private static ImmutableList<ImmutableBitSet> remap(ImmutableBitSet groupSet, Iterable<ImmutableBitSet> bitSets) {
    final ImmutableList.Builder<ImmutableBitSet> builder = ImmutableList.builder();
    for (ImmutableBitSet bitSet : bitSets) {
        builder.add(remap(groupSet, bitSet));
    }
    return builder.build();
}

19 Source : AggregateExpandDistinctAggregatesRule.java
with Apache License 2.0
from lealone

private static ImmutableBitSet remap(ImmutableBitSet groupSet, ImmutableBitSet bitSet) {
    final ImmutableBitSet.Builder builder = ImmutableBitSet.builder();
    for (Integer bit : bitSet) {
        builder.set(remap(groupSet, bit));
    }
    return builder.build();
}

19 Source : MutableCorrelate.java
with Apache License 2.0
from lealone

/**
 * Mutable equivalent of {@link org.apache.calcite.rel.core.Correlate}.
 */
public clreplaced MutableCorrelate extends MutableBiRel {

    public final CorrelationId correlationId;

    public final ImmutableBitSet requiredColumns;

    public final SemiJoinType joinType;

    private MutableCorrelate(RelDataType rowType, MutableRel left, MutableRel right, CorrelationId correlationId, ImmutableBitSet requiredColumns, SemiJoinType joinType) {
        super(MutableRelType.CORRELATE, left.cluster, rowType, left, right);
        this.correlationId = correlationId;
        this.requiredColumns = requiredColumns;
        this.joinType = joinType;
    }

    /**
     * Creates a MutableCorrelate.
     *
     * @param rowType         Row type
     * @param left            Left input relational expression
     * @param right           Right input relational expression
     * @param correlationId   Variable name for the row of left input
     * @param requiredColumns Required columns
     * @param joinType        Join type
     */
    public static MutableCorrelate of(RelDataType rowType, MutableRel left, MutableRel right, CorrelationId correlationId, ImmutableBitSet requiredColumns, SemiJoinType joinType) {
        return new MutableCorrelate(rowType, left, right, correlationId, requiredColumns, joinType);
    }

    @Override
    public boolean equals(Object obj) {
        return obj == this || obj instanceof MutableCorrelate && correlationId.equals(((MutableCorrelate) obj).correlationId) && requiredColumns.equals(((MutableCorrelate) obj).requiredColumns) && joinType == ((MutableCorrelate) obj).joinType && left.equals(((MutableCorrelate) obj).left) && right.equals(((MutableCorrelate) obj).right);
    }

    @Override
    public int hashCode() {
        return Objects.hash(left, right, correlationId, requiredColumns, joinType);
    }

    @Override
    public StringBuilder digest(StringBuilder buf) {
        return buf.append("Correlate(correlationId: ").append(correlationId).append(", requiredColumns: ").append(requiredColumns).append(", joinType: ").append(joinType).append(")");
    }

    @Override
    public MutableRel clone() {
        return MutableCorrelate.of(rowType, left.clone(), right.clone(), correlationId, requiredColumns, joinType);
    }
}

19 Source : MutableCorrelate.java
with Apache License 2.0
from lealone

/**
 * Creates a MutableCorrelate.
 *
 * @param rowType         Row type
 * @param left            Left input relational expression
 * @param right           Right input relational expression
 * @param correlationId   Variable name for the row of left input
 * @param requiredColumns Required columns
 * @param joinType        Join type
 */
public static MutableCorrelate of(RelDataType rowType, MutableRel left, MutableRel right, CorrelationId correlationId, ImmutableBitSet requiredColumns, SemiJoinType joinType) {
    return new MutableCorrelate(rowType, left, right, correlationId, requiredColumns, joinType);
}

19 Source : MutableAggregate.java
with Apache License 2.0
from lealone

/**
 * Mutable equivalent of {@link org.apache.calcite.rel.core.Aggregate}.
 */
public clreplaced MutableAggregate extends MutableSingleRel {

    public final ImmutableBitSet groupSet;

    public final ImmutableList<ImmutableBitSet> groupSets;

    public final List<AggregateCall> aggCalls;

    private MutableAggregate(MutableRel input, RelDataType rowType, ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) {
        super(MutableRelType.AGGREGATE, rowType, input);
        this.groupSet = groupSet;
        this.groupSets = groupSets == null ? ImmutableList.of(groupSet) : ImmutableList.copyOf(groupSets);
        this.aggCalls = aggCalls;
    }

    /**
     * Creates a MutableAggregate.
     *
     * @param input     Input relational expression
     * @param groupSet  Bit set of grouping fields
     * @param groupSets List of all grouping sets; null for just {@code groupSet}
     * @param aggCalls  Collection of calls to aggregate functions
     */
    public static MutableAggregate of(MutableRel input, ImmutableBitSet groupSet, ImmutableList<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) {
        RelDataType rowType = Aggregate.deriveRowType(input.cluster.getTypeFactory(), input.rowType, false, groupSet, groupSets, aggCalls);
        return new MutableAggregate(input, rowType, groupSet, groupSets, aggCalls);
    }

    @Override
    public boolean equals(Object obj) {
        return obj == this || obj instanceof MutableAggregate && groupSet.equals(((MutableAggregate) obj).groupSet) && aggCalls.equals(((MutableAggregate) obj).aggCalls) && input.equals(((MutableAggregate) obj).input);
    }

    @Override
    public int hashCode() {
        return Objects.hash(input, groupSet, aggCalls);
    }

    @Override
    public StringBuilder digest(StringBuilder buf) {
        return buf.append("Aggregate(groupSet: ").append(groupSet).append(", groupSets: ").append(groupSets).append(", calls: ").append(aggCalls).append(")");
    }

    public Aggregate.Group getGroupType() {
        return Aggregate.Group.induce(groupSet, groupSets);
    }

    @Override
    public MutableRel clone() {
        return MutableAggregate.of(input.clone(), groupSet, groupSets, aggCalls);
    }
}

19 Source : MutableAggregate.java
with Apache License 2.0
from lealone

/**
 * Creates a MutableAggregate.
 *
 * @param input     Input relational expression
 * @param groupSet  Bit set of grouping fields
 * @param groupSets List of all grouping sets; null for just {@code groupSet}
 * @param aggCalls  Collection of calls to aggregate functions
 */
public static MutableAggregate of(MutableRel input, ImmutableBitSet groupSet, ImmutableList<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) {
    RelDataType rowType = Aggregate.deriveRowType(input.cluster.getTypeFactory(), input.rowType, false, groupSet, groupSets, aggCalls);
    return new MutableAggregate(input, rowType, groupSet, groupSets, aggCalls);
}

19 Source : RelMetadataQuery.java
with Apache License 2.0
from lealone

/**
 * Returns whether the rows of a given relational expression are distinct.
 * This is derived by applying the
 * {@link BuiltInMetadata.ColumnUniqueness#areColumnsUnique(org.apache.calcite.util.ImmutableBitSet, boolean)}
 * statistic over all columns.
 *
 * @param rel     the relational expression
 *
 * @return true or false depending on whether the rows are unique, or
 * null if not enough information is available to make that determination
 */
public Boolean areRowsUnique(RelNode rel) {
    final ImmutableBitSet columns = ImmutableBitSet.range(rel.getRowType().getFieldCount());
    return areColumnsUnique(rel, columns, false);
}

19 Source : RelMetadataQuery.java
with Apache License 2.0
from lealone

/**
 * Returns the
 * {@link BuiltInMetadata.DistinctRowCount#getDistinctRowCount(ImmutableBitSet, RexNode)}
 * statistic.
 *
 * @param rel       the relational expression
 * @param groupKey  column mask representing group by columns
 * @param predicate pre-filtered predicates
 * @return distinct row count for groupKey, filtered by predicate, or null
 * if no reliable estimate can be determined
 */
public Double getDistinctRowCount(RelNode rel, ImmutableBitSet groupKey, RexNode predicate) {
    for (; ; ) {
        try {
            Double result = distinctRowCountHandler.getDistinctRowCount(rel, this, groupKey, predicate);
            return validateResult(result);
        } catch (JaninoRelMetadataProvider.NoHandler e) {
            distinctRowCountHandler = revise(e.relClreplaced, BuiltInMetadata.DistinctRowCount.DEF);
        }
    }
}

19 Source : RelMetadataQuery.java
with Apache License 2.0
from lealone

/**
 * Returns the
 * {@link BuiltInMetadata.ColumnUniqueness#areColumnsUnique(ImmutableBitSet, boolean)}
 * statistic.
 *
 * @param rel     the relational expression
 * @param columns column mask representing the subset of columns for which
 *                uniqueness will be determined
 *
 * @return true or false depending on whether the columns are unique, or
 * null if not enough information is available to make that determination
 */
public Boolean areColumnsUnique(RelNode rel, ImmutableBitSet columns) {
    return areColumnsUnique(rel, columns, false);
}

19 Source : RelMetadataQuery.java
with Apache License 2.0
from lealone

/**
 * Returns the
 * {@link BuiltInMetadata.PopulationSize#getPopulationSize(ImmutableBitSet)}
 * statistic.
 *
 * @param rel      the relational expression
 * @param groupKey column mask representing the subset of columns for which
 *                 the row count will be determined
 * @return distinct row count for the given groupKey, or null if no reliable
 * estimate can be determined
 */
public Double getPopulationSize(RelNode rel, ImmutableBitSet groupKey) {
    for (; ; ) {
        try {
            Double result = populationSizeHandler.getPopulationSize(rel, this, groupKey);
            return validateResult(result);
        } catch (JaninoRelMetadataProvider.NoHandler e) {
            populationSizeHandler = revise(e.relClreplaced, BuiltInMetadata.PopulationSize.DEF);
        }
    }
}

19 Source : RelMetadataQuery.java
with Apache License 2.0
from lealone

/**
 * Returns the
 * {@link BuiltInMetadata.ColumnUniqueness#areColumnsUnique(ImmutableBitSet, boolean)}
 * statistic.
 *
 * @param rel         the relational expression
 * @param columns     column mask representing the subset of columns for which
 *                    uniqueness will be determined
 * @param ignoreNulls if true, ignore null values when determining column
 *                    uniqueness
 * @return true or false depending on whether the columns are unique, or
 * null if not enough information is available to make that determination
 */
public Boolean areColumnsUnique(RelNode rel, ImmutableBitSet columns, boolean ignoreNulls) {
    for (; ; ) {
        try {
            return columnUniquenessHandler.areColumnsUnique(rel, this, columns, ignoreNulls);
        } catch (JaninoRelMetadataProvider.NoHandler e) {
            columnUniquenessHandler = revise(e.relClreplaced, BuiltInMetadata.ColumnUniqueness.DEF);
        }
    }
}

19 Source : RelMdUtil.java
with Apache License 2.0
from lealone

/**
 * Takes a bitmap representing a set of input references and extracts the
 * ones that reference the group by columns in an aggregate.
 *
 * @param groupKey the original bitmap
 * @param aggRel   the aggregate
 * @param childKey sets bits from groupKey corresponding to group by columns
 */
public static void setAggChildKeys(ImmutableBitSet groupKey, Aggregate aggRel, ImmutableBitSet.Builder childKey) {
    List<AggregateCall> aggCalls = aggRel.getAggCallList();
    for (int bit : groupKey) {
        if (bit < aggRel.getGroupCount()) {
            // group by column
            childKey.set(bit);
        } else {
            // aggregate column -- set a bit for each argument being
            // aggregated
            AggregateCall agg = aggCalls.get(bit - (aggRel.getGroupCount() + aggRel.getIndicatorCount()));
            for (Integer arg : agg.getArgList()) {
                childKey.set(arg);
            }
        }
    }
}

19 Source : RelMdUtil.java
with Apache License 2.0
from lealone

/**
 * Computes the selectivity of a semijoin filter if it is applied on a fact
 * table. The computation is based on the selectivity of the dimension
 * table/columns and the number of distinct values in the fact table
 * columns.
 *
 * @param factRel     fact table participating in the semijoin
 * @param dimRel      dimension table participating in the semijoin
 * @param factKeyList LHS keys used in the filter
 * @param dimKeyList  RHS keys used in the filter
 * @return calculated selectivity
 */
public static double computeSemiJoinSelectivity(RelMetadataQuery mq, RelNode factRel, RelNode dimRel, List<Integer> factKeyList, List<Integer> dimKeyList) {
    ImmutableBitSet.Builder factKeys = ImmutableBitSet.builder();
    for (int factCol : factKeyList) {
        factKeys.set(factCol);
    }
    ImmutableBitSet.Builder dimKeyBuilder = ImmutableBitSet.builder();
    for (int dimCol : dimKeyList) {
        dimKeyBuilder.set(dimCol);
    }
    final ImmutableBitSet dimKeys = dimKeyBuilder.build();
    Double factPop = mq.getPopulationSize(factRel, factKeys.build());
    if (factPop == null) {
        // use the dimension population if the fact population is
        // unavailable; since we're filtering the fact table, that's
        // the population we ideally want to use
        factPop = mq.getPopulationSize(dimRel, dimKeys);
    }
    // if cardinality and population are available, use them; otherwise
    // use percentage original rows
    Double selectivity;
    Double dimCard = mq.getDistinctRowCount(dimRel, dimKeys, null);
    if ((dimCard != null) && (factPop != null)) {
        // to avoid division by zero
        if (factPop < 1.0) {
            factPop = 1.0;
        }
        selectivity = dimCard / factPop;
    } else {
        selectivity = mq.getPercentageOriginalRows(dimRel);
    }
    if (selectivity == null) {
        // set a default selectivity based on the number of semijoin keys
        selectivity = Math.pow(0.1, dimKeys.cardinality());
    } else if (selectivity > 1.0) {
        selectivity = 1.0;
    }
    return selectivity;
}

19 Source : RelMdUtil.java
with Apache License 2.0
from lealone

/**
 * Returns true if the columns represented in a bit mask are definitely
 * known to form a unique column set, when nulls have been filtered from
 * the columns.
 *
 * @param rel     the relational expression that the column mask corresponds
 *                to
 * @param colMask bit mask containing columns that will be tested for
 *                uniqueness
 * @return true if bit mask represents a unique column set; false if not (or
 * if no metadata is available)
 */
public static boolean areColumnsDefinitelyUniqueWhenNullsFiltered(RelMetadataQuery mq, RelNode rel, ImmutableBitSet colMask) {
    Boolean b = mq.areColumnsUnique(rel, colMask, true);
    if (b == null) {
        return false;
    }
    return b;
}

19 Source : RelMdUtil.java
with Apache License 2.0
from lealone

/**
 * Returns true if the columns represented in a bit mask are definitely
 * known to form a unique column set.
 *
 * @param rel     the relational expression that the column mask corresponds
 *                to
 * @param colMask bit mask containing columns that will be tested for
 *                uniqueness
 * @return true if bit mask represents a unique column set; false if not (or
 * if no metadata is available)
 */
public static boolean areColumnsDefinitelyUnique(RelMetadataQuery mq, RelNode rel, ImmutableBitSet colMask) {
    Boolean b = mq.areColumnsUnique(rel, colMask, false);
    return b != null && b;
}

19 Source : RelMdUtil.java
with Apache License 2.0
from lealone

/**
 * Separates a bit-mask representing a join into masks representing the left
 * and right inputs into the join.
 *
 * @param groupKey      original bit-mask
 * @param leftMask      left bit-mask to be set
 * @param rightMask     right bit-mask to be set
 * @param nFieldsOnLeft number of fields in the left input
 */
public static void setLeftRightBitmaps(ImmutableBitSet groupKey, ImmutableBitSet.Builder leftMask, ImmutableBitSet.Builder rightMask, int nFieldsOnLeft) {
    for (int bit : groupKey) {
        if (bit < nFieldsOnLeft) {
            leftMask.set(bit);
        } else {
            rightMask.set(bit - nFieldsOnLeft);
        }
    }
}

19 Source : RelMdPopulationSize.java
with Apache License 2.0
from lealone

public Double getPopulationSize(Union rel, RelMetadataQuery mq, ImmutableBitSet groupKey) {
    double population = 0.0;
    for (RelNode input : rel.getInputs()) {
        Double subPop = mq.getPopulationSize(input, groupKey);
        if (subPop == null) {
            return null;
        }
        population += subPop;
    }
    return population;
}

19 Source : RelMdPopulationSize.java
with Apache License 2.0
from lealone

public Double getPopulationSize(Aggregate rel, RelMetadataQuery mq, ImmutableBitSet groupKey) {
    ImmutableBitSet.Builder childKey = ImmutableBitSet.builder();
    RelMdUtil.setAggChildKeys(groupKey, rel, childKey);
    return mq.getPopulationSize(rel.getInput(), childKey.build());
}

19 Source : RelMdPopulationSize.java
with Apache License 2.0
from lealone

public Double getPopulationSize(Exchange rel, RelMetadataQuery mq, ImmutableBitSet groupKey) {
    return mq.getPopulationSize(rel.getInput(), groupKey);
}

19 Source : RelMdPopulationSize.java
with Apache License 2.0
from lealone

public Double getPopulationSize(SemiJoin rel, RelMetadataQuery mq, ImmutableBitSet groupKey) {
    return mq.getPopulationSize(rel.getLeft(), groupKey);
}

19 Source : RelMdPopulationSize.java
with Apache License 2.0
from lealone

public Double getPopulationSize(Project rel, RelMetadataQuery mq, ImmutableBitSet groupKey) {
    ImmutableBitSet.Builder baseCols = ImmutableBitSet.builder();
    ImmutableBitSet.Builder projCols = ImmutableBitSet.builder();
    List<RexNode> projExprs = rel.getProjects();
    RelMdUtil.splitCols(projExprs, groupKey, baseCols, projCols);
    Double population = mq.getPopulationSize(rel.getInput(), baseCols.build());
    if (population == null) {
        return null;
    }
    // No further computation required if the projection expressions are
    // all column references
    if (projCols.cardinality() == 0) {
        return population;
    }
    for (int bit : projCols.build()) {
        Double subRowCount = RelMdUtil.cardOfProjExpr(mq, rel, projExprs.get(bit));
        if (subRowCount == null) {
            return null;
        }
        population *= subRowCount;
    }
    // REVIEW zfong 6/22/06 - Broadbase did not have the call to
    // numDistinctVals.  This is needed; otherwise, population can be
    // larger than the number of rows in the RelNode.
    return RelMdUtil.numDistinctVals(population, mq.getRowCount(rel));
}

19 Source : RelMdPopulationSize.java
with Apache License 2.0
from lealone

public Double getPopulationSize(Values rel, RelMetadataQuery mq, ImmutableBitSet groupKey) {
    // replacedume half the rows are duplicates
    return rel.estimateRowCount(mq) / 2;
}

See More Examples