Skip to content

Commit a348db1

Browse files
authored
feat: Add 'show tables' functionality in SQL executor (#61)
* feat: Add 'show tables' functionality in SQL executor This commit introduces 'show tables' feature, allowing users to display table names in the database. Necessary changes were made in the execution module, database, binder, and storage to facilitate this feature. This includes addition of `ShowTables` struct and implementing the `Executor` trait for it, modifications in `Binder` to create a logical plan for 'show tables' commands, and adding `show_tables` function in storage to return a list of existing table names. Additionally, a 'ShowTablesOperator' was added in operator module to support operation, and new test cases were added to validate the modifications. * Remove hardcoded table insertions in table_codec.rs * feat(executor): add column count to `show_tables` function Functions `show_tables` in the Storage trait and its implementations in Kip and Memory now return a tuple containing table name and column count. The functions `encode_root_table` and `decode_root_table` in table_codec have been updated for the new format. These changes improve utility of `show_tables` by providing more detailed information.
1 parent 1853a9b commit a348db1

File tree

13 files changed

+223
-1
lines changed

13 files changed

+223
-1
lines changed

src/binder/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod delete;
88
mod drop_table;
99
mod truncate;
1010
mod distinct;
11+
mod show;
1112

1213
use std::collections::BTreeMap;
1314
use sqlparser::ast::{Ident, ObjectName, ObjectType, SetExpr, Statement};
@@ -121,7 +122,10 @@ impl<S: Storage> Binder<S> {
121122
Statement::Truncate { table_name, .. } => {
122123
self.bind_truncate(table_name).await?
123124
}
124-
_ => unimplemented!(),
125+
Statement::ShowTables { .. } => {
126+
self.bind_show_tables()?
127+
}
128+
_ => return Err(BindError::UnsupportedStmt(stmt.to_string())),
125129
};
126130
Ok(plan)
127131
}

src/binder/show.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use crate::binder::{Binder, BindError};
2+
use crate::planner::LogicalPlan;
3+
use crate::planner::operator::Operator;
4+
use crate::planner::operator::show::ShowTablesOperator;
5+
use crate::storage::Storage;
6+
7+
impl<S: Storage> Binder<S> {
8+
pub(crate) fn bind_show_tables(
9+
&mut self,
10+
) -> Result<LogicalPlan, BindError> {
11+
let plan = LogicalPlan {
12+
operator: Operator::Show(
13+
ShowTablesOperator {}
14+
),
15+
childrens: vec![],
16+
};
17+
Ok(plan)
18+
}
19+
}

src/catalog/column.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ impl ColumnCatalog {
2727
}
2828
}
2929

30+
pub(crate) fn new_dummy(column_name: String)-> ColumnCatalog {
31+
ColumnCatalog {
32+
id: 0,
33+
name: column_name,
34+
table_name: None,
35+
nullable: false,
36+
desc: ColumnDesc::new(LogicalType::Varchar(None), false),
37+
}
38+
}
39+
3040
pub(crate) fn datatype(&self) -> &LogicalType {
3141
&self.desc.column_datatype
3242
}

src/db.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,10 @@ mod test {
301301
println!("drop t1:");
302302
let _ = kipsql.run("drop table t1").await?;
303303

304+
println!("show tables:");
305+
let tuples_show_tables = kipsql.run("show tables").await?;
306+
println!("{}", create_table(&tuples_show_tables));
307+
304308
Ok(())
305309
}
306310
}

src/execution/executor/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub(crate) mod dql;
22
pub(crate)mod ddl;
33
pub(crate)mod dml;
4+
pub(crate) mod show;
45

56
use futures::stream::BoxStream;
67
use futures::TryStreamExt;
@@ -20,6 +21,7 @@ use crate::execution::executor::dql::projection::Projection;
2021
use crate::execution::executor::dql::seq_scan::SeqScan;
2122
use crate::execution::executor::dql::sort::Sort;
2223
use crate::execution::executor::dql::values::Values;
24+
use crate::execution::executor::show::show_table::ShowTables;
2325
use crate::execution::ExecutorError;
2426
use crate::planner::LogicalPlan;
2527
use crate::planner::operator::Operator;
@@ -103,6 +105,9 @@ pub fn build<S: Storage>(plan: LogicalPlan, storage: &S) -> BoxedExecutor {
103105
Operator::Truncate(op) => {
104106
Truncate::from(op).execute(storage)
105107
}
108+
Operator::Show(op) => {
109+
ShowTables::from(op).execute(storage)
110+
}
106111
}
107112
}
108113

src/execution/executor/show/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pub(crate) mod show_table;
2+
3+
4+
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use futures_async_stream::try_stream;
2+
use crate::execution::executor::{BoxedExecutor, Executor};
3+
use crate::execution::ExecutorError;
4+
use crate::planner::operator::show::ShowTablesOperator;
5+
use crate::storage::Storage;
6+
use crate::types::tuple::Tuple;
7+
use crate::catalog::ColumnCatalog;
8+
use crate::catalog::ColumnRef;
9+
use std::sync::Arc;
10+
use crate::types::value::{DataValue, ValueRef};
11+
12+
pub struct ShowTables {
13+
op: ShowTablesOperator,
14+
}
15+
16+
impl From<ShowTablesOperator> for ShowTables {
17+
fn from(op: ShowTablesOperator) -> Self {
18+
ShowTables {
19+
op
20+
}
21+
}
22+
}
23+
24+
impl<S: Storage> Executor<S> for ShowTables {
25+
fn execute(self, storage: &S) -> BoxedExecutor {
26+
self._execute(storage.clone())
27+
}
28+
}
29+
30+
impl ShowTables {
31+
#[try_stream(boxed, ok = Tuple, error = ExecutorError)]
32+
pub async fn _execute<S: Storage>(self, storage: S) {
33+
if let Some(tables) = storage.show_tables().await {
34+
for (table,column_count) in tables {
35+
let columns: Vec<ColumnRef> = vec![
36+
Arc::new(ColumnCatalog::new_dummy("TABLES".to_string())),
37+
Arc::new(ColumnCatalog::new_dummy("COLUMN_COUNT".to_string())),
38+
];
39+
let values: Vec<ValueRef> = vec![
40+
Arc::new(DataValue::Utf8(Some(table))),
41+
Arc::new(DataValue::UInt32(Some(column_count as u32))),
42+
];
43+
44+
yield Tuple {
45+
id: None,
46+
columns,
47+
values,
48+
};
49+
}
50+
}
51+
}
52+
}

src/planner/operator/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub mod update;
1212
pub mod delete;
1313
pub mod drop_table;
1414
pub mod truncate;
15+
pub mod show;
1516

1617
use itertools::Itertools;
1718
use crate::catalog::ColumnRef;
@@ -21,6 +22,7 @@ use crate::planner::operator::delete::DeleteOperator;
2122
use crate::planner::operator::drop_table::DropTableOperator;
2223
use crate::planner::operator::insert::InsertOperator;
2324
use crate::planner::operator::join::JoinCondition;
25+
use crate::planner::operator::show::ShowTablesOperator;
2426
use crate::planner::operator::truncate::TruncateOperator;
2527
use crate::planner::operator::update::UpdateOperator;
2628
use crate::planner::operator::values::ValuesOperator;
@@ -50,6 +52,8 @@ pub enum Operator {
5052
CreateTable(CreateTableOperator),
5153
DropTable(DropTableOperator),
5254
Truncate(TruncateOperator),
55+
// Show
56+
Show(ShowTablesOperator),
5357
}
5458

5559
impl Operator {

src/planner/operator/show.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#[derive(Debug, PartialEq, Clone)]
2+
pub struct ShowTablesOperator {}

src/storage/kip.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ impl Storage for KipStorage {
4949
{
5050
self.inner.set(key, value).await?;
5151
}
52+
53+
let (k, v)= TableCodec::encode_root_table(table_name.as_str(), table.columns.len())
54+
.ok_or(StorageError::Serialization)?;
55+
self.inner.set(k, v).await?;
56+
5257
self.cache.put(table_name.to_string(), table);
5358

5459
Ok(table_name)
@@ -72,6 +77,9 @@ impl Storage for KipStorage {
7277
for col_key in col_keys {
7378
tx.remove(&col_key)?
7479
}
80+
let (k, _) = TableCodec::encode_root_table(name.as_str(),0)
81+
.ok_or(StorageError::Serialization)?;
82+
tx.remove(&k)?;
7583
tx.commit().await?;
7684

7785
let _ = self.cache.remove(name);
@@ -139,6 +147,24 @@ impl Storage for KipStorage {
139147

140148
option
141149
}
150+
151+
async fn show_tables(&self) -> Option<Vec<(String,usize)>> {
152+
let mut tables = vec![];
153+
let (min, max) = TableCodec::root_table_bound();
154+
155+
let tx = self.inner.new_transaction().await;
156+
let mut iter = tx.iter(Bound::Included(&min), Bound::Included(&max)).ok()?;
157+
158+
while let Some((key, value_option)) = iter.try_next().ok().flatten() {
159+
if let Some(value) = value_option {
160+
if let Some((table_name, column_count)) = TableCodec::decode_root_table(&key, &value) {
161+
tables.push((table_name,column_count));
162+
}
163+
}
164+
}
165+
166+
Some(tables)
167+
}
142168
}
143169

144170
pub struct KipTable {

0 commit comments

Comments
 (0)