mirror of
https://github.com/actiontech/dble.git
synced 2026-05-06 22:40:44 -05:00
fix hint parse error inner 1831
This commit is contained in:
+16
@@ -40,6 +40,7 @@ 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.util.StringUtil;
|
||||
import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -374,6 +375,21 @@ public abstract class BaseHandlerBuilder {
|
||||
addDelayTableHandler(sh, (TableNode) node);
|
||||
} else if (node instanceof JoinNode && canDoAsMerge()) {
|
||||
nestLoopAddHandler(sh, node);
|
||||
} else if (node.haveDependOnNode()) {
|
||||
List<PlanNode> nestLoopDependOnNodeList = node.getNestLoopDependOnNodeList();
|
||||
for (PlanNode planNode : nestLoopDependOnNodeList) {
|
||||
TableNode tableNode = (TableNode) planNode.getNestLoopDependNode();
|
||||
HintNestLoopHelper hintNestLoopHelper = tableNode.getHintNestLoopHelper();
|
||||
List<DelayTableHandler> delayTableHandlers = hintNestLoopHelper.getDelayTableHandlers(tableNode);
|
||||
Map<PlanNode, SendMakeHandler> sendMakeHandlerHashMap = hintNestLoopHelper.getSendMakeHandlerHashMap();
|
||||
Set<BaseDMLHandler> tableHandlers = sh.getTableHandlers();
|
||||
for (DelayTableHandler delayTableHandler : delayTableHandlers) {
|
||||
if (StringUtil.equals(planNode.getAlias(), delayTableHandler.getTableAlias())) {
|
||||
tableHandlers.add(delayTableHandler);
|
||||
}
|
||||
}
|
||||
sendMakeHandlerHashMap.put(tableNode, sh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -12,6 +12,8 @@ public class HintNestLoopHelper {
|
||||
|
||||
Map<PlanNode, List<DelayTableHandler>> delayTableHandlerMap = new HashMap<>();
|
||||
Map<PlanNode, SendMakeHandler> sendMakeHandlerHashMap = new HashMap<>();
|
||||
//hint plan that the node is a dependent node, when in fact the node is not
|
||||
Set<PlanNode> fakeDependSet = new HashSet<>();
|
||||
Map<PlanNode, Pair<Item, Item>> itemMap = new HashMap<>();
|
||||
|
||||
public Map<PlanNode, SendMakeHandler> getSendMakeHandlerHashMap() {
|
||||
@@ -33,4 +35,8 @@ public class HintNestLoopHelper {
|
||||
public Map<PlanNode, Pair<Item, Item>> getItemMap() {
|
||||
return itemMap;
|
||||
}
|
||||
|
||||
public Set<PlanNode> getFakeDependSet() {
|
||||
return fakeDependSet;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-4
@@ -234,12 +234,15 @@ class JoinNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
if (Objects.nonNull(dependNode)) {
|
||||
Pair<Item, Item> itemPair = ((TableNode) currentNode).getHintNestLoopHelper().getItemMap().get(currentNode);
|
||||
DelayTableHandler delayTableHandler = buildDelayHandler(isLeft, currentNode, itemPair.getKey(), itemPair.getValue());
|
||||
Map<PlanNode, List<DelayTableHandler>> delayTableHandlerMap = dependNode.getHintNestLoopHelper().getDelayTableHandlerMap();
|
||||
HintNestLoopHelper hintNestLoopHelper = dependNode.getHintNestLoopHelper();
|
||||
Map<PlanNode, List<DelayTableHandler>> delayTableHandlerMap = hintNestLoopHelper.getDelayTableHandlerMap();
|
||||
List<DelayTableHandler> delayTableHandlerList = Optional.ofNullable(delayTableHandlerMap.get(dependNode)).orElse(new ArrayList<>());
|
||||
delayTableHandlerList.add(delayTableHandler);
|
||||
if (!hintNestLoopHelper.getFakeDependSet().contains(currentNode)) {
|
||||
delayTableHandlerList.add(delayTableHandler);
|
||||
}
|
||||
delayTableHandlerMap.put(dependNode, delayTableHandlerList);
|
||||
pres.add(delayTableHandler);
|
||||
SendMakeHandler sendMakeHandler = dependNode.getHintNestLoopHelper().getSendMakeHandlerHashMap().get(dependNode);
|
||||
SendMakeHandler sendMakeHandler = hintNestLoopHelper.getSendMakeHandlerHashMap().get(dependNode);
|
||||
if (Objects.nonNull(sendMakeHandler)) {
|
||||
sendMakeHandler.getTableHandlers().add(delayTableHandler);
|
||||
}
|
||||
@@ -250,7 +253,7 @@ class JoinNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
} else if (currentNode instanceof TableNode) {
|
||||
DMLResponseHandler rh = buildJoinChild(currentNode, isLeft);
|
||||
HintNestLoopHelper hintNestLoopHelper = ((TableNode) currentNode).getHintNestLoopHelper();
|
||||
List<DelayTableHandler> delayTableHandlerList = Optional.ofNullable(hintNestLoopHelper.getDelayTableHandlerMap().get(currentNode)).orElse(new ArrayList<>());
|
||||
List<DelayTableHandler> delayTableHandlerList = hintNestLoopHelper.getDelayTableHandlers(node);
|
||||
SendMakeHandler sendMakeHandler = ((TableNode) currentNode).getHintNestLoopHelper().getSendMakeHandlerHashMap().get(currentNode);
|
||||
for (DelayTableHandler handler : delayTableHandlerList) {
|
||||
sendMakeHandler.getTableHandlers().add(handler);
|
||||
@@ -314,6 +317,7 @@ class JoinNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
|
||||
private DelayTableHandler buildDelayHandler(boolean isLeft, PlanNode tnBig, Item keySource, Item keyToPass) {
|
||||
final DelayTableHandler delayTableHandler = new DelayTableHandler(getSequenceId(), session, keySource);
|
||||
delayTableHandler.setTableAlias(tnBig.getAlias());
|
||||
delayTableHandler.setLeft(isLeft);
|
||||
CallBackHandler tempDone = () -> {
|
||||
Set<String> valueSet = delayTableHandler.getValueSet();
|
||||
|
||||
+8
@@ -51,6 +51,7 @@ public class DelayTableHandler extends BaseDMLHandler {
|
||||
private final Item sourceSel;
|
||||
private Field sourceField;
|
||||
private Set<String> valueSet;
|
||||
private String tableAlias;
|
||||
|
||||
public DelayTableHandler(long id, Session session, Item sourceSel) {
|
||||
super(id, session);
|
||||
@@ -183,4 +184,11 @@ public class DelayTableHandler extends BaseDMLHandler {
|
||||
return HandlerType.TEMPTABLE;
|
||||
}
|
||||
|
||||
public String getTableAlias() {
|
||||
return tableAlias;
|
||||
}
|
||||
|
||||
public void setTableAlias(String tableAlias) {
|
||||
this.tableAlias = tableAlias;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,11 @@ import com.actiontech.dble.plan.node.PlanNode;
|
||||
import com.actiontech.dble.plan.node.TableNode;
|
||||
import com.actiontech.dble.plan.util.PlanUtil;
|
||||
import com.actiontech.dble.route.parser.util.Pair;
|
||||
import com.actiontech.dble.server.parser.HintPlanParse;
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class JoinNestLoopChooser {
|
||||
private Map<String, PlanNode> nodeMap;
|
||||
@@ -27,17 +28,9 @@ public class JoinNestLoopChooser {
|
||||
this.hintPlanInfo = hintPlanInfo;
|
||||
nodeMap = new HashMap<>();
|
||||
nodeDependMap = new HashMap<>();
|
||||
conversionNodeDependMap(hintPlanInfo.getDependMap());
|
||||
hintNestLoopHelper = new HintNestLoopHelper();
|
||||
}
|
||||
|
||||
private void conversionNodeDependMap(HashMap<String, Set<HintPlanNode>> dependMap) {
|
||||
dependMap.forEach((k, v) -> {
|
||||
List<String> dependList = v.stream().map(HintPlanNode::getName).collect(Collectors.toList());
|
||||
nodeDependMap.put(k, dependList);
|
||||
});
|
||||
}
|
||||
|
||||
public void tryNestLoop() throws MySQLOutPutException {
|
||||
buildNode(jn);
|
||||
checkHintDependency();
|
||||
@@ -72,7 +65,21 @@ public class JoinNestLoopChooser {
|
||||
private void buildNestLoop() {
|
||||
nodeDependMap.forEach((alias, v) -> {
|
||||
if (!v.isEmpty()) {
|
||||
String dependName = v.get(0);
|
||||
HashMap<String, Set<HintPlanNode>> dependMap = hintPlanInfo.getDependMap();
|
||||
Set<HintPlanNode> hintPlanNodes = dependMap.get(alias);
|
||||
LinkedHashMap<String, HintPlanParse.Type> hintPlanNodeMap = hintPlanInfo.getHintPlanNodeMap();
|
||||
String dependName = hintPlanNodes.iterator().next().getName();
|
||||
if (hintPlanNodes.size() > 1 && !StringUtil.equals(dependName, v.get(0)) && hintPlanNodeMap.get(dependName) == HintPlanParse.Type.AND) {
|
||||
PlanNode currentNode = nodeMap.get(alias);
|
||||
PlanNode dependNode = nodeMap.get(dependName).getParent();
|
||||
TableNode fakeDependNode = (TableNode) nodeMap.get(v.get(0));
|
||||
List<PlanNode> nodeList = Optional.ofNullable(dependNode.getNestLoopDependOnNodeList()).orElse(new ArrayList<>());
|
||||
nodeList.add(nodeList.size(), currentNode);
|
||||
dependNode.setNestLoopDependOnNodeList(nodeList);
|
||||
fakeDependNode.getHintNestLoopHelper().getFakeDependSet().add(currentNode);
|
||||
}
|
||||
|
||||
dependName = v.get(0);
|
||||
PlanNode currentNode = nodeMap.get(alias);
|
||||
PlanNode dependNode = nodeMap.get(dependName);
|
||||
List<PlanNode> nodeList = Optional.ofNullable(dependNode.getNestLoopDependOnNodeList()).orElse(new ArrayList<>());
|
||||
@@ -109,13 +116,17 @@ public class JoinNestLoopChooser {
|
||||
}
|
||||
|
||||
private void checkHintDependency() {
|
||||
HashMap<String, Set<HintPlanNode>> dependMap = hintPlanInfo.getDependMap();
|
||||
LinkedHashMap<String, HintPlanParse.Type> hintPlanNodeMap = hintPlanInfo.getHintPlanNodeMap();
|
||||
HashMap<String, Set<HintPlanNode>> erMap = hintPlanInfo.getErMap();
|
||||
checkErCondition(erMap);
|
||||
if (hintPlanInfo.nodeSize() != nodeMap.size()) {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "the number of tables in the hint plan and the actual SQL varies");
|
||||
}
|
||||
dependMap.forEach((k, v) -> checkAndOrCondition(k));
|
||||
hintPlanNodeMap.forEach((k, v) -> {
|
||||
if (v != HintPlanParse.Type.ER) {
|
||||
checkAndOrCondition(k);
|
||||
}
|
||||
});
|
||||
hintAndCheck();
|
||||
}
|
||||
|
||||
@@ -128,7 +139,11 @@ public class JoinNestLoopChooser {
|
||||
PlanNode dependNode = nodeMap.get(node.getName());
|
||||
boolean result = dependencyHelper(dependNode, currentNode, currentNode);
|
||||
if (result) {
|
||||
nodeDependMap.get(currentNode.getAlias()).add(dependNode.getAlias());
|
||||
//the verified dependency need to be put into the nodeDependMap
|
||||
String alias = currentNode.getAlias();
|
||||
List<String> dependList = Optional.ofNullable(nodeDependMap.get(alias)).orElse(Lists.newArrayList());
|
||||
dependList.add(dependNode.getAlias());
|
||||
nodeDependMap.put(k, dependList);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,8 @@ public class HintPlanParse {
|
||||
nodeStack = buildChildNode(nodeStack, and);
|
||||
nodeStack = buildChildNode(nodeStack, or);
|
||||
}
|
||||
if (nodeStack.size() > 1 || !nodeStack.peek().isTable()) {
|
||||
Node peek = nodeStack.peek();
|
||||
if (nodeStack.size() > 1 || !(peek.isTable() || peek.getType() == Type.ER)) {
|
||||
throw new ConfigException("hint parse failure");
|
||||
}
|
||||
return nodeStack.pop();
|
||||
@@ -161,13 +162,13 @@ public class HintPlanParse {
|
||||
er.append(c);
|
||||
break;
|
||||
case '|':
|
||||
addNode(nodeName.toString(), nodeList, erRelation);
|
||||
addNode(nodeName.toString(), nodeList, erRelation, Type.OR);
|
||||
nodeList.add(new Node(String.valueOf(c), Type.OR));
|
||||
nodeName = new StringBuilder();
|
||||
er = new StringBuilder();
|
||||
break;
|
||||
case '&':
|
||||
addNode(nodeName.toString(), nodeList, erRelation);
|
||||
addNode(nodeName.toString(), nodeList, erRelation, Type.AND);
|
||||
nodeList.add(new Node(String.valueOf(c), Type.AND));
|
||||
nodeName = new StringBuilder();
|
||||
er = new StringBuilder();
|
||||
@@ -198,7 +199,7 @@ public class HintPlanParse {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private void addNode(String nodeName, List<Node> nodeList, boolean erRelation) throws ConfigException {
|
||||
private void addNode(String nodeName, List<Node> nodeList, boolean erRelation, Type type) throws ConfigException {
|
||||
if (erRelation) {
|
||||
throw new ConfigException("er Relation need like (a,b,c)");
|
||||
}
|
||||
@@ -208,7 +209,7 @@ public class HintPlanParse {
|
||||
}
|
||||
nodeMap.putIfAbsent(nodeName, HintPlanNode.of(nodeName));
|
||||
//table has dependencies will be added to the end
|
||||
hintPlanNodeMap.put(nodeName, Type.OR);
|
||||
hintPlanNodeMap.put(nodeName, type);
|
||||
nodeList.add(new Node(nodeName));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user