Skip to content
This repository was archived by the owner on Dec 25, 2019. It is now read-only.

Commit e1ded18

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

4 files changed

Lines changed: 168 additions & 9 deletions

File tree

src/ast/mod.rs

Lines changed: 42 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 28 additions & 9 deletions
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("equals sign or TO", 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

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
1717
use sqlparser::ast::*;
1818
use sqlparser::dialect::{GenericDialect, PostgreSqlDialect};
19+
use sqlparser::parser::ParserError;
1920
use sqlparser::test_utils::*;
2021

2122
#[test]
@@ -251,6 +252,102 @@ PHP ₱ USD $
251252
//assert_eq!(sql, ast.to_string());
252253
}
253254

255+
#[test]
256+
fn parse_set() {
257+
let stmt = pg_and_generic().verified_stmt("SET a = b");
258+
assert_eq!(
259+
stmt,
260+
Statement::SetVariable {
261+
local: false,
262+
variable: "a".into(),
263+
value: SetVariableValue::Ident("b".into()),
264+
}
265+
);
266+
267+
let stmt = pg_and_generic().verified_stmt("SET a = 'b'");
268+
assert_eq!(
269+
stmt,
270+
Statement::SetVariable {
271+
local: false,
272+
variable: "a".into(),
273+
value: SetVariableValue::Literal(Value::SingleQuotedString("b".into())),
274+
}
275+
);
276+
277+
let stmt = pg_and_generic().verified_stmt("SET a = 0");
278+
assert_eq!(
279+
stmt,
280+
Statement::SetVariable {
281+
local: false,
282+
variable: "a".into(),
283+
value: SetVariableValue::Literal(Value::Long(0)),
284+
}
285+
);
286+
287+
let stmt = pg_and_generic().verified_stmt("SET a = DEFAULT");
288+
assert_eq!(
289+
stmt,
290+
Statement::SetVariable {
291+
local: false,
292+
variable: "a".into(),
293+
value: SetVariableValue::Ident("DEFAULT".into()),
294+
}
295+
);
296+
297+
let stmt = pg_and_generic().verified_stmt("SET LOCAL a = b");
298+
assert_eq!(
299+
stmt,
300+
Statement::SetVariable {
301+
local: true,
302+
variable: "a".into(),
303+
value: SetVariableValue::Ident("b".into()),
304+
}
305+
);
306+
307+
pg_and_generic().one_statement_parses_to("SET a TO b", "SET a = b");
308+
pg_and_generic().one_statement_parses_to("SET SESSION a = b", "SET a = b");
309+
310+
assert_eq!(
311+
pg_and_generic().parse_sql_statements("SET"),
312+
Err(ParserError::ParserError(
313+
"Expected identifier, found: EOF".to_string()
314+
)),
315+
);
316+
317+
assert_eq!(
318+
pg_and_generic().parse_sql_statements("SET a b"),
319+
Err(ParserError::ParserError(
320+
"Expected equals sign or TO, found: b".to_string()
321+
)),
322+
);
323+
324+
assert_eq!(
325+
pg_and_generic().parse_sql_statements("SET a ="),
326+
Err(ParserError::ParserError(
327+
"Expected variable value, found: EOF".to_string()
328+
)),
329+
);
330+
}
331+
332+
#[test]
333+
fn parse_show() {
334+
let stmt = pg_and_generic().verified_stmt("SHOW a");
335+
assert_eq!(
336+
stmt,
337+
Statement::ShowVariable {
338+
variable: "a".into()
339+
}
340+
);
341+
342+
let stmt = pg_and_generic().verified_stmt("SHOW ALL");
343+
assert_eq!(
344+
stmt,
345+
Statement::ShowVariable {
346+
variable: "ALL".into()
347+
}
348+
)
349+
}
350+
254351
fn pg() -> TestedDialects {
255352
TestedDialects {
256353
dialects: vec![Box::new(PostgreSqlDialect {})],

0 commit comments

Comments
 (0)