老叶茶馆|ClickHouse和他的朋友们(8)纯手工打造的SQL解析器
北京联盟_本文原题:ClickHouse和他的朋友们(8)纯手工打造的SQL解析器
原文出处:https://bohutang.me/2020/07/25/clickhouse-and-friends-parser/
现实生活中的物品一旦被标记为“纯手工打造” , 给人的第一感觉就是“上乘之品” , 一个字“贵” , 比如北京老布鞋 。
但是在计算机世界里 , 如果有人告诉你 ClickHouse 的 SQL 解析器是纯手工打造的 , 是不是很惊讶!这个问题引起了不少网友的关注 , 所以本篇聊聊 ClickHouse 的纯手工解析器 , 看看它们的底层工作机制及优缺点 。
枯燥先从一个 SQL 开始:
EXPLAIN SELECT a,b FROM t1
token
首先对 SQL 里的字符逐个做判断 , 然后根据其关联性做 token 分割:
本文插图
比如连续的 WordChar , 那它就是 BareWord , 解析函数在 Lexer::nextTokenImpl , 解析调用栈:
DB::Lexer::nextTokenImpl Lexer.cpp:63
DB::Lexer::nextToken Lexer.cpp:52
DB::Tokens::operator[](unsigned long) TokenIterator.h:36
DB::TokenIterator::get TokenIterator.h:62
DB::TokenIterator::operator-> TokenIterator.h:64
DB::tryParseQuery(DB::IParser&, char const*&, char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, unsigned long, unsigned long) parseQuery.cpp:224
DB::parseQueryAndMovePosition(DB::IParser&, char const*&, char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, unsigned long, unsigned long) parseQuery.cpp:314
DB::parseQuery(DB::IParser&, char const*, char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long, unsigned long) parseQuery.cpp:332
DB::executeQueryImpl(const char *, const char *, DB::Context &, bool, DB::QueryProcessingStage::Enum, bool, DB::ReadBuffer *) executeQuery.cpp:272
DB::executeQuery(DB::ReadBuffer&, DB::WriteBuffer&, bool, DB::Context&, std::__1:: function<void (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)>) executeQuery.cpp:731
DB::MySQLHandler::comQuery(DB::ReadBuffer&) MySQLHandler.cpp:313
DB::MySQLHandler::run MySQLHandler.cpp:150
ast
token 是最基础的元组 , 他们之间没有任何关联 , 只是一堆生冷的词组与符号 , 所以我们还需对其进行 语法解析 , 让这些 token 之间建立一定的关系 , 达到一个可描述的活力 。
ClickHouse 在解每一个 token 的时候 , 会根据当前的 token 进行状态空间进行预判(parse 返回 true 则进入子状态空间继续) , 然后决定状态跳转 , 比如:
推荐阅读
- 老叶|植物花卉缺啥元素,11种症状对应11种元素
- 植株|多肉出现老叶子,要不要摘掉?熟知2个后果,你就知道了!
- 多肉植物|砍头的多肉植物爆芽后,老叶片该不该摘掉
- 养护|多肉出现老叶子,要不要摘掉?熟知2个后果,你就知道了!
- 叶子|养金钱树做好两件事,一年“撑破盆”,新芽比老叶还多
- 春季养虎皮兰的正确方法,让你的虎皮兰长满新芽,老叶肥厚硬挺
- 砍头的多肉植物爆芽后,老叶片该不该摘掉
- 朋友家的盆栽龙吐珠老叶黄不开花,为啥我的爬满围墙,每年都开花
- 盆栽的幸福树发新芽后,老叶全部脱落,手一碰就掉,是什么情况?
- 天冷了建兰最下面的老叶发黄了什么原因