You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by gi...@apache.org on 2026/10/01 18:29:46 UTC
(datafusion-sqlparser-rs) 01/01: Generic: Render prefix `!` operator with space before operator characters (#2541)
This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-2541-c2e085d5527b88059d353932674f13f3b87118c0
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
commit bfc7d388bfa8ae84d4d29b5f8798867e1f496342
Author: Luca Cappelletti <ca...@gmail.com>
AuthorDate: Thu Oct 1 18:29:25 2026 +0000
Generic: Render prefix `!` operator with space before operator characters (#2541)
---
src/ast/mod.rs | 31 +++++++++++--------------------
tests/sqlparser_common.rs | 17 +++++++++++++++++
2 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index a899d3ec3..d97f23dac 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -1986,16 +1986,14 @@ impl fmt::Display for Expr {
| UnaryOperator::QuestionPipe
| UnaryOperator::PGSquareRoot
| UnaryOperator::PGCubeRoot => write!(f, "{op} {expr}"),
- UnaryOperator::Minus => {
+ UnaryOperator::Minus | UnaryOperator::BangNot => {
if starts_with_operator_char(expr) {
write!(f, "{op} {expr}")
} else {
write!(f, "{op}{expr}")
}
}
- UnaryOperator::Plus | UnaryOperator::BangNot | UnaryOperator::PGPrefixFactorial => {
- write!(f, "{op}{expr}")
- }
+ UnaryOperator::Plus | UnaryOperator::PGPrefixFactorial => write!(f, "{op}{expr}"),
},
Expr::Convert {
is_try,
@@ -8114,24 +8112,17 @@ impl fmt::Display for FunctionArg {
}
}
-/// Whether `expr` renders with an operator character first. A prefix `-`
-/// must not abut one, since `--` starts a line comment and operator-run
-/// dialects fuse `-@`, `-~`, `-#`, `-!!` and `-||/` into single tokens.
-fn starts_with_operator_char(expr: &Expr) -> bool {
- use fmt::Write;
- struct FirstChar(Option<char>);
- impl fmt::Write for FirstChar {
- fn write_str(&mut self, s: &str) -> fmt::Result {
- if self.0.is_none() {
- self.0 = s.chars().next();
- }
- Ok(())
+/// Whether `expr` renders with an operator character first. A prefix `-` or `!`
+/// must not abut one, since `--` starts a line comment and compound tokens
+/// like `!!` or `!~` alter the parsed AST or fail to parse.
+fn starts_with_operator_char(mut expr: &Expr) -> bool {
+ loop {
+ match expr {
+ Expr::UnaryOp { op, .. } => return !matches!(op, UnaryOperator::Not),
+ Expr::BinaryOp { left, .. } => expr = left,
+ _ => return false,
}
}
- let mut first = FirstChar(None);
- let _ = write!(first, "{expr}");
- const OPERATOR_CHARS: &str = "+-*/<>=~!@%#^&|";
- first.0.is_some_and(|c| OPERATOR_CHARS.contains(c))
}
/// `FunctionArgOperator::Space` has no token of its own, so the name and the
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index 354ccc8b7..bd5440992 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -20263,3 +20263,20 @@ fn parse_placeholder_disallows_quoted_ident() {
err
);
}
+
+#[test]
+fn parse_bang_not_renders_apart_from_operand() {
+ let dialects = all_dialects_where(|d| d.supports_bang_not_operator());
+ dialects.verified_stmt("SELECT ! !a");
+ dialects.verified_stmt("SELECT ! ! !a");
+ dialects.verified_stmt("SELECT ! ~ a");
+ dialects.verified_stmt("SELECT ! -a");
+ dialects.verified_stmt("SELECT ! +a");
+ dialects.verified_stmt("SELECT !a");
+ dialects.verified_stmt("SELECT !(b > 3)");
+ dialects.verified_stmt("SELECT ! -a + b");
+ dialects.verified_stmt("SELECT !a + b");
+ dialects.verified_stmt("SELECT !NOT a");
+ dialects.verified_stmt("SET eaac_cion = ! !o");
+ dialects.one_statement_parses_to("SET eaac_cion = ! ! o", "SET eaac_cion = ! !o");
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org