From bb9561280f1e0c0624e58bd2b72c8121eceac22d Mon Sep 17 00:00:00 2001 From: Kfir Ben Shimon Date: Mon, 1 Jun 2026 15:47:26 +0300 Subject: [PATCH 1/2] Added support to parse xmlnamespace in mssql --- src/dialect/mod.rs | 12 ++++++++++++ src/dialect/mssql.rs | 4 ++++ src/parser/mod.rs | 31 +++++++++++++++++++++++++------ tests/sqlparser_mssql.rs | 23 +++++++++++++++++++++++ 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs index 9b2ede40d2..611ba7310c 100644 --- a/src/dialect/mod.rs +++ b/src/dialect/mod.rs @@ -1767,6 +1767,18 @@ pub trait Dialect: Debug + Any { false } + /// Returns true if the dialect supports a leading `WITH XMLNAMESPACES (...)` + /// clause in queries. + /// + /// Example: + /// ```sql + /// WITH XMLNAMESPACES ('urn:example' AS ns) + /// SELECT 1 + /// ``` + fn supports_with_xmlnamespaces_clause(&self) -> bool { + false + } + /// Returns true if the dialect supports `USING ` in `CREATE TABLE`. /// /// Example: diff --git a/src/dialect/mssql.rs b/src/dialect/mssql.rs index 980b63d289..e07a7fc807 100644 --- a/src/dialect/mssql.rs +++ b/src/dialect/mssql.rs @@ -248,6 +248,10 @@ impl Dialect for MsSqlDialect { _ => None, } } + + fn supports_with_xmlnamespaces_clause(&self) -> bool { + true + } } impl MsSqlDialect { diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 3c61851930..604bf8ed54 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -14108,12 +14108,31 @@ impl<'a> Parser<'a> { pub fn parse_query(&mut self) -> Result, ParserError> { let _guard = self.recursion_counter.try_decrease()?; let with = if self.parse_keyword(Keyword::WITH) { - let with_token = self.get_current_token(); - Some(With { - with_token: with_token.clone().into(), - recursive: self.parse_keyword(Keyword::RECURSIVE), - cte_tables: self.parse_comma_separated(Parser::parse_cte)?, - }) + let with_token = self.get_current_token().clone(); + if self.dialect.supports_with_xmlnamespaces_clause() + && self.parse_keyword(Keyword::XMLNAMESPACES) + { + self.expect_token(&Token::LParen)?; + let _namespaces = + self.parse_comma_separated(Parser::parse_xml_namespace_definition)?; + self.expect_token(&Token::RParen)?; + + if self.consume_token(&Token::Comma) { + Some(With { + with_token: with_token.clone().into(), + recursive: self.parse_keyword(Keyword::RECURSIVE), + cte_tables: self.parse_comma_separated(Parser::parse_cte)?, + }) + } else { + None + } + } else { + Some(With { + with_token: with_token.clone().into(), + recursive: self.parse_keyword(Keyword::RECURSIVE), + cte_tables: self.parse_comma_separated(Parser::parse_cte)?, + }) + } } else { None }; diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs index 6e866746d7..f7ec5254af 100644 --- a/tests/sqlparser_mssql.rs +++ b/tests/sqlparser_mssql.rs @@ -2923,3 +2923,26 @@ fn parse_mssql_money_constants() { expr_from_projection(only(&select.projection)), ); } + +#[test] +fn parse_xmlnamespaces() { + let sql = r#"WITH XMLNAMESPACES ('urn:test' AS ns) +SELECT 1 AS [ns:Value] +FOR XML PATH('ns:Root');"#; + + tsql().parse_sql_statements(sql).unwrap(); + ms().parse_sql_statements(sql).unwrap(); + +} + +#[test] +fn parse_xmlnamespaces_with_cte() { + let sql = r#" +WITH XMLNAMESPACES ('urn:example' AS ns), t AS ( + SELECT 1 AS id +) +SELECT id FROM t +"#; + + tsql().parse_sql_statements(sql).unwrap(); +} \ No newline at end of file From 5d63c97de01c80f2c1f18e088f02de6ae29bd3cc Mon Sep 17 00:00:00 2001 From: Kfir Ben Shimon Date: Mon, 1 Jun 2026 16:59:26 +0300 Subject: [PATCH 2/2] Aligned tests to mssql --- tests/sqlparser_mssql.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs index f7ec5254af..2a6eb67b78 100644 --- a/tests/sqlparser_mssql.rs +++ b/tests/sqlparser_mssql.rs @@ -2930,7 +2930,6 @@ fn parse_xmlnamespaces() { SELECT 1 AS [ns:Value] FOR XML PATH('ns:Root');"#; - tsql().parse_sql_statements(sql).unwrap(); ms().parse_sql_statements(sql).unwrap(); } @@ -2944,5 +2943,5 @@ WITH XMLNAMESPACES ('urn:example' AS ns), t AS ( SELECT id FROM t "#; - tsql().parse_sql_statements(sql).unwrap(); + ms().parse_sql_statements(sql).unwrap(); } \ No newline at end of file