package com.taobao.tddl.executor.cursor.impl; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; import org.apache.commons.lang.StringUtils; import com.taobao.tddl.common.utils.GeneralUtil; import com.taobao.tddl.executor.common.IRowsValueScaner; import com.taobao.tddl.executor.common.RowsValueScanerImp; import com.taobao.tddl.executor.cursor.ICursorMeta; import com.taobao.tddl.executor.utils.ExecUtils; import com.taobao.tddl.optimizer.config.table.ColumnMessage; import com.taobao.tddl.optimizer.config.table.ColumnMeta; import com.taobao.tddl.optimizer.core.expression.ISelectable; public class CursorMetaImp implements ICursorMeta { private CursorMetaImp(String name, List<ColumnMessage> columns, Integer indexRange){ super(); // this.name = name; this.columns = new ArrayList<ColumnMeta>(); this.indexRange = indexRange; int index = 0; for (ColumnMessage cm : columns) { String colName = cm.getName(); String tabName = name; addAColumn(tabName, colName, cm.getAlias(), index); this.columns.add(new ColumnMeta(name, cm.getName(), cm.getDataType(), cm.getAlias(), cm.getNullable())); index++; } } private CursorMetaImp(String name, List<ColumnMessage> columns, List<Integer> indexes, Integer indexRange){ // this.name = name; this.columns = new ArrayList<ColumnMeta>(); Iterator<Integer> iteratorIndex = indexes.iterator(); for (ColumnMessage cm : columns) { if (!iteratorIndex.hasNext()) { throw new IllegalArgumentException("iterator and columns not match"); } String colName = cm.getName(); String tabName = name; addAColumn(tabName, colName, cm.getAlias(), iteratorIndex.next()); this.columns.add(new ColumnMeta(name, cm.getName(), cm.getDataType(), cm.getAlias(), cm.getNullable())); } this.indexRange = indexRange; } private CursorMetaImp(List<ColumnMeta> columns, List<Integer> indexes, Integer indexRange){ this.columns = new ArrayList<ColumnMeta>(columns); Iterator<Integer> iteratorIndex = indexes.iterator(); for (ColumnMeta cm : columns) { if (!iteratorIndex.hasNext()) { throw new IllegalArgumentException("iterator and columns not match"); } String colName = cm.getName(); String tabName = cm.getTableName(); addAColumn(tabName, colName, cm.getAlias(), iteratorIndex.next()); } this.indexRange = indexRange; } private CursorMetaImp(List<ColumnMeta> columns, Integer indexRange){ super(); this.columns = new ArrayList<ColumnMeta>(columns); int index = 0; for (ColumnMeta cm : columns) { String colName = cm.getName(); String tabName = cm.getTableName(); addAColumn(tabName, colName, cm.getAlias(), index); index++; } this.indexRange = indexRange; } private CursorMetaImp(List<ColumnMeta> columns){ super(); this.columns = new ArrayList<ColumnMeta>(columns); int index = 0; for (ColumnMeta cm : columns) { String colName = cm.getName(); String tabName = cm.getTableName(); addAColumn(tabName, colName, cm.getAlias(), index); index++; } if (indexMap == null) { indexMap = new HashMap<String, CursorMetaImp.ColumnHolder>(); } this.indexRange = index; } /** * 就是表名+index 因为可能出现多个表有相同列的情况。 但从速度上考虑,列必然应该做hash,否则效率太低了。表重的可能性,有,但不会很多。 * 所以不想用map结构。 * * @author whisper */ public static class ColumnHolder { public ColumnHolder(ColumnHolder next, String tablename, Integer index){ super(); this.next = next; this.tablename = tablename; this.index = index; } /** * 如果有同列名,不同表名,放这里, 预计不会出现很多这样的情况。 */ ColumnHolder next = null; /** * 表名 */ String tablename = null; /** * indexName */ Integer index = null; @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("ColumnHolder [\t"); if (next != null) { builder.append("next:"); builder.append(next); builder.append(", \t"); } if (tablename != null) { builder.append("tablename:"); builder.append(tablename); builder.append(",\t"); } if (index != null) { builder.append("index:"); builder.append(index); } builder.append("]\n"); return builder.toString(); } } private String name; private List<ColumnMeta> columns; private Map<String/* 列名字哦。注意,不是表名,因为列名更长取,量也更大 */, ColumnHolder> indexMap = null; private Integer indexRange; private boolean isSureLogicalIndexEqualActualIndex; @Override public Integer getIndexRange() { return indexRange; } // @Override // public String getName() { // return name; // } @Override public List<ColumnMeta> getColumns() { return Collections.unmodifiableList(columns); } @Override public Integer getIndex(String tableName, String columnName) { tableName = ExecUtils.getLogicTableName(tableName); ColumnHolder ch = indexMap.get(columnName); if (ch == null) { return null; } // 第一个P Integer index = null; if (tableName == null /* || ch.next == null */) {// hook tableName == // null.取第一个,如果没有下一个,那么无论表名是什么都返回当前的。。因为没的选择。 return ch.index; } index = findTableName(tableName, ch); if (index != null) { return index; } ColumnHolder nextCh = ch; // 其它的ColumnHolder while ((nextCh = nextCh.next) != null) { index = findTableName(tableName, nextCh); if (index != null) { return index; } } // throw new IllegalArgumentException("can't find Index by tableName : " // + tableName + " colname : " + columnName + " .index Map : " // + indexMap); return null; } private static Integer findTableName(String tableName, ColumnHolder ch) { if (StringUtils.equals(tableName, ch.tablename)) { return ch.index; } return null; } public Map<String, ColumnHolder> getIndexMap() { return Collections.unmodifiableMap(indexMap); } public static CursorMetaImp buildNew(List<ColumnMeta> columns) { return new CursorMetaImp(columns); } public static CursorMetaImp buildNew(String name, List<ColumnMessage> columns, Integer indexRange) { return new CursorMetaImp(name, columns, indexRange); } public static CursorMetaImp buildNew(List<ColumnMeta> columns, Integer indexRange) { return new CursorMetaImp(columns, indexRange); } public static CursorMetaImp buildNew(String name, List<ColumnMessage> columns, List<Integer> indexes, Integer indexRange) { return new CursorMetaImp(name, columns, indexes, indexRange); } public static CursorMetaImp buildNew(List<ColumnMeta> columns, List<Integer> indexes, Integer indexRange) { return new CursorMetaImp(columns, indexes, indexRange); } protected void addAColumn(String tableName, String colName, String colAlias, Integer index) { if (indexMap == null) { indexMap = new HashMap<String, CursorMetaImp.ColumnHolder>(); } // if (aliasIndexMap == null) { // aliasIndexMap = new HashMap<String, CursorMetaImp.ColumnHolder>(); // } tableName = ExecUtils.getLogicTableName(tableName); ColumnHolder ch = indexMap.get(colName); if (ch == null) { ch = new ColumnHolder(null, tableName, index); indexMap.put(colName, ch); // if (colAlias != null) aliasIndexMap.put(colAlias, ch); return; } boolean success = findTableAndReplaceIndexNumber(tableName, index, ch); if (success) { return; } ColumnHolder nextCh = null; // 其它的ColumnHolder while ((nextCh = ch.next) != null) { success = findTableAndReplaceIndexNumber(tableName, index, nextCh); if (success) { return; } } } // protected void addAColumn(Map<String, ColumnHolder> columnHolderMap, // String tableName, String colName, Integer index) { // // } /** * 如果能找到同表名的,就替换对应的index 如果不能找到,但链表下一个为空,则构建新的ColumnHolder 放到队尾,也算成功 其他算失败 * * @param tableName * @param index * @param ch * @return */ private static boolean findTableAndReplaceIndexNumber(String tableName, Integer index, ColumnHolder ch) { boolean success = false; if (StringUtils.equals(tableName, ch.tablename)) { ch.index = index; success = true; } else if (ch.next == null) { ch.next = new ColumnHolder(null, tableName, index); success = true; } return success; } @Override public String toStringWithInden(int inden) { StringBuilder sb = new StringBuilder(); String tabTittle = GeneralUtil.getTab(inden); sb.append(tabTittle).append("["); sb.append("cursor meta name : ").append(name).append("\t"); List<ColumnMeta> metas = columns; if (metas != null) { for (ColumnMeta cm : metas) { sb.append(cm.toStringWithInden(0)).append(":"); sb.append(getIndex(cm.getTableName(), cm.getName())); sb.append(" "); } } return sb.toString(); } private static class IndexMetaIterator implements Iterator<ColMetaAndIndex> { Iterator<Entry<String, ColumnHolder>> entryIterator = null; /** * 临时iterator 因为可能出现同列名,不同表名的情况 */ ColMetaAndIndex current = null; public IndexMetaIterator(Map<String/* 列名字 */, ColumnHolder> indexMap){ entryIterator = indexMap.entrySet().iterator(); } @Override public boolean hasNext() { if (current == null) { return entryIterator.hasNext(); } else { boolean hasNext = current.getColumnHolder().next != null; if (!hasNext) { current = null; hasNext = hasNext(); } return hasNext; } } @Override public ColMetaAndIndex next() { if (current == null) { current = new ColMetaAndIndex(); Entry<String, ColumnHolder> entry = entryIterator.next(); if (entry == null) { throw new NoSuchElementException(); } else { current.setColumnHolder(entry.getValue()); current.setName(entry.getKey()); return current; } } else { ColumnHolder chNext = current.getColumnHolder().next; if (chNext != null) { current.setColumnHolder(chNext); return current; } else { current = null; return next(); } } } @Override public void remove() { throw new IllegalStateException(); } } @Override public Iterator<ColMetaAndIndex> indexIterator() { return new IndexMetaIterator(indexMap); } @Override public IRowsValueScaner scaner(List<ISelectable> columnsYouWant) { RowsValueScanerImp rvs = new RowsValueScanerImp(this, columnsYouWant); return rvs; } @Override public String toString() { return toStringWithInden(0); } @Override public boolean isSureLogicalIndexEqualActualIndex() { return this.isSureLogicalIndexEqualActualIndex; } @Override public void setIsSureLogicalIndexEqualActualIndex(boolean b) { this.isSureLogicalIndexEqualActualIndex = b; } public static ICursorMeta buildEmpty() { List<ColumnMeta> empty = Collections.emptyList(); return new CursorMetaImp(empty); } }