From 241f835b523014f1b41368da3de247dfde3f59fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=9E=97=E4=BC=9F?= Date: Fri, 2 Feb 2024 12:48:17 +0800 Subject: [PATCH] Pretty print tuples --- Cargo.lock | 35 ------------------- bustubx-cli/src/main.rs | 12 +++++-- bustubx/Cargo.toml | 3 -- bustubx/src/buffer/mod.rs | 2 +- bustubx/src/buffer/page.rs | 1 + bustubx/src/common/config.rs | 11 +++++- bustubx/src/common/mod.rs | 3 +- bustubx/src/common/util.rs | 33 +++++++++-------- bustubx/src/database.rs | 6 ++-- .../execution/physical_plan/create_index.rs | 5 +-- .../execution/physical_plan/create_table.rs | 2 +- bustubx/src/execution/physical_plan/insert.rs | 24 ++++++------- .../src/execution/physical_plan/seq_scan.rs | 2 +- bustubx/src/expression/column.rs | 2 +- bustubx/src/lib.rs | 1 + .../src/planner/logical_plan/create_index.rs | 2 +- .../src/planner/logical_plan/create_table.rs | 2 +- bustubx/src/planner/logical_plan/insert.rs | 2 +- bustubx/src/planner/logical_plan/mod.rs | 7 ++-- .../src/planner/logical_plan/table_scan.rs | 2 +- .../src/planner/logical_planner/bind_expr.rs | 2 +- .../logical_planner/logical_planner.rs | 2 +- bustubx/src/storage/index.rs | 4 +-- bustubx/src/storage/index_page.rs | 7 ++-- bustubx/src/storage/table_heap.rs | 7 ++-- 25 files changed, 81 insertions(+), 98 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d91964..28d0b95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,13 +106,10 @@ dependencies = [ "derive-with", "itertools 0.11.0", "lazy_static", - "petgraph", "sqlparser", "tempfile", "thiserror", "tracing", - "tracing-chrome", - "tracing-subscriber", ] [[package]] @@ -345,12 +342,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - [[package]] name = "fs-err" version = "2.11.0" @@ -465,12 +456,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "heck" version = "0.4.1" @@ -498,16 +483,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown", -] - [[package]] name = "itertools" version = "0.10.5" @@ -716,16 +691,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "petgraph" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" -dependencies = [ - "fixedbitset", - "indexmap", -] - [[package]] name = "pin-project-lite" version = "0.2.13" diff --git a/bustubx-cli/src/main.rs b/bustubx-cli/src/main.rs index 573040f..4e026ea 100644 --- a/bustubx-cli/src/main.rs +++ b/bustubx-cli/src/main.rs @@ -1,4 +1,4 @@ -use bustubx::Database; +use bustubx::{pretty_format_tuples, BustubxResult, Database}; use rustyline::error::ReadlineError; use rustyline::{DefaultEditor, Result}; use std::io::Write; @@ -35,7 +35,15 @@ fn main() -> Result<()> { println!("bye!"); break; } - let _ = db.run(&line); + let result = db.run(&line); + match result { + Ok(tuples) => { + if !tuples.is_empty() { + println!("{}", pretty_format_tuples(&tuples)) + } + } + Err(e) => println!("{}", e), + } } Err(ReadlineError::Interrupted) => { println!("CTRL-C"); diff --git a/bustubx/Cargo.toml b/bustubx/Cargo.toml index e53556c..59e309c 100644 --- a/bustubx/Cargo.toml +++ b/bustubx/Cargo.toml @@ -13,14 +13,11 @@ doctest = false [dependencies] sqlparser = "0.34.0" -petgraph = "0.6.3" lazy_static = "1.4.0" itertools = "0.11.0" comfy-table = "7.0.1" derive-new = "0.5.9" tracing = "0.1" -tracing-subscriber = "0.3" -tracing-chrome = "0.7.1" thiserror = "1.0.56" tempfile = "3" derive-with = "0.5.0" \ No newline at end of file diff --git a/bustubx/src/buffer/mod.rs b/bustubx/src/buffer/mod.rs index fd498b2..d8e6266 100644 --- a/bustubx/src/buffer/mod.rs +++ b/bustubx/src/buffer/mod.rs @@ -3,4 +3,4 @@ mod page; mod replacer; pub use buffer_pool::BufferPoolManager; -pub use page::{Page, PageId}; +pub use page::{Page, PageId, INVALID_PAGE_ID}; diff --git a/bustubx/src/buffer/page.rs b/bustubx/src/buffer/page.rs index 2d0e4ed..1b39021 100644 --- a/bustubx/src/buffer/page.rs +++ b/bustubx/src/buffer/page.rs @@ -1,6 +1,7 @@ use crate::common::config::BUSTUBX_PAGE_SIZE; pub type PageId = u32; +pub const INVALID_PAGE_ID: PageId = u32::MAX; #[derive(Debug, Clone)] pub struct Page { diff --git a/bustubx/src/common/config.rs b/bustubx/src/common/config.rs index bf6f996..d29c838 100644 --- a/bustubx/src/common/config.rs +++ b/bustubx/src/common/config.rs @@ -1,10 +1,19 @@ use crate::buffer::PageId; +use crate::catalog::{Column, DataType, Schema, SchemaRef}; +use std::sync::Arc; // 数据页的大小(字节) pub const BUSTUBX_PAGE_SIZE: usize = 4096; -pub const INVALID_PAGE_ID: PageId = std::u32::MAX; // table heap对应的缓冲池的大小(页) pub const TABLE_HEAP_BUFFER_POOL_SIZE: usize = 100; pub type TransactionId = u32; + +lazy_static::lazy_static! { + pub static ref EMPTY_SCHEMA_REF: SchemaRef = Arc::new(Schema::empty()); + + pub static ref INSERT_OUTPUT_SCHEMA_REF: SchemaRef = Arc::new(Schema::new( + vec![Column::new("insert_rows".to_string(), DataType::Int32)] + )); +} diff --git a/bustubx/src/common/mod.rs b/bustubx/src/common/mod.rs index 754cd60..50144ea 100644 --- a/bustubx/src/common/mod.rs +++ b/bustubx/src/common/mod.rs @@ -1,7 +1,8 @@ pub mod config; pub mod rid; mod scalar; -pub mod table_ref; +mod table_ref; pub mod util; pub use scalar::ScalarValue; +pub use table_ref::TableReference; diff --git a/bustubx/src/common/util.rs b/bustubx/src/common/util.rs index b1ad637..fc8f574 100644 --- a/bustubx/src/common/util.rs +++ b/bustubx/src/common/util.rs @@ -1,25 +1,30 @@ use comfy_table::Cell; -use crate::{catalog::Schema, storage::Tuple}; +use crate::storage::Tuple; + +pub fn pretty_format_tuples(tuples: &Vec) -> comfy_table::Table { + let mut table = comfy_table::Table::new(); + table.load_preset("||--+-++| ++++++"); -pub fn print_tuples(tuples: &Vec, schema: &Schema) { if tuples.is_empty() { - return; + return table; } - let mut headers = Vec::new(); - for column in &schema.columns { - headers.push(Cell::new(column.name.clone())); + + let schema = &tuples[0].schema; + + let mut header = Vec::new(); + for column in schema.columns.iter() { + header.push(Cell::new(column.name.clone())); } - let mut table = comfy_table::Table::new(); - table.set_header(headers); + table.set_header(header); for tuple in tuples { - let mut row = Vec::new(); - tuple.all_values(schema).iter().for_each(|v| { - row.push(Cell::new(format!("{v:?}"))); - }); - table.add_row(row); + let mut cells = Vec::new(); + for value in tuple.data.iter() { + cells.push(Cell::new(format!("{value}"))); + } + table.add_row(cells); } - println!("{}", table); + table } diff --git a/bustubx/src/database.rs b/bustubx/src/database.rs index 1736bbd..49effb5 100644 --- a/bustubx/src/database.rs +++ b/bustubx/src/database.rs @@ -51,18 +51,18 @@ impl Database { pub fn run(&mut self, sql: &str) -> BustubxResult> { let logical_plan = self.build_logical_plan(sql)?; - println!("{:?}", logical_plan); + // println!("{:?}", logical_plan); // logical plan -> physical plan let physical_plan = PhysicalPlanner::new().create_physical_plan(logical_plan); - println!("{:?}", physical_plan); + // println!("{:?}", physical_plan); let execution_ctx = ExecutionContext::new(&mut self.catalog); let mut execution_engine = ExecutionEngine { context: execution_ctx, }; let tuples = execution_engine.execute(Arc::new(physical_plan))?; - println!("execution result: {:?}", tuples); + // println!("execution result: {:?}", tuples); Ok(tuples) } diff --git a/bustubx/src/execution/physical_plan/create_index.rs b/bustubx/src/execution/physical_plan/create_index.rs index 4ec9a16..e02b5ef 100644 --- a/bustubx/src/execution/physical_plan/create_index.rs +++ b/bustubx/src/execution/physical_plan/create_index.rs @@ -1,5 +1,6 @@ use crate::catalog::SchemaRef; -use crate::common::table_ref::TableReference; +use crate::common::config::EMPTY_SCHEMA_REF; +use crate::common::TableReference; use crate::planner::logical_plan::OrderByExpr; use crate::{ catalog::Schema, @@ -23,7 +24,7 @@ impl VolcanoExecutor for PhysicalCreateIndex { Ok(None) } fn output_schema(&self) -> SchemaRef { - Arc::new(Schema::empty()) + EMPTY_SCHEMA_REF.clone() } } diff --git a/bustubx/src/execution/physical_plan/create_table.rs b/bustubx/src/execution/physical_plan/create_table.rs index 79478e0..48b7d78 100644 --- a/bustubx/src/execution/physical_plan/create_table.rs +++ b/bustubx/src/execution/physical_plan/create_table.rs @@ -1,5 +1,5 @@ use crate::catalog::SchemaRef; -use crate::common::table_ref::TableReference; +use crate::common::TableReference; use crate::{ catalog::Schema, execution::{ExecutionContext, VolcanoExecutor}, diff --git a/bustubx/src/execution/physical_plan/insert.rs b/bustubx/src/execution/physical_plan/insert.rs index 48469b3..61e8f77 100644 --- a/bustubx/src/execution/physical_plan/insert.rs +++ b/bustubx/src/execution/physical_plan/insert.rs @@ -1,7 +1,9 @@ use std::sync::{atomic::AtomicU32, Arc}; +use tracing::debug; use crate::catalog::SchemaRef; -use crate::common::table_ref::TableReference; +use crate::common::config::INSERT_OUTPUT_SCHEMA_REF; +use crate::common::TableReference; use crate::{ catalog::{Column, DataType, Schema}, common::ScalarValue, @@ -39,27 +41,28 @@ impl PhysicalInsert { } impl VolcanoExecutor for PhysicalInsert { fn init(&self, context: &mut ExecutionContext) -> BustubxResult<()> { - println!("init insert executor"); + debug!("init insert executor"); + self.input.init(context)?; self.insert_rows .store(0, std::sync::atomic::Ordering::SeqCst); - self.input.init(context) + Ok(()) } fn next(&self, context: &mut ExecutionContext) -> BustubxResult> { loop { let next_tuple = self.input.next(context)?; if next_tuple.is_none() { // only return insert_rows when input exhausted - if self.insert_rows.load(std::sync::atomic::Ordering::SeqCst) == 0 { - return Ok(None); + return if self.insert_rows.load(std::sync::atomic::Ordering::SeqCst) == 0 { + Ok(None) } else { let insert_rows = self.insert_rows.load(std::sync::atomic::Ordering::SeqCst); self.insert_rows .store(0, std::sync::atomic::Ordering::SeqCst); - return Ok(Some(Tuple::new( + Ok(Some(Tuple::new( self.output_schema(), vec![ScalarValue::Int32(Some(insert_rows as i32))], - ))); - } + ))) + }; } let tuple = next_tuple.unwrap(); @@ -93,10 +96,7 @@ impl VolcanoExecutor for PhysicalInsert { } fn output_schema(&self) -> SchemaRef { - Arc::new(Schema::new(vec![Column::new( - "insert_rows".to_string(), - DataType::Int32, - )])) + INSERT_OUTPUT_SCHEMA_REF.clone() } } diff --git a/bustubx/src/execution/physical_plan/seq_scan.rs b/bustubx/src/execution/physical_plan/seq_scan.rs index 0239c10..206688a 100644 --- a/bustubx/src/execution/physical_plan/seq_scan.rs +++ b/bustubx/src/execution/physical_plan/seq_scan.rs @@ -1,7 +1,7 @@ use std::sync::Mutex; use crate::catalog::SchemaRef; -use crate::common::table_ref::TableReference; +use crate::common::TableReference; use crate::{ execution::{ExecutionContext, VolcanoExecutor}, storage::{TableIterator, Tuple}, diff --git a/bustubx/src/expression/column.rs b/bustubx/src/expression/column.rs index f00ea90..346920b 100644 --- a/bustubx/src/expression/column.rs +++ b/bustubx/src/expression/column.rs @@ -1,7 +1,7 @@ use crate::catalog::Schema; use crate::catalog::{Column, DataType}; -use crate::common::table_ref::TableReference; use crate::common::ScalarValue; +use crate::common::TableReference; use crate::error::{BustubxError, BustubxResult}; use crate::expression::ExprTrait; use crate::storage::Tuple; diff --git a/bustubx/src/lib.rs b/bustubx/src/lib.rs index ddb52b7..624b1f4 100644 --- a/bustubx/src/lib.rs +++ b/bustubx/src/lib.rs @@ -10,6 +10,7 @@ mod parser; mod planner; mod storage; +pub use common::util::pretty_format_tuples; pub use database::Database; pub use error::{BustubxError, BustubxResult}; pub use storage::Tuple; diff --git a/bustubx/src/planner/logical_plan/create_index.rs b/bustubx/src/planner/logical_plan/create_index.rs index a9d8a54..c02b482 100644 --- a/bustubx/src/planner/logical_plan/create_index.rs +++ b/bustubx/src/planner/logical_plan/create_index.rs @@ -1,5 +1,5 @@ use crate::catalog::SchemaRef; -use crate::common::table_ref::TableReference; +use crate::common::TableReference; use crate::planner::logical_plan::OrderByExpr; #[derive(derive_new::new, Debug, Clone)] diff --git a/bustubx/src/planner/logical_plan/create_table.rs b/bustubx/src/planner/logical_plan/create_table.rs index 2f6b265..aad37d8 100644 --- a/bustubx/src/planner/logical_plan/create_table.rs +++ b/bustubx/src/planner/logical_plan/create_table.rs @@ -1,5 +1,5 @@ use crate::catalog::Column; -use crate::common::table_ref::TableReference; +use crate::common::TableReference; #[derive(Debug, Clone)] pub struct CreateTable { diff --git a/bustubx/src/planner/logical_plan/insert.rs b/bustubx/src/planner/logical_plan/insert.rs index 1f87d02..2226264 100644 --- a/bustubx/src/planner/logical_plan/insert.rs +++ b/bustubx/src/planner/logical_plan/insert.rs @@ -1,5 +1,5 @@ use crate::catalog::SchemaRef; -use crate::common::table_ref::TableReference; +use crate::common::TableReference; use crate::planner::logical_plan::LogicalPlan; use std::sync::Arc; diff --git a/bustubx/src/planner/logical_plan/mod.rs b/bustubx/src/planner/logical_plan/mod.rs index 681e829..7168fcc 100644 --- a/bustubx/src/planner/logical_plan/mod.rs +++ b/bustubx/src/planner/logical_plan/mod.rs @@ -12,6 +12,7 @@ mod util; mod values; use crate::catalog::SchemaRef; +use crate::common::config::{EMPTY_SCHEMA_REF, INSERT_OUTPUT_SCHEMA_REF}; pub use create_index::CreateIndex; pub use create_table::CreateTable; pub use empty_relation::EmptyRelation; @@ -43,10 +44,10 @@ pub enum LogicalPlan { impl LogicalPlan { pub fn schema(&self) -> &SchemaRef { match self { - LogicalPlan::CreateTable(_) => todo!(), - LogicalPlan::CreateIndex(_) => todo!(), + LogicalPlan::CreateTable(_) => &EMPTY_SCHEMA_REF, + LogicalPlan::CreateIndex(_) => &EMPTY_SCHEMA_REF, LogicalPlan::Filter(Filter { input, .. }) => input.schema(), - LogicalPlan::Insert(_) => todo!(), + LogicalPlan::Insert(_) => &INSERT_OUTPUT_SCHEMA_REF, LogicalPlan::Join(Join { schema, .. }) => schema, LogicalPlan::Limit(Limit { input, .. }) => input.schema(), LogicalPlan::Project(Project { schema, .. }) => schema, diff --git a/bustubx/src/planner/logical_plan/table_scan.rs b/bustubx/src/planner/logical_plan/table_scan.rs index bd13444..a2edb63 100644 --- a/bustubx/src/planner/logical_plan/table_scan.rs +++ b/bustubx/src/planner/logical_plan/table_scan.rs @@ -1,5 +1,5 @@ use crate::catalog::SchemaRef; -use crate::common::table_ref::TableReference; +use crate::common::TableReference; use crate::expression::Expr; #[derive(derive_new::new, Debug, Clone)] diff --git a/bustubx/src/planner/logical_planner/bind_expr.rs b/bustubx/src/planner/logical_planner/bind_expr.rs index 8e4151d..df3fdaf 100644 --- a/bustubx/src/planner/logical_planner/bind_expr.rs +++ b/bustubx/src/planner/logical_planner/bind_expr.rs @@ -1,4 +1,4 @@ -use crate::common::table_ref::TableReference; +use crate::common::TableReference; use crate::expression::{BinaryExpr, ColumnExpr, Expr, Literal}; use crate::planner::LogicalPlanner; use crate::{BustubxError, BustubxResult}; diff --git a/bustubx/src/planner/logical_planner/logical_planner.rs b/bustubx/src/planner/logical_planner/logical_planner.rs index e238f7d..20bb0d2 100644 --- a/bustubx/src/planner/logical_planner/logical_planner.rs +++ b/bustubx/src/planner/logical_planner/logical_planner.rs @@ -1,7 +1,7 @@ use crate::{BustubxError, BustubxResult}; use crate::catalog::Catalog; -use crate::common::table_ref::TableReference; +use crate::common::TableReference; use crate::planner::logical_plan::{LogicalPlan, OrderByExpr}; pub struct PlannerContext<'a> { diff --git a/bustubx/src/storage/index.rs b/bustubx/src/storage/index.rs index 1a477b8..60545e3 100644 --- a/bustubx/src/storage/index.rs +++ b/bustubx/src/storage/index.rs @@ -1,12 +1,12 @@ use std::collections::VecDeque; use std::sync::Arc; -use crate::buffer::PageId; +use crate::buffer::{PageId, INVALID_PAGE_ID}; use crate::catalog::SchemaRef; use crate::{ buffer::BufferPoolManager, catalog::Schema, - common::{config::INVALID_PAGE_ID, rid::Rid}, + common::rid::Rid, storage::index_page::{BPlusTreeInternalPage, BPlusTreeLeafPage, BPlusTreePage}, }; diff --git a/bustubx/src/storage/index_page.rs b/bustubx/src/storage/index_page.rs index 594d14e..b7f2ffe 100644 --- a/bustubx/src/storage/index_page.rs +++ b/bustubx/src/storage/index_page.rs @@ -1,14 +1,11 @@ use std::mem::size_of; use super::Tuple; -use crate::buffer::PageId; +use crate::buffer::{PageId, INVALID_PAGE_ID}; use crate::catalog::SchemaRef; use crate::{ catalog::Schema, - common::{ - config::{BUSTUBX_PAGE_SIZE, INVALID_PAGE_ID}, - rid::Rid, - }, + common::{config::BUSTUBX_PAGE_SIZE, rid::Rid}, }; pub const INTERNAL_PAGE_HEADER_SIZE: usize = 4 + 4 + 4; diff --git a/bustubx/src/storage/table_heap.rs b/bustubx/src/storage/table_heap.rs index 223b092..bb790d0 100644 --- a/bustubx/src/storage/table_heap.rs +++ b/bustubx/src/storage/table_heap.rs @@ -1,9 +1,6 @@ -use crate::buffer::PageId; +use crate::buffer::{PageId, INVALID_PAGE_ID}; use crate::catalog::SchemaRef; -use crate::{ - buffer::BufferPoolManager, - common::{config::INVALID_PAGE_ID, rid::Rid}, -}; +use crate::{buffer::BufferPoolManager, common::rid::Rid}; use super::{ table_page::TablePage,