package com.taobao.tddl.optimizer.costbased.after;
import java.util.Map;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import com.taobao.tddl.common.jdbc.ParameterContext;
import com.taobao.tddl.common.model.ExtraCmd;
import com.taobao.tddl.common.utils.GeneralUtil;
import com.taobao.tddl.optimizer.core.plan.IDataNodeExecutor;
import com.taobao.tddl.optimizer.core.plan.IQueryTree;
import com.taobao.tddl.optimizer.core.plan.query.IJoin;
import com.taobao.tddl.optimizer.core.plan.query.IMerge;
import com.taobao.tddl.optimizer.core.plan.query.IParallelizableQueryTree.QUERY_CONCURRENCY;
import com.taobao.tddl.optimizer.core.plan.query.IQuery;
/**
* 会修改一个状态标记。
*
* @author Whisper
*/
public class MergeConcurrentOptimizer implements QueryPlanOptimizer {
public MergeConcurrentOptimizer(){
}
/**
* 如果设置了MergeConcurrent 并且值为True,则将所有的Merge变为并行
*/
@Override
public IDataNodeExecutor optimize(IDataNodeExecutor dne, Map<Integer, ParameterContext> parameterSettings,
Map<String, Object> extraCmd) {
this.findMergeAndSetConcurrent(dne, extraCmd);
return dne;
}
private void findMergeAndSetConcurrent(IDataNodeExecutor dne, Map<String, Object> extraCmd) {
if (dne instanceof IMerge) {
if (isMergeConcurrent(extraCmd, (IMerge) dne)) {
((IMerge) dne).setQueryConcurrency(QUERY_CONCURRENCY.CONCURRENT);
} else {
((IMerge) dne).setQueryConcurrency(QUERY_CONCURRENCY.SEQUENTIAL);
}
for (IDataNodeExecutor child : ((IMerge) dne).getSubNode()) {
this.findMergeAndSetConcurrent(child, extraCmd);
}
}
if (dne instanceof IJoin) {
this.findMergeAndSetConcurrent(((IJoin) dne).getLeftNode(), extraCmd);
this.findMergeAndSetConcurrent(((IJoin) dne).getRightNode(), extraCmd);
}
if (dne instanceof IQuery && ((IQuery) dne).getSubQuery() != null) {
this.findMergeAndSetConcurrent(((IQuery) dne).getSubQuery(), extraCmd);
}
}
private static boolean isMergeConcurrent(Map<String, Object> extraCmd, IMerge query) {
String value = ObjectUtils.toString(GeneralUtil.getExtraCmdString(extraCmd, ExtraCmd.MERGE_CONCURRENT));
if (StringUtils.isEmpty(value)) {
if (query.getSql() != null) {
// 如果存在sql,那说明是hint直接路由
return true;
}
if ((query.getLimitFrom() != null || query.getLimitTo() != null)) {
if (query.getOrderBys() == null || query.getOrderBys().isEmpty()) {
// 存在limit,但不存在order by时不允许走并行
return false;
}
} else if ((query.getOrderBys() == null || query.getOrderBys().isEmpty())
&& (query.getGroupBys() == null || query.getGroupBys().isEmpty())
&& query.getHavingFilter() == null) {
if (isNoFilter(query)) {
// 没有其他的order by / group by / having /
// where等条件时,就是个简单的select *
// from xxx,暂时也不做并行
return false;
}
}
return true;
} else {
return BooleanUtils.toBoolean(value);
}
}
private static boolean isNoFilter(IDataNodeExecutor dne) {
if (!(dne instanceof IQueryTree)) {
return true;
}
if (dne instanceof IMerge) {
for (IDataNodeExecutor child : ((IMerge) dne).getSubNode()) {
return isNoFilter(child);
}
}
if (dne instanceof IJoin) {
return isNoFilter(((IJoin) dne).getLeftNode()) && isNoFilter(((IJoin) dne).getRightNode());
}
if (dne instanceof IQuery) {
if (((IQuery) dne).getSubQuery() != null) {
return isNoFilter(((IQuery) dne).getSubQuery());
} else {
return ((IQuery) dne).getKeyFilter() == null && ((IQuery) dne).getValueFilter() == null;
}
}
return true;
}
}