use of com.actiontech.dble.plan.node.PlanNode in project dble by actiontech.
the class FilterPusher method pushJoinOnFilter.
/**
* inner join's other join on would add to where when FilterPre and push down,
* when Left join, eg" select * from t1 left join t2 on t1.id=t2.id and t1.id = 10 and
* t2.name = 'aaa' push down t2.id=10 and t2.name='aaa'
*/
private static PlanNode pushJoinOnFilter(PlanNode qtn) {
if (PlanUtil.isGlobalOrER(qtn))
return qtn;
if (qtn.type().equals(PlanNodeType.JOIN)) {
JoinNode jn = (JoinNode) qtn;
Item otherJoinOn = jn.getOtherJoinOnFilter();
if (jn.isLeftOuterJoin() && otherJoinOn != null) {
List<Item> pushToRightNode = new ArrayList<>();
List<Item> splitedFilters = FilterUtils.splitFilter(otherJoinOn);
for (Item filter : splitedFilters) {
if (filter.getReferTables().isEmpty())
pushToRightNode.add(filter);
else if (PlanUtil.canPush(filter, jn.getRightNode(), jn))
pushToRightNode.add(filter);
else if (PlanUtil.canPush(filter, jn.getLeftNode(), jn)) {
Item copyedFilter = copyFilterToJoinOnColumns(filter, jn.getRightKeys(), jn.getLeftKeys());
if (copyedFilter != null)
pushToRightNode.add(copyedFilter);
} else
continue;
}
if (!pushToRightNode.isEmpty()) {
splitedFilters.removeAll(pushToRightNode);
Item newOtherJoinOn = FilterUtils.and(splitedFilters);
jn.setOtherJoinOnFilter(newOtherJoinOn);
refreshPdFilters(jn, pushToRightNode);
List<Item> subHavingList = new ArrayList<>();
List<Item> subWhereList = new ArrayList<>();
for (Item filter : pushToRightNode) {
if (filter.isWithSumFunc()) {
subHavingList.add(filter);
} else {
subWhereList.add(filter);
}
}
Item subHaving = FilterUtils.and(subHavingList);
Item subWhere = FilterUtils.and(subWhereList);
jn.getRightNode().having(FilterUtils.and(jn.getRightNode().getHavingFilter(), subHaving));
jn.getRightNode().setWhereFilter(FilterUtils.and(jn.getRightNode().getWhereFilter(), subWhere));
}
}
}
for (PlanNode child : qtn.getChildren()) pushJoinOnFilter(child);
return qtn;
}
use of com.actiontech.dble.plan.node.PlanNode in project dble by actiontech.
the class GlobalTableProcessor method initGlobalStatus.
/**
* @param tn
* @return true:parent node maybe is global;false parent node must not be global
*/
private static boolean initGlobalStatus(PlanNode tn) {
if (tn == null || ((tn.type() == PlanNodeType.TABLE || tn.type() == PlanNodeType.NONAME) && tn.getSubQueries().size() == 0)) {
return true;
}
boolean status = true;
for (PlanNode child : tn.getChildren()) {
boolean ret = initGlobalStatus(child);
if (status) {
status = ret;
}
}
for (ItemSubQuery subQuery : tn.getSubQueries()) {
boolean ret = initGlobalStatus(subQuery.getPlanNode());
if (status) {
status = ret;
}
}
if (PlanUtil.isERNode(tn)) {
// treat er join as an un global table
tn.setUnGlobalTableCount(1);
Set<String> newSet = new HashSet<>();
newSet.addAll(tn.getReferedTableNodes().get(0).getNoshardNode());
tn.setNoshardNode(newSet);
} else {
int unGlobalCount = calcUnGlobalCount(tn);
tn.setUnGlobalTableCount(unGlobalCount);
if (tn.getNoshardNode() != null && tn.getNoshardNode().size() == 0) {
tn.setNoshardNode(null);
}
if (!status) {
tn.setNoshardNode(null);
return false;
}
if (unGlobalCount == 1 && tn instanceof JoinNode) {
// joinNode
JoinNode jn = (JoinNode) tn;
if (jn.isNotIn()) {
tn.setNoshardNode(null);
status = false;
} else if (jn.isInnerJoin()) {
if (!isGlobalTableBigEnough(jn)) {
tn.setNoshardNode(null);
status = false;
}
} else {
// left join
PlanNode left = jn.getLeftNode();
if (left.getUnGlobalTableCount() == 0) {
// left node is global,left join will not push down
tn.setNoshardNode(null);
status = false;
} else if (left.type() == PlanNode.PlanNodeType.TABLE || !PlanUtil.isERNode(left)) {
if (!isGlobalTableBigEnough(jn)) {
tn.setNoshardNode(null);
status = false;
}
} else {
// left node is not single table or er table
tn.setNoshardNode(null);
status = false;
}
}
} else if (unGlobalCount != 0) {
tn.setNoshardNode(null);
status = false;
}
}
return status;
}
use of com.actiontech.dble.plan.node.PlanNode in project dble by actiontech.
the class GlobalTableProcessor method isGlobalTableBigEnough.
private static boolean isGlobalTableBigEnough(JoinNode jn) {
PlanNode left = jn.getLeftNode();
PlanNode right = jn.getRightNode();
PlanNode global, normal;
if (left.getUnGlobalTableCount() == 0) {
global = left;
normal = right;
} else {
global = right;
normal = left;
}
Set<String> result = new HashSet<>();
result.addAll(global.getNoshardNode());
Set<String> normalSet = normal.getNoshardNode();
result.retainAll(normalSet);
return result.size() == normalSet.size();
}
use of com.actiontech.dble.plan.node.PlanNode in project dble by actiontech.
the class JoinPreProcessor method findAndChangeRightJoinToLeftJoin.
/**
* change right join to left join.
* <p>
* <pre>
* eg: A right join B on A.id = B.id
* change to B left join B on A.id = B.id
* </pre>
*/
private static PlanNode findAndChangeRightJoinToLeftJoin(PlanNode qtn) {
for (PlanNode child : qtn.getChildren()) {
findAndChangeRightJoinToLeftJoin(child);
}
if (qtn instanceof JoinNode && ((JoinNode) qtn).isRightOuterJoin()) {
JoinNode jn = (JoinNode) qtn;
jn.exchangeLeftAndRight();
}
return qtn;
}
use of com.actiontech.dble.plan.node.PlanNode in project dble by actiontech.
the class LimitPusher method findChild.
private static PlanNode findChild(PlanNode qtn) {
if (qtn instanceof MergeNode) {
// optimizer limit
// union: push down limit to children
// union all:push down limit to children and add distinct
MergeNode node = (MergeNode) qtn;
long limitFrom = node.getLimitFrom();
long limitTo = node.getLimitTo();
if (limitFrom != -1 && limitTo != -1) {
for (PlanNode child : node.getChildren()) {
pushLimit(child, limitFrom, limitTo, node.isUnion());
}
}
} else if ((qtn instanceof JoinNode) || (qtn instanceof QueryNode)) {
for (PlanNode child : qtn.getChildren()) {
findChild(child);
}
}
return qtn;
}
Aggregations