/* * Copyright 2015 Liu Huanting. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package fm.liu.timo.merger; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import fm.liu.timo.mysql.packet.RowDataPacket; import fm.liu.timo.route.Info; import fm.liu.timo.route.Outlets; /** * @author Liu Huanting 2015年6月4日 * <p> * 多节点结果集合并器 */ public class Merger { private Grouper grouper; private Sorter sorter; private Distincter distincter; private ArrayDeque<RowDataPacket> rows; private Outlets outlets; private int fieldCount; public Merger(Outlets outlets) { this.outlets = outlets; this.rows = new ArrayDeque<RowDataPacket>(); } public ArrayDeque<RowDataPacket> getResult() { if (grouper != null) { grouper.offer(rows); rows = grouper.getResult(); } if (sorter != null) { sorter.offer(rows); rows = sorter.getResult(); } if (distincter != null) { distincter.offer(rows); rows = distincter.getResult(); } return rows; } public void init(Map<String, ColumnInfo> columnInfos, int fieldCount) { this.fieldCount = fieldCount; int info = outlets.getInfo(); MergeInfo[] groupBy = null; ArrayList<MergeInfo> lsit = new ArrayList<MergeInfo>(); if ((info & Info.HAS_GROUPBY) == Info.HAS_GROUPBY) { Set<String> columns = outlets.getGroupBy(); groupBy = new MergeInfo[columns.size()]; int i = 0; for (String column : columns) { ColumnInfo columnInfo = columnInfos.get(column); if (columnInfo == null) { throw new IllegalArgumentException("can't find group by column in select list"); } groupBy[i++] = new MergeInfo(MergeType.ASC, columnInfo); } } if ((info & Info.NEED_MERGE) == Info.NEED_MERGE) { for (String column : columnInfos.keySet()) { int result = MergeInfo.getType(column); if (result != MergeType.UNSUPPORT) { lsit.add(new MergeInfo(result, columnInfos.get(column))); } } this.grouper = new Grouper(groupBy, lsit.toArray(new MergeInfo[lsit.size()])); } else if ((info & Info.HAS_GROUPBY) == Info.HAS_GROUPBY) { Set<String> columns = outlets.getGroupBy(); for (String column : columns) { lsit.add(new MergeInfo(MergeType.NOMERGE, columnInfos.get(column))); } this.grouper = new Grouper(groupBy, lsit.toArray(new MergeInfo[lsit.size()])); } if ((info & Info.HAS_ORDERBY) == Info.HAS_ORDERBY) { Map<String, Integer> orderBy = outlets.getOrderBy(); MergeInfo[] mergeInfo = new MergeInfo[orderBy.size()]; int i = 0; for (Entry<String, Integer> entry : orderBy.entrySet()) { mergeInfo[i++] = new MergeInfo(entry.getValue(), columnInfos.get(entry.getKey())); } this.sorter = new Sorter(mergeInfo); } } public void offer(byte[] row) { RowDataPacket packet = new RowDataPacket(fieldCount); packet.read(row); rows.add(packet); } public Outlets getOutlets() { return this.outlets; } }