1 分•作者: surprisetalk•7 个月前
返回首页
最新
1 分•作者: surprisetalk•7 个月前
1 分•作者: surprisetalk•7 个月前
1 分•作者: terran9•7 个月前
1 分•作者: shayac2•7 个月前
1 分•作者: freediver•7 个月前
2 分•作者: mooreds•7 个月前
1 分•作者: a_w•7 个月前
1 分•作者: mooreds•7 个月前
1 分•作者: mooreds•7 个月前
1 分•作者: zdw•7 个月前
1 分•作者: thunderbong•7 个月前
1 分•作者: georgecmu•7 个月前
12 分•作者: stmw•7 个月前
1 分•作者: carsoon•7 个月前
1 分•作者: rustic-indian•7 个月前
小时候,我常常想知道计算机是如何“理解”一门新编程语言的。编译器对我来说还是一个模糊的概念,而解释型语言则像是魔法:你输入一些东西,机器就能知道该怎么做。<p>SQL 并不是直接编译成机器码的,但构建一个 SQL 引擎迫使你面对一个类似的问题:你如何让一种语言(比如我用的 Rust)理解并执行另一种语言(SQL),而 Rust 自己的编译器对 SQL 一无所知?<p>数据库不是从一堆现有代码中生长出来的。它源于一组概念:行、列、表达式、连接、聚合、索引、事务。<p>我的引擎的起点是一个通用的 SQL 方言,它深受 SQLite 和 DuckDB 的影响,因为它们都提供了一个大型的测试集,采用名为 SQLLogicTest 的通用格式。我的理论是,一个能够通过这些测试的引擎将具有坚实的兼容性基础。我的目标不是发明一种新的 SQL 风格,而是支持足够多的现有系统,以便我可以重用它们的测试套件和查询生态系统。<p>我没有编写自己的解析器。我使用 `sqlparser`,它将 SQL 转换为抽象语法树(AST),这是一个查询的内存中图状表示。然后,我将 AST 映射到我自己的 Rust 枚举和数据结构。从那里开始,SQL 就不再是文本,而变成了一组引擎可以推理的概念。<p>我没有从优化器开始,而是从一个测试框架开始。我将其连接起来以运行 SQLite 发布的 SQLLogicTest 测试集,并添加了一些对 DuckDB 风格测试的支持。如今,我运行的所有 SQLite 提供的测试都通过了。这并不意味着引擎是万无一失的;这仍然是早期的绿地代码。但这确实意味着引擎的行为是锚定在我的头脑之外的:当测试失败时,它就是我的实现与已知结果的对抗。该套件已成为事实上的规范;对规划器或执行器的任何更改都必须保持其通过。<p>一开始,我以为我会为我想支持的每个数据类型编写自己的计算内核。当你在一个领域缺乏经验时,你的头脑会欺骗你,让你相信重新发明是“正确”的唯一途径。最终,我将引擎转移到 Apache Arrow 的内存模型上。Arrow 为我提供了一个列式表示和一组用于常见操作的内核。我不必手动编写和维护所有这些,我可以专注于规划查询并将 SQL 语义映射到 Arrow 数组上。<p>这个项目是单人完成的。为了弥补这一点,我依赖于 LLM。在任何一天,我都会在 Claude Sonnet 4.5 和 GPT-5.x Codex 之间切换,以帮助勾勒新功能、推理生命周期问题或探索替代设计。它们不够可靠,不能盲目信任,但足够快,可以充当嘈杂的、上下文感知的结对编程者。<p>这创造了一种平衡:我有一个相对较大的测试集,必须保持通过,我希望新功能是高效的,而且我不想让微妙的正确性回归隐藏在“聪明”的 LLM 生成的代码背后。测试形成了一个护栏。如果建议的优化破坏了行为,它就会被抛弃。如果它通过了但看起来很脆弱,我就会重构它。<p>我从未写过编译器。这个项目是我离编译器最近的一次。它介于查询引擎、解释器和一堂课之间,告诉你站在其他系统的肩膀上你能走多远:SQLite 的测试、DuckDB 的查询风格、Apache Arrow 的内存模型,以及有时会以错误的形式提出正确想法的 LLM。<p>如果说有什么的话,它已经回答了我童年的问题。计算机不会“仅仅理解”新语言。必须有人来搭建这座桥梁。<p>(如果你喜欢这个故事,搜索“rust-llkv”并给它点个星。)
1 分•作者: gmays•7 个月前
2 分•作者: dropbox_miner•7 个月前
1 分•作者: Anon84•7 个月前
1 分•作者: vinhnx•7 个月前