use of com.actiontech.dble.plan.node.JoinNode 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.JoinNode 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;
}
use of com.actiontech.dble.plan.node.JoinNode in project dble by actiontech.
the class OrderByPusher method pushOrderBy.
private static PlanNode pushOrderBy(PlanNode qtn) {
if (PlanUtil.isGlobalOrER(qtn))
return qtn;
if (qtn.type() == PlanNodeType.MERGE) {
// note:do not execute mergenode
for (PlanNode child : qtn.getChildren()) {
pushOrderBy(child);
}
return qtn;
} else if (qtn.type() == PlanNodeType.JOIN) {
JoinNode join = (JoinNode) qtn;
// sort merge join's order by, need to push down to left/right node
List<Order> implicitOrders = getOrderBysGroupFirst(join);
boolean canMatch = getJoinColumnOrders(join.getJoinFilter(), join.getLeftJoinOnOrders(), join.getRightJoinOnOrders(), implicitOrders);
boolean leftOrderPushSuc = false;
boolean rightOrderPushSuc = false;
if (canMatch) {
// push down join column first
leftOrderPushSuc = tryPushOrderToChild(join, join.getLeftJoinOnOrders(), join.getLeftNode());
if (leftOrderPushSuc) {
tryPushOrderToChild(join, implicitOrders, join.getLeftNode());
}
rightOrderPushSuc = tryPushOrderToChild(join, join.getRightJoinOnOrders(), join.getRightNode());
if (rightOrderPushSuc) {
tryPushOrderToChild(join, implicitOrders, join.getRightNode());
}
} else {
leftOrderPushSuc = tryPushOrderToChild(join, join.getLeftJoinOnOrders(), join.getLeftNode());
rightOrderPushSuc = tryPushOrderToChild(join, join.getRightJoinOnOrders(), join.getRightNode());
}
join.setLeftOrderMatch(leftOrderPushSuc);
join.setRightOrderMatch(rightOrderPushSuc);
} else if (qtn.type() == PlanNodeType.QUERY) {
// push order to subQuery
QueryNode query = (QueryNode) qtn;
tryPushOrderToChild(query, getOrderBysGroupFirst(query), query.getChild());
}
for (PlanNode child : qtn.getChildren()) {
if (child instanceof PlanNode) {
pushOrderBy(child);
}
}
return qtn;
}
use of com.actiontech.dble.plan.node.JoinNode in project dble by actiontech.
the class SubQueryPreProcessor method transformInSubQuery.
private static SubQueryFilter transformInSubQuery(SubQueryFilter qtn, ItemInSubQuery filter, BoolPtr childTransform) {
Item leftColumn = filter.getLeftOperand();
PlanNode query = filter.getPlanNode();
query = findComparisonsSubQueryToJoinNode(query, childTransform);
QueryNode changeQuery = new QueryNode(query);
String alias = AUTOALIAS + query.getPureName();
changeQuery.setAlias(alias);
if (query.getColumnsSelected().size() != 1)
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "only support subquery of one column");
query.setSubQuery(true).setDistinct(true);
final List<Item> newSelects = qtn.query.getColumnsSelected();
SubQueryFilter result = new SubQueryFilter();
Item rightColumn = query.getColumnsSelected().get(0);
qtn.query.setColumnsSelected(new ArrayList<Item>());
String rightJoinName = rightColumn.getAlias();
if (StringUtils.isEmpty(rightJoinName)) {
if (rightColumn instanceof ItemField) {
rightJoinName = rightColumn.getItemName();
} else {
rightColumn.setAlias(AUTONAME);
rightJoinName = AUTONAME;
}
}
ItemField rightJoinColumn = new ItemField(null, alias, rightJoinName);
// rename the left column's table name
result.query = new JoinNode(qtn.query, changeQuery);
// leave origin sql to new join node
result.query.setSql(qtn.query.getSql());
qtn.query.setSql(null);
result.query.select(newSelects);
qtn.query.setSubQuery(false);
if (!qtn.query.getOrderBys().isEmpty()) {
List<Order> orderBys = new ArrayList<>();
orderBys.addAll(qtn.query.getOrderBys());
result.query.setOrderBys(orderBys);
qtn.query.getOrderBys().clear();
}
if (!qtn.query.getGroupBys().isEmpty()) {
List<Order> groupBys = new ArrayList<>();
groupBys.addAll(qtn.query.getGroupBys());
result.query.setGroupBys(groupBys);
qtn.query.getGroupBys().clear();
result.query.having(qtn.query.getHavingFilter());
qtn.query.having(null);
}
if (qtn.query.getLimitFrom() != -1) {
result.query.setLimitFrom(qtn.query.getLimitFrom());
qtn.query.setLimitFrom(-1);
}
if (qtn.query.getLimitTo() != -1) {
result.query.setLimitTo(qtn.query.getLimitTo());
qtn.query.setLimitTo(-1);
}
if (filter.isNeg()) {
((JoinNode) result.query).setLeftOuterJoin().setNotIn(true);
ItemFuncEqual joinFilter = FilterUtils.equal(leftColumn, rightJoinColumn);
((JoinNode) result.query).addJoinFilter(joinFilter);
result.filter = null;
} else {
Item joinFilter = FilterUtils.equal(leftColumn, rightJoinColumn);
result.query.query(joinFilter);
result.filter = joinFilter;
}
result.query.setUpFields();
return result;
}
use of com.actiontech.dble.plan.node.JoinNode in project dble by actiontech.
the class ERJoinChooser method joinWithGlobal.
private PlanNode joinWithGlobal(PlanNode t, List<PlanNode> globalList) {
PlanNode newT = t;
while (globalList.size() > 0) {
boolean foundJoin = false;
for (int i = 0; i < globalList.size(); i++) {
PlanNode global = globalList.get(i);
// try join
JoinNode joinNode = new JoinNode(newT, global);
List<ItemFuncEqual> jnFilter = makeJoinFilter(joinNode, newT, global, false);
// @if no join column, then the other is cross join
if (jnFilter.size() > 0 || selLists.size() == 0) {
// join
replaceSelListReferedTn(newT, global, joinNode);
foundJoin = true;
joinNode.setJoinFilter(jnFilter);
globalList.remove(i);
newT = joinNode;
break;
}
}
if (// no join can do from t and globals
!foundJoin)
break;
}
return newT;
}
Aggregations