package com.taobao.tddl.executor.cursor;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.taobao.tddl.executor.cursor.impl.ColMetaAndIndex;
import com.taobao.tddl.executor.cursor.impl.CursorMetaImp;
import com.taobao.tddl.executor.function.ExtraFunction;
import com.taobao.tddl.executor.rowset.ArrayRowSet;
import com.taobao.tddl.executor.rowset.IRowSet;
import com.taobao.tddl.executor.utils.ExecUtils;
import com.taobao.tddl.optimizer.config.table.ColumnMeta;
import com.taobao.tddl.optimizer.core.datatype.DataType;
import com.taobao.tddl.optimizer.core.datatype.DataTypeUtil;
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.IFunction;
import com.taobao.tddl.optimizer.core.expression.ILogicalFilter;
import com.taobao.tddl.optimizer.core.expression.IOrderBy;
public class RangeMaker {
public static class Range {
public IRowSet from;
public IRowSet to;
}
public RangeMaker.Range makeRange(IFilter lf, List<IOrderBy> orderBys) {
RangeMaker.Range range = new RangeMaker.Range();
ICursorMeta cursorMetaNew = getICursorMetaByOrderBy(orderBys);
range.to = new ArrayRowSet(orderBys.size(), cursorMetaNew);
//
range.from = new ArrayRowSet(orderBys.size(), cursorMetaNew);
convertFilterToLowerAndTopLimit(range, lf, cursorMetaNew);
boolean min = false;
fillRowSet(range.from, min);
boolean max = true;
fillRowSet(range.to, max);
return range;
}
public ICursorMeta getICursorMetaByOrderBy(List<IOrderBy> orderBys) {
List<ColumnMeta> columnsNew = new ArrayList<ColumnMeta>(orderBys.size());
for (IOrderBy orderBy : orderBys) {
ColumnMeta cmNew = ExecUtils.getColumnMeta(orderBy.getColumn());
columnsNew.add(cmNew);
}
ICursorMeta cursorMetaNew = CursorMetaImp.buildNew(columnsNew, orderBys.size());
return cursorMetaNew;
}
private void convertFilterToLowerAndTopLimit(RangeMaker.Range range, IFilter lf, ICursorMeta cursorMetaNew) {
if (lf instanceof IBooleanFilter) {
processBoolfilter(range, lf, cursorMetaNew);
} else if (lf instanceof ILogicalFilter) {
ILogicalFilter lo = (ILogicalFilter) lf;
if (lo.getOperation() == OPERATION.OR) {
throw new IllegalStateException("or ? should not be here");
}
List<IFilter> list = lo.getSubFilter();
for (IFilter filter : list) {
convertFilterToLowerAndTopLimit(range, filter, cursorMetaNew);
}
}
}
/**
* 将大于等于 变成大于 小于 变成小于等于 将
*
* @param lf
* @param cursorMetaNew
*/
private void processBoolfilter(RangeMaker.Range range, IFilter lf, ICursorMeta cursorMetaNew) {
IBooleanFilter bf = (IBooleanFilter) lf;
switch (bf.getOperation()) {
case GT_EQ:
setIntoRowSet(cursorMetaNew, bf, range.from, new ColumnEQProcessor() {
@Override
public Object process(Object c, DataType type) {
return c;
}
});
break;
case GT:
setIntoRowSet(cursorMetaNew, bf, range.from, new ColumnEQProcessor() {
@Override
public Object process(Object c, DataType type) {
return incr(c, type);
}
});
break;
case LT:
setIntoRowSet(cursorMetaNew, bf, range.to, new ColumnEQProcessor() {
@Override
public Object process(Object c, DataType type) {
return decr(c, type);
}
});
break;
case LT_EQ:
setIntoRowSet(cursorMetaNew, bf, range.to, new ColumnEQProcessor() {
@Override
public Object process(Object c, DataType type) {
return c;
}
});
break;
case EQ:
setIntoRowSet(cursorMetaNew, bf, range.from, new ColumnEQProcessor() {
@Override
public Object process(Object c, DataType type) {
return c;
}
});
setIntoRowSet(cursorMetaNew, bf, range.to, new ColumnEQProcessor() {
@Override
public Object process(Object c, DataType type) {
return c;
}
});
break;
default:
throw new IllegalArgumentException("not supported yet");
}
}
private void setIntoRowSet(ICursorMeta cursorMetaNew, IBooleanFilter bf, IRowSet rowSet,
ColumnEQProcessor columnProcessor) {
IColumn col = ExecUtils.getIColumn(bf.getColumn());
Object val = bf.getValue();
// if (col.getDataType() == DATA_TYPE.DATE_VAL) {
// if (val instanceof Long) {
// val = new Date((Long) val);
// }
// }
val = processFunction(val);
val = columnProcessor.process(val, col.getDataType());
Integer inte = cursorMetaNew.getIndex(col.getTableName(), col.getColumnName());
if (inte == null) inte = cursorMetaNew.getIndex(col.getTableName(), col.getAlias());
rowSet.setObject(inte, val);
}
public Object decr(Object c, DataType type) {
if (type == null) {
type = DataTypeUtil.getTypeOfObject(c); // 可能为null
}
return type.decr(c);
}
/**
* 用来做一些值的处理工作
*
* @author whisper
*/
public static interface ColumnEQProcessor {
public Object process(Object c, DataType type);
}
public Object incr(Object c, DataType type) {
if (type == null) {
type = DataTypeUtil.getTypeOfObject(c); // 可能为null
}
return type.incr(c);
}
@SuppressWarnings("rawtypes")
private Comparable processFunction(Object v) {
if (v instanceof IFunction) {/*
* shenxun : 这个地方实现有点ugly。写个注释。。 函数在key
* filter里面做起来难度较大,
* 如果是个无参函数,或者函数内包含了所有列数据,比如pk = 1+1
* 这样的表达式,那么是可以直接计算的。
* 但如果函数内包含当前keyFilter列本身
* ,那么就需要遍历所有记录,进行条件判断。
* 这个实现比较麻烦,意义不大,暂时不予实现。
*/
IFunction func = (IFunction) v;
func.getArgs();
try {
((ExtraFunction) func.getExtraFunction()).serverMap((IRowSet) null);
} catch (Exception e) {
throw new RuntimeException(e);
}
Comparable val = (Comparable) func.getExtraFunction().getResult();
return val;
}
return (Comparable) v;
}
private void fillRowSet(IRowSet iRowSet, boolean max) {
ICursorMeta icm = iRowSet.getParentCursorMeta();
Iterator<ColMetaAndIndex> iterator = icm.indexIterator();
while (iterator.hasNext()) {
ColMetaAndIndex cai = iterator.next();
String cname = cai.getName();
List<ColumnMeta> columns = iRowSet.getParentCursorMeta().getColumns();
// TODO shenxun : 如果条件是null。。。没处理。。应该在Comparator里面处理
if (iRowSet.getObject(cai.getIndex()) == null) {
boolean find = false;
for (ColumnMeta cm : columns) {
if (cname.equalsIgnoreCase(cm.getName())) {
find = true;
iRowSet.setObject(cai.getIndex(), getExtremum(max, cm.getDataType()));
break;
}
}
if (!find) {
throw new IllegalStateException(" can't find column name : " + cname + " on . " + columns);
}
}
}
}
public Object getExtremum(boolean max, DataType type) {
if (max) {
return type.getMaxValue();
// switch (type) {
// case INT_VAL:
// return Integer.MAX_VALUE;
// case LONG_VAL:
// return Long.MAX_VALUE;
// case SHORT_VAL:
// return Short.MAX_VALUE;
// case FLOAT_VAL:
// return Float.MAX_VALUE;
// case DOUBLE_VAL:
// return Double.MAX_VALUE;
// case DATE_VAL:
// return new Date(Long.MAX_VALUE);
// case STRING_VAL:
// return Character.MAX_VALUE + "";
// case TIMESTAMP_VAL:
// return new Date(Long.MAX_VALUE);
// case BOOLEAN_VAL:
// return new Boolean(true);
// case CHAR_VAL:
// return Character.MAX_VALUE + "";
// default:
// throw new IllegalArgumentException("not supported yet");
// }
} else {
// 任何类型的最小值都是null;
return type.getMinValue();
}
// return null;
}
}