Skip to content

Commit d2351a9

Browse files
committed
More structured representation of MS-SQL session params
1 parent 0ccf760 commit d2351a9

File tree

3 files changed

+174
-62
lines changed

3 files changed

+174
-62
lines changed

src/ast/mod.rs

+122-21
Original file line numberDiff line numberDiff line change
@@ -3440,12 +3440,7 @@ pub enum Statement {
34403440
/// MS-SQL session
34413441
///
34423442
/// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3443-
SetSessionParam {
3444-
names: Vec<String>,
3445-
identity_insert_obj: Option<ObjectName>,
3446-
offsets_keywords: Option<Vec<String>>,
3447-
value: String,
3448-
},
3443+
SetSessionParam(SetSessionParamKind),
34493444
}
34503445

34513446
impl fmt::Display for Statement {
@@ -5033,21 +5028,7 @@ impl fmt::Display for Statement {
50335028
}
50345029
Statement::List(command) => write!(f, "LIST {command}"),
50355030
Statement::Remove(command) => write!(f, "REMOVE {command}"),
5036-
Statement::SetSessionParam {
5037-
names,
5038-
identity_insert_obj,
5039-
offsets_keywords,
5040-
value,
5041-
} => {
5042-
write!(f, "SET")?;
5043-
write!(f, " {}", display_comma_separated(names))?;
5044-
if let Some(obj) = identity_insert_obj {
5045-
write!(f, " {obj}")?;
5046-
} else if let Some(keywords) = offsets_keywords {
5047-
write!(f, " {}", display_comma_separated(keywords))?;
5048-
}
5049-
write!(f, " {value}")
5050-
}
5031+
Statement::SetSessionParam(kind) => write!(f, "SET {kind}"),
50515032
}
50525033
}
50535034
}
@@ -7963,6 +7944,126 @@ impl fmt::Display for TableObject {
79637944
}
79647945
}
79657946

7947+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7948+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7949+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7950+
pub enum SetSessionParamKind {
7951+
Generic(SetSessionParamGeneric),
7952+
IdentityInsert(SetSessionParamIdentityInsert),
7953+
Offsets(SetSessionParamOffsets),
7954+
Statistics(SetSessionParamStatistics),
7955+
}
7956+
7957+
impl fmt::Display for SetSessionParamKind {
7958+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7959+
match self {
7960+
SetSessionParamKind::Generic(x) => write!(f, "{x}"),
7961+
SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
7962+
SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
7963+
SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
7964+
}
7965+
}
7966+
}
7967+
7968+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7969+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7970+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7971+
pub struct SetSessionParamGeneric {
7972+
pub names: Vec<String>,
7973+
pub value: String,
7974+
}
7975+
7976+
impl fmt::Display for SetSessionParamGeneric {
7977+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7978+
write!(f, "{} {}", display_comma_separated(&self.names), self.value)
7979+
}
7980+
}
7981+
7982+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7983+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7984+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7985+
pub struct SetSessionParamIdentityInsert {
7986+
pub obj: ObjectName,
7987+
pub value: SessionParamValue,
7988+
}
7989+
7990+
impl fmt::Display for SetSessionParamIdentityInsert {
7991+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7992+
write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
7993+
}
7994+
}
7995+
7996+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7997+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7998+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7999+
pub struct SetSessionParamOffsets {
8000+
pub keywords: Vec<String>,
8001+
pub value: SessionParamValue,
8002+
}
8003+
8004+
impl fmt::Display for SetSessionParamOffsets {
8005+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8006+
write!(
8007+
f,
8008+
"OFFSETS {} {}",
8009+
display_comma_separated(&self.keywords),
8010+
self.value
8011+
)
8012+
}
8013+
}
8014+
8015+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8016+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8017+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8018+
pub struct SetSessionParamStatistics {
8019+
pub topic: SessionParamStatsTopic,
8020+
pub value: SessionParamValue,
8021+
}
8022+
8023+
impl fmt::Display for SetSessionParamStatistics {
8024+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8025+
write!(f, "STATISTICS {} {}", self.topic, self.value)
8026+
}
8027+
}
8028+
8029+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8030+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8031+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8032+
pub enum SessionParamStatsTopic {
8033+
IO,
8034+
Profile,
8035+
Time,
8036+
Xml,
8037+
}
8038+
8039+
impl fmt::Display for SessionParamStatsTopic {
8040+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8041+
match self {
8042+
SessionParamStatsTopic::IO => write!(f, "IO"),
8043+
SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
8044+
SessionParamStatsTopic::Time => write!(f, "TIME"),
8045+
SessionParamStatsTopic::Xml => write!(f, "XML"),
8046+
}
8047+
}
8048+
}
8049+
8050+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8051+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8052+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8053+
pub enum SessionParamValue {
8054+
On,
8055+
Off,
8056+
}
8057+
8058+
impl fmt::Display for SessionParamValue {
8059+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8060+
match self {
8061+
SessionParamValue::On => write!(f, "ON"),
8062+
SessionParamValue::Off => write!(f, "OFF"),
8063+
}
8064+
}
8065+
}
8066+
79668067
#[cfg(test)]
79678068
mod tests {
79688069
use super::*;

src/keywords.rs

+3
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ define_keywords!(
388388
HOURS,
389389
ID,
390390
IDENTITY,
391+
IDENTITY_INSERT,
391392
IF,
392393
IGNORE,
393394
ILIKE,
@@ -558,7 +559,9 @@ define_keywords!(
558559
OCTETS,
559560
OCTET_LENGTH,
560561
OF,
562+
OFF,
561563
OFFSET,
564+
OFFSETS,
562565
OLD,
563566
OMIT,
564567
ON,

src/parser/mod.rs

+49-41
Original file line numberDiff line numberDiff line change
@@ -10437,56 +10437,64 @@ impl<'a> Parser<'a> {
1043710437
}
1043810438

1043910439
pub fn parse_set_session_params(&mut self) -> Result<Statement, ParserError> {
10440-
let names = self.parse_comma_separated(Parser::parse_set_session_param_name)?;
10441-
10442-
let last_name = if let Some(last_name) = names.last() {
10443-
last_name.to_uppercase()
10444-
} else {
10445-
return self.expected("Session param name", self.peek_token());
10446-
};
10447-
10448-
let identity_insert_obj = if last_name == "IDENTITY_INSERT" {
10449-
Some(self.parse_object_name(false)?)
10450-
} else {
10451-
None
10452-
};
10453-
10454-
let offsets_keywords = if last_name == "OFFSETS" {
10455-
Some(self.parse_comma_separated(|parser| {
10440+
if self.parse_keyword(Keyword::STATISTICS) {
10441+
let topic = match self.parse_one_of_keywords(&[
10442+
Keyword::IO,
10443+
Keyword::PROFILE,
10444+
Keyword::TIME,
10445+
Keyword::XML,
10446+
]) {
10447+
Some(Keyword::IO) => SessionParamStatsTopic::IO,
10448+
Some(Keyword::PROFILE) => SessionParamStatsTopic::Profile,
10449+
Some(Keyword::TIME) => SessionParamStatsTopic::Time,
10450+
Some(Keyword::XML) => SessionParamStatsTopic::Xml,
10451+
_ => return self.expected("IO, PROFILE, TIME or XML", self.peek_token()),
10452+
};
10453+
let value = self.parse_session_param_value()?;
10454+
Ok(Statement::SetSessionParam(SetSessionParamKind::Statistics(
10455+
SetSessionParamStatistics { topic, value },
10456+
)))
10457+
} else if self.parse_keyword(Keyword::IDENTITY_INSERT) {
10458+
let obj = self.parse_object_name(false)?;
10459+
let value = self.parse_session_param_value()?;
10460+
Ok(Statement::SetSessionParam(
10461+
SetSessionParamKind::IdentityInsert(SetSessionParamIdentityInsert { obj, value }),
10462+
))
10463+
} else if self.parse_keyword(Keyword::OFFSETS) {
10464+
let keywords = self.parse_comma_separated(|parser| {
1045610465
let next_token = parser.next_token();
1045710466
match &next_token.token {
1045810467
Token::Word(w) => Ok(w.to_string()),
1045910468
_ => parser.expected("SQL keyword", next_token),
1046010469
}
10461-
})?)
10470+
})?;
10471+
let value = self.parse_session_param_value()?;
10472+
Ok(Statement::SetSessionParam(SetSessionParamKind::Offsets(
10473+
SetSessionParamOffsets { keywords, value },
10474+
)))
1046210475
} else {
10463-
None
10464-
};
10465-
10466-
let value = self.parse_expr()?.to_string();
10467-
Ok(Statement::SetSessionParam {
10468-
names,
10469-
identity_insert_obj,
10470-
offsets_keywords,
10471-
value,
10472-
})
10476+
let names = self.parse_comma_separated(|parser| {
10477+
let next_token = parser.next_token();
10478+
match next_token.token {
10479+
Token::Word(w) => Ok(w.to_string()),
10480+
_ => parser.expected("Session param name", next_token),
10481+
}
10482+
})?;
10483+
let value = self.parse_expr()?.to_string();
10484+
Ok(Statement::SetSessionParam(SetSessionParamKind::Generic(
10485+
SetSessionParamGeneric { names, value },
10486+
)))
10487+
}
1047310488
}
1047410489

10475-
pub fn parse_set_session_param_name(&mut self) -> Result<String, ParserError> {
10476-
if self.parse_keywords(&[Keyword::STATISTICS, Keyword::IO]) {
10477-
return Ok("STATISTICS IO".to_string());
10478-
} else if self.parse_keywords(&[Keyword::STATISTICS, Keyword::XML]) {
10479-
return Ok("STATISTICS XML".to_string());
10480-
} else if self.parse_keywords(&[Keyword::STATISTICS, Keyword::PROFILE]) {
10481-
return Ok("STATISTICS PROFILE".to_string());
10482-
} else if self.parse_keywords(&[Keyword::STATISTICS, Keyword::TIME]) {
10483-
return Ok("STATISTICS TIME".to_string());
10484-
}
10485-
let next_token = self.next_token();
10486-
if let Token::Word(w) = next_token.token {
10487-
return Ok(w.to_string());
10490+
fn parse_session_param_value(&mut self) -> Result<SessionParamValue, ParserError> {
10491+
if self.parse_keyword(Keyword::ON) {
10492+
Ok(SessionParamValue::On)
10493+
} else if self.parse_keyword(Keyword::OFF) {
10494+
Ok(SessionParamValue::Off)
10495+
} else {
10496+
self.expected("ON or OFF", self.peek_token())
1048810497
}
10489-
self.expected("Session param name", next_token)
1049010498
}
1049110499

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

0 commit comments

Comments
 (0)