Skip to content

Commit 3e1743e

Browse files
committed
More structured representation of MS-SQL session params
1 parent 9b7faec commit 3e1743e

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
}
@@ -7933,6 +7914,126 @@ impl fmt::Display for RenameTable {
79337914
}
79347915
}
79357916

7917+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7918+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7919+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7920+
pub enum SetSessionParamKind {
7921+
Generic(SetSessionParamGeneric),
7922+
IdentityInsert(SetSessionParamIdentityInsert),
7923+
Offsets(SetSessionParamOffsets),
7924+
Statistics(SetSessionParamStatistics),
7925+
}
7926+
7927+
impl fmt::Display for SetSessionParamKind {
7928+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7929+
match self {
7930+
SetSessionParamKind::Generic(x) => write!(f, "{x}"),
7931+
SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
7932+
SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
7933+
SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
7934+
}
7935+
}
7936+
}
7937+
7938+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7939+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7940+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7941+
pub struct SetSessionParamGeneric {
7942+
pub names: Vec<String>,
7943+
pub value: String,
7944+
}
7945+
7946+
impl fmt::Display for SetSessionParamGeneric {
7947+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7948+
write!(f, "{} {}", display_comma_separated(&self.names), self.value)
7949+
}
7950+
}
7951+
7952+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7953+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7954+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7955+
pub struct SetSessionParamIdentityInsert {
7956+
pub obj: ObjectName,
7957+
pub value: SessionParamValue,
7958+
}
7959+
7960+
impl fmt::Display for SetSessionParamIdentityInsert {
7961+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7962+
write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
7963+
}
7964+
}
7965+
7966+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7967+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7968+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7969+
pub struct SetSessionParamOffsets {
7970+
pub keywords: Vec<String>,
7971+
pub value: SessionParamValue,
7972+
}
7973+
7974+
impl fmt::Display for SetSessionParamOffsets {
7975+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7976+
write!(
7977+
f,
7978+
"OFFSETS {} {}",
7979+
display_comma_separated(&self.keywords),
7980+
self.value
7981+
)
7982+
}
7983+
}
7984+
7985+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7986+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7987+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7988+
pub struct SetSessionParamStatistics {
7989+
pub topic: SessionParamStatsTopic,
7990+
pub value: SessionParamValue,
7991+
}
7992+
7993+
impl fmt::Display for SetSessionParamStatistics {
7994+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7995+
write!(f, "STATISTICS {} {}", self.topic, self.value)
7996+
}
7997+
}
7998+
7999+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8000+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8001+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8002+
pub enum SessionParamStatsTopic {
8003+
IO,
8004+
Profile,
8005+
Time,
8006+
Xml,
8007+
}
8008+
8009+
impl fmt::Display for SessionParamStatsTopic {
8010+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8011+
match self {
8012+
SessionParamStatsTopic::IO => write!(f, "IO"),
8013+
SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
8014+
SessionParamStatsTopic::Time => write!(f, "TIME"),
8015+
SessionParamStatsTopic::Xml => write!(f, "XML"),
8016+
}
8017+
}
8018+
}
8019+
8020+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8021+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8022+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8023+
pub enum SessionParamValue {
8024+
On,
8025+
Off,
8026+
}
8027+
8028+
impl fmt::Display for SessionParamValue {
8029+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8030+
match self {
8031+
SessionParamValue::On => write!(f, "ON"),
8032+
SessionParamValue::Off => write!(f, "OFF"),
8033+
}
8034+
}
8035+
}
8036+
79368037
#[cfg(test)]
79378038
mod tests {
79388039
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
@@ -10425,56 +10425,64 @@ impl<'a> Parser<'a> {
1042510425
}
1042610426

1042710427
pub fn parse_set_session_params(&mut self) -> Result<Statement, ParserError> {
10428-
let names = self.parse_comma_separated(Parser::parse_set_session_param_name)?;
10429-
10430-
let last_name = if let Some(last_name) = names.last() {
10431-
last_name.to_uppercase()
10432-
} else {
10433-
return self.expected("Session param name", self.peek_token());
10434-
};
10435-
10436-
let identity_insert_obj = if last_name == "IDENTITY_INSERT" {
10437-
Some(self.parse_object_name(false)?)
10438-
} else {
10439-
None
10440-
};
10441-
10442-
let offsets_keywords = if last_name == "OFFSETS" {
10443-
Some(self.parse_comma_separated(|parser| {
10428+
if self.parse_keyword(Keyword::STATISTICS) {
10429+
let topic = match self.parse_one_of_keywords(&[
10430+
Keyword::IO,
10431+
Keyword::PROFILE,
10432+
Keyword::TIME,
10433+
Keyword::XML,
10434+
]) {
10435+
Some(Keyword::IO) => SessionParamStatsTopic::IO,
10436+
Some(Keyword::PROFILE) => SessionParamStatsTopic::Profile,
10437+
Some(Keyword::TIME) => SessionParamStatsTopic::Time,
10438+
Some(Keyword::XML) => SessionParamStatsTopic::Xml,
10439+
_ => return self.expected("IO, PROFILE, TIME or XML", self.peek_token()),
10440+
};
10441+
let value = self.parse_session_param_value()?;
10442+
Ok(Statement::SetSessionParam(SetSessionParamKind::Statistics(
10443+
SetSessionParamStatistics { topic, value },
10444+
)))
10445+
} else if self.parse_keyword(Keyword::IDENTITY_INSERT) {
10446+
let obj = self.parse_object_name(false)?;
10447+
let value = self.parse_session_param_value()?;
10448+
Ok(Statement::SetSessionParam(
10449+
SetSessionParamKind::IdentityInsert(SetSessionParamIdentityInsert { obj, value }),
10450+
))
10451+
} else if self.parse_keyword(Keyword::OFFSETS) {
10452+
let keywords = self.parse_comma_separated(|parser| {
1044410453
let next_token = parser.next_token();
1044510454
match &next_token.token {
1044610455
Token::Word(w) => Ok(w.to_string()),
1044710456
_ => parser.expected("SQL keyword", next_token),
1044810457
}
10449-
})?)
10458+
})?;
10459+
let value = self.parse_session_param_value()?;
10460+
Ok(Statement::SetSessionParam(SetSessionParamKind::Offsets(
10461+
SetSessionParamOffsets { keywords, value },
10462+
)))
1045010463
} else {
10451-
None
10452-
};
10453-
10454-
let value = self.parse_expr()?.to_string();
10455-
Ok(Statement::SetSessionParam {
10456-
names,
10457-
identity_insert_obj,
10458-
offsets_keywords,
10459-
value,
10460-
})
10464+
let names = self.parse_comma_separated(|parser| {
10465+
let next_token = parser.next_token();
10466+
match next_token.token {
10467+
Token::Word(w) => Ok(w.to_string()),
10468+
_ => parser.expected("Session param name", next_token),
10469+
}
10470+
})?;
10471+
let value = self.parse_expr()?.to_string();
10472+
Ok(Statement::SetSessionParam(SetSessionParamKind::Generic(
10473+
SetSessionParamGeneric { names, value },
10474+
)))
10475+
}
1046110476
}
1046210477

10463-
pub fn parse_set_session_param_name(&mut self) -> Result<String, ParserError> {
10464-
if self.parse_keywords(&[Keyword::STATISTICS, Keyword::IO]) {
10465-
return Ok("STATISTICS IO".to_string());
10466-
} else if self.parse_keywords(&[Keyword::STATISTICS, Keyword::XML]) {
10467-
return Ok("STATISTICS XML".to_string());
10468-
} else if self.parse_keywords(&[Keyword::STATISTICS, Keyword::PROFILE]) {
10469-
return Ok("STATISTICS PROFILE".to_string());
10470-
} else if self.parse_keywords(&[Keyword::STATISTICS, Keyword::TIME]) {
10471-
return Ok("STATISTICS TIME".to_string());
10472-
}
10473-
let next_token = self.next_token();
10474-
if let Token::Word(w) = next_token.token {
10475-
return Ok(w.to_string());
10478+
fn parse_session_param_value(&mut self) -> Result<SessionParamValue, ParserError> {
10479+
if self.parse_keyword(Keyword::ON) {
10480+
Ok(SessionParamValue::On)
10481+
} else if self.parse_keyword(Keyword::OFF) {
10482+
Ok(SessionParamValue::Off)
10483+
} else {
10484+
self.expected("ON or OFF", self.peek_token())
1047610485
}
10477-
self.expected("Session param name", next_token)
1047810486
}
1047910487

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

0 commit comments

Comments
 (0)