/*
* Copyright 1999-2015 dangdang.com.
*
* 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 com.dangdang.ddframe.rdb.sharding.parser.result.merger;
import com.dangdang.ddframe.rdb.sharding.executor.ExecutorEngine;
import com.dangdang.ddframe.rdb.sharding.merger.component.other.WrapperResultSet;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 结果归并上下文.
*
* @author zhangliang
*/
@Getter
@ToString
public final class MergeContext {
private final List orderByColumns = new ArrayList<>();
private final List groupByColumns = new ArrayList<>();
private final List aggregationColumns = new ArrayList<>();
@Setter
private Limit limit;
@Setter
private ExecutorEngine executorEngine;
private Map columnLabelIndexMap;
private final List currentOrderByKeys = new LinkedList<>();
/**
* 是否包含分组.
*
* @return 是否包含分组
*/
public boolean hasGroupBy() {
return !groupByColumns.isEmpty();
}
/**
* 判断是否为分组或者聚合计算.
* 此处将聚合计算想象成为特殊的分组计算,统一进行处理.
*
* @return true:是分组或者聚合计算 false:不是分组且不是聚合计算
*/
public boolean hasGroupByOrAggregation() {
return hasGroupBy() || !aggregationColumns.isEmpty();
}
/**
* 是否包含排序列.
*
* @return true 包含 false 不包含
*/
public boolean hasOrderBy() {
return !orderByColumns.isEmpty();
}
/**
* 判断是否为排序计算并且是否需要进行排序.
*
* @return true:是排序计算 false:不是排序计算
*/
public boolean needToSort() {
return hasOrderBy() && !equalsOrderByKeys(orderByColumns);
}
/**
* 分组排序结果与底层排序是否相同.
* 不同就修改底层排序键为分组排序键
*
* @return true 相同 false 不同
*/
public boolean groupByKeysEqualsOrderByKeys() {
List orderByKeysFromGroupByColumns = Lists.transform(groupByColumns, new Function() {
@Override
public OrderByColumn apply(final GroupByColumn input) {
OrderByColumn result = new OrderByColumn(input.getOwner(), input.getName().get(), input.getAlias(), input.getOrderByType());
result.setColumnIndex(input.getColumnIndex());
return result;
}
});
return equalsOrderByKeys(orderByKeysFromGroupByColumns);
}
private boolean equalsOrderByKeys(final List expectedOrderByKeys) {
if (currentOrderByKeys.equals(expectedOrderByKeys)) {
return true;
}
currentOrderByKeys.clear();
currentOrderByKeys.addAll(expectedOrderByKeys);
return false;
}
/**
* 判断是否有限定结果集计算.
*
* @return true:是限定结果集计算 false:不是限定结果集计算
*/
public boolean hasLimit() {
return limit != null;
}
/**
* 使用结果集构造合并上下文信息.
*
* @param resultSet 结果集
* @throws SQLException 访问结果集可能抛出的异常抛出
*/
public void buildContextWithResultSet(final WrapperResultSet resultSet) throws SQLException {
columnLabelIndexMap = resultSet.getColumnLabelIndexMap();
setColumnIndex();
currentOrderByKeys.addAll(orderByColumns);
}
private void setColumnIndex() {
for (IndexColumn each : extractFocusedColumns()) {
if (each.getColumnIndex() > 0) {
continue;
}
Preconditions.checkState(columnLabelIndexMap.containsKey(each.getColumnLabel().orNull()) || columnLabelIndexMap.containsKey(each.getColumnName().orNull()),
String.format("%s has not index", each));
if (each.getColumnLabel().isPresent() && columnLabelIndexMap.containsKey(each.getColumnLabel().get())) {
each.setColumnIndex(columnLabelIndexMap.get(each.getColumnLabel().get()));
} else if (each.getColumnName().isPresent() && columnLabelIndexMap.containsKey(each.getColumnName().get())) {
each.setColumnIndex(columnLabelIndexMap.get(each.getColumnName().get()));
}
}
}
private List extractFocusedColumns() {
List result = new LinkedList<>();
result.addAll(groupByColumns);
result.addAll(orderByColumns);
LinkedList allAggregationColumns = Lists.newLinkedList(aggregationColumns);
while (allAggregationColumns.size() > 0) {
AggregationColumn head = allAggregationColumns.poll();
result.add(head);
if (head.getDerivedColumns().isEmpty()) {
continue;
}
allAggregationColumns.addAll(head.getDerivedColumns());
}
return result;
}
}