fix hint parse error inner 1831

This commit is contained in:
lin
2022-08-01 15:51:20 +08:00
parent d4e7eba373
commit 412ccb7a08
6 changed files with 72 additions and 22 deletions
@@ -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);
}
}
}
@@ -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;
}
}
@@ -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();
@@ -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));
}