Commit 3be381da authored by terrymanu's avatar terrymanu
Browse files

refactor router for hint

parent d9605b76
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -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();
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -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() {
+27 −50
Original line number Diff line number Diff line
@@ -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();
        }
@@ -150,4 +106,25 @@ public final class SQLRouteEngine {
        // 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;
    }
}
+0 −46
Original line number Diff line number Diff line
@@ -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();
        }
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import org.junit.runners.Suite;
        UpdateStatementParserTest.class,
        DeleteStatementParserTest.class,
        MySQLStatementTest.class,
        SQLParsingEngineTest.class,
        MySQLPreparedStatementForOneParameterTest.class, 
        MySQLPreparedStatementForTowParametersTest.class,  
        OrParseTest.class,
Loading