Search in sources :

Example 91 with Pair

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.util.Pair in project calcite by apache.

the class RelOptUtil method pushDownJoinConditions.

/**
 * Pushes down expressions in "equal" join condition.
 *
 * <p>For example, given
 * "emp JOIN dept ON emp.deptno + 1 = dept.deptno", adds a project above
 * "emp" that computes the expression
 * "emp.deptno + 1". The resulting join condition is a simple combination
 * of AND, equals, and input fields, plus the remaining non-equal conditions.
 *
 * @param originalJoin Join whose condition is to be pushed down
 * @param relBuilder Factory to create project operator
 */
public static RelNode pushDownJoinConditions(Join originalJoin, RelBuilder relBuilder) {
    RexNode joinCond = originalJoin.getCondition();
    final JoinRelType joinType = originalJoin.getJoinType();
    final List<RexNode> extraLeftExprs = new ArrayList<>();
    final List<RexNode> extraRightExprs = new ArrayList<>();
    final int leftCount = originalJoin.getLeft().getRowType().getFieldCount();
    final int rightCount = originalJoin.getRight().getRowType().getFieldCount();
    // yet.
    if (!containsGet(joinCond) && RexUtil.SubQueryFinder.find(joinCond) == null) {
        joinCond = pushDownEqualJoinConditions(joinCond, leftCount, rightCount, extraLeftExprs, extraRightExprs);
    }
    relBuilder.push(originalJoin.getLeft());
    if (!extraLeftExprs.isEmpty()) {
        final List<RelDataTypeField> fields = relBuilder.peek().getRowType().getFieldList();
        final List<Pair<RexNode, String>> pairs = new AbstractList<Pair<RexNode, String>>() {

            public int size() {
                return leftCount + extraLeftExprs.size();
            }

            public Pair<RexNode, String> get(int index) {
                if (index < leftCount) {
                    RelDataTypeField field = fields.get(index);
                    return Pair.<RexNode, String>of(new RexInputRef(index, field.getType()), field.getName());
                } else {
                    return Pair.of(extraLeftExprs.get(index - leftCount), null);
                }
            }
        };
        relBuilder.project(Pair.left(pairs), Pair.right(pairs));
    }
    relBuilder.push(originalJoin.getRight());
    if (!extraRightExprs.isEmpty()) {
        final List<RelDataTypeField> fields = relBuilder.peek().getRowType().getFieldList();
        final int newLeftCount = leftCount + extraLeftExprs.size();
        final List<Pair<RexNode, String>> pairs = new AbstractList<Pair<RexNode, String>>() {

            public int size() {
                return rightCount + extraRightExprs.size();
            }

            public Pair<RexNode, String> get(int index) {
                if (index < rightCount) {
                    RelDataTypeField field = fields.get(index);
                    return Pair.<RexNode, String>of(new RexInputRef(index, field.getType()), field.getName());
                } else {
                    return Pair.of(RexUtil.shift(extraRightExprs.get(index - rightCount), -newLeftCount), null);
                }
            }
        };
        relBuilder.project(Pair.left(pairs), Pair.right(pairs));
    }
    final RelNode right = relBuilder.build();
    final RelNode left = relBuilder.build();
    relBuilder.push(originalJoin.copy(originalJoin.getTraitSet(), joinCond, left, right, joinType, originalJoin.isSemiJoinDone()));
    if (!extraLeftExprs.isEmpty() || !extraRightExprs.isEmpty()) {
        Mappings.TargetMapping mapping = Mappings.createShiftMapping(leftCount + extraLeftExprs.size() + rightCount + extraRightExprs.size(), 0, 0, leftCount, leftCount, leftCount + extraLeftExprs.size(), rightCount);
        relBuilder.project(relBuilder.fields(mapping.inverse()));
    }
    return relBuilder.build();
}
Also used : AbstractList(java.util.AbstractList) ArrayList(java.util.ArrayList) JoinRelType(org.apache.calcite.rel.core.JoinRelType) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) Mappings(org.apache.calcite.util.mapping.Mappings) RexInputRef(org.apache.calcite.rex.RexInputRef) RexNode(org.apache.calcite.rex.RexNode) Pair(org.apache.calcite.util.Pair)

Example 92 with Pair

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.util.Pair in project calcite by apache.

the class RelOptUtil method createProjectJoinRel.

// to be removed before 2.0
@Deprecated
public static RelNode createProjectJoinRel(List<Integer> outputProj, RelNode joinRel) {
    int newProjectOutputSize = outputProj.size();
    List<RelDataTypeField> joinOutputFields = joinRel.getRowType().getFieldList();
    // join, then no need to create a projection
    if ((newProjectOutputSize > 0) && (newProjectOutputSize < joinOutputFields.size())) {
        final List<Pair<RexNode, String>> newProjects = new ArrayList<>();
        final RelBuilder relBuilder = RelFactories.LOGICAL_BUILDER.create(joinRel.getCluster(), null);
        final RexBuilder rexBuilder = relBuilder.getRexBuilder();
        for (int fieldIndex : outputProj) {
            final RelDataTypeField field = joinOutputFields.get(fieldIndex);
            newProjects.add(Pair.<RexNode, String>of(rexBuilder.makeInputRef(field.getType(), fieldIndex), field.getName()));
        }
        // Create a project rel on the output of the join.
        return relBuilder.push(joinRel).project(Pair.left(newProjects), Pair.right(newProjects), true).build();
    }
    return joinRel;
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelBuilder(org.apache.calcite.tools.RelBuilder) ArrayList(java.util.ArrayList) RexBuilder(org.apache.calcite.rex.RexBuilder) Pair(org.apache.calcite.util.Pair)

Example 93 with Pair

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.util.Pair in project calcite by apache.

the class RexImplicationChecker method implies2.

/**
 * Returns whether the predicate {@code first} (not a conjunction)
 * implies {@code second}.
 */
private boolean implies2(RexNode first, RexNode second) {
    if (second.isAlwaysFalse()) {
        // f cannot imply s
        return false;
    }
    // E.g. "x is null" implies "x is null".
    if (RexUtil.eq(first, second)) {
        return true;
    }
    // Several things imply "IS NOT NULL"
    switch(second.getKind()) {
        case IS_NOT_NULL:
            // Suppose we know that first is strong in second; that is,
            // the if second is null, then first will be null.
            // Then, first being not null implies that second is not null.
            // 
            // For example, first is "x > y", second is "x".
            // If we know that "x > y" is not null, we know that "x" is not null.
            final RexNode operand = ((RexCall) second).getOperands().get(0);
            final Strong strong = new Strong() {

                @Override
                public boolean isNull(RexNode node) {
                    return RexUtil.eq(node, operand) || super.isNull(node);
                }
            };
            if (strong.isNull(first)) {
                return true;
            }
    }
    final InputUsageFinder firstUsageFinder = new InputUsageFinder();
    final InputUsageFinder secondUsageFinder = new InputUsageFinder();
    RexUtil.apply(firstUsageFinder, ImmutableList.<RexNode>of(), first);
    RexUtil.apply(secondUsageFinder, ImmutableList.<RexNode>of(), second);
    // Check Support
    if (!checkSupport(firstUsageFinder, secondUsageFinder)) {
        LOGGER.warn("Support for checking {} => {} is not there", first, second);
        return false;
    }
    ImmutableList.Builder<Set<Pair<RexInputRef, RexNode>>> usagesBuilder = ImmutableList.builder();
    for (Map.Entry<RexInputRef, InputRefUsage<SqlOperator, RexNode>> entry : firstUsageFinder.usageMap.entrySet()) {
        ImmutableSet.Builder<Pair<RexInputRef, RexNode>> usageBuilder = ImmutableSet.builder();
        if (entry.getValue().usageList.size() > 0) {
            for (final Pair<SqlOperator, RexNode> pair : entry.getValue().usageList) {
                usageBuilder.add(Pair.of(entry.getKey(), pair.getValue()));
            }
            usagesBuilder.add(usageBuilder.build());
        }
    }
    final Set<List<Pair<RexInputRef, RexNode>>> usages = Sets.cartesianProduct(usagesBuilder.build());
    for (List<Pair<RexInputRef, RexNode>> usageList : usages) {
        // Get the literals from first conjunction and executes second conjunction
        // using them.
        // 
        // E.g., for
        // x > 30 &rArr; x > 10,
        // we will replace x by 30 in second expression and execute it i.e.,
        // 30 > 10
        // 
        // If it's true then we infer implication.
        final DataContext dataValues = VisitorDataContext.of(rowType, usageList);
        if (!isSatisfiable(second, dataValues)) {
            return false;
        }
    }
    return true;
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) ImmutableList(com.google.common.collect.ImmutableList) SqlOperator(org.apache.calcite.sql.SqlOperator) DataContext(org.apache.calcite.DataContext) ImmutableSet(com.google.common.collect.ImmutableSet) RexInputRef(org.apache.calcite.rex.RexInputRef) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) RexNode(org.apache.calcite.rex.RexNode) Pair(org.apache.calcite.util.Pair)

Example 94 with Pair

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.util.Pair in project calcite by apache.

the class RexImplicationChecker method checkSupport.

/**
 * Looks at the usage of variables in first and second conjunction to decide
 * whether this kind of expression is currently supported for proving first
 * implies second.
 *
 * <ol>
 * <li>Variables should be used only once in both the conjunction against
 * given set of operations only: &gt;, &lt;, &le;, &ge;, =; &ne;.
 *
 * <li>All the variables used in second condition should be used even in the
 * first.
 *
 * <li>If operator used for variable in first is op1 and op2 for second, then
 * we support these combination for conjunction (op1, op2) then op1, op2
 * belongs to one of the following sets:
 *
 * <ul>
 *    <li>(&lt;, &le;) X (&lt;, &le;) <i>note: X represents cartesian product</i>
 *    <li>(&gt; / &ge;) X (&gt;, &ge;)
 *    <li>(=) X (&gt;, &ge;, &lt;, &le;, =, &ne;)
 *    <li>(&ne;, =)
 * </ul>
 *
 * <li>We support at most 2 operators to be be used for a variable in first
 * and second usages.
 *
 * </ol>
 *
 * @return whether input usage pattern is supported
 */
private boolean checkSupport(InputUsageFinder firstUsageFinder, InputUsageFinder secondUsageFinder) {
    final Map<RexInputRef, InputRefUsage<SqlOperator, RexNode>> firstUsageMap = firstUsageFinder.usageMap;
    final Map<RexInputRef, InputRefUsage<SqlOperator, RexNode>> secondUsageMap = secondUsageFinder.usageMap;
    for (Map.Entry<RexInputRef, InputRefUsage<SqlOperator, RexNode>> entry : secondUsageMap.entrySet()) {
        final InputRefUsage<SqlOperator, RexNode> secondUsage = entry.getValue();
        final List<Pair<SqlOperator, RexNode>> secondUsageList = secondUsage.usageList;
        final int secondLen = secondUsageList.size();
        if (secondUsage.usageCount != secondLen || secondLen > 2) {
            return false;
        }
        final InputRefUsage<SqlOperator, RexNode> firstUsage = firstUsageMap.get(entry.getKey());
        if (firstUsage == null || firstUsage.usageList.size() != firstUsage.usageCount || firstUsage.usageCount > 2) {
            return false;
        }
        final List<Pair<SqlOperator, RexNode>> firstUsageList = firstUsage.usageList;
        final int firstLen = firstUsageList.size();
        final SqlKind fKind = firstUsageList.get(0).getKey().getKind();
        final SqlKind sKind = secondUsageList.get(0).getKey().getKind();
        final SqlKind fKind2 = (firstUsageList.size() == 2) ? firstUsageList.get(1).getKey().getKind() : null;
        final SqlKind sKind2 = (secondUsageList.size() == 2) ? secondUsageList.get(1).getKey().getKind() : null;
        if (firstLen == 2 && secondLen == 2 && !(isEquivalentOp(fKind, sKind) && isEquivalentOp(fKind2, sKind2)) && !(isEquivalentOp(fKind, sKind2) && isEquivalentOp(fKind2, sKind))) {
            return false;
        } else if (firstLen == 1 && secondLen == 1 && fKind != SqlKind.EQUALS && !isSupportedUnaryOperators(sKind) && !isEquivalentOp(fKind, sKind)) {
            return false;
        } else if (firstLen == 1 && secondLen == 2 && fKind != SqlKind.EQUALS) {
            return false;
        } else if (firstLen == 2 && secondLen == 1) {
            // x > 30 and x > 40 implies x < 70
            if (!isOppositeOp(fKind, fKind2) && !isSupportedUnaryOperators(sKind) && !(isEquivalentOp(fKind, fKind2) && isEquivalentOp(fKind, sKind))) {
                return false;
            }
        }
    }
    return true;
}
Also used : SqlOperator(org.apache.calcite.sql.SqlOperator) RexInputRef(org.apache.calcite.rex.RexInputRef) SqlKind(org.apache.calcite.sql.SqlKind) HashMap(java.util.HashMap) Map(java.util.Map) RexNode(org.apache.calcite.rex.RexNode) Pair(org.apache.calcite.util.Pair)

Example 95 with Pair

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.util.Pair in project calcite by apache.

the class JdbcTest method testCloneQueries.

/**
 * A selection of queries generated by Mondrian.
 */
@Ignore
@Test
public void testCloneQueries() {
    CalciteAssert.AssertThat with = CalciteAssert.that().with(CalciteAssert.Config.FOODMART_CLONE);
    for (Ord<Pair<String, String>> query : Ord.zip(FOODMART_QUERIES)) {
        try {
            // uncomment to run specific queries:
            // if (query.i != FOODMART_QUERIES.size() - 1) continue;
            final String sql = query.e.left;
            if (sql.startsWith("ignore:")) {
                continue;
            }
            final String expected = query.e.right;
            final CalciteAssert.AssertQuery query1 = with.query(sql);
            if (expected != null) {
                if (sql.contains("order by")) {
                    query1.returns(expected);
                } else {
                    query1.returnsUnordered(expected.split("\n"));
                }
            } else {
                query1.runs();
            }
        } catch (Throwable e) {
            throw new RuntimeException("while running query #" + query.i, e);
        }
    }
}
Also used : CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Pair(org.apache.calcite.util.Pair) Ignore(org.junit.Ignore) Test(org.junit.Test)

Aggregations

Pair (org.apache.calcite.util.Pair)112 RexNode (org.apache.calcite.rex.RexNode)72 ArrayList (java.util.ArrayList)70 RelNode (org.apache.calcite.rel.RelNode)59 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)55 RexInputRef (org.apache.calcite.rex.RexInputRef)29 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)29 HashMap (java.util.HashMap)26 RexBuilder (org.apache.calcite.rex.RexBuilder)23 Map (java.util.Map)21 AggregateCall (org.apache.calcite.rel.core.AggregateCall)20 List (java.util.List)19 RelDataType (org.apache.calcite.rel.type.RelDataType)19 ImmutableList (com.google.common.collect.ImmutableList)18 JoinRelType (org.apache.calcite.rel.core.JoinRelType)16 TreeMap (java.util.TreeMap)14 RelDataTypeFactory (org.apache.calcite.rel.type.RelDataTypeFactory)13 RelBuilder (org.apache.calcite.tools.RelBuilder)13 ImmutableMap (com.google.common.collect.ImmutableMap)12 ImmutableSortedMap (com.google.common.collect.ImmutableSortedMap)12