package com.taobao.tddl.executor.cursor.impl; import java.util.Comparator; import java.util.List; import com.taobao.tddl.common.exception.TddlException; import com.taobao.tddl.common.utils.GeneralUtil; import com.taobao.tddl.executor.common.KVPair; import com.taobao.tddl.executor.cursor.IRangeCursor; import com.taobao.tddl.executor.cursor.ISchematicCursor; import com.taobao.tddl.executor.cursor.RangeMaker; import com.taobao.tddl.executor.cursor.SchematicCursor; import com.taobao.tddl.executor.record.CloneableRecord; 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.expression.IFilter; import com.taobao.tddl.optimizer.core.expression.IOrderBy; import com.taobao.tddl.optimizer.core.expression.ISelectable; import com.taobao.tddl.common.utils.logger.Logger; import com.taobao.tddl.common.utils.logger.LoggerFactory; /** * 现在具有对多个索引内前缀字段+非前缀字段 * * @author jianxing <jianxing.qx@taobao.com> */ public class RangeCursor extends SchematicCursor implements IRangeCursor { public static final Logger log = LoggerFactory.getLogger(RangeCursor.class); /** * 范围,到哪里结束 */ protected IRowSet to; /** * 范围,从哪里开始? */ protected IRowSet from; protected Comparator<IRowSet> fromComparator; protected Comparator<IRowSet> toComparator; private boolean schemaInited = false; private IFilter lf = null; boolean first = true; public RangeCursor(ISchematicCursor cursor, IFilter lf){ super(cursor, null, cursor.getOrderBy()); this.lf = lf; RangeMaker.Range range = makeRange(lf, orderBys); this.from = range.from; this.to = range.to; } protected RangeMaker.Range makeRange(IFilter lf, List<IOrderBy> orderBys) { return new RangeMaker().makeRange(lf, orderBys); } private void initSchema(IRowSet firstRowSet, IFilter lf) { if (schemaInited) { return; } schemaInited = true; List<ColumnMeta> columnMetas = to.getParentCursorMeta().getColumns(); List<ISelectable> iColumns = ExecUtils.getIColumnsWithISelectable(columnMetas.toArray(new ColumnMeta[0])); toComparator = ExecUtils.getComp(iColumns, iColumns, to.getParentCursorMeta(), firstRowSet.getParentCursorMeta()); fromComparator = ExecUtils.getComp(iColumns, iColumns, from.getParentCursorMeta(), firstRowSet.getParentCursorMeta()); // init(rangeFilters); } @Override public IRowSet next() throws TddlException { if (cursor == null) { return null; } IRowSet kv = null; if (!first) { kv = cursor.next(); } else { first = false; kv = first(); if (kv == null) { return null; } } if (kv == null) { return null; } if (match(kv)) { return kv; } else { return null; } } /** * @param kv * @return true 如果符合区间。false 如果不符合区间 */ private boolean match(IRowSet kv) { initSchema(kv, lf); int res = fromComparator.compare(from, kv); if (res == 0) {// eq; return true; } else if (res > 0) { return false; } res = toComparator.compare(to, kv); if (res == 0) { return true; } else if (res < 0) { return false; } return true; } @Override public boolean skipTo(CloneableRecord key) throws TddlException { if (parentCursorSkipTo(key)) { IRowSet kv = current(); if (match(kv)) { return true; } } return false; } @Override public boolean skipTo(KVPair key) throws TddlException { return skipTo(key.getKey()); } @Override public IRowSet first() throws TddlException { this.first = false; IRowSet iRowSet = from; CloneableRecord cr = ExecUtils.convertToClonableRecord(iRowSet); if (!cursor.skipTo(cr)) { return null; } else { return cursor.current(); } } @Override public IRowSet last() throws TddlException { first = false; IRowSet iRowSet = to; CloneableRecord cr = ExecUtils.convertToClonableRecord(iRowSet); // to在数据中间有四种可能 // data:5,6,7,8,9,10,15 // case1: to是data的某个值,如9 // case2: to大于最大值,如17 // case3: to小于最小值,如2 // case4: to在某两个值之间,如11 // case5: data为空 if (!cursor.skipTo(cr)) { // case2: to大于最大值,如17 IRowSet last = cursor.last(); if (last == null) {// case5: data为空 return null; } if (match(last)) { // 只考虑to,是肯定匹配的,不匹配的可能是from return last; } else { return null; } } else { if (match(cursor.current())) { // case1: to是data的某个值,如9 // 此时current和to相等 return cursor.current(); }// current>to或者current<from // 取prev的值 // 如果current<from,则prev同样小于from,不会match else { IRowSet prevCurrent = cursor.prev(); if (prevCurrent == null) { // case3: to小于最小值,如2 return null; } else { // case4: to在某两个值之间,如11 if (match(prevCurrent)) { return prevCurrent; } else { return null; } } } } } @Override public IRowSet prev() throws TddlException { IRowSet kv; if (!first) { kv = parentCursorPrev(); } else { first = false; kv = last(); if (kv == null) { return null; } } if (kv == null) { return null; } if (match(kv)) { return kv; } else { return null; } } @Override public String toString() { return toStringWithInden(0); } public String toStringWithInden(int inden) { StringBuilder sb = new StringBuilder(); String tab = GeneralUtil.getTab(inden); sb.append(tab) .append("【Range cursor .start : ") .append(from) .append("|") .append(" end : ") .append(to) .append("\n"); ExecUtils.printOrderBy(orderBys, inden, sb); sb.append(super.toStringWithInden(inden)); return sb.toString(); } @Override public void beforeFirst() throws TddlException { this.first = true; } public IRowSet getTo() { return to; } public void setTo(IRowSet to) { this.to = to; } public IRowSet getFrom() { return from; } public void setFrom(IRowSet from) { this.from = from; } }