Search in sources :

Example 1 with JoinNode

use of com.actiontech.dble.plan.node.JoinNode in project dble by actiontech.

the class ItemField method fixFields.

@Override
public Item fixFields(NameResolutionContext context) {
    if (this.isWild())
        return this;
    String tmpFieldTable = null;
    String tmpFieldName = getItemName();
    PlanNode planNode = context.getPlanNode();
    if (context.getPlanNode().type() == PlanNodeType.MERGE) {
        return getMergeNodeColumn(tmpFieldTable, tmpFieldName, planNode);
    }
    Item column = null;
    if (context.isFindInSelect()) {
        // try to find in selectlist
        if (StringUtils.isEmpty(getTableName())) {
            for (NamedField namedField : planNode.getOuterFields().keySet()) {
                if (StringUtils.equalsIgnoreCase(tmpFieldName, namedField.getName())) {
                    if (column == null) {
                        column = planNode.getOuterFields().get(namedField);
                    } else
                        throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "42S22", "duplicate column:" + this);
                }
            }
        } else {
            tmpFieldTable = getTableName();
            column = planNode.getOuterFields().get(new NamedField(tmpFieldTable, tmpFieldName, null));
        }
    }
    if (column != null && context.isSelectFirst()) {
        return column;
    }
    // find from inner fields
    Item columnFromMeta = null;
    if (StringUtils.isEmpty(getTableName())) {
        for (NamedField namedField : planNode.getInnerFields().keySet()) {
            if (StringUtils.equalsIgnoreCase(tmpFieldName, namedField.getName())) {
                if (columnFromMeta == null) {
                    tmpFieldTable = namedField.getTable();
                    NamedField coutField = planNode.getInnerFields().get(new NamedField(tmpFieldTable, tmpFieldName, null));
                    this.tableName = namedField.getTable();
                    getReferTables().clear();
                    this.getReferTables().add(coutField.planNode);
                    columnFromMeta = this;
                } else {
                    if (planNode.type() == PlanNodeType.JOIN) {
                        JoinNode jn = (JoinNode) planNode;
                        if (jn.getUsingFields() != null && jn.getUsingFields().contains(columnFromMeta.getItemName().toLowerCase())) {
                            continue;
                        }
                    }
                    throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "42S22", "duplicate column:" + this);
                }
            }
        }
    } else {
        tmpFieldTable = getTableName();
        NamedField tmpField = new NamedField(tmpFieldTable, tmpFieldName, null);
        if (planNode.getInnerFields().containsKey(tmpField)) {
            NamedField coutField = planNode.getInnerFields().get(tmpField);
            getReferTables().clear();
            getReferTables().add(coutField.planNode);
            this.tableName = tmpField.getTable();
            columnFromMeta = this;
        }
    }
    if (columnFromMeta != null) {
        return columnFromMeta;
    } else if (column == null)
        throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "42S22", "column " + this + " not found");
    else {
        return column;
    }
}
Also used : PlanNode(com.actiontech.dble.plan.node.PlanNode) NamedField(com.actiontech.dble.plan.NamedField) JoinNode(com.actiontech.dble.plan.node.JoinNode) MySQLOutPutException(com.actiontech.dble.plan.common.exception.MySQLOutPutException)

Example 2 with JoinNode

use of com.actiontech.dble.plan.node.JoinNode in project dble by actiontech.

the class ConfigTest method testERjoin.

private boolean testERjoin(ERTable er0, ERTable er1) {
    Class<ERJoinChooser> classERJoin = ERJoinChooser.class;
    try {
        Constructor<ERJoinChooser> construtor = classERJoin.getConstructor(new Class[] { JoinNode.class, Map.class });
        Object instance = construtor.newInstance(new Object[] { new JoinNode(), this.erRealtions });
        Method isERRelstionMethod = classERJoin.getDeclaredMethod("isErRelation", new Class[] { ERTable.class, ERTable.class });
        isERRelstionMethod.setAccessible(true);
        Object result = isERRelstionMethod.invoke(instance, new Object[] { er0, er1 });
        return (Boolean) result;
    } catch (Exception e) {
        System.out.println(e);
        return false;
    }
}
Also used : JoinNode(com.actiontech.dble.plan.node.JoinNode) Method(java.lang.reflect.Method) ERJoinChooser(com.actiontech.dble.plan.optimizer.ERJoinChooser)

Example 3 with JoinNode

use of com.actiontech.dble.plan.node.JoinNode in project dble by actiontech.

the class FilterPusher method getJoinNode.

private static PlanNode getJoinNode(PlanNode qtn, List<Item> dnfNodeToPush) {
    JoinNode jn = (JoinNode) qtn;
    List<Item> dnfNodetoPushToLeft = new LinkedList<>();
    List<Item> dnfNodetoPushToRight = new LinkedList<>();
    List<Item> leftCopyedPushFilters = new LinkedList<>();
    List<Item> rightCopyedPushFilters = new LinkedList<>();
    List<Item> dnfNodeToCurrent = new LinkedList<>();
    PlanUtil.findJoinKeysAndRemoveIt(dnfNodeToPush, jn);
    for (Item filter : dnfNodeToPush) {
        // ex. 1 = -1
        if (filter.getReferTables().size() == 0) {
            dnfNodetoPushToLeft.add(filter);
            dnfNodetoPushToRight.add(filter);
            continue;
        }
        if (PlanUtil.canPush(filter, jn.getLeftNode(), jn)) {
            dnfNodetoPushToLeft.add(filter);
        } else if (PlanUtil.canPush(filter, jn.getRightNode(), jn)) {
            dnfNodetoPushToRight.add(filter);
        } else {
            dnfNodeToCurrent.add(filter);
        }
    }
    if (jn.isInnerJoin() || jn.isLeftOuterJoin() || jn.isRightOuterJoin()) {
        // push the left expr to join filter's right condition
        rightCopyedPushFilters.addAll(copyFilterToJoinOnColumns(dnfNodetoPushToLeft, jn.getLeftKeys(), jn.getRightKeys()));
        // push the right expr to join filter's left condition
        leftCopyedPushFilters.addAll(copyFilterToJoinOnColumns(dnfNodetoPushToRight, jn.getRightKeys(), jn.getLeftKeys()));
    }
    // if it can not push down, merge to current where
    Item node = FilterUtils.and(dnfNodeToCurrent);
    if (node != null) {
        qtn.query(FilterUtils.and(qtn.getWhereFilter(), node));
    }
    if (jn.isInnerJoin() || jn.isLeftOuterJoin() || jn.isRightOuterJoin()) {
        if (jn.isLeftOuterJoin()) {
            // left join, push down the right join ,but still contains right joins condition
            jn.query(FilterUtils.and(qtn.getWhereFilter(), FilterUtils.and(dnfNodetoPushToRight)));
        }
        if (jn.isRightOuterJoin()) {
            // right join, push down the left join ,but still contains left joins condition
            jn.query(FilterUtils.and(qtn.getWhereFilter(), FilterUtils.and(dnfNodetoPushToLeft)));
        }
        // merge
        dnfNodetoPushToRight.addAll(rightCopyedPushFilters);
        dnfNodetoPushToLeft.addAll(leftCopyedPushFilters);
        refreshPdFilters(jn, dnfNodetoPushToLeft);
        refreshPdFilters(jn, dnfNodetoPushToRight);
        jn.setLeftNode(pushFilter(jn.getLeftNode(), dnfNodetoPushToLeft));
        jn.setRightNode(pushFilter(((JoinNode) qtn).getRightNode(), dnfNodetoPushToRight));
    } else {
        if (!dnfNodeToPush.isEmpty()) {
            jn.query(FilterUtils.and(qtn.getWhereFilter(), FilterUtils.and(dnfNodeToPush)));
        }
    }
    return jn;
}
Also used : Item(com.actiontech.dble.plan.common.item.Item) JoinNode(com.actiontech.dble.plan.node.JoinNode) LinkedList(java.util.LinkedList)

Example 4 with JoinNode

use of com.actiontech.dble.plan.node.JoinNode 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 5 with JoinNode

use of com.actiontech.dble.plan.node.JoinNode 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)

Aggregations

JoinNode (com.actiontech.dble.plan.node.JoinNode)21 PlanNode (com.actiontech.dble.plan.node.PlanNode)16 Item (com.actiontech.dble.plan.common.item.Item)6 ItemFuncEqual (com.actiontech.dble.plan.common.item.function.operator.cmpfunc.ItemFuncEqual)5 ArrayList (java.util.ArrayList)4 ItemField (com.actiontech.dble.plan.common.item.ItemField)3 QueryNode (com.actiontech.dble.plan.node.QueryNode)3 ERTable (com.actiontech.dble.config.model.ERTable)2 MySQLOutPutException (com.actiontech.dble.plan.common.exception.MySQLOutPutException)2 TableNode (com.actiontech.dble.plan.node.TableNode)2 LinkedList (java.util.LinkedList)2 NamedField (com.actiontech.dble.plan.NamedField)1 Order (com.actiontech.dble.plan.Order)1 ItemSubQuery (com.actiontech.dble.plan.common.item.subquery.ItemSubQuery)1 MergeNode (com.actiontech.dble.plan.node.MergeNode)1 ERJoinChooser (com.actiontech.dble.plan.optimizer.ERJoinChooser)1 Method (java.lang.reflect.Method)1 HashSet (java.util.HashSet)1 List (java.util.List)1