Skip to content

Commit

Permalink
fix unit test & add docs
Browse files Browse the repository at this point in the history
Signed-off-by: Veeupup <code@tanweime.com>
  • Loading branch information
Veeupup committed Apr 1, 2022
1 parent 49fdec2 commit c9b0603
Show file tree
Hide file tree
Showing 16 changed files with 149 additions and 100 deletions.
1 change: 0 additions & 1 deletion common/meta/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ pub use table::TableIdent;
pub use table::TableInfo;
pub use table::TableMeta;
pub use table::TableNameIndent;
pub use table::TableView;
pub use table::UpsertTableOptionReply;
pub use table::UpsertTableOptionReq;
pub use user_auth::AuthInfo;
Expand Down
8 changes: 0 additions & 8 deletions common/meta/types/src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,6 @@ pub struct TableInfo {
pub meta: TableMeta,
}

/// TableView info
///
/// it only store the subquery string to make future reading
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, Eq, PartialEq)]
pub struct TableView {
pub subquery: String,
}

/// The essential state that defines what a table is.
///
/// It is what a meta store just needs to save.
Expand Down
4 changes: 4 additions & 0 deletions docs/doc/03-reference/03-sql/01-ddl/06-view/_category_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
label: 'DDL for Logical View'
link:
type: generated-index
title: 'DDL for Logical View'
37 changes: 37 additions & 0 deletions docs/doc/03-reference/03-sql/01-ddl/06-view/ddl-alter-view.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: ALTER VIEW
---

Alter the existing view by using another `QUERY`.

## Syntax

```sql
ALTER VIEW [db.]view_name AS SELECT query
```

## Examples

```sql
mysql> create view tmp_view as select number % 3 as a, avg(number) from numbers(1000) group by a order by a;

mysql> select * from tmp_view;
+------+-------------+
| a | avg(number) |
+------+-------------+
| 0 | 499.5 |
| 1 | 499 |
| 2 | 500 |
+------+-------------+

mysql> ALTER VIEW tmp_view AS SELECT * from numbers(3);

mysql> select * from tmp_view;
+--------+
| number |
+--------+
| 0 |
| 1 |
| 2 |
+--------+
```
43 changes: 43 additions & 0 deletions docs/doc/03-reference/03-sql/01-ddl/06-view/ddl-create-view.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: CREATE VIEW
---

Create a new Logical View of a Table. The Logical View does not store any physical data, when we access a logical view, it
will convert the sql into the subqery format to finish it.

For example, if you create a Logical View like:

```sql
CREATE VIEW view_t1 AS SELECT a, b FROM t1;
```
And do a query like:
```sql
SELECT a from view_t1;
```
the result equals the below query
```sql
SELECT a from (SELECT a, b FROM t1);
```

So, if you delete the table which the view depends on, it occurs an error that the original table does not exist. And you may need to drop the old view and recreate the new view you need.

## Syntax

```sql
CREATE VIEW [IF NOT EXISTS] [db.]view_name AS SELECT query
```

## Examples

```sql
mysql> create view tmp_view as select number % 3 as a, avg(number) from numbers(1000) group by a order by a;

mysql> select * from tmp_view;
+------+-------------+
| a | avg(number) |
+------+-------------+
| 0 | 499.5 |
| 1 | 499 |
| 2 | 500 |
+------+-------------+
```
20 changes: 20 additions & 0 deletions docs/doc/03-reference/03-sql/01-ddl/06-view/ddl-drop-view.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: DROP VIEW
---

Drop the view.

## Syntax

```sql
DROP VIEW [IF EXISTS] [db.]view_name
```

## Examples

```sql
mysql> DROP VIEW IF EXISTS tmp_view;

mysql> select * from tmp_view;
ERROR 1105 (HY000): Code: 1025, displayText = Unknown table 'tmp_view'.
```
2 changes: 1 addition & 1 deletion query/src/interpreters/interpreter_table_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl Interpreter for DropTableInterpreter {
if let Some(table) = &tbl {
if table.get_table_info().engine() == VIEW_ENGINE {
return Err(ErrorCode::UnexpectedError(format!(
"{}.{} is VIEW, planse use `DROP VIEW {}.{}`",
"{}.{} is VIEW, please use `DROP VIEW {}.{}`",
&self.plan.db, &self.plan.table, &self.plan.db, &self.plan.table
)));
}
Expand Down
24 changes: 3 additions & 21 deletions query/src/sql/statements/statement_alter_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

use std::sync::Arc;

use common_exception::ErrorCode;
use common_exception::Result;
use common_planners::AlterViewPlan;
use common_planners::PlanNode;
Expand All @@ -24,6 +23,7 @@ use sqlparser::ast::ObjectName;
use crate::sessions::QueryContext;
use crate::sql::statements::AnalyzableStatement;
use crate::sql::statements::AnalyzedResult;
use crate::sql::statements::DfCreateTable;
use crate::sql::statements::DfQueryStatement;

#[derive(Debug, Clone, PartialEq)]
Expand All @@ -40,12 +40,11 @@ pub struct DfAlterView {
impl AnalyzableStatement for DfAlterView {
#[tracing::instrument(level = "debug", skip(self, ctx), fields(ctx.id = ctx.get_id().as_str()))]
async fn analyze(&self, ctx: Arc<QueryContext>) -> Result<AnalyzedResult> {
// check if query is ok
// check whether query is valid
let _ = self.query.analyze(ctx.clone()).await?;
//
let subquery = self.subquery.clone();
let tenant = ctx.get_tenant();
let (db, viewname) = Self::resolve_viewname(ctx.clone(), &self.name)?;
let (db, viewname) = DfCreateTable::resolve_table(ctx.clone(), &self.name, "View")?;
Ok(AnalyzedResult::SimpleQuery(Box::new(PlanNode::AlterView(
AlterViewPlan {
tenant,
Expand All @@ -56,20 +55,3 @@ impl AnalyzableStatement for DfAlterView {
))))
}
}

impl DfAlterView {
fn resolve_viewname(
ctx: Arc<QueryContext>,
table_name: &ObjectName,
) -> Result<(String, String)> {
let idents = &table_name.0;
match idents.len() {
0 => Err(ErrorCode::SyntaxException("Create VIEW name is empty")),
1 => Ok((ctx.get_current_database(), idents[0].value.clone())),
2 => Ok((idents[0].value.clone(), idents[1].value.clone())),
_ => Err(ErrorCode::SyntaxException(
"Create VIEW name must be [`db`].`VIEW`",
)),
}
}
}
22 changes: 15 additions & 7 deletions query/src/sql/statements/statement_create_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub struct DfCreateTable {
impl AnalyzableStatement for DfCreateTable {
#[tracing::instrument(level = "debug", skip(self, ctx), fields(ctx.id = ctx.get_id().as_str()))]
async fn analyze(&self, ctx: Arc<QueryContext>) -> Result<AnalyzedResult> {
let (db, table) = Self::resolve_table(ctx.clone(), &self.name)?;
let (db, table) = Self::resolve_table(ctx.clone(), &self.name, "Table")?;
let mut table_meta = self.table_meta(ctx.clone(), db.as_str()).await?;
let if_not_exists = self.if_not_exists;
let tenant = ctx.get_tenant();
Expand Down Expand Up @@ -101,15 +101,23 @@ impl AnalyzableStatement for DfCreateTable {
}

impl DfCreateTable {
fn resolve_table(ctx: Arc<QueryContext>, table_name: &ObjectName) -> Result<(String, String)> {
pub fn resolve_table(
ctx: Arc<QueryContext>,
table_name: &ObjectName,
table_type: &str,
) -> Result<(String, String)> {
let idents = &table_name.0;
match idents.len() {
0 => Err(ErrorCode::SyntaxException("Create table name is empty")),
0 => Err(ErrorCode::SyntaxException(format!(
"{} name is empty",
table_type
))),
1 => Ok((ctx.get_current_database(), idents[0].value.clone())),
2 => Ok((idents[0].value.clone(), idents[1].value.clone())),
_ => Err(ErrorCode::SyntaxException(
"Create table name must be [`db`].`table`",
)),
_ => Err(ErrorCode::SyntaxException(format!(
"{} name must be [`db`].`{}`",
table_type, table_type
))),
}
}

Expand All @@ -132,7 +140,7 @@ impl DfCreateTable {
Some(like_table_name) => {
// resolve database and table name from 'like statement'
let (origin_db_name, origin_table_name) =
Self::resolve_table(ctx.clone(), like_table_name)?;
Self::resolve_table(ctx.clone(), like_table_name, "Table")?;

// use the origin table's schema for the table to create
let origin_table = ctx.get_table(&origin_db_name, &origin_table_name).await?;
Expand Down
24 changes: 3 additions & 21 deletions query/src/sql/statements/statement_create_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

use std::sync::Arc;

use common_exception::ErrorCode;
use common_exception::Result;
use common_planners::CreateViewPlan;
use common_planners::PlanNode;
Expand All @@ -25,6 +24,7 @@ use sqlparser::ast::ObjectName;
use crate::sessions::QueryContext;
use crate::sql::statements::AnalyzableStatement;
use crate::sql::statements::AnalyzedResult;
use crate::sql::statements::DfCreateTable;
use crate::sql::statements::DfQueryStatement;

#[derive(Debug, Clone, PartialEq)]
Expand All @@ -42,13 +42,12 @@ pub struct DfCreateView {
impl AnalyzableStatement for DfCreateView {
#[tracing::instrument(level = "debug", skip(self, ctx), fields(ctx.id = ctx.get_id().as_str()))]
async fn analyze(&self, ctx: Arc<QueryContext>) -> Result<AnalyzedResult> {
// check if query is ok
// check whether query is valid
let _ = self.query.analyze(ctx.clone()).await?;
//
let if_not_exists = self.if_not_exists;
let subquery = self.subquery.clone();
let tenant = ctx.get_tenant();
let (db, viewname) = Self::resolve_viewname(ctx.clone(), &self.name)?;
let (db, viewname) = DfCreateTable::resolve_table(ctx.clone(), &self.name, "View")?;
Ok(AnalyzedResult::SimpleQuery(Box::new(PlanNode::CreateView(
CreateViewPlan {
if_not_exists,
Expand All @@ -60,20 +59,3 @@ impl AnalyzableStatement for DfCreateView {
))))
}
}

impl DfCreateView {
fn resolve_viewname(
ctx: Arc<QueryContext>,
table_name: &ObjectName,
) -> Result<(String, String)> {
let idents = &table_name.0;
match idents.len() {
0 => Err(ErrorCode::SyntaxException("Create VIEW name is empty")),
1 => Ok((ctx.get_current_database(), idents[0].value.clone())),
2 => Ok((idents[0].value.clone(), idents[1].value.clone())),
_ => Err(ErrorCode::SyntaxException(
"Create VIEW name must be [`db`].`VIEW`",
)),
}
}
}
23 changes: 3 additions & 20 deletions query/src/sql/statements/statement_drop_view.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2021 Datafuse Labs.
// Copyright 2022 Datafuse Labs.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -14,7 +14,6 @@

use std::sync::Arc;

use common_exception::ErrorCode;
use common_exception::Result;
use common_planners::DropViewPlan;
use common_planners::PlanNode;
Expand All @@ -24,6 +23,7 @@ use sqlparser::ast::ObjectName;
use crate::sessions::QueryContext;
use crate::sql::statements::AnalyzableStatement;
use crate::sql::statements::AnalyzedResult;
use crate::sql::statements::DfCreateTable;

#[derive(Debug, Clone, PartialEq)]
pub struct DfDropView {
Expand All @@ -37,7 +37,7 @@ impl AnalyzableStatement for DfDropView {
async fn analyze(&self, ctx: Arc<QueryContext>) -> Result<AnalyzedResult> {
let if_exists = self.if_exists;
let tenant = ctx.get_tenant();
let (db, viewname) = self.resolve_table(ctx)?;
let (db, viewname) = DfCreateTable::resolve_table(ctx, &self.name, "View")?;

Ok(AnalyzedResult::SimpleQuery(Box::new(PlanNode::DropView(
DropViewPlan {
Expand All @@ -49,20 +49,3 @@ impl AnalyzableStatement for DfDropView {
))))
}
}

impl DfDropView {
fn resolve_table(&self, ctx: Arc<QueryContext>) -> Result<(String, String)> {
let DfDropView {
name: ObjectName(idents),
..
} = self;
match idents.len() {
0 => Err(ErrorCode::SyntaxException("Drop VIEW name is empty")),
1 => Ok((ctx.get_current_database(), idents[0].value.clone())),
2 => Ok((idents[0].value.clone(), idents[1].value.clone())),
_ => Err(ErrorCode::SyntaxException(
"Drop VIEW name must be [`db`].`VIEW`",
)),
}
}
}
3 changes: 0 additions & 3 deletions query/src/storages/storage_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,6 @@ impl StorageFactory {
});

// Register View table engine
// to store view as normal table in meta service
// so we will need a table engine to present VIEW type
// TODO(veeupup) add a new table engine storage
creators.insert("VIEW".to_string(), Storage {
creator: Arc::new(ViewTable::try_create),
descriptor: Arc::new(ViewTable::description),
Expand Down
17 changes: 9 additions & 8 deletions query/tests/it/interpreters/interpreter_show_engines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ async fn test_show_engines_interpreter() -> Result<()> {
let stream = executor.execute(None).await?;
let result = stream.try_collect::<Vec<_>>().await?;
let expected = vec![
"+--------+-----------------------+",
"| Engine | Comment |",
"+--------+-----------------------+",
"| FUSE | FUSE Storage Engine |",
"| GITHUB | GITHUB Storage Engine |",
"| MEMORY | MEMORY Storage Engine |",
"| NULL | NULL Storage Engine |",
"+--------+-----------------------+",
"+--------+-----------------------------+",
"| Engine | Comment |",
"+--------+-----------------------------+",
"| FUSE | FUSE Storage Engine |",
"| GITHUB | GITHUB Storage Engine |",
"| MEMORY | MEMORY Storage Engine |",
"| NULL | NULL Storage Engine |",
"| VIEW | VIEW STORAGE (LOGICAL VIEW) |",
"+--------+-----------------------------+",
];
common_datablocks::assert_blocks_sorted_eq(expected, result.as_slice());
}
Expand Down
Loading

0 comments on commit c9b0603

Please sign in to comment.