use of org.apache.calcite.rel.core.CorrelationId in project calcite by apache.
the class ProjectCorrelateTransposeRule method onMatch.
// ~ Methods ----------------------------------------------------------------
@Override
public void onMatch(RelOptRuleCall call) {
final Project origProject = call.rel(0);
final Correlate correlate = 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
final PushProjector pushProjector = new PushProjector(origProject, call.builder().literal(true), correlate, config.preserveExprCondition(), call.builder());
if (pushProjector.locateAllRefs()) {
return;
}
// create left and right projections, projecting only those
// fields referenced on each side
final RelNode leftProject = pushProjector.createProjectRefsAndExprs(correlate.getLeft(), true, false);
RelNode rightProject = pushProjector.createProjectRefsAndExprs(correlate.getRight(), true, true);
final Map<Integer, Integer> requiredColsMap = new HashMap<>();
// adjust requiredColumns that reference the projected columns
int[] adjustments = pushProjector.getAdjustments();
BitSet updatedBits = new BitSet();
for (Integer col : correlate.getRequiredColumns()) {
int newCol = col + adjustments[col];
updatedBits.set(newCol);
requiredColsMap.put(col, newCol);
}
final RexBuilder rexBuilder = call.builder().getRexBuilder();
CorrelationId correlationId = correlate.getCluster().createCorrel();
RexCorrelVariable rexCorrel = (RexCorrelVariable) rexBuilder.makeCorrel(leftProject.getRowType(), correlationId);
// updates RexCorrelVariable and sets actual RelDataType for RexFieldAccess
rightProject = rightProject.accept(new RelNodesExprsHandler(new RexFieldAccessReplacer(correlate.getCorrelationId(), rexCorrel, rexBuilder, requiredColsMap)));
// create a new correlate with the projected children
final Correlate newCorrelate = correlate.copy(correlate.getTraitSet(), leftProject, rightProject, correlationId, ImmutableBitSet.of(BitSets.toIter(updatedBits)), correlate.getJoinType());
// put the original project on top of the correlate, converting it to
// reference the modified projection list
final RelNode topProject = pushProjector.createNewProject(newCorrelate, adjustments);
call.transformTo(topProject);
}
use of org.apache.calcite.rel.core.CorrelationId in project calcite by apache.
the class RelOptRulesTest method checkProjectCorrelateTransposeRuleSemiOrAntiCorrelate.
private void checkProjectCorrelateTransposeRuleSemiOrAntiCorrelate(JoinRelType type) {
final Function<RelBuilder, RelNode> relFn = b -> {
RelNode left = b.values(new String[] { "f", "f2" }, "1", "2").build();
CorrelationId correlationId = new CorrelationId(0);
RexNode rexCorrel = b.getRexBuilder().makeCorrel(left.getRowType(), correlationId);
RelNode right = b.values(new String[] { "f3", "f4" }, "1", "2").project(b.field(0), b.getRexBuilder().makeFieldAccess(rexCorrel, 0)).build();
LogicalCorrelate correlate = new LogicalCorrelate(left.getCluster(), left.getTraitSet(), ImmutableList.of(), left, right, correlationId, ImmutableBitSet.of(0), type);
b.push(correlate);
return b.project(b.field(0)).build();
};
relFn(relFn).withRule(CoreRules.PROJECT_CORRELATE_TRANSPOSE).check();
}
use of org.apache.calcite.rel.core.CorrelationId in project calcite by apache.
the class RelJson method toRex.
@SuppressWarnings({ "rawtypes", "unchecked" })
@PolyNull
RexNode toRex(RelInput relInput, @PolyNull Object o) {
final RelOptCluster cluster = relInput.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
if (o == null) {
return null;
} else if (o instanceof Map) {
final Map<String, @Nullable Object> map = (Map) o;
final RelDataTypeFactory typeFactory = cluster.getTypeFactory();
if (map.containsKey("op")) {
final Map<String, @Nullable Object> opMap = get(map, "op");
if (map.containsKey("class")) {
opMap.put("class", get(map, "class"));
}
final List operands = get(map, "operands");
final List<RexNode> rexOperands = toRexList(relInput, operands);
final Object jsonType = map.get("type");
final Map window = (Map) map.get("window");
if (window != null) {
final SqlAggFunction operator = requireNonNull(toAggregation(opMap), "operator");
final RelDataType type = toType(typeFactory, requireNonNull(jsonType, "jsonType"));
List<RexNode> partitionKeys = new ArrayList<>();
Object partition = window.get("partition");
if (partition != null) {
partitionKeys = toRexList(relInput, (List) partition);
}
List<RexFieldCollation> orderKeys = new ArrayList<>();
if (window.containsKey("order")) {
addRexFieldCollationList(orderKeys, relInput, (List) window.get("order"));
}
final RexWindowBound lowerBound;
final RexWindowBound upperBound;
final 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
// Note: lower and upper bounds are non-nullable, so this branch is not reachable
lowerBound = null;
upperBound = null;
physical = false;
}
final boolean distinct = get((Map<String, Object>) map, "distinct");
return rexBuilder.makeOver(type, operator, rexOperands, partitionKeys, ImmutableList.copyOf(orderKeys), requireNonNull(lowerBound, "lowerBound"), requireNonNull(upperBound, "upperBound"), physical, true, false, distinct, false);
} else {
final SqlOperator operator = requireNonNull(toOp(opMap), "operator");
final RelDataType type;
if (jsonType != null) {
type = toType(typeFactory, jsonType);
} else {
type = rexBuilder.deriveReturnType(operator, rexOperands);
}
return rexBuilder.makeCall(type, operator, rexOperands);
}
}
final Integer input = (Integer) map.get("input");
if (input != null) {
return inputTranslator.translateInput(this, input, map, relInput);
}
final String field = (String) map.get("field");
if (field != null) {
final Object jsonExpr = get(map, "expr");
final RexNode expr = toRex(relInput, jsonExpr);
return rexBuilder.makeFieldAccess(expr, field, true);
}
final String correl = (String) map.get("correl");
if (correl != null) {
final Object jsonType = get(map, "type");
RelDataType type = toType(typeFactory, jsonType);
return rexBuilder.makeCorrel(type, new CorrelationId(correl));
}
if (map.containsKey("literal")) {
Object literal = map.get("literal");
if (literal == null) {
final RelDataType type = toType(typeFactory, get(map, "type"));
return rexBuilder.makeNullLiteral(type);
}
if (!map.containsKey("type")) {
// we just interpret the literal
return toRex(relInput, literal);
}
final RelDataType type = toType(typeFactory, get(map, "type"));
if (type.getSqlTypeName() == SqlTypeName.SYMBOL) {
literal = RelEnumTypes.toEnum((String) literal);
}
return rexBuilder.makeLiteral(literal, type);
}
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) {
final 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 calcite by apache.
the class SubQueryRemoveRule method matchProject.
private static void matchProject(SubQueryRemoveRule rule, RelOptRuleCall call) {
final Project project = call.rel(0);
final RelBuilder builder = call.builder();
final RexSubQuery e = RexUtil.SubQueryFinder.find(project.getProjects());
assert e != null;
final RelOptUtil.Logic logic = LogicVisitor.find(RelOptUtil.Logic.TRUE_FALSE_UNKNOWN, project.getProjects(), e);
builder.push(project.getInput());
final int fieldCount = builder.peek().getRowType().getFieldCount();
final Set<CorrelationId> variablesSet = RelOptUtil.getVariablesUsed(e.rel);
final RexNode target = rule.apply(e, variablesSet, logic, builder, 1, fieldCount);
final RexShuttle shuttle = new ReplaceSubQueryShuttle(e, target);
builder.project(shuttle.apply(project.getProjects()), project.getRowType().getFieldNames());
call.transformTo(builder.build());
}
use of org.apache.calcite.rel.core.CorrelationId in project calcite by apache.
the class RexBuilderTest method testCopyCorrelVariable.
/**
* Tests {@link RexCopier#visitCorrelVariable(RexCorrelVariable)}.
*/
@Test
void testCopyCorrelVariable() {
final RelDataTypeFactory sourceTypeFactory = new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
RelDataType type = sourceTypeFactory.createSqlType(SqlTypeName.VARCHAR, 65536);
final RelDataTypeFactory targetTypeFactory = new MySqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
final RexBuilder builder = new RexBuilder(targetTypeFactory);
final RexCorrelVariable node = (RexCorrelVariable) builder.makeCorrel(type, new CorrelationId(0));
final RexNode copy = builder.copy(node);
assertTrue(copy instanceof RexCorrelVariable);
final RexCorrelVariable result = (RexCorrelVariable) copy;
assertThat(result.id, is(node.id));
assertThat(result.getType().getSqlTypeName(), is(SqlTypeName.VARCHAR));
assertThat(result.getType().getPrecision(), is(PRECISION));
}
Aggregations