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