mirror of
https://github.com/actiontech/dble.git
synced 2026-01-28 00:09:26 -06:00
inner 1466,1477
This commit is contained in:
@@ -229,7 +229,7 @@ public abstract class BaseHandlerBuilder {
|
||||
*/
|
||||
protected void noShardBuild() {
|
||||
this.needCommon = false;
|
||||
GlobalVisitor visitor = new GlobalVisitor(node, true);
|
||||
GlobalVisitor visitor = new GlobalVisitor(node, true, false);
|
||||
visitor.visit();
|
||||
String sql = visitor.getSql().toString();
|
||||
Map<String, String> mapTableToSimple = visitor.getMapTableToSimple();
|
||||
@@ -555,8 +555,15 @@ public abstract class BaseHandlerBuilder {
|
||||
Set<String> routeNodes = HandlerBuilder.canRouteToNodes(merges);
|
||||
if (routeNodes != null && routeNodes.size() > 0) {
|
||||
this.needCommon = false;
|
||||
PushDownVisitor visitor = new PushDownVisitor(node, true);
|
||||
RouteResultset rrs = visitor.buildRouteResultset();
|
||||
GlobalVisitor visitor = new GlobalVisitor(node, true, true);
|
||||
visitor.visit();
|
||||
String sql = visitor.getSql().toString();
|
||||
Map<String, String> mapTableToSimple = visitor.getMapTableToSimple();
|
||||
for (Map.Entry<String, String> tableToSimple : mapTableToSimple.entrySet()) {
|
||||
sql = sql.replace(tableToSimple.getKey(), tableToSimple.getValue());
|
||||
}
|
||||
RouteResultset rrs = new RouteResultset(sql, ServerParse.SELECT);
|
||||
rrs.setStatement(sql);
|
||||
rrs.setComplexSQL(true);
|
||||
buildOneMergeHandler(routeNodes, rrs);
|
||||
return true;
|
||||
@@ -605,4 +612,13 @@ public abstract class BaseHandlerBuilder {
|
||||
public PlanNode getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
public boolean isExistView() {
|
||||
return subQueryBuilderList.stream().anyMatch(BaseHandlerBuilder::isExistView) || node.isExistView();
|
||||
}
|
||||
|
||||
|
||||
public boolean isContainSubQuery(PlanNode planNode) {
|
||||
return planNode.getSubQueries().size() > 0 || planNode.getChildren().stream().anyMatch(this::isContainSubQuery);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,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;
|
||||
@@ -13,15 +14,14 @@ import com.actiontech.dble.plan.node.*;
|
||||
import com.actiontech.dble.route.RouteResultsetNode;
|
||||
import com.actiontech.dble.route.util.RouterUtil;
|
||||
import com.actiontech.dble.server.NonBlockingSession;
|
||||
import com.actiontech.dble.server.parser.ServerParse;
|
||||
import com.actiontech.dble.services.factorys.FinalHandlerFactory;
|
||||
import com.actiontech.dble.singleton.TraceManager;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public class HandlerBuilder {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HandlerBuilder.class);
|
||||
@@ -79,7 +79,7 @@ public class HandlerBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
public String build() throws Exception {
|
||||
public RouteResultsetNode build() throws Exception {
|
||||
TraceManager.TraceObject traceObject = TraceManager.serviceTrace(session.getShardingService(), "build&execute-complex-sql");
|
||||
try {
|
||||
final long startTime = System.nanoTime();
|
||||
@@ -98,7 +98,7 @@ public class HandlerBuilder {
|
||||
if (endHandler.getMerges().size() == 1 && builder.getSubQueryBuilderList().size() == 0) {
|
||||
RouteResultsetNode[] routes = ((MultiNodeMergeHandler) (endHandler.getMerges().get(0))).getRoute();
|
||||
if (routes.length == 1) {
|
||||
return routes[0].getName();
|
||||
return getRouteResultsetNode(builder, routes[0].getName());
|
||||
}
|
||||
}
|
||||
HandlerBuilder.startHandler(fh);
|
||||
@@ -112,6 +112,27 @@ public class HandlerBuilder {
|
||||
return null;
|
||||
}
|
||||
|
||||
private RouteResultsetNode getRouteResultsetNode(BaseHandlerBuilder builder, String nodeName) {
|
||||
Set<String> tableSet = Sets.newHashSet();
|
||||
for (RouteResultsetNode routeResultsetNode : rrsNodes) {
|
||||
Set<String> set = routeResultsetNode.getTableSet();
|
||||
if (null != set) {
|
||||
tableSet.addAll(set);
|
||||
}
|
||||
}
|
||||
String sql = node.getSql();
|
||||
if (builder.isExistView() || builder.isContainSubQuery(node)) {
|
||||
GlobalVisitor visitor = new GlobalVisitor(node, true, true);
|
||||
visitor.visit();
|
||||
sql = visitor.getSql().toString();
|
||||
Map<String, String> mapTableToSimple = visitor.getMapTableToSimple();
|
||||
for (Map.Entry<String, String> tableToSimple : mapTableToSimple.entrySet()) {
|
||||
sql = sql.replace(tableToSimple.getKey(), tableToSimple.getValue());
|
||||
}
|
||||
}
|
||||
return new RouteResultsetNode(nodeName, ServerParse.SELECT, sql, tableSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* DBLE0REQ-504
|
||||
* According to the execution plan, judge whether it can be routed to the same node to simplify the query
|
||||
|
||||
@@ -29,8 +29,10 @@ import com.actiontech.dble.util.StringUtil;
|
||||
*/
|
||||
public class GlobalVisitor extends MysqlVisitor {
|
||||
|
||||
public GlobalVisitor(PlanNode globalQuery, boolean isTopQuery) {
|
||||
private final boolean rebuildSubQuery;
|
||||
public GlobalVisitor(PlanNode globalQuery, boolean isTopQuery, boolean rebuildSubQuery) {
|
||||
super(globalQuery, isTopQuery);
|
||||
this.rebuildSubQuery = rebuildSubQuery;
|
||||
}
|
||||
|
||||
public void visit() {
|
||||
@@ -118,7 +120,7 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
}
|
||||
sqlBuilder.append('(');
|
||||
PlanNode child = query.getChild();
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true);
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true, rebuildSubQuery);
|
||||
childVisitor.visit();
|
||||
mapTableToSimple.putAll(childVisitor.getMapTableToSimple());
|
||||
sqlBuilder.append(childVisitor.getSql()).append(") ").append(query.getAlias());
|
||||
@@ -142,7 +144,7 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
boolean isUnion = merge.isUnion();
|
||||
boolean isFirst = true;
|
||||
for (PlanNode child : merge.getChildren()) {
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true);
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true, rebuildSubQuery);
|
||||
childVisitor.visit();
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
@@ -186,7 +188,7 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
}
|
||||
|
||||
PlanNode left = join.getLeftNode();
|
||||
MysqlVisitor leftVisitor = new GlobalVisitor(left, false);
|
||||
MysqlVisitor leftVisitor = new GlobalVisitor(left, false, rebuildSubQuery);
|
||||
leftVisitor.visit();
|
||||
mapTableToSimple.putAll(leftVisitor.getMapTableToSimple());
|
||||
sqlBuilder.append(leftVisitor.getSql());
|
||||
@@ -201,7 +203,7 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
sqlBuilder.append(" join ");
|
||||
|
||||
PlanNode right = join.getRightNode();
|
||||
MysqlVisitor rightVisitor = new GlobalVisitor(right, false);
|
||||
MysqlVisitor rightVisitor = new GlobalVisitor(right, false, rebuildSubQuery);
|
||||
rightVisitor.visit();
|
||||
mapTableToSimple.putAll(rightVisitor.getMapTableToSimple());
|
||||
sqlBuilder.append(rightVisitor.getSql());
|
||||
@@ -328,7 +330,12 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
protected String visitPushDownNameSel(Item item) {
|
||||
String orgPushDownName;
|
||||
if (item.isWithSubQuery()) {
|
||||
orgPushDownName = buildSubQueryItem(item, false);
|
||||
if (rebuildSubQuery) {
|
||||
Item tmpItem = PlanUtil.rebuildSubQueryItem(item);
|
||||
orgPushDownName = tmpItem.getItemName();
|
||||
} else {
|
||||
orgPushDownName = buildSubQueryItem(item, false);
|
||||
}
|
||||
} else {
|
||||
orgPushDownName = item.getItemName();
|
||||
}
|
||||
@@ -364,7 +371,12 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
// pushDown's name of not in select list
|
||||
protected final String visitUnSelPushDownName(Item item, boolean canUseAlias) {
|
||||
if (item.isWithSubQuery()) {
|
||||
return buildSubQueryItem(item, canUseAlias);
|
||||
if (rebuildSubQuery) {
|
||||
Item tmpItem = PlanUtil.rebuildSubQueryItem(item);
|
||||
return tmpItem.getItemName();
|
||||
} else {
|
||||
return buildSubQueryItem(item, canUseAlias);
|
||||
}
|
||||
}
|
||||
String selName = getItemName(item);
|
||||
String nameInMap = pushNameMap.get(selName);
|
||||
@@ -394,7 +406,7 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
}
|
||||
builder.append(" in ");
|
||||
PlanNode child = inSubItem.getPlanNode();
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true);
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true, rebuildSubQuery);
|
||||
childVisitor.visit();
|
||||
builder.append("(");
|
||||
builder.append(childVisitor.getSql());
|
||||
@@ -409,7 +421,7 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
}
|
||||
builder.append(" exists ");
|
||||
PlanNode child = existsSubQuery.getPlanNode();
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true);
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true, rebuildSubQuery);
|
||||
childVisitor.visit();
|
||||
builder.append("(");
|
||||
builder.append(childVisitor.getSql());
|
||||
@@ -439,7 +451,7 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
|
||||
private String buildScalarSubQuery(ItemScalarSubQuery item) {
|
||||
PlanNode child = item.getPlanNode();
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true);
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true, rebuildSubQuery);
|
||||
childVisitor.visit();
|
||||
mapTableToSimple.putAll(childVisitor.getMapTableToSimple());
|
||||
return "(" + childVisitor.getSql() + ")";
|
||||
@@ -464,7 +476,7 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
builder.append(" any ");
|
||||
}
|
||||
PlanNode child = allAnySubItem.getPlanNode();
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true);
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true, rebuildSubQuery);
|
||||
childVisitor.visit();
|
||||
builder.append("(");
|
||||
builder.append(childVisitor.getSql());
|
||||
|
||||
@@ -113,7 +113,7 @@ public class PushDownVisitor extends MysqlVisitor {
|
||||
}
|
||||
|
||||
PlanNode left = join.getLeftNode();
|
||||
MysqlVisitor leftVisitor = new GlobalVisitor(left, false);
|
||||
MysqlVisitor leftVisitor = new GlobalVisitor(left, false, true);
|
||||
leftVisitor.visit();
|
||||
mapTableToSimple.putAll(leftVisitor.getMapTableToSimple());
|
||||
replaceableSqlBuilder.append(leftVisitor.getSql());
|
||||
@@ -129,7 +129,7 @@ public class PushDownVisitor extends MysqlVisitor {
|
||||
sqlBuilder.append(" join ");
|
||||
|
||||
PlanNode right = join.getRightNode();
|
||||
MysqlVisitor rightVisitor = new GlobalVisitor(right, false);
|
||||
MysqlVisitor rightVisitor = new GlobalVisitor(right, false, true);
|
||||
rightVisitor.visit();
|
||||
mapTableToSimple.putAll(rightVisitor.getMapTableToSimple());
|
||||
replaceableSqlBuilder.append(rightVisitor.getSql());
|
||||
@@ -156,7 +156,7 @@ public class PushDownVisitor extends MysqlVisitor {
|
||||
boolean isUnion = merge.isUnion();
|
||||
boolean isFirst = true;
|
||||
for (PlanNode child : merge.getChildren()) {
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true);
|
||||
MysqlVisitor childVisitor = new GlobalVisitor(child, true, true);
|
||||
childVisitor.visit();
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.actiontech.dble.backend.datasource.ShardingNode;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.*;
|
||||
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.OutputHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.transaction.ImplicitCommitHandler;
|
||||
@@ -42,7 +41,6 @@ import com.actiontech.dble.server.status.LoadDataBatch;
|
||||
import com.actiontech.dble.server.status.SlowQueryLog;
|
||||
import com.actiontech.dble.server.trace.TraceRecord;
|
||||
import com.actiontech.dble.server.trace.TraceResult;
|
||||
import com.actiontech.dble.util.exception.NeedDelayedException;
|
||||
import com.actiontech.dble.services.mysqlsharding.MySQLResponseService;
|
||||
import com.actiontech.dble.services.mysqlsharding.ShardingService;
|
||||
import com.actiontech.dble.singleton.DDLTraceManager;
|
||||
@@ -52,10 +50,9 @@ import com.actiontech.dble.singleton.TraceManager;
|
||||
import com.actiontech.dble.statistic.sql.StatisticListener;
|
||||
import com.actiontech.dble.statistic.stat.QueryTimeCost;
|
||||
import com.actiontech.dble.statistic.stat.QueryTimeCostContainer;
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
import com.actiontech.dble.util.exception.NeedDelayedException;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -606,26 +603,9 @@ public class NonBlockingSession extends Session {
|
||||
init();
|
||||
HandlerBuilder builder = new HandlerBuilder(node, this);
|
||||
try {
|
||||
String nodeName = builder.build();
|
||||
if (!StringUtil.isBlank(nodeName)) {
|
||||
Set<String> tableSet = Sets.newHashSet();
|
||||
for (RouteResultsetNode routeResultsetNode : builder.getRrsNodes()) {
|
||||
Set<String> set = routeResultsetNode.getTableSet();
|
||||
if (null != set) {
|
||||
tableSet.addAll(set);
|
||||
}
|
||||
}
|
||||
String sql = node.getSql();
|
||||
if (node.isExistView()) {
|
||||
GlobalVisitor visitor = new GlobalVisitor(node, true);
|
||||
visitor.visit();
|
||||
sql = visitor.getSql().toString();
|
||||
Map<String, String> mapTableToSimple = visitor.getMapTableToSimple();
|
||||
for (Map.Entry<String, String> tableToSimple : mapTableToSimple.entrySet()) {
|
||||
sql = sql.replace(tableToSimple.getKey(), tableToSimple.getValue());
|
||||
}
|
||||
}
|
||||
RouteResultsetNode[] nodes = {new RouteResultsetNode(nodeName, rrs.getSqlType(), sql, tableSet)};
|
||||
RouteResultsetNode rrsNode = builder.build();
|
||||
if (rrsNode != null) {
|
||||
RouteResultsetNode[] nodes = {rrsNode};
|
||||
rrs.setNodes(nodes);
|
||||
setRouteResultToTrace(nodes);
|
||||
// dml or simple select
|
||||
|
||||
@@ -239,8 +239,8 @@ public final class ExplainHandler {
|
||||
if (!StringUtil.isBlank(routeNode)) {
|
||||
PlanNode node = builder.getNode();
|
||||
String sql = node.getSql();
|
||||
if (node.isExistView()) {
|
||||
GlobalVisitor visitor = new GlobalVisitor(node, true);
|
||||
if (builder.isExistView() || builder.isContainSubQuery(node)) {
|
||||
GlobalVisitor visitor = new GlobalVisitor(node, true, true);
|
||||
visitor.visit();
|
||||
sql = visitor.getSql().toString();
|
||||
Map<String, String> mapTableToSimple = visitor.getMapTableToSimple();
|
||||
|
||||
Reference in New Issue
Block a user