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
19
Source : StreamAggPrel.java
with Apache License 2.0
from zpochen
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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