Skip to content

Commit

Permalink
feat: support show views statement (#4360)
Browse files Browse the repository at this point in the history
This commit enables show view statement which will display a list of views
names.
  • Loading branch information
lyang24 authored Jul 15, 2024
1 parent b8bd845 commit 9501318
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/frontend/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,9 @@ pub fn check_permission(
Statement::ShowIndex(stmt) => {
validate_db_permission!(stmt, query_ctx);
}
Statement::ShowViews(stmt) => {
validate_db_permission!(stmt, query_ctx);
}
Statement::ShowStatus(_stmt) => {}
Statement::DescribeTable(stmt) => {
validate_param(stmt.name(), query_ctx)?;
Expand Down
2 changes: 2 additions & 0 deletions src/operator/src/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ impl StatementExecutor {

Statement::ShowCharset(kind) => self.show_charset(kind, query_ctx).await,

Statement::ShowViews(stmt) => self.show_views(stmt, query_ctx).await,

Statement::Copy(sql::statements::copy::Copy::CopyTable(stmt)) => {
let req = to_copy_table_request(stmt, query_ctx.clone())?;
match req.direction {
Expand Down
13 changes: 12 additions & 1 deletion src/operator/src/statement/show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use sql::ast::Ident;
use sql::statements::create::Partitions;
use sql::statements::show::{
ShowColumns, ShowCreateFlow, ShowCreateView, ShowDatabases, ShowIndex, ShowKind,
ShowTableStatus, ShowTables, ShowVariables,
ShowTableStatus, ShowTables, ShowVariables, ShowViews,
};
use table::metadata::TableType;
use table::table_name::TableName;
Expand Down Expand Up @@ -152,6 +152,17 @@ impl StatementExecutor {
.context(error::ExecuteStatementSnafu)
}

#[tracing::instrument(skip_all)]
pub(super) async fn show_views(
&self,
stmt: ShowViews,
query_ctx: QueryContextRef,
) -> Result<Output> {
query::sql::show_views(stmt, &self.query_engine, &self.catalog_manager, query_ctx)
.await
.context(ExecuteStatementSnafu)
}

#[tracing::instrument(skip_all)]
pub async fn show_create_flow(
&self,
Expand Down
40 changes: 39 additions & 1 deletion src/query/src/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use std::sync::Arc;

use catalog::information_schema::{
columns, key_column_usage, schemata, tables, CHARACTER_SETS, COLLATIONS, COLUMNS,
KEY_COLUMN_USAGE, SCHEMATA, TABLES,
KEY_COLUMN_USAGE, SCHEMATA, TABLES, VIEWS,
};
use catalog::CatalogManagerRef;
use common_catalog::consts::{
Expand Down Expand Up @@ -55,6 +55,7 @@ use sql::parser::ParserContext;
use sql::statements::create::{CreateFlow, CreateView, Partitions};
use sql::statements::show::{
ShowColumns, ShowDatabases, ShowIndex, ShowKind, ShowTableStatus, ShowTables, ShowVariables,
ShowViews,
};
use sql::statements::statement::Statement;
use sqlparser::ast::ObjectName;
Expand All @@ -69,6 +70,7 @@ use crate::QueryEngineRef;
const SCHEMAS_COLUMN: &str = "Database";
const OPTIONS_COLUMN: &str = "Options";
const TABLES_COLUMN: &str = "Tables";
const VIEWS_COLUMN: &str = "Views";
const FIELD_COLUMN: &str = "Field";
const TABLE_TYPE_COLUMN: &str = "Table_type";
const COLUMN_NAME_COLUMN: &str = "Column";
Expand Down Expand Up @@ -725,6 +727,42 @@ pub fn show_create_view(
Ok(Output::new_with_record_batches(records))
}

/// Execute [`ShowViews`] statement and return the [`Output`] if success.
pub async fn show_views(
stmt: ShowViews,
query_engine: &QueryEngineRef,
catalog_manager: &CatalogManagerRef,
query_ctx: QueryContextRef,
) -> Result<Output> {
let schema_name = if let Some(database) = stmt.database {
database
} else {
query_ctx.current_schema()
};

let projects = vec![(tables::TABLE_NAME, VIEWS_COLUMN)];
let filters = vec![
col(tables::TABLE_SCHEMA).eq(lit(schema_name.clone())),
col(tables::TABLE_CATALOG).eq(lit(query_ctx.current_catalog())),
];
let like_field = Some(tables::TABLE_NAME);
let sort = vec![col(tables::TABLE_NAME).sort(true, true)];

query_from_information_schema_table(
query_engine,
catalog_manager,
query_ctx,
VIEWS,
vec![],
projects,
filters,
like_field,
sort,
stmt.kind,
)
.await
}

pub fn show_create_flow(
flow_name: ObjectName,
flow_val: FlowInfoValue,
Expand Down
60 changes: 59 additions & 1 deletion src/sql/src/parsers/show_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::error::{
use crate::parser::ParserContext;
use crate::statements::show::{
ShowColumns, ShowCreateFlow, ShowCreateTable, ShowCreateView, ShowDatabases, ShowIndex,
ShowKind, ShowStatus, ShowTableStatus, ShowTables, ShowVariables,
ShowKind, ShowStatus, ShowTableStatus, ShowTables, ShowVariables, ShowViews,
};
use crate::statements::statement::Statement;

Expand All @@ -44,6 +44,8 @@ impl<'a> ParserContext<'a> {
} else {
self.unsupported(self.peek_token_as_string())
}
} else if self.consume_token("VIEWS") {
self.parse_show_views()
} else if self.matches_keyword(Keyword::CHARSET) {
self.parser.next_token();
Ok(Statement::ShowCharset(self.parse_show_kind()?))
Expand Down Expand Up @@ -430,6 +432,28 @@ impl<'a> ParserContext<'a> {
_ => self.unsupported(self.peek_token_as_string()),
}
}

fn parse_show_views(&mut self) -> Result<Statement> {
let database = match self.parser.peek_token().token {
Token::EOF | Token::SemiColon => {
return Ok(Statement::ShowViews(ShowViews {
kind: ShowKind::All,
database: None,
}));
}

// SHOW VIEWS [in | FROM] [DATABASE]
Token::Word(w) => match w.keyword {
Keyword::IN | Keyword::FROM => self.parse_db_name()?,
_ => None,
},
_ => None,
};

let kind = self.parse_show_kind()?;

Ok(Statement::ShowViews(ShowViews { kind, database }))
}
}

#[cfg(test)]
Expand Down Expand Up @@ -942,4 +966,38 @@ mod tests {
);
assert_eq!(sql, stmts[0].to_string());
}

#[test]
pub fn test_show_views() {
let sql = "SHOW VIEWS";
let result =
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
let stmts = result.unwrap();
assert_eq!(1, stmts.len());
assert_eq!(
stmts[0],
Statement::ShowViews(ShowViews {
kind: ShowKind::All,
database: None,
})
);
assert_eq!(sql, stmts[0].to_string());
}

#[test]
pub fn test_show_views_in_db() {
let sql = "SHOW VIEWS IN d1";
let result =
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default());
let stmts = result.unwrap();
assert_eq!(1, stmts.len());
assert_eq!(
stmts[0],
Statement::ShowViews(ShowViews {
kind: ShowKind::All,
database: Some("d1".to_string()),
})
);
assert_eq!(sql, stmts[0].to_string());
}
}
62 changes: 62 additions & 0 deletions src/sql/src/statements/show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,25 @@ impl Display for ShowCreateView {
}
}

/// SQL structure for `SHOW VIEWS`.
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
pub struct ShowViews {
pub kind: ShowKind,
pub database: Option<String>,
}

impl Display for ShowViews {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SHOW VIEWS")?;
if let Some(database) = &self.database {
write!(f, " IN {database}")?;
}
format_kind!(self, f);

Ok(())
}
}

/// SQL structure for `SHOW VARIABLES xxx`.
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
pub struct ShowVariables {
Expand Down Expand Up @@ -473,6 +492,49 @@ SHOW FULL TABLES"#,
}
}

#[test]
fn test_display_show_views() {
let sql = r"show views in d1;";
let stmts: Vec<Statement> =
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
.unwrap();
assert_eq!(1, stmts.len());
assert_matches!(&stmts[0], Statement::ShowViews { .. });
match &stmts[0] {
Statement::ShowViews(show) => {
let new_sql = format!("\n{}", show);
assert_eq!(
r#"
SHOW VIEWS IN d1"#,
&new_sql
);
}
_ => {
unreachable!();
}
}

let sql = r"show views;";
let stmts: Vec<Statement> =
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
.unwrap();
assert_eq!(1, stmts.len());
assert_matches!(&stmts[0], Statement::ShowViews { .. });
match &stmts[0] {
Statement::ShowViews(show) => {
let new_sql = format!("\n{}", show);
assert_eq!(
r#"
SHOW VIEWS"#,
&new_sql
);
}
_ => {
unreachable!();
}
}
}

#[test]
fn test_display_show_databases() {
let sql = r"show databases;";
Expand Down
5 changes: 4 additions & 1 deletion src/sql/src/statements/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use crate::statements::query::Query;
use crate::statements::set_variables::SetVariables;
use crate::statements::show::{
ShowColumns, ShowCreateFlow, ShowCreateTable, ShowCreateView, ShowDatabases, ShowIndex,
ShowKind, ShowStatus, ShowTableStatus, ShowTables, ShowVariables,
ShowKind, ShowStatus, ShowTableStatus, ShowTables, ShowVariables, ShowViews,
};
use crate::statements::tql::Tql;
use crate::statements::truncate::TruncateTable;
Expand Down Expand Up @@ -91,6 +91,8 @@ pub enum Statement {
ShowCreateView(ShowCreateView),
// SHOW STATUS
ShowStatus(ShowStatus),
// SHOW VIEWS
ShowViews(ShowViews),
// DESCRIBE TABLE
DescribeTable(DescribeTable),
// EXPLAIN QUERY
Expand Down Expand Up @@ -132,6 +134,7 @@ impl Display for Statement {
Statement::ShowCreateTable(s) => s.fmt(f),
Statement::ShowCreateFlow(s) => s.fmt(f),
Statement::ShowCreateView(s) => s.fmt(f),
Statement::ShowViews(s) => s.fmt(f),
Statement::ShowStatus(s) => s.fmt(f),
Statement::DescribeTable(s) => s.fmt(f),
Statement::Explain(s) => s.fmt(f),
Expand Down
13 changes: 13 additions & 0 deletions tests/cases/standalone/common/view/view.result
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ CREATE VIEW v1 AS SELECT * FROM dontexist;

Error: 3000(PlanQuery), Failed to plan SQL: Error during planning: Table not found: greptime.public.dontexist

SHOW VIEWS;

+-------+
| Views |
+-------+
| v1 |
+-------+

DROP VIEW v1;

Affected Rows: 0
Expand Down Expand Up @@ -81,3 +89,8 @@ SHOW TABLES;
| numbers |
+---------+

SHOW VIEWS;

++
++

4 changes: 4 additions & 0 deletions tests/cases/standalone/common/view/view.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ INSERT INTO v1 VALUES (1);

CREATE VIEW v1 AS SELECT * FROM dontexist;

SHOW VIEWS;

DROP VIEW v1;

SELECT * FROM v1;
Expand All @@ -42,3 +44,5 @@ DROP VIEW IF EXISTS v2;
DROP TABLE t1;

SHOW TABLES;

SHOW VIEWS;

0 comments on commit 9501318

Please sign in to comment.