上一篇文章我们分析了sql词法解析,主要讲了sql是如何被解析为一个一个的单词的,在这个基础上,我们来看看sharding-jdbc是如何针对不同的DML语句来识别sql语法,提取表结构信息的。
SQL解析的入口,主要方法是parse(),
1、根据入参 dbType 实例化具体的 SQLParser
2、根据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为例:
/** * 创建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语句对象,不同的数据库有不同的实现
/** * 解析单表. * * @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语句有不同的实现,不同的数据库也有不同的实现;来看张实现截图:
以 AbstractSelectParser为例:
private final SQLParser sqlParser; private final SelectStatement selectStatement; 复制代码
这是2个重要参数;通过调用SQLParser中的方法分析sql语句的表结构,然后构造SelectStatement返回
@Override public final SelectStatement parse() { query(); parseOrderBy(); customizedSelect(); appendDerivedColumns(); appendDerivedOrderBy(); return selectStatement; } 复制代码
SQL最终解析后的对象,不同的DML语句有不同的实现,来看下实现截图:
以SELECT语句为例,来看看都有哪些参数:
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语句是怎么被解析的
小尾巴走一波,欢迎关注我的公众号,不定期分享编程、投资、生活方面的感悟:)