You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by lu...@apache.org on 2026/09/21 21:12:48 UTC

(datafusion-sqlparser-rs) branch pg-postfix-factorial-spacing created (now 0d001461)

This is an automated email from the ASF dual-hosted git repository.

LucaCappelletti94 pushed a change to branch pg-postfix-factorial-spacing
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git


      at 0d001461 PostgreSQL: Fix spacing between adjacent postfix factorial operators

This branch includes the following new commits:

     new 0d001461 PostgreSQL: Fix spacing between adjacent postfix factorial operators

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org


(datafusion-sqlparser-rs) 01/01: PostgreSQL: Fix spacing between adjacent postfix factorial operators

Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

LucaCappelletti94 pushed a commit to branch pg-postfix-factorial-spacing
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git

commit 0d001461fa512b64596837ccd196c3110d1c013e
Author: LucaCappelletti94 <ca...@gmail.com>
AuthorDate: Mon Sep 21 23:12:33 2026 +0200

    PostgreSQL: Fix spacing between adjacent postfix factorial operators
---
 src/ast/mod.rs              | 28 +++++++++++++++++++++++++++-
 tests/sqlparser_postgres.rs | 18 ++++++++++++++++++
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index dcfd1a96..0755d7fa 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -1956,7 +1956,13 @@ impl fmt::Display for Expr {
                 )
             }
             Expr::UnaryOp { op, expr } => match op {
-                UnaryOperator::PGPostfixFactorial => write!(f, "{expr}{op}"),
+                UnaryOperator::PGPostfixFactorial => {
+                    if ends_with_operator_char(expr) {
+                        write!(f, "{expr} {op}")
+                    } else {
+                        write!(f, "{expr}{op}")
+                    }
+                }
                 UnaryOperator::Not
                 | UnaryOperator::BitwiseNot
                 | UnaryOperator::Hash
@@ -8109,6 +8115,26 @@ fn starts_with_operator_char(expr: &Expr) -> bool {
     first.0.is_some_and(|c| OPERATOR_CHARS.contains(c))
 }
 
+/// Whether `expr` renders with an operator character last. A postfix `!`
+/// must not abut one, since `!!` is the prefix factorial operator in
+/// PostgreSQL.
+fn ends_with_operator_char(expr: &Expr) -> bool {
+    use fmt::Write;
+    struct LastChar(Option<char>);
+    impl fmt::Write for LastChar {
+        fn write_str(&mut self, s: &str) -> fmt::Result {
+            if let Some(c) = s.chars().last() {
+                self.0 = Some(c);
+            }
+            Ok(())
+        }
+    }
+    let mut last = LastChar(None);
+    let _ = write!(last, "{expr}");
+    const OPERATOR_CHARS: &str = "+-*/<>=~!@%#^&|";
+    last.0.is_some_and(|c| OPERATOR_CHARS.contains(c))
+}
+
 /// `FunctionArgOperator::Space` has no token of its own, so the name and the
 /// value are separated by a single space instead.
 fn fmt_named_function_arg(
diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs
index ab2d4b8e..543ff6aa 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -9984,3 +9984,21 @@ fn parse_unary_minus_before_pg_prefix_operators() {
     pg().verified_stmt("SELECT - @ 2");
     pg().one_statement_parses_to("SELECT - #x", "SELECT - # x");
 }
+
+#[test]
+fn parse_postfix_factorial_spacing() {
+    pg().verified_stmt("SELECT a!");
+    pg().verified_stmt("SELECT 5!");
+    pg().verified_stmt("SELECT (a!)!");
+    pg().verified_stmt("SELECT a! !");
+    pg().verified_stmt("SELECT a! ! !");
+    pg().verified_stmt("SELECT a! ! % 2");
+    pg().one_statement_parses_to("SELECT a! !%2", "SELECT a! ! % 2");
+    pg().one_statement_parses_to("SELECT -a, +b, a! !%2, a", "SELECT -a, +b, a! ! % 2, a");
+
+    let err = pg().parse_sql_statements("SELECT a!!").unwrap_err();
+    assert_eq!(
+        ParserError::ParserError("Expected: end of statement, found: !!".to_string()),
+        err
+    );
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org