点击之家 SQL 莱克瑟
这个 点击之家的实际 SQL 借记器 (单位:千美元)src/Parsers/Lexer.cpp)被编译为WebAssembly:~9 KB,没有依赖性,在浏览器和Node.js中工作. 因为它是服务器使用的确切代码,它给 ClickHouse SQL 的每一个角落都以正确的标记——巢接 /* */ 评论, $heredoc$ 字符串,回击和双引号标识符, 0x编号 :0b 字迹, \G, (中文(简体) ), |>,然后随你.
此模块与在 点击之家网络用户界面 (单位:千美元)play.html)和 ClickHouse 文件。 一个 GitHub 动作从 ClickHouse 同步此寄存器 master 每日出版发行,只要lexer更改.
安装
npm install @clickhouse/lexer
使用量
import {tokenize, TokenType, TOKEN_NAMES, isSignificant, isError} from "@clickhouse/lexer"
const tokens = await tokenize("SELECT count() FROM `events` WHERE user != 'guest' -- filter")
for (const token of tokens)
console.log(TOKEN_NAMES[token.type], JSON.stringify(token.text))
// BareWord "SELECT"
// Whitespace " "
// BareWord "count"
// OpeningRoundBracket "("
// ...
// StringLiteral "'guest'"
// Whitespace " "
// Comment "-- filter"
// Only keywords/identifiers/literals/operators, no whitespace and comments:
tokens.filter(t => isSignificant(t.type))
// The lexer stops at unlexable input and reports what went wrong:
const bad = await tokenize("SELECT 'unterminated")
isError(bad.at(-1).type) // true
TOKEN_NAMES[bad.at(-1).type] // "ErrorSingleQuoteIsNotClosed"
每个符号是 {type, text, begin, end}. 将输入从头到尾的相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相接相相接相接相接相接相相相相接相相接相相接相接相相相相接相接相接相相接相相相接相相相相接相相相接相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相. begin编号 :end a. 输入查询的UTF-8编码的字节; text 是已解码的符号.
在浏览器中,它的工作原理是相同的——WASM被嵌入为base64,因此没有任何可配置在任何捆绑器中:
<script type="module">
import {tokenize} from "https://esm.sh/@clickhouse/lexer"
console.log(await tokenize("SELECT 1"))
</script>
对于热路, 装入一次并同时表示:
import {loadLexer, tokenizeSync} from "@clickhouse/lexer"
await loadLexer()
const tokens = tokenizeSync(query) // no await, e.g. inside an editor's render path
API 密码
| 导出 | 说明 |
|---|---|
tokenize(query, options?) | Promise<Token[]>; 将 lexer 装入第一次使用时. |
loadLexer() | 证明WASM模块(专有). |
tokenizeSync(query, options?) | 之后同步符号化 loadLexer()。 。 。 . |
lexerIsLoaded() | 是否为 tokenizeSync 可以调用. |
TokenType | 名称 ~ 数字类型 (TokenType.StringLiteral(......) (中文(简体) ). |
TOKEN_NAMES | 数字类型 名称. |
isSignificant(type) | 不是白空间,也不是评论. |
isError(type) | 一个 Error* 类型. |
options.maxQuerySize | 词典的字节限制; 0 (默认) = 无限. |
重要内容: 符号类型值是位置值 TokenType 插入 src/Parsers/Lexer.h,并插入一个符号类型,重新编号之后的一切(这种情况已经发生)。 总是比较 TokenType.* 从此包中,从不与硬码数字相对抗,也从不将一个版本的符号表与另一个版本的WASM相混合. 相同的 ClickHouse 修订版(收录于 upstream/COMMIT) (中文(简体) ).
使用原始的 WASM( 非 JavaScript 主机)
软件包还将平面二进制作为 @clickhouse/lexer/lexer.wasm 用于任何WASM运行时间. 上诉委员会(见 upstream/clickhouse_lexer.h:
extern size_t clickhouse_lexer_size; // size of the lexer state object
void clickhouse_lexer_create(void * ptr, const char * begin, const char * end, size_t max_query_size);
unsigned char clickhouse_lexer_next_token(void * ptr, const char ** out_token_begin, const char ** out_token_end);
int clickhouse_lexer_token_is_significant(unsigned char token);
int clickhouse_lexer_token_is_error(unsigned char token);
int clickhouse_lexer_token_is_end(unsigned char token);
将您的缓冲器( 语法状态、 查询字节和两个出点) 放在 __heap_base 或以上——模块的"阴影堆栈"占据了下方的内存并向下生长,因此更低的缓冲被大查询所腐蚀. 打电话 clickhouse_lexer_next_token 循环到 is_end 或者说 is_error。 。 。 . index.js 在此一揽子方案中是完整的参考执行.
此寄存器是如何同步的
Lexer 源头住在这里 upstream/,从 src/Parsers 联 合 国 点击之家/ 点击之家 (单位:千美元)Lexer.cpp, (中文(简体) ), Lexer.h, (中文(简体) ), LexerStandalone.h, (中文(简体) ), clickhouse_lexer.h(三); upstream/COMMIT 记录主人承诺 他们来自.
这个 同步工作流程 每日运行 :
scripts/sync.sh——从 ClickHouse 主机获取最新来源; 如果无变化则停止 .scripts/build.sh——编译lexer.wasm有条纹( c) (--target=wasm32 -nostdlib,与lexer_wasm主寄存器中的CMake目标).scripts/generate.js——再生lexer-wasm-base64.js财务报告和审定财务报表tokens.js(符号表从Lexer.h,保持编号与二进制相锁.- 运行测试, 承诺, 撞击补丁版本, 创建 GitHub 发布, 并发布到 npm .
手动重建
所需经费: clang, (中文(简体) ), lld (计: wasm-ld和节点js 18.
npm run sync # pull the latest lexer sources from ClickHouse master into upstream/
npm run build # compile lexer.wasm and regenerate the derived JS modules
npm test
同样,从主 ClickHouse 寄存器的检出结果来看,独立的Lexer 构建是:
clang++ -Os -fno-exceptions -fno-rtti -DLEXER_STANDALONE_BUILD --target=wasm32 -flto -nostdlib \
-I src -Wl,--no-entry -Wl,--export-all \
src/Parsers/Lexer.cpp -o Lexer.wasm
这是什么 lexer_wasm CMake 目标生成于 build/src/Parsers/Lexer.wasm 配置时 -DENABLE_LEXER_TEST=1。 。 。 .
许可证
Apache 许可证 2.0,与ClickHouse一样。 这个 upstream/ 来源是来自ClickHouse仓库的逐字记录本,仍为“ClickHouse股份有限公司”.