Skip to content

Commit 5c6832a

Browse files
committed
Merge branch 'show-columns' into materialize-master
2 parents 2fdb016 + a214407 commit 5c6832a

File tree

10 files changed

+520
-115
lines changed

10 files changed

+520
-115
lines changed

src/ast/mod.rs

+112-31
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,39 @@ pub enum Statement {
461461
/// `RESTRICT` or no drop behavior at all was specified.
462462
cascade: bool,
463463
},
464-
/// { BEGIN [ TRANSACTION | WORK ] | START TRANSACTION } ...
464+
/// SET <variable>
465+
///
466+
/// Note: this is not a standard SQL statement, but it is supported by at
467+
/// least MySQL and PostgreSQL. Not all MySQL-specific syntatic forms are
468+
/// supported yet.
469+
SetVariable {
470+
local: bool,
471+
variable: Ident,
472+
value: SetVariableValue,
473+
},
474+
/// SHOW <variable>
475+
///
476+
/// Note: this is a PostgreSQL-specific statement.
477+
ShowVariable { variable: Ident },
478+
/// SHOW <object>S
479+
///
480+
/// ```sql
481+
/// SHOW TABLES;
482+
/// SHOW VIEWS;
483+
/// SHOW SOURCES;
484+
/// SHOW SINKS;
485+
/// ```
486+
ShowObjects { object_type: ObjectType },
487+
/// SHOW COLUMNS
488+
///
489+
/// Note: this is a MySQL-specific statement.
490+
ShowColumns {
491+
extended: bool,
492+
full: bool,
493+
table_name: ObjectName,
494+
filter: Option<ShowStatementFilter>,
495+
},
496+
/// `{ BEGIN [ TRANSACTION | WORK ] | START TRANSACTION } ...`
465497
StartTransaction { modes: Vec<TransactionMode> },
466498
/// SET TRANSACTION ...
467499
SetTransaction { modes: Vec<TransactionMode> },
@@ -473,25 +505,12 @@ pub enum Statement {
473505
Peek { name: ObjectName, immediate: bool },
474506
/// TAIL
475507
Tail { name: ObjectName },
476-
/// The mysql-ish `SHOW COLUMNS FROM`
477-
///
478-
/// ```sql
479-
/// SHOW COLUMNS FROM mydb.mytable;
480-
/// ```
481-
/// Limitations: doesn't support `LIKE`, `WHERE` or `SHOW COLUMNS FROM mytable FROM mydb;`
482-
ShowColumns { table_name: ObjectName },
483-
/// SHOW <object>S
484-
///
485-
/// ```sql
486-
/// SHOW TABLES;
487-
/// SHOW VIEWS;
488-
/// SHOW SOURCES;
489-
/// SHOW SINKS;
490-
/// ```
491-
Show { object_type: ObjectType },
492508
}
493509

494510
impl fmt::Display for Statement {
511+
// Clippy thinks this function is too complicated, but it is painful to
512+
// split up without extracting structs for each `Statement` variant.
513+
#[allow(clippy::cognitive_complexity)]
495514
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
496515
match self {
497516
Statement::Query(s) => write!(f, "{}", s),
@@ -689,6 +708,50 @@ impl fmt::Display for Statement {
689708
display_comma_separated(names),
690709
if *cascade { " CASCADE" } else { "" },
691710
),
711+
Statement::SetVariable {
712+
local,
713+
variable,
714+
value,
715+
} => {
716+
f.write_str("SET ")?;
717+
if *local {
718+
f.write_str("LOCAL ")?;
719+
}
720+
write!(f, "{} = {}", variable, value)
721+
}
722+
Statement::ShowVariable { variable } => write!(f, "SHOW {}", variable),
723+
Statement::ShowObjects { object_type } => {
724+
use ObjectType::*;
725+
write!(
726+
f,
727+
"SHOW {}",
728+
match object_type {
729+
Table => "TABLES",
730+
View => "VIEWS",
731+
Source => "SOURCES",
732+
Sink => "SINKS",
733+
}
734+
)
735+
}
736+
Statement::ShowColumns {
737+
extended,
738+
full,
739+
table_name,
740+
filter,
741+
} => {
742+
f.write_str("SHOW ")?;
743+
if *extended {
744+
f.write_str("EXTENDED ")?;
745+
}
746+
if *full {
747+
f.write_str("FULL ")?;
748+
}
749+
write!(f, "COLUMNS FROM {}", table_name)?;
750+
if let Some(filter) = filter {
751+
write!(f, " {}", filter)?;
752+
}
753+
Ok(())
754+
}
692755
Statement::StartTransaction { modes } => {
693756
write!(f, "START TRANSACTION")?;
694757
if !modes.is_empty() {
@@ -716,20 +779,6 @@ impl fmt::Display for Statement {
716779
}
717780
write!(f, "{}", name)
718781
}
719-
Statement::Show { object_type } => {
720-
use ObjectType::*;
721-
write!(
722-
f,
723-
"SHOW {}",
724-
match object_type {
725-
Table => "TABLES",
726-
View => "VIEWS",
727-
Source => "SOURCES",
728-
Sink => "SINKS",
729-
}
730-
)
731-
}
732-
Statement::ShowColumns { table_name } => write!(f, "SHOW COLUMNS FROM {}", table_name),
733782
Statement::Tail { name } => write!(f, "TAIL {}", name),
734783
}
735784
}
@@ -916,3 +965,35 @@ impl fmt::Display for TransactionIsolationLevel {
916965
})
917966
}
918967
}
968+
969+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
970+
pub enum ShowStatementFilter {
971+
Like(String),
972+
Where(Expr),
973+
}
974+
975+
impl fmt::Display for ShowStatementFilter {
976+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
977+
use ShowStatementFilter::*;
978+
match self {
979+
Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
980+
Where(expr) => write!(f, "WHERE {}", expr),
981+
}
982+
}
983+
}
984+
985+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
986+
pub enum SetVariableValue {
987+
Ident(Ident),
988+
Literal(Value),
989+
}
990+
991+
impl fmt::Display for SetVariableValue {
992+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
993+
use SetVariableValue::*;
994+
match self {
995+
Ident(ident) => f.write_str(ident),
996+
Literal(literal) => write!(f, "{}", literal),
997+
}
998+
}
999+
}

src/ast/value.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,8 @@ impl fmt::Display for DateTimeField {
167167
}
168168
}
169169

170-
struct EscapeSingleQuoteString<'a>(&'a str);
170+
pub struct EscapeSingleQuoteString<'a>(&'a str);
171+
171172
impl<'a> fmt::Display for EscapeSingleQuoteString<'a> {
172173
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
173174
for c in self.0.chars() {
@@ -180,6 +181,7 @@ impl<'a> fmt::Display for EscapeSingleQuoteString<'a> {
180181
Ok(())
181182
}
182183
}
183-
fn escape_single_quote_string(s: &str) -> EscapeSingleQuoteString<'_> {
184+
185+
pub fn escape_single_quote_string(s: &str) -> EscapeSingleQuoteString<'_> {
184186
EscapeSingleQuoteString(s)
185187
}

src/ast/visit.rs

+93-12
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,39 @@ pub trait Visit<'ast> {
445445
visit_alter_drop_constraint(self, name)
446446
}
447447

448+
fn visit_set_variable(
449+
&mut self,
450+
local: bool,
451+
variable: &'ast Ident,
452+
value: &'ast SetVariableValue,
453+
) {
454+
visit_set_variable(self, local, variable, value)
455+
}
456+
457+
fn visit_set_variable_value(&mut self, value: &'ast SetVariableValue) {
458+
visit_set_variable_value(self, value)
459+
}
460+
461+
fn visit_show_variable(&mut self, variable: &'ast Ident) {
462+
visit_show_variable(self, variable)
463+
}
464+
465+
fn visit_show_objects(&mut self, _object_type: ObjectType) {}
466+
467+
fn visit_show_columns(
468+
&mut self,
469+
extended: bool,
470+
full: bool,
471+
table_name: &'ast ObjectName,
472+
filter: Option<&'ast ShowStatementFilter>,
473+
) {
474+
visit_show_columns(self, extended, full, table_name, filter)
475+
}
476+
477+
fn visit_show_statement_filter(&mut self, filter: &'ast ShowStatementFilter) {
478+
visit_show_statement_filter(self, filter)
479+
}
480+
448481
fn visit_start_transaction(&mut self, modes: &'ast [TransactionMode]) {
449482
visit_start_transaction(self, modes)
450483
}
@@ -474,12 +507,6 @@ pub trait Visit<'ast> {
474507
visit_peek(self, name, immediate)
475508
}
476509

477-
fn visit_show_columns(&mut self, name: &'ast ObjectName) {
478-
visit_show_columns(self, name)
479-
}
480-
481-
fn visit_show(&mut self, _object_type: ObjectType) {}
482-
483510
fn visit_tail(&mut self, name: &'ast ObjectName) {
484511
visit_tail(self, name)
485512
}
@@ -555,15 +582,26 @@ pub fn visit_statement<'ast, V: Visit<'ast> + ?Sized>(visitor: &mut V, statement
555582
location,
556583
),
557584
Statement::AlterTable { name, operation } => visitor.visit_alter_table(name, operation),
585+
Statement::SetVariable {
586+
local,
587+
variable,
588+
value,
589+
} => visitor.visit_set_variable(*local, variable, value),
590+
Statement::ShowVariable { variable } => visitor.visit_show_variable(variable),
591+
Statement::ShowObjects { object_type } => visitor.visit_show_objects(*object_type),
592+
Statement::ShowColumns {
593+
extended,
594+
full,
595+
table_name,
596+
filter,
597+
} => visitor.visit_show_columns(*extended, *full, table_name, filter.as_ref()),
558598
Statement::StartTransaction { modes } => visitor.visit_start_transaction(modes),
559599
Statement::SetTransaction { modes } => visitor.visit_set_transaction(modes),
560600
Statement::Commit { chain } => visitor.visit_commit(*chain),
561601
Statement::Rollback { chain } => visitor.visit_rollback(*chain),
562602
Statement::Peek { name, immediate } => {
563603
visitor.visit_peek(name, *immediate);
564604
}
565-
Statement::Show { object_type } => visitor.visit_show(*object_type),
566-
Statement::ShowColumns { table_name } => visitor.visit_show_columns(table_name),
567605
Statement::Tail { name } => {
568606
visitor.visit_tail(name);
569607
}
@@ -1365,6 +1403,53 @@ pub fn visit_alter_drop_constraint<'ast, V: Visit<'ast> + ?Sized>(
13651403
visitor.visit_ident(name);
13661404
}
13671405

1406+
pub fn visit_set_variable<'ast, V: Visit<'ast> + ?Sized>(
1407+
visitor: &mut V,
1408+
_local: bool,
1409+
variable: &'ast Ident,
1410+
value: &'ast SetVariableValue,
1411+
) {
1412+
visitor.visit_ident(variable);
1413+
visitor.visit_set_variable_value(value);
1414+
}
1415+
1416+
pub fn visit_set_variable_value<'ast, V: Visit<'ast> + ?Sized>(
1417+
visitor: &mut V,
1418+
value: &'ast SetVariableValue,
1419+
) {
1420+
match value {
1421+
SetVariableValue::Ident(ident) => visitor.visit_ident(ident),
1422+
SetVariableValue::Literal(value) => visitor.visit_value(value),
1423+
}
1424+
}
1425+
1426+
pub fn visit_show_variable<'ast, V: Visit<'ast> + ?Sized>(visitor: &mut V, variable: &'ast Ident) {
1427+
visitor.visit_ident(variable);
1428+
}
1429+
1430+
pub fn visit_show_columns<'ast, V: Visit<'ast> + ?Sized>(
1431+
visitor: &mut V,
1432+
_extended: bool,
1433+
_full: bool,
1434+
table_name: &'ast ObjectName,
1435+
filter: Option<&'ast ShowStatementFilter>,
1436+
) {
1437+
visitor.visit_object_name(table_name);
1438+
if let Some(filter) = filter {
1439+
visitor.visit_show_statement_filter(filter);
1440+
}
1441+
}
1442+
1443+
pub fn visit_show_statement_filter<'ast, V: Visit<'ast> + ?Sized>(
1444+
visitor: &mut V,
1445+
filter: &'ast ShowStatementFilter,
1446+
) {
1447+
match filter {
1448+
ShowStatementFilter::Like(pattern) => visitor.visit_literal_string(pattern),
1449+
ShowStatementFilter::Where(expr) => visitor.visit_expr(expr),
1450+
}
1451+
}
1452+
13681453
pub fn visit_start_transaction<'ast, V: Visit<'ast> + ?Sized>(
13691454
visitor: &mut V,
13701455
modes: &'ast [TransactionMode],
@@ -1405,10 +1490,6 @@ pub fn visit_peek<'ast, V: Visit<'ast> + ?Sized>(
14051490
visitor.visit_object_name(name);
14061491
}
14071492

1408-
pub fn visit_show_columns<'ast, V: Visit<'ast> + ?Sized>(visitor: &mut V, name: &'ast ObjectName) {
1409-
visitor.visit_object_name(name);
1410-
}
1411-
14121493
pub fn visit_tail<'ast, V: Visit<'ast> + ?Sized>(visitor: &mut V, name: &'ast ObjectName) {
14131494
visitor.visit_object_name(name);
14141495
}

src/dialect/keywords.rs

+3
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,12 @@ define_keywords!(
167167
EXECUTE,
168168
EXISTS,
169169
EXP,
170+
EXTENDED,
170171
EXTERNAL,
171172
EXTRACT,
172173
FALSE,
173174
FETCH,
175+
FIELDS,
174176
FIRST,
175177
FILTER,
176178
FIRST_VALUE,
@@ -337,6 +339,7 @@ define_keywords!(
337339
SELECT,
338340
SENSITIVE,
339341
SERIALIZABLE,
342+
SESSION,
340343
SESSION_USER,
341344
SET,
342345
SHOW,

src/dialect/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ mod ansi;
1414
mod generic;
1515
pub mod keywords;
1616
mod mssql;
17+
mod mysql;
1718
mod postgresql;
1819

1920
use std::fmt::Debug;
2021

2122
pub use self::ansi::AnsiDialect;
2223
pub use self::generic::GenericDialect;
2324
pub use self::mssql::MsSqlDialect;
25+
pub use self::mysql::MySqlDialect;
2426
pub use self::postgresql::PostgreSqlDialect;
2527

2628
pub trait Dialect: Debug {

0 commit comments

Comments
 (0)