Query sqlite_schema table

This commit is contained in:
Pekka Enberg 2023-08-29 19:33:19 +03:00
parent 61b1071d8d
commit 7c100ea217
3 changed files with 91 additions and 22 deletions

View file

@ -20,6 +20,11 @@ impl Database {
pub fn open(io: Arc<dyn IO>, path: &str) -> Result<Database> {
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<String>) -> 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<String>) -> 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()?;
}
}
}

View file

@ -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<dyn IO>,
_buffer_pool: BufferPool,
io: Arc<dyn IO>,
database_ref: DatabaseRef,
buffer_pool: Arc<Mutex<BufferPool>>,
}
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<BTreePage> {
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,
)
}
}

View file

@ -38,10 +38,6 @@ pub struct ColumnInsn {
pub struct GotoInsn {
pub target_pc: usize,
}
pub struct Program {
pub insns: Vec<Insn>,
pub pc: usize,
}
pub struct ProgramBuilder {
pub insns: Vec<Insn>,
@ -70,14 +66,27 @@ impl ProgramBuilder {
self.insns.len()
}
pub fn build(self) -> Program {
pub fn build(self, pager: Arc<Pager>) -> Program {
Program {
pager,
insns: self.insns,
pc: 0,
}
}
}
pub enum StepResult {
Done,
IO,
Row,
}
pub struct Program {
pager: Arc<Pager>,
pub insns: Vec<Insn>,
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<Pager>) -> Result<()> {
pub fn column_count(&self) -> usize {
0
}
pub fn column(&self, _i: usize) -> Option<&str> {
None
}
pub fn step(&mut self) -> Result<StepResult> {
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<Program> {
pub fn translate(pager: Arc<Pager>, schema: &Schema, stmt: Stmt) -> Result<Program> {
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<Program> {
fn translate_select(pager: Arc<Pager>, schema: &Schema, select: Select) -> Result<Program> {
match select.body.select {
OneSelect::Select {
columns,
@ -199,7 +218,7 @@ fn translate_select(schema: &Schema, select: Select) -> Result<Program> {
program.emit_insn(Insn::Goto(GotoInsn {
target_pc: open_read_offset,
}));
Ok(program.build())
Ok(program.build(pager))
}
_ => todo!(),
}