Vladsz83 commented on code in PR #11935:
URL: https://github.com/apache/ignite/pull/11935#discussion_r2007301991
##########
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PlannerHelper.java:
##########
@@ -129,6 +152,179 @@ public static IgniteRel optimize(SqlNode sqlNode,
IgnitePlanner planner, IgniteL
}
}
+ /** */
+ private static RelNode actualTopLevelJoinTypeHints(RelNode rel,
List<RelHint> topLevelHints) {
+ assert rel instanceof Hintable;
+
+ List<RelHint> curHints = ((Hintable)rel).getHints();
+
+ List<RelHint> res = new ArrayList<>(topLevelHints.size());
+
+ for (RelHint topHint : topLevelHints) {
+ assert topHint.inheritPath.isEmpty();
+
+ if (!JOIN_TYPE_HINT_NAMES.contains(topHint.hintName))
+ continue;
+
+ if (curHints.isEmpty()) {
+ res.add(topHint);
+
+ continue;
+ }
+
+ for (RelHint curHint : curHints) {
+ // Consider only hints of the join types and which differ by
name or parameters.
+ if (!JOIN_TYPE_HINT_NAMES.contains(curHint.hintName)
+ || topHint.equals(curHint.inheritPath.isEmpty() ? curHint
: curHint.copy(Collections.emptyList())))
+ continue;
+
+ res.add(topHint);
+ }
+ }
+
+ if (!res.isEmpty()) {
+ rel = ((Hintable)rel).withHints(res);
+
+ if (!curHints.isEmpty())
+ rel = ((Hintable)rel).attachHints(curHints);
+ }
+
+ return rel;
+ }
+
+ /**
+ * Tries to optimize joins order.
+ *
+ * @see JoinToMultiJoinRule
+ * @see IgniteMultiJoinOptimizeRule
+ *
+ * @return An node with optimized joins or original {@code root} if didn't
optimize.
+ */
+ private static RelNode optimizeJoinsOrder(IgnitePlanner planner, RelNode
root, List<RelHint> topLevelHints) {
+ List<Join> joins = findNodes(root, Join.class, false);
+
+ // No original joins found, nothing to optimize.
+ if (joins.isEmpty())
+ return root;
+
+ int disabledCnt = 0;
+
+ // If all the joins have the forced order, no need to optimize the
joins order at all.
+ for (Join join : joins) {
+ for (RelHint hint : join.getHints()) {
+ if
(HintDefinition.ENFORCE_JOIN_ORDER.name().equals(hint.hintName)) {
+ ++disabledCnt;
+
+ break;
+ }
+ }
+ }
+
+ if (disabledCnt == joins.size())
+ return root;
+
+ RelNode res = planner.transform(PlannerPhase.HEP_OPTIMIZE_JOIN_ORDER,
root.getTraitSet(), root);
+
+ // Still has a MultiJoin, didn't manage to collect one flat join to
optimize.
+ if (!findNodes(res, MultiJoin.class, true).isEmpty())
+ return root;
+
+ // If a new joins order was proposed, no need to launch another join
order optimizations.
+
planner.setDisabledRules(HintDefinition.ENFORCE_JOIN_ORDER.disabledRules().stream().map(RelOptRule::toString)
+ .collect(Collectors.toList()));
+
+ if (!topLevelHints.isEmpty()) {
+ res = actualTopLevelJoinTypeHints(res, topLevelHints);
+
+ restoreJoinTypeHints(res);
+ }
+
+ return res;
+ }
+
+ /**
+ * A join type hint might be assigned to a query root (top-level hint) or
to a table. Originally, SELECT-level hints
+ * are propagated and assigned to following Joins and TableScans. We lose
assigned to Join nodes ones
+ * in {@link JoinToMultiJoinRule} and have to reassign them from top-level
hints.
+ */
+ private static void restoreJoinTypeHints(RelNode root) {
+ RelShuttle visitor = new RelHomogeneousShuttle() {
+ /** Hints to assign on current tree level. */
+ private final List<List<RelHint>> hintsStack = new ArrayList<>();
+
+ /** Current hint inheritance path. It is important for hint
priority. */
+ private final List<Integer> inputsStack = new ArrayList<>();
+
+ /** {@inheritDoc} */
+ @Override public RelNode visit(RelNode rel) {
+ // Leaf TableScans have no inputs. And we are interrested only
in Joins.
+ if (rel.getInputs().isEmpty())
+ return rel;
+
+ List<RelHint> curHints = Collections.emptyList();
+
+ if ((rel instanceof Hintable) && !(rel instanceof Join) &&
!((Hintable)rel).getHints().isEmpty()) {
Review Comment:
We get joins without hints and repeat hints pushing to join nodes from the
top nodes. If join has a hint, it was already inherited from above. No need to
duplicate. Thus, we assign hints to joins, but do not consider already
assigned. Current join type hint will be pushed further.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]