ShardingSphere5.0.0-beta-jdbc-结果归并源码(三)
目录
- SQL结果并归
- 总结
结果归并
- this.resultSetHandler.handleResultSets(ps)
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(this.mappedStatement.getId());
List<Object> multipleResults = new ArrayList();
int resultSetCount = 0;
//获取到并归后的包装结果
ResultSetWrapper rsw = this.getFirstResultSet(stmt);
List<ResultMap> resultMaps = this.mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
this.validateResultMapsCount(rsw, resultMapCount);
while(rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = (ResultMap)resultMaps.get(resultSetCount);
this.handleResultSet(rsw, resultMap, multipleResults, (ResultMapping)null);
rsw = this.getNextResultSet(stmt);
this.cleanUpAfterHandlingResultSet();
++resultSetCount;
}
String[] resultSets = this.mappedStatement.getResultSets();
if (resultSets != null) {
while(rsw != null && resultSetCount < resultSets.length) {
ResultMapping parentMapping = (ResultMapping)this.nextResultMaps.get(resultSets[resultSetCount]);
if (parentMapping != null) {
String nestedResultMapId = parentMapping.getNestedResultMapId();
ResultMap resultMap = this.configuration.getResultMap(nestedResultMapId);
this.handleResultSet(rsw, resultMap, (List)null, parentMapping);
}
rsw = this.getNextResultSet(stmt);
this.cleanUpAfterHandlingResultSet();
++resultSetCount;
}
}
return this.collapseSingleResultList(multipleResults);
}
- ResultSetWrapper rsw = this.getFirstResultSet(stmt)
private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
//核心处理,stmt对象是ShardingSpherePreparedStatement
ResultSet rs = stmt.getResultSet();
while(rs == null) {
if (stmt.getMoreResults()) {
rs = stmt.getResultSet();
} else if (stmt.getUpdateCount() == -1) {
break;
}
}
return rs != null ? new ResultSetWrapper(rs, this.configuration) : null;
}
#########################################################
public ResultSet getResultSet() throws SQLException {
if (null != this.currentResultSet) {
return this.currentResultSet;
} else {
if (this.executionContext.getSqlStatementContext() instanceof SelectStatementContext || this.executionContext.getSqlStatementContext().getSqlStatement() instanceof DALStatement) {
//遍历PreparedStatement对象,把结果集统一保存到List<ResultSet>返回
List<ResultSet> resultSets = this.getResultSets();
// 执行结果归并
MergedResult mergedResult = this.mergeQuery(this.getQueryResults(resultSets));
this.currentResultSet = new ShardingSphereResultSet(resultSets, mergedResult, this, this.executionContext);
}
return this.currentResultSet;
}
}
- ShardingSpherePreparedStatement#getResultSet
List resultSets = this.getResultSets():遍历PreparedStatement对象,把结果集统一保存到List返回
private List<ResultSet> getResultSets() throws SQLException {
List<ResultSet> result = new ArrayList(this.statements.size());
// this.statements对应List<PreparedStatement>,在sql执行完成后设置值的
Iterator var2 = this.statements.iterator();
//遍历PreparedStatement对象,把结果集统一保存到List<ResultSet>返回
while(var2.hasNext()) {
Statement each = (Statement)var2.next();
result.add(each.getResultSet());
}
if (this.executionContext.getRouteContext().isFederated()) {
result.add(this.federateExecutor.getResultSet());
}
return result;
}
- this.mergeQuery(this.getQueryResults(resultSets))
this.getQueryResults(resultSets)
:将多个路由执行的结果集封装在 queryResults 列表中
private MergedResult mergeQuery(List<QueryResult> queryResults) throws SQLException {
//拿到分片的规则元数据
ShardingSphereMetaData metaData = this.metaDataContexts.getDefaultMetaData();
//根据数据库类型,分片规则创建执行引擎
MergeEngine mergeEngine = new MergeEngine(this.metaDataContexts.getDefaultMetaData().getResource().getDatabaseType(), metaData.getSchema(), this.metaDataContexts.getProps(), metaData.getRuleMetaData().getRules());
//执行结果归并
return mergeEngine.merge(queryResults, this.executionContext.getSqlStatementContext());
}
#########################################################
public MergedResult merge(List<QueryResult> queryResults, SQLStatementContext<?> sqlStatementContext) throws SQLException {
Optional<MergedResult> mergedResult = this.executeMerge(queryResults, sqlStatementContext);
//合并后结果的装饰 加解密 :EncryptDQLResultDecorator EncryptDALResultDecorator TransparentResultDecorator
Optional<MergedResult> result = mergedResult.isPresent() ? Optional.of(this.decorate((MergedResult)mergedResult.get(), sqlStatementContext)) : this.decorate((QueryResult)queryResults.get(0), sqlStatementContext);
return (MergedResult)result.orElseGet(() -> {
return new TransparentMergedResult((QueryResult)queryResults.get(0));
});
}
//this.executeMerge(queryResults, sqlStatementContext)
//根据SQLStatementContext类型的种类创建不同的ResultMerger实例。如果是SQL是Select,则创建ShardingDQLResultMerger对象;如果是DAL语句(show database、show table 等),则创建ShardingDALResultMerger对象
private Optional<MergedResult> executeMerge(List<QueryResult> queryResults, SQLStatementContext<?> sqlStatementContext) throws SQLException {
Iterator var3 = this.engines.entrySet().iterator();
Entry entry;
do {
if (!var3.hasNext()) {
return Optional.empty();
}
entry = (Entry)var3.next();
} while(!(entry.getValue() instanceof ResultMergerEngine));
//根据SQLStatementContext类型的种类创建不同的ResultMerger实例。如果是SQL是Select,则创建ShardingDQLResultMerger对象;如果是DAL语句(show database、show table 等),则创建ShardingDALResultMerger对象
ResultMerger resultMerger = ((ResultMergerEngine)entry.getValue()).newInstance(this.databaseType, (ShardingSphereRule)entry.getKey(), this.props, sqlStatementContext);
return Optional.of(resultMerger.merge(queryResults, sqlStatementContext, this.schema));
}
- 我们直接分析ShardingDQLResultMerger#merge
-
首先生成columnLabel位置下标的Map,然后传入SelectStatementContext.setIndexes方法,进行聚合projecttion、group by、order by设置其对应的columnLabel所在位置下标,这些下标会在GroupByStreamMergedResult的等类中访问。
-
build方法中判断是否需要处理group by、distinct以及order by,然后返回对应的
MergedResult实现类。这些实现类是合并结果集的真正逻辑所在。 -
getGroupByMergedResult方法中判断group by与order by的列是否一样,如果是则创建GroupByStreamMergedResult实例,否则创建GroupByMemoryMergedResult实例,前者为基于流方式,后者为基于内存方式
-
public MergedResult merge(List<QueryResult> queryResults, SQLStatementContext<?> sqlStatementContext, ShardingSphereSchema schema) throws SQLException {
if (1 == queryResults.size()) {
return new IteratorStreamMergedResult(queryResults);
} else {
Map<String, Integer> columnLabelIndexMap = this.getColumnLabelIndexMap((QueryResult)queryResults.get(0));
SelectStatementContext selectStatementContext = (SelectStatementContext)sqlStatementContext;
selectStatementContext.setIndexes(columnLabelIndexMap);
MergedResult mergedResult = this.build(queryResults, selectStatementContext, columnLabelIndexMap, schema);
return this.decorate(queryResults, selectStatementContext, mergedResult);
}
}
private MergedResult build(List<QueryResult> queryResults, SelectStatementContext selectStatementContext, Map<String, Integer> columnLabelIndexMap, ShardingSphereSchema schema) throws SQLException {
if (this.isNeedProcessGroupBy(selectStatementContext)) {
return this.getGroupByMergedResult(queryResults, selectStatementContext, columnLabelIndexMap, schema);
} else if (this.isNeedProcessDistinctRow(selectStatementContext)) {
this.setGroupByForDistinctRow(selectStatementContext);
return this.getGroupByMergedResult(queryResults, selectStatementContext, columnLabelIndexMap, schema);
} else {
return (MergedResult)(this.isNeedProcessOrderBy(selectStatementContext) ? new OrderByStreamMergedResult(queryResults, selectStatementContext, schema) : new IteratorStreamMergedResult(queryResults));
}
}
private MergedResult getGroupByMergedResult(List<QueryResult> queryResults, SelectStatementContext selectStatementContext, Map<String, Integer> columnLabelIndexMap, ShardingSphereSchema schema) throws SQLException {
return (MergedResult)(selectStatementContext.isSameGroupByAndOrderByItems() ? new GroupByStreamMergedResult(columnLabelIndexMap, queryResults, selectStatementContext, schema) : new GroupByMemoryMergedResult(queryResults, selectStatementContext, schema));
}
总结
- 归并引擎的职责定位是进行多个数据库执行后结果集的合并,合并处理后的结果和数据库在一个库查询的效果是一样的,各数据节点的结果集之间是独立不关联的,在排序、分组、聚合等操作时,就需要对结果集进行归并处理,以屏蔽后端多个数据库给应用操作带来的差异性
- 官方提供的图片