Skip to content

Commit de590fa

Browse files
SET statements: scope modifier for multiple assignments
1 parent f487cbe commit de590fa

4 files changed

Lines changed: 90 additions & 60 deletions

File tree

src/ast/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5727,13 +5727,14 @@ impl fmt::Display for SequenceOptions {
57275727
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
57285728
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
57295729
pub struct SetAssignment {
5730+
pub scope: ContextModifier,
57305731
pub name: ObjectName,
57315732
pub value: Expr,
57325733
}
57335734

57345735
impl fmt::Display for SetAssignment {
57355736
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5736-
write!(f, "{} = {}", self.name, self.value)
5737+
write!(f, "{}{} = {}", self.scope, self.name, self.value)
57375738
}
57385739
}
57395740

src/dialect/generic.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,8 @@ impl Dialect for GenericDialect {
159159
fn supports_set_names(&self) -> bool {
160160
true
161161
}
162+
163+
fn supports_comma_separated_set_assignments(&self) -> bool {
164+
true
165+
}
162166
}

src/parser/mod.rs

Lines changed: 49 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -11145,17 +11145,16 @@ impl<'a> Parser<'a> {
1114511145
}
1114611146

1114711147
/// Parse a `SET ROLE` statement. Expects SET to be consumed already.
11148-
fn parse_set_role(&mut self, modifier: Option<Keyword>) -> Result<Statement, ParserError> {
11148+
fn parse_set_role(&mut self, modifier: ContextModifier) -> Result<Statement, ParserError> {
1114911149
self.expect_keyword_is(Keyword::ROLE)?;
11150-
let context_modifier = Self::keyword_to_modifier(modifier);
1115111150

1115211151
let role_name = if self.parse_keyword(Keyword::NONE) {
1115311152
None
1115411153
} else {
1115511154
Some(self.parse_identifier()?)
1115611155
};
1115711156
Ok(Statement::Set(Set::SetRole {
11158-
context_modifier,
11157+
context_modifier: modifier,
1115911158
role_name,
1116011159
}))
1116111160
}
@@ -11191,46 +11190,52 @@ impl<'a> Parser<'a> {
1119111190
}
1119211191
}
1119311192

11194-
fn parse_set_assignment(
11195-
&mut self,
11196-
) -> Result<(OneOrManyWithParens<ObjectName>, Expr), ParserError> {
11197-
let variables = if self.dialect.supports_parenthesized_set_variables()
11193+
fn parse_context_modifier(&mut self) -> ContextModifier {
11194+
let modifier =
11195+
self.parse_one_of_keywords(&[Keyword::SESSION, Keyword::LOCAL, Keyword::GLOBAL]);
11196+
11197+
Self::keyword_to_modifier(modifier)
11198+
}
11199+
11200+
/// Parse a single SET statement assignment `var = expr`.
11201+
fn parse_set_assignment(&mut self) -> Result<SetAssignment, ParserError> {
11202+
let scope = self.parse_context_modifier();
11203+
11204+
let name = if self.dialect.supports_parenthesized_set_variables()
1119811205
&& self.consume_token(&Token::LParen)
1119911206
{
11200-
let vars = OneOrManyWithParens::Many(
11201-
self.parse_comma_separated(|parser: &mut Parser<'a>| parser.parse_identifier())?
11202-
.into_iter()
11203-
.map(|ident| ObjectName::from(vec![ident]))
11204-
.collect(),
11205-
);
11206-
self.expect_token(&Token::RParen)?;
11207-
vars
11207+
// Parenthesized assignments are handled in the `parse_set` function after
11208+
// trying to parse list of assignments using this function.
11209+
// If a dialect supports both, and we find a LParen, we early exit from this function.
11210+
self.expected("Unparenthesized assignment", self.peek_token())?
1120811211
} else {
11209-
OneOrManyWithParens::One(self.parse_object_name(false)?)
11212+
self.parse_object_name(false)?
1121011213
};
1121111214

1121211215
if !(self.consume_token(&Token::Eq) || self.parse_keyword(Keyword::TO)) {
1121311216
return self.expected("assignment operator", self.peek_token());
1121411217
}
1121511218

11216-
let values = self.parse_expr()?;
11219+
let value = self.parse_expr()?;
1121711220

11218-
Ok((variables, values))
11221+
Ok(SetAssignment { scope, name, value })
1121911222
}
1122011223

1122111224
fn parse_set(&mut self) -> Result<Statement, ParserError> {
11222-
let modifier = self.parse_one_of_keywords(&[
11223-
Keyword::SESSION,
11224-
Keyword::LOCAL,
11225-
Keyword::HIVEVAR,
11226-
Keyword::GLOBAL,
11227-
]);
11228-
11229-
if let Some(Keyword::HIVEVAR) = modifier {
11225+
let hivevar = self.parse_keyword(Keyword::HIVEVAR);
11226+
11227+
// Modifier is either HIVEVAR: or a ContextModifier (LOCAL, SESSION, etc), not both
11228+
let scope = if !hivevar {
11229+
self.parse_context_modifier()
11230+
} else {
11231+
ContextModifier::None
11232+
};
11233+
11234+
if hivevar {
1123011235
self.expect_token(&Token::Colon)?;
1123111236
}
1123211237

11233-
if let Some(set_role_stmt) = self.maybe_parse(|parser| parser.parse_set_role(modifier))? {
11238+
if let Some(set_role_stmt) = self.maybe_parse(|parser| parser.parse_set_role(scope))? {
1123411239
return Ok(set_role_stmt);
1123511240
}
1123611241

@@ -11240,8 +11245,8 @@ impl<'a> Parser<'a> {
1124011245
{
1124111246
if self.consume_token(&Token::Eq) || self.parse_keyword(Keyword::TO) {
1124211247
return Ok(Set::SingleAssignment {
11243-
scope: Self::keyword_to_modifier(modifier),
11244-
hivevar: modifier == Some(Keyword::HIVEVAR),
11248+
scope,
11249+
hivevar,
1124511250
variable: ObjectName::from(vec!["TIMEZONE".into()]),
1124611251
values: self.parse_set_values(false)?,
1124711252
}
@@ -11251,7 +11256,7 @@ impl<'a> Parser<'a> {
1125111256
// the assignment operator. It's originally PostgreSQL specific,
1125211257
// but we allow it for all the dialects
1125311258
return Ok(Set::SetTimeZone {
11254-
local: modifier == Some(Keyword::LOCAL),
11259+
local: scope == ContextModifier::Local,
1125511260
value: self.parse_expr()?,
1125611261
}
1125711262
.into());
@@ -11299,41 +11304,26 @@ impl<'a> Parser<'a> {
1129911304
}
1130011305

1130111306
if self.dialect.supports_comma_separated_set_assignments() {
11307+
if scope != ContextModifier::None {
11308+
self.prev_token();
11309+
}
11310+
1130211311
if let Some(assignments) = self
1130311312
.maybe_parse(|parser| parser.parse_comma_separated(Parser::parse_set_assignment))?
1130411313
{
1130511314
return if assignments.len() > 1 {
11306-
let assignments = assignments
11307-
.into_iter()
11308-
.map(|(var, val)| match var {
11309-
OneOrManyWithParens::One(v) => Ok(SetAssignment {
11310-
name: v,
11311-
value: val,
11312-
}),
11313-
OneOrManyWithParens::Many(_) => {
11314-
self.expected("List of single identifiers", self.peek_token())
11315-
}
11316-
})
11317-
.collect::<Result<_, _>>()?;
11318-
1131911315
Ok(Set::MultipleAssignments { assignments }.into())
1132011316
} else {
11321-
let (vars, values): (Vec<_>, Vec<_>) = assignments.into_iter().unzip();
11322-
11323-
let variable = match vars.into_iter().next() {
11324-
Some(OneOrManyWithParens::One(v)) => Ok(v),
11325-
Some(OneOrManyWithParens::Many(_)) => self.expected(
11326-
"Single assignment or list of assignments",
11327-
self.peek_token(),
11328-
),
11329-
None => self.expected("At least one identifier", self.peek_token()),
11330-
}?;
11317+
let SetAssignment { scope, name, value } =
11318+
assignments.into_iter().next().ok_or_else(|| {
11319+
ParserError::ParserError("Expected at least one assignment".to_string())
11320+
})?;
1133111321

1133211322
Ok(Set::SingleAssignment {
11333-
scope: Self::keyword_to_modifier(modifier),
11334-
hivevar: modifier == Some(Keyword::HIVEVAR),
11335-
variable,
11336-
values,
11323+
scope,
11324+
hivevar,
11325+
variable: name,
11326+
values: vec![value],
1133711327
}
1133811328
.into())
1133911329
};
@@ -11358,8 +11348,8 @@ impl<'a> Parser<'a> {
1135811348
if self.consume_token(&Token::Eq) || self.parse_keyword(Keyword::TO) {
1135911349
let stmt = match variables {
1136011350
OneOrManyWithParens::One(var) => Set::SingleAssignment {
11361-
scope: Self::keyword_to_modifier(modifier),
11362-
hivevar: modifier == Some(Keyword::HIVEVAR),
11351+
scope,
11352+
hivevar,
1136311353
variable: var,
1136411354
values: self.parse_set_values(false)?,
1136511355
},

tests/sqlparser_common.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14856,10 +14856,12 @@ fn parse_multiple_set_statements() -> Result<(), ParserError> {
1485614856
assignments,
1485714857
vec![
1485814858
SetAssignment {
14859+
scope: ContextModifier::None,
1485914860
name: ObjectName::from(vec!["@a".into()]),
1486014861
value: Expr::value(number("1"))
1486114862
},
1486214863
SetAssignment {
14864+
scope: ContextModifier::None,
1486314865
name: ObjectName::from(vec!["b".into()]),
1486414866
value: Expr::value(number("2"))
1486514867
}
@@ -14869,6 +14871,39 @@ fn parse_multiple_set_statements() -> Result<(), ParserError> {
1486914871
_ => panic!("Expected SetVariable with 2 variables and 2 values"),
1487014872
};
1487114873

14874+
let stmt = dialects.verified_stmt("SET GLOBAL @a = 1, SESSION b = 2, LOCAL c = 3, d = 4");
14875+
14876+
match stmt {
14877+
Statement::Set(Set::MultipleAssignments { assignments }) => {
14878+
assert_eq!(
14879+
assignments,
14880+
vec![
14881+
SetAssignment {
14882+
scope: ContextModifier::Global,
14883+
name: ObjectName::from(vec!["@a".into()]),
14884+
value: Expr::value(number("1"))
14885+
},
14886+
SetAssignment {
14887+
scope: ContextModifier::Session,
14888+
name: ObjectName::from(vec!["b".into()]),
14889+
value: Expr::value(number("2"))
14890+
},
14891+
SetAssignment {
14892+
scope: ContextModifier::Local,
14893+
name: ObjectName::from(vec!["c".into()]),
14894+
value: Expr::value(number("3"))
14895+
},
14896+
SetAssignment {
14897+
scope: ContextModifier::None,
14898+
name: ObjectName::from(vec!["d".into()]),
14899+
value: Expr::value(number("4"))
14900+
}
14901+
]
14902+
);
14903+
}
14904+
_ => panic!("Expected SetVariable with 2 variables and 2 values"),
14905+
};
14906+
1487214907
Ok(())
1487314908
}
1487414909

0 commit comments

Comments
 (0)