1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.infra.merge;
19
20 import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation;
21 import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
22 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
23 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResult;
24 import org.apache.shardingsphere.infra.merge.engine.ResultProcessEngine;
25 import org.apache.shardingsphere.infra.merge.engine.decorator.ResultDecorator;
26 import org.apache.shardingsphere.infra.merge.engine.decorator.ResultDecoratorEngine;
27 import org.apache.shardingsphere.infra.merge.engine.decorator.impl.TransparentResultDecorator;
28 import org.apache.shardingsphere.infra.merge.engine.merger.ResultMerger;
29 import org.apache.shardingsphere.infra.merge.engine.merger.ResultMergerEngine;
30 import org.apache.shardingsphere.infra.merge.result.MergedResult;
31 import org.apache.shardingsphere.infra.merge.result.impl.transparent.TransparentMergedResult;
32 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
33 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
34 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
35 import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
36 import org.apache.shardingsphere.infra.session.query.QueryContext;
37 import org.apache.shardingsphere.infra.spi.type.ordered.OrderedSPILoader;
38
39 import java.sql.SQLException;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Map.Entry;
43 import java.util.Optional;
44
45
46
47
48 @HighFrequencyInvocation
49 public final class MergeEngine {
50
51 private final ShardingSphereMetaData metaData;
52
53 private final ShardingSphereDatabase database;
54
55 private final ConfigurationProperties props;
56
57 @SuppressWarnings("rawtypes")
58 private final Map<ShardingSphereRule, ResultProcessEngine> engines;
59
60 private final ConnectionContext connectionContext;
61
62 public MergeEngine(final ShardingSphereMetaData metaData, final ShardingSphereDatabase database, final ConfigurationProperties props, final ConnectionContext connectionContext) {
63 this.metaData = metaData;
64 this.database = database;
65 this.props = props;
66 engines = OrderedSPILoader.getServices(ResultProcessEngine.class, database.getRuleMetaData().getRules());
67 this.connectionContext = connectionContext;
68 }
69
70
71
72
73
74
75
76
77
78 public MergedResult merge(final List<QueryResult> queryResults, final QueryContext queryContext) throws SQLException {
79 MergedResult mergedResult = executeMerge(queryResults, queryContext).orElseGet(() -> new TransparentMergedResult(queryResults.get(0)));
80 return decorate(mergedResult, queryContext);
81 }
82
83 @SuppressWarnings({"unchecked", "rawtypes"})
84 private Optional<MergedResult> executeMerge(final List<QueryResult> queryResults, final QueryContext queryContext) throws SQLException {
85 for (Entry<ShardingSphereRule, ResultProcessEngine> entry : engines.entrySet()) {
86 if (entry.getValue() instanceof ResultMergerEngine) {
87 ResultMerger resultMerger =
88 ((ResultMergerEngine) entry.getValue()).newInstance(database.getName(), database.getProtocolType(), entry.getKey(), props, queryContext.getSqlStatementContext());
89 return Optional.of(resultMerger.merge(queryResults, queryContext.getSqlStatementContext(), database, connectionContext));
90 }
91 }
92 return Optional.empty();
93 }
94
95 @SuppressWarnings({"unchecked", "rawtypes"})
96 private MergedResult decorate(final MergedResult mergedResult, final QueryContext queryContext) throws SQLException {
97 MergedResult result = null;
98 for (Entry<ShardingSphereRule, ResultProcessEngine> entry : engines.entrySet()) {
99 if (entry.getValue() instanceof ResultDecoratorEngine) {
100 ResultDecorator resultDecorator = getResultDecorator(queryContext.getSqlStatementContext(), entry.getValue());
101 result = null == result ? resultDecorator.decorate(mergedResult, queryContext, entry.getKey())
102 : resultDecorator.decorate(result, queryContext, entry.getKey());
103 }
104 }
105 return null == result ? mergedResult : result;
106 }
107
108 @SuppressWarnings({"unchecked", "rawtypes"})
109 private ResultDecorator getResultDecorator(final SQLStatementContext sqlStatementContext, final ResultProcessEngine resultProcessEngine) {
110 return (ResultDecorator) ((ResultDecoratorEngine) resultProcessEngine).newInstance(metaData, database, props, sqlStatementContext).orElseGet(TransparentResultDecorator::new);
111 }
112 }