explain for subquery

This commit is contained in:
yanhuqing
2017-10-27 00:05:16 +08:00
parent 078a7dd079
commit a78b8a100a
18 changed files with 195 additions and 77 deletions
@@ -43,7 +43,6 @@ import org.apache.log4j.Logger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -53,7 +52,7 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
abstract class BaseHandlerBuilder {
public abstract class BaseHandlerBuilder {
private static final Logger LOGGER = Logger.getLogger(BaseHandlerBuilder.class);
private static AtomicLong sequenceId = new AtomicLong(0);
protected NonBlockingSession session;
@@ -73,7 +72,7 @@ abstract class BaseHandlerBuilder {
protected boolean needSendMaker = true;
protected boolean isExplain = false;
protected List<DMLResponseHandler> endHandlerList = new ArrayList<>(1);
protected List<BaseHandlerBuilder> subQueryBuilderList = new ArrayList<>(1);
protected BaseHandlerBuilder(NonBlockingSession session, PlanNode node, HandlerBuilder hBuilder, boolean isExplain) {
this.session = session;
@@ -89,8 +88,8 @@ abstract class BaseHandlerBuilder {
return currentLast;
}
public List<DMLResponseHandler> getEndHandlerList() {
return endHandlerList;
public List<BaseHandlerBuilder> getSubQueryBuilderList() {
return subQueryBuilderList;
}
/**
@@ -438,13 +437,25 @@ abstract class BaseHandlerBuilder {
for (ItemSubQuery itemSubQuery : node.getSubQueries()) {
if (itemSubQuery instanceof ItemSingleRowSubQuery) {
final SubQueryHandler tempHandler = new SingleRowSubQueryHandler(getSequenceId(), session, (ItemSingleRowSubQuery) itemSubQuery);
handleSubQuery(lock, finishSubQuery, finished, subNodes, errorPackets, itemSubQuery.getPlanNode(), tempHandler);
if (isExplain) {
handleSubQueryForExplain(lock, finishSubQuery, finished, subNodes, itemSubQuery.getPlanNode(), tempHandler);
} else {
handleSubQuery(lock, finishSubQuery, finished, subNodes, errorPackets, itemSubQuery.getPlanNode(), tempHandler);
}
} else if (itemSubQuery instanceof ItemInSubQuery) {
final SubQueryHandler tempHandler = new InSubQueryHandler(getSequenceId(), session, (ItemInSubQuery) itemSubQuery);
handleSubQuery(lock, finishSubQuery, finished, subNodes, errorPackets, itemSubQuery.getPlanNode(), tempHandler);
if (isExplain) {
handleSubQueryForExplain(lock, finishSubQuery, finished, subNodes, itemSubQuery.getPlanNode(), tempHandler);
} else {
handleSubQuery(lock, finishSubQuery, finished, subNodes, errorPackets, itemSubQuery.getPlanNode(), tempHandler);
}
} else if (itemSubQuery instanceof ItemAllAnySubQuery) {
final SubQueryHandler tempHandler = new AllAnySubQueryHandler(getSequenceId(), session, (ItemAllAnySubQuery) itemSubQuery);
handleSubQuery(lock, finishSubQuery, finished, subNodes, errorPackets, itemSubQuery.getPlanNode(), tempHandler);
if (isExplain) {
handleSubQueryForExplain(lock, finishSubQuery, finished, subNodes, itemSubQuery.getPlanNode(), tempHandler);
} else {
handleSubQuery(lock, finishSubQuery, finished, subNodes, errorPackets, itemSubQuery.getPlanNode(), tempHandler);
}
}
}
lock.lock();
@@ -467,33 +478,35 @@ abstract class BaseHandlerBuilder {
}
}
private void handleSubQueryForExplain(final ReentrantLock lock, final Condition finishSubQuery, final AtomicBoolean finished,
final AtomicInteger subNodes, final PlanNode planNode, final SubQueryHandler tempHandler) {
tempHandler.setForExplain();
BaseHandlerBuilder builder = hBuilder.getBuilder(session, planNode, true);
DMLResponseHandler endHandler = builder.getEndHandler();
endHandler.setNextHandler(tempHandler);
this.getSubQueryBuilderList().add(builder);
subQueryFinished(subNodes, lock, finished, finishSubQuery);
return;
}
private void handleSubQuery(final ReentrantLock lock, final Condition finishSubQuery, final AtomicBoolean finished,
final AtomicInteger subNodes, final CopyOnWriteArrayList<ErrorPacket> errorPackets, final PlanNode planNode, final SubQueryHandler tempHandler) {
DbleServer.getInstance().getComplexQueryExecutor().execute(new Runnable() {
@Override
public void run() {
try {
DMLResponseHandler endHandler = hBuilder.buildNode(session, planNode);
DMLResponseHandler endHandler = hBuilder.buildNode(session, planNode, false);
endHandler.setNextHandler(tempHandler);
HandlerBuilder.startHandler(endHandler);
CallBackHandler tempDone = new CallBackHandler() {
@Override
public void call() throws Exception {
if (tempHandler.getErrorPacket() != null) {
errorPackets.add(tempHandler.getErrorPacket());
}
if (subNodes.decrementAndGet() == 0) {
lock.lock();
try {
finished.set(true);
finishSubQuery.signal();
} finally {
lock.unlock();
}
}
subQueryFinished(subNodes, lock, finished, finishSubQuery);
}
};
tempHandler.setTempDoneCallBack(tempDone);
HandlerBuilder.startHandler(endHandler);
} catch (Exception e) {
LOGGER.warn("execute ItemScalarSubQuery error", e);
ErrorPacket errorPackage = new ErrorPacket();
@@ -506,4 +519,16 @@ abstract class BaseHandlerBuilder {
});
}
private void subQueryFinished(AtomicInteger subNodes, ReentrantLock lock, AtomicBoolean finished, Condition finishSubQuery) {
if (subNodes.decrementAndGet() == 0) {
lock.lock();
try {
finished.set(true);
finishSubQuery.signal();
} finally {
lock.unlock();
}
}
}
}
@@ -15,7 +15,6 @@ import com.actiontech.dble.server.NonBlockingSession;
import org.apache.log4j.Logger;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class HandlerBuilder {
@@ -55,22 +54,20 @@ public class HandlerBuilder {
* @param planNode
* @return
*/
public DMLResponseHandler buildNode(NonBlockingSession nonBlockingSession, PlanNode planNode) {
BaseHandlerBuilder builder = createBuilder(nonBlockingSession, planNode, false);
builder.build();
public DMLResponseHandler buildNode(NonBlockingSession nonBlockingSession, PlanNode planNode, boolean isExplain) {
BaseHandlerBuilder builder = getBuilder(nonBlockingSession, planNode, isExplain);
return builder.getEndHandler();
}
public List<DMLResponseHandler> buildNodes(NonBlockingSession nonBlockingSession, PlanNode planNode) {
BaseHandlerBuilder builder = createBuilder(nonBlockingSession, planNode, true);
public BaseHandlerBuilder getBuilder(NonBlockingSession nonBlockingSession, PlanNode planNode, boolean isExplain) {
BaseHandlerBuilder builder = createBuilder(nonBlockingSession, planNode, isExplain);
builder.build();
builder.getEndHandlerList().add(builder.getEndHandler());
return builder.getEndHandlerList();
return builder;
}
public void build(boolean hasNext) throws Exception {
final long startTime = System.nanoTime();
DMLResponseHandler endHandler = buildNode(session, node);
DMLResponseHandler endHandler = buildNode(session, node, false);
OutputHandler fh = new OutputHandler(BaseHandlerBuilder.getSequenceId(), session, hasNext);
endHandler.setNextHandler(fh);
HandlerBuilder.startHandler(fh);
@@ -126,7 +126,7 @@ class JoinNodeHandlerBuilder extends BaseHandlerBuilder {
}
private DMLResponseHandler buildJoinChild(PlanNode child, boolean isLeft) {
DMLResponseHandler endHandler = hBuilder.buildNode(session, child);
DMLResponseHandler endHandler = hBuilder.buildNode(session, child, isExplain);
if (isLeft) {
if (!node.isLeftOrderMatch()) {
OrderByHandler oh = new OrderByHandler(getSequenceId(), session, node.getLeftJoinOnOrders());
@@ -31,7 +31,7 @@ class MergeNodeHandlerBuilder extends BaseHandlerBuilder {
protected List<DMLResponseHandler> buildPre() {
List<DMLResponseHandler> pres = new ArrayList<>();
for (PlanNode child : node.getChildren()) {
DMLResponseHandler ch = hBuilder.buildNode(session, child);
DMLResponseHandler ch = hBuilder.buildNode(session, child, isExplain);
pres.add(ch);
}
return pres;
@@ -31,7 +31,7 @@ class QueryNodeHandlerBuilder extends BaseHandlerBuilder {
public List<DMLResponseHandler> buildPre() {
List<DMLResponseHandler> pres = new ArrayList<>();
PlanNode subNode = node.getChild();
DMLResponseHandler subHandler = hBuilder.buildNode(session, subNode);
DMLResponseHandler subHandler = hBuilder.buildNode(session, subNode, isExplain);
pres.add(subHandler);
return pres;
}
@@ -13,6 +13,7 @@ import com.actiontech.dble.net.mysql.RowDataPacket;
import com.actiontech.dble.plan.Order;
import com.actiontech.dble.plan.common.field.Field;
import com.actiontech.dble.plan.common.item.Item;
import com.actiontech.dble.plan.common.item.ItemString;
import com.actiontech.dble.plan.common.item.subquery.ItemAllAnySubQuery;
import com.actiontech.dble.server.NonBlockingSession;
@@ -129,5 +130,42 @@ public class AllAnySubQueryHandler extends SubQueryHandler {
}
@Override
public void setForExplain() {
switch (itemSubQuery.getOperator()) {
case Equality:
if (itemSubQuery.isAll()) {
itemSubQuery.getValue().add(new ItemString("{ALL_SUB_QUERY_RESULTS}"));
}
break;
case NotEqual:
case LessThanOrGreater:
if (!itemSubQuery.isAll()) {
itemSubQuery.getValue().add(new ItemString("{ALL_SUB_QUERY_RESULTS}"));
}
break;
case LessThan:
case LessThanOrEqual:
if (itemSubQuery.isAll()) {
//row < tmpRow
itemSubQuery.getValue().add(new ItemString("{MIN_SUB_QUERY_RESULTS}"));
} else if (!itemSubQuery.isAll()) {
//row > tmpRow
itemSubQuery.getValue().add(new ItemString("{MAX_SUB_QUERY_RESULTS}"));
}
break;
case GreaterThan:
case GreaterThanOrEqual:
if (itemSubQuery.isAll()) {
//row > tmpRow
itemSubQuery.getValue().add(new ItemString("{MAX_SUB_QUERY_RESULTS}"));
} else if (!itemSubQuery.isAll()) {
//row < tmpRow
itemSubQuery.getValue().add(new ItemString("{MIN_SUB_QUERY_RESULTS}"));
}
break;
default:
break;
}
}
}
@@ -13,12 +13,15 @@ import com.actiontech.dble.net.mysql.FieldPacket;
import com.actiontech.dble.net.mysql.RowDataPacket;
import com.actiontech.dble.plan.common.field.Field;
import com.actiontech.dble.plan.common.item.Item;
import com.actiontech.dble.plan.common.item.ItemString;
import com.actiontech.dble.plan.common.item.subquery.ItemInSubQuery;
import com.actiontech.dble.server.NonBlockingSession;
import java.util.Collections;
import java.util.List;
import static com.actiontech.dble.plan.optimizer.JoinStrategyProcessor.NEED_REPLACE;
public class InSubQueryHandler extends SubQueryHandler {
private int maxPartSize = 2000;
private int maxConnSize = 4;
@@ -95,4 +98,8 @@ public class InSubQueryHandler extends SubQueryHandler {
return HandlerType.IN_SUB_QUERY;
}
@Override
public void setForExplain() {
itemSubQuery.getValue().add(new ItemString(NEED_REPLACE));
}
}
@@ -12,12 +12,15 @@ import com.actiontech.dble.net.mysql.FieldPacket;
import com.actiontech.dble.net.mysql.RowDataPacket;
import com.actiontech.dble.plan.common.field.Field;
import com.actiontech.dble.plan.common.item.Item;
import com.actiontech.dble.plan.common.item.ItemString;
import com.actiontech.dble.plan.common.item.subquery.ItemSingleRowSubQuery;
import com.actiontech.dble.server.NonBlockingSession;
import java.util.Collections;
import java.util.List;
import static com.actiontech.dble.plan.optimizer.JoinStrategyProcessor.NEED_REPLACE;
public class SingleRowSubQueryHandler extends SubQueryHandler {
private int rowCount = 0;
private Field sourceField;
@@ -88,4 +91,9 @@ public class SingleRowSubQueryHandler extends SubQueryHandler {
Item tmpItem = HandlerTool.createItem(select, Collections.singletonList(this.sourceField), 0, isAllPushDown(), type());
itemSubQuery.setValue(tmpItem);
}
@Override
public void setForExplain() {
itemSubQuery.setValue(new ItemString(NEED_REPLACE));
}
}
@@ -22,6 +22,7 @@ public abstract class SubQueryHandler extends BaseDMLHandler {
protected final ReentrantLock lock;
protected CallBackHandler tempDoneCallBack;
protected ErrorPacket errorPacket;
public abstract void setForExplain();
public SubQueryHandler(long id, NonBlockingSession session) {
super(id, session);
this.lock = new ReentrantLock();
@@ -10,6 +10,8 @@ package com.actiontech.dble.plan.common.item.subquery;
import com.actiontech.dble.config.ErrorCode;
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
import com.actiontech.dble.plan.common.field.Field;
import com.actiontech.dble.plan.common.item.Item;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLAllExpr;
import com.alibaba.druid.sql.ast.expr.SQLAnyExpr;
@@ -17,6 +19,8 @@ import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import java.util.List;
public class ItemAllAnySubQuery extends ItemMultiRowSubQuery {
private boolean isAll;
private SQLBinaryOperator operator;
@@ -46,6 +50,11 @@ public class ItemAllAnySubQuery extends ItemMultiRowSubQuery {
}
}
@Override
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fields) {
return new ItemAllAnySubQuery(this.currentDb, this.operator, this.query, this.isAll);
}
public boolean isAll() {
return isAll;
}
@@ -76,7 +76,7 @@ public class ItemExistsSubQuery extends ItemSingleRowSubQuery {
@Override
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fields) {
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "unexpected!");
return new ItemExistsSubQuery(this.currentDb, this.query, this.isNot);
}
@Override
public SubSelectType subType() {
@@ -3,24 +3,25 @@
* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
*/
/**
*
*/
package com.actiontech.dble.plan.common.item.subquery;
import com.actiontech.dble.config.ErrorCode;
import com.actiontech.dble.plan.common.context.NameResolutionContext;
import com.actiontech.dble.plan.common.context.ReferContext;
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
import com.actiontech.dble.plan.common.field.Field;
import com.actiontech.dble.plan.common.item.Item;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import java.util.List;
public class ItemInSubQuery extends ItemMultiRowSubQuery {
private boolean isNeg;
protected Item leftOperand;
public ItemInSubQuery(String currentDb, Item leftOperand, SQLSelectQuery query, boolean isNeg) {
super(currentDb, query);
this.leftOperand = leftOperand;
@@ -62,6 +63,11 @@ public class ItemInSubQuery extends ItemMultiRowSubQuery {
return inSub;
}
@Override
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fields) {
return new ItemInSubQuery(this.currentDb, this.leftOperand.cloneItem(), this.query, this.isNeg);
}
public Item getLeftOperand() {
return leftOperand;
}
@@ -10,7 +10,6 @@ package com.actiontech.dble.plan.common.item.subquery;
import com.actiontech.dble.config.ErrorCode;
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
import com.actiontech.dble.plan.common.field.Field;
import com.actiontech.dble.plan.common.item.Item;
import com.actiontech.dble.plan.common.time.MySQLTime;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
@@ -66,10 +65,6 @@ public abstract class ItemMultiRowSubQuery extends ItemSubQuery {
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support yet!");
}
@Override
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fields) {
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "unexpected!");
}
public Item getSelect() {
@@ -52,7 +52,7 @@ public class ItemScalarSubQuery extends ItemSingleRowSubQuery {
@Override
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fieldList) {
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "unexpected!");
return new ItemScalarSubQuery(this.currentDb, this.query);
}
@@ -5,16 +5,12 @@
package com.actiontech.dble.plan.common.item.subquery;
import com.actiontech.dble.config.ErrorCode;
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
import com.actiontech.dble.plan.common.field.Field;
import com.actiontech.dble.plan.common.item.Item;
import com.actiontech.dble.plan.common.time.MySQLTime;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
public abstract class ItemSingleRowSubQuery extends ItemSubQuery {
protected Item value;
@@ -117,11 +113,6 @@ public abstract class ItemSingleRowSubQuery extends ItemSubQuery {
}
@Override
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fieldList) {
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "unexpected!");
}
/*--------------------------------------getter/setter-----------------------------------*/
public Item getValue() {
@@ -19,7 +19,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
public abstract class ItemSubQuery extends ItemResultField {
protected SQLSelectQuery query;
private String currentDb;
protected String currentDb;
protected PlanNode planNode;
public enum SubSelectType {
@@ -120,7 +120,11 @@ public final class GlobalTableProcessor {
}
}
if (tn.getNoshardNode() != null) {
tn.getNoshardNode().retainAll(tnChild.getNoshardNode());
if (tnChild.getNoshardNode() != null) {
tn.getNoshardNode().retainAll(tnChild.getNoshardNode());
} else {
tn.setNoshardNode(null);
}
}
}
@@ -7,6 +7,7 @@ package com.actiontech.dble.server.handler;
import com.actiontech.dble.DbleServer;
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.query.DMLResponseHandler;
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.*;
@@ -14,6 +15,9 @@ import com.actiontech.dble.backend.mysql.nio.handler.query.impl.groupby.DirectGr
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.groupby.OrderedGroupByHandler;
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.join.JoinHandler;
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.join.NotInHandler;
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.subquery.AllAnySubQueryHandler;
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.subquery.InSubQueryHandler;
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.subquery.SingleRowSubQueryHandler;
import com.actiontech.dble.config.ErrorCode;
import com.actiontech.dble.config.Fields;
import com.actiontech.dble.config.model.SchemaConfig;
@@ -114,24 +118,51 @@ public final class ExplainHandler {
}
private static List<String[]> getComplexQueryResult(RouteResultset rrs, ServerConnection c) {
List<DMLResponseHandler> endHandlers = buildNodes(rrs, c);
if (endHandlers.size() == 1) {
DMLResponseHandler endHandler = endHandlers.get(0);
Map<String, RefHandlerInfo> refMap = new HashMap<>();
String rootName = buildHandlerTree(endHandler, refMap, new HashMap<DMLResponseHandler, RefHandlerInfo>(), new HashMap<String, Integer>(), null);
List<RefHandlerInfo> resultList = new ArrayList<>(refMap.size());
getDFSHandlers(refMap, rootName, resultList);
List<String[]> result = new ArrayList<>();
for (int i = resultList.size() - 1; i >= 0; i--) {
RefHandlerInfo handlerInfo = resultList.get(i);
result.add(new String[]{handlerInfo.name, handlerInfo.type, handlerInfo.getRefOrSQL()});
List<BaseHandlerBuilder> builderList = getBaseHandlerBuilders(rrs, c);
Map<String, Integer> nameMap = new HashMap<>();
List<String[]> result = new ArrayList<>();
Map<BaseHandlerBuilder, String> builderNameMap = new HashMap<>();
for (int i = builderList.size() - 1; i >= 0; i--) {
BaseHandlerBuilder tmpBuilder = builderList.get(i);
Set<String> subQueries = new LinkedHashSet<>();
for (BaseHandlerBuilder childBuilder : tmpBuilder.getSubQueryBuilderList()) {
subQueries.add(builderNameMap.get(childBuilder));
}
return result;
String subQueryRootName = buildResultByEndHandler(subQueries, result, tmpBuilder.getEndHandler(), nameMap);
builderNameMap.put(tmpBuilder, subQueryRootName);
}
return null;
return result;
}
private static String buildHandlerTree(DMLResponseHandler endHandler, Map<String, RefHandlerInfo> refMap, Map<DMLResponseHandler, RefHandlerInfo> handlerMap, Map<String, Integer> nameMap, String brotherName) {
private static List<BaseHandlerBuilder> getBaseHandlerBuilders(RouteResultset rrs, ServerConnection c) {
BaseHandlerBuilder builder = buildNodes(rrs, c);
Queue<BaseHandlerBuilder> queue = new LinkedList<>();
queue.add(builder);
List<BaseHandlerBuilder> builderList = new ArrayList<>();
while (queue.size() > 0) {
BaseHandlerBuilder rootBuilder = queue.poll();
builderList.add(rootBuilder);
if (rootBuilder.getSubQueryBuilderList().size() > 0) {
queue.addAll(rootBuilder.getSubQueryBuilderList());
}
}
return builderList;
}
private static String buildResultByEndHandler(Set<String> subQueries, List<String[]> result, DMLResponseHandler endHandler, Map<String, Integer> nameMap) {
Map<String, RefHandlerInfo> refMap = new HashMap<>();
String rootName = buildHandlerTree(endHandler, refMap, new HashMap<DMLResponseHandler, RefHandlerInfo>(), nameMap, subQueries);
List<RefHandlerInfo> resultList = new ArrayList<>(refMap.size());
getDFSHandlers(refMap, rootName, resultList);
for (int i = resultList.size() - 1; i >= 0; i--) {
RefHandlerInfo handlerInfo = resultList.get(i);
result.add(new String[]{handlerInfo.name, handlerInfo.type, handlerInfo.getRefOrSQL()});
}
return rootName;
}
private static String buildHandlerTree(DMLResponseHandler endHandler, Map<String, RefHandlerInfo> refMap, Map<DMLResponseHandler, RefHandlerInfo> handlerMap, Map<String, Integer> nameMap, Set<String> dependencies) {
String rootName = null;
for (DMLResponseHandler startHandler : endHandler.getMerges()) {
MultiNodeMergeHandler mergeHandler = (MultiNodeMergeHandler) startHandler;
@@ -146,13 +177,13 @@ public final class ExplainHandler {
String dateNode = rrss.getName() + "." + rrss.getMultiplexNum();
refInfo.addChild(dateNode);
String type = "BASE SQL";
if (brotherName != null) {
if (dependencies != null && dependencies.size() > 0) {
type += "(May No Need)";
}
RefHandlerInfo baseSQLInfo = new RefHandlerInfo(dateNode, type, rrss.getStatement());
refMap.put(dateNode, baseSQLInfo);
if (brotherName != null) {
baseSQLInfo.addBrother(brotherName);
if (dependencies != null && dependencies.size() > 0) {
baseSQLInfo.addAllStepChildren(dependencies);
}
}
String mergeRootName = getAllNodesFromLeaf(mergeHandler, refMap, handlerMap, nameMap);
@@ -204,7 +235,7 @@ public final class ExplainHandler {
TempTableHandler tmp = (TempTableHandler) handler;
DMLResponseHandler endHandler = tmp.getCreatedHandler();
endHandler.setNextHandler(nextHandler);
buildHandlerTree(endHandler, refMap, handlerMap, nameMap, childName + "'s RESULTS add to QUERY's WHERE");
buildHandlerTree(endHandler, refMap, handlerMap, nameMap, Collections.singleton(childName + "'s RESULTS"));
}
handler = nextHandler;
nextHandler = skipSendMake(nextHandler.getNextHandler());
@@ -257,11 +288,17 @@ public final class ExplainHandler {
return "DIRECT_GROUP";
} else if (handler instanceof TempTableHandler) {
return "NEST_LOOP";
} else if (handler instanceof InSubQueryHandler) {
return "IN_SUB_QUERY";
} else if (handler instanceof AllAnySubQueryHandler) {
return "ALL_ANY_SUB_QUERY";
} else if (handler instanceof SingleRowSubQueryHandler) {
return "SCALAR_SUB_QUERY";
}
return "OTHER";
}
private static List<DMLResponseHandler> buildNodes(RouteResultset rrs, ServerConnection c) {
private static BaseHandlerBuilder buildNodes(RouteResultset rrs, ServerConnection c) {
SQLSelectStatement ast = (SQLSelectStatement) rrs.getSqlStatement();
MySQLPlanNodeVisitor visitor = new MySQLPlanNodeVisitor(c.getSchema(), c.getCharset().getResultsIndex());
visitor.visit(ast);
@@ -270,7 +307,7 @@ public final class ExplainHandler {
node.setUpFields();
node = MyOptimizer.optimize(node);
HandlerBuilder builder = new HandlerBuilder(node, c.getSession2());
return builder.buildNodes(c.getSession2(), node);
return builder.getBuilder(c.getSession2(), node, true);
}
private static RowDataPacket getRow(RouteResultsetNode node, String charset) {
@@ -341,7 +378,7 @@ public final class ExplainHandler {
private String type;
private String baseSQL;
private Set<String> children = new LinkedHashSet<>();
private Set<String> brothers = new LinkedHashSet<>();
private Set<String> stepChildren = new LinkedHashSet<>();
RefHandlerInfo(String name, String type, String baseSQL) {
this(name, type);
@@ -354,7 +391,7 @@ public final class ExplainHandler {
String getRefOrSQL() {
StringBuilder names = new StringBuilder("");
for (String child : brothers) {
for (String child : stepChildren) {
if (names.length() > 0) {
names.append("; ");
}
@@ -380,8 +417,8 @@ public final class ExplainHandler {
return children;
}
void addBrother(String brother) {
this.brothers.add(brother);
void addAllStepChildren(Set<String> dependencies) {
this.stepChildren.addAll(dependencies);
}
void addChild(String child) {
this.children.add(child);