use of org.apache.calcite.rex.RexFieldAccess in project flink by apache.
the class SubQueryDecorrelator method analyzeCorConditions.
private static void analyzeCorConditions(final Set<CorrelationId> variableSet, final RexNode condition, final RexBuilder rexBuilder, final int maxCnfNodeCount, final List<RexNode> corConditions, final List<RexNode> nonCorConditions, final List<RexNode> unsupportedCorConditions) {
// converts the expanded expression to conjunctive normal form,
// like "(a AND b) OR c" will be converted to "(a OR c) AND (b OR c)"
final RexNode cnf = FlinkRexUtil.toCnf(rexBuilder, maxCnfNodeCount, condition);
// converts the cnf condition to a list of AND conditions
final List<RexNode> conjunctions = RelOptUtil.conjunctions(cnf);
// `true` for RexNode is supported correlation condition,
// `false` for RexNode is unsupported correlation condition,
// `null` for RexNode is not a correlation condition.
final RexVisitorImpl<Boolean> visitor = new RexVisitorImpl<Boolean>(true) {
@Override
public Boolean visitFieldAccess(RexFieldAccess fieldAccess) {
final RexNode ref = fieldAccess.getReferenceExpr();
if (ref instanceof RexCorrelVariable) {
return visitCorrelVariable((RexCorrelVariable) ref);
} else {
return super.visitFieldAccess(fieldAccess);
}
}
@Override
public Boolean visitCorrelVariable(RexCorrelVariable correlVariable) {
return variableSet.contains(correlVariable.id);
}
@Override
public Boolean visitSubQuery(RexSubQuery subQuery) {
final List<Boolean> result = new ArrayList<>();
for (RexNode operand : subQuery.operands) {
result.add(operand.accept(this));
}
// in (select t3.d from t3)
if (result.contains(true) || result.contains(false)) {
return false;
} else {
return null;
}
}
@Override
public Boolean visitCall(RexCall call) {
final List<Boolean> result = new ArrayList<>();
for (RexNode operand : call.operands) {
result.add(operand.accept(this));
}
if (result.contains(false)) {
return false;
} else if (result.contains(true)) {
// return call.op.getKind() != SqlKind.OR || !result.contains(null);
return call.op.getKind() != SqlKind.OR;
} else {
return null;
}
}
};
for (RexNode c : conjunctions) {
Boolean r = c.accept(visitor);
if (r == null) {
nonCorConditions.add(c);
} else if (r) {
corConditions.add(c);
} else {
unsupportedCorConditions.add(c);
}
}
}
use of org.apache.calcite.rex.RexFieldAccess in project beam by apache.
the class BeamZetaSqlUnnestRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
LogicalCorrelate correlate = call.rel(0);
RelNode outer = call.rel(1);
RelNode uncollect = call.rel(2);
if (correlate.getRequiredColumns().cardinality() != 1) {
// can only unnest a single column
return;
}
if (correlate.getJoinType() != JoinRelType.INNER) {
return;
}
if (!(uncollect instanceof ZetaSqlUnnest)) {
// Drop projection
uncollect = ((SingleRel) uncollect).getInput();
if (uncollect instanceof RelSubset) {
uncollect = ((RelSubset) uncollect).getOriginal();
}
if (!(uncollect instanceof ZetaSqlUnnest)) {
return;
}
}
RelNode project = ((ZetaSqlUnnest) uncollect).getInput();
if (project instanceof RelSubset) {
project = ((RelSubset) project).getOriginal();
}
if (!(project instanceof LogicalProject)) {
return;
}
if (((LogicalProject) project).getProjects().size() != 1) {
// can only unnest a single column
return;
}
RexNode exp = ((LogicalProject) project).getProjects().get(0);
if (!(exp instanceof RexFieldAccess)) {
return;
}
RexFieldAccess fieldAccess = (RexFieldAccess) exp;
// Innermost field index comes first (e.g. struct.field1.field2 => [2, 1])
ImmutableList.Builder<Integer> fieldAccessIndices = ImmutableList.builder();
while (true) {
fieldAccessIndices.add(fieldAccess.getField().getIndex());
if (!(fieldAccess.getReferenceExpr() instanceof RexFieldAccess)) {
break;
}
fieldAccess = (RexFieldAccess) fieldAccess.getReferenceExpr();
}
call.transformTo(new BeamZetaSqlUnnestRel(correlate.getCluster(), correlate.getTraitSet().replace(BeamLogicalConvention.INSTANCE), convert(outer, outer.getTraitSet().replace(BeamLogicalConvention.INSTANCE)), call.rel(2).getRowType(), fieldAccessIndices.build()));
}
use of org.apache.calcite.rex.RexFieldAccess in project hive by apache.
the class HiveRelOptUtil method splitCorrelatedFilterCondition.
private static void splitCorrelatedFilterCondition(Filter filter, RexNode condition, List<RexNode> joinKeys, List<RexNode> correlatedJoinKeys, List<RexNode> nonEquiList, boolean extractCorrelatedFieldAccess) {
if (condition instanceof RexCall) {
RexCall call = (RexCall) condition;
if (call.getOperator().getKind() == SqlKind.AND) {
for (RexNode operand : call.getOperands()) {
splitCorrelatedFilterCondition(filter, operand, joinKeys, correlatedJoinKeys, nonEquiList, extractCorrelatedFieldAccess);
}
return;
}
if (call.getOperator().getKind() == SqlKind.EQUALS) {
final List<RexNode> operands = call.getOperands();
RexNode op0 = operands.get(0);
RexNode op1 = operands.get(1);
if (extractCorrelatedFieldAccess) {
if (!RexUtil.containsFieldAccess(op0) && (op1 instanceof RexFieldAccess)) {
joinKeys.add(op0);
correlatedJoinKeys.add(op1);
return;
} else if ((op0 instanceof RexFieldAccess) && !RexUtil.containsFieldAccess(op1)) {
correlatedJoinKeys.add(op0);
joinKeys.add(op1);
return;
}
} else {
if (!(RexUtil.containsInputRef(op0)) && (op1 instanceof RexInputRef)) {
correlatedJoinKeys.add(op0);
joinKeys.add(op1);
return;
} else if ((op0 instanceof RexInputRef) && !(RexUtil.containsInputRef(op1))) {
joinKeys.add(op0);
correlatedJoinKeys.add(op1);
return;
}
}
}
}
// The operator is not of RexCall type
// So we fail. Fall through.
// Add this condition to the list of non-equi-join conditions.
nonEquiList.add(condition);
}
use of org.apache.calcite.rex.RexFieldAccess in project hive 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() {
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.rex.RexFieldAccess in project hive by apache.
the class RelFieldTrimmer method result.
protected TrimResult result(RelNode r, final Mapping mapping) {
final RelBuilder relBuilder = REL_BUILDER.get();
final RexBuilder rexBuilder = relBuilder.getRexBuilder();
for (final CorrelationId correlation : r.getVariablesSet()) {
r = r.accept(new CorrelationReferenceFinder() {
protected RexNode handle(RexFieldAccess fieldAccess) {
final RexCorrelVariable v = (RexCorrelVariable) fieldAccess.getReferenceExpr();
if (v.id.equals(correlation) && v.getType().getFieldCount() == mapping.getSourceCount()) {
final int old = fieldAccess.getField().getIndex();
final int new_ = mapping.getTarget(old);
final RelDataTypeFactory.Builder typeBuilder = relBuilder.getTypeFactory().builder();
for (int target : Util.range(mapping.getTargetCount())) {
typeBuilder.add(v.getType().getFieldList().get(mapping.getSource(target)));
}
final RexNode newV = rexBuilder.makeCorrel(typeBuilder.build(), v.id);
if (old != new_) {
return rexBuilder.makeFieldAccess(newV, new_);
}
}
return fieldAccess;
}
});
}
return new TrimResult(r, mapping);
}
Aggregations