提交 3be381da 编写于 作者: T terrymanu

refactor router for hint

上级 d9605b76
......@@ -19,14 +19,24 @@ package com.dangdang.ddframe.rdb.sharding.parsing;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.constant.DatabaseType;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.Lexer;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.analyzer.Dictionary;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Assist;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Keyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Symbol;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.TokenType;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.SQLParser;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.DeleteSQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.InsertSQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.SQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.SelectSQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.UpdateSQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.dialect.mysql.MySQLParser;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.dialect.oracle.OracleParser;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.dialect.postgresql.PostgreSQLParser;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.dialect.sqlserver.SQLServerParser;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.exception.SQLParsingException;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.exception.SQLParsingUnsupportedException;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.statement.delete.SQLDeleteParserFactory;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.statement.insert.SQLInsertParserFactory;
......@@ -34,6 +44,12 @@ import com.dangdang.ddframe.rdb.sharding.parsing.parser.statement.select.SQLSele
import com.dangdang.ddframe.rdb.sharding.parsing.parser.statement.update.SQLUpdateParserFactory;
import lombok.RequiredArgsConstructor;
import static com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Assist.END;
import static com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword.DELETE;
import static com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword.INSERT;
import static com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword.SELECT;
import static com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword.UPDATE;
/**
* SQL解析引擎.
*
......@@ -98,4 +114,32 @@ public final class SQLParsingEngine {
sqlParser.skipParentheses();
} while (sqlParser.skipIfEqual(Symbol.COMMA));
}
/**
* 获取SQL类型.
*
* @return SQL解析对象
*/
public SQLContext getStatementType() {
Lexer lexer = new Lexer(sql, new Dictionary());
lexer.nextToken();
while (true) {
TokenType tokenType = lexer.getCurrentToken().getType();
if (tokenType instanceof Keyword) {
if (tokenType.equals(SELECT)) {
return new SelectSQLContext();
} else if (tokenType.equals(UPDATE)) {
return new UpdateSQLContext();
} else if (tokenType.equals(INSERT)) {
return new InsertSQLContext();
} else if (tokenType.equals(DELETE)) {
return new DeleteSQLContext();
}
}
if (tokenType instanceof Assist && tokenType.equals(END)) {
throw new SQLParsingException("Unsupported SQL statement: [%s]", sql);
}
lexer.nextToken();
}
}
}
......@@ -64,7 +64,7 @@ public final class PreparedSQLRouteEngine {
List<Number> generatedIds = generateId();
parameters.addAll(generatedIds);
}
return engine.routeSQL(logicSql, sqlContext, parameters);
return engine.route(logicSql, sqlContext, parameters);
}
private List<Number> generateId() {
......
......@@ -24,12 +24,10 @@ import com.dangdang.ddframe.rdb.sharding.hint.HintManagerHolder;
import com.dangdang.ddframe.rdb.sharding.metrics.MetricsContext;
import com.dangdang.ddframe.rdb.sharding.parsing.SQLParsingEngine;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.ConditionContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.DeleteSQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.InsertSQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.SQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.SelectSQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.TableContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.UpdateSQLContext;
import com.dangdang.ddframe.rdb.sharding.rewrite.DerivedColumnUtils;
import com.dangdang.ddframe.rdb.sharding.rewrite.GenerateKeysUtils;
import com.dangdang.ddframe.rdb.sharding.rewrite.SQLRewriteEngine;
......@@ -37,7 +35,6 @@ import com.dangdang.ddframe.rdb.sharding.router.binding.BindingTablesRouter;
import com.dangdang.ddframe.rdb.sharding.router.database.DatabaseRouter;
import com.dangdang.ddframe.rdb.sharding.router.mixed.MixedTablesRouter;
import com.dangdang.ddframe.rdb.sharding.router.single.SingleTableRouter;
import com.dangdang.ddframe.rdb.sharding.util.SQLUtil;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Sets;
......@@ -69,54 +66,13 @@ public final class SQLRouteEngine {
* @return 路由结果
*/
public SQLRouteResult route(final String logicSQL) {
return routeSQL(logicSQL, parseSQL(logicSQL, Collections.emptyList()), Collections.emptyList());
return route(logicSQL, parseSQL(logicSQL, Collections.emptyList()), Collections.emptyList());
}
SQLContext parseSQL(final String logicSql, final List<Object> parameters) {
if (HintManagerHolder.isDatabaseShardingOnly()) {
return buildHintParsedResult(logicSql);
}
Context context = MetricsContext.start("Parse SQL");
log.debug("Logic SQL: {}, {}", logicSql, parameters);
SQLContext result = new SQLParsingEngine(databaseType, logicSql, shardingRule).parseStatement();
MetricsContext.stop(context);
if (result instanceof InsertSQLContext) {
GenerateKeysUtils.appendGenerateKeys(shardingRule, parameters, (InsertSQLContext) result);
}
if (result instanceof SelectSQLContext) {
DerivedColumnUtils.appendDerivedColumns((SelectSQLContext) result);
}
if (null != result.getLimitContext()) {
result.getLimitContext().processParameters(parameters);
}
return result;
}
private SQLContext buildHintParsedResult(final String logicSql) {
SQLContext result;
switch (SQLUtil.getTypeByStart(logicSql)) {
case SELECT:
result = new SelectSQLContext();
break;
case INSERT:
result = new InsertSQLContext();
break;
case UPDATE:
result = new UpdateSQLContext();
break;
case DELETE:
result = new DeleteSQLContext();
break;
default:
throw new UnsupportedOperationException("");
}
return result;
}
SQLRouteResult routeSQL(final String logicSQL, final SQLContext sqlContext, final List<Object> parameters) {
SQLRouteResult route(final String logicSQL, final SQLContext sqlContext, final List<Object> parameters) {
Context context = MetricsContext.start("Route SQL");
SQLRouteResult result = new SQLRouteResult(sqlContext);
RoutingResult routingResult = routeSQL(sqlContext.getConditionContext(), sqlContext, parameters);
RoutingResult routingResult = route(sqlContext.getConditionContext(), sqlContext, parameters);
SQLRewriteEngine sqlRewriteEngine = new SQLRewriteEngine(logicSQL, sqlContext);
result.getExecutionUnits().addAll(routingResult.getSQLExecutionUnits(sqlRewriteEngine.rewrite()));
if (null != sqlContext.getLimitContext() && 1 == result.getExecutionUnits().size()) {
......@@ -130,7 +86,7 @@ public final class SQLRouteEngine {
return result;
}
private RoutingResult routeSQL(final ConditionContext conditionContext, final SQLContext sqlContext, final List<Object> parameters) {
private RoutingResult route(final ConditionContext conditionContext, final SQLContext sqlContext, final List<Object> parameters) {
if (HintManagerHolder.isDatabaseShardingOnly()) {
return new DatabaseRouter(shardingRule.getDataSourceRule(), shardingRule.getDatabaseShardingStrategy(), sqlContext.getType()).route();
}
......@@ -143,11 +99,32 @@ public final class SQLRouteEngine {
}));
if (1 == logicTables.size()) {
return new SingleTableRouter(shardingRule, parameters, logicTables.iterator().next(), conditionContext, sqlContext.getType()).route();
}
}
if (shardingRule.isAllBindingTables(logicTables)) {
return new BindingTablesRouter(shardingRule, parameters, logicTables, conditionContext, sqlContext.getType()).route();
}
}
// TODO 可配置是否执行笛卡尔积
return new MixedTablesRouter(shardingRule, parameters, logicTables, conditionContext, sqlContext.getType()).route();
}
SQLContext parseSQL(final String logicSQL, final List<Object> parameters) {
SQLParsingEngine sqlParsingEngine = new SQLParsingEngine(databaseType, logicSQL, shardingRule);
if (HintManagerHolder.isDatabaseShardingOnly()) {
return sqlParsingEngine.getStatementType();
}
Context context = MetricsContext.start("Parse SQL");
log.debug("Logic SQL: {}, {}", logicSQL, parameters);
SQLContext result = sqlParsingEngine.parseStatement();
MetricsContext.stop(context);
if (result instanceof InsertSQLContext) {
GenerateKeysUtils.appendGenerateKeys(shardingRule, parameters, (InsertSQLContext) result);
}
if (result instanceof SelectSQLContext) {
DerivedColumnUtils.appendDerivedColumns((SelectSQLContext) result);
}
if (null != result.getLimitContext()) {
result.getLimitContext().processParameters(parameters);
}
return result;
}
}
......@@ -17,14 +17,6 @@
package com.dangdang.ddframe.rdb.sharding.util;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.exception.SQLParsingException;
import com.dangdang.ddframe.rdb.sharding.constant.SQLType;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.dialect.mysql.MySQLKeyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.Lexer;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.analyzer.Dictionary;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Assist;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Keyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.TokenType;
import com.google.common.base.CharMatcher;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
......@@ -32,12 +24,6 @@ import lombok.AllArgsConstructor;
import java.sql.SQLException;
import java.util.Collection;
import static com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Assist.END;
import static com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword.DELETE;
import static com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword.INSERT;
import static com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword.SELECT;
import static com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword.UPDATE;
/**
* SQL工具类.
*
......@@ -83,36 +69,4 @@ public class SQLUtil {
throw current;
}
}
/**
* 根据SQL第一个单词判断SQL类型.
*
* @param sql SQL语句
* @return SQL类型
*/
public static SQLType getTypeByStart(final String sql) {
// TODO: Use new Lexer Util, only support mysql now.
Lexer lexer = new Lexer(sql, new Dictionary(MySQLKeyword.values()));
lexer.nextToken();
while (true) {
TokenType tokenType = lexer.getCurrentToken().getType();
if (tokenType instanceof Keyword) {
if (tokenType.equals(SELECT)) {
return SQLType.SELECT;
} else if (tokenType.equals(UPDATE)) {
return SQLType.UPDATE;
} else if (tokenType.equals(INSERT)) {
return SQLType.INSERT;
} else if (tokenType.equals(DELETE)) {
return SQLType.DELETE;
}
}
if (tokenType instanceof Assist) {
if (tokenType.equals(END)) {
throw new SQLParsingException("Unsupported SQL statement: [%s]", sql);
}
}
lexer.nextToken();
}
}
}
......@@ -44,10 +44,11 @@ import org.junit.runners.Suite;
InsertStatementParserTest.class,
UpdateStatementParserTest.class,
DeleteStatementParserTest.class,
MySQLStatementTest.class,
MySQLStatementTest.class,
SQLParsingEngineTest.class,
MySQLPreparedStatementForOneParameterTest.class,
MySQLPreparedStatementForTowParametersTest.class,
OrParseTest.class,
OrParseTest.class,
UnsupportedParseTest.class
})
public class AllParsingTests {
......
package com.dangdang.ddframe.rdb.sharding.parsing;
import com.dangdang.ddframe.rdb.sharding.constant.DatabaseType;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.DeleteSQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.InsertSQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.SelectSQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.UpdateSQLContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.exception.SQLParsingException;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertThat;
public final class SQLParsingEngineTest {
@Test
public void assertGetStatementTypeForSelect() {
assertThat(new SQLParsingEngine(DatabaseType.MySQL, " /*COMMENT*/ \t \n \r \fsElecT\t\n * from table ", null).getStatementType(), instanceOf(SelectSQLContext.class));
}
@Test
public void assertGetStatementTypeForInsert() {
assertThat(new SQLParsingEngine(DatabaseType.MySQL, " - - COMMENT \t \n \r \fInsert\t\n into table ", null).getStatementType(), instanceOf(InsertSQLContext.class));
}
@Test
public void assertGetStatementTypeForUpdate() {
assertThat(new SQLParsingEngine(DatabaseType.MySQL, " /*+ HINT SELECT * FROM TT*/ \t \n \r \fuPdAte\t\n table ", null).getStatementType(), instanceOf(UpdateSQLContext.class));
}
@Test
public void assertGetStatementTypeForDelete() {
assertThat(new SQLParsingEngine(DatabaseType.MySQL, " /*+ HINT SELECT * FROM TT*/ \t \n \r \fdelete\t\n table ", null).getStatementType(), instanceOf(DeleteSQLContext.class));
}
@Test(expected = SQLParsingException.class)
public void assertGetStatementTypeForInvalidSQL() {
new SQLParsingEngine(DatabaseType.MySQL, "int i = 0", null).getStatementType();
}
}
......@@ -17,8 +17,6 @@
package com.dangdang.ddframe.rdb.sharding.util;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.exception.SQLParsingException;
import com.dangdang.ddframe.rdb.sharding.constant.SQLType;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
......@@ -33,17 +31,4 @@ public class SQLUtilTest {
assertThat(SQLUtil.getExactlyValue("\"xxx\""), is("xxx"));
assertThat(SQLUtil.getExactlyValue("'xxx'"), is("xxx"));
}
@Test
public void assertSQLType() {
assertThat(SQLUtil.getTypeByStart(" /*COMMENT*/ \t \n \r \fsElecT\t\n * from table "), is(SQLType.SELECT));
assertThat(SQLUtil.getTypeByStart(" - - COMMENT \t \n \r \fInsert\t\n into table "), is(SQLType.INSERT));
assertThat(SQLUtil.getTypeByStart(" /*+ HINT SELECT * FROM TT*/ \t \n \r \fuPdAte\t\n table "), is(SQLType.UPDATE));
assertThat(SQLUtil.getTypeByStart(" /*+ HINT SELECT * FROM TT*/ \t \n \r \fdelete\t\n table "), is(SQLType.DELETE));
}
@Test(expected = SQLParsingException.class)
public void assertNoSQL() {
SQLUtil.getTypeByStart("int i = 0");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册