use of org.apache.calcite.rel.core.CorrelationId in project calcite by apache.
the class SubQueryRemoveRule method matchFilter.
private static void matchFilter(SubQueryRemoveRule rule, RelOptRuleCall call) {
final Filter filter = call.rel(0);
final RelBuilder builder = call.builder();
builder.push(filter.getInput());
int count = 0;
RexNode c = filter.getCondition();
while (true) {
final RexSubQuery e = RexUtil.SubQueryFinder.find(c);
if (e == null) {
assert count > 0;
break;
}
++count;
final RelOptUtil.Logic logic = LogicVisitor.find(RelOptUtil.Logic.TRUE, ImmutableList.of(c), e);
final Set<CorrelationId> variablesSet = RelOptUtil.getVariablesUsed(e.rel);
final RexNode target = rule.apply(e, variablesSet, logic, builder, 1, builder.peek().getRowType().getFieldCount());
final RexShuttle shuttle = new ReplaceSubQueryShuttle(e, target);
c = c.accept(shuttle);
}
builder.filter(c);
builder.project(fields(builder, filter.getRowType().getFieldCount()));
call.transformTo(builder.build());
}
use of org.apache.calcite.rel.core.CorrelationId in project calcite by apache.
the class RelFieldTrimmer method trimChild.
/**
* Trims the fields of an input relational expression.
*
* @param rel Relational expression
* @param input Input relational expression, whose fields to trim
* @param fieldsUsed Bitmap of fields needed by the consumer
* @return New relational expression and its field mapping
*/
protected TrimResult trimChild(RelNode rel, RelNode input, final ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields) {
final ImmutableBitSet.Builder fieldsUsedBuilder = fieldsUsed.rebuild();
// Fields that define the collation cannot be discarded.
final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
final ImmutableList<RelCollation> collations = mq.collations(input);
if (collations != null) {
for (RelCollation collation : collations) {
for (RelFieldCollation fieldCollation : collation.getFieldCollations()) {
fieldsUsedBuilder.set(fieldCollation.getFieldIndex());
}
}
}
// fields.
for (final CorrelationId correlation : rel.getVariablesSet()) {
rel.accept(new CorrelationReferenceFinder() {
@Override
protected RexNode handle(RexFieldAccess fieldAccess) {
final RexCorrelVariable v = (RexCorrelVariable) fieldAccess.getReferenceExpr();
if (v.id.equals(correlation)) {
fieldsUsedBuilder.set(fieldAccess.getField().getIndex());
}
return fieldAccess;
}
});
}
return dispatchTrimFields(input, fieldsUsedBuilder.build(), extraFields);
}
use of org.apache.calcite.rel.core.CorrelationId in project calcite by apache.
the class RelBuilder method join.
/**
* Creates a {@link Join} with correlating variables.
*/
public RelBuilder join(JoinRelType joinType, RexNode condition, Set<CorrelationId> variablesSet) {
Frame right = stack.pop();
final Frame left = stack.pop();
final RelNode join;
final boolean correlate = checkIfCorrelated(variablesSet, joinType, left.rel, right.rel);
RexNode postCondition = literal(true);
if (config.simplify()) {
// transform the expression to something unrecognizable
if (condition instanceof RexCall) {
condition = RelOptUtil.collapseExpandedIsNotDistinctFromExpr((RexCall) condition, getRexBuilder());
}
condition = simplifier.simplifyUnknownAsFalse(condition);
}
if (correlate) {
final CorrelationId id = Iterables.getOnlyElement(variablesSet);
// Correlate does not have an ON clause.
switch(joinType) {
case LEFT:
case SEMI:
case ANTI:
// For a LEFT/SEMI/ANTI, predicate must be evaluated first.
stack.push(right);
filter(condition.accept(new Shifter(left.rel, id, right.rel)));
right = stack.pop();
break;
case INNER:
// For INNER, we can defer.
postCondition = condition;
break;
default:
throw new IllegalArgumentException("Correlated " + joinType + " join is not supported");
}
final ImmutableBitSet requiredColumns = RelOptUtil.correlationColumns(id, right.rel);
join = struct.correlateFactory.createCorrelate(left.rel, right.rel, ImmutableList.of(), id, requiredColumns, joinType);
} else {
RelNode join0 = struct.joinFactory.createJoin(left.rel, right.rel, ImmutableList.of(), condition, variablesSet, joinType, false);
if (join0 instanceof Join && config.pushJoinCondition()) {
join = RelOptUtil.pushDownJoinConditions((Join) join0, this);
} else {
join = join0;
}
}
final ImmutableList.Builder<Field> fields = ImmutableList.builder();
fields.addAll(left.fields);
fields.addAll(right.fields);
stack.push(new Frame(join, fields.build()));
filter(postCondition);
return this;
}
use of org.apache.calcite.rel.core.CorrelationId in project ignite by apache.
the class RelJson method toRex.
/**
*/
RexNode toRex(RelInput relInput, Object o) {
RelOptCluster cluster = relInput.getCluster();
RexBuilder rexBuilder = cluster.getRexBuilder();
if (o == null)
return null;
else if (o instanceof Map) {
Map map = (Map) o;
Map<String, Object> opMap = (Map) map.get("op");
IgniteTypeFactory typeFactory = Commons.typeFactory(cluster);
if (opMap != null) {
if (map.containsKey("class"))
opMap.put("class", map.get("class"));
List operands = (List) map.get("operands");
List<RexNode> rexOperands = toRexList(relInput, operands);
Object jsonType = map.get("type");
Map window = (Map) map.get("window");
if (window != null) {
SqlAggFunction operator = (SqlAggFunction) toOp(opMap);
RelDataType type = toType(typeFactory, jsonType);
List<RexNode> partitionKeys = new ArrayList<>();
if (window.containsKey("partition"))
partitionKeys = toRexList(relInput, (List) window.get("partition"));
List<RexFieldCollation> orderKeys = new ArrayList<>();
if (window.containsKey("order"))
orderKeys = toRexFieldCollationList(relInput, (List) window.get("order"));
RexWindowBound lowerBound;
RexWindowBound upperBound;
boolean physical;
if (window.get("rows-lower") != null) {
lowerBound = toRexWindowBound(relInput, (Map) window.get("rows-lower"));
upperBound = toRexWindowBound(relInput, (Map) window.get("rows-upper"));
physical = true;
} else if (window.get("range-lower") != null) {
lowerBound = toRexWindowBound(relInput, (Map) window.get("range-lower"));
upperBound = toRexWindowBound(relInput, (Map) window.get("range-upper"));
physical = false;
} else {
// No ROWS or RANGE clause
lowerBound = null;
upperBound = null;
physical = false;
}
boolean distinct = (Boolean) map.get("distinct");
return rexBuilder.makeOver(type, operator, rexOperands, partitionKeys, ImmutableList.copyOf(orderKeys), lowerBound, upperBound, physical, true, false, distinct, false);
} else {
SqlOperator operator = toOp(opMap);
RelDataType type;
if (jsonType != null)
type = toType(typeFactory, jsonType);
else
type = rexBuilder.deriveReturnType(operator, rexOperands);
return rexBuilder.makeCall(type, operator, rexOperands);
}
}
Integer input = (Integer) map.get("input");
if (input != null) {
// Check if it is a local ref.
if (map.containsKey("type")) {
RelDataType type = toType(typeFactory, map.get("type"));
return map.get("dynamic") == Boolean.TRUE ? rexBuilder.makeDynamicParam(type, input) : rexBuilder.makeLocalRef(type, input);
}
List<RelNode> inputNodes = relInput.getInputs();
int i = input;
for (RelNode inputNode : inputNodes) {
RelDataType rowType = inputNode.getRowType();
if (i < rowType.getFieldCount()) {
RelDataTypeField field = rowType.getFieldList().get(i);
return rexBuilder.makeInputRef(field.getType(), input);
}
i -= rowType.getFieldCount();
}
throw new RuntimeException("input field " + input + " is out of range");
}
String field = (String) map.get("field");
if (field != null) {
Object jsonExpr = map.get("expr");
RexNode expr = toRex(relInput, jsonExpr);
return rexBuilder.makeFieldAccess(expr, field, true);
}
String correl = (String) map.get("correl");
if (correl != null) {
RelDataType type = toType(typeFactory, map.get("type"));
return rexBuilder.makeCorrel(type, new CorrelationId(correl));
}
if (map.containsKey("literal")) {
Object literal = map.get("literal");
RelDataType type = toType(typeFactory, map.get("type"));
if (literal == null)
return rexBuilder.makeNullLiteral(type);
if (type.getSqlTypeName() == SqlTypeName.SYMBOL)
literal = toEnum(literal);
else if (type.getSqlTypeName().getFamily() == SqlTypeFamily.BINARY)
literal = toByteString(literal);
return rexBuilder.makeLiteral(literal, type, false);
}
throw new UnsupportedOperationException("cannot convert to rex " + o);
} else if (o instanceof Boolean)
return rexBuilder.makeLiteral((Boolean) o);
else if (o instanceof String)
return rexBuilder.makeLiteral((String) o);
else if (o instanceof Number) {
Number number = (Number) o;
if (number instanceof Double || number instanceof Float)
return rexBuilder.makeApproxLiteral(BigDecimal.valueOf(number.doubleValue()));
else
return rexBuilder.makeExactLiteral(BigDecimal.valueOf(number.longValue()));
} else
throw new UnsupportedOperationException("cannot convert to rex " + o);
}
use of org.apache.calcite.rel.core.CorrelationId in project ignite by apache.
the class IgniteMdCumulativeCost method getCumulativeCost.
/**
*/
public RelOptCost getCumulativeCost(IgniteCorrelatedNestedLoopJoin rel, RelMetadataQuery mq) {
RelOptCost cost = nonCumulativeCost(rel, mq);
if (cost.isInfinite())
return cost;
RelNode left = rel.getLeft();
RelNode right = rel.getRight();
Set<CorrelationId> corIds = rel.getVariablesSet();
RelOptCost leftCost = mq.getCumulativeCost(left);
if (leftCost.isInfinite())
return leftCost;
RelOptCost rightCost = mq.getCumulativeCost(right);
if (rightCost.isInfinite())
return rightCost;
return cost.plus(leftCost).plus(rightCost.multiplyBy(left.estimateRowCount(mq) / corIds.size()));
}
Aggregations