package com.taobao.tddl.optimizer.core.ast.build; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import com.taobao.tddl.optimizer.core.ASTNodeFactory; import com.taobao.tddl.optimizer.core.ast.ASTNode; import com.taobao.tddl.optimizer.core.ast.QueryTreeNode; import com.taobao.tddl.optimizer.core.ast.query.MergeNode; import com.taobao.tddl.optimizer.core.expression.IColumn; import com.taobao.tddl.optimizer.core.expression.IFilter; import com.taobao.tddl.optimizer.core.expression.IFunction; import com.taobao.tddl.optimizer.core.expression.IOrderBy; import com.taobao.tddl.optimizer.core.expression.ISelectable; import com.taobao.tddl.optimizer.utils.OptimizerUtils; /** * @since 5.0.0 */ public class MergeNodeBuilder extends QueryTreeNodeBuilder { public MergeNodeBuilder(MergeNode mergeNode){ this.setNode(mergeNode); } @Override public MergeNode getNode() { return (MergeNode) super.getNode(); } @Override public void build() { for (ASTNode sub : this.getNode().getChildren()) { sub.build(); } if (!(this.getNode().getChild() instanceof QueryTreeNode)) { return; } this.buildAlias(); this.buildSelected(); this.buildWhere(); this.buildGroupBy(); this.buildOrderBy(); this.buildHaving(); this.buildLimit(); this.buildFunction(); this.buildExistAggregate(); } /** * <pre> * 1. max(id)+min(id),要把聚合函数单独推到子节点去(比如max(id),min(id)),然后在父节点留一个scalar函数进行计算 * 2. substring(),to_date()等简单scalar函数(不包含条件1的函数),推到子节点去,然后在父节点留一个字段,而不是函数 * </pre> */ public void buildFunction() { super.buildFunction(); List<IFunction> aggregateInScalar = new ArrayList<IFunction>(); List<ISelectable> simpleScalar = new ArrayList<ISelectable>(); for (ISelectable s : this.getNode().getColumnsSelected()) { if (s instanceof IFunction) { if (IFunction.FunctionType.Aggregate.equals(((IFunction) s).getFunctionType())) { continue; } else { List<IFunction> argsAggregateFunctions = this.findAggregateFunctionsInScalar((IFunction) s); if (!argsAggregateFunctions.isEmpty()) { aggregateInScalar.addAll(argsAggregateFunctions); } else { simpleScalar.add(s); } } } } // case 2,删除父节点的简单scalar函数 // this.getNode().getColumnsSelected().removeAll(simpleScalar); // for (ISelectable f : simpleScalar) { // IColumn scalarColumn = ASTNodeFactory.getInstance().createColumn(); // if (f.getAlias() != null) { // scalarColumn.setColumnName(f.getAlias()); // } // scalarColumn.setTableName(f.getTableName()); // scalarColumn.setDistinct(f.isDistinct()); // scalarColumn.setIsNot(f.isNot()); // this.getNode().addColumnsSelected(buildSelectable(scalarColumn, // true)); // } List<ISelectable> toRemove = new ArrayList(); for (ISelectable s : ((QueryTreeNode) this.getNode().getChild()).getColumnsSelected()) { if (s instanceof IFunction && IFunction.FunctionType.Scalar.equals(((IFunction) s).getFunctionType())) { if (!this.findAggregateFunctionsInScalar((IFunction) s).isEmpty()) { // scalar里存在聚合函数 toRemove.add(s); } } } for (ASTNode child : this.getNode().getChildren()) { ((QueryTreeNode) child).getColumnsSelected().removeAll(toRemove);// 干掉查询的min(id)+max(id)函数 for (ISelectable f : aggregateInScalar) { // 只添加min(id) ,max(id)的独立函数 ((QueryTreeNode) child).addColumnsSelected(f); } child.build(); } } public void buildFunction(IFunction f, boolean findInSelectList) { for (Object arg : f.getArgs()) { if (arg instanceof IFunction) { this.buildSelectable((ISelectable) arg, findInSelectList); } else if (arg instanceof ISelectable) { // 针对非distinct的函数,没必要下推字段 if (((ISelectable) arg).isDistinct()) { this.buildSelectable((ISelectable) arg, findInSelectList); } } } } private List<IFunction> findAggregateFunctionsInScalar(IFunction s) { List<IFunction> res = new ArrayList(); this.findAggregateFunctionsInScalar(s, res); return res; } private void findAggregateFunctionsInScalar(IFunction s, List<IFunction> res) { if (IFunction.FunctionType.Aggregate.equals(s.getFunctionType())) { res.add(s); } for (Object arg : s.getArgs()) { if (arg instanceof IFunction) { this.findAggregateFunctionsInScalar((IFunction) arg, res); } } } @Override public void buildHaving() { if (this.getNode().getChild() instanceof QueryTreeNode) { // 干掉子节点查询的having条件,转移到父节点中 IFilter havingFilter = ((QueryTreeNode) this.getNode().getChild()).getHavingFilter(); this.getNode().having(OptimizerUtils.copyFilter(havingFilter)); for (ASTNode child : this.getNode().getChildren()) { if (child instanceof QueryTreeNode) { ((QueryTreeNode) child).having(""); } } } replaceAliasInFilter(this.getNode().getHavingFilter(), ((QueryTreeNode) this.getNode().getChild()).getAlias()); } private void replaceAliasInFilter(Object filter, String alias) { if (filter instanceof IFunction) { for (Object sub : ((IFunction) filter).getArgs()) { this.replaceAliasInFilter(sub, alias); } } if (filter instanceof ISelectable) { if (alias != null) { ((ISelectable) filter).setTableName(alias); } if (((ISelectable) filter).getAlias() != null) { ((ISelectable) filter).setColumnName(((ISelectable) filter).getAlias()); ((ISelectable) filter).setAlias(null); } } } private void buildLimit() { // 将子节点的limit条件转移到父节点 // 不能出现多级的merge节点都带着limit Comparable from = ((QueryTreeNode) this.getNode().getChild()).getLimitFrom(); Comparable to = ((QueryTreeNode) this.getNode().getChild()).getLimitTo(); this.getNode().setLimitFrom(from); this.getNode().setLimitTo(to); if (from instanceof Long && to instanceof Long) { if ((from != null && (Long) from != -1) || (to != null && (Long) to != -1)) { for (ASTNode s : this.getNode().getChildren()) { // 底下采取limit 0,from+to逻辑,上层来过滤 ((QueryTreeNode) s).setLimitFrom(0L); ((QueryTreeNode) s).setLimitTo((Long) from + (Long) to); } } } } @Override public void buildOrderBy() { // 如果merge本身没指定order by,则继承子节点的order by if (this.getNode().getOrderBys() == null || this.getNode().getOrderBys().isEmpty()) { QueryTreeNode child = (QueryTreeNode) this.getNode().getChild(); if (child.getOrderBys() != null) { for (IOrderBy o : child.getOrderBys()) { ISelectable sc = o.getColumn().copy(); if (o.getColumn().getAlias() != null) { sc.setColumnName(o.getColumn().getAlias()); } if (child.getAlias() != null) { sc.setTableName(child.getAlias()); } this.getNode().orderBy(sc, o.getDirection()); } } } super.buildOrderBy(); } @Override public void buildGroupBy() { // 如果merge本身没指定group by,则继承子节点的group by if (this.getNode().getGroupBys() == null || this.getNode().getGroupBys().isEmpty()) { QueryTreeNode child = (QueryTreeNode) this.getNode().getChild(); if (child.getGroupBys() != null) { for (IOrderBy s : child.getGroupBys()) { IOrderBy sc = s.copy(); if (s.getAlias() != null) { sc.setColumnName(s.getAlias()); } if (child.getAlias() != null) { sc.setTableName(child.getAlias()); } this.getNode().groupBy(sc); } } } super.buildGroupBy(); } private void buildAlias() { if (this.getNode().getAlias() == null) { this.getNode().alias(((QueryTreeNode) this.getNode().getChild()).getAlias()); } } /** * 构建列信息 * * @param indexNode */ public void buildSelected() { buildSelectedFromSelectableObject(); } private void buildSelectedFromSelectableObject() { if (this.getNode().getColumnsSelected().isEmpty()) { this.getNode() .getColumnsSelected() .add(ASTNodeFactory.getInstance().createColumn().setColumnName(IColumn.STAR)); } // 如果有 * ,最后需要把*删掉 List<ISelectable> delete = new LinkedList(); for (ISelectable selected : getNode().getColumnsSelected()) { if (selected.getColumnName().equals(IColumn.STAR)) { delete.add(selected); } } if (!delete.isEmpty()) { this.getNode().getColumnsSelected().removeAll(delete); } for (ISelectable selected : delete) { // 遇到*就把所有列再添加一遍 // select *,id这样的语法最后会有两个id列,mysql是这样的 QueryTreeNode child = (QueryTreeNode) this.getNode().getChild(); for (ISelectable selectedFromChild : child.getColumnsSelected()) { if (selected.getTableName() != null) { if (!selected.getTableName().equals(selectedFromChild.getTableName())) { break; } } ISelectable newS = selectedFromChild.copy(); // IColumn newS = ASTNodeFactory.getInstance().createColumn(); if (child.getAlias() != null) { newS.setTableName(child.getAlias()); } else { newS.setTableName(selectedFromChild.getTableName()); } if (selectedFromChild.getAlias() == null) { newS.setColumnName(selectedFromChild.getColumnName()); } else { newS.setColumnName(selectedFromChild.getAlias()); } getNode().getColumnsSelected().add(newS); } } for (int i = 0; i < getNode().getColumnsSelected().size(); i++) { getNode().getColumnsSelected().set(i, this.buildSelectable(getNode().getColumnsSelected().get(i))); } } @Override public ISelectable getSelectableFromChild(ISelectable c) { QueryTreeNode child = (QueryTreeNode) this.getNode().getChild(); if (IColumn.STAR.equals(c.getColumnName())) { return c; } if (c instanceof IFunction) { return c; } if (child.hasColumn(c)) { ISelectable s = this.getColumnFromOtherNode(c, child); if (s == null) { // 下推select for (int i = 0; i < this.getNode().getChildren().size(); i++) { QueryTreeNode sub = (QueryTreeNode) this.getNode().getChildren().get(i); sub.addColumnsSelected(c.copy()); } s = this.getColumnFromOtherNode(c, child); } return s; } else { return null; } } }