上一篇文章咱們分析了sql詞法解析,主要講了sql是如何被解析爲一個一個的單詞的,在這個基礎上,咱們來看看sharding-jdbc是如何針對不一樣的DML語句來識別sql語法,提取表結構信息的。sql
SQL解析的入口,主要方法是parse(),數據庫
一、根據入參dbType實例化具體的SQLParser
二、根據sqlParser分析sql語義(是哪一種類型的sql),實例化對應的解析類編程
/**
* 解析SQL.
*
* @return SQL語句對象
*/
public SQLStatement parse() {
SQLParser sqlParser = getSQLParser();
sqlParser.skipIfEqual(Symbol.SEMI);
if (sqlParser.equalAny(DefaultKeyword.WITH)) {
skipWith(sqlParser);
}
if (sqlParser.equalAny(DefaultKeyword.SELECT)) {
return SelectParserFactory.newInstance(sqlParser).parse();
}
if (sqlParser.equalAny(DefaultKeyword.INSERT)) {
return InsertParserFactory.newInstance(shardingRule, sqlParser).parse();
}
if (sqlParser.equalAny(DefaultKeyword.UPDATE)) {
return UpdateParserFactory.newInstance(sqlParser).parse();
}
if (sqlParser.equalAny(DefaultKeyword.DELETE)) {
return DeleteParserFactory.newInstance(sqlParser).parse();
}
throw new SQLParsingUnsupportedException(sqlParser.getLexer().getCurrentToken().getType());
}
複製代碼
以SelectParserFactory爲例:bash
/**
* 建立Select語句解析器.
*
* @param sqlParser SQL解析器
* @return Select語句解析器
*/
public static AbstractSelectParser newInstance(final SQLParser sqlParser) {
if (sqlParser instanceof MySQLParser) {
return new MySQLSelectParser(sqlParser);
}
if (sqlParser instanceof OracleParser) {
return new OracleSelectParser(sqlParser);
}
if (sqlParser instanceof SQLServerParser) {
return new SQLServerSelectParser(sqlParser);
}
if (sqlParser instanceof PostgreSQLParser) {
return new PostgreSQLSelectParser(sqlParser);
}
throw new UnsupportedOperationException(String.format("Cannot support sqlParser class [%s].", sqlParser.getClass()));
}
複製代碼
SQL解析器,主要用來解析SQL語句對象,不一樣的數據庫有不一樣的實現app
/**
* 解析單表.
*
* @param sqlStatement SQL語句對象
*/
public final void parseSingleTable(final SQLStatement sqlStatement) {
...//省略
sqlStatement.getTables().add(table);
}
/**
* 解析表達式.
*
* @param sqlStatement SQL語句對象
* @return 表達式
*/
public final SQLExpression parseExpression(final SQLStatement sqlStatement) {
int beginPosition = getLexer().getCurrentToken().getEndPosition();
SQLExpression result = parseExpression();
if (result instanceof SQLPropertyExpression) {
setTableToken(sqlStatement, beginPosition, (SQLPropertyExpression) result);
}
return result;
}
/**
* 解析查詢條件.
*
* @param sqlStatement SQL語句對象
*/
public final void parseWhere(final SQLStatement sqlStatement) {
parseAlias();
if (skipIfEqual(DefaultKeyword.WHERE)) {
parseConditions(sqlStatement);
}
}
複製代碼
SQL語句解釋器,不一樣的DML語句有不一樣的實現,不一樣的數據庫也有不一樣的實現;來看張實現截圖:ide
以 AbstractSelectParser 爲例:private final SQLParser sqlParser;
private final SelectStatement selectStatement;
複製代碼
這是2個重要參數;經過調用SQLParser中的方法分析sql語句的表結構,而後構造SelectStatement返回post
@Override
public final SelectStatement parse() {
query();
parseOrderBy();
customizedSelect();
appendDerivedColumns();
appendDerivedOrderBy();
return selectStatement;
}
複製代碼
SQL最終解析後的對象,不一樣的DML語句有不一樣的實現,來看下實現截圖:ui
以SELECT語句爲例,來看看都有哪些參數:spa
private boolean distinct;
private boolean containStar;
private int selectListLastPosition;
private int groupByLastPosition;
private final List<SelectItem> items = new LinkedList<>();
private final List<OrderItem> groupByItems = new LinkedList<>();
private final List<OrderItem> orderByItems = new LinkedList<>();
private Limit limit;
public SelectStatement() {
super(SQLType.SELECT);
}
複製代碼
好了,今天咱們總體上看下SQL解析過程當中用的類,以及主要的方法,下面一篇文章咱們將分析SELECT語句是怎麼被解析的code
小尾巴走一波,歡迎關注個人公衆號,不按期分享編程、投資、生活方面的感悟:)