SQL解析函数
ClickHouse的SQL解析入口函数:parseQuery, 函数原型:
ASTPtr parseQuery(
IParser & parser,
const char * begin,
const char * end,
const std::string & query_description,
size_t max_query_size)
具体的功能实现是通过调用tryParseQuery函数完成。
tryParseQuery函数
函数原型:
ASTPtr tryParseQuery(
IParser & parser,
const char * & pos,
const char * end,
std::string & out_error_message,
bool hilite,
const std::string & query_description,
bool allow_multi_statements,
size_t max_query_size)
该函数主要实现了两种功能:词法分析和语法解析。
ClickHouse词法解析
词法解析的主要任务是读入源程序的输入字符、将它们组成词素,生成并输出一个词法单元(Token)序列,每个词法单元对应于一个词素。
ClickHouse中的每个词法单元(Token)使用一个struct Tocken结构体对象来进行存储,结构体中存储了词法单元的type和value。
ClickHouse中token的种类列表:
name |
description |
Whitespace |
{‘ ’|‘\t’|‘\n’|‘\r’|‘\f’| ‘\v’}+ |
Comment |
// /*…*/ |
BareWord |
{‘a’… ‘z’| ‘A’ … ‘Z’| ‘_’}+ |
Number |
二进制、八进制、十进制、十六进制等 |
StringLiteral |
\’ |
QuotedIdentifier |
‘ “ |
OpeningRoundBracket |
( |
ClosingRoundBracket |
) |
OpeningSquareBracket |
[ |
ClosingSquareBracket |
] |
Comma |
, |
Semicolon |
; |
Dot |
. |
Asterisk |
* |
Plus |
+ |
Minus |
- |
Slash |
/ |
Percent |
% |
Arrow |
-> |
QuestionMark |
? |
Colon |
: |
Equals |
== |
NotEquals |
!= <> |
Less |
< |
Creater |
> |
LessOrEquals |
<= |
GreaterOrEquals |
>= |
Concatenation |
|| |
ClickHouse词法分析器是由Tokens和Lexer类来实现, DB::Lexer::nextTokenImpl()函数用来对SQL语句进行词法分析的具体实现。
ClickHouse语法分析
语法分析器的作用是根据给定的形式文法对由词法单元(Token)序列构成的输入进行语法检查、并构建由输入的词法单元(Token)组成的数据结构(一般是语法分析树、抽象语法树等层次化的数据结构)。
ClickHouse中定义了不同的Parser用来对不同类型的SQL语句进行语法分析,例如:ParserInsertQuery(Insert语法分析器)、ParserCreateQuery(Create语法分析器)、ParserAlterQuery(Alter语法分析器)等等。
Parser首先判断输入的Token序列是否是该类型的SQL,若是该类型的SQL,则继续检查语法的正确性,正确则生成AST返回,语法错误的则抛出语法错误异常,否则直接返回空AST语法树。
ClickHouse语法分析器的入口类:ParserQuery。该函数接收词法分析器传递的Token序列,将其传递给具体的Parser进行语法分析,并接受Parser产生的AST结果。
ClickHouse中Parser间的调用关系如下图所示: