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

iffyio pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new f487cbe0 Add GLOBAL context/modifier to SET statements (#1767)
f487cbe0 is described below

commit f487cbe00404454ce88a297bbe27dd98122f6fab
Author: Mohamed Abdeen <[email protected]>
AuthorDate: Thu Mar 20 07:52:56 2025 +0200

    Add GLOBAL context/modifier to SET statements (#1767)
---
 src/ast/mod.rs              | 19 ++++++++++++-------
 src/parser/mod.rs           | 29 +++++++++++++++++++----------
 tests/sqlparser_common.rs   | 32 ++++++++++++++++++++++++++------
 tests/sqlparser_hive.rs     |  9 +++++----
 tests/sqlparser_mssql.rs    |  2 +-
 tests/sqlparser_mysql.rs    |  2 +-
 tests/sqlparser_postgres.rs | 18 ++++++++----------
 7 files changed, 72 insertions(+), 39 deletions(-)

diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index 6dc4f5b2..9f895ee6 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -2629,7 +2629,7 @@ pub enum Set {
     /// SQL Standard-style
     /// SET a = 1;
     SingleAssignment {
-        local: bool,
+        scope: ContextModifier,
         hivevar: bool,
         variable: ObjectName,
         values: Vec<Expr>,
@@ -2711,7 +2711,7 @@ impl Display for Set {
                 role_name,
             } => {
                 let role_name = role_name.clone().unwrap_or_else(|| 
Ident::new("NONE"));
-                write!(f, "SET{context_modifier} ROLE {role_name}")
+                write!(f, "SET {context_modifier}ROLE {role_name}")
             }
             Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
             Self::SetTransaction {
@@ -2758,7 +2758,7 @@ impl Display for Set {
                 Ok(())
             }
             Set::SingleAssignment {
-                local,
+                scope,
                 hivevar,
                 variable,
                 values,
@@ -2766,7 +2766,7 @@ impl Display for Set {
                 write!(
                     f,
                     "SET {}{}{} = {}",
-                    if *local { "LOCAL " } else { "" },
+                    scope,
                     if *hivevar { "HIVEVAR:" } else { "" },
                     variable,
                     display_comma_separated(values)
@@ -7955,7 +7955,7 @@ impl fmt::Display for FlushLocation {
     }
 }
 
-/// Optional context modifier for statements that can be or `LOCAL`, or 
`SESSION`.
+/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, 
or `SESSION`.
 #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
@@ -7966,6 +7966,8 @@ pub enum ContextModifier {
     Local,
     /// `SESSION` identifier
     Session,
+    /// `GLOBAL` identifier
+    Global,
 }
 
 impl fmt::Display for ContextModifier {
@@ -7975,10 +7977,13 @@ impl fmt::Display for ContextModifier {
                 write!(f, "")
             }
             Self::Local => {
-                write!(f, " LOCAL")
+                write!(f, "LOCAL ")
             }
             Self::Session => {
-                write!(f, " SESSION")
+                write!(f, "SESSION ")
+            }
+            Self::Global => {
+                write!(f, "GLOBAL ")
             }
         }
     }
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index ee50cd04..dcf7a4a8 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -1819,6 +1819,15 @@ impl<'a> Parser<'a> {
         })
     }
 
+    fn keyword_to_modifier(k: Option<Keyword>) -> ContextModifier {
+        match k {
+            Some(Keyword::LOCAL) => ContextModifier::Local,
+            Some(Keyword::GLOBAL) => ContextModifier::Global,
+            Some(Keyword::SESSION) => ContextModifier::Session,
+            _ => ContextModifier::None,
+        }
+    }
+
     /// Check if the root is an identifier and all fields are identifiers.
     fn is_all_ident(root: &Expr, fields: &[AccessExpr]) -> bool {
         if !matches!(root, Expr::Identifier(_)) {
@@ -11138,11 +11147,7 @@ impl<'a> Parser<'a> {
     /// Parse a `SET ROLE` statement. Expects SET to be consumed already.
     fn parse_set_role(&mut self, modifier: Option<Keyword>) -> 
Result<Statement, ParserError> {
         self.expect_keyword_is(Keyword::ROLE)?;
-        let context_modifier = match modifier {
-            Some(Keyword::LOCAL) => ContextModifier::Local,
-            Some(Keyword::SESSION) => ContextModifier::Session,
-            _ => ContextModifier::None,
-        };
+        let context_modifier = Self::keyword_to_modifier(modifier);
 
         let role_name = if self.parse_keyword(Keyword::NONE) {
             None
@@ -11214,8 +11219,12 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_set(&mut self) -> Result<Statement, ParserError> {
-        let modifier =
-            self.parse_one_of_keywords(&[Keyword::SESSION, Keyword::LOCAL, 
Keyword::HIVEVAR]);
+        let modifier = self.parse_one_of_keywords(&[
+            Keyword::SESSION,
+            Keyword::LOCAL,
+            Keyword::HIVEVAR,
+            Keyword::GLOBAL,
+        ]);
 
         if let Some(Keyword::HIVEVAR) = modifier {
             self.expect_token(&Token::Colon)?;
@@ -11231,7 +11240,7 @@ impl<'a> Parser<'a> {
         {
             if self.consume_token(&Token::Eq) || 
self.parse_keyword(Keyword::TO) {
                 return Ok(Set::SingleAssignment {
-                    local: modifier == Some(Keyword::LOCAL),
+                    scope: Self::keyword_to_modifier(modifier),
                     hivevar: modifier == Some(Keyword::HIVEVAR),
                     variable: ObjectName::from(vec!["TIMEZONE".into()]),
                     values: self.parse_set_values(false)?,
@@ -11321,7 +11330,7 @@ impl<'a> Parser<'a> {
                     }?;
 
                     Ok(Set::SingleAssignment {
-                        local: modifier == Some(Keyword::LOCAL),
+                        scope: Self::keyword_to_modifier(modifier),
                         hivevar: modifier == Some(Keyword::HIVEVAR),
                         variable,
                         values,
@@ -11349,7 +11358,7 @@ impl<'a> Parser<'a> {
         if self.consume_token(&Token::Eq) || self.parse_keyword(Keyword::TO) {
             let stmt = match variables {
                 OneOrManyWithParens::One(var) => Set::SingleAssignment {
-                    local: modifier == Some(Keyword::LOCAL),
+                    scope: Self::keyword_to_modifier(modifier),
                     hivevar: modifier == Some(Keyword::HIVEVAR),
                     variable: var,
                     values: self.parse_set_values(false)?,
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index c8df7cab..4ba8df7f 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -8627,12 +8627,12 @@ fn parse_set_transaction() {
 fn parse_set_variable() {
     match verified_stmt("SET SOMETHING = '1'") {
         Statement::Set(Set::SingleAssignment {
-            local,
+            scope,
             hivevar,
             variable,
             values,
         }) => {
-            assert!(!local);
+            assert_eq!(scope, ContextModifier::None);
             assert!(!hivevar);
             assert_eq!(variable, ObjectName::from(vec!["SOMETHING".into()]));
             assert_eq!(
@@ -8645,6 +8645,26 @@ fn parse_set_variable() {
         _ => unreachable!(),
     }
 
+    match verified_stmt("SET GLOBAL VARIABLE = 'Value'") {
+        Statement::Set(Set::SingleAssignment {
+            scope,
+            hivevar,
+            variable,
+            values,
+        }) => {
+            assert_eq!(scope, ContextModifier::Global);
+            assert!(!hivevar);
+            assert_eq!(variable, ObjectName::from(vec!["VARIABLE".into()]));
+            assert_eq!(
+                values,
+                vec![Expr::Value(
+                    
(Value::SingleQuotedString("Value".into())).with_empty_span()
+                )]
+            );
+        }
+        _ => unreachable!(),
+    }
+
     let multi_variable_dialects = all_dialects_where(|d| 
d.supports_parenthesized_set_variables());
     let sql = r#"SET (a, b, c) = (1, 2, 3)"#;
     match multi_variable_dialects.verified_stmt(sql) {
@@ -8719,12 +8739,12 @@ fn parse_set_variable() {
 fn parse_set_role_as_variable() {
     match verified_stmt("SET role = 'foobar'") {
         Statement::Set(Set::SingleAssignment {
-            local,
+            scope,
             hivevar,
             variable,
             values,
         }) => {
-            assert!(!local);
+            assert_eq!(scope, ContextModifier::None);
             assert!(!hivevar);
             assert_eq!(variable, ObjectName::from(vec!["role".into()]));
             assert_eq!(
@@ -8766,12 +8786,12 @@ fn parse_double_colon_cast_at_timezone() {
 fn parse_set_time_zone() {
     match verified_stmt("SET TIMEZONE = 'UTC'") {
         Statement::Set(Set::SingleAssignment {
-            local,
+            scope,
             hivevar,
             variable,
             values,
         }) => {
-            assert!(!local);
+            assert_eq!(scope, ContextModifier::None);
             assert!(!hivevar);
             assert_eq!(variable, ObjectName::from(vec!["TIMEZONE".into()]));
             assert_eq!(
diff --git a/tests/sqlparser_hive.rs b/tests/sqlparser_hive.rs
index 56fe22a0..a9549cb6 100644
--- a/tests/sqlparser_hive.rs
+++ b/tests/sqlparser_hive.rs
@@ -21,9 +21,10 @@
 //! is also tested (on the inputs it can handle).
 
 use sqlparser::ast::{
-    ClusteredBy, CommentDef, CreateFunction, CreateFunctionBody, 
CreateFunctionUsing, CreateTable,
-    Expr, Function, FunctionArgumentList, FunctionArguments, Ident, 
ObjectName, OrderByExpr,
-    OrderByOptions, SelectItem, Set, Statement, TableFactor, UnaryOperator, 
Use, Value,
+    ClusteredBy, CommentDef, ContextModifier, CreateFunction, 
CreateFunctionBody,
+    CreateFunctionUsing, CreateTable, Expr, Function, FunctionArgumentList, 
FunctionArguments,
+    Ident, ObjectName, OrderByExpr, OrderByOptions, SelectItem, Set, 
Statement, TableFactor,
+    UnaryOperator, Use, Value,
 };
 use sqlparser::dialect::{GenericDialect, HiveDialect, MsSqlDialect};
 use sqlparser::parser::ParserError;
@@ -369,7 +370,7 @@ fn set_statement_with_minus() {
     assert_eq!(
         hive().verified_stmt("SET hive.tez.java.opts = -Xmx4g"),
         Statement::Set(Set::SingleAssignment {
-            local: false,
+            scope: ContextModifier::None,
             hivevar: false,
             variable: ObjectName::from(vec![
                 Ident::new("hive"),
diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs
index af71d252..d4e5fa71 100644
--- a/tests/sqlparser_mssql.rs
+++ b/tests/sqlparser_mssql.rs
@@ -1251,7 +1251,7 @@ fn parse_mssql_declare() {
                 }]
             },
             Statement::Set(Set::SingleAssignment {
-                local: false,
+                scope: ContextModifier::None,
                 hivevar: false,
                 variable: ObjectName::from(vec![Ident::new("@bar")]),
                 values: vec![Expr::Value(
diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs
index b6287d92..88435149 100644
--- a/tests/sqlparser_mysql.rs
+++ b/tests/sqlparser_mysql.rs
@@ -618,7 +618,7 @@ fn parse_set_variables() {
     assert_eq!(
         mysql_and_generic().verified_stmt("SET LOCAL autocommit = 1"),
         Statement::Set(Set::SingleAssignment {
-            local: true,
+            scope: ContextModifier::Local,
             hivevar: false,
             variable: ObjectName::from(vec!["autocommit".into()]),
             values: vec![Expr::value(number("1"))],
diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs
index e62f2359..cf66af74 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -988,8 +988,7 @@ fn parse_create_schema_if_not_exists() {
         Statement::CreateSchema {
             if_not_exists: true,
             schema_name,
-            options: _,
-            default_collate_spec: _,
+            ..
         } => assert_eq!("schema_name", schema_name.to_string()),
         _ => unreachable!(),
     }
@@ -1433,7 +1432,7 @@ fn parse_set() {
     assert_eq!(
         stmt,
         Statement::Set(Set::SingleAssignment {
-            local: false,
+            scope: ContextModifier::None,
             hivevar: false,
             variable: ObjectName::from(vec![Ident::new("a")]),
             values: vec![Expr::Identifier(Ident {
@@ -1448,7 +1447,7 @@ fn parse_set() {
     assert_eq!(
         stmt,
         Statement::Set(Set::SingleAssignment {
-            local: false,
+            scope: ContextModifier::None,
             hivevar: false,
             variable: ObjectName::from(vec![Ident::new("a")]),
             values: vec![Expr::Value(
@@ -1461,7 +1460,7 @@ fn parse_set() {
     assert_eq!(
         stmt,
         Statement::Set(Set::SingleAssignment {
-            local: false,
+            scope: ContextModifier::None,
             hivevar: false,
             variable: ObjectName::from(vec![Ident::new("a")]),
             values: vec![Expr::value(number("0"))],
@@ -1472,7 +1471,7 @@ fn parse_set() {
     assert_eq!(
         stmt,
         Statement::Set(Set::SingleAssignment {
-            local: false,
+            scope: ContextModifier::None,
             hivevar: false,
             variable: ObjectName::from(vec![Ident::new("a")]),
             values: vec![Expr::Identifier(Ident::new("DEFAULT"))],
@@ -1483,7 +1482,7 @@ fn parse_set() {
     assert_eq!(
         stmt,
         Statement::Set(Set::SingleAssignment {
-            local: true,
+            scope: ContextModifier::Local,
             hivevar: false,
             variable: ObjectName::from(vec![Ident::new("a")]),
             values: vec![Expr::Identifier("b".into())],
@@ -1494,7 +1493,7 @@ fn parse_set() {
     assert_eq!(
         stmt,
         Statement::Set(Set::SingleAssignment {
-            local: false,
+            scope: ContextModifier::None,
             hivevar: false,
             variable: ObjectName::from(vec![Ident::new("a"), Ident::new("b"), 
Ident::new("c")]),
             values: vec![Expr::Identifier(Ident {
@@ -1512,7 +1511,7 @@ fn parse_set() {
     assert_eq!(
         stmt,
         Statement::Set(Set::SingleAssignment {
-            local: false,
+            scope: ContextModifier::None,
             hivevar: false,
             variable: ObjectName::from(vec![
                 Ident::new("hive"),
@@ -1526,7 +1525,6 @@ fn parse_set() {
     );
 
     pg_and_generic().one_statement_parses_to("SET a TO b", "SET a = b");
-    pg_and_generic().one_statement_parses_to("SET SESSION a = b", "SET a = b");
 
     assert_eq!(
         pg_and_generic().parse_sql_statements("SET"),


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

Reply via email to