
VexDB-Lite 测试体系完整拆解一份 YAML Spec DSL 驱动三大数据库引擎的测试指南【免费下载链接】VexDB-LiteA cross-platform vector database, which can be integrated into existing databases as a plugin.项目地址: https://gitcode.com/gh_mirrors/ve/VexDB-Lite向量数据库 VexDB-Lite 是一个跨平台向量数据库可作为插件集成进 DuckDB、PostgreSQL、openGauss、SQLite 等现有数据库。它的最大测试难题在于同一个 HNSW 图索引在不同引擎里写法完全不同——DuckDB 用GRAPH_INDEX索引类型和函数式距离PG 用vexdb_graph索引方法和中缀操作符-openGauss 还要再兼容一套。VexDB-Lite 的答案是 tests/spec/ 下的YAML Spec DSL 测试框架一份 YAML 用例Single Source of Truth由渲染器自动编译成各引擎的原生测试产物一次编写、多引擎跑测。本文带你完整拆解这套体系的设计、用法与运行方式。为什么多引擎测试需要单一事实来源如果为每个引擎各写一套测试用例很快会出现三个问题用例漂移DuckDB 侧修了个边界 bugPG 侧对应用例忘了同步维护成本倍增100 个用例 × 3 个引擎 300 份脚本归属混乱到底哪些用例是跨引擎核心行为哪些是某个引擎的专属特性VexDB-Lite 的解法见 tests/spec/README.md所有用例统一写成声明式 YAML物理上按引擎分目录组织渲染时按路由规则组合。旧的 109 个 sqllogictest 和 59 个手写 PG SQL 测试已全部反向迁入 spec不再维护两套体系。tests/spec/ ├── _lib/ # 工具链方言字典、渲染器、分类器、Docker runner ├── shared/ # 跨引擎核心用例DuckDB PG openGauss 共用 ├── duckdb/ # DuckDB 独有约 80 个ATTACH、restart、SIMD 等 ├── pg/ # PG 独有并行构建、PQ 量化、GUC 参数等 ├── sqlite/ # SQLite 虚拟表专属用例MATCH k 查询语法 └── opengauss/ # openGauss 独有引擎路由加一个引擎只需一行配置渲染器 tests/spec/_lib/render.py 里有一张路由表ENGINE_DIRS决定每个引擎取哪些目录的用例引擎用例来源DuckDBshared/duckdb/PGshared/pg/openGaussshared/pg/opengauss/PG 兼容 自家SQLiteshared/sqlite/这种按目录物理分类 一行路由的设计让新引擎接入几乎零成本不改任何业务规则只需在路由表加一行。一个 Spec 用例长什么样下面以 tests/spec/shared/index/graph_index_simple.yaml 为例看一份跨引擎用例代码量极小重点是结构name: index__graph_index_simple engines: [duckdb, pg, opengauss] description: Simple test for graph index steps: - statement: CREATE TABLE test_vectors (id INTEGER, vec ${VECTOR(3)}); - statement: INSERT INTO test_vectors VALUES (1, ${VEC_LITERAL([1.0, 0.0, 0.0], 3)}); - statement: CREATE INDEX test_idx ON test_vectors USING ${VEX_INDEX} (vec${OPS_L2_COL})${IDX_OPTS_L2}; - query: SELECT COUNT(*) FROM ${SYS_INDEXES} WHERE ${SYS_INDEXES_NAME} test_idx; expect: [[1]] skip: sqlite: true # 精确豁免该用例不适用于 SQLite注意那些${...}占位符——这是整套 DSL 的灵魂引擎差异不写进用例而是抽到方言字典里。同一条CREATE INDEX语句渲染后在 DuckDB 里是USING GRAPH_INDEX在 PG 里是USING vexdb_graph (vec floatvector_l2_ops)但用例本身一行都不用改。用例还支持tags子集筛选比如只跑pq相关用例、skip按引擎精确豁免并写明原因、_sort结果行排序等字段足够表达绝大多数回归场景。方言字典一份 YAML 抹平三种 SQL 写法所有引擎差异集中在 tests/spec/_lib/dialects.yaml变量分三种形式简单替换${KEY}、函数调用${FUNC(a, b)}、中缀运算符。核心映射举例变量DuckDB 渲染结果PG / openGauss 渲染结果${VECTOR(N)}FLOAT[N]floatvector(N)${VEC_LITERAL([1,0,0], 3)}[1,0,0]::FLOAT[3]ARRAY[1,0,0]::floatvector${VEX_INDEX}GRAPH_INDEXvexdb_graph${L2(a,b)}l2_distance(a,b)(a - b)${RANGE(n)}range(n)generate_series(0, n-1)${SYS_INDEXES}duckdb_indexes()pg_indexes值得玩味的细节inherit继承机制openGauss 直接inherit: pg空字典覆盖天然兼容 PG 语法PG 的 metric 藏在 opclass 里所以${OPS_L2_COL}要插在列名之后vec floatvector_l2_ops而 DuckDB 的 metric 写在WITH (metriccosine)里由${IDX_OPTS_COSINE}追加在语句末尾——这类插入位置差异正是变量被切分成*_COL和*_OPTS两组的原因SQLite 用占位符防炸SQLite 的虚拟表语法CREATE VIRTUAL TABLE ... MATCH与CREATE INDEX根本不同构字典里给它填__unsupported_sqlite_create_index__哨兵值相关用例靠skip: {sqlite: true}豁免走 tests/spec/sqlite/vtab/ 下的专属用例。引擎专属能力则放在对应目录例如 PG 的 PQ 量化冒烟用例 tests/spec/pg/index/graph_index_pq_smoke.yaml验证 encode-at-flush、ADC scan、建索引后 DML 增量编码以及 DuckDB 特有的 ATTACH、崩溃恢复、SIMD 架构用例tests/spec/duckdb/index/ 约 80 个。从 YAML 到测试报告三步跑通第 1 步渲染。一条命令把所有 YAML 编译成各引擎原生产物python3 tests/spec/_lib/render.py --engine all --out build/spec产物形态各不相同但都长得像各引擎的原生测试引擎产物格式DuckDBbuild/spec/duckdb/name.testsqllogictestPGbuild/spec/pg/sql/name.sqlexpected/name.outpg_regress 风格Pythonbuild/spec/python/test_name.pypytestbuild/spec/严格禁止手工编辑CI 的render-checkjob 会校验产物必须来自 spec——这是防止改了产物不改用例导致漂移的关键闸门。第 2 步执行。各引擎 runner 负责渲染 部署 运行DuckDB本地无需 Dockertests/spec/_lib/docker/run_duckdb.shPG自带三阶段 Docker 容器PG 19devel 编译扩展tests/spec/_lib/docker/run_pg.shSQLitetests/spec/_lib/docker/run_sqlite.shbash tests/spec/_lib/docker/run_duckdb.sh test # DuckDB 全集 bash tests/spec/_lib/docker/run_pg.sh build bash tests/spec/_lib/docker/run_pg.sh test第 3 步比较。PG 侧的浮点结果由容差比较器 tests/spec/_lib/docker/compare.py 处理atol/rtol 容差、NULL/bool 规范化、向量字面量逐元素比较避免差一个 ulp 就红的脆弱断言。工具链还包括自动分类器 tests/spec/_lib/classify.py从 30 种 DuckDB-only 语法模式判定用例该放shared/还是duckdb/和反向迁移工具 tests/spec/_lib/migrate_test_to_yaml.py后者正是历史上把 109 个旧 .test 批量迁成 YAML 的那把刷子。当前成绩与扩展思路截至 2026-05体系状态引自 tests/spec/README.md项状态shared/ 跨引擎用例25 个duckdb/ 引擎独有约 80 个DuckDB spec runner105/105100%PG Docker runner26/3672%剩余为 PG 侧功能缺口非测试问题遗留 .test / pg_tests 旧体系已全部退役删除对新手最有价值的两点启发测试框架也是产品架构的镜子——shared/目录里放的就是跨引擎必须行为一致的核心契约它比任何文档都更权威地定义了 VexDB-Lite 的兼容性边界DSL 的克制——整个渲染器只有约 600 行render.py只解决方言差异这一件事不试图变成通用测试平台。规划中的高阶断言如recall_vs_brute_force召回率差分测试留待下一阶段避免过早设计。想深入某个方向的细节可以直接从 tests/spec/README.md 出发按目录翻一两个同族用例对比阅读建议shared/index/graph_index_search.yaml与pg/index/graph_index_parallel_build_ctx_race.yaml对照半小时就能对整套 YAML Spec DSL 体系上手。【免费下载链接】VexDB-LiteA cross-platform vector database, which can be integrated into existing databases as a plugin.项目地址: https://gitcode.com/gh_mirrors/ve/VexDB-Lite创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考