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();
}
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;
}
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 ⇒ 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;
}
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: >, <, ≤, ≥, =; ≠.
*
* <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>(<, ≤) X (<, ≤) <i>note: X represents cartesian product</i>
* <li>(> / ≥) X (>, ≥)
* <li>(=) X (>, ≥, <, ≤, =, ≠)
* <li>(≠, =)
* </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;
}
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);
}
}
}
Aggregations