use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode in project calcite by apache.
the class RexToLixTranslator method translateConstructor.
public Expression translateConstructor(List<RexNode> operandList, SqlKind kind) {
switch(kind) {
case MAP_VALUE_CONSTRUCTOR:
Expression map = list.append("map", Expressions.new_(LinkedHashMap.class), false);
for (int i = 0; i < operandList.size(); i++) {
RexNode key = operandList.get(i++);
RexNode value = operandList.get(i);
list.add(Expressions.statement(Expressions.call(map, BuiltInMethod.MAP_PUT.method, Expressions.box(translate(key)), Expressions.box(translate(value)))));
}
return map;
case ARRAY_VALUE_CONSTRUCTOR:
Expression lyst = list.append("list", Expressions.new_(ArrayList.class), false);
for (RexNode value : operandList) {
list.add(Expressions.statement(Expressions.call(lyst, BuiltInMethod.COLLECTION_ADD.method, Expressions.box(translate(value)))));
}
return lyst;
default:
throw new AssertionError("unexpected: " + kind);
}
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode in project calcite by apache.
the class EnumerableWindow method translateBound.
private Expression translateBound(RexToLixTranslator translator, ParameterExpression i_, Expression row_, Expression min_, Expression max_, Expression rows_, Group group, boolean lower, PhysType physType, Expression rowComparator, Expression keySelector, Expression keyComparator) {
RexWindowBound bound = lower ? group.lowerBound : group.upperBound;
if (bound.isUnbounded()) {
return bound.isPreceding() ? min_ : max_;
}
if (group.isRows) {
if (bound.isCurrentRow()) {
return i_;
}
RexNode node = bound.getOffset();
Expression offs = translator.translate(node);
// Floating offset does not make sense since we refer to array index.
// Nulls do not make sense as well.
offs = RexToLixTranslator.convert(offs, int.class);
Expression b = i_;
if (bound.isFollowing()) {
b = Expressions.add(b, offs);
} else {
b = Expressions.subtract(b, offs);
}
return b;
}
Expression searchLower = min_;
Expression searchUpper = max_;
if (bound.isCurrentRow()) {
if (lower) {
searchUpper = i_;
} else {
searchLower = i_;
}
}
List<RelFieldCollation> fieldCollations = group.collation().getFieldCollations();
if (bound.isCurrentRow() && fieldCollations.size() != 1) {
return Expressions.call((lower ? BuiltInMethod.BINARY_SEARCH5_LOWER : BuiltInMethod.BINARY_SEARCH5_UPPER).method, rows_, row_, searchLower, searchUpper, keySelector, keyComparator);
}
assert fieldCollations.size() == 1 : "When using range window specification, ORDER BY should have" + " exactly one expression." + " Actual collation is " + group.collation();
// isRange
int orderKey = fieldCollations.get(0).getFieldIndex();
RelDataType keyType = physType.getRowType().getFieldList().get(orderKey).getType();
Type desiredKeyType = translator.typeFactory.getJavaClass(keyType);
if (bound.getOffset() == null) {
desiredKeyType = Primitive.box(desiredKeyType);
}
Expression val = translator.translate(new RexInputRef(orderKey, keyType), desiredKeyType);
if (!bound.isCurrentRow()) {
RexNode node = bound.getOffset();
Expression offs = translator.translate(node);
// TODO: support date + interval somehow
if (bound.isFollowing()) {
val = Expressions.add(val, offs);
} else {
val = Expressions.subtract(val, offs);
}
}
return Expressions.call((lower ? BuiltInMethod.BINARY_SEARCH6_LOWER : BuiltInMethod.BINARY_SEARCH6_UPPER).method, rows_, val, searchLower, searchUpper, keySelector, keyComparator);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode in project calcite by apache.
the class AbstractMaterializedViewRule method computeCompensationPredicates.
/**
* We check whether the predicates in the source are contained in the predicates
* in the target. The method treats separately the equi-column predicates, the
* range predicates, and the rest of predicates.
*
* <p>If the containment is confirmed, we produce compensation predicates that
* need to be added to the target to produce the results in the source. Thus,
* if source and target expressions are equivalent, those predicates will be the
* true constant.
*
* <p>In turn, if containment cannot be confirmed, the method returns null.
*/
private static Triple<RexNode, RexNode, RexNode> computeCompensationPredicates(RexBuilder rexBuilder, RexSimplify simplify, EquivalenceClasses sourceEC, Triple<RexNode, RexNode, RexNode> sourcePreds, EquivalenceClasses targetEC, Triple<RexNode, RexNode, RexNode> targetPreds, BiMap<RelTableRef, RelTableRef> sourceToTargetTableMapping) {
final RexNode compensationColumnsEquiPred;
final RexNode compensationRangePred;
final RexNode compensationResidualPred;
// 1. Establish relationship between source and target equivalence classes.
// If every target equivalence class is not a subset of a source
// equivalence class, we bail out.
compensationColumnsEquiPred = generateEquivalenceClasses(rexBuilder, sourceEC, targetEC);
if (compensationColumnsEquiPred == null) {
// Cannot rewrite
return null;
}
// 2. We check that range intervals for the source are contained in the target.
// Compute compensating predicates.
final RexNode queryRangePred = RexUtil.swapColumnReferences(rexBuilder, sourcePreds.getMiddle(), sourceEC.getEquivalenceClassesMap());
final RexNode viewRangePred = RexUtil.swapTableColumnReferences(rexBuilder, targetPreds.getMiddle(), sourceToTargetTableMapping.inverse(), sourceEC.getEquivalenceClassesMap());
compensationRangePred = SubstitutionVisitor.splitFilter(simplify, queryRangePred, viewRangePred);
if (compensationRangePred == null) {
// Cannot rewrite
return null;
}
// 3. Finally, we check that residual predicates of the source are satisfied
// within the target.
// Compute compensating predicates.
final RexNode queryResidualPred = RexUtil.swapColumnReferences(rexBuilder, sourcePreds.getRight(), sourceEC.getEquivalenceClassesMap());
final RexNode viewResidualPred = RexUtil.swapTableColumnReferences(rexBuilder, targetPreds.getRight(), sourceToTargetTableMapping.inverse(), sourceEC.getEquivalenceClassesMap());
compensationResidualPred = SubstitutionVisitor.splitFilter(simplify, queryResidualPred, viewResidualPred);
if (compensationResidualPred == null) {
// Cannot rewrite
return null;
}
return ImmutableTriple.<RexNode, RexNode, RexNode>of(compensationColumnsEquiPred, compensationRangePred, compensationResidualPred);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode in project calcite by apache.
the class AbstractMaterializedViewRule method generateEquivalenceClasses.
/**
* Given the equi-column predicates of the source and the target and the
* computed equivalence classes, it extracts possible mappings between
* the equivalence classes.
*
* <p>If there is no mapping, it returns null. If there is a exact match,
* it will return a compensation predicate that evaluates to true.
* Finally, if a compensation predicate needs to be enforced on top of
* the target to make the equivalences classes match, it returns that
* compensation predicate.
*/
private static RexNode generateEquivalenceClasses(RexBuilder rexBuilder, EquivalenceClasses sourceEC, EquivalenceClasses targetEC) {
if (sourceEC.getEquivalenceClasses().isEmpty() && targetEC.getEquivalenceClasses().isEmpty()) {
// Empty mapping and compensation predicate
return rexBuilder.makeLiteral(true);
}
if (sourceEC.getEquivalenceClasses().isEmpty() && !targetEC.getEquivalenceClasses().isEmpty()) {
// No column equality predicates in source, but column equality predicates in target
return null;
}
final List<Set<RexTableInputRef>> sourceEquivalenceClasses = sourceEC.getEquivalenceClasses();
final List<Set<RexTableInputRef>> targetEquivalenceClasses = targetEC.getEquivalenceClasses();
final Multimap<Integer, Integer> mapping = extractPossibleMapping(sourceEquivalenceClasses, targetEquivalenceClasses);
if (mapping == null) {
// bail out
return null;
}
// Create the compensation predicate
RexNode compensationPredicate = rexBuilder.makeLiteral(true);
for (int i = 0; i < sourceEquivalenceClasses.size(); i++) {
if (!mapping.containsKey(i)) {
// Add all predicates
Iterator<RexTableInputRef> it = sourceEquivalenceClasses.get(i).iterator();
RexTableInputRef e0 = it.next();
while (it.hasNext()) {
RexNode equals = rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, e0, it.next());
compensationPredicate = rexBuilder.makeCall(SqlStdOperatorTable.AND, compensationPredicate, equals);
}
} else {
// Add only predicates that are not there
for (int j : mapping.get(i)) {
Set<RexTableInputRef> difference = new HashSet<>(sourceEquivalenceClasses.get(i));
difference.removeAll(targetEquivalenceClasses.get(j));
for (RexTableInputRef e : difference) {
RexNode equals = rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, e, targetEquivalenceClasses.get(j).iterator().next());
compensationPredicate = rexBuilder.makeCall(SqlStdOperatorTable.AND, compensationPredicate, equals);
}
}
}
}
return compensationPredicate;
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode in project calcite by apache.
the class AbstractMaterializedViewRule method generateSwapTableColumnReferencesLineage.
/**
* It swaps the table references and then the column references of the input
* expressions using the table mapping and the equivalence classes.
*/
private static NodeLineage generateSwapTableColumnReferencesLineage(RexBuilder rexBuilder, RelMetadataQuery mq, RelNode node, BiMap<RelTableRef, RelTableRef> tableMapping, EquivalenceClasses ec, List<RexNode> nodeExprs) {
Map<String, Integer> exprsLineage = new HashMap<>();
Map<String, Integer> exprsLineageLosslessCasts = new HashMap<>();
for (int i = 0; i < nodeExprs.size(); i++) {
final Set<RexNode> s = mq.getExpressionLineage(node, nodeExprs.get(i));
if (s == null) {
// Next expression
continue;
}
// a single expression
assert s.size() == 1;
// Rewrite expr. First we swap the table references following the table
// mapping, then we take first element from the corresponding equivalence class
final RexNode e = RexUtil.swapTableColumnReferences(rexBuilder, s.iterator().next(), tableMapping, ec.getEquivalenceClassesMap());
exprsLineage.put(e.toString(), i);
if (RexUtil.isLosslessCast(e)) {
exprsLineageLosslessCasts.put(((RexCall) e).getOperands().get(0).toString(), i);
}
}
return NodeLineage.of(exprsLineage, exprsLineageLosslessCasts);
}
Aggregations