SQL Formatter项目修复DuckDB JSON操作符格式化问题
痛点场景:DuckDB JSON操作符格式化混乱
在日常的SQL开发中,DuckDB作为一种新兴的高性能分析型数据库,其强大的JSON处理能力备受开发者青睐。然而,当我们使用SQL Formatter对包含JSON操作符的DuckDB查询进行格式化时,经常会遇到以下问题:
-- 格式化前
SELECT data->'name' as user_name, data->>'email' as user_email FROM users WHERE data@>'{"active": true}';
-- 格式化后出现异常
SELECT
data - > 'name' as user_name,
data - >> 'email' as user_email
FROM
users
WHERE
data @ > '{"active": true}';
可以看到,JSON操作符 ->、->>、@> 被错误地分割,导致SQL语法错误,无法正常执行。
问题根源分析
JSON操作符在SQL方言中的差异
不同数据库对JSON操作符的支持存在显著差异:
| 数据库 | JSON操作符 | 功能描述 |
|---|---|---|
| PostgreSQL | ->, ->>, #>, #>>, @>, <@ | 完整的JSON路径查询 |
| MySQL | ->, ->> | 简化的JSON提取 |
| DuckDB | ->, ->>, @>, <@, ?, ?|, ?& | 扩展的JSON操作符集 |
| SQLite | ->, ->> | JSON1扩展的操作符 |
SQL Formatter的运算符解析机制
SQL Formatter使用正则表达式模式匹配来识别运算符,当前实现中:
解决方案:增强DuckDB方言支持
1. 识别DuckDB特有的JSON操作符
通过分析DuckDB文档,需要支持以下JSON操作符:
const duckdbOperators = [
// JSON提取操作符
'->', // 提取JSON对象字段(返回JSON)
'->>', // 提取JSON对象字段(返回文本)
'#>', // 提取JSON路径(返回JSON)
'#>>', // 提取JSON路径(返回文本)
// JSON包含操作符
'@>', // 左侧JSON包含右侧JSON
'<@', // 右侧JSON包含左侧JSON
// JSON存在性检查
'?', // 字符串是否存在作为顶级键
'?|', // 数组中任一字符串是否存在作为顶级键
'?&', // 数组中所有字符串是否存在作为顶级键
// JSON连接操作符
'||' // JSON连接
];
2. 修改方言配置文件
在SQL Formatter的DuckDB方言配置中添加完整的操作符支持:
// src/languages/duckdb/duckdb.formatter.ts
export const duckdb: DialectOptions = {
name: 'duckdb',
tokenizerOptions: {
operators: [
// 标准运算符
'%', '^', '|', '&', '~', '<<', '>>', '<=>',
// JSON操作符
'->', '->>', '#>', '#>>', '@>', '<@', '?', '?|', '?&',
// 其他DuckDB特有运算符
'::', '||'
],
// 其他配置...
}
};
3. 添加测试用例确保兼容性
为确保修复的有效性,需要添加相应的测试用例:
// test/duckdb.test.ts
describe('duckdb JSON operators', () => {
it('formats JSON extraction operators correctly', () => {
expect(
format(`SELECT data->'name', data->>'email' FROM users`, {
language: 'duckdb'
})
).toBe(`SELECT
data -> 'name',
data ->> 'email'
FROM
users`);
});
it('formats JSON containment operators correctly', () => {
expect(
format(`SELECT * FROM events WHERE metadata @> '{"type":"click"}'`, {
language: 'duckdb'
})
).toBe(`SELECT
*
FROM
events
WHERE
metadata @> '{"type":"click"}'`);
});
});
修复效果对比
修复前的问题表现
-- 错误格式化
SELECT
data - > 'name',
data - >> 'email'
FROM
users
WHERE
data @ > '{"active": true}'
修复后的正确格式化
-- 正确格式化
SELECT
data->'name',
data->>'email'
FROM
users
WHERE
data @> '{"active": true}'
技术实现细节
运算符优先级处理
JSON操作符具有特定的优先级规则,需要在格式化时正确处理:
边界情况处理
修复过程中需要特别注意的边界情况:
- 运算符与注释的交互
- 多行表达式的格式化
- 嵌套JSON路径的处理
- 与其他运算符的混合使用
最佳实践建议
1. 选择合适的分方言配置
// 针对DuckDB使用专用配置
const formattedSQL = format(sql, {
language: 'duckdb',
tabWidth: 2,
keywordCase: 'upper'
});
2. 自定义运算符支持
对于特殊需求,可以扩展运算符配置:
format(sql, {
paramTypes: {
custom: [{
regex: /->>?|#>>?|@>|<@|[\?&|]/,
key: v => v
}]
}
});
3. 版本兼容性检查
确保使用的SQL Formatter版本包含DuckDB修复:
npm list sql-formatter
# 确保版本 >= 12.1.0 包含DuckDB修复
总结
通过本次修复,SQL Formatter项目完善了对DuckDB JSON操作符的支持,解决了格式化过程中运算符错误分割的问题。这一改进使得开发者能够更加顺畅地在DuckDB中使用JSON功能,同时保持了代码的可读性和一致性。
关键改进点:
- ✅ 完整支持DuckDB所有JSON操作符
- ✅ 保持运算符的连贯性和正确性
- ✅ 提供全面的测试用例覆盖
- ✅ 确保向后兼容性
对于使用DuckDB进行JSON数据处理的开发团队,这一修复显著提升了开发体验和代码质量。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



