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/10/05 13:04:14 UTC

(datafusion-sqlparser-rs) 01/01: SQLite: Reject colon-based semi-structured data traversal

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

LucaCappelletti94 pushed a commit to branch upstream/sqlite-postfix-colon
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git

commit de5c5e8ecd4f961fad329039122cf1dd3520286d
Author: LucaCappelletti94 <ca...@gmail.com>
AuthorDate: Mon Oct 5 15:03:57 2026 +0200

    SQLite: Reject colon-based semi-structured data traversal
---
 src/dialect/sqlite.rs     |  9 +++++++++
 tests/sqlparser_sqlite.rs | 21 +++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/src/dialect/sqlite.rs b/src/dialect/sqlite.rs
index 6f9ec0d2..a01ced32 100644
--- a/src/dialect/sqlite.rs
+++ b/src/dialect/sqlite.rs
@@ -23,6 +23,7 @@ use crate::ast::{Expr, Statement};
 use crate::dialect::Dialect;
 use crate::keywords::Keyword;
 use crate::parser::{Parser, ParserError};
+use crate::tokenizer::Token;
 
 /// A [`Dialect`] for [SQLite](https://www.sqlite.org)
 ///
@@ -97,6 +98,14 @@ impl Dialect for SQLiteDialect {
         None
     }
 
+    fn get_next_precedence(&self, parser: &Parser) -> Option<Result<u8, ParserError>> {
+        match &parser.peek_token_ref().token {
+            // lowest prec to prevent it from turning into a binary op
+            Token::Colon => Some(Ok(self.prec_unknown())),
+            _ => None,
+        }
+    }
+
     fn supports_in_empty_list(&self) -> bool {
         true
     }
diff --git a/tests/sqlparser_sqlite.rs b/tests/sqlparser_sqlite.rs
index b8fad7e9..2ed39bfc 100644
--- a/tests/sqlparser_sqlite.rs
+++ b/tests/sqlparser_sqlite.rs
@@ -1024,6 +1024,27 @@ fn parse_n_prefix_not_national_string() {
     all_dialects_where(|d| d.supports_national_string_literal()).verified_stmt("SELECT N'hello'");
 }
 
+#[test]
+fn parse_colon_does_not_start_json_access() {
+    // SQLite rejects `SELECT c:se` (`near ":se": syntax error`); no `:` traversal.
+    assert!(sqlite().parse_sql_statements("SELECT c:se").is_err());
+    assert!(sqlite().parse_sql_statements("SELECT a:b FROM t").is_err());
+
+    // Named parameters are unaffected, `:` still starts a placeholder.
+    let ast = sqlite().verified_only_select("SELECT :xxx");
+    assert_eq!(
+        ast.projection[0],
+        UnnamedExpr(Expr::Value(
+            (Value::Placeholder(":xxx".into())).with_empty_span()
+        )),
+    );
+
+    // Other dialects keep the `:` traversal operator.
+    assert!(TestedDialects::new(vec![Box::new(GenericDialect {})])
+        .parse_sql_statements("SELECT a:b FROM t")
+        .is_ok());
+}
+
 fn sqlite() -> TestedDialects {
     TestedDialects::new(vec![Box::new(SQLiteDialect {})])
 }


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