mirror of
https://github.com/actiontech/dble.git
synced 2026-05-08 07:21:00 -05:00
subquery transform to join bug
This commit is contained in:
@@ -31,6 +31,6 @@ public final class ViewUtil {
|
||||
boolean selectsAllowMerge = viewSelNode.type() != PlanNode.PlanNodeType.MERGE;
|
||||
// TODO as the same as LEX::can_be_merged();
|
||||
boolean existAggr = PlanUtil.existAggr(viewSelNode);
|
||||
return selectsAllowMerge && viewSelNode.getReferedTableNodes().size() >= 1 && !existAggr;
|
||||
return selectsAllowMerge && viewSelNode.getReferedTableNodes().size() == 1 && !existAggr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.actiontech.dble.plan.common.item.function.operator.cmpfunc.ItemFuncEq
|
||||
import com.actiontech.dble.plan.common.item.function.operator.logic.ItemCondAnd;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.logic.ItemCondOr;
|
||||
import com.actiontech.dble.plan.common.item.subquery.*;
|
||||
import com.actiontech.dble.plan.common.ptr.BoolPtr;
|
||||
import com.actiontech.dble.plan.node.JoinNode;
|
||||
import com.actiontech.dble.plan.util.FilterUtils;
|
||||
import com.actiontech.dble.plan.util.PlanUtil;
|
||||
@@ -35,63 +36,67 @@ public final class SubQueryPreProcessor {
|
||||
|
||||
public static PlanNode optimize(PlanNode qtn) {
|
||||
MergeHavingFilter.optimize(qtn);
|
||||
qtn = findComparisonsSubQueryToJoinNode(qtn);
|
||||
qtn = findComparisonsSubQueryToJoinNode(qtn, new BoolPtr(false));
|
||||
return qtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* http://dev.mysql.com/doc/refman/5.0/en/comparisons-using-subqueries.html
|
||||
*/
|
||||
private static PlanNode findComparisonsSubQueryToJoinNode(PlanNode qtn) {
|
||||
private static PlanNode findComparisonsSubQueryToJoinNode(PlanNode qtn, BoolPtr childTransform) {
|
||||
for (int i = 0; i < qtn.getChildren().size(); i++) {
|
||||
PlanNode child = qtn.getChildren().get(i);
|
||||
qtn.getChildren().set(i, findComparisonsSubQueryToJoinNode(child));
|
||||
qtn.getChildren().set(i, findComparisonsSubQueryToJoinNode(child, childTransform));
|
||||
}
|
||||
|
||||
SubQueryFilter find = new SubQueryFilter();
|
||||
find.query = qtn;
|
||||
find.filter = null;
|
||||
Item where = qtn.getWhereFilter();
|
||||
SubQueryFilter result = buildSubQuery(qtn, find, where, false);
|
||||
SubQueryFilter result = buildSubQuery(qtn, find, where, false, childTransform);
|
||||
if (result != find) {
|
||||
// that means where filter only contains sub query,just replace it
|
||||
result.query.query(result.filter);
|
||||
qtn.query(null);
|
||||
// change result.filter and rebuild
|
||||
result.query.setUpFields();
|
||||
childTransform.set(true);
|
||||
return result.query;
|
||||
} else {
|
||||
if (childTransform.get()) {
|
||||
qtn.setUpFields();
|
||||
}
|
||||
return qtn;
|
||||
}
|
||||
}
|
||||
|
||||
private static SubQueryFilter buildSubQuery(PlanNode node, SubQueryFilter qtn, Item filter, boolean isOrChild) {
|
||||
private static SubQueryFilter buildSubQuery(PlanNode node, SubQueryFilter qtn, Item filter, boolean isOrChild, BoolPtr childTransform) {
|
||||
if (filter == null)
|
||||
return qtn;
|
||||
if (!filter.isWithSubQuery()) {
|
||||
qtn.filter = filter;
|
||||
} else if (filter instanceof ItemCondOr) {
|
||||
return buildSubQueryWithOrFilter(node, qtn, (ItemCondOr) filter);
|
||||
return buildSubQueryWithOrFilter(node, qtn, (ItemCondOr) filter, childTransform);
|
||||
} else if (filter instanceof ItemCondAnd) {
|
||||
return buildSubQueryWithAndFilter(node, qtn, (ItemCondAnd) filter, isOrChild);
|
||||
return buildSubQueryWithAndFilter(node, qtn, (ItemCondAnd) filter, isOrChild, childTransform);
|
||||
} else {
|
||||
return buildSubQueryByFilter(node, qtn, filter, isOrChild);
|
||||
return buildSubQueryByFilter(node, qtn, filter, isOrChild, childTransform);
|
||||
}
|
||||
return qtn;
|
||||
}
|
||||
|
||||
private static SubQueryFilter buildSubQueryByFilter(PlanNode node, SubQueryFilter qtn, Item filter, boolean isOrChild) {
|
||||
private static SubQueryFilter buildSubQueryByFilter(PlanNode node, SubQueryFilter qtn, Item filter, boolean isOrChild, BoolPtr childTransform) {
|
||||
if (filter instanceof ItemInSubQuery && !isOrChild) {
|
||||
return transformInSubQuery(qtn, (ItemInSubQuery) filter);
|
||||
return transformInSubQuery(qtn, (ItemInSubQuery) filter, childTransform);
|
||||
} else if (filter instanceof ItemInSubQuery) {
|
||||
addSubQuey(node, (ItemInSubQuery) filter);
|
||||
addSubQuey(node, (ItemInSubQuery) filter, childTransform);
|
||||
return qtn;
|
||||
} else if (PlanUtil.isCmpFunc(filter)) {
|
||||
ItemBoolFunc2 eqFilter = (ItemBoolFunc2) filter;
|
||||
Item arg0 = eqFilter.arguments().get(0);
|
||||
if (arg0.type().equals(ItemType.SUBSELECT_ITEM)) {
|
||||
if (arg0 instanceof ItemScalarSubQuery) {
|
||||
addSubQuey(node, ((ItemScalarSubQuery) arg0));
|
||||
addSubQuey(node, (ItemScalarSubQuery) arg0, childTransform);
|
||||
} else {
|
||||
//todo: when happened?
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support subquery of:" + filter.type());
|
||||
@@ -101,9 +106,9 @@ public final class SubQueryPreProcessor {
|
||||
Item arg1 = eqFilter.arguments().get(1);
|
||||
if (arg1.type().equals(ItemType.SUBSELECT_ITEM)) {
|
||||
if (arg1 instanceof ItemScalarSubQuery) {
|
||||
addSubQuey(node, ((ItemScalarSubQuery) arg1));
|
||||
addSubQuey(node, (ItemScalarSubQuery) arg1, childTransform);
|
||||
} else if (arg1 instanceof ItemAllAnySubQuery) {
|
||||
addSubQuey(node, ((ItemAllAnySubQuery) arg1));
|
||||
addSubQuey(node, (ItemAllAnySubQuery) arg1, childTransform);
|
||||
} else {
|
||||
//todo: when happened?
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support subquery of:" + filter.type());
|
||||
@@ -112,7 +117,7 @@ public final class SubQueryPreProcessor {
|
||||
return qtn;
|
||||
} else if (filter.type().equals(ItemType.SUBSELECT_ITEM)) {
|
||||
if (filter instanceof ItemExistsSubQuery) {
|
||||
addSubQuey(node, ((ItemExistsSubQuery) filter));
|
||||
addSubQuey(node, (ItemExistsSubQuery) filter, childTransform);
|
||||
} else {
|
||||
//todo: when happened?
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support subquery of:" + filter.type());
|
||||
@@ -124,16 +129,16 @@ public final class SubQueryPreProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private static void addSubQuey(PlanNode node, ItemSubQuery subQuery) {
|
||||
private static void addSubQuey(PlanNode node, ItemSubQuery subQuery, BoolPtr childTransform) {
|
||||
node.getSubQueries().add(subQuery);
|
||||
PlanNode subNode = findComparisonsSubQueryToJoinNode(subQuery.getPlanNode());
|
||||
PlanNode subNode = findComparisonsSubQueryToJoinNode(subQuery.getPlanNode(), childTransform);
|
||||
subQuery.setPlanNode(subNode);
|
||||
}
|
||||
|
||||
private static SubQueryFilter transformInSubQuery(SubQueryFilter qtn, ItemInSubQuery filter) {
|
||||
private static SubQueryFilter transformInSubQuery(SubQueryFilter qtn, ItemInSubQuery filter, BoolPtr childTransform) {
|
||||
Item leftColumn = filter.getLeftOperand();
|
||||
PlanNode query = filter.getPlanNode();
|
||||
query = findComparisonsSubQueryToJoinNode(query);
|
||||
query = findComparisonsSubQueryToJoinNode(query, childTransform);
|
||||
if (StringUtils.isEmpty(query.getAlias()))
|
||||
query.alias(AUTOALIAS + query.getPureName());
|
||||
if (query.getColumnsSelected().size() != 1)
|
||||
@@ -205,16 +210,16 @@ public final class SubQueryPreProcessor {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static SubQueryFilter buildSubQueryWithOrFilter(PlanNode node, SubQueryFilter qtn, ItemCondOr filter) {
|
||||
private static SubQueryFilter buildSubQueryWithOrFilter(PlanNode node, SubQueryFilter qtn, ItemCondOr filter, BoolPtr childTransform) {
|
||||
for (int index = 0; index < filter.getArgCount(); index++) {
|
||||
buildSubQuery(node, qtn, filter.arguments().get(index), true);
|
||||
buildSubQuery(node, qtn, filter.arguments().get(index), true, childTransform);
|
||||
}
|
||||
return qtn;
|
||||
}
|
||||
|
||||
private static SubQueryFilter buildSubQueryWithAndFilter(PlanNode node, SubQueryFilter qtn, ItemCondAnd filter, boolean isOrChild) {
|
||||
private static SubQueryFilter buildSubQueryWithAndFilter(PlanNode node, SubQueryFilter qtn, ItemCondAnd filter, boolean isOrChild, BoolPtr childTransform) {
|
||||
for (int index = 0; index < filter.getArgCount(); index++) {
|
||||
SubQueryFilter result = buildSubQuery(node, qtn, filter.arguments().get(index), isOrChild);
|
||||
SubQueryFilter result = buildSubQuery(node, qtn, filter.arguments().get(index), isOrChild, childTransform);
|
||||
if (result != qtn) {
|
||||
if (result.filter == null) {
|
||||
result.filter = new ItemInt(1);
|
||||
|
||||
@@ -237,7 +237,7 @@ public class MySQLPlanNodeVisitor {
|
||||
this.tableNode.setSubQuery(true);
|
||||
if (subQueryTables.getAlias() != null) {
|
||||
tableNode.alias(subQueryTables.getAlias());
|
||||
if (tableNode.getSubAlias() == null && tableNode.type() == PlanNode.PlanNodeType.TABLE) {
|
||||
if (tableNode.getSubAlias() == null && tableNode.type() == PlanNode.PlanNodeType.TABLE && !tableNode.isSubQuery()) {
|
||||
tableNode.setSubAlias(tableNode.getAlias());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,14 +229,14 @@ public class Testparser {
|
||||
+ " from char_columns where id =1 and name = 'x';";
|
||||
|
||||
// obj.test(selectSQl);
|
||||
selectSQl = "select * from constant_one where id > SOME(select name from constant_two);";
|
||||
obj.test(selectSQl);
|
||||
selectSQl = "select * from constant_one where id > ANY(select name from constant_two);";
|
||||
obj.test(selectSQl);
|
||||
selectSQl = "select * from constant_one where id > ALL(select name from constant_two);";
|
||||
obj.test(selectSQl);
|
||||
selectSQl = "select * from constant_one where id <> ALL(select name from constant_two);";
|
||||
obj.test(selectSQl);
|
||||
// selectSQl = "select * from constant_one where id > SOME(select name from constant_two);";
|
||||
// obj.test(selectSQl);
|
||||
// selectSQl = "select * from constant_one where id > ANY(select name from constant_two);";
|
||||
// obj.test(selectSQl);
|
||||
// selectSQl = "select * from constant_one where id > ALL(select name from constant_two);";
|
||||
// obj.test(selectSQl);
|
||||
// selectSQl = "select * from constant_one where id <> ALL(select name from constant_two);";
|
||||
// obj.test(selectSQl);
|
||||
// selectSQl = "SELECT BINARY 'a' = 'A';";
|
||||
// obj.test(selectSQl);
|
||||
// selectSQl = "SELECT b'1000001';";
|
||||
@@ -362,6 +362,8 @@ public class Testparser {
|
||||
// //not support
|
||||
// selectSQl = "select sql_big_result distinct pad from sbtest1;";
|
||||
// obj.test(selectSQl);
|
||||
String insertSQl = "insert into test_shard values(1,1,'a\\%string','test001');";
|
||||
obj.test(insertSQl);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user