Skip to content

Commit a214407

Browse files
committed
Support SHOW <var> and SET <var>
1 parent f64928e commit a214407

File tree

4 files changed

+146
-9
lines changed

4 files changed

+146
-9
lines changed

src/ast/mod.rs

+42
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,20 @@ pub enum Statement {
440440
/// `RESTRICT` or no drop behavior at all was specified.
441441
cascade: bool,
442442
},
443+
/// SET <variable>
444+
///
445+
/// Note: this is not a standard SQL statement, but it is supported by at
446+
/// least MySQL and PostgreSQL. Not all MySQL-specific syntatic forms are
447+
/// supported yet.
448+
SetVariable {
449+
local: bool,
450+
variable: Ident,
451+
value: SetVariableValue,
452+
},
453+
/// SHOW <variable>
454+
///
455+
/// Note: this is a PostgreSQL-specific statement.
456+
ShowVariable { variable: Ident },
443457
/// SHOW COLUMNS
444458
///
445459
/// Note: this is a MySQL-specific statement.
@@ -601,6 +615,18 @@ impl fmt::Display for Statement {
601615
display_comma_separated(names),
602616
if *cascade { " CASCADE" } else { "" },
603617
),
618+
Statement::SetVariable {
619+
local,
620+
variable,
621+
value,
622+
} => {
623+
f.write_str("SET ")?;
624+
if *local {
625+
f.write_str("LOCAL ")?;
626+
}
627+
write!(f, "{} = {}", variable, value)
628+
}
629+
Statement::ShowVariable { variable } => write!(f, "SHOW {}", variable),
604630
Statement::ShowColumns {
605631
extended,
606632
full,
@@ -827,3 +853,19 @@ impl fmt::Display for ShowStatementFilter {
827853
}
828854
}
829855
}
856+
857+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
858+
pub enum SetVariableValue {
859+
Ident(Ident),
860+
Literal(Value),
861+
}
862+
863+
impl fmt::Display for SetVariableValue {
864+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
865+
use SetVariableValue::*;
866+
match self {
867+
Ident(ident) => f.write_str(ident),
868+
Literal(literal) => write!(f, "{}", literal),
869+
}
870+
}
871+
}

src/dialect/keywords.rs

+1
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ define_keywords!(
335335
SELECT,
336336
SENSITIVE,
337337
SERIALIZABLE,
338+
SESSION,
338339
SESSION_USER,
339340
SET,
340341
SHOW,

src/parser.rs

+28-9
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@ impl Parser {
125125
"UPDATE" => Ok(self.parse_update()?),
126126
"ALTER" => Ok(self.parse_alter()?),
127127
"COPY" => Ok(self.parse_copy()?),
128+
"SET" => Ok(self.parse_set()?),
128129
"SHOW" => Ok(self.parse_show()?),
129130
"START" => Ok(self.parse_start_transaction()?),
130-
"SET" => Ok(self.parse_set_transaction()?),
131131
// `BEGIN` is a nonstandard but common alias for the
132132
// standard `START TRANSACTION` statement. It is supported
133133
// by at least PostgreSQL and MySQL.
@@ -1593,6 +1593,30 @@ impl Parser {
15931593
})
15941594
}
15951595

1596+
pub fn parse_set(&mut self) -> Result<Statement, ParserError> {
1597+
let modifier = self.parse_one_of_keywords(&["SESSION", "LOCAL"]);
1598+
let variable = self.parse_identifier()?;
1599+
if self.consume_token(&Token::Eq) || self.parse_keyword("TO") {
1600+
let token = self.peek_token();
1601+
let value = match (self.parse_value(), token) {
1602+
(Ok(value), _) => SetVariableValue::Literal(value),
1603+
(Err(_), Some(Token::Word(ident))) => SetVariableValue::Ident(ident.as_ident()),
1604+
(Err(_), other) => self.expected("variable value", other)?,
1605+
};
1606+
Ok(Statement::SetVariable {
1607+
local: modifier == Some("LOCAL"),
1608+
variable,
1609+
value,
1610+
})
1611+
} else if variable == "TRANSACTION" && modifier.is_none() {
1612+
Ok(Statement::SetTransaction {
1613+
modes: self.parse_transaction_modes()?,
1614+
})
1615+
} else {
1616+
self.expected("variable name", self.peek_token())
1617+
}
1618+
}
1619+
15961620
pub fn parse_show(&mut self) -> Result<Statement, ParserError> {
15971621
if self
15981622
.parse_one_of_keywords(&["EXTENDED", "FULL", "COLUMNS", "FIELDS"])
@@ -1601,7 +1625,9 @@ impl Parser {
16011625
self.prev_token();
16021626
self.parse_show_columns()
16031627
} else {
1604-
self.expected("EXTENDED, FULL, COLUMNS, or FIELDS", self.peek_token())
1628+
Ok(Statement::ShowVariable {
1629+
variable: self.parse_identifier()?,
1630+
})
16051631
}
16061632
}
16071633

@@ -1973,13 +1999,6 @@ impl Parser {
19731999
})
19742000
}
19752001

1976-
pub fn parse_set_transaction(&mut self) -> Result<Statement, ParserError> {
1977-
self.expect_keyword("TRANSACTION")?;
1978-
Ok(Statement::SetTransaction {
1979-
modes: self.parse_transaction_modes()?,
1980-
})
1981-
}
1982-
19832002
pub fn parse_transaction_modes(&mut self) -> Result<Vec<TransactionMode>, ParserError> {
19842003
let mut modes = vec![];
19852004
let mut required = false;

tests/sqlparser_postgres.rs

+75
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,81 @@ PHP ₱ USD $
251251
//assert_eq!(sql, ast.to_string());
252252
}
253253

254+
#[test]
255+
fn parse_set() {
256+
let stmt = pg_and_generic().verified_stmt("SET a = b");
257+
assert_eq!(
258+
stmt,
259+
Statement::SetVariable {
260+
local: false,
261+
variable: "a".into(),
262+
value: SetVariableValue::Ident("b".into()),
263+
}
264+
);
265+
266+
let stmt = pg_and_generic().verified_stmt("SET a = 'b'");
267+
assert_eq!(
268+
stmt,
269+
Statement::SetVariable {
270+
local: false,
271+
variable: "a".into(),
272+
value: SetVariableValue::Literal(Value::SingleQuotedString("b".into())),
273+
}
274+
);
275+
276+
let stmt = pg_and_generic().verified_stmt("SET a = 0");
277+
assert_eq!(
278+
stmt,
279+
Statement::SetVariable {
280+
local: false,
281+
variable: "a".into(),
282+
value: SetVariableValue::Literal(Value::Long(0)),
283+
}
284+
);
285+
286+
let stmt = pg_and_generic().verified_stmt("SET a = DEFAULT");
287+
assert_eq!(
288+
stmt,
289+
Statement::SetVariable {
290+
local: false,
291+
variable: "a".into(),
292+
value: SetVariableValue::Ident("DEFAULT".into()),
293+
}
294+
);
295+
296+
let stmt = pg_and_generic().verified_stmt("SET LOCAL a = b");
297+
assert_eq!(
298+
stmt,
299+
Statement::SetVariable {
300+
local: true,
301+
variable: "a".into(),
302+
value: SetVariableValue::Ident("b".into()),
303+
}
304+
);
305+
306+
pg_and_generic().one_statement_parses_to("SET a TO b", "SET a = b");
307+
pg_and_generic().one_statement_parses_to("SET SESSION a = b", "SET a = b");
308+
}
309+
310+
#[test]
311+
fn parse_show() {
312+
let stmt = pg_and_generic().verified_stmt("SHOW a");
313+
assert_eq!(
314+
stmt,
315+
Statement::ShowVariable {
316+
variable: "a".into()
317+
}
318+
);
319+
320+
let stmt = pg_and_generic().verified_stmt("SHOW ALL");
321+
assert_eq!(
322+
stmt,
323+
Statement::ShowVariable {
324+
variable: "ALL".into()
325+
}
326+
)
327+
}
328+
254329
fn pg() -> TestedDialects {
255330
TestedDialects {
256331
dialects: vec![Box::new(PostgreSqlDialect {})],

0 commit comments

Comments
 (0)