Skip to content

Commit 8f592a6

Browse files
committed
支持RouteRule配置不包含tbName
1 parent bb2c1f2 commit 8f592a6

File tree

2 files changed

+167
-53
lines changed

2 files changed

+167
-53
lines changed

ddal-ddr/src/main/java/org/hellojavaer/ddal/ddr/datasource/manager/rw/DefaultReadWriteDataSourceManager.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,12 @@ private void check(Connection conn, String scName) {
565565
return;
566566
}
567567
Map<String, Set<String>> physicalTables = getPhysicalTables();
568-
metaDataChecker.check(conn, scName, physicalTables.get(scName));
568+
if (physicalTables != null) {
569+
Set<String> tbNames = physicalTables.get(scName);
570+
if (tbNames != null && !tbNames.isEmpty()) {
571+
metaDataChecker.check(conn, scName, tbNames);
572+
}
573+
}
569574
}
570575

571576
private void initWriteOnlyDataSource(List<WriteOnlyDataSourceBinding> bindings) {

ddal-ddr/src/main/java/org/hellojavaer/ddal/ddr/shard/simple/SimpleShardRouter.java

Lines changed: 161 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
*/
1616
package org.hellojavaer.ddal.ddr.shard.simple;
1717

18-
import org.hellojavaer.ddal.ddr.expression.range.RangeExpressionParser;
18+
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
19+
import com.googlecode.concurrentlinkedhashmap.Weighers;
1920
import org.hellojavaer.ddal.ddr.expression.range.RangeExpressionItemVisitor;
21+
import org.hellojavaer.ddal.ddr.expression.range.RangeExpressionParser;
2022
import org.hellojavaer.ddal.ddr.shard.*;
2123
import org.hellojavaer.ddal.ddr.shard.exception.*;
2224
import org.hellojavaer.ddal.ddr.utils.DDRStringUtils;
@@ -31,11 +33,21 @@
3133
*/
3234
public class SimpleShardRouter implements ShardRouter {
3335

34-
private Logger logger = LoggerFactory.getLogger(getClass());
35-
private List<SimpleShardRouteRuleBinding> routeRuleBindings = null;
36-
private Map<String, InnerSimpleShardRouteRuleBindingWrapper> cache = Collections.EMPTY_MAP;
37-
private Map<String, List<ShardRouteInfo>> routeInfoMap = new HashMap<>();
38-
private Map<String, Set<String>> routedTables = new HashMap<>();
36+
private Logger logger = LoggerFactory.getLogger(getClass());
37+
38+
// schema+table级路由配置
39+
private List<SimpleShardRouteRuleBinding> routeRuleBindings = null;
40+
private Map<String, InnerSimpleShardRouteRuleBindingWrapper> routeInfoCache = Collections.EMPTY_MAP;
41+
private Map<String, List<ShardRouteInfo>> routeInfosCache = new HashMap<>();
42+
private Map<String, Set<String>> routedTables = new HashMap<>();
43+
44+
// schema级路由配置
45+
private Map<String, SimpleShardRouteRuleBinding> schemaBindingMap = new HashMap<>();
46+
private SimpleShardRouteRuleBinding defaultSchemaBinding = null;
47+
private Map<String, List<ShardRouteInfo>> routeInfosCacheForSchemaLevel = new ConcurrentLinkedHashMap.Builder<String, List<ShardRouteInfo>>()//
48+
.maximumWeightedCapacity(10000)//
49+
.weigher(Weighers.singleton())//
50+
.build();
3951

4052
private SimpleShardRouter() {
4153
}
@@ -63,47 +75,54 @@ public void setRouteRuleBindings(List<SimpleShardRouteRuleBinding> bindings) {
6375
if (scName == null) {
6476
throw new IllegalArgumentException("'scName' can't be empty");
6577
}
66-
if (tbName == null) {
67-
throw new IllegalArgumentException("'tbName' can't be empty");
68-
}
69-
final SimpleShardRouteRuleBinding b0 = new SimpleShardRouteRuleBinding();
70-
b0.setScName(scName);
71-
b0.setTbName(tbName);
72-
b0.setSdKey(sdKey);
73-
b0.setRule(binding.getRule());
74-
StringBuilder sb = new StringBuilder();
75-
sb.append(scName).append('.').append(tbName);
76-
putToCache(cache, sb.toString(), b0, true);
77-
putToCache(cache, tbName, b0, false);
78-
79-
final Set<ShardRouteInfo> routeInfos = new LinkedHashSet<>();
80-
if (sdValues != null) {
81-
new RangeExpressionParser(sdValues).visit(new RangeExpressionItemVisitor() {
78+
if (tbName != null) {
79+
final SimpleShardRouteRuleBinding b0 = new SimpleShardRouteRuleBinding();
80+
b0.setScName(scName);
81+
b0.setTbName(tbName);
82+
b0.setSdKey(sdKey);
83+
b0.setRule(binding.getRule());
84+
StringBuilder sb = new StringBuilder();
85+
sb.append(scName).append('.').append(tbName);
86+
putToCache(cache, sb.toString(), b0, true);
87+
putToCache(cache, tbName, b0, false);
8288

83-
@Override
84-
public void visit(Object val) {
85-
ShardRouteInfo routeInfo = getRouteInfo(b0, scName, tbName, val);
86-
routeInfos.add(routeInfo);
89+
final Set<ShardRouteInfo> routeInfos = new LinkedHashSet<>();
90+
if (sdValues != null) {
91+
new RangeExpressionParser(sdValues).visit(new RangeExpressionItemVisitor() {
92+
93+
@Override
94+
public void visit(Object val) {
95+
ShardRouteInfo routeInfo = getRouteInfo(b0, scName, tbName, val);
96+
routeInfos.add(routeInfo);
97+
}
98+
});
99+
}
100+
String key = buildQueryKey(scName, tbName);
101+
if (routeInfoMap.containsKey(key)) {
102+
throw new IllegalArgumentException("Duplicate route config for table '" + key + "'");
103+
} else {
104+
Set<String> tables = routedTables.get(scName);
105+
if (tables == null) {
106+
tables = new LinkedHashSet<>();
107+
routedTables.put(scName, tables);
87108
}
88-
});
89-
}
90-
String key = buildQueryKey(scName, tbName);
91-
if (routeInfoMap.containsKey(key)) {
92-
throw new IllegalArgumentException("Duplicate route config for table '" + key + "'");
93-
} else {
94-
Set<String> tables = routedTables.get(scName);
95-
if (tables == null) {
96-
tables = new LinkedHashSet<>();
97-
routedTables.put(scName, tables);
109+
tables.add(tbName);
110+
routeInfoMap.put(key, new ArrayList(routeInfos));
111+
}
112+
} else {// 配置schema级别路由规则
113+
if (defaultSchemaBinding == null) {// 使用列表中的第一个作为默认配置
114+
defaultSchemaBinding = binding;
115+
}
116+
if (schemaBindingMap.put(scName, binding) != null) {
117+
throw new DuplicateRouteRuleBindingException("Duplicate route rule binding for scName:"
118+
+ scName);
98119
}
99-
tables.add(tbName);
100-
routeInfoMap.put(key, new ArrayList(routeInfos));
101120
}
102121
}
103122
}
104123
this.routeRuleBindings = bindings;
105-
this.cache = cache;
106-
this.routeInfoMap = routeInfoMap;
124+
this.routeInfoCache = cache;
125+
this.routeInfosCache = routeInfoMap;
107126
this.routedTables = routedTables;
108127
}
109128

@@ -164,7 +183,7 @@ private InnerSimpleShardRouteRuleBindingWrapper getBinding(String scName, String
164183
if (scName != null) {
165184
queryKey = new StringBuilder().append(scName).append('.').append(tbName).toString();
166185
}
167-
InnerSimpleShardRouteRuleBindingWrapper ruleBindingWrapper = cache.get(queryKey);
186+
InnerSimpleShardRouteRuleBindingWrapper ruleBindingWrapper = routeInfoCache.get(queryKey);
168187
if (ruleBindingWrapper == null) {
169188
return null;
170189
} else if (ruleBindingWrapper.getConflictSchemas().size() > 1) {
@@ -179,23 +198,47 @@ private InnerSimpleShardRouteRuleBindingWrapper getBinding(String scName, String
179198
public ShardRouteRule getRouteRule(String scName, String tbName) {
180199
scName = DDRStringUtils.toLowerCase(scName);
181200
tbName = DDRStringUtils.toLowerCase(tbName);
201+
if (tbName == null) {
202+
throw new IllegalArgumentException("tbName can't be null");
203+
}
182204
InnerSimpleShardRouteRuleBindingWrapper bindingWrapper = getBinding(scName, tbName);
183-
if (bindingWrapper == null || bindingWrapper.getRuleBinding() == null) {
184-
return null;
185-
} else {
186-
return bindingWrapper.getRuleBinding().getRule();
205+
if (bindingWrapper != null) {// 1.从schema+table级中获取
206+
if (bindingWrapper.getRuleBinding() != null) {
207+
return bindingWrapper.getRuleBinding().getRule();
208+
} else {
209+
return null;
210+
}
211+
} else {// 2.从schema级别获取
212+
SimpleShardRouteRuleBinding binding = getRouteRuleBindingBySchemaLevel(scName);
213+
if (binding != null) {
214+
return binding.getRule();
215+
} else {
216+
return null;
217+
}
187218
}
188219
}
189220

190221
@Override
191222
public ShardRouteConfig getRouteConfig(String scName, String tbName) {
192223
scName = DDRStringUtils.toLowerCase(scName);
193224
tbName = DDRStringUtils.toLowerCase(tbName);
225+
if (tbName == null) {
226+
throw new IllegalArgumentException("tbName can't be null");
227+
}
194228
InnerSimpleShardRouteRuleBindingWrapper bindingWrapper = getBinding(scName, tbName);
195-
if (bindingWrapper == null) {
196-
return null;
197-
} else {
229+
if (bindingWrapper != null) {// 1.从schema+table级中获取
198230
return bindingWrapper.getRouteConfig();
231+
} else {// 2.从schema级别获取
232+
SimpleShardRouteRuleBinding binding = getRouteRuleBindingBySchemaLevel(scName);
233+
if (binding == null) {
234+
return null;
235+
} else {
236+
ShardRouteConfig config = new ShardRouteConfig();
237+
config.setScName(binding.getScName());
238+
config.setTbName(tbName);// note here
239+
config.setSdKey(binding.getSdKey());
240+
return config;
241+
}
199242
}
200243
}
201244

@@ -205,20 +248,86 @@ public ShardRouteInfo getRouteInfo(String scName, String tbName, Object sdValue)
205248
ShardRouteException {
206249
scName = DDRStringUtils.toLowerCase(scName);
207250
tbName = DDRStringUtils.toLowerCase(tbName);
251+
if (tbName == null) {
252+
throw new IllegalArgumentException("tbName can't be null");
253+
}
254+
SimpleShardRouteRuleBinding binding = null;
208255
InnerSimpleShardRouteRuleBindingWrapper bindingWrapper = getBinding(scName, tbName);
209-
SimpleShardRouteRuleBinding binding = bindingWrapper.getRuleBinding();
256+
if (bindingWrapper != null) {// 1.从schema+table级中获取
257+
binding = bindingWrapper.getRuleBinding();
258+
} else {// 2.从schema级获取
259+
binding = getRouteRuleBindingBySchemaLevel(scName);
260+
}
210261
if (binding == null) {
211262
return null;
212-
} else {// 必须使用 binding 中的 scName,因为sql中的scName可能为空
213-
ShardRouteInfo info = getRouteInfo(binding, binding.getScName(), binding.getTbName(), sdValue);
263+
} else {// 必须使用binding中的scName,因为sql中的scName可能为空,binding.getTbName()可能为null必须使用tbName
264+
ShardRouteInfo info = getRouteInfo(binding, binding.getScName(), tbName, sdValue);
214265
return info;
215266
}
216267
}
217268

269+
/**
270+
*
271+
* @param scName can be null
272+
* @param tbName can't be null
273+
* @return if sdValues is null or scName-tbName don't hit config return null
274+
* @throws ShardValueNotFoundException
275+
* @throws ShardRouteException
276+
*/
218277
@Override
219278
public List<ShardRouteInfo> getRouteInfos(String scName, String tbName) throws ShardValueNotFoundException,
220279
ShardRouteException {
221-
return routeInfoMap.get(buildQueryKey(scName, tbName));
280+
scName = DDRStringUtils.toLowerCase(scName);
281+
tbName = DDRStringUtils.toLowerCase(tbName);
282+
if (tbName == null) {
283+
throw new IllegalArgumentException("tbName can't be null");
284+
}
285+
List<ShardRouteInfo> result = routeInfosCache.get(buildQueryKey(scName, tbName));
286+
if (result != null) {
287+
return result;
288+
} else {// 查询schema配置级别
289+
SimpleShardRouteRuleBinding binding = getRouteRuleBindingBySchemaLevel(scName);
290+
if (binding == null) {
291+
return null;
292+
} else {
293+
String key = buildQueryKey(binding.getScName(), tbName);
294+
String sdValues = binding.getSdValues();
295+
if (sdValues != null) {
296+
List<ShardRouteInfo> list = routeInfosCacheForSchemaLevel.get(key);
297+
if (list == null) {
298+
final List<ShardRouteInfo> routeInfos = new ArrayList<>();
299+
final String scName0 = scName;
300+
final String tbName0 = tbName;
301+
new RangeExpressionParser(sdValues).visit(new RangeExpressionItemVisitor() {
302+
303+
@Override
304+
public void visit(Object val) {
305+
ShardRouteInfo routeInfo = getRouteInfo(scName0, tbName0, val);
306+
routeInfos.add(routeInfo);
307+
}
308+
});
309+
routeInfosCacheForSchemaLevel.put(key, routeInfos);
310+
list = routeInfos;
311+
}
312+
return list;
313+
} else {
314+
return null;
315+
}
316+
}
317+
}
318+
}
319+
320+
/**
321+
*
322+
* @param scName can be null
323+
* @return
324+
*/
325+
private SimpleShardRouteRuleBinding getRouteRuleBindingBySchemaLevel(String scName) {
326+
if (scName != null) {
327+
return schemaBindingMap.get(scName);
328+
} else {
329+
return defaultSchemaBinding;
330+
}
222331
}
223332

224333
@Override

0 commit comments

Comments
 (0)