[Fix](Nereids) fix leading syntax problems and data mismatched problem (#32286)

- fix syntax problems of only one table used in leading or mistake usage of brace
  example: leading(t1),leading(t1 {t2})
- fix cte used in subquery of using leading
  example: with cte as (select c1 from t1) select count(*) from t1 join (select /*+ leading(cte t2) */ c2 from t2 join cte on c2 = cte.c1) as alias on t1.c1 = alias.c2;
  which cte used in subquery and subquery also have leading
- fix data mismatched with original plan cause of on predicate push to nullable side
  example: select count(*) from t1 left join t2 on c1 > 500 and c2 > 500 can not change to select count(*) from t1 left join t2 on c2 > 500 where c1 > 500
This commit is contained in:
LiBinfeng
2024-03-18 14:41:44 +08:00
committed by yiguolei
parent fab48f54b1
commit 4d4cd43458
7 changed files with 92 additions and 6 deletions

View File

@ -533,6 +533,11 @@ public class LeadingHint extends Hint {
stackTopLevel = currentLevel;
}
}
if (stack.size() > 1) {
this.setStatus(HintStatus.SYNTAX_ERROR);
this.setErrorMessage("please check your brace pairs in leading");
return null;
}
LogicalJoin finalJoin = (LogicalJoin) stack.pop().second.first;
// we want all filters been remove

View File

@ -41,6 +41,14 @@ public class PullUpSubqueryAliasToCTE extends PlanPreprocessor {
StatementContext context) {
Plan topPlan = visitChildren(this, unboundResultSink, context);
if (!aliasQueries.isEmpty()) {
if (((UnboundResultSink) topPlan).child() instanceof LogicalCTE) {
LogicalCTE logicalCTE = (LogicalCTE) ((UnboundResultSink) topPlan).child();
List<LogicalSubQueryAlias<Plan>> subQueryAliases = new ArrayList<>();
subQueryAliases.addAll(logicalCTE.getAliasQueries());
subQueryAliases.addAll(aliasQueries);
return topPlan.withChildren(
new LogicalCTE<>(subQueryAliases, (LogicalPlan) ((UnboundResultSink) topPlan).child()));
}
return topPlan.withChildren(
new LogicalCTE<>(aliasQueries, (LogicalPlan) ((UnboundResultSink) topPlan).child()));
}

View File

@ -58,6 +58,9 @@ public class CollectJoinConstraint implements RewriteRuleFactory {
leading.setStatus(Hint.HintStatus.UNUSED);
leading.setErrorMessage("condition does not matched joinType");
}
Long leftHand = LongBitmap.computeTableBitmap(join.left().getInputRelations());
Long rightHand = LongBitmap.computeTableBitmap(join.right().getInputRelations());
join.setBitmap(LongBitmap.or(leftHand, rightHand));
List<Expression> expressions = join.getHashJoinConjuncts();
Long totalFilterBitMap = 0L;
Long nonNullableSlotBitMap = 0L;
@ -66,6 +69,9 @@ public class CollectJoinConstraint implements RewriteRuleFactory {
nonNullableSlotBitMap = LongBitmap.or(nonNullableSlotBitMap, nonNullable);
Long filterBitMap = calSlotsTableBitMap(leading, expression.getInputSlots(), false);
totalFilterBitMap = LongBitmap.or(totalFilterBitMap, filterBitMap);
if (join.getJoinType().isLeftJoin()) {
filterBitMap = LongBitmap.or(filterBitMap, rightHand);
}
leading.getFilters().add(Pair.of(filterBitMap, expression));
leading.putConditionJoinType(expression, join.getJoinType());
}
@ -75,12 +81,12 @@ public class CollectJoinConstraint implements RewriteRuleFactory {
nonNullableSlotBitMap = LongBitmap.or(nonNullableSlotBitMap, nonNullable);
Long filterBitMap = calSlotsTableBitMap(leading, expression.getInputSlots(), false);
totalFilterBitMap = LongBitmap.or(totalFilterBitMap, filterBitMap);
if (join.getJoinType().isLeftJoin()) {
filterBitMap = LongBitmap.or(filterBitMap, rightHand);
}
leading.getFilters().add(Pair.of(filterBitMap, expression));
leading.putConditionJoinType(expression, join.getJoinType());
}
Long leftHand = LongBitmap.computeTableBitmap(join.left().getInputRelations());
Long rightHand = LongBitmap.computeTableBitmap(join.right().getInputRelations());
join.setBitmap(LongBitmap.or(leftHand, rightHand));
collectJoinConstraintList(leading, leftHand, rightHand, join, totalFilterBitMap, nonNullableSlotBitMap);
return ctx.root;

View File

@ -122,11 +122,19 @@ public class EliminateLogicalSelectHint extends OneRewriteRuleFactory {
context.setLeadingJoin(false);
return;
}
statementContext.addHint(hint);
context.getHintMap().put("Leading", hint);
if (hint.getTablelist().size() < 2) {
hint.setStatus(Hint.HintStatus.SYNTAX_ERROR);
context.getHintMap().get("Leading").setStatus(Hint.HintStatus.UNUSED);
hint.setErrorMessage("less than two tables is not allowed in leading clause");
statementContext.addHint(hint);
context.setLeadingJoin(false);
return;
}
if (!hint.isSyntaxError()) {
hint.setStatus(Hint.HintStatus.SUCCESS);
}
statementContext.addHint(hint);
context.getHintMap().put("Leading", hint);
if (hints.get("ordered") != null || ConnectContext.get().getSessionVariable().isDisableJoinReorder()
|| context.isLeadingDisableJoinReorder()) {
context.setLeadingJoin(false);