diff --git a/Cargo.lock b/Cargo.lock index 99c459f..3e24047 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -119,6 +119,7 @@ name = "bustubx-cli" version = "0.1.0" dependencies = [ "bustubx", + "rustyline", "tracing", "tracing-chrome", "tracing-subscriber", @@ -180,6 +181,15 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +[[package]] +name = "clipboard-win" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c57002a5d9be777c1ef967e33674dac9ebd310d8893e4e3437b14d5f0f6372cc" +dependencies = [ + "error-code", +] + [[package]] name = "colorchoice" version = "1.0.0" @@ -272,6 +282,12 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + [[package]] name = "enum-ordinalize" version = "3.1.15" @@ -295,12 +311,29 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "error-code" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "281e452d3bad4005426416cdba5ccfd4f5c1280e10099e21db27f7c1c28347fc" + [[package]] name = "fastrand" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +[[package]] +name = "fd-lock" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys 0.52.0", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -439,6 +472,15 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "humantime" version = "2.1.0" @@ -552,6 +594,26 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "libc", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -683,6 +745,16 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + [[package]] name = "redox_syscall" version = "0.3.5" @@ -749,6 +821,28 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +[[package]] +name = "rustyline" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02a2d683a4ac90aeef5b1013933f6d977bd37d51ff3f4dad829d4931a7e6be86" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "clipboard-win", + "fd-lock", + "home", + "libc", + "log", + "memchr", + "nix", + "radix_trie", + "unicode-segmentation", + "unicode-width", + "utf8parse", + "winapi", +] + [[package]] name = "ryu" version = "1.0.15" @@ -1073,6 +1167,12 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + [[package]] name = "unicode-width" version = "0.1.10" diff --git a/bustubx-cli/src/main.rs b/bustubx-cli/src/main.rs index 22e3b9e..ebc81eb 100644 --- a/bustubx-cli/src/main.rs +++ b/bustubx-cli/src/main.rs @@ -1,6 +1,7 @@ -use bustubx::database::Database; +use bustubx::Database; use rustyline::error::ReadlineError; use rustyline::{DefaultEditor, Result}; +use std::io::Write; use tracing::info; use tracing_chrome::ChromeLayerBuilder; use tracing_subscriber::fmt; diff --git a/bustubx/src/common/scalar.rs b/bustubx/src/common/scalar.rs index 9e788b8..3986774 100644 --- a/bustubx/src/common/scalar.rs +++ b/bustubx/src/common/scalar.rs @@ -1,5 +1,3 @@ -use std::fmt::Formatter; - use crate::catalog::DataType; #[derive(Debug, Clone, PartialEq, Eq)] @@ -10,6 +8,7 @@ pub enum ScalarValue { Int32(Option), Int64(Option), } + impl ScalarValue { pub fn new_empty(data_type: DataType) -> Self { match data_type { @@ -55,7 +54,6 @@ impl ScalarValue { DataType::Int64 => Self::Int64(Some(v.parse::().unwrap())), _ => panic!("Not implemented"), }, - // sqlparser::ast::Value::SingleQuotedString(_) => {} sqlparser::ast::Value::Boolean(b) => ScalarValue::Boolean(Some(*b)), _ => unreachable!(), } @@ -109,16 +107,19 @@ impl ScalarValue { } } -// TODO delete -// impl std::fmt::Display for ScalarValue { -// fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { -// match self { -// ScalarValue::Boolean(e) => write!(f, "{}", e)?, -// ScalarValue::Int8(e) => write!(f, "{}", e)?, -// ScalarValue::Int16(e) => write!(f, "{}", e)?, -// ScalarValue::Int32(e) => write!(f, "{}", e)?, -// ScalarValue::Int64(e) => write!(f, "{}", e)?, -// }; -// Ok(()) -// } -// } +impl std::fmt::Display for ScalarValue { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + ScalarValue::Boolean(None) => write!(f, "NULL"), + ScalarValue::Boolean(Some(v)) => write!(f, "{v}"), + ScalarValue::Int8(None) => write!(f, "NULL"), + ScalarValue::Int8(Some(v)) => write!(f, "{v}"), + ScalarValue::Int16(None) => write!(f, "NULL"), + ScalarValue::Int16(Some(v)) => write!(f, "{v}"), + ScalarValue::Int32(None) => write!(f, "NULL"), + ScalarValue::Int32(Some(v)) => write!(f, "{v}"), + ScalarValue::Int64(None) => write!(f, "NULL"), + ScalarValue::Int64(Some(v)) => write!(f, "{v}"), + } + } +} diff --git a/bustubx/src/lib.rs b/bustubx/src/lib.rs index dbaa731..ddb52b7 100644 --- a/bustubx/src/lib.rs +++ b/bustubx/src/lib.rs @@ -1,11 +1,15 @@ mod buffer; mod catalog; mod common; -pub mod database; -pub mod error; +mod database; +mod error; mod execution; mod expression; mod optimizer; mod parser; mod planner; mod storage; + +pub use database::Database; +pub use error::{BustubxError, BustubxResult}; +pub use storage::Tuple; diff --git a/tests/sqllogictest/src/lib.rs b/tests/sqllogictest/src/lib.rs index 6b688e8..9698e76 100644 --- a/tests/sqllogictest/src/lib.rs +++ b/tests/sqllogictest/src/lib.rs @@ -1,27 +1,45 @@ -use bustubx::database::Database; -use bustubx::error::BustubxError; +use bustubx::Database; +use bustubx::{BustubxError, Tuple}; use sqllogictest::{DBOutput, DefaultColumnType}; -use tempfile::TempDir; -pub struct Bustubx { +pub struct BustubxDB { db: Database, - tmp_dir: TempDir, } -impl Bustubx { +impl BustubxDB { pub fn new() -> Self { - let tmp_dir = TempDir::new().unwrap(); - let db = Database::new_on_disk(tmp_dir.path().to_str().unwrap()); - Self { db, tmp_dir } + let db = Database::new_temp(); + Self { db } } } -#[async_trait::async_trait] -impl sqllogictest::AsyncDB for &Bustubx { +fn tuples_to_sqllogictest_string(tuples: Vec) -> Vec> { + todo!() +} + +impl sqllogictest::DB for BustubxDB { type Error = BustubxError; type ColumnType = DefaultColumnType; - async fn run(&mut self, sql: &str) -> Result, Self::Error> { - todo!() + fn run(&mut self, sql: &str) -> Result, Self::Error> { + let is_query_sql = { + let lower_sql = sql.trim_start().to_ascii_lowercase(); + lower_sql.starts_with("select") + }; + let tuples = self.db.run(sql)?; + if tuples.is_empty() { + if is_query_sql { + return Ok(DBOutput::Rows { + types: vec![], + rows: vec![], + }); + } else { + return Ok(DBOutput::StatementComplete(0)); + } + } + // TODO fix type count + let types = vec![DefaultColumnType::Any; 3]; + let rows = tuples_to_sqllogictest_string(tuples); + Ok(DBOutput::Rows { types, rows }) } }