61 lines
2.1 KiB
Rust
61 lines
2.1 KiB
Rust
use anyhow::{bail, Result};
|
|
use sqlite_starter_rust::{
|
|
header::PageHeader, record::parse_record, schema::Schema, varint::parse_varint,
|
|
};
|
|
use std::convert::TryInto;
|
|
use std::fs::File;
|
|
use std::io::prelude::*;
|
|
|
|
fn main() -> Result<()> {
|
|
// Parse arguments
|
|
let args = std::env::args().collect::<Vec<_>>();
|
|
match args.len() {
|
|
0 | 1 => bail!("Missing <database path> and <command>"),
|
|
2 => bail!("Missing <command>"),
|
|
_ => {}
|
|
}
|
|
|
|
// Read database file into database
|
|
let mut file = File::open(&args[1])?;
|
|
let mut database = Vec::new();
|
|
file.read_to_end(&mut database)?;
|
|
|
|
// Parse command and act accordingly
|
|
let command = &args[2];
|
|
match command.as_str() {
|
|
".dbinfo" => {
|
|
// Parse page header from database
|
|
let page_header = PageHeader::parse(&database[100..108])?;
|
|
|
|
// Obtain all cell pointers
|
|
let cell_pointers = database[108..]
|
|
.chunks_exact(2)
|
|
.take(page_header.number_of_cells.into())
|
|
.map(|bytes| u16::from_be_bytes(bytes.try_into().unwrap()))
|
|
.collect::<Vec<_>>();
|
|
|
|
// Obtain all records from column 5
|
|
#[allow(unused_variables)]
|
|
let schemas = cell_pointers
|
|
.into_iter()
|
|
.map(|cell_pointer| {
|
|
let stream = &database[cell_pointer as usize..];
|
|
let (_, offset) = parse_varint(stream);
|
|
let (_rowid, read_bytes) = parse_varint(&stream[offset..]);
|
|
parse_record(&stream[offset + read_bytes..], 5)
|
|
.map(|record| Schema::parse(record).expect("Invalid record"))
|
|
})
|
|
.collect::<Result<Vec<_>>>()?;
|
|
|
|
// You can use print statements as follows for debugging, they'll be visible when running tests.
|
|
println!("Logs from your program will appear here!");
|
|
|
|
// Uncomment this block to pass the first stage
|
|
// println!("number of tables: {}", schemas.len());
|
|
}
|
|
_ => bail!("Missing or invalid command passed: {}", command),
|
|
}
|
|
|
|
Ok(())
|
|
}
|