PostgreSQL: unary minus binds more loosely than `^`, so `-1 ^ 0` parses as `-(1 ^ 0)`
维护者通常 1 天内回复
还没有人认领这个 Issue。
- #2830 来自 @compiler-segfault —— 已关闭,未合并
评估
- 难度
- 3/5
- 预计耗时
- 1-2 天
- 新手友好度
- 72/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 技术栈
- rust
调研方向
Read parse_prefix_inner in src/parser/mod.rs and the precedence constants in src/dialect/postgresql.rs; compare the PostgreSQL precedence table cited in the issue. Add or adjust parser coverage for unary plus and minus with ^, including the reproduced expressions. Done means the PostgreSQL dialect produces the expected AST grouping while the generic dialect remains unaffected.
由索引模型根据 Issue 内容生成。
描述
Problem
In PostgreSqlDialect, a unary minus binds more loosely than ^. The parser reads -1 ^ 0 as -(1 ^ 0).
In PostgreSQL, unary minus binds more tightly than ^ (operator precedence table). PostgreSQL reads -1 ^ 0 as (-1) ^ 0.
Reproduction
At main (d1c1790e3):
use sqlparser::dialect::PostgreSqlDialect;
use sqlparser::parser::Parser;
let ast = Parser::parse_sql(&PostgreSqlDialect {}, "SELECT -1 ^ 0").unwrap();
println!("{ast:#?}");
The projection expression is (spans removed):
UnaryOp {
op: Minus,
expr: BinaryOp {
left: Value(Number("1", false)),
op: PGExp,
right: Value(Number("0", false)),
},
}
The expected expression is:
BinaryOp {
left: UnaryOp { op: Minus, expr: Value(Number("1", false)) },
op: PGExp,
right: Value(Number("0", false)),
}
SELECT -2 ^ 2 and SELECT +2 ^ 2 parse the same way.
Effect on query results
The grouping changes the result:
| Query | PostgreSQL 17 | DuckDB | DataFusion (PostgreSQL dialect) |
|---|---|---|---|
SELECT -1 ^ 0 |
1 | 1 | -1 |
SELECT -2 ^ 2 |
4 | 4 | -4 |
DataFusion tracks this in apache/datafusion#27094.
Cause
parse_prefix_inner parses the operand of a unary - or + at Precedence::MulDivModOp (src/parser/mod.rs#L1967-L1979):
tok @ Token::Minus | tok @ Token::Plus => {
// ...
Ok(Expr::UnaryOp {
op,
expr: Box::new(
self.parse_subexpr(self.dialect.prec_value(Precedence::MulDivModOp))?,
),
})
}
PostgreSqlDialect sets CARET_PREC (100) above MUL_DIV_MOD_OP_PREC (90) (src/dialect/postgresql.rs#L213-L214). So the operand of the minus also takes the ^ that follows.
For the PostgreSQL dialect, the operand of a unary - or + must be parsed at a precedence above CARET_PREC. In the PostgreSQL table, unary + and - are also above COLLATE and AT.
The generic dialect is not affected in this way: there, Caret is below MulDivModOp.
Related: #814 (precedence of ~).
- 主要语言
- Rust
- 星标
- 3.5k
- 派生
- 805
- 平均合并
- 2 天 3 小时
- 30 天内合并 PR
- 116
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 没有贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
apache/datafusion-sqlparser-rs 的其他 Issue
-
Redshift
难度 2/5 1-3 小时 新手友好度 82/100
apache/datafusion-sqlparser-rs#2959 ·
维护者通常 1 天内回复
-
Redshift
难度 2/5 1-3 小时 新手友好度 68/100
apache/datafusion-sqlparser-rs#2958 ·
维护者通常 1 天内回复
-
PostgreSQL
难度 2/5 1-3 小时 新手友好度 76/100
apache/datafusion-sqlparser-rs#2862 ·
维护者通常 1 天内回复
-
PostgreSQL
难度 2/5 1-3 小时 新手友好度 75/100
apache/datafusion-sqlparser-rs#2861 ·
维护者通常 1 天内回复
-
PostgreSQL
难度 2/5 1-3 小时 新手友好度 77/100
apache/datafusion-sqlparser-rs#2858 ·
维护者通常 1 天内回复
查看 apache/datafusion-sqlparser-rs 的全部 Issue
相似的 Issue
-
area:schema documentation
难度 2/5 1-3 小时 新手友好度 76/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 82/100
ElectronicWave/Elemental#252 ·
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 78/100
dekobon/big-code-analysis#1887 ·
维护者通常 1 天内回复
-
Shell中文符号输入异常未关闭bug
难度 2/5 1-3 小时 新手友好度 76/100
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 82/100
维护者通常 1 天内回复