package com.taobao.tddl.executor.handler;
import java.util.List;
import com.taobao.tddl.common.exception.TddlException;
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.impl.RangeCursor;
import com.taobao.tddl.executor.spi.IRepository;
import com.taobao.tddl.executor.spi.ITable;
import com.taobao.tddl.executor.spi.ITransaction;
import com.taobao.tddl.executor.utils.ExecUtils;
import com.taobao.tddl.optimizer.config.table.IndexMeta;
import com.taobao.tddl.optimizer.core.expression.IBooleanFilter;
import com.taobao.tddl.optimizer.core.expression.IColumn;
import com.taobao.tddl.optimizer.core.expression.IFilter;
import com.taobao.tddl.optimizer.core.expression.IFilter.OPERATION;
import com.taobao.tddl.optimizer.core.expression.ILogicalFilter;
import com.taobao.tddl.optimizer.core.expression.IOrderBy;
import com.taobao.tddl.optimizer.core.plan.IDataNodeExecutor;
import com.taobao.tddl.optimizer.core.plan.IQueryTree;
import com.taobao.tddl.optimizer.core.plan.query.IQuery;
/**
* 用于处理执行的handler 。 目的是将执行计划中的Query节点进行转义处理。
* 这个执行器主要是用在使用KV接口的数据库里,比如bdb.concurrentHashMap等。
*
* @author Whisper
*/
public class QueryHandler extends QueryHandlerCommon {
public QueryHandler(){
super();
}
@Override
protected ISchematicCursor doQuery(ISchematicCursor cursor, IDataNodeExecutor executor,
ExecutionContext executionContext) throws TddlException {
List<IOrderBy> _orderBy = ((IQueryTree) executor).getOrderBys();
IRepository repo = executionContext.getCurrentRepository();
IDataNodeExecutor _subQuery = null;
IQuery query = (IQuery) executor;
_subQuery = query.getSubQuery();
if (_subQuery != null) {
// 如果有subQuery,则按照subquery构建
cursor = ExecutorContext.getContext().getTopologyExecutor().execByExecPlanNode(_subQuery, executionContext);
} else {
ITable table = null;
IndexMeta meta = null;
buildTableAndMeta(query, executionContext);
table = executionContext.getTable();
meta = executionContext.getMeta();
cursor = table.getCursor(executionContext, meta, (IQuery) executor);
}
// 获得查询结果的元数据
// 获得本次查询的keyFilter
IFilter keyFilter = query.getKeyFilter();
if (keyFilter != null) {
if (keyFilter instanceof IBooleanFilter) {
// 外键约束好像没用
// if (meta.getRelationship() == Relationship.MANY_TO_MANY) {
// cursor = manageToReverseIndex(cursor, executor, repo,
// transaction, executionContext.getTable(), meta,
// keyFilter);
// } else {}
// 非倒排索引,即普通索引,走的查询方式
cursor = manageToBooleanRangeCursor(executionContext, cursor, repo, keyFilter);
} else if (keyFilter instanceof ILogicalFilter) {
ILogicalFilter lf = (ILogicalFilter) keyFilter;
cursor = repo.getCursorFactory().rangeCursor(executionContext, cursor, lf);
}
if (cursor instanceof RangeCursor) {//
if (_orderBy != null) {
if (_orderBy.size() == 1) {
IOrderBy o1 = _orderBy.get(0);
IOrderBy o2 = cursor.getOrderBy().get(0);
boolean needSort = !equalsIOrderBy(o1, o2);
boolean direction = o1.getDirection();
if (!needSort) {
if (!direction) {
// DescRangeCursor
cursor = repo.getCursorFactory().reverseOrderCursor(executionContext, cursor);
} else {
// asc,default
}
_orderBy = null;
}
}
}
}
}
return cursor;
}
protected ISchematicCursor manageToBooleanRangeCursor(ExecutionContext executionContext, ISchematicCursor cursor,
IRepository repo, IFilter keyFilter) throws TddlException {
IBooleanFilter bf = (IBooleanFilter) keyFilter;
IColumn c = ExecUtils.getColumn(bf.getColumn());
OPERATION op = bf.getOperation();
if (op == OPERATION.IN) {
List<Object> values = bf.getValues();
if (values == null) {
throw new IllegalArgumentException("values is null ,but operation is in . logical error");
} else {
return repo.getCursorFactory().inCursor(executionContext, cursor, cursor.getOrderBy(), c, values, op);
}
}
try {
cursor = repo.getCursorFactory().rangeCursor(executionContext, cursor, keyFilter);
} catch (Exception e) {
throw new RuntimeException(e);
}
return cursor;
}
protected ISchematicCursor manageToReverseIndex(ExecutionContext executionContext, ISchematicCursor cursor,
IDataNodeExecutor executor, IRepository repo,
ITransaction transaction, ITable table, IndexMeta meta,
IFilter keyFilter) throws TddlException {
throw new IllegalArgumentException("should not be here");
}
}