From 1ba473ac4645bb9c6c0aa369ed77f7603afcdce9 Mon Sep 17 00:00:00 2001 From: wenyh <44251917+wenyh1@users.noreply.github.com> Date: Mon, 14 Mar 2022 16:39:32 +0800 Subject: [PATCH] [inner-1674] fix: nestloop scenarios's bug (#3172) --- .../nio/handler/builder/HandlerBuilder.java | 18 ++++++++++++++---- .../dble/server/handler/ExplainHandler.java | 17 ++++++++++++++++- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/builder/HandlerBuilder.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/builder/HandlerBuilder.java index d0f5b23d3..beaa3f2da 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/builder/HandlerBuilder.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/builder/HandlerBuilder.java @@ -7,9 +7,7 @@ package com.actiontech.dble.backend.mysql.nio.handler.builder; import com.actiontech.dble.backend.mysql.nio.handler.builder.sqlvisitor.GlobalVisitor; import com.actiontech.dble.backend.mysql.nio.handler.query.DMLResponseHandler; -import com.actiontech.dble.backend.mysql.nio.handler.query.impl.BaseSelectHandler; -import com.actiontech.dble.backend.mysql.nio.handler.query.impl.MultiNodeEasyMergeHandler; -import com.actiontech.dble.backend.mysql.nio.handler.query.impl.MultiNodeMergeHandler; +import com.actiontech.dble.backend.mysql.nio.handler.query.impl.*; import com.actiontech.dble.plan.node.*; import com.actiontech.dble.route.RouteResultsetNode; import com.actiontech.dble.route.util.RouterUtil; @@ -111,10 +109,22 @@ public class HandlerBuilder { return null; } + public boolean canAsWholeToSingle(List merges) { + if (merges.size() != 1) + return false; + DMLResponseHandler next = merges.get(0).getNextHandler(); + while (next != null) { + if (next instanceof TempTableHandler || next instanceof DelayTableHandler) + return false; + next = next.getNextHandler(); + } + return true; + } + // check whether the SQL can be directly sent to a single node private RouteResultsetNode getTryRouteSingleNode(BaseHandlerBuilder builder, boolean isHaveHintPlan2Inner) { RouteResultsetNode routeNode = null; - if (builder.getEndHandler().getMerges().size() == 1 && builder.getSubQueryBuilderList().size() == 0) { + if (canAsWholeToSingle(builder.getEndHandler().getMerges()) && builder.getSubQueryBuilderList().size() == 0) { RouteResultsetNode[] routes = ((MultiNodeMergeHandler) (builder.getEndHandler().getMerges().get(0))).getRoute(); if (routes.length == 1) { routeNode = routes[0]; diff --git a/src/main/java/com/actiontech/dble/server/handler/ExplainHandler.java b/src/main/java/com/actiontech/dble/server/handler/ExplainHandler.java index f8ab8a4c4..fc5be1f6e 100644 --- a/src/main/java/com/actiontech/dble/server/handler/ExplainHandler.java +++ b/src/main/java/com/actiontech/dble/server/handler/ExplainHandler.java @@ -10,7 +10,10 @@ import com.actiontech.dble.backend.mysql.PacketUtil; import com.actiontech.dble.backend.mysql.nio.handler.builder.BaseHandlerBuilder; import com.actiontech.dble.backend.mysql.nio.handler.builder.HandlerBuilder; import com.actiontech.dble.backend.mysql.nio.handler.builder.sqlvisitor.GlobalVisitor; +import com.actiontech.dble.backend.mysql.nio.handler.query.DMLResponseHandler; +import com.actiontech.dble.backend.mysql.nio.handler.query.impl.DelayTableHandler; import com.actiontech.dble.backend.mysql.nio.handler.query.impl.MultiNodeMergeHandler; +import com.actiontech.dble.backend.mysql.nio.handler.query.impl.TempTableHandler; import com.actiontech.dble.config.ErrorCode; import com.actiontech.dble.config.Fields; import com.actiontech.dble.config.model.sharding.SchemaConfig; @@ -202,10 +205,22 @@ public final class ExplainHandler { return false; } + public static boolean canAsWholeToSingle(List merges) { + if (merges.size() != 1) + return false; + DMLResponseHandler next = merges.get(0).getNextHandler(); + while (next != null) { + if (next instanceof TempTableHandler || next instanceof DelayTableHandler) + return false; + next = next.getNextHandler(); + } + return true; + } + // check whether the SQL can be directly sent to a single node private static RouteResultsetNode getTryRouteSingleNode(BaseHandlerBuilder builder, RouteResultset rrs) { RouteResultsetNode routeNode = null; - if (builder.getEndHandler().getMerges().size() == 1 && builder.getSubQueryBuilderList().size() == 0) { + if (canAsWholeToSingle(builder.getEndHandler().getMerges()) && builder.getSubQueryBuilderList().size() == 0) { RouteResultsetNode[] routes = ((MultiNodeMergeHandler) (builder.getEndHandler().getMerges().get(0))).getRoute(); if (routes.length == 1) { routeNode = routes[0];