Skip to content

Commit 36b1a41

Browse files
committed
More structured representation of MS-SQL session params
1 parent 11bef3e commit 36b1a41

File tree

3 files changed

+174
-62
lines changed

3 files changed

+174
-62
lines changed

src/ast/mod.rs

Lines changed: 122 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3438,12 +3438,7 @@ pub enum Statement {
34383438
/// MS-SQL session
34393439
///
34403440
/// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3441-
SetSessionParam {
3442-
names: Vec<String>,
3443-
identity_insert_obj: Option<ObjectName>,
3444-
offsets_keywords: Option<Vec<String>>,
3445-
value: String,
3446-
},
3441+
SetSessionParam(SetSessionParamKind),
34473442
}
34483443

34493444
impl fmt::Display for Statement {
@@ -5021,21 +5016,7 @@ impl fmt::Display for Statement {
50215016
}
50225017
Statement::List(command) => write!(f, "LIST {command}"),
50235018
Statement::Remove(command) => write!(f, "REMOVE {command}"),
5024-
Statement::SetSessionParam {
5025-
names,
5026-
identity_insert_obj,
5027-
offsets_keywords,
5028-
value,
5029-
} => {
5030-
write!(f, "SET")?;
5031-
write!(f, " {}", display_comma_separated(names))?;
5032-
if let Some(obj) = identity_insert_obj {
5033-
write!(f, " {obj}")?;
5034-
} else if let Some(keywords) = offsets_keywords {
5035-
write!(f, " {}", display_comma_separated(keywords))?;
5036-
}
5037-
write!(f, " {value}")
5038-
}
5019+
Statement::SetSessionParam(kind) => write!(f, "SET {kind}"),
50395020
}
50405021
}
50415022
}
@@ -7821,6 +7802,126 @@ impl fmt::Display for RenameTable {
78217802
}
78227803
}
78237804

7805+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7806+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7807+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7808+
pub enum SetSessionParamKind {
7809+
Generic(SetSessionParamGeneric),
7810+
IdentityInsert(SetSessionParamIdentityInsert),
7811+
Offsets(SetSessionParamOffsets),
7812+
Statistics(SetSessionParamStatistics),
7813+
}
7814+
7815+
impl fmt::Display for SetSessionParamKind {
7816+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7817+
match self {
7818+
SetSessionParamKind::Generic(x) => write!(f, "{x}"),
7819+
SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
7820+
SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
7821+
SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
7822+
}
7823+
}
7824+
}
7825+
7826+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7827+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7828+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7829+
pub struct SetSessionParamGeneric {
7830+
pub names: Vec<String>,
7831+
pub value: String,
7832+
}
7833+
7834+
impl fmt::Display for SetSessionParamGeneric {
7835+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7836+
write!(f, "{} {}", display_comma_separated(&self.names), self.value)
7837+
}
7838+
}
7839+
7840+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7841+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7842+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7843+
pub struct SetSessionParamIdentityInsert {
7844+
pub obj: ObjectName,
7845+
pub value: SessionParamValue,
7846+
}
7847+
7848+
impl fmt::Display for SetSessionParamIdentityInsert {
7849+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7850+
write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
7851+
}
7852+
}
7853+
7854+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7855+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7856+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7857+
pub struct SetSessionParamOffsets {
7858+
pub keywords: Vec<String>,
7859+
pub value: SessionParamValue,
7860+
}
7861+
7862+
impl fmt::Display for SetSessionParamOffsets {
7863+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7864+
write!(
7865+
f,
7866+
"OFFSETS {} {}",
7867+
display_comma_separated(&self.keywords),
7868+
self.value
7869+
)
7870+
}
7871+
}
7872+
7873+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7874+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7875+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7876+
pub struct SetSessionParamStatistics {
7877+
pub topic: SessionParamStatsTopic,
7878+
pub value: SessionParamValue,
7879+
}
7880+
7881+
impl fmt::Display for SetSessionParamStatistics {
7882+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7883+
write!(f, "STATISTICS {} {}", self.topic, self.value)
7884+
}
7885+
}
7886+
7887+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7888+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7889+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7890+
pub enum SessionParamStatsTopic {
7891+
IO,
7892+
Profile,
7893+
Time,
7894+
Xml,
7895+
}
7896+
7897+
impl fmt::Display for SessionParamStatsTopic {
7898+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7899+
match self {
7900+
SessionParamStatsTopic::IO => write!(f, "IO"),
7901+
SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
7902+
SessionParamStatsTopic::Time => write!(f, "TIME"),
7903+
SessionParamStatsTopic::Xml => write!(f, "XML"),
7904+
}
7905+
}
7906+
}
7907+
7908+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7909+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7910+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7911+
pub enum SessionParamValue {
7912+
On,
7913+
Off,
7914+
}
7915+
7916+
impl fmt::Display for SessionParamValue {
7917+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7918+
match self {
7919+
SessionParamValue::On => write!(f, "ON"),
7920+
SessionParamValue::Off => write!(f, "OFF"),
7921+
}
7922+
}
7923+
}
7924+
78247925
#[cfg(test)]
78257926
mod tests {
78267927
use super::*;

src/keywords.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ define_keywords!(
386386
HOURS,
387387
ID,
388388
IDENTITY,
389+
IDENTITY_INSERT,
389390
IF,
390391
IGNORE,
391392
ILIKE,
@@ -554,7 +555,9 @@ define_keywords!(
554555
OCTETS,
555556
OCTET_LENGTH,
556557
OF,
558+
OFF,
557559
OFFSET,
560+
OFFSETS,
558561
OLD,
559562
OMIT,
560563
ON,

src/parser/mod.rs

Lines changed: 49 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10330,56 +10330,64 @@ impl<'a> Parser<'a> {
1033010330
}
1033110331

1033210332
pub fn parse_set_session_params(&mut self) -> Result<Statement, ParserError> {
10333-
let names = self.parse_comma_separated(Parser::parse_set_session_param_name)?;
10334-
10335-
let last_name = if let Some(last_name) = names.last() {
10336-
last_name.to_uppercase()
10337-
} else {
10338-
return self.expected("Session param name", self.peek_token());
10339-
};
10340-
10341-
let identity_insert_obj = if last_name == "IDENTITY_INSERT" {
10342-
Some(self.parse_object_name(false)?)
10343-
} else {
10344-
None
10345-
};
10346-
10347-
let offsets_keywords = if last_name == "OFFSETS" {
10348-
Some(self.parse_comma_separated(|parser| {
10333+
if self.parse_keyword(Keyword::STATISTICS) {
10334+
let topic = match self.parse_one_of_keywords(&[
10335+
Keyword::IO,
10336+
Keyword::PROFILE,
10337+
Keyword::TIME,
10338+
Keyword::XML,
10339+
]) {
10340+
Some(Keyword::IO) => SessionParamStatsTopic::IO,
10341+
Some(Keyword::PROFILE) => SessionParamStatsTopic::Profile,
10342+
Some(Keyword::TIME) => SessionParamStatsTopic::Time,
10343+
Some(Keyword::XML) => SessionParamStatsTopic::Xml,
10344+
_ => return self.expected("IO, PROFILE, TIME or XML", self.peek_token()),
10345+
};
10346+
let value = self.parse_session_param_value()?;
10347+
Ok(Statement::SetSessionParam(SetSessionParamKind::Statistics(
10348+
SetSessionParamStatistics { topic, value },
10349+
)))
10350+
} else if self.parse_keyword(Keyword::IDENTITY_INSERT) {
10351+
let obj = self.parse_object_name(false)?;
10352+
let value = self.parse_session_param_value()?;
10353+
Ok(Statement::SetSessionParam(
10354+
SetSessionParamKind::IdentityInsert(SetSessionParamIdentityInsert { obj, value }),
10355+
))
10356+
} else if self.parse_keyword(Keyword::OFFSETS) {
10357+
let keywords = self.parse_comma_separated(|parser| {
1034910358
let next_token = parser.next_token();
1035010359
match &next_token.token {
1035110360
Token::Word(w) => Ok(w.to_string()),
1035210361
_ => parser.expected("SQL keyword", next_token),
1035310362
}
10354-
})?)
10363+
})?;
10364+
let value = self.parse_session_param_value()?;
10365+
Ok(Statement::SetSessionParam(SetSessionParamKind::Offsets(
10366+
SetSessionParamOffsets { keywords, value },
10367+
)))
1035510368
} else {
10356-
None
10357-
};
10358-
10359-
let value = self.parse_expr()?.to_string();
10360-
Ok(Statement::SetSessionParam {
10361-
names,
10362-
identity_insert_obj,
10363-
offsets_keywords,
10364-
value,
10365-
})
10369+
let names = self.parse_comma_separated(|parser| {
10370+
let next_token = parser.next_token();
10371+
match next_token.token {
10372+
Token::Word(w) => Ok(w.to_string()),
10373+
_ => parser.expected("Session param name", next_token),
10374+
}
10375+
})?;
10376+
let value = self.parse_expr()?.to_string();
10377+
Ok(Statement::SetSessionParam(SetSessionParamKind::Generic(
10378+
SetSessionParamGeneric { names, value },
10379+
)))
10380+
}
1036610381
}
1036710382

10368-
pub fn parse_set_session_param_name(&mut self) -> Result<String, ParserError> {
10369-
if self.parse_keywords(&[Keyword::STATISTICS, Keyword::IO]) {
10370-
return Ok("STATISTICS IO".to_string());
10371-
} else if self.parse_keywords(&[Keyword::STATISTICS, Keyword::XML]) {
10372-
return Ok("STATISTICS XML".to_string());
10373-
} else if self.parse_keywords(&[Keyword::STATISTICS, Keyword::PROFILE]) {
10374-
return Ok("STATISTICS PROFILE".to_string());
10375-
} else if self.parse_keywords(&[Keyword::STATISTICS, Keyword::TIME]) {
10376-
return Ok("STATISTICS TIME".to_string());
10377-
}
10378-
let next_token = self.next_token();
10379-
if let Token::Word(w) = next_token.token {
10380-
return Ok(w.to_string());
10383+
fn parse_session_param_value(&mut self) -> Result<SessionParamValue, ParserError> {
10384+
if self.parse_keyword(Keyword::ON) {
10385+
Ok(SessionParamValue::On)
10386+
} else if self.parse_keyword(Keyword::OFF) {
10387+
Ok(SessionParamValue::Off)
10388+
} else {
10389+
self.expected("ON or OFF", self.peek_token())
1038110390
}
10382-
self.expected("Session param name", next_token)
1038310391
}
1038410392

1038510393
pub fn parse_show(&mut self) -> Result<Statement, ParserError> {

0 commit comments

Comments
 (0)