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]