Shading-jdbc源碼分析(二)-sql解析

前言

上一篇文章咱們分析了sql詞法解析,主要講了sql是如何被解析爲一個一個的單詞的,在這個基礎上,咱們來看看sharding-jdbc是如何針對不一樣的DML語句來識別sql語法,提取表結構信息的。sql

相關類簡要說明

  • SQLParsingEngine:解析SQL的入口,分析不一樣的SQL(SELECT,UPDATE etc),不一樣的SQLParser(MySQLParser etc),實例化不一樣的解析類(MySQLSelectParser etc).
  • SQLParser:SQL解釋器,分析SQL中表名稱、別名、列名稱、表達式等,填充到具體的對象;不一樣的數據庫有不一樣的實現。
  • SQLStatementParser:SQL解析器的父類,AbstractSelectParser、AbstractInsertParser、AbstractSelectParser、AbstractUpdateParser是其實現(每一個數據庫又有不一樣的實現,例如:MySQLSelectParser就是AbstractSelectParser的實現),對於parse()方法,子類有不一樣的實現;經過調用SQLParser中的方法,分析SQL語句
  • SQLStatement:SQL語句的最終解析對象,主要有Table、Conditions(SQL的條件)、Column;不一樣的DML語句有不一樣的實現
  • SQLExpression:SQL表達式,分析where語句後的表達式,主要有標識、數字、屬性、佔位符等表達式

時序圖

一、SQLParsingEngine

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()));
    } 
複製代碼

二、SQLParser:

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);
        }
    }
複製代碼

三、SQLStatementParse

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;
    }
複製代碼

四、SQLStatement:

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

最後

小尾巴走一波,歡迎關注個人公衆號,不按期分享編程、投資、生活方面的感悟:)

相關文章
相關標籤/搜索