package org.opencloudb.mpp; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.opencloudb.net.mysql.RowDataPacket; import org.opencloudb.util.ByteUtil; import org.opencloudb.util.CompareUtil; public class RowDataPacketSorter { private final OrderCol[] orderCols; private List<RowDataPacket> sorted = new ArrayList<RowDataPacket>(); private RowDataPacket[] array, resultTemp; private int p1, pr, p2; public RowDataPacketSorter(OrderCol[] orderCols) { super(); this.orderCols = orderCols; } public void addRow(RowDataPacket row) { this.sorted.add(row); } public Collection<RowDataPacket> getSortedResult() { try { this.mergeSort(sorted.toArray(new RowDataPacket[sorted.size()])); } catch (Exception e) { } Collections.addAll(this.sorted,array); return sorted; } private RowDataPacket[] mergeSort(RowDataPacket[] result) throws Exception { this.sorted.clear(); if (result == null || result.length < 2 || this.orderCols == null || orderCols.length < 1) { return result; } array = result; mergeR(0, result.length - 1); return array; } private void mergeR(int startIndex, int endIndex) { if (startIndex < endIndex) { int mid = (startIndex + endIndex) / 2; mergeR(startIndex, mid); mergeR(mid + 1, endIndex); merge(startIndex, mid, endIndex); } } private void merge(int startIndex, int midIndex, int endIndex) { resultTemp = new RowDataPacket[(endIndex - startIndex + 1)]; pr = 0; p1 = startIndex; p2 = midIndex + 1; while (p1 <= midIndex || p2 <= endIndex) { if (p1 == midIndex + 1) { while (p2 <= endIndex) { resultTemp[pr++] = array[p2++]; } } else if (p2 == endIndex + 1) { while (p1 <= midIndex) { resultTemp[pr++] = array[p1++]; } } else { compare(0); } } for (p1 = startIndex, p2 = 0; p1 <= endIndex; p1++, p2++) { array[p1] = resultTemp[p2]; } } /** * 递归按照排序字段进行排序 * * @param byColumnIndex */ private void compare(int byColumnIndex) { if (byColumnIndex == this.orderCols.length) { if(this.orderCols[byColumnIndex - 1].orderType == OrderCol.COL_ORDER_TYPE_ASC){ resultTemp[pr++] = array[p1++]; } else { resultTemp[pr++] = array[p2++]; } return; } byte[] left = array[p1].fieldValues.get(this.orderCols[byColumnIndex].colMeta.colIndex); byte[] right = array[p2].fieldValues.get(this.orderCols[byColumnIndex].colMeta.colIndex); if (compareObject(left, right, this.orderCols[byColumnIndex]) <= 0) { if (compareObject(left, right, this.orderCols[byColumnIndex]) < 0) { if (this.orderCols[byColumnIndex].orderType == OrderCol.COL_ORDER_TYPE_ASC) {// 升序 resultTemp[pr++] = array[p1++]; } else { resultTemp[pr++] = array[p2++]; } } else {// 如果当前字段相等,则按照下一个字段排序 compare(byColumnIndex + 1); } } else { if (this.orderCols[byColumnIndex].orderType == OrderCol.COL_ORDER_TYPE_ASC) {// 升序 resultTemp[pr++] = array[p2++]; } else { resultTemp[pr++] = array[p1++]; } } } private int compareObject(Object l, Object r, OrderCol orderCol) { int colType = orderCol.getColMeta().getColType(); byte[] left = (byte[]) l; byte[] right = (byte[]) r; // System.out.println("------------" + colType); switch (colType) { case ColMeta.COL_TYPE_INT: return CompareUtil.compareInt(ByteUtil.getInt(left), ByteUtil.getInt(right)); case ColMeta.COL_TYPE_LONG: case ColMeta.COL_TYPE_NEWDECIMAL: return CompareUtil.compareLong(ByteUtil.getLong(left), ByteUtil.getLong(right)); case ColMeta.COL_TYPE_VAR_STRING: return CompareUtil.compareString(ByteUtil.getString(left), ByteUtil.getString(right)); case ColMeta.COL_TYPE_BIT: return CompareUtil.compareChar(ByteUtil.getChar(left), ByteUtil.getChar(right)); case ColMeta.COL_TYPE_DOUBLE: return CompareUtil.compareDouble(ByteUtil.getDouble(left), ByteUtil.getDouble(right)); case ColMeta.COL_TYPE_FLOAT: return CompareUtil.compareFloat(ByteUtil.getFloat(left), ByteUtil.getFloat(right)); case ColMeta.COL_TYPE_DATE: return CompareUtil.compareString(ByteUtil.getDate(left), ByteUtil.getDate(right)); case ColMeta.COL_TYPE_TIMSTAMP: return CompareUtil.compareString(ByteUtil.getTimestmap(left), ByteUtil.getTimestmap(right)); case ColMeta.COL_TYPE_TIME: return CompareUtil.compareString(ByteUtil.getTimestmap(left), ByteUtil.getTimestmap(right)); } return 0; } }