diff --git a/src/binder/mod.rs b/src/binder/mod.rs index b26c4d11..e4329da4 100644 --- a/src/binder/mod.rs +++ b/src/binder/mod.rs @@ -14,7 +14,8 @@ mod explain; pub mod expr; mod insert; mod select; -mod show; +mod show_table; +mod show_view; mod truncate; mod update; @@ -55,7 +56,8 @@ pub fn command_type(stmt: &Statement) -> Result { Statement::Query(_) | Statement::Explain { .. } | Statement::ExplainTable { .. } - | Statement::ShowTables { .. } => Ok(CommandType::DQL), + | Statement::ShowTables { .. } + | Statement::ShowVariable { .. } => Ok(CommandType::DQL), Statement::Analyze { .. } | Statement::Truncate { .. } | Statement::Update { .. } @@ -409,6 +411,10 @@ impl<'a, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'a, ' Statement::Analyze { table_name, .. } => self.bind_analyze(table_name)?, Statement::Truncate { table_name, .. } => self.bind_truncate(table_name)?, Statement::ShowTables { .. } => self.bind_show_tables()?, + Statement::ShowVariable { variable } => match &variable[0].value.to_lowercase()[..] { + "views" => self.bind_show_views()?, + _ => return Err(DatabaseError::UnsupportedStmt(stmt.to_string())), + }, Statement::Copy { source, to, diff --git a/src/binder/show.rs b/src/binder/show_table.rs similarity index 85% rename from src/binder/show.rs rename to src/binder/show_table.rs index f229555d..04672df9 100644 --- a/src/binder/show.rs +++ b/src/binder/show_table.rs @@ -7,6 +7,6 @@ use crate::types::value::DataValue; impl> Binder<'_, '_, T, A> { pub(crate) fn bind_show_tables(&mut self) -> Result { - Ok(LogicalPlan::new(Operator::Show, Childrens::None)) + Ok(LogicalPlan::new(Operator::ShowTable, Childrens::None)) } } diff --git a/src/binder/show_view.rs b/src/binder/show_view.rs new file mode 100644 index 00000000..dbcc9b2c --- /dev/null +++ b/src/binder/show_view.rs @@ -0,0 +1,12 @@ +use crate::binder::Binder; +use crate::errors::DatabaseError; +use crate::planner::operator::Operator; +use crate::planner::{Childrens, LogicalPlan}; +use crate::storage::Transaction; +use crate::types::value::DataValue; + +impl> Binder<'_, '_, T, A> { + pub(crate) fn bind_show_views(&mut self) -> Result { + Ok(LogicalPlan::new(Operator::ShowView, Childrens::None)) + } +} diff --git a/src/execution/dql/mod.rs b/src/execution/dql/mod.rs index 87464b2e..bcc05555 100644 --- a/src/execution/dql/mod.rs +++ b/src/execution/dql/mod.rs @@ -10,6 +10,7 @@ pub(crate) mod limit; pub(crate) mod projection; pub(crate) mod seq_scan; pub(crate) mod show_table; +pub(crate) mod show_view; pub(crate) mod sort; pub(crate) mod union; pub(crate) mod values; diff --git a/src/execution/dql/show_view.rs b/src/execution/dql/show_view.rs new file mode 100644 index 00000000..b16de4ce --- /dev/null +++ b/src/execution/dql/show_view.rs @@ -0,0 +1,34 @@ +use crate::catalog::view::View; +use crate::execution::{Executor, ReadExecutor}; +use crate::storage::{StatisticsMetaCache, TableCache, Transaction, ViewCache}; +use crate::throw; +use crate::types::tuple::Tuple; +use crate::types::value::{DataValue, Utf8Type}; +use sqlparser::ast::CharLengthUnits; + +pub struct ShowViews; + +impl<'a, T: Transaction + 'a> ReadExecutor<'a, T> for ShowViews { + fn execute( + self, + (TableCache, _, _): (&'a TableCache, &'a ViewCache, &'a StatisticsMetaCache), + transaction: *mut T, + ) -> Executor<'a> { + Box::new( + #[coroutine] + move || { + let metas = throw!(unsafe { &mut (*transaction) }.views(TableCache)); + + for View { name, .. } in metas { + let values = vec![DataValue::Utf8 { + value: name.to_string(), + ty: Utf8Type::Variable(None), + unit: CharLengthUnits::Characters, + }]; + + yield Ok(Tuple::new(None, values)); + } + }, + ) + } +} diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 7fab3246..9c4ed8c6 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -32,6 +32,7 @@ use crate::execution::dql::limit::Limit; use crate::execution::dql::projection::Projection; use crate::execution::dql::seq_scan::SeqScan; use crate::execution::dql::show_table::ShowTables; +use crate::execution::dql::show_view::ShowViews; use crate::execution::dql::sort::Sort; use crate::execution::dql::union::Union; use crate::execution::dql::values::Values; @@ -131,7 +132,8 @@ pub fn build_read<'a, T: Transaction + 'a>( Limit::from((op, input)).execute(cache, transaction) } Operator::Values(op) => Values::from(op).execute(cache, transaction), - Operator::Show => ShowTables.execute(cache, transaction), + Operator::ShowTable => ShowTables.execute(cache, transaction), + Operator::ShowView => ShowViews.execute(cache, transaction), Operator::Explain => { let input = childrens.pop_only(); diff --git a/src/optimizer/rule/normalization/column_pruning.rs b/src/optimizer/rule/normalization/column_pruning.rs index 06cd94c1..b8340897 100644 --- a/src/optimizer/rule/normalization/column_pruning.rs +++ b/src/optimizer/rule/normalization/column_pruning.rs @@ -149,7 +149,8 @@ impl ColumnPruning { | Operator::DropTable(_) | Operator::DropView(_) | Operator::Truncate(_) - | Operator::Show + | Operator::ShowTable + | Operator::ShowView | Operator::CopyFromFile(_) | Operator::CopyToFile(_) | Operator::AddColumn(_) diff --git a/src/optimizer/rule/normalization/compilation_in_advance.rs b/src/optimizer/rule/normalization/compilation_in_advance.rs index 63afe35e..cf1c4f2d 100644 --- a/src/optimizer/rule/normalization/compilation_in_advance.rs +++ b/src/optimizer/rule/normalization/compilation_in_advance.rs @@ -90,7 +90,8 @@ impl ExpressionRemapper { | Operator::TableScan(_) | Operator::Limit(_) | Operator::Values(_) - | Operator::Show + | Operator::ShowTable + | Operator::ShowView | Operator::Explain | Operator::Describe(_) | Operator::Insert(_) @@ -197,7 +198,8 @@ impl EvaluatorBind { | Operator::TableScan(_) | Operator::Limit(_) | Operator::Values(_) - | Operator::Show + | Operator::ShowTable + | Operator::ShowView | Operator::Explain | Operator::Describe(_) | Operator::Insert(_) diff --git a/src/planner/mod.rs b/src/planner/mod.rs index accec76e..39d67a83 100644 --- a/src/planner/mod.rs +++ b/src/planner/mod.rs @@ -174,9 +174,12 @@ impl LogicalPlan { .. }) => SchemaOutput::SchemaRef(schema_ref.clone()), Operator::Dummy => SchemaOutput::Schema(vec![]), - Operator::Show => SchemaOutput::Schema(vec![ColumnRef::from( + Operator::ShowTable => SchemaOutput::Schema(vec![ColumnRef::from( ColumnCatalog::new_dummy("TABLE".to_string()), )]), + Operator::ShowView => SchemaOutput::Schema(vec![ColumnRef::from( + ColumnCatalog::new_dummy("VIEW".to_string()), + )]), Operator::Explain => SchemaOutput::Schema(vec![ColumnRef::from( ColumnCatalog::new_dummy("PLAN".to_string()), )]), diff --git a/src/planner/operator/mod.rs b/src/planner/operator/mod.rs index 49fb2573..d51cf047 100644 --- a/src/planner/operator/mod.rs +++ b/src/planner/operator/mod.rs @@ -67,7 +67,8 @@ pub enum Operator { Sort(SortOperator), Limit(LimitOperator), Values(ValuesOperator), - Show, + ShowTable, + ShowView, Explain, Describe(DescribeOperator), Union(UnionOperator), @@ -159,7 +160,8 @@ impl Operator { .map(|column| ScalarExpression::ColumnRef(column.clone())) .collect_vec(), ), - Operator::Show + Operator::ShowTable + | Operator::ShowView | Operator::Explain | Operator::Describe(_) | Operator::Insert(_) @@ -239,7 +241,8 @@ impl Operator { Operator::Delete(op) => op.primary_keys.clone(), Operator::Dummy | Operator::Limit(_) - | Operator::Show + | Operator::ShowTable + | Operator::ShowView | Operator::Explain | Operator::Describe(_) | Operator::Insert(_) @@ -271,7 +274,8 @@ impl fmt::Display for Operator { Operator::Sort(op) => write!(f, "{}", op), Operator::Limit(op) => write!(f, "{}", op), Operator::Values(op) => write!(f, "{}", op), - Operator::Show => write!(f, "Show Tables"), + Operator::ShowTable => write!(f, "Show Tables"), + Operator::ShowView => write!(f, "Show Views"), Operator::Explain => unreachable!(), Operator::Describe(op) => write!(f, "{}", op), Operator::Insert(op) => write!(f, "{}", op), diff --git a/src/storage/mod.rs b/src/storage/mod.rs index ad147ffe..838fc1e2 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -16,6 +16,7 @@ use crate::types::value::DataValue; use crate::types::{ColumnId, LogicalType}; use crate::utils::lru::SharedLruCache; use itertools::Itertools; +use sqlparser::keywords::NULL; use std::collections::Bound; use std::io::Cursor; use std::mem; @@ -466,6 +467,20 @@ pub trait Transaction: Sized { })?)) } + fn views(&self, table_cache: &TableCache) -> Result, DatabaseError> { + let mut metas = vec![]; + let (min, max) = unsafe { &*self.table_codec() }.view_bound(); + let mut iter = self.range(Bound::Included(min), Bound::Included(max))?; + + while let Some((_, value)) = iter.try_next().ok().flatten() { + let meta = TableCodec::decode_view(&value, (self, table_cache))?; + + metas.push(meta); + } + + Ok(metas) + } + fn table<'a>( &'a self, table_cache: &'a TableCache, diff --git a/tests/slt/show_view.slt b/tests/slt/show_view.slt new file mode 100644 index 00000000..905e644e --- /dev/null +++ b/tests/slt/show_view.slt @@ -0,0 +1,44 @@ +statement ok +create table t1(id int primary key, a int, b int, c int) + +statement ok +insert into t1 values(0, 0, 0, 0) + +statement ok +insert into t1 values(1, 1, 1, 1) + +statement ok +insert into t1 values(2, 2, 2, 2) + +statement ok +create view v1 as select * from t1 + +query I +show views +---- +v1 + +statement ok +create view v2 as select * from t1 where a != 1 + +query I +show views +---- +v1 +v2 + +statement ok +drop view v1 + +query I +show views +---- +v2 + +statement ok +drop view v2 + +query I +show views +---- +