package com.taobao.tddl.executor; import java.util.List; import java.util.concurrent.Future; import org.apache.commons.lang.exception.ExceptionUtils; import com.taobao.tddl.common.exception.TddlException; import com.taobao.tddl.common.model.ExtraCmd; import com.taobao.tddl.common.model.lifecycle.AbstractLifecycle; import com.taobao.tddl.common.utils.GeneralUtil; import com.taobao.tddl.executor.common.AtomicNumberCreator; import com.taobao.tddl.executor.common.ExecutionContext; import com.taobao.tddl.executor.common.ExecutorContext; import com.taobao.tddl.executor.cursor.ISchematicCursor; import com.taobao.tddl.executor.cursor.ResultCursor; import com.taobao.tddl.executor.cursor.impl.QueryPlanResultCursor; import com.taobao.tddl.executor.utils.ExecUtils; import com.taobao.tddl.monitor.Monitor; import com.taobao.tddl.optimizer.OptimizerContext; import com.taobao.tddl.optimizer.core.expression.ISelectable; import com.taobao.tddl.optimizer.core.plan.IDataNodeExecutor; import com.taobao.tddl.optimizer.core.plan.IQueryTree; import com.taobao.tddl.optimizer.exceptions.EmptyResultFilterException; import com.taobao.tddl.common.utils.logger.Logger; import com.taobao.tddl.common.utils.logger.LoggerFactory; public class MatrixExecutor extends AbstractLifecycle implements IExecutor { private final static Logger logger = LoggerFactory.getLogger(MatrixExecutor.class); private static final String EXPLAIN = "explain"; /** * id 生成器 */ private AtomicNumberCreator idGen = AtomicNumberCreator.getNewInstance(); /** * client端核心流程 解析 优化 执行 */ public ResultCursor execute(String sql, ExecutionContext executionContext) throws TddlException { // client端核心流程 try { int explainIndex = explainIndex(sql); if (explainIndex > 0) { sql = sql.substring(explainIndex); } IDataNodeExecutor qc = parseAndOptimize(sql, executionContext); if (explainIndex > 0) { return createQueryPlanResultCursor(qc); } return execByExecPlanNode(qc, executionContext); } catch (EmptyResultFilterException e) { return ResultCursor.EMPTY_RESULT_CURSOR; } catch (Exception e) { if (ExceptionUtils.getCause(e) instanceof EmptyResultFilterException) { return ResultCursor.EMPTY_RESULT_CURSOR; } else { throw new TddlException(e); } } } private ResultCursor createQueryPlanResultCursor(IDataNodeExecutor qc) { return new QueryPlanResultCursor(qc.toString(), null); } private int explainIndex(String sql) { String temp = sql; int i = 0; for (; i < temp.length(); ++i) { switch (temp.charAt(i)) { case ' ': case '\t': case '\r': case '\n': continue; } break; } if (temp.toLowerCase().startsWith(EXPLAIN, i)) { return i + EXPLAIN.length(); } else { return -1; } } public IDataNodeExecutor parseAndOptimize(String sql, ExecutionContext executionContext) throws TddlException { boolean cache = GeneralUtil.getExtraCmdBoolean(executionContext.getExtraCmds(), ExtraCmd.OPTIMIZER_CACHE, true); return OptimizerContext.getContext() .getOptimizer() .optimizeAndAssignment(sql, executionContext.getParams(), executionContext.getExtraCmds(), cache); } @Override public ResultCursor execByExecPlanNode(IDataNodeExecutor qc, ExecutionContext executionContext) throws TddlException { if (logger.isDebugEnabled()) { logger.warn("extraCmd:\n" + executionContext.getExtraCmds()); logger.warn("ParameterContext:\n" + executionContext.getParams()); } // client端核心流程y try { long time = System.currentTimeMillis(); ISchematicCursor sc = ExecutorContext.getContext() .getTopologyExecutor() .execByExecPlanNode(qc, executionContext); ResultCursor rc = this.wrapResultCursor(qc, sc, executionContext); // 控制语句 time = Monitor.monitorAndRenewTime(Monitor.KEY1, Monitor.TDDL_EXECUTE, Monitor.Key3Success, time); if (qc instanceof IQueryTree) { // 做下表名替换 List columnsForResultSet = ((IQueryTree) qc).getColumns(); if (((IQueryTree) qc).getAlias() != null) { columnsForResultSet = ExecUtils.copySelectables(columnsForResultSet); for (Object s : columnsForResultSet) { ((ISelectable) s).setTableName(((IQueryTree) qc).getAlias()); } } rc.setOriginalSelectColumns(columnsForResultSet); } return rc; } catch (EmptyResultFilterException e) { return ResultCursor.EMPTY_RESULT_CURSOR; } catch (Exception e) { if (ExceptionUtils.getCause(e) instanceof EmptyResultFilterException) { return ResultCursor.EMPTY_RESULT_CURSOR; } else { throw new TddlException(e); } } } @Override public Future<ISchematicCursor> execByExecPlanNodeFuture(IDataNodeExecutor qc, ExecutionContext executionContext) throws TddlException { return ExecutorContext.getContext().getTopologyExecutor().execByExecPlanNodeFuture(qc, executionContext); } @Override public ResultCursor commit(ExecutionContext executionContext) throws TddlException { return ExecutorContext.getContext().getTopologyExecutor().commit(executionContext); } @Override public ResultCursor rollback(ExecutionContext executionContext) throws TddlException { return ExecutorContext.getContext().getTopologyExecutor().rollback(executionContext); } @Override public Future<ResultCursor> commitFuture(ExecutionContext executionContext) throws TddlException { return ExecutorContext.getContext().getTopologyExecutor().commitFuture(executionContext); } @Override public Future<ResultCursor> rollbackFuture(ExecutionContext executionContext) throws TddlException { return ExecutorContext.getContext().getTopologyExecutor().rollbackFuture(executionContext); } protected ResultCursor wrapResultCursor(IDataNodeExecutor command, ISchematicCursor iSchematicCursor, ExecutionContext context) throws TddlException { ResultCursor cursor; // 包装为可以传输的ResultCursor if (command instanceof IQueryTree) { if (!(iSchematicCursor instanceof ResultCursor)) { cursor = new ResultCursor(iSchematicCursor, context); } else { cursor = (ResultCursor) iSchematicCursor; } } else { if (!(iSchematicCursor instanceof ResultCursor)) { cursor = new ResultCursor(iSchematicCursor, context); } else { cursor = (ResultCursor) iSchematicCursor; } } generateResultIdAndPutIntoResultSetMap(cursor); return cursor; } private void generateResultIdAndPutIntoResultSetMap(ResultCursor cursor) { int id = idGen.getIntegerNextNumber(); cursor.setResultID(id); } }