mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-07-07 17:04:59 +00:00
Add GLOBAL context/modifier to SET statements (#1767)
This commit is contained in:
parent
e3e88290cd
commit
f487cbe004
7 changed files with 72 additions and 39 deletions
|
@ -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 ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)?,
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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"))],
|
||||
|
|
|
@ -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"),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue