- 数据库
- 向量数据库
- 数据湖
- 人工智能
- RAG
【免费下载链接】deeplake
Deeplake is AI Data Runtime for Agents. It provides serverless postgres with a multimodal datalake, enabling scalable retrieval and training.
本篇技术指南以开源仓库中内置的第三方库HYRISE C++ SQL Parser(位于 cpp/3rd_party/sql-parser)为研究对象,讲解如何在 C++ 项目中构建该解析器、通过hsql命名空间将 SQL 字符串解析为强类型的 C++ 对象,并利用SQLParserResult与各SQLStatement子类进行后续处理。读完本文,你将掌握该解析器的完整集成流程、支持的 SQL 语法范围、已知边界限制,以及它在 Deeplake 数据库内核(cpp/deeplake_pg)等场景中作为第三方依赖被引入的工程实践。
一、项目概览:专为 C++ 打造的 SQL 解析器
HYRISE SQL Parser 是一个用 C++ 编写的 SQL 解析器,其核心目标是把一段 SQL 查询字符串解析为等价的 C++ 对象。它最初是为 Hyrise 内存数据库的集成而开发的,但设计上完全独立,可以很方便地嵌入其他 C++ 工程("can be used perfectly well in other environments as well")。
从仓库结构看,该库包含三大组成部分:
- 词法/语法分析器(src/parser):基于 flex(flex_lexer.l)与 bison(bison_parser.y)实现,关键字表由 sql_keywords.txt 与 keywordlist_generator.py 生成维护;
- 语句对象模型(src/sql):每种 SQL 语句对应一个结构体(如
SelectStatement、CreateStatement),本质上是"持有查询数据的 struct"; - 对外 API(src/SQLParser.h 与 src/SQLParserResult.h):提供静态解析入口与结果容器。
编译环境要求:官方 README 明确要求 gcc 5+(或 clang 5+),同时说明 gcc 4.8+ 亦可工作;docs/basic-usage.md 进一步指出已验证可工作的版本为 gcc 4.8 与 clang 3.4,更老的版本"可能可以工作或只需少量修改"(untested)。
二、构建与安装:从源码产出libsqlparser.so
该库采用 Makefile 驱动构建,流程非常简洁。进入 cpp/3rd_party/sql-parser 目录后执行:
make # 编译生成 libsqlparser.so make install # (可选,推荐)将库复制到 /usr/local/lib/ make test # 运行测试,确认一切正常其中make test会调用 test/test.sh 驱动位于 test 下的单元测试(sql_parser.cpp、select_tests.cpp、prepare_tests.cpp、tpc_h_tests.cpp、auto_query_file_test.cpp),并复用 test/thirdparty/microtest 这一轻量测试框架。此外仓库还提供 CMake 构建支持(CMakeLists.txt),便于集成到更大的 CMake 工程中——这正是 Deeplake 的做法:在 cpp/3rd_party/CMakeLists.txt 中通过add_subdirectory(sql-parser)将其纳入整个 C++ 内核的构建体系。
安装完成后,在你的工程中只需包含一个头文件SQLParser.h(源码位于 src/SQLParser.h,安装后位于/usr/local/lib/hsql/下),并在链接阶段加上-lsqlparser。
三、基础用法:两代 API 与完整的解析流程
整个框架被包裹在命名空间hsql中。当前版本对外提供两个静态解析方法(见 src/SQLParser.h):
| 方法 | 状态 | 说明 |
|---|---|---|
static bool parse(const std::string& sql, SQLParserResult* result) | 推荐(现行 API) | 解析 SQL 字符串并写入调用方传入的结果对象 |
static bool tokenize(const std::string& sql, std::vector<int16_t>* tokens) | 辅助 API | 仅做词法切分,输出 token 序列 |
static bool parseSQLString(...) | 已废弃(Deprecated) | 旧版 API,已由parse()取代 |
⚠️重要语义:
parse()的返回值只表示"词法/语法分析器内部运行没有崩溃",并不代表 SQL 本身合法。判断 SQL 是否合法必须检查result->isValid()。
3.1 现行推荐写法
以仓库自带的示例程序 example/example.cpp 为蓝本:
#include "SQLParser.h" // 唯一需要包含的头文件 #include "util/sqlhelper.h" // 可选的打印工具 int main(int argc, char* argv[]) { if (argc <= 1) { fprintf(stderr, "Usage: ./example \"SELECT * FROM test;\"\n"); return -1; } std::string query = argv[1]; // 解析给定的查询 hsql::SQLParserResult result; hsql::SQLParser::parse(query, &result); if (result.isValid()) { printf("Parsed successfully!\n"); printf("Number of statements: %lu\n", result.size()); for (auto i = 0u; i < result.size(); ++i) { // 打印语句摘要 hsql::printStatementInfo(result.getStatement(i)); } } else { fprintf(stderr, "Given string is not a valid SQL query.\n"); fprintf(stderr, "%s (L%d:%d)\n", result.errorMsg(), result.errorLine(), result.errorColumn()); } return 0; }3.2 README 中的最小示例
README.md 给出的更精简的骨架:
#include "hsql/SQLParser.h" const std::string query = "..."; hsql::SQLParserResult result; hsql::SQLParser::parse(query, &result); if (result.isValid() && result.size() > 0) { const hsql::SQLStatement* statement = result.getStatement(0); if (statement->isType(hsql::kStmtSelect)) { const auto* select = static_cast<const hsql::SelectStatement*>(statement); /* 处理 SELECT 语句 ... */ } }3.3SQLParserResult:结果容器与错误定位
解析结果由 src/SQLParserResult.h 定义,核心接口包括:
bool isValid() const/void setIsValid(bool):查询是否合法;size_t size() const:解析出的语句条数(一条 SQL 字符串可含多条语句,分号分隔);const SQLStatement* getStatement(size_t index) const/SQLStatement* getMutableStatement(size_t index):按索引取语句,调用方不持有所有权;const std::vector<SQLStatement*>& getStatements() const与std::vector<SQLStatement*> releaseStatements():批量取出或转移所有权;const char* errorMsg()、int errorLine()、int errorColumn():解析失败时定位错误消息与出错的行、列号;const std::vector<Expr*>& parameters():提取查询中的参数占位符(配合 PREPARE 语句使用,见下文);void reset():释放内部语句与数据。
注意所有权约定:SQLParserResult拥有其内部SQLStatement*的所有权(析构时统一释放),调用方通过getStatement访问时不要自行 delete;如需接管所有权应使用releaseStatements()。
3.4 编译链接示例
仓库在 example/Makefile 中给出了编译示例程序的完整规则:
CFLAGS = -std=c++11 -lstdc++ -Wall -I../src/ -L../ all: $(CXX) $(CFLAGS) example.cpp -o example -lsqlparser即:-I../src/指向解析器头文件目录,-L../指向libsqlparser.so所在目录,最终以-lsqlparser链接。标准要求是 C++11(-std=c++11)。
四、语句对象模型:从SQLStatement到各子类
解析成功后,SQLParserResult中存放的是SQLStatement*列表。SQLStatement是所有语句类型的基类(定义见 src/sql/SQLStatement.h),它记录:
StatementType type():语句类型枚举值;bool isType(StatementType type)/bool is(StatementType type):类型判断快捷方法;size_t stringLength:该语句在原始 SQL 字符串中的长度;std::vector<Expr*>* hints:查询提示(hints)。
StatementType枚举完整取值如下(同文件第 9-25 行):kStmtError、kStmtSelect、kStmtImport、kStmtInsert、kStmtUpdate、kStmtDelete、kStmtCreate、kStmtDrop、kStmtPrepare、kStmtExecute、kStmtExport、kStmtRename、kStmtAlter、kStmtShow、kStmtTransaction。注意文档 docs/basic-usage.md 明确提示:"部分枚举值并没有对应的语句类,因为它们尚未实现"——因此枚举与类并非一一对应。
目前已实现的语句子类,全部聚合在 src/sql/statements.h 中统一导出:
CreateStatement — CREATE 语句 DeleteStatement — DELETE 语句 DropStatement — DROP 语句 ExecuteStatement — EXECUTE 语句 ImportStatement — IMPORT 语句 PrepareStatement — PREPARE 语句 SelectStatement — SELECT 语句 UpdateStatement — UPDATE 语句 InsertStatement — INSERT 语句 ShowStatement — SHOW 语句 TransactionStatement — 事务语句 ExportStatement — EXPORT 语句 AlterStatement — ALTER 语句每种语句类都是"持有查询数据的 struct":例如SelectStatement记录投影列、FROM 子句、WHERE 表达式、GROUP BY、ORDER BY 等;表达式统一用 src/sql/Expr.h 中的Expr树表示。想快速熟悉各属性的实际含义,官方推荐两条路径:直接阅读各语句类的头文件定义(如 SelectStatement.h),或查看工具代码 src/util/sqlhelper.cpp 中printStatementInfo的打印逻辑——它展示了如何遍历语句对象树。
五、支持的 SQL 语法范围
5.1 SELECT 语句(最完整的支持面)
根据 docs/syntax-support.md,SELECT是支持度最高的语句类型,覆盖投影、别名、JOIN、WHERE 条件、聚合与排序等常见元素:
SELECT name, city, * FROM students AS t1 JOIN students AS t2 ON t1.city = t2.city WHERE t1.grade < 2.0 AND t2.grade > 2.0 AND t1.city = 'Frohnau' ORDER BY t1.grade DESC; SELECT city, AVG(grade) AS average, MIN(grade) AS best, MAX(grade) AS worst FROM students GROUP BY city;5.2 数据定义与修改
CREATE TABLE students ( name TEXT, student_number INTEGER, city TEXT, grade DOUBLE ); UPDATE students SET name='Max Mustermann' WHERE name = 'Ralf Mustermann'; DELETE FROM students WHERE name = 'Max Mustermann';5.3 预处理语句(Prepared Statements)
定义与执行采用标准PREPARE ... FROM ...+EXECUTE ...语法,问号?作为参数占位符:
PREPARE select_test FROM 'SELECT * FROM customer WHERE c_name = ?;'; EXECUTE select_test('Max Mustermann');解析后,PREPARE中的占位符参数会通过SQLParserResult::parameters()暴露出来;EXECUTE语句则记录实际传入的参数值。
更多可解析的查询样例,见仓库测试资产 test/queries/queries-good.sql(合法的解析输入)与 test/queries/queries-bad.sql(应被判定为非法的输入);test/queries/tpc-h-01.sql 至 tpc-h-22.sql 则提供了完整的 TPC-H 基准查询集,由 test/tpc_h_tests.cpp 驱动验证。同时 benchmark 目录(含 parser_benchmark.cpp)可用于解析性能基准测试。
六、已知限制与缺失功能
官方在 docs/known-limitations.md 中坦诚地列出了当前版本(以仓库内代码为准)的边界:
完全缺失的语句类型:
EXPLAINEXPORT(ExportStatement类虽已生成,但语法规则层面的支持有限)RENAMEALTER
此外,大量数据库厂商特有的语句类型不在开发路线图上,但项目欢迎以 Pull Request 形式贡献实现后合入。
其他 SQL 层面的限制:
- 表名会忽略 schema 前缀(见语法规则
table_name),这会影响到INSERT、IMPORT、DROP、DELETE等语句——即schema.table写法中 schema 部分目前不会被保留; - 列数据类型仅支持
INT、DOUBLE、TEXT三种。
在实际集成到 Deeplake 这样的完整数据库内核时,这些限制意味着复杂的类型系统与 DDL 语法需要由上层(如 cpp/deeplake_pg 中的 PostgreSQL 侧解析)自行补齐,第三方解析器更多承担通用 SQL 语句的快速解析职责。
七、快速上手指南:三步跑通示例
结合以上内容,把整套流程串起来只需三步:
- 构建:在 cpp/3rd_party/sql-parser 下执行
make生成libsqlparser.so; - 编译示例:进入 example 目录执行
make,得到example可执行文件; - 运行验证:
./example "SELECT * FROM test;" # 期望输出:Parsed successfully! / Number of statements: 1 ./example "this is not sql" # 期望输出:Given string is not a valid SQL query. (L1:1)
若需将该库集成进自己的 CMake 工程,参考 Deeplake 的做法——在父级 CMakeLists.txt 中add_subdirectory(sql-parser)即可纳入统一构建。
八、项目治理与许可证
- 许可证:HYRISE sql-parser 采用MIT License开源,许可证全文见仓库内 LICENSE 文件;
- 贡献方式:发现问题或希望增强功能,可通过提交 Issue 反馈;自行实现新特性后 Fork 并提交 Pull Request,经维护者审核合入即可;
- 开发者文档:深入参与开发前建议先阅读 docs/dev-docs.md(涵盖词法/语法生成、代码结构等内部细节)与 docs/technical_documentation.pdf(2015 年发表的原始技术论文,讨论开发细节及其在 Hyrise 数据库中的集成);
- 文档索引:docs/README.md 汇集了全部内部文档链接(开发者文档、支持语法、已知限制、基础用法)。
总结
HYRISE C++ SQL Parser 是一个"小而美"的解析组件:单一头文件入口、hsql命名空间封装、SQLParserResult+SQLStatement子类的对象模型,配合 flex/bison 生成的词法与语法分析器,让它既能独立服务于任意 C++ 项目,也能像在 Deeplake 中一样作为第三方依赖被add_subdirectory平滑纳入大型数据库内核。开发者应重点掌握parse()与isValid()的语义区分、结果对象的所有权约定,以及官方文档明示的语法支持面与已知限制,从而在实际集成中做出正确的技术取舍。
- 数据库
- 向量数据库
- 数据湖
- 人工智能
- RAG
【免费下载链接】deeplake
Deeplake is AI Data Runtime for Agents. It provides serverless postgres with a multimodal datalake, enabling scalable retrieval and training.
相关推荐
在 Deeplake C++ 工程中使用 Hyrise SQL Parser:构建、解析与语句对象实战指南
在 Deeplake C++ 工程中使用 Hyrise SQL Parser:构建、解析与语句对象实战指南 本篇指南以仓库内 sql parser 基础使用文档
数据库向量数据库数据湖人工智能RAGdeeplake 内置 C++ SQL Parser(hyrise/sql-parser)已知限制与缺失功能详解:语句类型覆盖与表名、列类型约束的实战避坑指南
deeplake 内置 C++ SQL Parser(hyrise/sql parser)已知限制与缺失功能详解:语句类型覆盖与表名、列类型约束的实战避坑指南
数据库向量数据库数据湖人工智能RAGHyrise SQL Parser 使用教程
Hyrise SQL Parser 使用教程 1. 项目介绍 Hyrise SQL Parser 是一个由 Hyrise 开发团队维护的高性能 SQL 解析器,
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考