From 2615cdce2c8af5e0001fc1a70cb88698109b52f1 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sun, 27 Aug 2023 20:40:12 +0300 Subject: [PATCH] Schema in-memory data structures --- core/lib.rs | 1 + core/schema.rs | 114 +++++++++++++++++++++++++++++++++++++++++++++++++ core/vdbe.rs | 3 ++ 3 files changed, 118 insertions(+) create mode 100644 core/schema.rs diff --git a/core/lib.rs b/core/lib.rs index c07770ab2..de4ef7a3a 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -1,5 +1,6 @@ mod buffer_pool; mod pager; +mod schema; mod sqlite3_ondisk; mod vdbe; diff --git a/core/schema.rs b/core/schema.rs new file mode 100644 index 000000000..43618dc03 --- /dev/null +++ b/core/schema.rs @@ -0,0 +1,114 @@ +use core::fmt; +use std::collections::HashMap; + +pub struct Schema { + pub tables: HashMap, +} + +impl Schema { + pub fn new() -> Self { + let mut tables: HashMap = HashMap::new(); + tables.insert("sqlite_schema".to_string(), sqlite_schema_table()); + Self { tables } + } + + pub fn add_table(&mut self, name: String, table: Table) { + self.tables.insert(name, table); + } +} + +pub struct Table { + root_page: i32, + name: String, + columns: Vec, +} + +impl Table { + pub fn to_sql(&self) -> String { + let mut sql = format!("CREATE TABLE {} (\n", self.name); + for (i, column) in self.columns.iter().enumerate() { + if i > 0 { + sql.push_str(",\n"); + } + sql.push_str(" "); + sql.push_str(&column.name); + sql.push_str(" "); + sql.push_str(&column.ty.to_string()); + } + sql.push_str(");\n"); + sql + } +} + +pub struct Column { + name: String, + ty: Type, +} + +pub enum Type { + Null, + Integer, + Real, + Text, + Blob, +} + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + Type::Null => "NULL", + Type::Integer => "INTEGER", + Type::Real => "REAL", + Type::Text => "TEXT", + Type::Blob => "BLOB", + }; + write!(f, "{}", s) + } +} + +pub fn sqlite_schema_table() -> Table { + Table { + root_page: 1, + name: "sqlite_schema".to_string(), + columns: vec![ + Column { + name: "type".to_string(), + ty: Type::Text, + }, + Column { + name: "name".to_string(), + ty: Type::Text, + }, + Column { + name: "tbl_name".to_string(), + ty: Type::Text, + }, + Column { + name: "rootpage".to_string(), + ty: Type::Integer, + }, + Column { + name: "sql".to_string(), + ty: Type::Text, + }, + ], + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + pub fn test_sqlite_schema() { + let expected = r#"CREATE TABLE sqlite_schema ( + type TEXT, + name TEXT, + tbl_name TEXT, + rootpage INTEGER, + sql TEXT); +"#; + let actual = sqlite_schema_table().to_sql(); + assert_eq!(expected, actual); + } +} diff --git a/core/vdbe.rs b/core/vdbe.rs index beb7dff48..8fb081939 100644 --- a/core/vdbe.rs +++ b/core/vdbe.rs @@ -1,4 +1,5 @@ use crate::pager::Pager; +use crate::schema::Schema; use anyhow::Result; use sqlite3_parser::ast::{Select, Stmt}; @@ -31,6 +32,7 @@ pub struct GotoInsn { pub target_pc: usize, } pub struct Program { + pub schema: Schema, pub insns: Vec, pub pc: usize, } @@ -64,6 +66,7 @@ impl ProgramBuilder { pub fn build(self) -> Program { Program { + schema: Schema::new(), insns: self.insns, pc: 0, }