惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

Mox的笔记库

细嗦下MLIR的环境搭建 | Mox的笔记库 博客重构:从Hexo到Astro | Mox的笔记库 2026PPoPP MLIR Tutorial学习 | Mox的笔记库 MacOS配置《明日方舟:终末地》 | Mox的笔记库 2025:向内生长 | Mox的笔记库 由mlir::ExecutionEngine引发的跨系统问题 | Mox的笔记库 WSL2配置Cuda-Tile环境记录(未完待续) | Mox的笔记库 Vibe Coding手搓项目记录 | Mox的笔记库 给Debian上包——以DuckDB为例 | Mox的笔记库 UCPD.sys事件存档 | Mox的笔记库 换新电脑之Mac mini M4从购买到配置 | Mox的笔记库 Mac配置MLX-C开发环境 | Mox的笔记库 RISC-V meets RDBMS——RISC-V架构上可运行数据库一览 | Mox的笔记库 DuckDB Sort实现调查 | Mox的笔记库 修复Redis在树莓派5上无法运行的问题 | Mox的笔记库 如何在MLIR中自定义类型并且输出运行 | Mox的笔记库 网站网络结构变更记录 | Mox的笔记库 EDBT25论文阅读:PhoebeDB——A Disk-Based RDBMS Kernel for High-Performance and Cost-Effective OLTP SIGMOD25论文阅读:BPF-DB:——A Kernel-Embedded Transactional Database Management System For eBPF Applications SIGMOD24文章阅读:Query Compilation Without Regrets | Mox的笔记库 论文阅读:Designing an Open Framework for Query Optimization and Compilation Apache Arrow Gandiva项目解析 | Mox的笔记库 VLDB24论文阅读:Cloud-Native Database Systems and Unikernels——Reimagining OS Abstractions for Modern Hardware NoisePage源码分析(未完待续) | Mox的笔记库 VLDB20论文阅读:Mainlining Databases——Supporting Fast Transactional Workloads on Universal Columnar Data File Formats VLDB17论文阅读:Relaxed Operator Fusion for In-Memory Databases:Making Compilation, Vectorization, and Prefetching Work Together At Last 论文阅读:How not to structure your database-backed web applications——a study of performance bugs in the wild SIGMOD24阅读:ROME——Robust Query Optimization via Parallel Multi-Plan Execution 文章阅读:First Past the Post-Evaluating Query Optimization in MongoDB SIGMOD文章阅读:Apache Calcite——A Foundational Framework for Optimized Query Processing Over Heterogeneous Data Sources VLDB23论文阅读:Analyzing the Impact of Cardinality Estimation on Execution Plans in Microsoft SQL Server SIGMOD22论文阅读:Efficient Massively Parallel Join Optimization for Large Queries VLDB论文阅读:Weaving Relations for Cache Performance VLDB22论文阅读:ConnectorX——Accelerating Data Loading From Databases to Dataframes 论文阅读:UniKraft-Fast, Specialized Unikernels the Easy Way 当DuckDB遇上RISC-V | Mox的笔记库 SIGMOD25论文阅读:An Elephant Under The Microscope——Analyzing The Interaction Of Optimizer Components In PostgreSQL 论文阅读:Compile-Time Analysis of Compiler Frameworks for Query Compilation VLDB23阅读:Bringing Compiling Databases to RISC Architectures LingoDB源码编译与分析 | Mox的笔记库 淦!MLIR输出Hello World不应该这么难! | Mox的笔记库 如何愉快的运行一个MLIR程序 | Mox的笔记库 2024:拥挤年代的想象与创造 | Mox的笔记库 如何给自己的博客添加MLIR和LLVM IR语法高亮 | Mox的笔记库 VLDB19-Parsing Gigabytes of JSON per Second论文阅读 MLIR学习资料整理 | Mox的笔记库 SIGMOD24文章阅读:VeriTxn | Mox的笔记库 VLDB23文章阅读——Exploiting Cloud Object Storage for High-Performance Analytics VLDB24——OLAP on Modern Chiplet-Based Processors走马观花阅读 VLDB22:YeSQL文章阅读(已废弃) | Mox的笔记库 如何让数据库中的Python跑的更快-VLDB22-YeSQL文章阅读 | Mox的笔记库 你好,世界! | Mox的笔记库 让系统研究更有意义:HarmonyOS NEXT的教训和经验——讲座回顾 | Mox的笔记库 UNSW 24T3 COMP9336上课记录 | Mox的笔记库 Velox开发环境配置踩坑记录 | Mox的笔记库 MLIR Toy Tutorial实践记录 | Mox的笔记库 论文阅读:Declarative Sub-Operators for Universal Data Processing LLVM-Kaleidoscope实操踩坑记录 | Mox的笔记库 2024年7月RSSHub开发体验 | Mox的笔记库 澳洲大学计算机硕士比较 | Mox的笔记库 论文阅读——CDUL:CLIP-Driven Unsupervised Learning for Multi-Label Image Classification 论批量快速添加图片与视频水印的事 | Mox的笔记库 CVPR2023-CLIP算法调研 | Mox的笔记库 基于元信息写入的服务器压力测试 | Mox的笔记库 MjAyMw==,希望,前进与平庸之道 | Mox的笔记库 家庭组网IPv6+Mesh折腾 | Mox的笔记库 code-server初体验 | Mox的笔记库 从Nginx到Caddy | Mox的笔记库 Hexo部署安装全流程回顾 | Mox的笔记库 RMM观察与初探 | Mox的笔记库 计算机网络课设——UDP/TCP/TLS Socket实验 | Mox的笔记库 JQuery的XSS初探 | Mox的笔记库 生产实习记录 | Mox的笔记库 Fedora-CoreOS配置与试用(2023年) | Mox的笔记库 Electron学习笔记 | Mox的笔记库 ServerSentEvent学习 | Mox的笔记库 报告翻译:容器云的安全挑战 | Mox的笔记库 Arch Linux迁移计划 | Mox的笔记库 Vagrant配置Metarget靶场环境 | Mox的笔记库 OpenAI-whisper折腾 | Mox的笔记库 202202,困惑,混乱与未曾设想之路 | Mox的笔记库 2022年Hack the box:Tier1免费区全解 | Mox的笔记库 Navidrome部署记录 | Mox的笔记库 长安杯2021-snake复现 | Mox的笔记库 报告概要翻译:OBFUSCATING C++ PROGRAMS VIA CONTROL FLOW FLATTENING 从零开始的Django CVE-2022-28346复现 | Mox的笔记库 2022CISCN(西北区赛)-The shinning | Mox的笔记库 Docker+QEMU+Arm64(Ubuntu)+环境配置(2022版) | Mox的笔记库 Arch Linux运行树莓派系统(2022年) | Mox的笔记库 2022CISCN初赛-ez_usb-复盘WriteUp | Mox的笔记库 NodeMCU-MicroPython配置实录 | Mox的笔记库 Django事务使用 | Mox的笔记库 记录第一次EduSRC上报 | Mox的笔记库 Jetbrain问题应急处理 | Mox的笔记库 Celery5.2学习&配置 | Mox的笔记库 Waline部署记录 | Mox的笔记库 2021年12月 Vivo千镜杯回顾 | Mox的笔记库 Frida hook初次实战 | Mox的笔记库 Log4j2漏洞复现 | Mox的笔记库 Windows的WSL2+Docker初探 | Mox的笔记库
CIDR25:Runtime-Extensible Parsers阅读 | Mox的笔记库
2024-12-12 · via Mox的笔记库

最早是在DuckDB的Blog中发现的这篇文章,作者是Hannes Mühleisen和Mark Raasveldt,是DuckDB的员工。

Runtime-Extensible SQL Parsers Using PEG

顺带发现了几个月前构建的DuckDB RSSHub订阅失效了,可能这周末修复

(实际修复于2024.12.11:fix(route/duckdb): change blogs link and author

该论文目前已被CIDR2025接收:下载地址

文章还提到了相关实现库:

https://github.com/yhirose/cpp-peglib

https://github.com/hannes/peg-parser-experiments

甚至有一个JIT的版本用于PL/0的示范😆

https://github.com/yhirose/pl0-jit-compiler

正文内容

image-20241209164636639

目前大部分的数据库解析都沿用了YACC的Style,使用BCNF,LALR的解析样式

(但我记得LLVM不是这么做的,这点还需要确认🤔)

image-20241209172545287

the most advanced SQL systems of 2024 use parser technology from the 1960s.

的确如此,长期以来人们不觉得从上世纪70年代沿用至今的SQL解析器有什么问题

in their traditional design, parser construction is a compile-time activity where enormous grammar files are translated into state machine transition lookup tables which are then baked in a system binary. Having those always be present in the parser might be wasteful especially for size-conscious binary distributions like WebAssembly (Wasm).

在传统的方案中,每增加新的语法,都会转成状态机查找表,嵌入到系统解析器的二进制文件中。这不利于编译器扩展

While this is also true in other ecosystems like Python, the design of SQL with its heavy focus on syntax and not function calls makes the extensions second-class citizens that have to somehow work around the restrictions by the original parser, e.g., by embedding custom expressions in strings.

但 SQL 的设计非常注重语法而非函数调用,这使得扩展必须以某种方式绕过原始解析器的限制,例如在字符串中嵌入自定义表达式,从而成为二等公民

(Note: 之前我在YeSQL的文章中看到过这种说法,相比较于YeSQL通过添加C扩展的方案,我认为这里从解析器入手是个不错的选项)

Parsing Expression Grammar

Parser Expression Grammars (PEG),一种Top-Down的解析,Recursive-Decent,在Python的PEP617中成为Python的解析

Another big advantage of PEG parsers is error handling: [11] describes a practical technique where parser rules are annotated with “recovery” actions, which can 1) show more than a single error and 2) annotate errors with a more meaningful error message.

PEG输出的错误信息也会更加友善些

Lexical analysis is typically part of the PEG parser itself, which removes the need for a separate step.

词法与语法解析一体?😮Interesting

One big advantage is that PEG parsers do not require a compilation step where the grammar is converted to for example a finite state automaton based on lookup tables.

不需要编译?😮Interesting

A possible disadvantage of memoized packrat parsing is the memory required for memoization: the amount required is proportional to the input size, not the stack size.

一个可能缺点是 memoization 所需的内存:所需内存与输入大小成正比,而不是与堆栈大小成正比🤔

(意思是内存消耗有点大?)

allow syntax extensions, new statements, or to add entirely new query languages.

允许语法扩展?听起来不错

总有人想着把图运算加入SQL,也出现了Cypher这种专门处理图处理的语言,但其也可以通过PEG扩展得到

One of the most-reported support issues with data management systems are unhelpful syntax errors.

点名批评了MySQL的错误报错提示🤣

Given the token list and the grammar, there are now two main ways to decide whether the input matches the grammar: Top-down and Bottom-up

我记得火山模型就是Top-down,这是向量化处理的前置条件,而YACC’s LALR是典型的Bottom-Up

Postgres’ parser for example makes heavy use of reduce actions to create the abstract syntax tree for the query (PGNode).

PGNode是PG Syntax Tree的体现,对我而言有点意外,但想想确实是这么回事

Because the parser does not need to generate a state machine, we are immediately able to accept the new syntax.

等等,连状态机也不用了?

For the actual parsing, YACC parses TPC-H Query 1 in ca. 0.03 ms, where cpp-peglib takes ca. 0.3 ms, a ca. 10 times increas

比YACC慢10倍?啊这,但Blog中也指出了这是可以改进的,而cpp-peglib的作者也将其列为了Issue

For example, parser extension load order should ideally not influence the final grammar.

居然没有个BenchMark图?😅要是有的话就完美了

文章在最后提到,会逐步把DuckDB的Postgres YACC转为PEG

总结

PEG易于扩展SQL语法(不需要提前预编译),而且许动态更改可接受的查询语法并提供更好的错误恢复

扩展资料

Shift-Reduce冲突

Shift-reduce 冲突是编译原理中解析上下文无关文法(Context-Free Grammar, CFG)时可能遇到的一种冲突,尤其是在使用LALR(1)或LR(1)等自底向上解析方法的时候。这种冲突出现在解析器无法决定在给定的输入符号上执行“移入”(shift)动作还是“归约”(reduce)动作。

Shift 动作

  • 当解析器选择“移入”时,它会将当前输入符号从输入流中读取并推入到解析栈中,然后继续解析下一个输入符号。

Reduce 动作

  • “归约”意味着解析器已经识别出一个句柄(即文法规则右侧的一系列符号),并且会用该文法规则左侧的非终结符替换这个句柄。这相当于按照某个产生式规则进行反向替换。

Shift-reduce 冲突的例子

考虑如下简单的算术表达式文法:

E -> E + T

E -> T

T -> num

假设解析栈中有 num +,而下一个输入符号也是 num。此时,解析器面临两种选择:

  1. Shift:将 num 移入栈中,期望之后能匹配规则 E -> E + T
  2. Reduce:立即使用规则 T -> num 对栈顶的 num 进行归约。

由于存在这两种合法的选择,解析器遇到了 shift-reduce 冲突。

解决冲突

对于 LR 解析器来说,默认情况下通常会选择“移入”操作以期后续能够完成正确的归约。然而,实际应用中的解决策略可能会根据具体的语言和解析器设计有所不同。例如,在 Yacc 或 Bison 这样的工具中,可以通过优先级和结合性规则来明确指定如何处理这些冲突。

在某些情况下,重新设计文法可以消除 shift-reduce 冲突,使得解析过程更加清晰且无歧义。

PEG

中文维基百科:https://zh.wikipedia.org/zh-cn/%E8%A7%A3%E6%9E%90%E8%A1%A8%E8%BE%BE%E6%96%87%E6%B3%95

使用指南:https://berthub.eu/articles/posts/practical-peg-parsing/

cpp-peglib

cpp-peglib的作者提供了一个在线的Playground,我想应该是转成WASM了

下面是一个解析Vector的样例

image-20241212110436520

而项目本身应该用了Gtest,CMake,我在Debian-Sid的测试环境中使用GCC-14运行没有任何问题,比预想的要顺利很多😘

下面贴一个最简单的加法

#include <assert.h>

#include <iostream>

#include <peglib.h>

using namespace peg;

using namespace std;

int main(void) {

// (2) Make a parser

parser parser(R"(

# Grammar for Calculator...

Additive <- Multiplicative '+' Additive / Multiplicative

Multiplicative <- Primary '*' Multiplicative^cond / Primary

Primary <- '(' Additive ')' / Number

Number <- < [0-9]+ >

%whitespace <- [ \t]*

cond <- '' { error_message "missing multiplicative" }

)");

assert(static_cast<bool>(parser) == true);

// (3) Setup actions

parser["Additive"] = [](const SemanticValues &vs) {

switch (vs.choice()) {

case 0: // "Multiplicative '+' Additive"

return any_cast<int>(vs[0]) + any_cast<int>(vs[1]);

default: // "Multiplicative"

return any_cast<int>(vs[0]);

}

};

parser["Multiplicative"] = [](const SemanticValues &vs) {

switch (vs.choice()) {

case 0: // "Primary '*' Multiplicative"

return any_cast<int>(vs[0]) * any_cast<int>(vs[1]);

default: // "Primary"

return any_cast<int>(vs[0]);

}

};

parser["Number"] = [](const SemanticValues &vs) {

return vs.token_to_number<int>();

};

// (4) Parse

parser.enable_packrat_parsing(); // Enable packrat parsing.

int val = 0;

//parser.parse(" (1 + 2) * ", val);

parser.parse(" (1 + 2) * 3", val);

std::cout << val << std::endl;

// assert(val == 9);

//assert(val == 0);

}

相比较于Bison,个人觉得看起来简单易懂,这个的输出结果为9

你甚至能看到使用PEG解析Docx:docx.cc,源代码有些长,这里就不贴了

思考

和正文内容没多大关系😂大伙们忽略就行

我时常在想,SQL解析器本质是对自然语言的一种处理/抽象,那为什么不能直接跨过SQL解析,直接Text2Data?(似乎和这篇文章无关了),低结构化跟容易达成共识,就像C与LISP,HTML与XML一样。只能说大伙们习惯SQL了,瘦死的骆驼终究比马大。