pgsql-parser-testing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePGSQL Parser Testing
PGSQL Parser 测试
Testing workflow for the pgsql-parser repository. This skill is scoped specifically to the monorepo.
constructive-io/pgsql-parserpgsql-parser仓库的测试工作流,本技能专门适用于 monorepo。
constructive-io/pgsql-parserWhen to Apply
适用场景
Use this skill when:
- Working in the pgsql-parser repository
- Fixing deparser or parser issues
- Running parser/deparser tests
- Validating SQL round-trip correctness
- Adding new SQL syntax support
在以下场景中使用本技能:
- 在pgsql-parser仓库中开展开发工作
- 修复反解析器或解析器问题
- 运行解析器/反解析器测试
- 验证SQL往返转换的正确性
- 新增SQL语法支持
Repository Structure
仓库结构
pgsql-parser/
packages/
parser/ # SQL parser (libpg_query bindings)
deparser/ # SQL deparser (AST to SQL)
plpgsql-parser/ # PL/pgSQL parser
plpgsql-deparser/ # PL/pgSQL deparser
types/ # TypeScript type definitions
utils/ # Utility functions
traverse/ # AST traversal utilities
transform/ # AST transformation utilitiespgsql-parser/
packages/
parser/ # SQL parser (libpg_query bindings)
deparser/ # SQL deparser (AST to SQL)
plpgsql-parser/ # PL/pgSQL parser
plpgsql-deparser/ # PL/pgSQL deparser
types/ # TypeScript type definitions
utils/ # Utility functions
traverse/ # AST traversal utilities
transform/ # AST transformation utilitiesTesting Strategy
测试策略
The pgsql-parser uses AST-level equality for correctness, not string equality:
parse(sql1) → ast1 → deparse(ast1) → sql2 → parse(sql2) → ast2While textually, a correct round-trip means .
sql2 !== sql1ast1 === ast2pgsql-parser使用AST层级的相等性判断正确性,而非字符串相等性:
parse(sql1) → ast1 → deparse(ast1) → sql2 → parse(sql2) → ast2虽然文本层面,但只要就说明往返转换是正确的。
sql2 !== sql1ast1 === ast2Key Principle
核心原则
Exact SQL string equality is not required. The focus is on comparing resulting ASTs. Use (deparser) or (ast package) to validate correctness.
expectAstMatchexpectPGParse不要求SQL字符串完全相等,重点是对比生成的AST是否一致。可以使用(反解析器)或(ast包)验证正确性。
expectAstMatchexpectPGParseDevelopment Workflow
开发工作流
Initial Setup
初始配置
bash
pnpm install
pnpm buildbash
pnpm install
pnpm buildRunning Tests
运行测试
Run all tests:
bash
pnpm testRun tests for a specific package:
bash
cd packages/deparser
pnpm testWatch mode for rapid iteration:
bash
cd packages/deparser
pnpm test:watchRun a specific test:
bash
pnpm test --testNamePattern="specific-test-name"运行所有测试:
bash
pnpm test运行指定包的测试:
bash
cd packages/deparser
pnpm test开启监听模式实现快速迭代:
bash
cd packages/deparser
pnpm test:watch运行单个指定测试:
bash
pnpm test --testNamePattern="specific-test-name"Fixing Deparser Issues
修复反解析器问题
Systematic Approach
系统化方法
-
One test at a time: Focus on individual failing testsbash
pnpm test --testNamePattern="specific-test" -
Always check for regressions: After each fix, run full test suitebash
pnpm test -
Build before testing: Always rebuild after code changesbash
pnpm build && pnpm test -
Clean commits: Stage files explicitlybash
git add packages/deparser/src/specific-file.ts
-
单次只处理一个测试:聚焦单个失败的测试用例bash
pnpm test --testNamePattern="specific-test" -
始终检查回归问题:每次修复完成后运行完整测试套件bash
pnpm test -
测试前先构建:代码修改后务必重新构建bash
pnpm build && pnpm test -
干净提交:显式暂存修改的文件bash
git add packages/deparser/src/specific-file.ts
Workflow Loop
工作流循环
Make changes → pnpm build → pnpm test --testNamePattern="target" → pnpm test (full) → commit修改代码 → pnpm build → pnpm test --testNamePattern="目标测试名" → 运行全量pnpm test → 提交Test Utilities
测试工具
Deparser Tests
反解析器测试
Location:
packages/deparser/test-utils/index.tstypescript
import { expectAstMatch } from '../test-utils';
it('deparses SELECT correctly', () => {
expectAstMatch('SELECT * FROM users');
});位置:
packages/deparser/test-utils/index.tstypescript
import { expectAstMatch } from '../test-utils';
it('deparses SELECT correctly', () => {
expectAstMatch('SELECT * FROM users');
});AST Package Tests
AST包测试
Location:
packages/ast/test/utils/index.tsUses database deparser for validation:
typescript
import { expectPGParse } from '../test/utils';
it('round-trips through database deparser', async () => {
await expectPGParse('SELECT * FROM users WHERE id = 1');
});Note: AST tests require the database to have function available.
deparser.expressions_array位置:
packages/ast/test/utils/index.ts使用数据库反解析器做验证:
typescript
import { expectPGParse } from '../test/utils';
it('round-trips through database deparser', async () => {
await expectPGParse('SELECT * FROM users WHERE id = 1');
});注意:AST测试要求数据库中存在函数。
deparser.expressions_arrayCommon Commands
常用命令
| Command | Description |
|---|---|
| Build all packages |
| Run all tests |
| Run tests in watch mode |
| Run linter |
| Clean build artifacts |
| 命令 | 描述 |
|---|---|
| 构建所有包 |
| 运行所有测试 |
| 以监听模式运行测试 |
| 运行代码检查 |
| 清理构建产物 |
Package-Specific Testing
特定包测试
Parser Package
Parser包
Tests libpg_query bindings and SQL parsing:
bash
cd packages/parser
pnpm test测试libpg_query绑定和SQL解析能力:
bash
cd packages/parser
pnpm testDeparser Package
Deparser包
Tests AST-to-SQL conversion:
bash
cd packages/deparser
pnpm test测试AST转SQL的转换能力:
bash
cd packages/deparser
pnpm testPL/pgSQL Packages
PL/pgSQL相关包
Tests PL/pgSQL parsing and deparsing:
bash
cd packages/plpgsql-parser
pnpm test
cd packages/plpgsql-deparser
pnpm test测试PL/pgSQL的解析和反解析能力:
bash
cd packages/plpgsql-parser
pnpm test
cd packages/plpgsql-deparser
pnpm testDebugging Tips
调试技巧
-
Use isolated debug scripts for complex issues (don't commit them)
-
Check the AST structure when tests fail:typescript
import { parse } from 'pgsql-parser'; console.log(JSON.stringify(parse('SELECT 1'), null, 2)); -
Compare ASTs visually to understand differences:typescript
const ast1 = parse(sql1); const ast2 = parse(deparse(ast1)); console.log('Original:', JSON.stringify(ast1, null, 2)); console.log('Round-trip:', JSON.stringify(ast2, null, 2));
-
复杂问题可以使用独立的调试脚本(不要提交这些脚本)
-
测试失败时检查AST结构:typescript
import { parse } from 'pgsql-parser'; console.log(JSON.stringify(parse('SELECT 1'), null, 2)); -
可视化对比AST来理解差异:typescript
const ast1 = parse(sql1); const ast2 = parse(deparse(ast1)); console.log('原始AST:', JSON.stringify(ast1, null, 2)); console.log('往返转换后AST:', JSON.stringify(ast2, null, 2));
Troubleshooting
问题排查
| Issue | Solution |
|---|---|
| Tests fail after changes | Run |
| Type errors | Check |
| Shared code changes | Rebuild dependent packages |
| Snapshot mismatches | Review changes, update with |
| 问题 | 解决方案 |
|---|---|
| 修改代码后测试失败 | 运行 |
| 类型错误 | 检查 |
| 公共代码修改 | 重新构建依赖该公共代码的包 |
| 快照不匹配 | 核查修改内容,确认正确后执行 |
Important Notes
注意事项
- Changes to or
typespackages may require rebuilding dependent packagesutils - Each package can be developed and tested independently
- The project uses Lerna for monorepo management
- Always verify no regressions before committing
- 修改或
types包可能需要重新构建依赖它们的其他包utils - 每个包都可以独立开发和测试
- 项目使用Lerna进行monorepo管理
- 提交前务必确认没有引入回归问题
References
参考资料
- Deparser testing docs:
packages/deparser/TESTING.md - Quoting rules:
packages/deparser/QUOTING-RULES.md - Deparser usage:
packages/deparser/DEPARSER_USAGE.md - PL/pgSQL deparser:
packages/plpgsql-deparser/AGENTS.md
- 反解析器测试文档:
packages/deparser/TESTING.md - 引号规则:
packages/deparser/QUOTING-RULES.md - 反解析器使用说明:
packages/deparser/DEPARSER_USAGE.md - PL/pgSQL反解析器:
packages/plpgsql-deparser/AGENTS.md