org.apache.calcite.util.ImmutableBitSet.of() - java examples

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

58 Examples 7

19 View Complete Implementation : JoinInfo.java
Copyright Apache License 2.0
Author : apache
public ImmutableBitSet rightSet() {
    return ImmutableBitSet.of(rightKeys);
}

19 View Complete Implementation : JoinInfo.java
Copyright Apache License 2.0
Author : apache
public ImmutableBitSet leftSet() {
    return ImmutableBitSet.of(leftKeys);
}

18 View Complete Implementation : QuarkCube.java
Copyright Apache License 2.0
Author : qubole
private void validateCubeLatticeFilter(Lattice.Builder latticeBuilder) {
    if (latticeBuilder.filter != null) {
        ImmutableBitSet rCols = RelOptUtil.InputFinder.bits(latticeBuilder.filter);
        Set<Integer> dimSet = new HashSet<>();
        for (Dimension dimension : dimensions) {
            dimSet.add(latticeBuilder.resolveColumn(dimension.qualifiedCol).ordinal);
        }
        ImmutableBitSet dims = ImmutableBitSet.of(dimSet);
        if (!dims.contains(rCols)) {
            throw new RuntimeException("Cube filter is only allowed on dimensions");
        }
    }
}

18 View Complete Implementation : InstanceByClassTable.java
Copyright Apache License 2.0
Author : vlsi
@Override
public Statistic getStatistic() {
    List<ImmutableBitSet> uniqueKeys = ImmutableList.of(ImmutableBitSet.of(0));
    return Statistics.of(clreplacedesList.getTotalObjects(), uniqueKeys);
}

18 View Complete Implementation : LoptSemiJoinOptimizer.java
Copyright Apache License 2.0
Author : lealone
/**
 * Determines whether a join of the dimension table in a semijoin can be
 * removed. It can be if the dimension keys are unique and the only fields
 * referenced from the dimension table are its semijoin keys. The semijoin
 * keys can be mapped to the corresponding keys from the fact table (because
 * of the equality condition replacedociated with the semijoin keys). Therefore,
 * that's why the dimension table can be removed even though those fields
 * are referenced elsewhere in the query tree.
 *
 * @param multiJoin join factors being optimized
 * @param semiJoin semijoin under consideration
 * @param factIdx id of the fact table in the semijoin
 * @param dimIdx id of the dimension table in the semijoin
 */
private void removeJoin(LoptMultiJoin multiJoin, SemiJoin semiJoin, int factIdx, int dimIdx) {
    // if the dimension can be removed because of another semijoin, then
    // no need to proceed any further
    if (multiJoin.getJoinRemovalFactor(dimIdx) != null) {
        return;
    }
    // Check if the semijoin keys corresponding to the dimension table
    // are unique.  The semijoin will filter out the nulls.
    final ImmutableBitSet dimKeys = ImmutableBitSet.of(semiJoin.getRightKeys());
    final RelNode dimRel = multiJoin.getJoinFactor(dimIdx);
    if (!RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(mq, dimRel, dimKeys)) {
        return;
    }
    // check that the only fields referenced from the dimension table
    // in either its projection or join conditions are the dimension
    // keys
    ImmutableBitSet dimProjRefs = multiJoin.getProjFields(dimIdx);
    if (dimProjRefs == null) {
        int nDimFields = multiJoin.getNumFieldsInJoinFactor(dimIdx);
        dimProjRefs = ImmutableBitSet.range(0, nDimFields);
    }
    if (!dimKeys.contains(dimProjRefs)) {
        return;
    }
    int[] dimJoinRefCounts = multiJoin.getJoinFieldRefCounts(dimIdx);
    for (int i = 0; i < dimJoinRefCounts.length; i++) {
        if (dimJoinRefCounts[i] > 0) {
            if (!dimKeys.get(i)) {
                return;
            }
        }
    }
    // criteria met; keep track of the fact table and the semijoin that
    // allow the join of this dimension table to be removed
    multiJoin.setJoinRemovalFactor(dimIdx, factIdx);
    multiJoin.setJoinRemovalSemiJoin(dimIdx, semiJoin);
    // if the dimension table doesn't reference anything in its projection
    // and the only fields referenced in its joins are the dimension keys
    // of this semijoin, then we can decrement the join reference counts
    // corresponding to the fact table's semijoin keys, since the
    // dimension table doesn't need to use those keys
    if (dimProjRefs.cardinality() != 0) {
        return;
    }
    for (int i = 0; i < dimJoinRefCounts.length; i++) {
        if (dimJoinRefCounts[i] > 1) {
            return;
        } else if (dimJoinRefCounts[i] == 1) {
            if (!dimKeys.get(i)) {
                return;
            }
        }
    }
    int[] factJoinRefCounts = multiJoin.getJoinFieldRefCounts(factIdx);
    for (Integer key : semiJoin.getLeftKeys()) {
        factJoinRefCounts[key]--;
    }
}

18 View Complete Implementation : SnapshotThreadStacksTable.java
Copyright Apache License 2.0
Author : vlsi
@Override
public Statistic getStatistic() {
    int counter = 0;
    for (IThreadStack threadStack : getThreadStacks()) {
        counter += threadStack.getStackFrames().length;
    }
    return Statistics.of(counter, ImmutableList.of(ImmutableBitSet.of(0, 1)));
}

18 View Complete Implementation : LoptSemiJoinOptimizer.java
Copyright Apache License 2.0
Author : apache
/**
 * Determines whether a join of the dimension table in a semijoin can be
 * removed. It can be if the dimension keys are unique and the only fields
 * referenced from the dimension table are its semijoin keys. The semijoin
 * keys can be mapped to the corresponding keys from the fact table (because
 * of the equality condition replacedociated with the semijoin keys). Therefore,
 * that's why the dimension table can be removed even though those fields
 * are referenced elsewhere in the query tree.
 *
 * @param multiJoin join factors being optimized
 * @param semiJoin semijoin under consideration
 * @param factIdx id of the fact table in the semijoin
 * @param dimIdx id of the dimension table in the semijoin
 */
private void removeJoin(LoptMultiJoin multiJoin, LogicalJoin semiJoin, int factIdx, int dimIdx) {
    // if the dimension can be removed because of another semijoin, then
    // no need to proceed any further
    if (multiJoin.getJoinRemovalFactor(dimIdx) != null) {
        return;
    }
    // Check if the semijoin keys corresponding to the dimension table
    // are unique.  The semijoin will filter out the nulls.
    final ImmutableBitSet dimKeys = ImmutableBitSet.of(semiJoin.replacedyzeCondition().rightKeys);
    final RelNode dimRel = multiJoin.getJoinFactor(dimIdx);
    if (!RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(mq, dimRel, dimKeys)) {
        return;
    }
    // check that the only fields referenced from the dimension table
    // in either its projection or join conditions are the dimension
    // keys
    ImmutableBitSet dimProjRefs = multiJoin.getProjFields(dimIdx);
    if (dimProjRefs == null) {
        int nDimFields = multiJoin.getNumFieldsInJoinFactor(dimIdx);
        dimProjRefs = ImmutableBitSet.range(0, nDimFields);
    }
    if (!dimKeys.contains(dimProjRefs)) {
        return;
    }
    int[] dimJoinRefCounts = multiJoin.getJoinFieldRefCounts(dimIdx);
    for (int i = 0; i < dimJoinRefCounts.length; i++) {
        if (dimJoinRefCounts[i] > 0) {
            if (!dimKeys.get(i)) {
                return;
            }
        }
    }
    // criteria met; keep track of the fact table and the semijoin that
    // allow the join of this dimension table to be removed
    multiJoin.setJoinRemovalFactor(dimIdx, factIdx);
    multiJoin.setJoinRemovalSemiJoin(dimIdx, semiJoin);
    // if the dimension table doesn't reference anything in its projection
    // and the only fields referenced in its joins are the dimension keys
    // of this semijoin, then we can decrement the join reference counts
    // corresponding to the fact table's semijoin keys, since the
    // dimension table doesn't need to use those keys
    if (dimProjRefs.cardinality() != 0) {
        return;
    }
    for (int i = 0; i < dimJoinRefCounts.length; i++) {
        if (dimJoinRefCounts[i] > 1) {
            return;
        } else if (dimJoinRefCounts[i] == 1) {
            if (!dimKeys.get(i)) {
                return;
            }
        }
    }
    int[] factJoinRefCounts = multiJoin.getJoinFieldRefCounts(factIdx);
    for (Integer key : semiJoin.replacedyzeCondition().leftKeys) {
        factJoinRefCounts[key]--;
    }
}

18 View Complete Implementation : SqlLatticeStatisticProvider.java
Copyright Apache License 2.0
Author : apache
private double cardinality(Lattice lattice, Lattice.Column column) {
    final String sql = lattice.countSql(ImmutableBitSet.of(column.ordinal));
    final Table table = new MaterializationService.DefaultTableFactory().createTable(lattice.rootSchema, sql, ImmutableList.of());
    final Object[] values = Iterables.getOnlyElement(((ScannableTable) table).scan(null));
    return ((Number) values[0]).doubleValue();
}

17 View Complete Implementation : TestProjectedFieldsInJoin.java
Copyright Apache License 2.0
Author : dremio
@Test
public void testSimpleJoin() throws Exception {
    final String sql = "SELECT c.c_custkey, c.c_mktsegment from cp.\"tpch/customer.parquet\" c inner join cp.\"tpch/nation.parquet\" n on c.c_nationkey = n.n_nationkey";
    testQuery(sql, ImmutableList.of(ImmutableBitSet.of(0, 2)));
}

17 View Complete Implementation : TestProjectedFieldsInJoin.java
Copyright Apache License 2.0
Author : dremio
@Test
public void testSimpleJoinWithKeysNotUsed() throws Exception {
    final String sql = "SELECT c.c_custkey from cp.\"tpch/customer.parquet\" c inner join cp.\"tpch/nation.parquet\" n on c.c_nationkey = n.n_nationkey";
    testQuery(sql, ImmutableList.of(ImmutableBitSet.of(0)));
}

17 View Complete Implementation : TestProjectedFieldsInJoin.java
Copyright Apache License 2.0
Author : dremio
@Test
public void testSimpleJoinWithPartialKeys2() throws Exception {
    final String sql = "SELECT c.c_custkey, n.n_nationkey from cp.\"tpch/customer.parquet\" c inner join cp.\"tpch/nation.parquet\" n on c.c_nationkey = n.n_nationkey";
    testQuery(sql, ImmutableList.of(ImmutableBitSet.of(0, 2)));
}

17 View Complete Implementation : TestProjectedFieldsInJoin.java
Copyright Apache License 2.0
Author : dremio
@Test
public void testSimpleJoinWithPartialKeys1() throws Exception {
    final String sql = "SELECT c.c_custkey, c.c_nationkey from cp.\"tpch/customer.parquet\" c inner join cp.\"tpch/nation.parquet\" n on c.c_nationkey = n.n_nationkey";
    testQuery(sql, ImmutableList.of(ImmutableBitSet.of(0, 1)));
}

17 View Complete Implementation : TestProjectedFieldsInJoin.java
Copyright Apache License 2.0
Author : dremio
@Test
public void testSimpleJoinWithLimit() throws Exception {
    final String sql = "SELECT c.c_custkey, c.c_mktsegment from cp.\"tpch/customer.parquet\" c inner join cp.\"tpch/nation.parquet\" n on c.c_nationkey = n.n_nationkey limit 10";
    testQuery(sql, ImmutableList.of(ImmutableBitSet.of(0, 2)));
}

17 View Complete Implementation : TestProjectedFieldsInJoin.java
Copyright Apache License 2.0
Author : dremio
@Test
public void testMultipleJoins() throws Exception {
    final String sql = "SELECT c.c_custkey, s.s_name from cp.\"tpch/customer.parquet\" c, cp.\"tpch/nation.parquet\" n, cp.\"tpch/supplier.parquet\" s where c.c_nationkey = n.n_nationkey and s.s_nationkey = n.n_nationkey";
    testQuery(sql, ImmutableList.of(ImmutableBitSet.of(0, 2), ImmutableBitSet.of(0, 2)));
}

16 View Complete Implementation : InduceGroupingTypeTest.java
Copyright Apache License 2.0
Author : apache
@Test
public void testInduceGroupingType0() {
    final ImmutableBitSet groupSet = ImmutableBitSet.of();
    // Could be CUBE or ROLLUP but we choose SIMPLE
    List<ImmutableBitSet> groupSets = new ArrayList<>();
    groupSets.add(groupSet);
    replacedertEquals(Aggregate.Group.SIMPLE, Aggregate.Group.induce(groupSet, groupSets));
    groupSets = new ArrayList<>();
    replacedertEquals(Aggregate.Group.OTHER, Aggregate.Group.induce(groupSet, groupSets));
}

16 View Complete Implementation : InduceGroupingTypeTest.java
Copyright Apache License 2.0
Author : apache
/**
 * Tests a singleton grouping set {2}, whose power set has only two elements,
 * { {2}, {} }.
 */
@Test
public void testInduceGroupingType1() {
    final ImmutableBitSet groupSet = ImmutableBitSet.of(2);
    // Could be ROLLUP but we prefer CUBE
    List<ImmutableBitSet> groupSets = new ArrayList<>();
    groupSets.add(groupSet);
    groupSets.add(ImmutableBitSet.of());
    replacedertEquals(Aggregate.Group.CUBE, Aggregate.Group.induce(groupSet, groupSets));
    groupSets = new ArrayList<>();
    groupSets.add(ImmutableBitSet.of());
    replacedertEquals(Aggregate.Group.OTHER, Aggregate.Group.induce(groupSet, groupSets));
    groupSets = new ArrayList<>();
    groupSets.add(groupSet);
    replacedertEquals(Aggregate.Group.SIMPLE, Aggregate.Group.induce(groupSet, groupSets));
    groupSets = new ArrayList<>();
    replacedertEquals(Aggregate.Group.OTHER, Aggregate.Group.induce(groupSet, groupSets));
}

16 View Complete Implementation : InduceGroupingTypeTest.java
Copyright Apache License 2.0
Author : apache
@Test
public void testInduceGroupingType() {
    final ImmutableBitSet groupSet = ImmutableBitSet.of(1, 2, 4, 5);
    // SIMPLE
    final List<ImmutableBitSet> groupSets = new ArrayList<>();
    groupSets.add(groupSet);
    replacedertEquals(Aggregate.Group.SIMPLE, Aggregate.Group.induce(groupSet, groupSets));
    // CUBE (has only one bit, so could also be ROLLUP)
    groupSets.clear();
    final ImmutableBitSet groupSet0 = ImmutableBitSet.of(2);
    groupSets.add(groupSet0);
    groupSets.add(ImmutableBitSet.of());
    replacedertEquals(Aggregate.Group.CUBE, Aggregate.Group.induce(groupSet0, groupSets));
    replacedertThat(Aggregate.Group.isRollup(groupSet0, groupSets), is(true));
    replacedertThat(Aggregate.Group.getRollup(groupSets).toString(), is("[2]"));
    // CUBE
    final List<ImmutableBitSet> groupSets0 = ImmutableBitSet.ORDERING.sortedCopy(groupSet.powerSet());
    replacedertEquals(Aggregate.Group.CUBE, Aggregate.Group.induce(groupSet, groupSets0));
    replacedertThat(Aggregate.Group.isRollup(groupSet, groupSets0), is(false));
    // ROLLUP
    groupSets.clear();
    groupSets.add(ImmutableBitSet.of(1, 2, 4, 5));
    groupSets.add(ImmutableBitSet.of(1, 2, 4));
    groupSets.add(ImmutableBitSet.of(1, 2));
    groupSets.add(ImmutableBitSet.of(1));
    groupSets.add(ImmutableBitSet.of());
    replacedertEquals(Aggregate.Group.ROLLUP, Aggregate.Group.induce(groupSet, groupSets));
    replacedertThat(Aggregate.Group.isRollup(groupSet, groupSets), is(true));
    replacedertThat(Aggregate.Group.getRollup(groupSets).toString(), is("[1, 2, 4, 5]"));
    // ROLLUP, not removing bits in order
    groupSets.clear();
    groupSets.add(ImmutableBitSet.of(1, 2, 4, 5));
    groupSets.add(ImmutableBitSet.of(1, 4, 5));
    groupSets.add(ImmutableBitSet.of(4, 5));
    groupSets.add(ImmutableBitSet.of(4));
    groupSets.add(ImmutableBitSet.of());
    replacedertEquals(Aggregate.Group.ROLLUP, Aggregate.Group.induce(groupSet, groupSets));
    replacedertThat(Aggregate.Group.getRollup(groupSets).toString(), is("[4, 5, 1, 2]"));
    // ROLLUP, removing bits in reverse order
    groupSets.clear();
    groupSets.add(ImmutableBitSet.of(1, 2, 4, 5));
    groupSets.add(ImmutableBitSet.of(2, 4, 5));
    groupSets.add(ImmutableBitSet.of(4, 5));
    groupSets.add(ImmutableBitSet.of(5));
    groupSets.add(ImmutableBitSet.of());
    replacedertEquals(Aggregate.Group.ROLLUP, Aggregate.Group.induce(groupSet, groupSets));
    replacedertThat(Aggregate.Group.getRollup(groupSets).toString(), is("[5, 4, 2, 1]"));
    // OTHER
    groupSets.clear();
    groupSets.add(ImmutableBitSet.of(1, 2, 4, 5));
    groupSets.add(ImmutableBitSet.of(1, 2, 4));
    groupSets.add(ImmutableBitSet.of(1, 2));
    groupSets.add(ImmutableBitSet.of());
    replacedertEquals(Aggregate.Group.OTHER, Aggregate.Group.induce(groupSet, groupSets));
    groupSets.clear();
    groupSets.add(ImmutableBitSet.of(1, 2, 4, 5));
    groupSets.add(ImmutableBitSet.of(1, 2, 4));
    groupSets.add(ImmutableBitSet.of(1, 2));
    groupSets.add(ImmutableBitSet.of(1));
    replacedertEquals(Aggregate.Group.OTHER, Aggregate.Group.induce(groupSet, groupSets));
    groupSets.clear();
    groupSets.add(ImmutableBitSet.of(1, 2, 4, 5));
    groupSets.add(ImmutableBitSet.of(1, 2, 4));
    groupSets.add(ImmutableBitSet.of(1, 2));
    groupSets.add(ImmutableBitSet.of(1, 4));
    groupSets.add(ImmutableBitSet.of());
    replacedertEquals(Aggregate.Group.OTHER, Aggregate.Group.induce(groupSet, groupSets));
    groupSets.clear();
    groupSets.add(ImmutableBitSet.of(1, 2, 5));
    groupSets.add(ImmutableBitSet.of(1, 2, 4));
    groupSets.add(ImmutableBitSet.of(1, 2));
    groupSets.add(ImmutableBitSet.of(1));
    groupSets.add(ImmutableBitSet.of());
    try {
        final Aggregate.Group x = Aggregate.Group.induce(groupSet, groupSets);
        fail("expected error, got " + x);
    } catch (IllegalArgumentException ignore) {
    // ok
    }
    List<ImmutableBitSet> groupSets1 = ImmutableBitSet.ORDERING.sortedCopy(groupSets);
    replacedertEquals(Aggregate.Group.OTHER, Aggregate.Group.induce(groupSet, groupSets1));
    groupSets.clear();
    replacedertEquals(Aggregate.Group.OTHER, Aggregate.Group.induce(groupSet, groupSets));
    groupSets.clear();
    groupSets.add(ImmutableBitSet.of());
    replacedertEquals(Aggregate.Group.OTHER, Aggregate.Group.induce(groupSet, groupSets));
}

16 View Complete Implementation : DrillJoinRelBase.java
Copyright Apache License 2.0
Author : apache
@Override
public double estimateRowCount(RelMetadataQuery mq) {
    if (this.condition.isAlwaysTrue()) {
        return joinRowFactor * this.getLeft().estimateRowCount(mq) * this.getRight().estimateRowCount(mq);
    }
    LogicalJoin jr = LogicalJoin.create(this.getLeft(), this.getRight(), this.getCondition(), this.getVariablesSet(), this.getJoinType());
    if (// Statistics present for left and right side of the join
    !DrillRelOptUtil.guessRows(this) && jr.getJoinType() == JoinRelType.INNER) {
        List<Pair<Integer, Integer>> joinConditions = DrillRelOptUtil.replacedyzeSimpleEquiJoin((Join) jr);
        if (joinConditions.size() > 0) {
            List<Integer> leftSide = new ArrayList<>();
            List<Integer> rightSide = new ArrayList<>();
            for (Pair<Integer, Integer> condition : joinConditions) {
                leftSide.add(condition.left);
                rightSide.add(condition.right);
            }
            ImmutableBitSet leq = ImmutableBitSet.of(leftSide);
            ImmutableBitSet req = ImmutableBitSet.of(rightSide);
            Double ldrc = mq.getDistinctRowCount(this.getLeft(), leq, null);
            Double rdrc = mq.getDistinctRowCount(this.getRight(), req, null);
            Double lrc = mq.getRowCount(this.getLeft());
            Double rrc = mq.getRowCount(this.getRight());
            if (ldrc != null && rdrc != null && lrc != null && rrc != null) {
                // Join cardinality = (lrc * rrc) / Math.max(ldrc, rdrc). Avoid overflow by dividing earlier
                return (lrc / Math.max(ldrc, rdrc)) * rrc;
            }
        }
    }
    return joinRowFactor * Math.max(mq.getRowCount(this.getLeft()), mq.getRowCount(this.getRight()));
}

16 View Complete Implementation : AggPruleBase.java
Copyright Apache License 2.0
Author : apache
/**
 * Returns group-by keys with the remapped arguments for specified aggregate.
 *
 * @param groupSet ImmutableBitSet of aggregate rel node, whose group-by keys should be remapped.
 * @return {@link ImmutableBitSet} instance with remapped keys.
 */
public static ImmutableBitSet remapGroupSet(ImmutableBitSet groupSet) {
    List<Integer> newGroupSet = Lists.newArrayList();
    int groupSetToAdd = 0;
    for (int ignored : groupSet) {
        newGroupSet.add(groupSetToAdd++);
    }
    return ImmutableBitSet.of(newGroupSet);
}

16 View Complete Implementation : CatalogStatisticsTest.java
Copyright Apache License 2.0
Author : apache
@Test
public void testGetParreplacedionStatsWithUnknownColumnStats() throws Exception {
    TestParreplacedionableSourceFactory.registerTableSource(tEnv, "PartT", true);
    createParreplacedionStats("A", 1);
    createParreplacedionStats("A", 2);
    createParreplacedionColumnStats("A", 2);
    RelNode t1 = ((PlannerBase) ((TableEnvironmentImpl) tEnv).getPlanner()).optimize(TableTestUtil.toRelNode(tEnv.sqlQuery("select id, name from PartT where part1 = 'A'")));
    FlinkRelMetadataQuery mq = FlinkRelMetadataQuery.reuseOrCreate(t1.getCluster().getMetadataQuery());
    replacedertEquals(200.0, mq.getRowCount(t1), 0.0);
    // long type
    replacedertNull(mq.getDistinctRowCount(t1, ImmutableBitSet.of(0), null));
    replacedertNull(mq.getColumnNullCount(t1, 0));
    replacedertNull(mq.getColumnInterval(t1, 0));
    // string type
    replacedertNull(mq.getDistinctRowCount(t1, ImmutableBitSet.of(1), null));
    replacedertNull(mq.getColumnNullCount(t1, 1));
}

16 View Complete Implementation : CatalogStatisticsTest.java
Copyright Apache License 2.0
Author : apache
@Test
public void testGetParreplacedionStatsWithSomeUnknownColumnStats() throws Exception {
    TestParreplacedionableSourceFactory.registerTableSource(tEnv, "PartT", true);
    createParreplacedionStats("A", 1);
    createParreplacedionColumnStats("A", 1, true);
    createParreplacedionStats("A", 2);
    createParreplacedionColumnStats("A", 2);
    RelNode t1 = ((PlannerBase) ((TableEnvironmentImpl) tEnv).getPlanner()).optimize(TableTestUtil.toRelNode(tEnv.sqlQuery("select id, name from PartT where part1 = 'A'")));
    FlinkRelMetadataQuery mq = FlinkRelMetadataQuery.reuseOrCreate(t1.getCluster().getMetadataQuery());
    replacedertEquals(200.0, mq.getRowCount(t1), 0.0);
    // long type
    replacedertNull(mq.getDistinctRowCount(t1, ImmutableBitSet.of(0), null));
    replacedertNull(mq.getColumnNullCount(t1, 0));
    replacedertNull(mq.getColumnInterval(t1, 0));
    // string type
    replacedertNull(mq.getDistinctRowCount(t1, ImmutableBitSet.of(1), null));
    replacedertNull(mq.getColumnNullCount(t1, 1));
}

16 View Complete Implementation : CatalogStatisticsTest.java
Copyright Apache License 2.0
Author : apache
private void replacedertColumnStatistics(RelNode rel, FlinkRelMetadataQuery mq) {
    replacedertEquals(Arrays.asList(1.0, 8.0, 43.5, 12.0, 8.0), mq.getAverageColumnSizes(rel));
    // boolean type
    replacedertEquals(2.0, mq.getDistinctRowCount(rel, ImmutableBitSet.of(0), null), 0.0);
    replacedertEquals(5.0, mq.getColumnNullCount(rel, 0), 0.0);
    replacedertNull(mq.getColumnInterval(rel, 0));
    // long type
    replacedertEquals(23.0, mq.getDistinctRowCount(rel, ImmutableBitSet.of(1), null), 0.0);
    replacedertEquals(77.0, mq.getColumnNullCount(rel, 1), 0.0);
    replacedertEquals(ValueInterval$.MODULE$.apply(-123L, 763322L, true, true), mq.getColumnInterval(rel, 1));
    // string type
    replacedertEquals(20.0, mq.getDistinctRowCount(rel, ImmutableBitSet.of(2), null), 0.0);
    replacedertEquals(0.0, mq.getColumnNullCount(rel, 2), 0.0);
    replacedertNull(mq.getColumnInterval(rel, 2));
    // date type
    replacedertEquals(100.0, mq.getDistinctRowCount(rel, ImmutableBitSet.of(3), null), 0.0);
    replacedertEquals(0.0, mq.getColumnNullCount(rel, 3), 0.0);
    replacedertEquals(ValueInterval$.MODULE$.apply(java.sql.Date.valueOf(DateTimeUtils.unixDateToString(71)), java.sql.Date.valueOf(DateTimeUtils.unixDateToString(17923)), true, true), mq.getColumnInterval(rel, 3));
    // double type
    replacedertEquals(73.0, mq.getDistinctRowCount(rel, ImmutableBitSet.of(4), null), 0.0);
    replacedertEquals(27.0, mq.getColumnNullCount(rel, 4), 0.0);
    replacedertEquals(ValueInterval$.MODULE$.apply(-123.35, 7633.22, true, true), mq.getColumnInterval(rel, 4));
}

16 View Complete Implementation : LoptSemiJoinOptimizer.java
Copyright Apache License 2.0
Author : lealone
/**
 * Computes a score relevant to applying a set of semijoins on a fact table.
 * The higher the score, the better.
 *
 * @param factRel fact table being filtered
 * @param dimRel dimension table that participates in semijoin
 * @param semiJoin semijoin between fact and dimension tables
 *
 * @return computed score of applying the dimension table filters on the
 * fact table
 */
private double computeScore(RelNode factRel, RelNode dimRel, SemiJoin semiJoin) {
    // Estimate savings as a result of applying semijoin filter on fact
    // table.  As a heuristic, the selectivity of the semijoin needs to
    // be less than half.  There may be instances where an even smaller
    // selectivity value is required because of the overhead of
    // index lookups on a very large fact table.  Half was chosen as
    // a middle ground based on testing that was done with a large
    // data set.
    final ImmutableBitSet dimCols = ImmutableBitSet.of(semiJoin.getRightKeys());
    final double selectivity = RelMdUtil.computeSemiJoinSelectivity(mq, factRel, dimRel, semiJoin);
    if (selectivity > .5) {
        return 0;
    }
    final RelOptCost factCost = mq.getreplacedulativeCost(factRel);
    // if not enough information, return a low score
    if (factCost == null) {
        return 0;
    }
    double savings = (1.0 - Math.sqrt(selectivity)) * Math.max(1.0, factCost.getRows());
    // Additional savings if the dimension columns are unique.  We can
    // ignore nulls since they will be filtered out by the semijoin.
    boolean uniq = RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(mq, dimRel, dimCols);
    if (uniq) {
        savings *= 2.0;
    }
    // compute the cost of doing an extra scan on the dimension table,
    // including the distinct sort on top of the scan; if the dimension
    // columns are already unique, no need to add on the dup removal cost
    final Double dimSortCost = mq.getRowCount(dimRel);
    final Double dupRemCost = uniq ? 0 : dimSortCost;
    final RelOptCost dimCost = mq.getreplacedulativeCost(dimRel);
    if ((dimSortCost == null) || (dupRemCost == null) || (dimCost == null)) {
        return 0;
    }
    double dimRows = dimCost.getRows();
    if (dimRows < 1.0) {
        dimRows = 1.0;
    }
    return savings / dimRows;
}

16 View Complete Implementation : SqlValidatorUtil.java
Copyright Apache License 2.0
Author : apache
/**
 * Gets the bit-set to the column ordinals in the source for columns that
 * intersect in the target.
 *
 * @param sourceRowType The source upon which to ordinate the bit set.
 * @param indexToField  The map of ordinals to target fields.
 */
public static ImmutableBitSet getOrdinalBitSet(RelDataType sourceRowType, Map<Integer, RelDataTypeField> indexToField) {
    ImmutableBitSet source = ImmutableBitSet.of(Lists.transform(sourceRowType.getFieldList(), RelDataTypeField::getIndex));
    ImmutableBitSet target = ImmutableBitSet.of(indexToField.keySet());
    return source.intersect(target);
}

16 View Complete Implementation : SubQueryRemoveRule.java
Copyright Apache License 2.0
Author : lealone
/**
 * Rewrites a scalar sub-query into an
 * {@link org.apache.calcite.rel.core.Aggregate}.
 *
 * @param e            IN sub-query to rewrite
 * @param variablesSet A set of variables used by a relational
 *                     expression of the specified RexSubQuery
 * @param builder      Builder
 * @param offset       Offset to shift {@link RexInputRef}
 *
 * @return Expression that may be used to replace the RexSubQuery
 */
private RexNode rewriteScalarQuery(RexSubQuery e, Set<CorrelationId> variablesSet, RelBuilder builder, int inputCount, int offset) {
    builder.push(e.getRel());
    final RelMetadataQuery mq = e.getRel().getCluster().getMetadataQuery();
    final Boolean unique = mq.areColumnsUnique(builder.peek(), ImmutableBitSet.of());
    if (unique == null || !unique) {
        builder.aggregate(builder.groupKey(), builder.aggregateCall(SqlStdOperatorTable.SINGLE_VALUE, builder.field(0)));
    }
    builder.join(JoinRelType.LEFT, builder.literal(true), variablesSet);
    return field(builder, inputCount, offset);
}

16 View Complete Implementation : LoptSemiJoinOptimizer.java
Copyright Apache License 2.0
Author : apache
/**
 * Computes a score relevant to applying a set of semijoins on a fact table.
 * The higher the score, the better.
 *
 * @param factRel fact table being filtered
 * @param dimRel dimension table that participates in semijoin
 * @param semiJoin semijoin between fact and dimension tables
 *
 * @return computed score of applying the dimension table filters on the
 * fact table
 */
private double computeScore(RelNode factRel, RelNode dimRel, LogicalJoin semiJoin) {
    // Estimate savings as a result of applying semijoin filter on fact
    // table.  As a heuristic, the selectivity of the semijoin needs to
    // be less than half.  There may be instances where an even smaller
    // selectivity value is required because of the overhead of
    // index lookups on a very large fact table.  Half was chosen as
    // a middle ground based on testing that was done with a large
    // data set.
    final ImmutableBitSet dimCols = ImmutableBitSet.of(semiJoin.replacedyzeCondition().rightKeys);
    final double selectivity = RelMdUtil.computeSemiJoinSelectivity(mq, factRel, dimRel, semiJoin);
    if (selectivity > .5) {
        return 0;
    }
    final RelOptCost factCost = mq.getreplacedulativeCost(factRel);
    // if not enough information, return a low score
    if (factCost == null) {
        return 0;
    }
    double savings = (1.0 - Math.sqrt(selectivity)) * Math.max(1.0, factCost.getRows());
    // Additional savings if the dimension columns are unique.  We can
    // ignore nulls since they will be filtered out by the semijoin.
    boolean uniq = RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(mq, dimRel, dimCols);
    if (uniq) {
        savings *= 2.0;
    }
    // compute the cost of doing an extra scan on the dimension table,
    // including the distinct sort on top of the scan; if the dimension
    // columns are already unique, no need to add on the dup removal cost
    final Double dimSortCost = mq.getRowCount(dimRel);
    final Double dupRemCost = uniq ? 0 : dimSortCost;
    final RelOptCost dimCost = mq.getreplacedulativeCost(dimRel);
    if ((dimSortCost == null) || (dupRemCost == null) || (dimCost == null)) {
        return 0;
    }
    double dimRows = dimCost.getRows();
    if (dimRows < 1.0) {
        dimRows = 1.0;
    }
    return savings / dimRows;
}

15 View Complete Implementation : ComplexUnnestVisitor.java
Copyright Apache License 2.0
Author : apache
@Override
public RelNode visit(LogicalCorrelate correlate) {
    RelNode left = correlate.getLeft().accept(this);
    leftInputs.put(correlate.getCorrelationId(), left);
    RelNode right = correlate.getRight().accept(this);
    // if right input wasn't changed or left input wasn't changed
    // after rewriting right input, no need to create Correlate with new CorrelationId
    if (correlate.getRight() == right || left == leftInputs.get(correlate.getCorrelationId())) {
        if (correlate.getLeft() == left) {
            return correlate;
        }
        // changed only inputs, but CorrelationId left the same
        return correlate.copy(correlate.getTraitSet(), Arrays.asList(left, right));
    }
    Correlate newCorrelate = correlate.copy(correlate.getTraitSet(), leftInputs.get(correlate.getCorrelationId()), right, updatedCorrelationIds.get(correlate.getCorrelationId()), ImmutableBitSet.of(left.getRowType().getFieldCount()), correlate.getJoinType());
    RelBuilder builder = DrillRelFactories.LOGICAL_BUILDER.create(correlate.getCluster(), null);
    builder.push(newCorrelate);
    List<RexNode> topProjectExpressions = left.getRowType().getFieldList().stream().map(field -> builder.getRexBuilder().makeInputRef(newCorrelate, field.getIndex())).collect(Collectors.toList());
    // Accommodate the new $COMPLEX_FIELD_NAME column.
    int rightStartIndex = left.getRowType().getFieldList().size() + 1;
    switch(correlate.getJoinType()) {
        case LEFT:
        case INNER:
            // adds field from the right input of correlate to the top project
            topProjectExpressions.addAll(right.getRowType().getFieldList().stream().map(field -> builder.getRexBuilder().makeInputRef(newCorrelate, field.getIndex() + rightStartIndex)).collect(Collectors.toList()));
        // fall through
        case ANTI:
        case SEMI:
            builder.project(topProjectExpressions, correlate.getRowType().getFieldNames());
    }
    return builder.build();
}

15 View Complete Implementation : FlinkAggregateJoinTransposeRule.java
Copyright Apache License 2.0
Author : apache
/**
 * Convert aggregate with AUXILIARY_GROUP to regular aggregate.
 * Return original aggregate and null project if the given aggregate does not contain AUXILIARY_GROUP,
 * else new aggregate without AUXILIARY_GROUP and a project to permute output columns if needed.
 */
private Pair<Aggregate, List<RexNode>> toRegularAggregate(Aggregate aggregate) {
    Tuple2<int[], Seq<AggregateCall>> auxGroupAndRegularAggCalls = AggregateUtil.checkAndSplitAggCalls(aggregate);
    final int[] auxGroup = auxGroupAndRegularAggCalls._1;
    final Seq<AggregateCall> regularAggCalls = auxGroupAndRegularAggCalls._2;
    if (auxGroup.length != 0) {
        int[] fullGroupSet = AggregateUtil.checkAndGetFullGroupSet(aggregate);
        ImmutableBitSet newGroupSet = ImmutableBitSet.of(fullGroupSet);
        List<AggregateCall> aggCalls = JavaConverters.seqAsJavaListConverter(regularAggCalls).asJava();
        final Aggregate newAgg = aggregate.copy(aggregate.getTraitSet(), aggregate.getInput(), aggregate.indicator, newGroupSet, com.google.common.collect.ImmutableList.of(newGroupSet), aggCalls);
        final List<RelDataTypeField> aggFields = aggregate.getRowType().getFieldList();
        final List<RexNode> projectAfterAgg = new ArrayList<>();
        for (int i = 0; i < fullGroupSet.length; ++i) {
            int group = fullGroupSet[i];
            int index = newGroupSet.indexOf(group);
            projectAfterAgg.add(new RexInputRef(index, aggFields.get(i).getType()));
        }
        int fieldCntOreplacedg = aggFields.size();
        for (int i = fullGroupSet.length; i < fieldCntOreplacedg; ++i) {
            projectAfterAgg.add(new RexInputRef(i, aggFields.get(i).getType()));
        }
        Preconditions.checkArgument(projectAfterAgg.size() == fieldCntOreplacedg);
        return new Pair<>(newAgg, projectAfterAgg);
    } else {
        return new Pair<>(aggregate, null);
    }
}

15 View Complete Implementation : DrillJoinRelBase.java
Copyright Apache License 2.0
Author : lealone
@Override
public double estimateRowCount(RelMetadataQuery mq) {
    if (this.condition.isAlwaysTrue()) {
        return joinRowFactor * this.getLeft().estimateRowCount(mq) * this.getRight().estimateRowCount(mq);
    }
    int[] joinFields = new int[2];
    LogicalJoin jr = LogicalJoin.create(this.getLeft(), this.getRight(), this.getCondition(), this.getVariablesSet(), this.getJoinType());
    if (// Statistics present for left and right side of the join
    !DrillRelOptUtil.guessRows(this) && jr.getJoinType() == JoinRelType.INNER && DrillRelOptUtil.replacedyzeSimpleEquiJoin((Join) jr, joinFields)) {
        ImmutableBitSet leq = ImmutableBitSet.of(joinFields[0]);
        ImmutableBitSet req = ImmutableBitSet.of(joinFields[1]);
        Double ldrc = mq.getDistinctRowCount(this.getLeft(), leq, null);
        Double rdrc = mq.getDistinctRowCount(this.getRight(), req, null);
        Double lrc = mq.getRowCount(this.getLeft());
        Double rrc = mq.getRowCount(this.getRight());
        if (ldrc != null && rdrc != null && lrc != null && rrc != null) {
            // Join cardinality = (lrc * rrc) / Math.max(ldrc, rdrc). Avoid overflow by dividing earlier
            return (lrc / Math.max(ldrc, rdrc)) * rrc;
        }
    }
    return joinRowFactor * Math.max(mq.getRowCount(this.getLeft()), mq.getRowCount(this.getRight()));
}

15 View Complete Implementation : AggregatingSelectScope.java
Copyright Apache License 2.0
Author : lealone
// ~ Methods ----------------------------------------------------------------
private Resolved resolve() {
    final ImmutableList.Builder<ImmutableList<ImmutableBitSet>> builder = ImmutableList.builder();
    List<SqlNode> extraExprs = ImmutableList.of();
    Map<Integer, Integer> groupExprProjection = ImmutableMap.of();
    if (select.getGroup() != null) {
        final SqlNodeList groupList = select.getGroup();
        final SqlValidatorUtil.Groupreplacedyzer groupreplacedyzer = new SqlValidatorUtil.Groupreplacedyzer(temporaryGroupExprList);
        for (SqlNode groupExpr : groupList) {
            SqlValidatorUtil.replacedyzeGroupItem(this, groupreplacedyzer, builder, groupExpr);
        }
        extraExprs = groupreplacedyzer.extraExprs;
        groupExprProjection = groupreplacedyzer.groupExprProjection;
    }
    final Set<ImmutableBitSet> flatGroupSets = Sets.newTreeSet(ImmutableBitSet.COMPARATOR);
    for (List<ImmutableBitSet> groupSet : EnumeratorUtils.product(builder.build())) {
        flatGroupSets.add(ImmutableBitSet.union(groupSet));
    }
    // For GROUP BY (), we need a singleton grouping set.
    if (flatGroupSets.isEmpty()) {
        flatGroupSets.add(ImmutableBitSet.of());
    }
    return new Resolved(extraExprs, temporaryGroupExprList, flatGroupSets, groupExprProjection);
}

15 View Complete Implementation : SubQueryRemoveRule.java
Copyright Apache License 2.0
Author : apache
/**
 * Rewrites a scalar sub-query into an
 * {@link org.apache.calcite.rel.core.Aggregate}.
 *
 * @param e            IN sub-query to rewrite
 * @param variablesSet A set of variables used by a relational
 *                     expression of the specified RexSubQuery
 * @param builder      Builder
 * @param offset       Offset to shift {@link RexInputRef}
 *
 * @return Expression that may be used to replace the RexSubQuery
 */
private RexNode rewriteScalarQuery(RexSubQuery e, Set<CorrelationId> variablesSet, RelBuilder builder, int inputCount, int offset) {
    builder.push(e.rel);
    final RelMetadataQuery mq = e.rel.getCluster().getMetadataQuery();
    final Boolean unique = mq.areColumnsUnique(builder.peek(), ImmutableBitSet.of());
    if (unique == null || !unique) {
        builder.aggregate(builder.groupKey(), builder.aggregateCall(SqlStdOperatorTable.SINGLE_VALUE, builder.field(0)));
    }
    builder.join(JoinRelType.LEFT, builder.literal(true), variablesSet);
    return field(builder, inputCount, offset);
}

15 View Complete Implementation : AggregatingSelectScope.java
Copyright Apache License 2.0
Author : apache
// ~ Methods ----------------------------------------------------------------
private Resolved resolve() {
    final ImmutableList.Builder<ImmutableList<ImmutableBitSet>> builder = ImmutableList.builder();
    List<SqlNode> extraExprs = ImmutableList.of();
    Map<Integer, Integer> groupExprProjection = ImmutableMap.of();
    if (select.getGroup() != null) {
        final SqlNodeList groupList = select.getGroup();
        final SqlValidatorUtil.Groupreplacedyzer groupreplacedyzer = new SqlValidatorUtil.Groupreplacedyzer(temporaryGroupExprList);
        for (SqlNode groupExpr : groupList) {
            SqlValidatorUtil.replacedyzeGroupItem(this, groupreplacedyzer, builder, groupExpr);
        }
        extraExprs = groupreplacedyzer.extraExprs;
        groupExprProjection = groupreplacedyzer.groupExprProjection;
    }
    final Set<ImmutableBitSet> flatGroupSets = Sets.newTreeSet(ImmutableBitSet.COMPARATOR);
    for (List<ImmutableBitSet> groupSet : Linq4j.product(builder.build())) {
        flatGroupSets.add(ImmutableBitSet.union(groupSet));
    }
    // For GROUP BY (), we need a singleton grouping set.
    if (flatGroupSets.isEmpty()) {
        flatGroupSets.add(ImmutableBitSet.of());
    }
    return new Resolved(extraExprs, temporaryGroupExprList, flatGroupSets, groupExprProjection);
}

15 View Complete Implementation : LatticeTest.java
Copyright Apache License 2.0
Author : apache
/**
 * Tests that it's OK for a lattice to have the same name as a table in the
 * schema.
 */
@Test
public void testLatticeSql() throws Exception {
    modelWithLattice("EMPLOYEES", "select * from \"foodmart\".\"days\"").doWithConnection(c -> {
        final SchemaPlus schema = c.getRootSchema();
        final SchemaPlus adhoc = schema.getSubSchema("adhoc");
        replacedertThat(adhoc.getTableNames().contains("EMPLOYEES"), is(true));
        final Map.Entry<String, CalciteSchema.LatticeEntry> entry = adhoc.unwrap(CalciteSchema.clreplaced).getLatticeMap().firstEntry();
        final Lattice lattice = entry.getValue().getLattice();
        final String sql = "SELECT \"days\".\"day\"\n" + "FROM \"foodmart\".\"days\" AS \"days\"\n" + "GROUP BY \"days\".\"day\"";
        replacedertThat(lattice.sql(ImmutableBitSet.of(0), ImmutableList.of()), is(sql));
        final String sql2 = "SELECT" + " \"days\".\"day\", \"days\".\"week_day\"\n" + "FROM \"foodmart\".\"days\" AS \"days\"";
        replacedertThat(lattice.sql(ImmutableBitSet.of(0, 1), false, ImmutableList.of()), is(sql2));
    });
}

15 View Complete Implementation : PigRelOpVisitor.java
Copyright Apache License 2.0
Author : apache
/**
 * Processes a CUBE/ROLLUP group type.
 *
 * @param groupType type of the group, either ROLLUP or CUBE
 * @param loCogroup Pig logical group operator
 * @throws FrontendException Exception during processing Pig operator
 */
private void processCube(GroupType groupType, LOCogroup loCogroup) throws FrontendException {
    replacedert loCogroup.getExpressionPlans().size() == 1;
    // First adjust the top rel in the builder, which will be served as input rel for
    // the CUBE COGROUP operator because Pig already convert LOCube into
    // a ForEach (to project out the group set using @CubeDimensions or @RollupDimension UDFs)
    // and a @LOCogroup. We dont need to use these UDFs to generate the groupset.
    // So we need to undo the effect of translate this ForEach int relational
    // algebra nodes before.
    adjustCubeInput();
    // Project out the group keys and the whole row, which will be aggregated with
    // COLLECT operator later.
    preprocessCogroup(loCogroup, true);
    // Generate the group set for the corresponding group type.
    ImmutableList.Builder<ImmutableBitSet> groupsetBuilder = new ImmutableList.Builder<>();
    List<Integer> keyIndexs = new ArrayList<>();
    groupsetBuilder.add(ImmutableBitSet.of(keyIndexs));
    int groupCount = loCogroup.getExpressionPlans().get(0).size();
    for (int i = groupCount - 1; i >= 0; i--) {
        keyIndexs.add(i);
        groupsetBuilder.add(ImmutableBitSet.of(keyIndexs));
    }
    final ImmutableBitSet groupSet = ImmutableBitSet.of(keyIndexs);
    final ImmutableList<ImmutableBitSet> groupSets = (groupType == GroupType.CUBE) ? ImmutableList.copyOf(groupSet.powerSet()) : groupsetBuilder.build();
    RelBuilder.GroupKey groupKey = builder.groupKey(groupSet, (Iterable<ImmutableBitSet>) groupSets);
    // Finally, do COLLECT aggregate.
    builder.cogroup(ImmutableList.of(groupKey));
}

15 View Complete Implementation : AggPrelBase.java
Copyright Apache License 2.0
Author : apache
@Override
public Prel prepareForLateralUnnestPipeline(List<RelNode> children) {
    List<Integer> groupingCols = Lists.newArrayList();
    groupingCols.add(0);
    for (int groupingCol : groupSet.asList()) {
        groupingCols.add(groupingCol + 1);
    }
    ImmutableBitSet groupingSet = ImmutableBitSet.of(groupingCols);
    List<ImmutableBitSet> groupingSets = Lists.newArrayList();
    groupingSets.add(groupingSet);
    List<AggregateCall> aggregateCalls = Lists.newArrayList();
    for (AggregateCall aggCall : aggCalls) {
        List<Integer> arglist = Lists.newArrayList();
        for (int arg : aggCall.getArgList()) {
            arglist.add(arg + 1);
        }
        aggregateCalls.add(AggregateCall.create(aggCall.getAggregation(), aggCall.isDistinct(), aggCall.isApproximate(), arglist, aggCall.filterArg, aggCall.type, aggCall.name));
    }
    return (Prel) copy(traitSet, children.get(0), indicator, groupingSet, groupingSets, aggregateCalls);
}

14 View Complete Implementation : RelMdColumnUniqueness.java
Copyright Apache License 2.0
Author : apache
/**
 * Deduce constant columns from predicates of rel and return the union
 * bitsets of checkingColumns and the constant columns.
 */
private static ImmutableBitSet decorateWithConstantColumnsFromPredicates(ImmutableBitSet checkingColumns, RelNode rel, RelMetadataQuery mq) {
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(rel);
    if (predicates != null) {
        final Set<Integer> constantIndexes = new HashSet();
        predicates.constantMap.keySet().forEach(rex -> {
            if (rex instanceof RexInputRef) {
                constantIndexes.add(((RexInputRef) rex).getIndex());
            }
        });
        if (!constantIndexes.isEmpty()) {
            return checkingColumns.union(ImmutableBitSet.of(constantIndexes));
        }
    }
    // If no constant columns deduced, return the original "checkingColumns".
    return checkingColumns;
}

14 View Complete Implementation : CatalogStatisticsTest.java
Copyright Apache License 2.0
Author : apache
@Test
public void testGetParreplacedionStatsFromCatalog() throws Exception {
    TestParreplacedionableSourceFactory.registerTableSource(tEnv, "PartT", true);
    createParreplacedionStats("A", 1);
    createParreplacedionColumnStats("A", 1);
    createParreplacedionStats("A", 2);
    createParreplacedionColumnStats("A", 2);
    RelNode t1 = ((PlannerBase) ((TableEnvironmentImpl) tEnv).getPlanner()).optimize(TableTestUtil.toRelNode(tEnv.sqlQuery("select id, name from PartT where part1 = 'A'")));
    FlinkRelMetadataQuery mq = FlinkRelMetadataQuery.reuseOrCreate(t1.getCluster().getMetadataQuery());
    replacedertEquals(200.0, mq.getRowCount(t1), 0.0);
    replacedertEquals(Arrays.asList(8.0, 43.5), mq.getAverageColumnSizes(t1));
    // long type
    replacedertEquals(46.0, mq.getDistinctRowCount(t1, ImmutableBitSet.of(0), null), 0.0);
    replacedertEquals(154.0, mq.getColumnNullCount(t1, 0), 0.0);
    replacedertEquals(ValueInterval$.MODULE$.apply(-123L, 763322L, true, true), mq.getColumnInterval(t1, 0));
    // string type
    replacedertEquals(40.0, mq.getDistinctRowCount(t1, ImmutableBitSet.of(1), null), 0.0);
    replacedertEquals(0.0, mq.getColumnNullCount(t1, 1), 0.0);
    replacedertNull(mq.getColumnInterval(t1, 1));
}

14 View Complete Implementation : CatalogStatisticsTest.java
Copyright Apache License 2.0
Author : apache
@Test
public void testGetParreplacedionStatsWithUnknownRowCount() throws Exception {
    TestParreplacedionableSourceFactory.registerTableSource(tEnv, "PartT", true);
    createParreplacedionStats("A", 1, TableStats.UNKNOWN.getRowCount());
    createParreplacedionColumnStats("A", 1);
    createParreplacedionStats("A", 2);
    createParreplacedionColumnStats("A", 2);
    RelNode t1 = ((PlannerBase) ((TableEnvironmentImpl) tEnv).getPlanner()).optimize(TableTestUtil.toRelNode(tEnv.sqlQuery("select id, name from PartT where part1 = 'A'")));
    FlinkRelMetadataQuery mq = FlinkRelMetadataQuery.reuseOrCreate(t1.getCluster().getMetadataQuery());
    replacedertEquals(100_000_000, mq.getRowCount(t1), 0.0);
    replacedertEquals(Arrays.asList(8.0, 43.5), mq.getAverageColumnSizes(t1));
    // long type
    replacedertEquals(46.0, mq.getDistinctRowCount(t1, ImmutableBitSet.of(0), null), 0.0);
    replacedertEquals(154.0, mq.getColumnNullCount(t1, 0), 0.0);
    replacedertEquals(ValueInterval$.MODULE$.apply(-123L, 763322L, true, true), mq.getColumnInterval(t1, 0));
    // string type
    replacedertEquals(40.0, mq.getDistinctRowCount(t1, ImmutableBitSet.of(1), null), 0.0);
    replacedertEquals(0.0, mq.getColumnNullCount(t1, 1), 0.0);
    replacedertNull(mq.getColumnInterval(t1, 1));
}

14 View Complete Implementation : DremioFieldTrimmer.java
Copyright Apache License 2.0
Author : dremio
/**
 * Variant of {@link #trimFields(RelNode, ImmutableBitSet, Set)} for
 * {@link com.dremio.exec.planner.logical.JoinRel}.
 * This sets ImmutableBitSet to JoinRel which indicates inputs used by its consumer
 */
public TrimResult trimFields(JoinRel join, ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields) {
    TrimResult result = super.trimFields(join, fieldsUsed, extraFields);
    Join rel = (Join) result.left;
    Mapping mapping = result.right;
    ImmutableBitSet projectedFields = ImmutableBitSet.of(fieldsUsed.asList().stream().map(mapping::getTarget).collect(Collectors.toList()));
    RelNode newJoin = JoinRel.create(rel.getCluster(), rel.getTraitSet(), rel.getLeft(), rel.getRight(), rel.getCondition(), rel.getJoinType(), projectedFields);
    final Mapping map = Mappings.create(MappingType.INVERSE_SURJECTION, join.getRowType().getFieldCount(), newJoin.getRowType().getFieldCount());
    int j = 0;
    for (int i = 0; i < join.getRowType().getFieldCount(); i++) {
        if (fieldsUsed.get(i)) {
            map.set(i, j);
            j++;
        }
    }
    return result(newJoin, map);
}

13 View Complete Implementation : ArrayTable.java
Copyright Apache License 2.0
Author : apache
public Statistic getStatistic() {
    final List<ImmutableBitSet> keys = new ArrayList<>();
    final Content content = supplier.get();
    for (Ord<Column> ord : Ord.zip(content.columns)) {
        if (ord.e.cardinality == content.size) {
            keys.add(ImmutableBitSet.of(ord.i));
        }
    }
    return Statistics.of(content.size, keys, content.collations);
}

13 View Complete Implementation : LogicalWindow.java
Copyright Apache License 2.0
Author : apache
private static void addWindows(Multimap<WindowKey, RexOver> windowMap, RexOver over, final int inputFieldCount) {
    final RexWindow aggWindow = over.getWindow();
    // Look up or create a window.
    RelCollation orderKeys = getCollation(Lists.newArrayList(Util.filter(aggWindow.orderKeys, rexFieldCollation -> rexFieldCollation.left instanceof RexLocalRef)));
    ImmutableBitSet groupSet = ImmutableBitSet.of(getProjectOrdinals(aggWindow.parreplacedionKeys));
    final int groupLength = groupSet.length();
    if (inputFieldCount < groupLength) {
        // If PARreplacedION BY references constant, we can ignore such parreplacedion key.
        // All the inputs after inputFieldCount are literals, thus we can clear.
        groupSet = groupSet.except(ImmutableBitSet.range(inputFieldCount, groupLength));
    }
    WindowKey windowKey = new WindowKey(groupSet, orderKeys, aggWindow.isRows(), aggWindow.getLowerBound(), aggWindow.getUpperBound());
    windowMap.put(windowKey, over);
}

13 View Complete Implementation : FlinkPreparingTableBase.java
Copyright Apache License 2.0
Author : apache
/**
 * Returns unique keySets of current table.
 */
public Optional<Set<ImmutableBitSet>> uniqueKeysSet() {
    Set<? extends Set<String>> uniqueKeys = statistic.getUniqueKeys();
    if (uniqueKeys == null) {
        return Optional.empty();
    } else if (uniqueKeys.size() == 0) {
        return Optional.of(ImmutableSet.of());
    } else {
        ImmutableSet.Builder<ImmutableBitSet> uniqueKeysSetBuilder = ImmutableSet.builder();
        for (Set<String> keys : uniqueKeys) {
            // some columns in original uniqueKeys may not exist in RowType after project push down.
            boolean allUniqueKeysExists = keys.stream().allMatch(f -> rowType.getField(f, false, false) != null);
            // if not all columns in original uniqueKey, skip this uniqueKey
            if (allUniqueKeysExists) {
                Set<Integer> keysPosition = keys.stream().map(f -> rowType.getField(f, false, false).getIndex()).collect(Collectors.toSet());
                uniqueKeysSetBuilder.add(ImmutableBitSet.of(keysPosition));
            }
        }
        return Optional.of(uniqueKeysSetBuilder.build());
    }
}

13 View Complete Implementation : CatalogConstraintTest.java
Copyright Apache License 2.0
Author : apache
@Test
public void testWithPrimaryKey() throws Exception {
    TableSchema tableSchema = TableSchema.builder().fields(new String[] { "a", "b", "c" }, new DataType[] { DataTypes.STRING(), new AtomicDataType(new BigIntType(false)), DataTypes.INT() }).primaryKey("b").build();
    Map<String, String> properties = buildCatalogTableProperties(tableSchema);
    catalog.createTable(new ObjectPath(databaseName, "T1"), new CatalogTableImpl(tableSchema, properties, ""), false);
    RelNode t1 = TableTestUtil.toRelNode(tEnv.sqlQuery("select * from T1"));
    FlinkRelMetadataQuery mq = FlinkRelMetadataQuery.reuseOrCreate(t1.getCluster().getMetadataQuery());
    replacedertEquals(ImmutableSet.of(ImmutableBitSet.of(1)), mq.getUniqueKeys(t1));
}

12 View Complete Implementation : SqlValidatorUtil.java
Copyright Apache License 2.0
Author : apache
/**
 * Computes the cube of bit sets.
 *
 * <p>For example,  <code>rollup({0}, {1})</code>
 * returns <code>({0, 1}, {0}, {})</code>.
 *
 * <p>Bit sets are not necessarily singletons:
 * <code>rollup({0, 2}, {3, 5})</code>
 * returns <code>({0, 2, 3, 5}, {0, 2}, {})</code>.
 */
@VisibleForTesting
public static ImmutableList<ImmutableBitSet> cube(List<ImmutableBitSet> bitSets) {
    // Given the bit sets [{1}, {2, 3}, {5}],
    // form the lists [[{1}, {}], [{2, 3}, {}], [{5}, {}]].
    final Set<List<ImmutableBitSet>> builder = new LinkedHashSet<>();
    for (ImmutableBitSet bitSet : bitSets) {
        builder.add(Arrays.asList(bitSet, ImmutableBitSet.of()));
    }
    Set<ImmutableBitSet> flattenedBitSets = new LinkedHashSet<>();
    for (List<ImmutableBitSet> o : Linq4j.product(builder)) {
        flattenedBitSets.add(ImmutableBitSet.union(o));
    }
    return ImmutableList.copyOf(flattenedBitSets);
}

12 View Complete Implementation : SqlValidatorUtil.java
Copyright Apache License 2.0
Author : apache
/**
 * replacedyzes a component of a tuple in a GROUPING SETS clause.
 */
private static ImmutableBitSet replacedyzeGroupExpr(SqlValidatorScope scope, Groupreplacedyzer groupreplacedyzer, SqlNode groupExpr) {
    final SqlNode expandedGroupExpr = scope.getValidator().expand(groupExpr, scope);
    switch(expandedGroupExpr.getKind()) {
        case ROW:
            return ImmutableBitSet.union(replacedyzeGroupTuple(scope, groupreplacedyzer, ((SqlCall) expandedGroupExpr).getOperandList()));
        case OTHER:
            if (expandedGroupExpr instanceof SqlNodeList && ((SqlNodeList) expandedGroupExpr).size() == 0) {
                return ImmutableBitSet.of();
            }
    }
    final int ref = lookupGroupExpr(groupreplacedyzer, groupExpr);
    if (expandedGroupExpr instanceof SqlIdentifier) {
        // SQL 2003 does not allow expressions of column references
        SqlIdentifier expr = (SqlIdentifier) expandedGroupExpr;
        // column references should be fully qualified.
        replacedert expr.names.size() >= 2;
        String originalRelName = expr.names.get(0);
        String originalFieldName = expr.names.get(1);
        final SqlNameMatcher nameMatcher = scope.getValidator().getCatalogReader().nameMatcher();
        final SqlValidatorScope.ResolvedImpl resolved = new SqlValidatorScope.ResolvedImpl();
        scope.resolve(ImmutableList.of(originalRelName), nameMatcher, false, resolved);
        replacedert resolved.count() == 1;
        final SqlValidatorScope.Resolve resolve = resolved.only();
        final RelDataType rowType = resolve.rowType();
        final int childNamespaceIndex = resolve.path.steps().get(0).i;
        int namespaceOffset = 0;
        if (childNamespaceIndex > 0) {
            // If not the first child, need to figure out the width of
            // output types from all the preceding namespaces
            final SqlValidatorScope ancestorScope = resolve.scope;
            replacedert ancestorScope instanceof ListScope;
            List<SqlValidatorNamespace> children = ((ListScope) ancestorScope).getChildren();
            for (int j = 0; j < childNamespaceIndex; j++) {
                namespaceOffset += children.get(j).getRowType().getFieldCount();
            }
        }
        RelDataTypeField field = nameMatcher.field(rowType, originalFieldName);
        int origPos = namespaceOffset + field.getIndex();
        groupreplacedyzer.groupExprProjection.put(origPos, ref);
    }
    return ImmutableBitSet.of(ref);
}

12 View Complete Implementation : SqlValidatorUtil.java
Copyright Apache License 2.0
Author : lealone
/**
 * replacedyzes a component of a tuple in a GROUPING SETS clause.
 */
private static ImmutableBitSet replacedyzeGroupExpr(SqlValidatorScope scope, Groupreplacedyzer groupreplacedyzer, SqlNode groupExpr) {
    final SqlNode expandedGroupExpr = scope.getValidator().expand(groupExpr, scope);
    switch(expandedGroupExpr.getKind()) {
        case ROW:
            return ImmutableBitSet.union(replacedyzeGroupTuple(scope, groupreplacedyzer, ((SqlCall) expandedGroupExpr).getOperandList()));
        case OTHER:
            if (expandedGroupExpr instanceof SqlNodeList && ((SqlNodeList) expandedGroupExpr).size() == 0) {
                return ImmutableBitSet.of();
            }
    }
    final int ref = lookupGroupExpr(groupreplacedyzer, groupExpr);
    if (expandedGroupExpr instanceof SqlIdentifier) {
        // SQL 2003 does not allow expressions of column references
        SqlIdentifier expr = (SqlIdentifier) expandedGroupExpr;
        // column references should be fully qualified.
        replacedert expr.names.size() == 2;
        String originalRelName = expr.names.get(0);
        String originalFieldName = expr.names.get(1);
        final SqlNameMatcher nameMatcher = scope.getValidator().getCatalogReader().nameMatcher();
        final SqlValidatorScope.ResolvedImpl resolved = new SqlValidatorScope.ResolvedImpl();
        scope.resolve(ImmutableList.of(originalRelName), nameMatcher, false, resolved);
        replacedert resolved.count() == 1;
        final SqlValidatorScope.Resolve resolve = resolved.only();
        final RelDataType rowType = resolve.rowType();
        final int childNamespaceIndex = resolve.path.steps().get(0).i;
        int namespaceOffset = 0;
        if (childNamespaceIndex > 0) {
            // If not the first child, need to figure out the width of
            // output types from all the preceding namespaces
            final SqlValidatorScope ancestorScope = resolve.scope;
            replacedert ancestorScope instanceof ListScope;
            List<SqlValidatorNamespace> children = ((ListScope) ancestorScope).getChildren();
            for (int j = 0; j < childNamespaceIndex; j++) {
                namespaceOffset += children.get(j).getRowType().getFieldCount();
            }
        }
        RelDataTypeField field = nameMatcher.field(rowType, originalFieldName);
        int origPos = namespaceOffset + field.getIndex();
        groupreplacedyzer.groupExprProjection.put(origPos, ref);
    }
    return ImmutableBitSet.of(ref);
}

11 View Complete Implementation : SqlValidatorUtil.java
Copyright Apache License 2.0
Author : lealone
/**
 * Computes the cube of bit sets.
 *
 * <p>For example,  <code>rollup({0}, {1})</code>
 * returns <code>({0, 1}, {0}, {})</code>.
 *
 * <p>Bit sets are not necessarily singletons:
 * <code>rollup({0, 2}, {3, 5})</code>
 * returns <code>({0, 2, 3, 5}, {0, 2}, {})</code>.
 */
@VisibleForTesting
public static ImmutableList<ImmutableBitSet> cube(List<ImmutableBitSet> bitSets) {
    // Given the bit sets [{1}, {2, 3}, {5}],
    // form the lists [[{1}, {}], [{2, 3}, {}], [{5}, {}]].
    final Set<List<ImmutableBitSet>> builder = new LinkedHashSet<>();
    for (ImmutableBitSet bitSet : bitSets) {
        builder.add(Arrays.asList(bitSet, ImmutableBitSet.of()));
    }
    Set<ImmutableBitSet> flattenedBitSets = new LinkedHashSet<>();
    for (List<ImmutableBitSet> o : EnumeratorUtils.product(builder)) {
        flattenedBitSets.add(ImmutableBitSet.union(o));
    }
    return ImmutableList.copyOf(flattenedBitSets);
}

9 View Complete Implementation : AggregateExpandDistinctAggregatesRule.java
Copyright Apache License 2.0
Author : apache
/**
 * Converts an aggregate with one distinct aggregate and one or more
 * non-distinct aggregates to multi-phase aggregates (see reference example
 * below).
 *
 * @param relBuilder Contains the input relational expression
 * @param aggregate  Original aggregate
 * @param argLists   Arguments and filters to the distinct aggregate function
 */
private RelBuilder convertSingletonDistinct(RelBuilder relBuilder, Aggregate aggregate, Set<Pair<List<Integer>, Integer>> argLists) {
    // In this case, we are replaceduming that there is a single distinct function.
    // So make sure that argLists is of size one.
    Preconditions.checkArgument(argLists.size() == 1);
    // For example,
    // SELECT deptno, COUNT(*), SUM(bonus), MIN(DISTINCT sal)
    // FROM emp
    // GROUP BY deptno
    // 
    // becomes
    // 
    // SELECT deptno, SUM(cnt), SUM(bonus), MIN(sal)
    // FROM (
    // SELECT deptno, COUNT(*) as cnt, SUM(bonus), sal
    // FROM EMP
    // GROUP BY deptno, sal)            // Aggregate B
    // GROUP BY deptno                        // Aggregate A
    relBuilder.push(aggregate.getInput());
    final List<AggregateCall> originalAggCalls = aggregate.getAggCallList();
    final ImmutableBitSet originalGroupSet = aggregate.getGroupSet();
    // Add the distinct aggregate column(s) to the group-by columns,
    // if not already a part of the group-by
    final SortedSet<Integer> bottomGroups = new TreeSet<>(aggregate.getGroupSet().asList());
    for (AggregateCall aggCall : originalAggCalls) {
        if (aggCall.isDistinct()) {
            bottomGroups.addAll(aggCall.getArgList());
            // since we only have single distinct call
            break;
        }
    }
    final ImmutableBitSet bottomGroupSet = ImmutableBitSet.of(bottomGroups);
    // Generate the intermediate aggregate B, the one on the bottom that converts
    // a distinct call to group by call.
    // Bottom aggregate is the same as the original aggregate, except that
    // the bottom aggregate has converted the DISTINCT aggregate to a group by clause.
    final List<AggregateCall> bottomAggregateCalls = new ArrayList<>();
    for (AggregateCall aggCall : originalAggCalls) {
        // Project the column corresponding to the distinct aggregate. Project
        // as-is all the non-distinct aggregates
        if (!aggCall.isDistinct()) {
            final AggregateCall newCall = AggregateCall.create(aggCall.getAggregation(), false, aggCall.isApproximate(), aggCall.ignoreNulls(), aggCall.getArgList(), -1, aggCall.collation, bottomGroupSet.cardinality(), relBuilder.peek(), null, aggCall.name);
            bottomAggregateCalls.add(newCall);
        }
    }
    // Generate the aggregate B (see the reference example above)
    relBuilder.push(aggregate.copy(aggregate.getTraitSet(), relBuilder.build(), bottomGroupSet, null, bottomAggregateCalls));
    // Add aggregate A (see the reference example above), the top aggregate
    // to handle the rest of the aggregation that the bottom aggregate hasn't handled
    final List<AggregateCall> topAggregateCalls = new ArrayList<>();
    // Use the remapped arguments for the (non)distinct aggregate calls
    int nonDistinctAggCallProcessedSoFar = 0;
    for (AggregateCall aggCall : originalAggCalls) {
        final AggregateCall newCall;
        if (aggCall.isDistinct()) {
            List<Integer> newArgList = new ArrayList<>();
            for (int arg : aggCall.getArgList()) {
                newArgList.add(bottomGroups.headSet(arg).size());
            }
            newCall = AggregateCall.create(aggCall.getAggregation(), false, aggCall.isApproximate(), aggCall.ignoreNulls(), newArgList, -1, aggCall.collation, originalGroupSet.cardinality(), relBuilder.peek(), aggCall.getType(), aggCall.name);
        } else {
            // If aggregate B had a COUNT aggregate call the corresponding aggregate at
            // aggregate A must be SUM. For other aggregates, it remains the same.
            final int arg = bottomGroups.size() + nonDistinctAggCallProcessedSoFar;
            final List<Integer> newArgs = ImmutableList.of(arg);
            if (aggCall.getAggregation().getKind() == SqlKind.COUNT) {
                newCall = AggregateCall.create(new SqlSumEmptyIsZeroAggFunction(), false, aggCall.isApproximate(), aggCall.ignoreNulls(), newArgs, -1, aggCall.collation, originalGroupSet.cardinality(), relBuilder.peek(), aggCall.getType(), aggCall.getName());
            } else {
                newCall = AggregateCall.create(aggCall.getAggregation(), false, aggCall.isApproximate(), aggCall.ignoreNulls(), newArgs, -1, aggCall.collation, originalGroupSet.cardinality(), relBuilder.peek(), aggCall.getType(), aggCall.name);
            }
            nonDistinctAggCallProcessedSoFar++;
        }
        topAggregateCalls.add(newCall);
    }
    // Populate the group-by keys with the remapped arguments for aggregate A
    // The top groupset is basically an idenreplacedy (first X fields of aggregate B's
    // output), minus the distinct aggCall's input.
    final Set<Integer> topGroupSet = new HashSet<>();
    int groupSetToAdd = 0;
    for (int bottomGroup : bottomGroups) {
        if (originalGroupSet.get(bottomGroup)) {
            topGroupSet.add(groupSetToAdd);
        }
        groupSetToAdd++;
    }
    relBuilder.push(aggregate.copy(aggregate.getTraitSet(), relBuilder.build(), ImmutableBitSet.of(topGroupSet), null, topAggregateCalls));
    return relBuilder;
}

9 View Complete Implementation : ProjectCorrelateTransposeRule.java
Copyright Apache License 2.0
Author : apache
// ~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
    Project origProj = call.rel(0);
    final Correlate corr = call.rel(1);
    // locate all fields referenced in the projection
    // determine which inputs are referenced in the projection;
    // if all fields are being referenced and there are no
    // special expressions, no point in proceeding any further
    PushProjector pushProject = new PushProjector(origProj, call.builder().literal(true), corr, preserveExprCondition, call.builder());
    if (pushProject.locateAllRefs()) {
        return;
    }
    // create left and right projections, projecting only those
    // fields referenced on each side
    RelNode leftProjRel = pushProject.createProjectRefsAndExprs(corr.getLeft(), true, false);
    RelNode rightProjRel = pushProject.createProjectRefsAndExprs(corr.getRight(), true, true);
    Map<Integer, Integer> requiredColsMap = new HashMap<>();
    // adjust requiredColumns that reference the projected columns
    int[] adjustments = pushProject.getAdjustments();
    BitSet updatedBits = new BitSet();
    for (Integer col : corr.getRequiredColumns()) {
        int newCol = col + adjustments[col];
        updatedBits.set(newCol);
        requiredColsMap.put(col, newCol);
    }
    RexBuilder rexBuilder = call.builder().getRexBuilder();
    CorrelationId correlationId = corr.getCluster().createCorrel();
    RexCorrelVariable rexCorrel = (RexCorrelVariable) rexBuilder.makeCorrel(leftProjRel.getRowType(), correlationId);
    // updates RexCorrelVariable and sets actual RelDataType for RexFieldAccess
    rightProjRel = rightProjRel.accept(new RelNodesExprsHandler(new RexFieldAccessReplacer(corr.getCorrelationId(), rexCorrel, rexBuilder, requiredColsMap)));
    // create a new correlate with the projected children
    Correlate newCorrRel = corr.copy(corr.getTraitSet(), leftProjRel, rightProjRel, correlationId, ImmutableBitSet.of(BitSets.toIter(updatedBits)), corr.getJoinType());
    // put the original project on top of the correlate, converting it to
    // reference the modified projection list
    RelNode topProject = pushProject.createNewProject(newCorrRel, adjustments);
    call.transformTo(topProject);
}

9 View Complete Implementation : RuntimeFilterVisitor.java
Copyright Apache License 2.0
Author : apache
/**
 * Generate a possible RuntimeFilter of a HashJoinPrel, left some BF parameters of the generated RuntimeFilter
 * to be set later.
 *
 * @param hashJoinPrel
 * @return null or a partial information RuntimeFilterDef
 */
private RuntimeFilterDef generateRuntimeFilter(HashJoinPrel hashJoinPrel) {
    JoinRelType joinRelType = hashJoinPrel.getJoinType();
    JoinInfo joinInfo = hashJoinPrel.replacedyzeCondition();
    boolean allowJoin = (joinInfo.isEqui()) && (joinRelType == JoinRelType.INNER || joinRelType == JoinRelType.RIGHT);
    if (!allowJoin) {
        return null;
    }
    // TODO check whether to enable RuntimeFilter according to the NDV percent
    /**
     *     double threshold = 0.5;
     *     double percent = leftNDV / rightDNV;
     *     if (percent > threshold ) {
     *     return null;
     *     }
     */
    List<BloomFilterDef> bloomFilterDefs = new ArrayList<>();
    // find the possible left scan node of the left join key
    ScanPrel probeSideScanPrel = null;
    RelNode left = hashJoinPrel.getLeft();
    RelNode right = hashJoinPrel.getRight();
    ExchangePrel exchangePrel = findRightExchangePrel(right);
    if (exchangePrel == null) {
        // Does not support the single fragment mode ,that is the right build side
        // can only be BroadcastExchangePrel or HashToRandomExchangePrel
        return null;
    }
    List<String> leftFields = left.getRowType().getFieldNames();
    List<String> rightFields = right.getRowType().getFieldNames();
    List<Integer> leftKeys = hashJoinPrel.getLeftKeys();
    List<Integer> rightKeys = hashJoinPrel.getRightKeys();
    RelMetadataQuery metadataQuery = left.getCluster().getMetadataQuery();
    int i = 0;
    for (Integer leftKey : leftKeys) {
        String leftFieldName = leftFields.get(leftKey);
        Integer rightKey = rightKeys.get(i++);
        String rightFieldName = rightFields.get(rightKey);
        // This also avoids the left field of the join condition with a function call.
        ScanPrel scanPrel = findLeftScanPrel(leftFieldName, left);
        if (scanPrel != null) {
            boolean encounteredBlockNode = containBlockNode((Prel) left, scanPrel);
            if (encounteredBlockNode) {
                continue;
            }
            // Collect NDV from the Metadata
            RelDataType scanRowType = scanPrel.getRowType();
            RelDataTypeField field = scanRowType.getField(leftFieldName, true, true);
            int index = field.getIndex();
            Double ndv = metadataQuery.getDistinctRowCount(scanPrel, ImmutableBitSet.of(index), null);
            if (ndv == null) {
                // If NDV is not supplied, we use the row count to estimate the ndv.
                ndv = left.estimateRowCount(metadataQuery) * 0.1;
            }
            int bloomFilterSizeInBytes = BloomFilter.optimalNumOfBytes(ndv.longValue(), fpp);
            bloomFilterSizeInBytes = bloomFilterSizeInBytes > bloomFilterMaxSizeInBytesDef ? bloomFilterMaxSizeInBytesDef : bloomFilterSizeInBytes;
            // left the local parameter to be set later.
            BloomFilterDef bloomFilterDef = new BloomFilterDef(bloomFilterSizeInBytes, false, leftFieldName, rightFieldName);
            bloomFilterDef.setLeftNDV(ndv);
            bloomFilterDefs.add(bloomFilterDef);
            toAddRuntimeFilter.add(scanPrel);
            probeSideScanPrel = scanPrel;
        }
    }
    if (bloomFilterDefs.size() > 0) {
        // left sendToForeman parameter to be set later.
        RuntimeFilterDef runtimeFilterDef = new RuntimeFilterDef(true, false, bloomFilterDefs, false, -1);
        probeSideScan2hj.put(probeSideScanPrel, hashJoinPrel);
        return runtimeFilterDef;
    }
    return null;
}