抽象语法树mysql_从源码看ShardingSphere设计-解析引擎篇

SQL作为一种DSL(domain-specific language),可以理解为数据库的一种“编程语言”,与C、Java一样,真正执行这些文本字符串,需要先进行词法、语法分析,然后进行语义分析,编译器或者解释器才能将这些字符串转化为一系列确定的操作指令。

SQL解析引擎的作用就是词法、语法分析,将SQL解析成一颗抽象语法树AST,从而方便后续直接通过高级编程语言进行读取。当然与C、Java等编程语言相比,SQL相对来说简单很多,没有作用域、类、复杂的分支判断等。

抽象语法树 (Abstract Syntax Tree),简称 AST,它是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。

b22030d1af10

抽象语法树

ShardingSphere的解析引擎经过了三个版本的演化:

第一代SQL解析器:

sharding-jdbc在1.4.x 之前的版本使用的alibaba的druid(https://github.com/alibaba/druid),,druid) druid包含了一个手写的SQL解析器,优点是速度快,缺点是扩展不是很方便,只能通过修改源码。

第二代 SQL 解析器

从 1.5.x 版本开始,ShardingSphere 重新实现了一个简化版 SQL 解析引擎。因为ShardingSphere 并不需要像druid那样将 SQL 转为完整的AST,所以采用对 SQL 半理解的方式,仅提炼数据分片需要关注的上下文,在满足需要的前提下,SQL 解析的性能和兼容性得到了进一步的提高。

第三代 SQL 解析器

则从 3.0.x 版本开始,ShardingSphere统一将SQL解析器换成了基于antlr4实现,目的是为了更方便、更完整的支持SQL,例如对于复杂的表达式、递归、子查询等语句,因为后期ShardingSphere的定位已不仅仅是数据分片功能。

antlr4通过.g4文件定义解析词法和语法规则,ShardingSphere中将词法和语法文件进行了分离定义,例如mysql对应的g4文件,词法规则文件包括Alphabet.g4、Comments.g4、Keyword.g4、Literals.g4、MySQLKeyword.g4、Symbol.g4,语法规则文件有:BaseRule.g4、DALStatement.g4、DCLStatement.g4、DDLStatement.g4、DMLStatement.g4、RLStatement.g4、TCLStatement.g4,每个文件分别定义了一类关键字或者SQL类型规则。

Antlr4的g4文件

Keyword.g4它是一个纯词法规则文件,定义了SQL中通用的关键字

lexer grammar Keyword;

import Alphabet;

/* 跳过spaces, tabs, newlines */

WS

: [ \t\r\n] + ->skip

;

SELECT

: S E L E C T

;

INSERT

: I N S E R T

;

UPDATE

: U P D A T E

;

DELETE

: D E L E T E

;

CREATE

: C R E A T E

;

ALTER

: A L T E R

;

DROP

: D R O P

;

Symbol.g4定义了SQL中对应的计算、谓词运算符以及括号分号等标识符。

lexer grammar Symbol;

AND_: '&&';

OR_: '||';

NOT_: '!';

TILDE_: '~';

VERTICAL_BAR_: '|';

AMPERSAND_: '&';

SIGNED_LEFT_SHIFT_: '<

SIGNED_RIGHT_SHIFT_: '>>';

CARET_: '^';

MOD_: '%';

COLON_: ':';

PLUS_: '+';

MINUS_: '-';

ASTERISK_: '*';

SLASH_: '/';

BACKSLASH_: '\\';

Literals.g4定义SQL中的字面量值规则

lexer grammar Literals;

import Alphabet, Symbol;

IDENTIFIER_

: [A-Za-z_$0-9]*?[A-Za-z_$]+?[A-Za-z_$0-9]*

| BQ_ ~'`'+ BQ_

| (DQ_ ( '\\'. | '""' | ~('"'| '\\') )* DQ_)

;

STRING_

: (DQ_ ( '\\'. | '""' | ~('"'| '\\') )* DQ_)

| (SQ_ ('\\'. | '\'\'' | ~('\'' | '\\'))* SQ_)

;

NUMBER_

: INT_? DOT_? INT_ (E (PLUS_ | MINUS_)? INT_)?

;

MySQLKeyword.g4定义了MySQL中特有的关键字

lexer grammar MySQLKeyword;

import Alphabet;

USE

: U S E

;

DESCRIBE

: D E S C R I B E

;

SHOW

: S H O W

;

DATABASES

: D A T A B A S E S

;

DATABASE

: D A T A B A S E

;

SCHEMAS

: S C H E M A S

;

TABLES

: T A B L E S

;

TABLESPACE

: T A B L E S P A C E

;

COLUMNS

: C O L U M N S

;

FIELDS

: F I E L D S

;

Comments.g4定义SQL中注释词法规则

lexer grammar Comments;

import Symbol;

BLOCK_COMMENT: '/*' .*? '*/' -> channel(HIDDEN);

INLINE_COMMENT: (('-- ' | '#') ~[\r\n]* ('\r'? '\n' | EOF) | '--' ('\r'? '\n' | EOF)) -> channel(HIDDEN);

BaseRule.g4定义了SQL中的各类字面值语法规则

grammar BaseRule;

import Symbol, Keyword, MySQLKeyword, Literals;

parameterMarker

: QUESTION_

;

literals

: stringLiterals

| numberLiterals

| dateTimeLiterals

| hexadecimalLiterals

| bitValueLiterals

| booleanLiterals

| nullValueLiterals

;

stringLiterals

: characterSetName_? STRING_ collateClause_?

;

numberLiterals

: MINUS_? NUMBER_

;

dateTimeLiterals

: (DATE | TIME | TIMESTAMP) STRING_

| LBE_ identifier STRING_ RBE_

;

DMLStatement.g4定义DML语句的语法规则

grammar DMLStatement;

import Symbol, Keyword, MySQLKeyword, Literals, BaseRule;

insert

: INSERT insertSpecification_ INTO? tableName partitionNames_? (insertValuesClause | setAssignmentsClause | insertSelectClause) onDuplicateKeyClause?

;

insertSpecification_

: (LOW_PRIORITY | DELAYED | HIGH_PRIORITY)? IGNORE?

;

insertValuesClause

: columnNames? (VALUES | VALUE) assignmentValues (COMMA_ assignmentValues)*

;

insertSelectClause

: columnNames? select

;

onDuplicateKeyClause

: ON DUPLICATE KEY UPDATE assignment (COMMA_ assignment)*

;

replace

: REPLACE replaceSpecification_? INTO? tableName partitionNames_? (insertValuesClause | setAssignmentsClause | insertSelectClause)

;

replaceSpecification_

: LOW_PRIORITY | DELAYED

;

update

: UPDATE updateSpecification_ tableReferences setAssignmentsClause whereClause? orderByClause? limitClause?

;

updateSpecification_

: LOW_PRIORITY? IGNORE?

;

assignment

: columnName EQ_ assignmentValue

;

setAssignmentsClause

: SET assignment (COMMA_ assignment)*

;

assignmentValues

: LP_ assignmentValue (COMMA_ assignmentValue)* RP_

| LP_ RP_

;

assignmentValue

: expr | DEFAULT | blobValue

;

blobValue

: UL_BINARY STRING_

;

delete

: DELETE deleteSpecification_ (singleTableClause | multipleTablesClause) whereClause?

;

deleteSpecification_

: LOW_PRIORITY? QUICK? IGNORE?

;

DDLStatement.g4定义了DDL语句语法规则

grammar DDLStatement;

import Symbol, Keyword, MySQLKeyword, Literals, BaseRule, DMLStatement;

createTable

: CREATE createTableSpecification_? TABLE tableNotExistClause_ tableName (createDefinitionClause | createLikeClause)

;

alterTable

: ALTER TABLE tableName alterDefinitionClause?

;

dropTable

: DROP dropTableSpecification_ TABLE tableExistClause_ tableNames

;

dropIndex

: DROP INDEX dropIndexSpecification_? indexName (ON tableName)?

( ALGORITHM EQ_? (DEFAULT | INPLACE | COPY) | LOCK EQ_? (DEFAULT | NONE | SHARED | EXCLUSIVE) )*

;

truncateTable

: TRUNCATE TABLE? tableName

;

限于篇幅,其它的.g4文件这里就不贴其内容了,通过这些g4规则文件可以快速的得知目前ShardingSphere支持的SQL种类,对于不支持的,也可以通过修改或增加g4文件中规则进行扩展,这种方式要比druid在代码中写死的方式要灵活很多。不过这种自动生成的解析器相比手写解析器性能要低,官方文档给出的数据比第二代自研的 SQL 解析引擎慢 3-10 倍左右。

SQL种类

在看代码前,首先我们看下SQL的分类,因为ShardingSpher

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值