Compare commits
6 Commits
9eab0248c4
...
c5f31a9922
Author | SHA1 | Date | |
---|---|---|---|
c5f31a9922 | |||
5c086c10b9 | |||
ef7a802993 | |||
b4a86dca9f | |||
53870fecce | |||
c4ce04d700 |
168
Cargo.lock
generated
168
Cargo.lock
generated
@ -8,14 +8,81 @@ version = "1.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "dbonk"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.66"
|
||||
@ -34,6 +101,28 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
|
||||
dependencies = [
|
||||
"bitflags 2.4.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.28"
|
||||
@ -45,6 +134,19 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"redox_syscall",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.44"
|
||||
@ -70,3 +172,69 @@ name = "unicode-ident"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
|
@ -6,3 +6,6 @@ edition = "2021"
|
||||
[dependencies]
|
||||
anyhow = "1.0.72"
|
||||
thiserror = "1.0.44"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.7.1"
|
||||
|
40
src/cursor.rs
Normal file
40
src/cursor.rs
Normal file
@ -0,0 +1,40 @@
|
||||
use crate::table::Table;
|
||||
|
||||
pub type Position = (usize, usize);
|
||||
|
||||
pub struct Cursor<'a> {
|
||||
pub table: &'a mut Table,
|
||||
pub row_num: usize,
|
||||
pub end_of_table: bool,
|
||||
}
|
||||
|
||||
impl<'a> Cursor<'a> {
|
||||
pub fn at_table_start(table: &'a mut Table) -> Self {
|
||||
let end_of_table = table.row_count == 0;
|
||||
Self {
|
||||
table,
|
||||
row_num: 0,
|
||||
end_of_table,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn at_table_end(table: &'a mut Table) -> Self {
|
||||
let row_count = table.row_count;
|
||||
Self {
|
||||
table,
|
||||
row_num: row_count,
|
||||
end_of_table: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn position(&self) -> Position {
|
||||
self.table.row_slot(self.row_num)
|
||||
}
|
||||
|
||||
pub fn advance(&mut self) {
|
||||
self.row_num += 1;
|
||||
if self.row_num >= self.table.row_count {
|
||||
self.end_of_table = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
pub mod cursor;
|
||||
pub mod layout;
|
||||
pub mod pager;
|
||||
pub mod row;
|
||||
|
11
src/pager.rs
11
src/pager.rs
@ -1,9 +1,10 @@
|
||||
use std::{
|
||||
fs::{File, OpenOptions},
|
||||
os::unix::prelude::FileExt,
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use crate::layout::*;
|
||||
use crate::{cursor::Position, layout::*};
|
||||
use anyhow::Result;
|
||||
use thiserror::Error;
|
||||
|
||||
@ -23,7 +24,7 @@ pub struct Pager {
|
||||
}
|
||||
|
||||
impl Pager {
|
||||
pub fn new(file_path: &str) -> Result<Self> {
|
||||
pub fn new<T: AsRef<Path>>(file_path: T) -> Result<Self> {
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
@ -41,7 +42,7 @@ impl Pager {
|
||||
metadata.len() as usize
|
||||
}
|
||||
|
||||
pub fn row_location(&self, row_num: usize) -> (usize, usize) {
|
||||
pub fn row_location(&self, row_num: usize) -> Position {
|
||||
let page_num = row_num / ROWS_PER_PAGE;
|
||||
let row_offset = row_num % ROWS_PER_PAGE;
|
||||
let byte_offset = row_offset * ROW_SIZE;
|
||||
@ -61,12 +62,12 @@ impl Pager {
|
||||
num_pages += 1
|
||||
}
|
||||
|
||||
if page_num <= num_pages {
|
||||
let mut page: Page = [0; PAGE_SIZE];
|
||||
if page_num <= num_pages {
|
||||
let offset: u64 = (page_num * PAGE_SIZE).try_into()?;
|
||||
self.file.read_at(&mut page, offset)?;
|
||||
self.pages[page_num] = Some(page);
|
||||
}
|
||||
self.pages[page_num] = Some(page);
|
||||
}
|
||||
|
||||
Ok(self.pages[page_num].as_mut().unwrap())
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::{
|
||||
cursor::Cursor,
|
||||
layout::{ROW_SIZE, TABLE_MAX_ROWS},
|
||||
row::{Row, RowBytes},
|
||||
table::Table,
|
||||
@ -6,8 +7,6 @@ use crate::{
|
||||
use anyhow::Result;
|
||||
use thiserror::Error;
|
||||
|
||||
type FilteredRows = Vec<Row>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum StatementType {
|
||||
Insert(Box<Row>),
|
||||
@ -73,23 +72,69 @@ pub fn execute_insert(row: Row, table: &mut Table) -> Result<()> {
|
||||
return Err(ExecutionError::TableFull.into());
|
||||
}
|
||||
|
||||
let cursor = Cursor::at_table_end(table);
|
||||
let bytes: RowBytes = row.into();
|
||||
let (page_num, offset) = table.row_slot(table.row_count);
|
||||
|
||||
let (page_num, offset) = cursor.position();
|
||||
let page = table.pager.page(page_num)?;
|
||||
// let page = table.pager.pages[page_num].as_mut().unwrap();
|
||||
page[offset..offset + ROW_SIZE].copy_from_slice(&bytes);
|
||||
table.row_count += 1;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn execute_select(table: &mut Table) -> Result<FilteredRows> {
|
||||
let mut rows: FilteredRows = vec![];
|
||||
for i in 0..table.row_count {
|
||||
let (page_num, offset) = table.row_slot(i);
|
||||
let page = table.pager.page(page_num)?;
|
||||
pub fn execute_select(table: &mut Table) -> Result<Vec<Row>> {
|
||||
let mut rows: Vec<Row> = vec![];
|
||||
let mut cursor = Cursor::at_table_start(table);
|
||||
while !cursor.end_of_table {
|
||||
let (page_num, offset) = cursor.position();
|
||||
let page = cursor.table.pager.page(page_num)?;
|
||||
let row: RowBytes = page[offset..offset + ROW_SIZE].try_into()?;
|
||||
rows.push(row.into());
|
||||
cursor.advance();
|
||||
}
|
||||
|
||||
Ok(rows)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{pager::Pager, row::Row, table::Table};
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
#[test]
|
||||
fn execute_select_with_data_succeeds() {
|
||||
let file = NamedTempFile::new_in("target").unwrap();
|
||||
let pager = Pager::new(file.path()).unwrap();
|
||||
let mut table = Table::new(pager);
|
||||
for _ in 0..5 {
|
||||
execute_insert(Row::default(), &mut table).unwrap();
|
||||
}
|
||||
let rows = execute_select(&mut table).unwrap();
|
||||
assert_eq!(rows.len(), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn execute_insert_exceeding_row_limit_fails() {
|
||||
let file = NamedTempFile::new_in("target").unwrap();
|
||||
let pager = Pager::new(file.path()).unwrap();
|
||||
let mut table = Table::new(pager);
|
||||
for _ in 0..TABLE_MAX_ROWS {
|
||||
let row = Row::new(u16::MAX, "a".repeat(32).as_str(), "a".repeat(255).as_str());
|
||||
execute_insert(row, &mut table).unwrap();
|
||||
}
|
||||
let result = execute_insert(Row::default(), &mut table);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn execute_insert_input_exceeding_length_fails() {
|
||||
let file = NamedTempFile::new_in("target").unwrap();
|
||||
let pager = Pager::new(file.path()).unwrap();
|
||||
let mut table = Table::new(pager);
|
||||
let row = Row::new(u16::MAX, "a".repeat(33).as_str(), "a".repeat(256).as_str());
|
||||
let result = execute_insert(row, &mut table);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{layout::*, pager::Pager};
|
||||
use crate::{cursor::Position, layout::*, pager::Pager};
|
||||
|
||||
pub struct Table {
|
||||
pub row_count: usize,
|
||||
@ -11,7 +11,7 @@ impl Table {
|
||||
Self { row_count, pager }
|
||||
}
|
||||
|
||||
pub fn row_slot(&self, index: usize) -> (usize, usize) {
|
||||
pub fn row_slot(&self, index: usize) -> Position {
|
||||
self.pager.row_location(index)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user