package com.taobao.tddl.executor.cursor.impl; import java.util.List; import com.taobao.tddl.common.exception.TddlException; import com.taobao.tddl.common.utils.GeneralUtil; import com.taobao.tddl.executor.codec.CodecFactory; import com.taobao.tddl.executor.codec.RecordCodec; import com.taobao.tddl.executor.cursor.IIndexNestLoopCursor; import com.taobao.tddl.executor.cursor.ISchematicCursor; 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; /** * @author jianxing <jianxing.qx@taobao.com> 重构用以支持mget接口实现。 * @author whisper */ @SuppressWarnings("rawtypes") public class IndexNestLoopCursor extends JoinSchematicCursor implements IIndexNestLoopCursor { protected static enum IteratorDirection { FORWARD, BACKWARD } protected IRowSet left; protected IRowSet dup; protected IRowSet current; protected IteratorDirection iteratorDirection = null; protected boolean right_prefix; protected ISchematicCursor dup_cursor; protected CloneableRecord right_key; protected RecordCodec rightJoinOnColumnCodec; protected CloneableRecord left_key; public IndexNestLoopCursor(ISchematicCursor leftCursor, ISchematicCursor rightCursor, List leftJoinOnColumns, List rightJoinOnColumns, List columns, boolean prefix, List leftColumns, List rightColumns) throws TddlException{ super(leftCursor, rightCursor, leftJoinOnColumns, rightJoinOnColumns); this.right_prefix = prefix; this.orderBys = leftCursor.getOrderBy(); this.left_cursor = leftCursor; this.right_cursor = rightCursor; List<ColumnMeta> colMetas = ExecUtils.convertIColumnsToColumnMeta(rightJoinOnColumns); rightJoinOnColumnCodec = CodecFactory.getInstance(CodecFactory.FIXED_LENGTH).getCodec(colMetas); this.right_key = rightJoinOnColumnCodec.newEmptyRecord(); } /** * one of left join on columns */ public IndexNestLoopCursor(ISchematicCursor leftCursor, ISchematicCursor rightCursor, List leftJoinOnColumns, List rightJoinOnColumns, List columns, List leftColumns, List rightColumns) throws TddlException{ this(leftCursor, rightCursor, leftJoinOnColumns, rightJoinOnColumns, columns, false, leftColumns, rightColumns); } @Override public void beforeFirst() throws TddlException { left_cursor.beforeFirst(); } @Override public IRowSet current() throws TddlException { return current; } protected IRowSet getOneLeftCursor(boolean forward) throws TddlException { if (forward) { left = ExecUtils.fromIRowSetToArrayRowSet(left_cursor.next()); } else { left = ExecUtils.fromIRowSetToArrayRowSet(left_cursor.prev()); } return left; } @Override public IRowSet next() throws TddlException { if (iteratorDirection == null) { iteratorDirection = IteratorDirection.FORWARD; } else if (iteratorDirection == IteratorDirection.BACKWARD) { throw new IllegalStateException("亲,别折腾。。先前进再后退。。暂时不支持"); } /* * 左边的cursor next一次。然后右边的next一次拼装,如果有重复key的情况。 * 那么标记重复key为dup,利用重复key再次构建一个cursor。 */ if (!right_prefix) { IRowSet pair = proecessJoinOneWithNoneProfix(true); current = pair; return pair; } else { IRowSet pair = processJoinOneWithProfix(); current = pair; return pair; } } @Override public IRowSet prev() throws TddlException { if (iteratorDirection == null) { iteratorDirection = IteratorDirection.BACKWARD; } else if (iteratorDirection == IteratorDirection.FORWARD) { throw new IllegalStateException("亲,别折腾。。先前进再后退。。暂时不支持"); } if (!right_prefix) { IRowSet pair = proecessJoinOneWithNoneProfix(false); current = pair; return pair; } else { IRowSet pair = processJoinOneWithProfix(); current = pair; return pair; } } /** * 处理右值重复用。 左值不变,右值因为有相同key的值,所以取右,下移指针一次。 * * @return * @throws TddlException */ protected IRowSet processDuplicateValue() throws TddlException { IRowSet ret; ret = joinRecord(left, dup); if (!right_prefix) { dup = dup_cursor.getNextDup(); } else { dup = dup_cursor.next(); } return ret; } protected IRowSet processJoinOneWithProfix() throws TddlException { IRowSet ret = null; if (dup != null) { ret = processDuplicateValue(); return ret; } throw new UnsupportedOperationException(); } protected IRowSet proecessJoinOneWithNoneProfix(boolean forward) throws TddlException { IRowSet ret = null; if (dup != null) { ret = processDuplicateValue(); return ret; } while (getOneLeftCursor(forward) != null) { GeneralUtil.checkInterrupted(); putLeftCursorValueIntoReturnVal(); boolean hasVal = right_cursor.skipTo(left_key); if (hasVal) { IRowSet right = right_cursor.current(); ret = joinRecord(left, right); dup = right_cursor.getNextDup(); dup_cursor = right_cursor; return ret; } } return null; } /** * 将左面的Join on columns找到。 放到右边key这个对象里。 */ protected void putLeftCursorValueIntoReturnVal() { right_key = rightJoinOnColumnCodec.newEmptyRecord(); for (int k = 0; k < leftJoinOnColumns.size(); k++) { Object v = ExecUtils.getValueByIColumn(left, leftJoinOnColumns.get(k)); right_key.put(ExecUtils.getColumn(rightJoinOnColumns.get(k)).getColumnName(), v); } } @Override public String toString() { return toStringWithInden(0); } @Override public String toStringWithInden(int inden) { String tabTittle = GeneralUtil.getTab(inden); String tabContent = GeneralUtil.getTab(inden + 1); StringBuilder sb = new StringBuilder(); GeneralUtil.printlnToStringBuilder(sb, tabTittle + "IndexNestedLoopCursor "); GeneralUtil.printAFieldToStringBuilder(sb, "leftColumns", this.leftJoinOnColumns, tabContent); GeneralUtil.printAFieldToStringBuilder(sb, "rightColumns", this.rightJoinOnColumns, tabContent); GeneralUtil.printlnToStringBuilder(sb, tabContent + "left:"); sb.append(this.left_cursor.toStringWithInden(inden + 1)); GeneralUtil.printlnToStringBuilder(sb, tabContent + "right:"); sb.append(this.right_cursor.toStringWithInden(inden + 1)); return sb.toString(); } }