mirror of
https://github.com/actiontech/dble.git
synced 2026-05-08 07:21:00 -05:00
explain for subquery
This commit is contained in:
+44
-19
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-9
@@ -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);
|
||||
|
||||
+1
-1
@@ -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());
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
+39
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user