Skip to content

Commit

Permalink
feat: add show views & desc view (#14926)
Browse files Browse the repository at this point in the history
* add show views & desc view

* replace useless use of `format!`

* fix error & add test case

* rust fmt

* add logic tests

* add more logic tests

* move desc view test case to package 05_ddl

---------

Co-authored-by: TCeason <[email protected]>
  • Loading branch information
blackstar-baba and TCeason authored Mar 20, 2024
1 parent 83c68ae commit c4dcf91
Show file tree
Hide file tree
Showing 23 changed files with 799 additions and 1 deletion.
27 changes: 27 additions & 0 deletions src/query/ast/src/ast/format/ast_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1723,6 +1723,33 @@ impl<'ast> Visitor<'ast> for AstFormatVisitor {
self.children.push(node);
}

fn visit_show_views(&mut self, stmt: &'ast ShowViewsStmt) {
let mut children = Vec::new();
if let Some(database) = &stmt.database {
let database_name = format!("Database {}", database);
let database_format_ctx = AstFormatContext::new(database_name);
let database_node = FormatTreeNode::new(database_format_ctx);
children.push(database_node);
}
if let Some(limit) = &stmt.limit {
self.visit_show_limit(limit);
children.push(self.children.pop().unwrap());
}
let name = "ShowViews".to_string();
let format_ctx = AstFormatContext::with_children(name, children.len());
let node = FormatTreeNode::with_children(format_ctx, children);
self.children.push(node);
}

fn visit_describe_view(&mut self, stmt: &'ast DescribeViewStmt) {
self.visit_table_ref(&stmt.catalog, &stmt.database, &stmt.view);
let child = self.children.pop().unwrap();
let name = "DescribeView".to_string();
let format_ctx = AstFormatContext::with_children(name, 1);
let node = FormatTreeNode::with_children(format_ctx, vec![child]);
self.children.push(node);
}

fn visit_create_stream(&mut self, stmt: &'ast CreateStreamStmt) {
let mut children = Vec::new();
self.visit_table_ref(&stmt.catalog, &stmt.database, &stmt.stream);
Expand Down
4 changes: 4 additions & 0 deletions src/query/ast/src/ast/statements/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ pub enum Statement {
CreateView(CreateViewStmt),
AlterView(AlterViewStmt),
DropView(DropViewStmt),
ShowViews(ShowViewsStmt),
DescribeView(DescribeViewStmt),

// Streams
CreateStream(CreateStreamStmt),
Expand Down Expand Up @@ -549,6 +551,8 @@ impl Display for Statement {
Statement::CreateView(stmt) => write!(f, "{stmt}")?,
Statement::AlterView(stmt) => write!(f, "{stmt}")?,
Statement::DropView(stmt) => write!(f, "{stmt}")?,
Statement::ShowViews(stmt) => write!(f, "{stmt}")?,
Statement::DescribeView(stmt) => write!(f, "{stmt}")?,
Statement::CreateStream(stmt) => write!(f, "{stmt}")?,
Statement::DropStream(stmt) => write!(f, "{stmt}")?,
Statement::ShowStreams(stmt) => write!(f, "{stmt}")?,
Expand Down
56 changes: 56 additions & 0 deletions src/query/ast/src/ast/statements/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::ast::write_comma_separated_list;
use crate::ast::write_dot_separated_list;
use crate::ast::Identifier;
use crate::ast::Query;
use crate::ast::ShowLimit;

#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
pub struct CreateViewStmt {
Expand Down Expand Up @@ -113,3 +114,58 @@ impl Display for DropViewStmt {
)
}
}

#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
pub struct ShowViewsStmt {
pub catalog: Option<Identifier>,
pub database: Option<Identifier>,
#[drive(skip)]
pub full: bool,
pub limit: Option<ShowLimit>,
#[drive(skip)]
pub with_history: bool,
}

impl Display for ShowViewsStmt {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, "SHOW")?;
if self.full {
write!(f, " FULL")?;
}
write!(f, " VIEWS")?;
if self.with_history {
write!(f, " HISTORY")?;
}
if let Some(database) = &self.database {
write!(f, " FROM ")?;
if let Some(catalog) = &self.catalog {
write!(f, "{catalog}.",)?;
}
write!(f, "{database}")?;
}
if let Some(limit) = &self.limit {
write!(f, " {limit}")?;
}

Ok(())
}
}

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub struct DescribeViewStmt {
pub catalog: Option<Identifier>,
pub database: Option<Identifier>,
pub view: Identifier,
}

impl Display for DescribeViewStmt {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, "DESCRIBE ")?;
write_dot_separated_list(
f,
self.catalog
.iter()
.chain(self.database.iter().chain(Some(&self.view))),
)
}
}
4 changes: 4 additions & 0 deletions src/query/ast/src/ast/visitors/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,10 @@ pub trait Visitor<'ast>: Sized {

fn visit_drop_view(&mut self, _stmt: &'ast DropViewStmt) {}

fn visit_show_views(&mut self, _stmt: &'ast ShowViewsStmt) {}

fn visit_describe_view(&mut self, _stmt: &'ast DescribeViewStmt) {}

fn visit_create_stream(&mut self, _stmt: &'ast CreateStreamStmt) {}

fn visit_drop_stream(&mut self, _stmt: &'ast DropStreamStmt) {}
Expand Down
4 changes: 4 additions & 0 deletions src/query/ast/src/ast/visitors/visitor_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,10 @@ pub trait VisitorMut: Sized {

fn visit_drop_view(&mut self, _stmt: &mut DropViewStmt) {}

fn visit_show_views(&mut self, _stmt: &mut ShowViewsStmt) {}

fn visit_describe_view(&mut self, _stmt: &mut DescribeViewStmt) {}

fn visit_create_stream(&mut self, _stmt: &mut CreateStreamStmt) {}

fn visit_drop_stream(&mut self, _stmt: &mut DropStreamStmt) {}
Expand Down
2 changes: 2 additions & 0 deletions src/query/ast/src/ast/visitors/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,8 @@ pub fn walk_statement<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Statem
Statement::CreateView(stmt) => visitor.visit_create_view(stmt),
Statement::AlterView(stmt) => visitor.visit_alter_view(stmt),
Statement::DropView(stmt) => visitor.visit_drop_view(stmt),
Statement::ShowViews(stmt) => visitor.visit_show_views(stmt),
Statement::DescribeView(stmt) => visitor.visit_describe_view(stmt),
Statement::CreateStream(stmt) => visitor.visit_create_stream(stmt),
Statement::DropStream(stmt) => visitor.visit_drop_stream(stmt),
Statement::ShowStreams(stmt) => visitor.visit_show_streams(stmt),
Expand Down
2 changes: 2 additions & 0 deletions src/query/ast/src/ast/visitors/walk_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,8 @@ pub fn walk_statement_mut<V: VisitorMut>(visitor: &mut V, statement: &mut Statem
Statement::CreateView(stmt) => visitor.visit_create_view(stmt),
Statement::AlterView(stmt) => visitor.visit_alter_view(stmt),
Statement::DropView(stmt) => visitor.visit_drop_view(stmt),
Statement::ShowViews(stmt) => visitor.visit_show_views(stmt),
Statement::DescribeView(stmt) => visitor.visit_describe_view(stmt),
Statement::CreateStream(stmt) => visitor.visit_create_stream(stmt),
Statement::DropStream(stmt) => visitor.visit_drop_stream(stmt),
Statement::ShowStreams(stmt) => visitor.visit_show_streams(stmt),
Expand Down
33 changes: 33 additions & 0 deletions src/query/ast/src/parser/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,37 @@ pub fn statement_body(i: Input) -> IResult<Statement> {
})
},
);
let show_views = map(
rule! {
SHOW ~ FULL? ~ VIEWS ~ HISTORY? ~ ( ( FROM | IN ) ~ #dot_separated_idents_1_to_2 )? ~ #show_limit?
},
|(_, opt_full, _, opt_history, ctl_db, limit)| {
let (catalog, database) = match ctl_db {
Some((_, (Some(c), d))) => (Some(c), Some(d)),
Some((_, (None, d))) => (None, Some(d)),
_ => (None, None),
};
Statement::ShowViews(ShowViewsStmt {
catalog,
database,
full: opt_full.is_some(),
limit,
with_history: opt_history.is_some(),
})
},
);
let describe_view = map(
rule! {
( DESC | DESCRIBE ) ~ VIEW ~ #dot_separated_idents_1_to_3
},
|(_, _, (catalog, database, view))| {
Statement::DescribeView(DescribeViewStmt {
catalog,
database,
view,
})
},
);

let create_index = map_res(
rule! {
Expand Down Expand Up @@ -2048,6 +2079,7 @@ pub fn statement_body(i: Input) -> IResult<Statement> {
#show_tables : "`SHOW [FULL] TABLES [FROM <database>] [<show_limit>]`"
| #show_columns : "`SHOW [FULL] COLUMNS FROM <table> [FROM|IN <catalog>.<database>] [<show_limit>]`"
| #show_create_table : "`SHOW CREATE TABLE [<database>.]<table>`"
| #describe_view : "`DESCRIBE VIEW [<database>.]<view>`"
| #describe_table : "`DESCRIBE [<database>.]<table>`"
| #show_fields : "`SHOW FIELDS FROM [<database>.]<table>`"
| #show_tables_status : "`SHOW TABLES STATUS [FROM <database>] [<show_limit>]`"
Expand All @@ -2071,6 +2103,7 @@ pub fn statement_body(i: Input) -> IResult<Statement> {
#create_view : "`CREATE [OR REPLACE] VIEW [IF NOT EXISTS] [<database>.]<view> [(<column>, ...)] AS SELECT ...`"
| #drop_view : "`DROP VIEW [IF EXISTS] [<database>.]<view>`"
| #alter_view : "`ALTER VIEW [<database>.]<view> [(<column>, ...)] AS SELECT ...`"
| #show_views : "`SHOW [FULL] VIEWS [FROM <database>] [<show_limit>]`"
| #stream_table
| #create_index: "`CREATE [OR REPLACE] AGGREGATING INDEX [IF NOT EXISTS] <index> AS SELECT ...`"
| #drop_index: "`DROP <index_type> INDEX [IF EXISTS] <index>`"
Expand Down
2 changes: 2 additions & 0 deletions src/query/ast/src/parser/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,8 @@ pub enum TokenKind {
VERBOSE,
#[token("VIEW", ignore(ascii_case))]
VIEW,
#[token("VIEWS", ignore(ascii_case))]
VIEWS,
#[token("VIRTUAL", ignore(ascii_case))]
VIRTUAL,
#[token("WHEN", ignore(ascii_case))]
Expand Down
5 changes: 5 additions & 0 deletions src/query/ast/tests/it/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ fn test_statement() {
r#"create view v1(c1) as select number % 3 as a from numbers(1000);"#,
r#"create or replace view v1(c1) as select number % 3 as a from numbers(1000);"#,
r#"alter view v1(c2) as select number % 3 as a from numbers(1000);"#,
r#"show views"#,
r#"show views format TabSeparatedWithNamesAndTypes;"#,
r#"show full views"#,
r#"show full views from db"#,
r#"show full views from ctl.db"#,
r#"create stream test2.s1 on table test.t append_only = false;"#,
r#"create stream if not exists test2.s2 on table test.t at (stream => test1.s1) comment = 'this is a stream';"#,
r#"create or replace stream test2.s1 on table test.t append_only = false;"#,
Expand Down
2 changes: 1 addition & 1 deletion src/query/ast/tests/it/testdata/statement-error.txt
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ error:
--> SQL:1:6
|
1 | SHOW GRANT FOR ROLE 'role1';
| ^^^^^ unexpected `GRANT`, expecting `GRANTS`, `CREATE`, `NETWORK`, `VIRTUAL`, `STREAMS`, `CATALOGS`, `FUNCTIONS`, `DATABASES`, `CONNECTIONS`, `TABLE_FUNCTIONS`, `DROP`, `TABLE`, `ROLES`, `SHARE`, `TASKS`, `INDEXES`, `COLUMNS`, `PASSWORD`, `PROCESSLIST`, `STAGES`, `TABLES`, `SHARES`, `ENGINES`, `METRICS`, `SETTINGS`, `LOCKS`, `SCHEMAS`, `FIELDS`, `USERS`, `USER`, `FILE`, or `FULL`
| ^^^^^ unexpected `GRANT`, expecting `GRANTS`, `CREATE`, `NETWORK`, `VIRTUAL`, `STREAMS`, `CATALOGS`, `FUNCTIONS`, `DATABASES`, `CONNECTIONS`, `TABLE_FUNCTIONS`, `DROP`, `TABLE`, `ROLES`, `SHARE`, `TASKS`, `INDEXES`, `COLUMNS`, `PASSWORD`, `PROCESSLIST`, `STAGES`, `TABLES`, `SHARES`, `ENGINES`, `METRICS`, `SETTINGS`, `LOCKS`, `SCHEMAS`, `FIELDS`, `VIEWS`, `USERS`, `USER`, `FILE`, or `FULL`


---------- Input ----------
Expand Down
108 changes: 108 additions & 0 deletions src/query/ast/tests/it/testdata/statement.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3240,6 +3240,114 @@ AlterView(
)


---------- Input ----------
show views
---------- Output ---------
SHOW VIEWS
---------- AST ------------
ShowViews(
ShowViewsStmt {
catalog: None,
database: None,
full: false,
limit: None,
with_history: false,
},
)


---------- Input ----------
show views format TabSeparatedWithNamesAndTypes;
---------- Output ---------
SHOW VIEWS
---------- AST ------------
ShowViews(
ShowViewsStmt {
catalog: None,
database: None,
full: false,
limit: None,
with_history: false,
},
)


---------- FORMAT ------------
Some(
"TabSeparatedWithNamesAndTypes",
)
---------- Input ----------
show full views
---------- Output ---------
SHOW FULL VIEWS
---------- AST ------------
ShowViews(
ShowViewsStmt {
catalog: None,
database: None,
full: true,
limit: None,
with_history: false,
},
)


---------- Input ----------
show full views from db
---------- Output ---------
SHOW FULL VIEWS FROM db
---------- AST ------------
ShowViews(
ShowViewsStmt {
catalog: None,
database: Some(
Identifier {
span: Some(
21..23,
),
name: "db",
quote: None,
},
),
full: true,
limit: None,
with_history: false,
},
)


---------- Input ----------
show full views from ctl.db
---------- Output ---------
SHOW FULL VIEWS FROM ctl.db
---------- AST ------------
ShowViews(
ShowViewsStmt {
catalog: Some(
Identifier {
span: Some(
21..24,
),
name: "ctl",
quote: None,
},
),
database: Some(
Identifier {
span: Some(
25..27,
),
name: "db",
quote: None,
},
),
full: true,
limit: None,
with_history: false,
},
)


---------- Input ----------
create stream test2.s1 on table test.t append_only = false;
---------- Output ---------
Expand Down
3 changes: 3 additions & 0 deletions src/query/service/src/interpreters/access/privilege_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,9 @@ impl AccessChecker for PrivilegeAccess {
Plan::DropView(plan) => {
self.validate_db_access(&plan.catalog, &plan.database, vec![UserPrivilegeType::Drop], plan.if_exists).await?
}
Plan::DescribeView(plan) => {
self.validate_table_access(&plan.catalog, &plan.database, &plan.view_name, vec![UserPrivilegeType::Select], false).await?
}
Plan::CreateStream(plan) => {
self.validate_db_access(&plan.catalog, &plan.database, vec![UserPrivilegeType::Create], false).await?
}
Expand Down
5 changes: 5 additions & 0 deletions src/query/service/src/interpreters/interpreter_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ use crate::interpreters::interpreter_tasks_show::ShowTasksInterpreter;
use crate::interpreters::interpreter_txn_abort::AbortInterpreter;
use crate::interpreters::interpreter_txn_begin::BeginInterpreter;
use crate::interpreters::interpreter_txn_commit::CommitInterpreter;
use crate::interpreters::interpreter_view_describe::DescribeViewInterpreter;
use crate::interpreters::AlterUserInterpreter;
use crate::interpreters::CreateShareEndpointInterpreter;
use crate::interpreters::CreateShareInterpreter;
Expand Down Expand Up @@ -262,6 +263,10 @@ impl InterpreterFactory {
ctx,
*drop_view.clone(),
)?)),
Plan::DescribeView(describe_view) => Ok(Arc::new(DescribeViewInterpreter::try_create(
ctx,
*describe_view.clone(),
)?)),

// Streams
Plan::CreateStream(create_stream) => Ok(Arc::new(CreateStreamInterpreter::try_create(
Expand Down
Loading

0 comments on commit c4dcf91

Please sign in to comment.