Skip to content

Commit 00dfac3

Browse files
authored
Merge pull request #53 from hellojavaer/dev
Dev
2 parents 6e657fb + 50cc149 commit 00dfac3

File tree

3 files changed

+203
-43
lines changed

3 files changed

+203
-43
lines changed

ddal-ddr/src/main/java/org/hellojavaer/ddal/ddr/sqlparse/cache/LRUSQLParserCache.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,20 @@ public class LRUSQLParserCache implements SQLParserCache {
2929

3030
private volatile ConcurrentLinkedHashMap<InnerQueryKey, SQLParsedState> cache;
3131
private Integer capacity;
32+
private Integer maxSQLLength;
3233
private SQLParser sqlParser;
3334

3435
private LRUSQLParserCache() {
3536
}
3637

3738
public LRUSQLParserCache(SQLParser sqlParser, Integer capacity) {
39+
this(sqlParser, capacity, null);
40+
}
41+
42+
public LRUSQLParserCache(SQLParser sqlParser, Integer capacity, Integer maxSQLLength) {
3843
this.sqlParser = sqlParser;
3944
this.capacity = capacity;
45+
this.maxSQLLength = maxSQLLength;
4046
init();
4147
}
4248

@@ -48,6 +54,14 @@ public void setCapacity(Integer capacity) {
4854
this.capacity = capacity;
4955
}
5056

57+
public Integer getMaxSQLLength() {
58+
return maxSQLLength;
59+
}
60+
61+
public void setMaxSQLLength(Integer maxSQLLength) {
62+
this.maxSQLLength = maxSQLLength;
63+
}
64+
5165
public SQLParser getSqlParser() {
5266
return sqlParser;
5367
}
@@ -62,6 +76,9 @@ public void setSqlParser(SQLParser sqlParser) {
6276
*/
6377
@Override
6478
public SQLParsedState parse(String sql, ShardRouter shardRouter) {
79+
if (maxSQLLength != null && sql.length() > maxSQLLength) {
80+
return sqlParser.parse(sql, shardRouter);
81+
}// else
6582
init();
6683
InnerQueryKey queryKey = new InnerQueryKey(sql, shardRouter);
6784
SQLParsedState result = cache.get(queryKey);

ddal-jsqlparser/src/main/java/org/hellojavaer/ddal/jsqlparser/JSQLParserAdapter.java

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,8 @@ public SQLParsedResult parse(final Map<Object, Object> jdbcParams) {
248248
final SQLParsedResult result = new SQLParsedResult() {
249249

250250
@Override
251-
public void checkIfCrossPreparedStatement(Map<Object, Object> jdbcParam)
252-
throws CrossPreparedStatementException {
251+
public void checkIfCrossPreparedStatement(final Map<Object, Object> jdbcParams)
252+
throws CrossPreparedStatementException {
253253
for (Map.Entry<TableWrapper, String> entry : convertedTables.entrySet()) {
254254
TableWrapper tab = entry.getKey();
255255
route1(tab, jdbcParams, entry.getValue(), this.getSql());
@@ -322,18 +322,11 @@ private ShardRouteInfo route1(TableWrapper tab, Map<Object, Object> jdbcParams,
322322
+ sql + "]");
323323
}
324324
routeInfo = getRouteInfo(tab, sdValue);
325-
String next = routeInfo.toString();
325+
String newRoutedFulltableName = routeInfo.toString();
326326
if (routedFullTableName == null) {
327-
routedFullTableName = next;
327+
routedFullTableName = newRoutedFulltableName;
328328
} else {
329-
if (!routedFullTableName.equals(next)) {
330-
throw new AmbiguousRouteResultException("In sql[" + sql + "], table:'"
331-
+ tab.getOriginalConfig().toString()
332-
+ "' has multiple routing results["
333-
+ routedFullTableName + "," + next
334-
+ "]. Jdbc parameter is "
335-
+ DDRJSONUtils.toJSONString(jdbcParams));
336-
}
329+
verifyRoutedFullTableName(tab, jdbcParams, routedFullTableName, routedSql, newRoutedFulltableName);
337330
}
338331
} else {// range
339332
RangeParam rangeParam = (RangeParam) sqlParam;
@@ -356,7 +349,10 @@ private ShardRouteInfo route1(TableWrapper tab, Map<Object, Object> jdbcParams,
356349
if (end.isJdbcParamType()) {
357350
Number number = (Number) jdbcParams.get(end.getValue());
358351
if (number == null) {
359-
352+
throw new IllegalSQLParameterException("Jdbc parameter can't be null. Jdbc parameter key is "
353+
+ end.getValue() + ", jdbc parameter is "
354+
+ DDRJSONUtils.toJSONString(jdbcParams)
355+
+ " and sql is [" + sql + "]");
360356
}
361357
e0 = number.longValue();
362358
} else {
@@ -368,32 +364,35 @@ private ShardRouteInfo route1(TableWrapper tab, Map<Object, Object> jdbcParams,
368364
if (routedFullTableName == null) {
369365
routedFullTableName = next;
370366
} else {
371-
if (!routedFullTableName.equals(next)) {
372-
if (routedSql != null) {
373-
throw new CrossPreparedStatementException("Sql[" + sql + "] has been routed to ["
374-
+ routedSql + "] and table:'"
375-
+ tab.getOriginalConfig().toString()
376-
+ "' has been route to '" + routedFullTableName
377-
+ "'. But current jdbc parameter:"
378-
+ DDRJSONUtils.toJSONString(jdbcParams)
379-
+ " require route to " + next
380-
+ DDRJSONUtils.toJSONString(jdbcParams));
381-
} else {
382-
throw new AmbiguousRouteResultException("In sql[" + sql + "], table:'"
383-
+ tab.getOriginalConfig().toString()
384-
+ "' has multiple routing results["
385-
+ routedFullTableName + "," + next
386-
+ "]. Jdbc parameter is "
387-
+ DDRJSONUtils.toJSONString(jdbcParams));
388-
}
389-
}
367+
verifyRoutedFullTableName(tab, jdbcParams, routedFullTableName, routedSql, next);
390368
}
391369

392370
}
393371
}
394372
return routeInfo;
395373
}
396374

375+
private void verifyRoutedFullTableName(TableWrapper tab, Map<Object, Object> jdbcParams,
376+
String routedFullTableName, String routedSql, String newRoutedFulltableName) {
377+
if (!routedFullTableName.equals(newRoutedFulltableName)) {
378+
if (routedSql != null) {
379+
throw new CrossPreparedStatementException("Sql[" + sql + "] has been routed to [" + routedSql
380+
+ "] and table:'" + tab.getOriginalConfig().toString()
381+
+ "' has been route to '" + routedFullTableName
382+
+ "'. But current jdbc parameter:"
383+
+ DDRJSONUtils.toJSONString(jdbcParams)
384+
+ " require route to " + newRoutedFulltableName
385+
+ DDRJSONUtils.toJSONString(jdbcParams));
386+
} else {
387+
throw new AmbiguousRouteResultException("In sql[" + sql + "], table:'"
388+
+ tab.getOriginalConfig().toString()
389+
+ "' has multiple routing results[" + routedFullTableName + ","
390+
+ newRoutedFulltableName + "]. Jdbc parameter is "
391+
+ DDRJSONUtils.toJSONString(jdbcParams));
392+
}
393+
}
394+
}
395+
397396
private void afterVisitBaseStatement() {
398397
FrameContext context = this.getStack().pop();
399398
for (Map.Entry<String, TableWrapper> entry : context.entrySet()) {
@@ -523,6 +522,7 @@ private TableWrapper getTableFromContext(Column col) {
523522
*/
524523
private void addRoutedTableIntoContext(TableWrapper table, ShardRouteConfig routeConfig, boolean appendAlias) {
525524
FrameContext frameContext = this.getStack().peek();
525+
String scName = table.getSchemaName();
526526
String tbName = table.getName();
527527
String tbAliasName = tbName;
528528
if (table.getAlias() != null && table.getAlias().getName() != null) {
@@ -533,18 +533,17 @@ private void addRoutedTableIntoContext(TableWrapper table, ShardRouteConfig rout
533533
}
534534
}
535535
String sdKey = DDRStringUtils.toLowerCase(routeConfig.getSdKey());// sdKey可以为null,当为null时需要通过context路由
536-
if (table.getSchemaName() != null) {
536+
if (scName != null) {
537537
StringBuilder sb = new StringBuilder();
538-
sb.append(DDRStringUtils.toLowerCase(table.getSchemaName()));
538+
sb.append(DDRStringUtils.toLowerCase(scName));
539539
sb.append('.');
540540
sb.append(DDRStringUtils.toLowerCase(tbAliasName));
541541
sb.append('.');
542542
sb.append(sdKey);
543543
String key = sb.toString();
544544
putIntoContext(frameContext, key, table);
545-
putIntoContext(frameContext, key.substring(table.getSchemaName().length() + 1), table);
546-
putIntoContext(frameContext, key.substring(table.getSchemaName().length() + 2 + tbAliasName.length()),
547-
table);
545+
putIntoContext(frameContext, key.substring(scName.length() + 1), table);
546+
putIntoContext(frameContext, key.substring(scName.length() + 2 + tbAliasName.length()), table);
548547
} else {
549548
StringBuilder sb = new StringBuilder();
550549
sb.append(DDRStringUtils.toLowerCase(tbAliasName));
@@ -556,7 +555,7 @@ private void addRoutedTableIntoContext(TableWrapper table, ShardRouteConfig rout
556555
}
557556
}
558557

559-
private Object getRouteValue(Column column, Expression obj) {
558+
protected Object getRouteValue(Column column, Expression obj) {
560559
if (obj == null) {
561560
return null;
562561
}
@@ -637,9 +636,7 @@ public void visit(Between between) {
637636
s1 = e1;
638637
e1 = temp;
639638
}
640-
for (long l = s1; l <= e1; l++) {
641-
routeTable(tab, column, l);
642-
}
639+
routeTable(tab, column, new RangeShardValue(s1, e1));
643640
}
644641
}
645642

ddal-jsqlparser/src/test/java/org.hellojavaer.ddal.jsqlparser/JSQLParserAdapterTest.java

Lines changed: 148 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,163 @@
2222
package org.hellojavaer.ddal.jsqlparser;
2323

2424
import net.sf.jsqlparser.JSQLParserException;
25+
import org.hellojavaer.ddal.core.utils.Assert;
26+
import org.hellojavaer.ddal.ddr.datasource.exception.CrossPreparedStatementException;
27+
import org.hellojavaer.ddal.ddr.shard.ShardRouter;
28+
import org.hellojavaer.ddal.ddr.shard.simple.SimpleShardParser;
29+
import org.hellojavaer.ddal.ddr.sqlparse.SQLParsedResult;
30+
import org.hellojavaer.ddal.ddr.sqlparse.SQLParsedState;
31+
import org.hellojavaer.ddal.ddr.sqlparse.exception.AmbiguousRouteResultException;
2532
import org.junit.Test;
2633

34+
import java.util.HashMap;
35+
import java.util.Map;
36+
2737
/**
2838
*
2939
* @author <a href="mailto:[email protected]">Kaiming Zou</a>,created on 2018/5/18.
3040
*/
31-
public class JSQLParserAdapterTest {
41+
public class JSQLParserAdapterTest extends BaseTestShardParser {
3242

3343
@Test
34-
public void test00() throws JSQLParserException {
44+
public void testInitCheck() throws JSQLParserException {
3545
JSQLParserAdapter.checkJSqlParserFeature();
3646
JSQLParserAdapter.checkCompatibilityWithJSqlParser();
3747
}
48+
49+
@Test
50+
public void testSelectLimitCheck00() {
51+
String sql = "select * from user where id = ?";
52+
ShardRouter shardRouter = buildParserForId().getShardRouter();
53+
JSQLParserAdapter jsqlParserAdapter = new JSQLParserAdapter(sql, shardRouter, false);
54+
SQLParsedState sqlParsedState = jsqlParserAdapter.parse();
55+
Map<Object, Object> jdbcParams = new HashMap<>();
56+
jdbcParams.put(1, 506);
57+
SQLParsedResult sqlParsedResult = sqlParsedState.parse(jdbcParams);
58+
Assert.equals(sqlParsedResult.getSql(), "SELECT * FROM db_02.user_0122 AS user WHERE id = ?");
59+
jsqlParserAdapter = new JSQLParserAdapter(sql, shardRouter, true);
60+
try {
61+
sqlParsedState = jsqlParserAdapter.parse();
62+
throw new Error();
63+
} catch (Exception e) {
64+
}
65+
}
66+
67+
@Test
68+
public void testSelectLimitCheck01() {
69+
String sql = "select * from user where id = ? limit 10";
70+
ShardRouter shardRouter = buildParserForId().getShardRouter();
71+
JSQLParserAdapter jsqlParserAdapter = new JSQLParserAdapter(sql, shardRouter, false);
72+
SQLParsedState sqlParsedState = jsqlParserAdapter.parse();
73+
Map<Object, Object> jdbcParams = new HashMap<>();
74+
jdbcParams.put(1, 506);
75+
SQLParsedResult sqlParsedResult = sqlParsedState.parse(jdbcParams);
76+
Assert.equals(sqlParsedResult.getSql(), "SELECT * FROM db_02.user_0122 AS user WHERE id = ? LIMIT 10");
77+
78+
jsqlParserAdapter = new JSQLParserAdapter(sql, shardRouter, true);
79+
sqlParsedState = jsqlParserAdapter.parse();
80+
jdbcParams = new HashMap<>();
81+
jdbcParams.put(1, 506);
82+
sqlParsedResult = sqlParsedState.parse(jdbcParams);
83+
Assert.equals(sqlParsedResult.getSql(), "SELECT * FROM db_02.user_0122 AS user WHERE id = ? LIMIT 10");
84+
}
85+
86+
@Test
87+
public void testUpdateLimitCheck00() {
88+
String sql = "update user set name='abc' where id = ? limit 10";
89+
ShardRouter shardRouter = buildParserForId().getShardRouter();
90+
JSQLParserAdapter jsqlParserAdapter = new JSQLParserAdapter(sql, shardRouter, false);
91+
SQLParsedState sqlParsedState = jsqlParserAdapter.parse();
92+
Map<Object, Object> jdbcParams = new HashMap<>();
93+
jdbcParams.put(1, 506);
94+
SQLParsedResult sqlParsedResult = sqlParsedState.parse(jdbcParams);
95+
Assert.equals(sqlParsedResult.getSql(), "UPDATE db_02.user_0122 SET name = 'abc' WHERE id = ? LIMIT 10");
96+
97+
jsqlParserAdapter = new JSQLParserAdapter(sql, shardRouter, true);
98+
sqlParsedState = jsqlParserAdapter.parse();
99+
jdbcParams = new HashMap<>();
100+
jdbcParams.put(1, 506);
101+
sqlParsedResult = sqlParsedState.parse(jdbcParams);
102+
Assert.equals(sqlParsedResult.getSql(), "UPDATE db_02.user_0122 SET name = 'abc' WHERE id = ? LIMIT 10");
103+
}
104+
105+
@Test
106+
public void testDeleteLimitCheck00() {
107+
String sql = "delete from user where id = ? limit 10";
108+
ShardRouter shardRouter = buildParserForId().getShardRouter();
109+
JSQLParserAdapter jsqlParserAdapter = new JSQLParserAdapter(sql, shardRouter, false);
110+
SQLParsedState sqlParsedState = jsqlParserAdapter.parse();
111+
Map<Object, Object> jdbcParams = new HashMap<>();
112+
jdbcParams.put(1, 506);
113+
SQLParsedResult sqlParsedResult = sqlParsedState.parse(jdbcParams);
114+
Assert.equals(sqlParsedResult.getSql(), "DELETE FROM db_02.user_0122 WHERE id = ? LIMIT 10");
115+
116+
jsqlParserAdapter = new JSQLParserAdapter(sql, shardRouter, true);
117+
sqlParsedState = jsqlParserAdapter.parse();
118+
jdbcParams = new HashMap<>();
119+
jdbcParams.put(1, 506);
120+
sqlParsedResult = sqlParsedState.parse(jdbcParams);
121+
Assert.equals(sqlParsedResult.getSql(), "DELETE FROM db_02.user_0122 WHERE id = ? LIMIT 10");
122+
}
123+
124+
@Test
125+
public void testSqlParsedState00() {
126+
String sql = "select * from user where id = ?";
127+
SimpleShardParser parser = buildParserForId();
128+
JSQLParserAdapter jsqlParserAdapter = new JSQLParserAdapter(sql, parser.getShardRouter(), false);
129+
SQLParsedState sqlParsedState = jsqlParserAdapter.parse();
130+
//
131+
Map<Object, Object> jdbcParams = new HashMap<>();
132+
jdbcParams.put(1, 506);
133+
SQLParsedResult sqlParsedResult = sqlParsedState.parse(jdbcParams);
134+
Assert.equals(sqlParsedResult.getSql(), "SELECT * FROM db_02.user_0122 AS user WHERE id = ?");
135+
136+
jdbcParams = new HashMap<>();
137+
jdbcParams.put(1, 507);
138+
sqlParsedResult = sqlParsedState.parse(jdbcParams);
139+
Assert.equals(sqlParsedResult.getSql(), "SELECT * FROM db_03.user_0123 AS user WHERE id = ?");
140+
}
141+
142+
@Test
143+
public void testSqlParsedState01() {
144+
String sql = "select * from user where id = ?";
145+
SimpleShardParser parser = buildParserForId();
146+
JSQLParserAdapter jsqlParserAdapter = new JSQLParserAdapter(sql, parser.getShardRouter(), false);
147+
SQLParsedState sqlParsedState = jsqlParserAdapter.parse();
148+
//
149+
Map<Object, Object> jdbcParams = new HashMap<>();
150+
jdbcParams.put(1, 506);
151+
SQLParsedResult sqlParsedResult = sqlParsedState.parse(jdbcParams);
152+
Assert.equals(sqlParsedResult.getSql(), "SELECT * FROM db_02.user_0122 AS user WHERE id = ?");
153+
//
154+
jdbcParams = new HashMap<>();
155+
jdbcParams.put(1, 507);
156+
try {
157+
sqlParsedResult.checkIfCrossPreparedStatement(jdbcParams);
158+
throw new Error();
159+
} catch (CrossPreparedStatementException e) {
160+
161+
}
162+
}
163+
164+
@Test
165+
public void testSqlParsedState02() {
166+
String sql = "select * from user where id = ? and id = 506";
167+
SimpleShardParser parser = buildParserForId();
168+
JSQLParserAdapter jsqlParserAdapter = new JSQLParserAdapter(sql, parser.getShardRouter(), false);
169+
SQLParsedState sqlParsedState = jsqlParserAdapter.parse();
170+
//
171+
Map<Object, Object> jdbcParams = new HashMap<>();
172+
jdbcParams.put(1, 506);
173+
SQLParsedResult sqlParsedResult = sqlParsedState.parse(jdbcParams);
174+
Assert.equals(sqlParsedResult.getSql(), "SELECT * FROM db_02.user_0122 AS user WHERE id = ? AND id = 506");
175+
//
176+
jdbcParams = new HashMap<>();
177+
jdbcParams.put(1, 507);
178+
try {
179+
sqlParsedState.parse(jdbcParams);
180+
throw new Error();
181+
} catch (AmbiguousRouteResultException e) {
182+
}
183+
}
38184
}

0 commit comments

Comments
 (0)