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

LucaCappelletti94 pushed a commit to branch compound-field-access-number-spacing
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git

commit a492c327a70a9b9c56d3cb05da2c33f188027ced
Author: LucaCappelletti94 <[email protected]>
AuthorDate: Tue Sep 22 10:26:10 2026 +0200

    Generic: Add spacing around dot in compound field access adjacent to numbers
---
 src/ast/mod.rs            | 25 +++++++++++++++++++++----
 tests/sqlparser_common.rs | 22 ++++++++++++++++++++++
 2 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index dcfd1a96..adabf760 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -1484,12 +1484,14 @@ pub enum AccessExpr {
     Subscript(Subscript),
 }
 
+const fn is_number_expr(expr: &Expr) -> bool {
+    matches!(expr, Expr::Value(v) if matches!(v.value, Value::Number(_, _)))
+}
+
 impl fmt::Display for AccessExpr {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            AccessExpr::Dot(Expr::Value(value)) if matches!(value.value, 
Value::Number(_, _)) => {
-                write!(f, " . {value}")
-            }
+            AccessExpr::Dot(expr) if is_number_expr(expr) => write!(f, " . 
{expr}"),
             AccessExpr::Dot(expr) => write!(f, ".{expr}"),
             AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
         }
@@ -1751,8 +1753,23 @@ impl fmt::Display for Expr {
             Expr::CompoundIdentifier(s) => write!(f, "{}", 
display_separated(s, ".")),
             Expr::CompoundFieldAccess { root, access_chain } => {
                 write!(f, "{root}")?;
+                let mut prev_is_number = is_number_expr(root);
                 for field in access_chain {
-                    write!(f, "{field}")?;
+                    match field {
+                        AccessExpr::Dot(expr) => {
+                            let curr_is_number = is_number_expr(expr);
+                            if prev_is_number || curr_is_number {
+                                write!(f, " . {expr}")?;
+                            } else {
+                                write!(f, ".{expr}")?;
+                            }
+                            prev_is_number = curr_is_number;
+                        }
+                        AccessExpr::Subscript(subscript) => {
+                            write!(f, "[{subscript}]")?;
+                            prev_is_number = false;
+                        }
+                    }
                 }
                 Ok(())
             }
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index c4aa607d..c9734166 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -20080,3 +20080,25 @@ fn parse_unary_minus_never_renders_line_comment() {
     all_dialects().verified_stmt("SELECT -1");
     all_dialects().verified_stmt("SELECT -x");
 }
+
+#[test]
+fn parse_compound_field_access_numeric_display() {
+    all_dialects().verified_stmt("SELECT 1 . i");
+    all_dialects().verified_stmt("SELECT (1 . i)");
+    all_dialects().verified_stmt("SELECT 1 . 2");
+    all_dialects().verified_stmt("SELECT (a . 1 . b)");
+    all_dialects().verified_stmt("SELECT 1 . i.j");
+    all_dialects().verified_stmt("SELECT 1 . 2 . 3");
+    all_dialects().verified_stmt("SELECT a.b.c");
+
+    // In dialects that do not treat `1.i` as a numeric-prefixed identifier,
+    // without space, `1.` is tokenized as a numeric literal with decimal 
point,
+    // causing a parse error when immediately followed by an identifier.
+    let err = all_dialects_where(|d| !d.supports_numeric_prefix())
+        .parse_sql_statements("SELECT (1.i)")
+        .unwrap_err();
+    assert_eq!(
+        err,
+        ParserError::ParserError("Expected: ), found: i".to_string())
+    );
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to