ShardingSphere5.0.0-beta-jdbc-结果归并源码(三)

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));
    }

总结

  • 归并引擎的职责定位是进行多个数据库执行后结果集的合并,合并处理后的结果和数据库在一个库查询的效果是一样的,各数据节点的结果集之间是独立不关联的,在排序、分组、聚合等操作时,就需要对结果集进行归并处理,以屏蔽后端多个数据库给应用操作带来的差异性
  • 官方提供的图片
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值