diff --git a/core/lib.rs b/core/lib.rs index 4f209a4c7..cf7a1ff54 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -20,6 +20,11 @@ impl Database { pub fn open(io: Arc, path: &str) -> Result { let pager = Arc::new(Pager::open(io.clone(), path)?); let schema = Arc::new(Schema::new()); + let conn = Connection { + pager: pager.clone(), + schema: schema.clone(), + }; + conn.query("SELECT * FROM sqlite_schema")?; Ok(Database { pager, schema }) } @@ -37,6 +42,38 @@ pub struct Connection { } impl Connection { + pub fn query(&self, sql: impl Into) -> Result<()> { + let sql = sql.into(); + let mut parser = Parser::new(sql.as_bytes()); + let cmd = parser.next()?; + if let Some(cmd) = cmd { + match cmd { + Cmd::Stmt(stmt) => { + let mut program = vdbe::translate(self.pager.clone(), &self.schema, stmt)?; + loop { + let result = program.step()?; + match result { + vdbe::StepResult::Row => { + let mut row = Vec::new(); + for i in 0..program.column_count() { + row.push(program.column(i).unwrap().to_string()); + } + println!("{:?}", row); + } + vdbe::StepResult::IO => todo!(), + vdbe::StepResult::Done => break, + } + } + } + Cmd::Explain(stmt) => { + todo!(); + } + Cmd::ExplainQueryPlan(_stmt) => todo!(), + } + } + Ok(()) + } + pub fn execute(&self, sql: impl Into) -> Result<()> { let sql = sql.into(); let mut parser = Parser::new(sql.as_bytes()); @@ -44,13 +81,13 @@ impl Connection { if let Some(cmd) = cmd { match cmd { Cmd::Explain(stmt) => { - let program = vdbe::translate(&self.schema, stmt)?; + let program = vdbe::translate(self.pager.clone(), &self.schema, stmt)?; program.explain(); } Cmd::ExplainQueryPlan(_stmt) => todo!(), Cmd::Stmt(stmt) => { - let mut program = vdbe::translate(&self.schema, stmt)?; - program.step(self.pager.clone())?; + let mut program = vdbe::translate(self.pager.clone(), &self.schema, stmt)?; + program.step()?; } } } diff --git a/core/pager.rs b/core/pager.rs index 311df505e..f30ed226d 100644 --- a/core/pager.rs +++ b/core/pager.rs @@ -1,13 +1,16 @@ use crate::buffer_pool; use crate::buffer_pool::BufferPool; use crate::sqlite3_ondisk; +use crate::sqlite3_ondisk::BTreePage; +use crate::DatabaseRef; use crate::IO; use anyhow::Result; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; pub struct Pager { - _io: Arc, - _buffer_pool: BufferPool, + io: Arc, + database_ref: DatabaseRef, + buffer_pool: Arc>, } impl Pager { @@ -15,11 +18,21 @@ impl Pager { let database_ref = io.open(path)?; let db_header = sqlite3_ondisk::read_database_header(io.clone(), database_ref)?; let page_size = db_header.page_size as usize; - let mut buffer_pool = buffer_pool::BufferPool::new(page_size); - let _ = sqlite3_ondisk::read_btree_page(io.clone(), database_ref, &mut buffer_pool, 1)?; + let buffer_pool = Arc::new(Mutex::new(buffer_pool::BufferPool::new(page_size))); Ok(Self { - _io: io, - _buffer_pool: buffer_pool, + io, + database_ref, + buffer_pool, }) } + + pub fn read_page(&self, page_idx: usize) -> Result { + let mut buffer_pool = self.buffer_pool.lock().unwrap(); + sqlite3_ondisk::read_btree_page( + self.io.clone(), + self.database_ref, + &mut buffer_pool, + page_idx, + ) + } } diff --git a/core/vdbe.rs b/core/vdbe.rs index fd9ebc3a9..dffe3de47 100644 --- a/core/vdbe.rs +++ b/core/vdbe.rs @@ -38,10 +38,6 @@ pub struct ColumnInsn { pub struct GotoInsn { pub target_pc: usize, } -pub struct Program { - pub insns: Vec, - pub pc: usize, -} pub struct ProgramBuilder { pub insns: Vec, @@ -70,14 +66,27 @@ impl ProgramBuilder { self.insns.len() } - pub fn build(self) -> Program { + pub fn build(self, pager: Arc) -> Program { Program { + pager, insns: self.insns, pc: 0, } } } +pub enum StepResult { + Done, + IO, + Row, +} + +pub struct Program { + pager: Arc, + pub insns: Vec, + pub pc: usize, +} + impl Program { pub fn explain(&self) { println!("addr opcode p1 p2 p3 p4 p5 comment"); @@ -87,7 +96,15 @@ impl Program { } } - pub fn step(&mut self, _pager: Arc) -> Result<()> { + pub fn column_count(&self) -> usize { + 0 + } + + pub fn column(&self, _i: usize) -> Option<&str> { + None + } + + pub fn step(&mut self) -> Result { loop { let insn = &self.insns[self.pc]; print_insn(self.pc, insn); @@ -95,7 +112,8 @@ impl Program { Insn::Init(init) => { self.pc = init.target_pc; } - Insn::OpenReadAsync(_) => { + Insn::OpenReadAsync(open_read_async) => { + self.pager.read_page(open_read_async.root_page)?; self.pc += 1; } Insn::OpenReadAwait => { @@ -113,6 +131,7 @@ impl Program { } Insn::ResultRow => { self.pc += 1; + return Ok(StepResult::Row); } Insn::NextAsync => { self.pc += 1; @@ -121,7 +140,7 @@ impl Program { self.pc += 1; } Insn::Halt => { - return Ok(()); + return Ok(StepResult::Done); } Insn::Transaction => { self.pc += 1; @@ -134,14 +153,14 @@ impl Program { } } -pub fn translate(schema: &Schema, stmt: Stmt) -> Result { +pub fn translate(pager: Arc, schema: &Schema, stmt: Stmt) -> Result { match stmt { - Stmt::Select(select) => translate_select(schema, select), + Stmt::Select(select) => translate_select(pager, schema, select), _ => todo!(), } } -fn translate_select(schema: &Schema, select: Select) -> Result { +fn translate_select(pager: Arc, schema: &Schema, select: Select) -> Result { match select.body.select { OneSelect::Select { columns, @@ -199,7 +218,7 @@ fn translate_select(schema: &Schema, select: Select) -> Result { program.emit_insn(Insn::Goto(GotoInsn { target_pc: open_read_offset, })); - Ok(program.build()) + Ok(program.build(pager)) } _ => todo!(), }