Search in sources :

Example 6 with PlanNode

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;
}
Also used : Item(com.actiontech.dble.plan.common.item.Item) PlanNode(com.actiontech.dble.plan.node.PlanNode) JoinNode(com.actiontech.dble.plan.node.JoinNode) ArrayList(java.util.ArrayList)

Example 7 with PlanNode

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;
}
Also used : PlanNode(com.actiontech.dble.plan.node.PlanNode) JoinNode(com.actiontech.dble.plan.node.JoinNode) ItemSubQuery(com.actiontech.dble.plan.common.item.subquery.ItemSubQuery) HashSet(java.util.HashSet)

Example 8 with PlanNode

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();
}
Also used : PlanNode(com.actiontech.dble.plan.node.PlanNode) HashSet(java.util.HashSet)

Example 9 with PlanNode

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;
}
Also used : PlanNode(com.actiontech.dble.plan.node.PlanNode) JoinNode(com.actiontech.dble.plan.node.JoinNode)

Example 10 with PlanNode

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;
}
Also used : MergeNode(com.actiontech.dble.plan.node.MergeNode) PlanNode(com.actiontech.dble.plan.node.PlanNode) JoinNode(com.actiontech.dble.plan.node.JoinNode) QueryNode(com.actiontech.dble.plan.node.QueryNode)

Aggregations

PlanNode (com.actiontech.dble.plan.node.PlanNode)50 JoinNode (com.actiontech.dble.plan.node.JoinNode)16 Item (com.actiontech.dble.plan.common.item.Item)14 ArrayList (java.util.ArrayList)10 QueryNode (com.actiontech.dble.plan.node.QueryNode)8 ItemFuncEqual (com.actiontech.dble.plan.common.item.function.operator.cmpfunc.ItemFuncEqual)6 MySQLOutPutException (com.actiontech.dble.plan.common.exception.MySQLOutPutException)5 MySQLPlanNodeVisitor (com.actiontech.dble.plan.visitor.MySQLPlanNodeVisitor)5 ItemSubQuery (com.actiontech.dble.plan.common.item.subquery.ItemSubQuery)4 SQLSelectStatement (com.alibaba.druid.sql.ast.statement.SQLSelectStatement)4 DMLResponseHandler (com.actiontech.dble.backend.mysql.nio.handler.query.DMLResponseHandler)3 NamedField (com.actiontech.dble.plan.NamedField)3 ErrorPacket (com.actiontech.dble.net.mysql.ErrorPacket)2 Order (com.actiontech.dble.plan.Order)2 TableNode (com.actiontech.dble.plan.node.TableNode)2 HashSet (java.util.HashSet)2 BaseHandlerBuilder (com.actiontech.dble.backend.mysql.nio.handler.builder.BaseHandlerBuilder)1 HandlerBuilder (com.actiontech.dble.backend.mysql.nio.handler.builder.HandlerBuilder)1 TempTableHandler (com.actiontech.dble.backend.mysql.nio.handler.query.impl.TempTableHandler)1 CallBackHandler (com.actiontech.dble.backend.mysql.nio.handler.util.CallBackHandler)1