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/15 17:58:41 UTC
(datafusion-sqlparser-rs) branch gh-readonly-queue/main/pr-2629-a6f518bf7ef58ec6e7a00da286f9185b0de01b2d created (now 6434b5a2)
This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a change to branch gh-readonly-queue/main/pr-2629-a6f518bf7ef58ec6e7a00da286f9185b0de01b2d
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
at 6434b5a2 Assert exact errors in negative tests (2/4): common and parser unit tests (#2629)
This branch includes the following new commits:
new 6434b5a2 Assert exact errors in negative tests (2/4): common and parser unit tests (#2629)
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: Assert exact errors in negative tests (2/4): common and parser unit tests (#2629)
Posted by gi...@apache.org.
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-2629-a6f518bf7ef58ec6e7a00da286f9185b0de01b2d
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
commit 6434b5a224a77ee9e1830b2a840eca0bf6bdc9fb
Author: Luca Cappelletti <ca...@gmail.com>
AuthorDate: Thu Oct 15 17:58:19 2026 +0000
Assert exact errors in negative tests (2/4): common and parser unit tests (#2629)
---
src/parser/mod.rs | 36 +++++-
tests/sqlparser_common.rs | 312 +++++++++++++++++++++++++---------------------
2 files changed, 202 insertions(+), 146 deletions(-)
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 37e9997c..24947764 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -22344,28 +22344,54 @@ mod tests {
fn test_replace_into_placeholders() {
let sql = "REPLACE INTO t (a) VALUES (&a)";
- assert!(Parser::parse_sql(&GenericDialect {}, sql).is_err());
+ assert_eq!(
+ ParserError::ParserError(
+ "Expected: an expression, found: & at Line: 1, Column: 28".to_string()
+ ),
+ Parser::parse_sql(&GenericDialect {}, sql).unwrap_err()
+ );
}
#[test]
fn test_replace_into_set_placeholder() {
let sql = "REPLACE INTO t SET ?";
- assert!(Parser::parse_sql(&GenericDialect {}, sql).is_err());
+ assert_eq!(
+ ParserError::ParserError(
+ "Expected: SELECT, VALUES, or a subquery in the query body, found: SET at Line: 1, Column: 16"
+ .to_string()
+ ),
+ Parser::parse_sql(&GenericDialect {}, sql).unwrap_err()
+ );
}
#[test]
fn test_replace_incomplete() {
let sql = r#"REPLACE"#;
- assert!(Parser::parse_sql(&MySqlDialect {}, sql).is_err());
+ assert_eq!(
+ ParserError::ParserError("Expected: identifier, found: EOF".to_string()),
+ Parser::parse_sql(&MySqlDialect {}, sql).unwrap_err()
+ );
}
#[test]
fn test_placeholder_invalid_whitespace() {
- for w in [" ", "/*invalid*/"] {
+ for (w, expected) in [
+ (
+ " ",
+ "Expected: placeholder, found: at Line: 3, Column: 4",
+ ),
+ (
+ "/*invalid*/",
+ "Expected: placeholder, found: /*invalid*/ at Line: 3, Column: 4",
+ ),
+ ] {
let sql = format!("\nSELECT\n :{w}fooBar");
- assert!(Parser::parse_sql(&GenericDialect, &sql).is_err());
+ assert_eq!(
+ ParserError::ParserError(expected.to_string()),
+ Parser::parse_sql(&GenericDialect, &sql).unwrap_err()
+ );
}
}
}
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index f153a59d..bfe5bf67 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -723,13 +723,21 @@ fn parse_invalid_table_name() {
let ast = all_dialects().run_parser_method("db.public..customer", |parser| {
parser.parse_object_name(false)
});
- assert!(ast.is_err());
+ assert_eq!(
+ ParserError::ParserError(
+ "Expected: identifier, found: . at Line: 1, Column: 11".to_string()
+ ),
+ ast.unwrap_err()
+ );
}
#[test]
fn parse_no_table_name() {
let ast = all_dialects().run_parser_method("", |parser| parser.parse_object_name(false));
- assert!(ast.is_err());
+ assert_eq!(
+ ParserError::ParserError("Expected: identifier, found: EOF".to_string()),
+ ast.unwrap_err()
+ );
}
#[test]
@@ -12410,9 +12418,12 @@ fn parse_non_latin_identifiers() {
Box::new(DuckDbDialect {}),
Box::new(MsSqlDialect {}),
]);
- assert!(supported_dialects
- .parse_sql_statements("SELECT 💝 FROM table1")
- .is_err());
+ assert_eq!(
+ ParserError::ParserError("Expected: an expression, found: 💝".to_string()),
+ supported_dialects
+ .parse_sql_statements("SELECT 💝 FROM table1")
+ .unwrap_err()
+ );
}
#[test]
@@ -17638,128 +17649,134 @@ fn parse_pipeline_operator_negative_tests() {
);
// Test that CALL without function name fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> CALL")
- .is_err());
-
- // Test that CALL without parentheses fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> CALL my_function")
- .is_err());
-
- // Test that CALL with invalid function syntax fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> CALL 123 invalid")
- .is_err());
-
- // Test that CALL with malformed arguments fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> CALL my_function(,)")
- .is_err());
-
- // Test that CALL with invalid alias syntax fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> CALL my_function() AS")
- .is_err());
-
- // Test that PIVOT without parentheses fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> PIVOT SUM(amount) FOR month IN ('Jan')")
- .is_err());
-
- // Test that PIVOT without FOR keyword fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> PIVOT(SUM(amount) month IN ('Jan'))")
- .is_err());
-
- // Test that PIVOT without IN keyword fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> PIVOT(SUM(amount) FOR month ('Jan'))")
- .is_err());
-
- // Test that PIVOT with empty IN list fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> PIVOT(SUM(amount) FOR month IN ())")
- .is_err());
-
- // Test that PIVOT with invalid alias syntax fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> PIVOT(SUM(amount) FOR month IN ('Jan')) AS")
- .is_err());
-
- // Test UNPIVOT negative cases
-
- // Test that UNPIVOT without parentheses fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> UNPIVOT value FOR name IN col1, col2")
- .is_err());
-
- // Test that UNPIVOT without FOR keyword fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> UNPIVOT(value name IN (col1, col2))")
- .is_err());
-
- // Test that UNPIVOT without IN keyword fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> UNPIVOT(value FOR name (col1, col2))")
- .is_err());
-
- // Test that UNPIVOT with missing value column fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> UNPIVOT(FOR name IN (col1, col2))")
- .is_err());
-
- // Test that UNPIVOT with missing name column fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> UNPIVOT(value FOR IN (col1, col2))")
- .is_err());
-
- // Test that UNPIVOT with empty IN list fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> UNPIVOT(value FOR name IN ())")
- .is_err());
-
- // Test that UNPIVOT with invalid alias syntax fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> UNPIVOT(value FOR name IN (col1, col2)) AS")
- .is_err());
-
- // Test that UNPIVOT with missing closing parenthesis fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> UNPIVOT(value FOR name IN (col1, col2)")
- .is_err());
-
- // Test that JOIN without table name fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> JOIN ON users.id = orders.user_id")
- .is_err());
-
- // Test that CROSS JOIN with ON condition fails
- assert!(dialects
- .parse_sql_statements(
- "SELECT * FROM users |> CROSS JOIN orders ON users.id = orders.user_id"
- )
- .is_err());
-
- // Test that CROSS JOIN with USING condition fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> CROSS JOIN orders USING (user_id)")
- .is_err());
-
- // Test that JOIN with empty USING list fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> JOIN orders USING ()")
- .is_err());
-
- // Test that JOIN with malformed ON condition fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> JOIN orders ON")
- .is_err());
-
- // Test that JOIN with invalid USING syntax fails
- assert!(dialects
- .parse_sql_statements("SELECT * FROM users |> JOIN orders USING user_id")
- .is_err());
+ for (sql, err_msg) in [
+ (
+ "SELECT * FROM users |> CALL",
+ "Expected: identifier, found: EOF",
+ ),
+ // Test that CALL without parentheses fails
+ (
+ "SELECT * FROM users |> CALL my_function",
+ "Expected: (, found: EOF",
+ ),
+ // Test that CALL with invalid function syntax fails
+ (
+ "SELECT * FROM users |> CALL 123 invalid",
+ "Expected: identifier, found: 123",
+ ),
+ // Test that CALL with malformed arguments fails
+ (
+ "SELECT * FROM users |> CALL my_function(,)",
+ "Expected: an expression, found: ,",
+ ),
+ // Test that CALL with invalid alias syntax fails
+ (
+ "SELECT * FROM users |> CALL my_function() AS",
+ "Expected: identifier, found: EOF",
+ ),
+ // Test that PIVOT without parentheses fails
+ (
+ "SELECT * FROM users |> PIVOT SUM(amount) FOR month IN ('Jan')",
+ "Expected: (, found: SUM",
+ ),
+ // Test that PIVOT without FOR keyword fails
+ (
+ "SELECT * FROM users |> PIVOT(SUM(amount) month IN ('Jan'))",
+ "Expected: FOR, found: IN",
+ ),
+ // Test that PIVOT without IN keyword fails
+ (
+ "SELECT * FROM users |> PIVOT(SUM(amount) FOR month ('Jan'))",
+ "Expected: IN, found: (",
+ ),
+ // Test that PIVOT with empty IN list fails
+ (
+ "SELECT * FROM users |> PIVOT(SUM(amount) FOR month IN ())",
+ "Expected: an expression, found: )",
+ ),
+ // Test that PIVOT with invalid alias syntax fails
+ (
+ "SELECT * FROM users |> PIVOT(SUM(amount) FOR month IN ('Jan')) AS",
+ "Expected: identifier, found: EOF",
+ ),
+ // Test UNPIVOT negative cases
+ // Test that UNPIVOT without parentheses fails
+ (
+ "SELECT * FROM users |> UNPIVOT value FOR name IN col1, col2",
+ "Expected: (, found: value",
+ ),
+ // Test that UNPIVOT without FOR keyword fails
+ (
+ "SELECT * FROM users |> UNPIVOT(value name IN (col1, col2))",
+ "Expected: FOR, found: name",
+ ),
+ // Test that UNPIVOT without IN keyword fails
+ (
+ "SELECT * FROM users |> UNPIVOT(value FOR name (col1, col2))",
+ "Expected: IN, found: (",
+ ),
+ // Test that UNPIVOT with missing value column fails
+ (
+ "SELECT * FROM users |> UNPIVOT(FOR name IN (col1, col2))",
+ "Expected: FOR, found: name",
+ ),
+ // Test that UNPIVOT with missing name column fails
+ (
+ "SELECT * FROM users |> UNPIVOT(value FOR IN (col1, col2))",
+ "Expected: IN, found: (",
+ ),
+ // Test that UNPIVOT with empty IN list fails
+ (
+ "SELECT * FROM users |> UNPIVOT(value FOR name IN ())",
+ "Expected: identifier, found: )",
+ ),
+ // Test that UNPIVOT with invalid alias syntax fails
+ (
+ "SELECT * FROM users |> UNPIVOT(value FOR name IN (col1, col2)) AS",
+ "Expected: identifier, found: EOF",
+ ),
+ // Test that UNPIVOT with missing closing parenthesis fails
+ (
+ "SELECT * FROM users |> UNPIVOT(value FOR name IN (col1, col2)",
+ "Expected: ), found: EOF",
+ ),
+ // Test that JOIN without table name fails
+ (
+ "SELECT * FROM users |> JOIN ON users.id = orders.user_id",
+ "Expected: end of statement, found: .",
+ ),
+ // Test that CROSS JOIN with ON condition fails
+ (
+ "SELECT * FROM users |> CROSS JOIN orders ON users.id = orders.user_id",
+ "Expected: end of statement, found: ON",
+ ),
+ // Test that CROSS JOIN with USING condition fails
+ (
+ "SELECT * FROM users |> CROSS JOIN orders USING (user_id)",
+ "Expected: end of statement, found: USING",
+ ),
+ // Test that JOIN with empty USING list fails
+ (
+ "SELECT * FROM users |> JOIN orders USING ()",
+ "Expected: identifier, found: )",
+ ),
+ // Test that JOIN with malformed ON condition fails
+ (
+ "SELECT * FROM users |> JOIN orders ON",
+ "Expected: an expression, found: EOF",
+ ),
+ // Test that JOIN with invalid USING syntax fails
+ (
+ "SELECT * FROM users |> JOIN orders USING user_id",
+ "Expected: a list of columns in parentheses, found: user_id",
+ ),
+ ] {
+ let res = dialects.parse_sql_statements(sql);
+ assert_eq!(
+ ParserError::ParserError(err_msg.to_string()),
+ res.unwrap_err()
+ );
+ }
}
#[test]
@@ -19828,10 +19845,11 @@ fn parse_select_item_multi_column_alias() {
all_dialects_where(|d| d.supports_select_item_multi_column_alias())
.verified_stmt("SELECT stack(2, 'a', 'b', 'c', 'd') AS (col1, col2) FROM t");
- assert!(
+ assert_eq!(
+ ParserError::ParserError("Expected: an identifier after AS, found: (".to_string()),
all_dialects_where(|d| !d.supports_select_item_multi_column_alias())
.parse_sql_statements("SELECT stack(2, 'a', 'b') AS (col1, col2)")
- .is_err()
+ .unwrap_err()
);
}
@@ -19852,9 +19870,12 @@ fn parse_aliased_function_args() {
dialects.verified_only_select("SELECT foo(lower(a) AS x, b AS y)");
dialects.verified_only_select(r#"SELECT foo(a AS "x y")"#);
dialects.verified_only_select("SELECT foo(bar(a AS x) AS y)");
- assert!(all_dialects_except(|d| d.supports_aliased_function_args())
- .parse_sql_statements("SELECT foo(a AS x)")
- .is_err());
+ assert_eq!(
+ ParserError::ParserError("Expected: ), found: AS".to_string()),
+ all_dialects_except(|d| d.supports_aliased_function_args())
+ .parse_sql_statements("SELECT foo(a AS x)")
+ .unwrap_err()
+ );
}
#[test]
@@ -19889,9 +19910,12 @@ fn parse_xmlparse() {
}
// XMLPARSE needs both a mode word and a value.
- assert!(dialects
- .parse_sql_statements("SELECT xmlparse('<a/>')")
- .is_err());
+ assert_eq!(
+ ParserError::ParserError("Expected: an expression, found: )".to_string()),
+ dialects
+ .parse_sql_statements("SELECT xmlparse('<a/>')")
+ .unwrap_err()
+ );
// Going through the ordinary function-call path, XMLPARSE accepts the same
// trailing clauses as any other function.
@@ -19902,9 +19926,12 @@ fn parse_xmlparse() {
// and the special `CONTENT <expr>` syntax is rejected.
let others = all_dialects_except(|d| d.supports_xml_expressions());
others.verified_only_select("SELECT xmlparse(1)");
- assert!(others
- .parse_sql_statements("SELECT xmlparse(content '<a/>')")
- .is_err());
+ assert_eq!(
+ ParserError::ParserError("Expected: ), found: '<a/>'".to_string()),
+ others
+ .parse_sql_statements("SELECT xmlparse(content '<a/>')")
+ .unwrap_err()
+ );
}
/// Regression test for the 2^N parse-time blowup in `parse_compound_expr` on
@@ -20235,9 +20262,12 @@ fn parse_alter_table_column_position() {
),
_ => unreachable!(),
}
- assert!(dialects
- .parse_sql_statements("ALTER TABLE tab ADD COLUMN c INT AFTER")
- .is_err());
+ assert_eq!(
+ ParserError::ParserError("Expected: identifier, found: EOF".to_string()),
+ dialects
+ .parse_sql_statements("ALTER TABLE tab ADD COLUMN c INT AFTER")
+ .unwrap_err()
+ );
let dialects = all_dialects_where(|d| !d.supports_alter_column_position());
for sql in [
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org