org.apache.calcite.rex.RexVisitorImpl Java Examples

The following examples show how to use org.apache.calcite.rex.RexVisitorImpl. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: FlinkSemiAntiJoinJoinTransposeRule.java    From flink with Apache License 2.0 6 votes vote down vote up
private Pair<ImmutableBitSet, ImmutableBitSet> getSemiAntiJoinConditionInputRefs(Join semiAntiJoin) {
	final int leftInputFieldCount = semiAntiJoin.getLeft().getRowType().getFieldCount();
	final ImmutableBitSet.Builder leftInputBitSet = ImmutableBitSet.builder();
	final ImmutableBitSet.Builder rightInputBitSet = ImmutableBitSet.builder();
	semiAntiJoin.getCondition().accept(new RexVisitorImpl<Void>(true) {
		public Void visitInputRef(RexInputRef inputRef) {
			int index = inputRef.getIndex();
			if (index < leftInputFieldCount) {
				leftInputBitSet.set(index);
			} else {
				rightInputBitSet.set(index);
			}
			return null;
		}
	});
	return new Pair<>(leftInputBitSet.build(), rightInputBitSet.build());
}
 
Example #2
Source File: SubstitutionVisitor.java    From calcite with Apache License 2.0 6 votes vote down vote up
/** Check if join condition only references RexInputRef. */
private static boolean referenceByMapping(
    RexNode joinCondition, List<RexNode>... projectsOfInputs) {
  List<RexNode> projects = new ArrayList<>();
  for (List<RexNode> projectsOfInput: projectsOfInputs) {
    projects.addAll(projectsOfInput);
  }

  try {
    RexVisitor rexVisitor = new RexVisitorImpl<Void>(true) {
      @Override public Void visitInputRef(RexInputRef inputRef) {
        if (!(projects.get(inputRef.getIndex()) instanceof RexInputRef)) {
          throw Util.FoundOne.NULL;
        }
        return super.visitInputRef(inputRef);
      }
    };
    joinCondition.accept(rexVisitor);
  } catch (Util.FoundOne e) {
    return false;
  }
  return true;
}
 
Example #3
Source File: RelOptUtil.java    From calcite with Apache License 2.0 6 votes vote down vote up
private static boolean containsGet(RexNode node) {
  try {
    node.accept(
        new RexVisitorImpl<Void>(true) {
          @Override public Void visitCall(RexCall call) {
            if (call.getOperator() == RexBuilder.GET_OPERATOR) {
              throw Util.FoundOne.NULL;
            }
            return super.visitCall(call);
          }
        });
    return false;
  } catch (Util.FoundOne e) {
    return true;
  }
}
 
Example #4
Source File: RelMdColumnOrigins.java    From calcite with Apache License 2.0 6 votes vote down vote up
private Set<RelColumnOrigin> getMultipleColumns(RexNode rexNode, RelNode input,
    final RelMetadataQuery mq) {
  final Set<RelColumnOrigin> set = new HashSet<>();
  final RexVisitor<Void> visitor =
      new RexVisitorImpl<Void>(true) {
        public Void visitInputRef(RexInputRef inputRef) {
          Set<RelColumnOrigin> inputSet =
              mq.getColumnOrigins(input, inputRef.getIndex());
          if (inputSet != null) {
            set.addAll(inputSet);
          }
          return null;
        }
      };
  rexNode.accept(visitor);
  return set;
}
 
Example #5
Source File: FlinkSemiAntiJoinJoinTransposeRule.java    From flink with Apache License 2.0 6 votes vote down vote up
private Pair<ImmutableBitSet, ImmutableBitSet> getSemiAntiJoinConditionInputRefs(Join semiAntiJoin) {
	final int leftInputFieldCount = semiAntiJoin.getLeft().getRowType().getFieldCount();
	final ImmutableBitSet.Builder leftInputBitSet = ImmutableBitSet.builder();
	final ImmutableBitSet.Builder rightInputBitSet = ImmutableBitSet.builder();
	semiAntiJoin.getCondition().accept(new RexVisitorImpl<Void>(true) {
		public Void visitInputRef(RexInputRef inputRef) {
			int index = inputRef.getIndex();
			if (index < leftInputFieldCount) {
				leftInputBitSet.set(index);
			} else {
				rightInputBitSet.set(index);
			}
			return null;
		}
	});
	return new Pair<>(leftInputBitSet.build(), rightInputBitSet.build());
}
 
Example #6
Source File: DrillRelOptUtil.java    From Bats with Apache License 2.0 6 votes vote down vote up
/**
 * Find whether the given project rel has unknown output schema. This would happen if the
 * project has CONVERT_FROMJSON which can only derive the schema after evaluation is performed
 * @param project : The project rel
 * @return : Return true if the project output schema is unknown. Otherwise, false.
 */
public static boolean isProjectOutputSchemaUnknown(Project project) {
    try {
        RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {
            @Override
            public Void visitCall(RexCall call) {
                if ("convert_fromjson".equals(call.getOperator().getName().toLowerCase())) {
                    throw new Util.FoundOne(call); /* throw exception to interrupt tree walk (this is similar to
                                                   other utility methods in RexUtil.java */
                }
                return super.visitCall(call);
            }
        };
        for (RexNode rex : project.getProjects()) {
            rex.accept(visitor);
        }
    } catch (Util.FoundOne e) {
        Util.swallow(e, null);
        return true;
    }
    return false;
}
 
Example #7
Source File: RelOptUtil.java    From Bats with Apache License 2.0 6 votes vote down vote up
private static boolean containsGet(RexNode node) {
    try {
        node.accept(new RexVisitorImpl<Void>(true) {
            @Override
            public Void visitCall(RexCall call) {
                if (call.getOperator() == RexBuilder.GET_OPERATOR) {
                    throw Util.FoundOne.NULL;
                }
                return super.visitCall(call);
            }
        });
        return false;
    } catch (Util.FoundOne e) {
        return true;
    }
}
 
Example #8
Source File: DrillRelMdSelectivity.java    From Bats with Apache License 2.0 6 votes vote down vote up
private static RexInputRef findRexInputRef(final RexNode node) {
  try {
    RexVisitor<Void> visitor =
        new RexVisitorImpl<Void>(true) {
          public Void visitCall(RexCall call) {
            for (RexNode child : call.getOperands()) {
              child.accept(this);
            }
            return super.visitCall(call);
          }

          public Void visitInputRef(RexInputRef inputRef) {
            throw new Util.FoundOne(inputRef);
          }
        };
    node.accept(visitor);
    return null;
  } catch (Util.FoundOne e) {
    Util.swallow(e, null);
    return (RexInputRef) e.getNode();
  }
}
 
Example #9
Source File: SubQueryDecorrelator.java    From flink with Apache License 2.0 5 votes vote down vote up
/**
 * check whether the project has correlation expressions.
 * e.g. SELECT * FROM l WHERE a IN (SELECT l.b FROM r)
 */
private void checkCorCondition(final LogicalProject project) {
	if (!hasUnsupportedCorCondition) {
		for (RexNode node : project.getProjects()) {
			node.accept(new RexVisitorImpl<Void>(true) {
				@Override
				public Void visitCorrelVariable(RexCorrelVariable correlVariable) {
					hasUnsupportedCorCondition = true;
					return super.visitCorrelVariable(correlVariable);
				}
			});
		}
	}
}
 
Example #10
Source File: RelDecorrelator.java    From Bats with Apache License 2.0 5 votes vote down vote up
private RexVisitorImpl<Void> rexVisitor(final RelNode rel) {
    return new RexVisitorImpl<Void>(true) {
        @Override
        public Void visitFieldAccess(RexFieldAccess fieldAccess) {
            final RexNode ref = fieldAccess.getReferenceExpr();
            if (ref instanceof RexCorrelVariable) {
                final RexCorrelVariable var = (RexCorrelVariable) ref;
                if (mapFieldAccessToCorVar.containsKey(fieldAccess)) {
                    // for cases where different Rel nodes are referring to
                    // same correlation var (e.g. in case of NOT IN)
                    // avoid generating another correlation var
                    // and record the 'rel' is using the same correlation
                    mapRefRelToCorRef.put(rel, mapFieldAccessToCorVar.get(fieldAccess));
                } else {
                    final CorRef correlation = new CorRef(var.getCorrelationId(),
                            fieldAccess.getField().getIndex(), corrIdGenerator++);
                    mapFieldAccessToCorVar.put(fieldAccess, correlation);
                    mapRefRelToCorRef.put(rel, correlation);
                }
            }
            return super.visitFieldAccess(fieldAccess);
        }

        @Override
        public Void visitSubQuery(RexSubQuery subQuery) {
            subQuery.getRel().accept(CorelMapBuilder.this);
            return super.visitSubQuery(subQuery);
        }
    };
}
 
Example #11
Source File: RelDecorrelator.java    From calcite with Apache License 2.0 5 votes vote down vote up
private RexVisitorImpl<Void> rexVisitor(final RelNode rel) {
  return new RexVisitorImpl<Void>(true) {
    @Override public Void visitFieldAccess(RexFieldAccess fieldAccess) {
      final RexNode ref = fieldAccess.getReferenceExpr();
      if (ref instanceof RexCorrelVariable) {
        final RexCorrelVariable var = (RexCorrelVariable) ref;
        if (mapFieldAccessToCorVar.containsKey(fieldAccess)) {
          // for cases where different Rel nodes are referring to
          // same correlation var (e.g. in case of NOT IN)
          // avoid generating another correlation var
          // and record the 'rel' is using the same correlation
          mapRefRelToCorRef.put(rel,
              mapFieldAccessToCorVar.get(fieldAccess));
        } else {
          final CorRef correlation =
              new CorRef(var.id, fieldAccess.getField().getIndex(),
                  corrIdGenerator++);
          mapFieldAccessToCorVar.put(fieldAccess, correlation);
          mapRefRelToCorRef.put(rel, correlation);
        }
      }
      return super.visitFieldAccess(fieldAccess);
    }

    @Override public Void visitSubQuery(RexSubQuery subQuery) {
      subQuery.rel.accept(CorelMapBuilder.this);
      return super.visitSubQuery(subQuery);
    }
  };
}
 
Example #12
Source File: CalcRelSplitter.java    From calcite with Apache License 2.0 5 votes vote down vote up
/**
 * Computes the order in which to visit expressions, so that we decide the
 * level of an expression only after the levels of lower expressions have
 * been decided.
 *
 * <p>First, we need to ensure that an expression is visited after all of
 * its inputs.
 *
 * <p>Further, if the expression is a member of a cohort, we need to visit
 * it after the inputs of all other expressions in that cohort. With this
 * condition, expressions in the same cohort will very likely end up in the
 * same level.
 *
 * <p>Note that if there are no cohorts, the expressions from the
 * {@link RexProgram} are already in a suitable order. We perform the
 * topological sort just to ensure that the code path is well-trodden.
 *
 * @param exprs   Expressions
 * @param cohorts List of cohorts, each of which is a set of expr ordinals
 * @return Expression ordinals in topological order
 */
private List<Integer> computeTopologicalOrdering(
    RexNode[] exprs,
    List<Set<Integer>> cohorts) {
  final DirectedGraph<Integer, DefaultEdge> graph =
      DefaultDirectedGraph.create();
  for (int i = 0; i < exprs.length; i++) {
    graph.addVertex(i);
  }
  for (int i = 0; i < exprs.length; i++) {
    final RexNode expr = exprs[i];
    final Set<Integer> cohort = findCohort(cohorts, i);
    final Set<Integer> targets;
    if (cohort == null) {
      targets = Collections.singleton(i);
    } else {
      targets = cohort;
    }
    expr.accept(
        new RexVisitorImpl<Void>(true) {
          public Void visitLocalRef(RexLocalRef localRef) {
            for (Integer target : targets) {
              graph.addEdge(localRef.getIndex(), target);
            }
            return null;
          }
        });
  }
  TopologicalOrderIterator<Integer, DefaultEdge> iter =
      new TopologicalOrderIterator<>(graph);
  final List<Integer> permutation = new ArrayList<>();
  while (iter.hasNext()) {
    permutation.add(iter.next());
  }
  return permutation;
}
 
Example #13
Source File: ElasticsearchRules.java    From calcite with Apache License 2.0 5 votes vote down vote up
/**
 * Checks if current node represents item access as in {@code _MAP['foo']} or
 * {@code cast(_MAP['foo'] as integer)}
 *
 * @return true if expression is item, false otherwise
 */
static boolean isItem(RexNode node) {
  final Boolean result = node.accept(new RexVisitorImpl<Boolean>(false) {
    @Override public Boolean visitCall(final RexCall call) {
      return isItemCall(uncast(call)) != null;
    }
  });
  return Boolean.TRUE.equals(result);
}
 
Example #14
Source File: DrillRelMdSelectivity.java    From Bats with Apache License 2.0 5 votes vote down vote up
private static List<RexInputRef> findAllRexInputRefs(final RexNode node) {
    List<RexInputRef> rexRefs = new ArrayList<>();
    RexVisitor<Void> visitor =
        new RexVisitorImpl<Void>(true) {
          public Void visitInputRef(RexInputRef inputRef) {
            rexRefs.add(inputRef);
            return super.visitInputRef(inputRef);
          }
        };
    node.accept(visitor);
    return rexRefs;
}
 
Example #15
Source File: SubQueryDecorrelator.java    From flink with Apache License 2.0 5 votes vote down vote up
/**
 * check whether a node has some input which have correlation condition.
 * e.g. SELECT * FROM l WHERE EXISTS (SELECT * FROM r LEFT JOIN (SELECT * FROM t WHERE t.j=l.b) t1 ON r.f=t1.k)
 * the above sql can not be converted to semi-join plan,
 * because the right input of Left-Join has the correlation condition(t.j=l.b).
 */
private void checkCorConditionOfInput(final RelNode input) {
	final RelShuttleImpl shuttle = new RelShuttleImpl() {
		final RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {
			@Override
			public Void visitCorrelVariable(RexCorrelVariable correlVariable) {
				hasUnsupportedCorCondition = true;
				return super.visitCorrelVariable(correlVariable);
			}
		};

		@Override
		public RelNode visit(LogicalFilter filter) {
			filter.getCondition().accept(visitor);
			return super.visit(filter);
		}

		@Override
		public RelNode visit(LogicalProject project) {
			for (RexNode rex : project.getProjects()) {
				rex.accept(visitor);
			}
			return super.visit(project);
		}

		@Override
		public RelNode visit(LogicalJoin join) {
			join.getCondition().accept(visitor);
			return super.visit(join);
		}
	};
	input.accept(shuttle);
}
 
Example #16
Source File: DrillRelOptUtil.java    From Bats with Apache License 2.0 5 votes vote down vote up
/**
 * Travesal RexNode to find at least one operator in the given collection. Continue search if RexNode has a
 * RexInputRef which refers to a RexNode in project expressions.
 *
 * @param node : RexNode to search
 * @param projExprs : the list of project expressions. Empty list means there is No project operator underneath.
 * @param operators collection of operators to find
 * @return : Return null if there is NONE; return the first appearance of item/flatten RexCall.
 */
public static RexCall findOperators(final RexNode node, final List<RexNode> projExprs,
        final Collection<String> operators) {
    try {
        RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {
            @Override
            public Void visitCall(RexCall call) {
                if (operators.contains(call.getOperator().getName().toLowerCase())) {
                    throw new Util.FoundOne(call); /* throw exception to interrupt tree walk (this is similar to
                                                   other utility methods in RexUtil.java */
                }
                return super.visitCall(call);
            }

            @Override
            public Void visitInputRef(RexInputRef inputRef) {
                if (projExprs.size() == 0) {
                    return super.visitInputRef(inputRef);
                } else {
                    final int index = inputRef.getIndex();
                    RexNode n = projExprs.get(index);
                    if (n instanceof RexCall) {
                        RexCall r = (RexCall) n;
                        if (operators.contains(r.getOperator().getName().toLowerCase())) {
                            throw new Util.FoundOne(r);
                        }
                    }

                    return super.visitInputRef(inputRef);
                }
            }
        };
        node.accept(visitor);
        return null;
    } catch (Util.FoundOne e) {
        Util.swallow(e, null);
        return (RexCall) e.getNode();
    }
}
 
Example #17
Source File: SubQueryDecorrelator.java    From flink with Apache License 2.0 5 votes vote down vote up
/**
 * check whether the predicate on join has unsupported correlation condition.
 * e.g. SELECT * FROM l WHERE a IN (SELECT c FROM r WHERE l.b IN (SELECT e FROM t))
 */
private void checkCorCondition(final LogicalJoin join) {
	if (!hasUnsupportedCorCondition) {
		join.getCondition().accept(new RexVisitorImpl<Void>(true) {
			@Override
			public Void visitCorrelVariable(RexCorrelVariable correlVariable) {
				hasUnsupportedCorCondition = true;
				return super.visitCorrelVariable(correlVariable);
			}
		});
	}
}
 
Example #18
Source File: SubQueryDecorrelator.java    From flink with Apache License 2.0 5 votes vote down vote up
private RexVisitorImpl<Void> handleSubQuery(final RelNode rel) {
	return new RexVisitorImpl<Void>(true) {

		@Override
		public Void visitSubQuery(RexSubQuery subQuery) {
			RelNode newRel = subQuery.rel;
			if (subQuery.getKind() == SqlKind.IN) {
				newRel = addProjectionForIn(subQuery.rel);
			}
			final Frame frame = decorrelator.getInvoke(newRel);
			if (frame != null && frame.c != null) {

				Frame target = frame;
				if (subQuery.getKind() == SqlKind.EXISTS) {
					target = addProjectionForExists(frame);
				}

				final DecorrelateRexShuttle shuttle = new DecorrelateRexShuttle(
						rel.getRowType(),
						target.r.getRowType(),
						rel.getVariablesSet());

				final RexNode newCondition = target.c.accept(shuttle);
				Pair<RelNode, RexNode> newNodeAndCondition = new Pair<>(target.r, newCondition);
				subQueryMap.put(subQuery, newNodeAndCondition);
			}
			return null;
		}
	};
}
 
Example #19
Source File: CalcRelSplitter.java    From Bats with Apache License 2.0 5 votes vote down vote up
/**
 * Computes the order in which to visit expressions, so that we decide the
 * level of an expression only after the levels of lower expressions have
 * been decided.
 *
 * <p>First, we need to ensure that an expression is visited after all of
 * its inputs.
 *
 * <p>Further, if the expression is a member of a cohort, we need to visit
 * it after the inputs of all other expressions in that cohort. With this
 * condition, expressions in the same cohort will very likely end up in the
 * same level.
 *
 * <p>Note that if there are no cohorts, the expressions from the
 * {@link RexProgram} are already in a suitable order. We perform the
 * topological sort just to ensure that the code path is well-trodden.
 *
 * @param exprs   Expressions
 * @param cohorts List of cohorts, each of which is a set of expr ordinals
 * @return Expression ordinals in topological order
 */
private List<Integer> computeTopologicalOrdering(RexNode[] exprs, List<Set<Integer>> cohorts) {
    final DirectedGraph<Integer, DefaultEdge> graph = DefaultDirectedGraph.create();
    for (int i = 0; i < exprs.length; i++) {
        graph.addVertex(i);
    }
    for (int i = 0; i < exprs.length; i++) {
        final RexNode expr = exprs[i];
        final Set<Integer> cohort = findCohort(cohorts, i);
        final Set<Integer> targets;
        if (cohort == null) {
            targets = Collections.singleton(i);
        } else {
            targets = cohort;
        }
        expr.accept(new RexVisitorImpl<Void>(true) {
            @Override
            public Void visitLocalRef(RexLocalRef localRef) {
                for (Integer target : targets) {
                    graph.addEdge(localRef.getIndex(), target);
                }
                return null;
            }
        });
    }
    TopologicalOrderIterator<Integer, DefaultEdge> iter = new TopologicalOrderIterator<>(graph);
    final List<Integer> permutation = new ArrayList<>();
    while (iter.hasNext()) {
        permutation.add(iter.next());
    }
    return permutation;
}
 
Example #20
Source File: SubQueryDecorrelator.java    From flink with Apache License 2.0 5 votes vote down vote up
/**
 * check whether a node has some input which have correlation condition.
 * e.g. SELECT * FROM l WHERE EXISTS (SELECT * FROM r LEFT JOIN (SELECT * FROM t WHERE t.j=l.b) t1 ON r.f=t1.k)
 * the above sql can not be converted to semi-join plan,
 * because the right input of Left-Join has the correlation condition(t.j=l.b).
 */
private void checkCorConditionOfInput(final RelNode input) {
	final RelShuttleImpl shuttle = new RelShuttleImpl() {
		final RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {
			@Override
			public Void visitCorrelVariable(RexCorrelVariable correlVariable) {
				hasUnsupportedCorCondition = true;
				return super.visitCorrelVariable(correlVariable);
			}
		};

		@Override
		public RelNode visit(LogicalFilter filter) {
			filter.getCondition().accept(visitor);
			return super.visit(filter);
		}

		@Override
		public RelNode visit(LogicalProject project) {
			for (RexNode rex : project.getProjects()) {
				rex.accept(visitor);
			}
			return super.visit(project);
		}

		@Override
		public RelNode visit(LogicalJoin join) {
			join.getCondition().accept(visitor);
			return super.visit(join);
		}
	};
	input.accept(shuttle);
}
 
Example #21
Source File: SubQueryDecorrelator.java    From flink with Apache License 2.0 5 votes vote down vote up
/**
 * check whether the project has correlation expressions.
 * e.g. SELECT * FROM l WHERE a IN (SELECT l.b FROM r)
 */
private void checkCorCondition(final LogicalProject project) {
	if (!hasUnsupportedCorCondition) {
		for (RexNode node : project.getProjects()) {
			node.accept(new RexVisitorImpl<Void>(true) {
				@Override
				public Void visitCorrelVariable(RexCorrelVariable correlVariable) {
					hasUnsupportedCorCondition = true;
					return super.visitCorrelVariable(correlVariable);
				}
			});
		}
	}
}
 
Example #22
Source File: SubQueryDecorrelator.java    From flink with Apache License 2.0 5 votes vote down vote up
/**
 * check whether the predicate on join has unsupported correlation condition.
 * e.g. SELECT * FROM l WHERE a IN (SELECT c FROM r WHERE l.b IN (SELECT e FROM t))
 */
private void checkCorCondition(final LogicalJoin join) {
	if (!hasUnsupportedCorCondition) {
		join.getCondition().accept(new RexVisitorImpl<Void>(true) {
			@Override
			public Void visitCorrelVariable(RexCorrelVariable correlVariable) {
				hasUnsupportedCorCondition = true;
				return super.visitCorrelVariable(correlVariable);
			}
		});
	}
}
 
Example #23
Source File: SubQueryDecorrelator.java    From flink with Apache License 2.0 5 votes vote down vote up
private RexVisitorImpl<Void> handleSubQuery(final RelNode rel) {
	return new RexVisitorImpl<Void>(true) {

		@Override
		public Void visitSubQuery(RexSubQuery subQuery) {
			RelNode newRel = subQuery.rel;
			if (subQuery.getKind() == SqlKind.IN) {
				newRel = addProjectionForIn(subQuery.rel);
			}
			final Frame frame = decorrelator.getInvoke(newRel);
			if (frame != null && frame.c != null) {

				Frame target = frame;
				if (subQuery.getKind() == SqlKind.EXISTS) {
					target = addProjectionForExists(frame);
				}

				final DecorrelateRexShuttle shuttle = new DecorrelateRexShuttle(
						rel.getRowType(),
						target.r.getRowType(),
						rel.getVariablesSet());

				final RexNode newCondition = target.c.accept(shuttle);
				Pair<RelNode, RexNode> newNodeAndCondition = new Pair<>(target.r, newCondition);
				subQueryMap.put(subQuery, newNodeAndCondition);
			}
			return null;
		}
	};
}
 
Example #24
Source File: RelDecorrelator.java    From flink with Apache License 2.0 5 votes vote down vote up
private RexVisitorImpl<Void> rexVisitor(final RelNode rel) {
  return new RexVisitorImpl<Void>(true) {
    @Override public Void visitFieldAccess(RexFieldAccess fieldAccess) {
      final RexNode ref = fieldAccess.getReferenceExpr();
      if (ref instanceof RexCorrelVariable) {
        final RexCorrelVariable var = (RexCorrelVariable) ref;
        if (mapFieldAccessToCorVar.containsKey(fieldAccess)) {
          // for cases where different Rel nodes are referring to
          // same correlation var (e.g. in case of NOT IN)
          // avoid generating another correlation var
          // and record the 'rel' is using the same correlation
          mapRefRelToCorRef.put(rel,
              mapFieldAccessToCorVar.get(fieldAccess));
        } else {
          final CorRef correlation =
              new CorRef(var.id, fieldAccess.getField().getIndex(),
                  corrIdGenerator++);
          mapFieldAccessToCorVar.put(fieldAccess, correlation);
          mapRefRelToCorRef.put(rel, correlation);
        }
      }
      return super.visitFieldAccess(fieldAccess);
    }

    @Override public Void visitSubQuery(RexSubQuery subQuery) {
      subQuery.rel.accept(CorelMapBuilder.this);
      return super.visitSubQuery(subQuery);
    }
  };
}
 
Example #25
Source File: RelDecorrelator.java    From flink with Apache License 2.0 5 votes vote down vote up
private RexVisitorImpl<Void> rexVisitor(final RelNode rel) {
  return new RexVisitorImpl<Void>(true) {
    @Override public Void visitFieldAccess(RexFieldAccess fieldAccess) {
      final RexNode ref = fieldAccess.getReferenceExpr();
      if (ref instanceof RexCorrelVariable) {
        final RexCorrelVariable var = (RexCorrelVariable) ref;
        if (mapFieldAccessToCorVar.containsKey(fieldAccess)) {
          // for cases where different Rel nodes are referring to
          // same correlation var (e.g. in case of NOT IN)
          // avoid generating another correlation var
          // and record the 'rel' is using the same correlation
          mapRefRelToCorRef.put(rel,
              mapFieldAccessToCorVar.get(fieldAccess));
        } else {
          final CorRef correlation =
              new CorRef(var.id, fieldAccess.getField().getIndex(),
                  corrIdGenerator++);
          mapFieldAccessToCorVar.put(fieldAccess, correlation);
          mapRefRelToCorRef.put(rel, correlation);
        }
      }
      return super.visitFieldAccess(fieldAccess);
    }

    @Override public Void visitSubQuery(RexSubQuery subQuery) {
      subQuery.rel.accept(CorelMapBuilder.this);
      return super.visitSubQuery(subQuery);
    }
  };
}
 
Example #26
Source File: SubQueryDecorrelator.java    From flink with Apache License 2.0 4 votes vote down vote up
private RexVisitorImpl<Void> rexVisitor(final RelNode rel) {
	return new RexVisitorImpl<Void>(true) {
		@Override
		public Void visitSubQuery(RexSubQuery subQuery) {
			hasAggregateNode = false; // reset to default value
			hasOverNode = false; // reset to default value
			subQuery.rel.accept(CorelMapBuilder.this);
			return super.visitSubQuery(subQuery);
		}

		@Override
		public Void visitFieldAccess(RexFieldAccess fieldAccess) {
			final RexNode ref = fieldAccess.getReferenceExpr();
			if (ref instanceof RexCorrelVariable) {
				final RexCorrelVariable var = (RexCorrelVariable) ref;
				// check the scope of correlation id
				// we do not support nested correlation variables in SubQuery, such as:
				// select * from t1 where exists (select * from t2 where t1.a = t2.c and
				// t2.d in (select t3.d from t3 where t1.b = t3.e)
				if (!hasUnsupportedCorCondition) {
					hasUnsupportedCorCondition = !mapSubQueryNodeToCorSet.containsKey(rel);
				}
				if (!hasNestedCorScope && mapSubQueryNodeToCorSet.containsKey(rel)) {
					hasNestedCorScope = !mapSubQueryNodeToCorSet.get(rel).contains(var.id);
				}

				if (mapFieldAccessToCorVar.containsKey(fieldAccess)) {
					// for cases where different Rel nodes are referring to
					// same correlation var (e.g. in case of NOT IN)
					// avoid generating another correlation var
					// and record the 'rel' is using the same correlation
					mapRefRelToCorRef.put(rel, mapFieldAccessToCorVar.get(fieldAccess));
				} else {
					final CorRef correlation = new CorRef(
							var.id,
							fieldAccess.getField().getIndex(),
							corrIdGenerator++);
					mapFieldAccessToCorVar.put(fieldAccess, correlation);
					mapRefRelToCorRef.put(rel, correlation);
				}
			}
			return super.visitFieldAccess(fieldAccess);
		}
	};
}
 
Example #27
Source File: SubQueryDecorrelator.java    From flink with Apache License 2.0 4 votes vote down vote up
private RexVisitorImpl<Void> rexVisitor(final RelNode rel) {
	return new RexVisitorImpl<Void>(true) {
		@Override
		public Void visitSubQuery(RexSubQuery subQuery) {
			hasAggregateNode = false; // reset to default value
			hasOverNode = false; // reset to default value
			subQuery.rel.accept(CorelMapBuilder.this);
			return super.visitSubQuery(subQuery);
		}

		@Override
		public Void visitFieldAccess(RexFieldAccess fieldAccess) {
			final RexNode ref = fieldAccess.getReferenceExpr();
			if (ref instanceof RexCorrelVariable) {
				final RexCorrelVariable var = (RexCorrelVariable) ref;
				// check the scope of correlation id
				// we do not support nested correlation variables in SubQuery, such as:
				// select * from t1 where exists (select * from t2 where t1.a = t2.c and
				// t2.d in (select t3.d from t3 where t1.b = t3.e)
				if (!hasUnsupportedCorCondition) {
					hasUnsupportedCorCondition = !mapSubQueryNodeToCorSet.containsKey(rel);
				}
				if (!hasNestedCorScope && mapSubQueryNodeToCorSet.containsKey(rel)) {
					hasNestedCorScope = !mapSubQueryNodeToCorSet.get(rel).contains(var.id);
				}

				if (mapFieldAccessToCorVar.containsKey(fieldAccess)) {
					// for cases where different Rel nodes are referring to
					// same correlation var (e.g. in case of NOT IN)
					// avoid generating another correlation var
					// and record the 'rel' is using the same correlation
					mapRefRelToCorRef.put(rel, mapFieldAccessToCorVar.get(fieldAccess));
				} else {
					final CorRef correlation = new CorRef(
							var.id,
							fieldAccess.getField().getIndex(),
							corrIdGenerator++);
					mapFieldAccessToCorVar.put(fieldAccess, correlation);
					mapRefRelToCorRef.put(rel, correlation);
				}
			}
			return super.visitFieldAccess(fieldAccess);
		}
	};
}
 
Example #28
Source File: SubstitutionVisitor.java    From calcite with Apache License 2.0 4 votes vote down vote up
@Override protected UnifyResult apply(UnifyRuleCall call) {
  final MutableAggregate query = (MutableAggregate) call.query;
  final MutableCalc qInput = (MutableCalc) query.getInput();
  final Pair<RexNode, List<RexNode>> qInputExplained = explainCalc(qInput);
  final RexNode qInputCond = qInputExplained.left;
  final List<RexNode> qInputProjs = qInputExplained.right;

  final MutableAggregate target = (MutableAggregate) call.target;

  final RexBuilder rexBuilder = call.getCluster().getRexBuilder();

  final Mappings.TargetMapping mapping =
      Project.getMapping(fieldCnt(qInput.getInput()), qInputProjs);
  if (mapping == null) {
    return null;
  }

  if (!qInputCond.isAlwaysTrue()) {
    try {
      // Fail the matching when filtering condition references
      // non-grouping columns in target.
      qInputCond.accept(new RexVisitorImpl<Void>(true) {
        @Override public Void visitInputRef(RexInputRef inputRef) {
          if (!target.groupSets.stream()
              .allMatch(groupSet -> groupSet.get(inputRef.getIndex()))) {
            throw Util.FoundOne.NULL;
          }
          return super.visitInputRef(inputRef);
        }
      });
    } catch (Util.FoundOne one) {
      return null;
    }
  }

  final Mapping inverseMapping = mapping.inverse();
  final MutableAggregate aggregate2 =
      permute(query, qInput.getInput(), inverseMapping);

  final Mappings.TargetMapping mappingForQueryCond = Mappings.target(
      target.groupSet::indexOf,
      target.getInput().rowType.getFieldCount(),
      target.groupSet.cardinality());
  final RexNode targetCond = RexUtil.apply(mappingForQueryCond, qInputCond);

  final MutableRel unifiedAggregate =
      unifyAggregates(aggregate2, targetCond, target);
  if (unifiedAggregate == null) {
    return null;
  }
  // Add Project if the mapping breaks order of fields in GroupSet
  if (!Mappings.keepsOrdering(mapping)) {
    final List<Integer> posList = new ArrayList<>();
    final int fieldCount = aggregate2.rowType.getFieldCount();
    final List<Pair<Integer, Integer>> pairs = new ArrayList<>();
    final List<Integer> groupings = aggregate2.groupSet.toList();
    for (int i = 0; i < groupings.size(); i++) {
      pairs.add(Pair.of(mapping.getTarget(groupings.get(i)), i));
    }
    Collections.sort(pairs);
    pairs.forEach(pair -> posList.add(pair.right));
    for (int i = posList.size(); i < fieldCount; i++) {
      posList.add(i);
    }
    final List<RexNode> compenProjs =
        MutableRels.createProjectExprs(unifiedAggregate, posList);
    final RexProgram compensatingRexProgram = RexProgram.create(
        unifiedAggregate.rowType, compenProjs, null,
        query.rowType, rexBuilder);
    final MutableCalc compenCalc =
        MutableCalc.of(unifiedAggregate, compensatingRexProgram);
    if (unifiedAggregate instanceof MutableCalc) {
      final MutableCalc newCompenCalc =
          mergeCalc(rexBuilder, compenCalc, (MutableCalc) unifiedAggregate);
      return tryMergeParentCalcAndGenResult(call, newCompenCalc);
    } else {
      return tryMergeParentCalcAndGenResult(call, compenCalc);
    }
  } else {
    return tryMergeParentCalcAndGenResult(call, unifiedAggregate);
  }
}
 
Example #29
Source File: Strong.java    From calcite with Apache License 2.0 3 votes vote down vote up
/**
 * Returns whether a given expression is strong.
 *
 * <p>Examples:</p>
 * <ul>
 *   <li>Returns true for {@code c = 1} since it returns null if and only if
 *   c is null
 *   <li>Returns false for {@code c IS NULL} since it always returns TRUE
 *   or FALSE
 *</ul>
 *
 * @param e Expression
 * @return true if the expression is strong, false otherwise
 */
public static boolean isStrong(RexNode e) {
  final ImmutableBitSet.Builder nullColumns = ImmutableBitSet.builder();
  e.accept(
      new RexVisitorImpl<Void>(true) {
        public Void visitInputRef(RexInputRef inputRef) {
          nullColumns.set(inputRef.getIndex());
          return super.visitInputRef(inputRef);
        }
      });
  return isNull(e, nullColumns.build());
}