From c71a00cb327c0c7d22444e1eccc7c9aaeffe4553 Mon Sep 17 00:00:00 2001 From: wszhdshys <1925792291@qq.com> Date: Mon, 14 Jul 2025 19:55:55 +0800 Subject: [PATCH 1/3] feat: Show View --- src/binder/mod.rs | 13 +++++- src/binder/{show.rs => show_table.rs} | 2 +- src/binder/show_view.rs | 12 +++++ src/execution/dql/mod.rs | 1 + src/execution/dql/show_view.rs | 35 +++++++++++++++ src/execution/mod.rs | 4 +- .../rule/normalization/column_pruning.rs | 3 +- .../normalization/compilation_in_advance.rs | 6 ++- src/planner/mod.rs | 5 ++- src/planner/operator/mod.rs | 12 +++-- src/storage/mod.rs | 15 +++++++ tests/slt/show_view.slt | 44 +++++++++++++++++++ 12 files changed, 140 insertions(+), 12 deletions(-) rename src/binder/{show.rs => show_table.rs} (85%) create mode 100644 src/binder/show_view.rs create mode 100644 src/execution/dql/show_view.rs create mode 100644 tests/slt/show_view.slt diff --git a/src/binder/mod.rs b/src/binder/mod.rs index b26c4d11..1ea251d2 100644 --- a/src/binder/mod.rs +++ b/src/binder/mod.rs @@ -14,9 +14,10 @@ mod explain; pub mod expr; mod insert; mod select; -mod show; +mod show_table; mod truncate; mod update; +mod show_view; use sqlparser::ast::{Ident, ObjectName, ObjectType, SetExpr, Statement}; use std::collections::{BTreeMap, HashMap, HashSet}; @@ -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,13 @@ 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 } => { + let value = variable[0].value.clone(); + match &value[..] { + "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..3ba60d4c 100644 --- a/src/execution/dql/mod.rs +++ b/src/execution/dql/mod.rs @@ -13,6 +13,7 @@ pub(crate) mod show_table; pub(crate) mod sort; pub(crate) mod union; pub(crate) mod values; +pub(crate) mod show_view; #[cfg(test)] pub(crate) mod test { diff --git a/src/execution/dql/show_view.rs b/src/execution/dql/show_view.rs new file mode 100644 index 00000000..08e91ab7 --- /dev/null +++ b/src/execution/dql/show_view.rs @@ -0,0 +1,35 @@ +use crate::catalog::TableMeta; +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; +use crate::catalog::view::View; + +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) }.view_metas(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..3c13fd23 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -42,6 +42,7 @@ use crate::storage::{StatisticsMetaCache, TableCache, Transaction, ViewCache}; use crate::types::index::IndexInfo; use crate::types::tuple::Tuple; use std::ops::Coroutine; +use crate::execution::dql::show_view::ShowViews; pub type Executor<'a> = Box, Return = ()> + 'a + Unpin>; @@ -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..92c3e531 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -22,6 +22,7 @@ use std::mem; use std::ops::SubAssign; use std::sync::Arc; use std::vec::IntoIter; +use sqlparser::keywords::NULL; use ulid::Generator; pub(crate) type StatisticsMetaCache = SharedLruCache<(TableName, IndexId), StatisticsMeta>; @@ -466,6 +467,20 @@ pub trait Transaction: Sized { })?)) } + fn view_metas(&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 +---- + From 2fbd2df110342346646c476e1ad13ecb4da263f7 Mon Sep 17 00:00:00 2001 From: wszhdshys <1925792291@qq.com> Date: Mon, 14 Jul 2025 20:01:03 +0800 Subject: [PATCH 2/3] feat: Show View --- src/binder/mod.rs | 6 +++--- src/execution/dql/mod.rs | 2 +- src/execution/dql/show_view.rs | 4 ++-- src/execution/mod.rs | 2 +- src/storage/mod.rs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/binder/mod.rs b/src/binder/mod.rs index 1ea251d2..1ace1117 100644 --- a/src/binder/mod.rs +++ b/src/binder/mod.rs @@ -15,9 +15,9 @@ pub mod expr; mod insert; mod select; mod show_table; +mod show_view; mod truncate; mod update; -mod show_view; use sqlparser::ast::{Ident, ObjectName, ObjectType, SetExpr, Statement}; use std::collections::{BTreeMap, HashMap, HashSet}; @@ -415,9 +415,9 @@ impl<'a, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'a, ' let value = variable[0].value.clone(); match &value[..] { "views" => self.bind_show_views()?, - _ => return Err(DatabaseError::UnsupportedStmt(stmt.to_string())) + _ => return Err(DatabaseError::UnsupportedStmt(stmt.to_string())), } - }, + } Statement::Copy { source, to, diff --git a/src/execution/dql/mod.rs b/src/execution/dql/mod.rs index 3ba60d4c..bcc05555 100644 --- a/src/execution/dql/mod.rs +++ b/src/execution/dql/mod.rs @@ -10,10 +10,10 @@ 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; -pub(crate) mod show_view; #[cfg(test)] pub(crate) mod test { diff --git a/src/execution/dql/show_view.rs b/src/execution/dql/show_view.rs index 08e91ab7..bbfafdc2 100644 --- a/src/execution/dql/show_view.rs +++ b/src/execution/dql/show_view.rs @@ -1,3 +1,4 @@ +use crate::catalog::view::View; use crate::catalog::TableMeta; use crate::execution::{Executor, ReadExecutor}; use crate::storage::{StatisticsMetaCache, TableCache, Transaction, ViewCache}; @@ -5,14 +6,13 @@ use crate::throw; use crate::types::tuple::Tuple; use crate::types::value::{DataValue, Utf8Type}; use sqlparser::ast::CharLengthUnits; -use crate::catalog::view::View; pub struct ShowViews; impl<'a, T: Transaction + 'a> ReadExecutor<'a, T> for ShowViews { fn execute( self, - (TableCache,_,_): (&'a TableCache, &'a ViewCache, &'a StatisticsMetaCache), + (TableCache, _, _): (&'a TableCache, &'a ViewCache, &'a StatisticsMetaCache), transaction: *mut T, ) -> Executor<'a> { Box::new( diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 3c13fd23..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; @@ -42,7 +43,6 @@ use crate::storage::{StatisticsMetaCache, TableCache, Transaction, ViewCache}; use crate::types::index::IndexInfo; use crate::types::tuple::Tuple; use std::ops::Coroutine; -use crate::execution::dql::show_view::ShowViews; pub type Executor<'a> = Box, Return = ()> + 'a + Unpin>; diff --git a/src/storage/mod.rs b/src/storage/mod.rs index 92c3e531..24476cca 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -16,13 +16,13 @@ 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; use std::ops::SubAssign; use std::sync::Arc; use std::vec::IntoIter; -use sqlparser::keywords::NULL; use ulid::Generator; pub(crate) type StatisticsMetaCache = SharedLruCache<(TableName, IndexId), StatisticsMeta>; From a894b7e6135035ba9407bdafff3139896e959ad2 Mon Sep 17 00:00:00 2001 From: wszhdshys <1925792291@qq.com> Date: Tue, 15 Jul 2025 12:49:09 +0800 Subject: [PATCH 3/3] feat: Show View --- src/binder/mod.rs | 11 ++++------- src/execution/dql/show_view.rs | 3 +-- src/storage/mod.rs | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/binder/mod.rs b/src/binder/mod.rs index 1ace1117..e4329da4 100644 --- a/src/binder/mod.rs +++ b/src/binder/mod.rs @@ -411,13 +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 } => { - let value = variable[0].value.clone(); - match &value[..] { - "views" => self.bind_show_views()?, - _ => return Err(DatabaseError::UnsupportedStmt(stmt.to_string())), - } - } + 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/execution/dql/show_view.rs b/src/execution/dql/show_view.rs index bbfafdc2..b16de4ce 100644 --- a/src/execution/dql/show_view.rs +++ b/src/execution/dql/show_view.rs @@ -1,5 +1,4 @@ use crate::catalog::view::View; -use crate::catalog::TableMeta; use crate::execution::{Executor, ReadExecutor}; use crate::storage::{StatisticsMetaCache, TableCache, Transaction, ViewCache}; use crate::throw; @@ -18,7 +17,7 @@ impl<'a, T: Transaction + 'a> ReadExecutor<'a, T> for ShowViews { Box::new( #[coroutine] move || { - let metas = throw!(unsafe { &mut (*transaction) }.view_metas(TableCache)); + let metas = throw!(unsafe { &mut (*transaction) }.views(TableCache)); for View { name, .. } in metas { let values = vec![DataValue::Utf8 { diff --git a/src/storage/mod.rs b/src/storage/mod.rs index 24476cca..838fc1e2 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -467,7 +467,7 @@ pub trait Transaction: Sized { })?)) } - fn view_metas(&self, table_cache: &TableCache) -> Result, DatabaseError> { + 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))?;