mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 18:18:03 +00:00
Query sqlite_schema table
This commit is contained in:
parent
61b1071d8d
commit
7c100ea217
3 changed files with 91 additions and 22 deletions
43
core/lib.rs
43
core/lib.rs
|
@ -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()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
43
core/vdbe.rs
43
core/vdbe.rs
|
@ -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!(),
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue