1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.shadow.route.engine.impl;
19
20 import lombok.RequiredArgsConstructor;
21 import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
22 import org.apache.shardingsphere.infra.route.context.RouteContext;
23 import org.apache.shardingsphere.shadow.api.shadow.ShadowOperationType;
24 import org.apache.shardingsphere.shadow.api.shadow.hint.HintShadowAlgorithm;
25 import org.apache.shardingsphere.shadow.condition.ShadowDetermineCondition;
26 import org.apache.shardingsphere.shadow.route.engine.ShadowRouteEngine;
27 import org.apache.shardingsphere.shadow.route.engine.determiner.HintShadowAlgorithmDeterminer;
28 import org.apache.shardingsphere.shadow.rule.ShadowRule;
29 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.CommentSegment;
30 import org.apache.shardingsphere.sql.parser.sql.common.statement.AbstractSQLStatement;
31
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.Map;
35 import java.util.Optional;
36 import java.util.stream.Collectors;
37
38
39
40
41 @RequiredArgsConstructor
42 public final class ShadowNonDMLStatementRoutingEngine implements ShadowRouteEngine {
43
44 private final SQLStatementContext sqlStatementContext;
45
46 @Override
47 public void route(final RouteContext routeContext, final ShadowRule rule) {
48 decorateRouteContext(routeContext, rule, findShadowDataSourceMappings(rule));
49 }
50
51 private Map<String, String> findShadowDataSourceMappings(final ShadowRule rule) {
52 Optional<Collection<String>> sqlComments = parseSQLComments();
53 if (!sqlComments.isPresent()) {
54 return Collections.emptyMap();
55 }
56 if (isMatchAnyNoteShadowAlgorithms(rule, createShadowDetermineCondition(sqlComments.get()))) {
57 return rule.getAllShadowDataSourceMappings();
58 }
59 return Collections.emptyMap();
60 }
61
62 private Optional<Collection<String>> parseSQLComments() {
63
64 Collection<String> result = ((AbstractSQLStatement) sqlStatementContext.getSqlStatement()).getCommentSegments().stream().map(CommentSegment::getText).collect(Collectors.toList());
65 return result.isEmpty() ? Optional.empty() : Optional.of(result);
66 }
67
68 private ShadowDetermineCondition createShadowDetermineCondition(final Collection<String> sqlComments) {
69 return new ShadowDetermineCondition("", ShadowOperationType.HINT_MATCH).initSQLComments(sqlComments);
70 }
71
72 private boolean isMatchAnyNoteShadowAlgorithms(final ShadowRule rule, final ShadowDetermineCondition shadowCondition) {
73 for (HintShadowAlgorithm<Comparable<?>> each : rule.getAllHintShadowAlgorithms()) {
74 if (HintShadowAlgorithmDeterminer.isShadow(each, shadowCondition, rule)) {
75 return true;
76 }
77 }
78 return false;
79 }
80 }