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

栏目: Java · 发布时间: 6年前

内容简介:上一篇文章我们分析了sql词法解析,主要讲了sql是如何被解析为一个一个的单词的,在这个基础上,我们来看看sharding-jdbc是如何针对不同的DML语句来识别sql语法,提取表结构信息的。SQL解析的入口,主要方法是parse(),1、根据入参

上一篇文章我们分析了 sql 词法解析,主要讲了sql是如何被解析为一个一个的单词的,在这个基础上,我们来看看sharding-jdbc是如何针对不同的DML语句来识别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语句后的表达式,主要有标识、数字、属性、占位符等表达式

时序图

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

1、SQLParsingEngine

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()));
    } 
复制代码

2、SQLParser:

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);
        }
    }
复制代码

3、SQLStatementParse

SQL语句解释器,不同的DML语句有不同的实现,不同的数据库也有不同的实现;来看张实现截图:

Shading-jdbc源码分析(二)-sql解析
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;
    }
复制代码

4、SQLStatement:

SQL最终解析后的对象,不同的DML语句有不同的实现,来看下实现截图:

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

以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语句是怎么被解析的

最后

小尾巴走一波,欢迎关注我的公众号,不定期分享编程、投资、生活方面的感悟:)

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

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

新媒体十讲

新媒体十讲

范卫锋 / 中信出版社 / 2015-8 / 38.00元

“新媒体参谋长”范卫锋解答:媒体人如何转型?怎么创业?如何看准新媒体项目进行投资? 作为“新媒体的参谋长”,本书作者范卫锋将十余年从业亲历的经验教训、行业内幕串联成册,从定位、突破、扩张、商业模式、价值几个方面剖析新媒体策略,解密国内媒体圈转型、创业、投资的实操法则。案例信手拈来,观点鞭辟入里,打造出国内第一本由专业新媒体投资人撰写的新媒体实战兵法,涉及媒体人转型、新媒体实操、媒体公关营销、......一起来看看 《新媒体十讲》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

SHA 加密
SHA 加密

SHA 加密工具