Skip to content

Commit 1a10a8c

Browse files
Implement index
1 parent ce59259 commit 1a10a8c

File tree

1 file changed

+110
-9
lines changed

1 file changed

+110
-9
lines changed

src/database.rs

Lines changed: 110 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,112 @@
11
use super::container::{BaseContainer, TailContainer};
22
use super::page::PhysicalPage;
33
use pyo3::prelude::*;
4+
use std::collections::BTreeMap;
45
use std::collections::HashMap;
56
use std::sync::{Arc, Mutex};
67

8+
/* A data strucutre holding indices for various columns of a table.
9+
Key column should be indexd by default, other columns can be indexed through this object.
10+
Indices are usually B-Trees, but other data structures can be used as well. */
11+
12+
#[pyclass]
13+
#[derive(Clone)]
14+
pub struct RIndex {
15+
/* EXPLANATION OF BTree, NOT TOO SURE ABOUT THIS.
16+
17+
A vector of BTreeMaps, can be either Some::BTreeMap or None as its elements.
18+
19+
BTreeMap<i64, Vec<[usize; 3]>>:
20+
-- BTreeMap: A balanced binary search tree (B-Tree), for maintaining sorted key-value pairs. --
21+
22+
Map primary key to RID
23+
*/
24+
indices: Vec<Option<BTreeMap<u64, Vec<u64>>>>,
25+
}
26+
27+
impl RIndex {
28+
// Mandatory: One index for each table. All our empty initially.
29+
pub fn new(primary_key_column: u64, num_columns: usize) -> RIndex {
30+
let mut indices = vec![None; num_columns]; // table.columns.len()
31+
indices[primary_key_column as usize] = Some(BTreeMap::new());
32+
RIndex { indices }
33+
}
34+
35+
/// Returns the location of all records with the given value on column "column"
36+
pub fn locate(&self, column: usize, value: u64) -> Option<&Vec<u64>> {
37+
if let Some(tree) = &self.indices[column] {
38+
return tree.get(&value);
39+
}
40+
None
41+
}
42+
43+
/// Returns the RIDs of all records with values in column "column" between "begin" and "end"
44+
pub fn locate_range(&self, begin: u64, end: u64, column: usize) -> Vec<u64> {
45+
if let Some(tree) = &self.indices[column] {
46+
// Gets all entries where the key is between begin and end
47+
let keys = tree.range(begin..=end);
48+
49+
let all_records: Vec<u64> = keys.flat_map(|(_, rids)| rids.clone()).collect();
50+
return all_records;
51+
}
52+
Vec::new()
53+
}
54+
55+
/// Create index on specific column
56+
pub fn create_index(&mut self, column: usize) {
57+
// Create BTree for column
58+
if self.indices[column].is_none() {
59+
self.indices[column] = Some(BTreeMap::new());
60+
// Populate new index with existing records
61+
62+
// let table = self.table.lock().unwrap();
63+
// for rid in table.page_directory.keys() {
64+
// let row = table.fetch_row(*rid);
65+
// let value = row[column];
66+
67+
// // Add RID to index
68+
// self.update_index(value, [*rid as usize, column, 0], column).unwrap();
69+
// }
70+
}
71+
}
72+
73+
/// Insert or update index for a specific column
74+
pub fn update_index(&mut self, key: u64, rid: u64, column: usize) -> Result<(), String> {
75+
if column >= self.indices.len() {
76+
return Err(format!("Column {} does not exist'", column));
77+
}
78+
// Gets column Some::BTreeMap, creates one if None
79+
let tree = self.indices[column].get_or_insert_with(BTreeMap::new);
80+
81+
// Insert or update key
82+
// Searches for the given key in the BTree, If the key exists, it returns a mutable reference to the corresponding value,
83+
// If the key does not exist, it creates a new entry in the BTree for the key, If the key does not exist, this initializes an empty vector (Vec::new) as the value for the key.
84+
// Appends the provided RID to the vector associated with the key
85+
tree.entry(key).or_insert_with(Vec::new).push(rid);
86+
Ok(())
87+
}
88+
89+
pub fn delete_from_index(&mut self, column: usize, key: u64, rid: u64) {
90+
if let Some(tree) = &mut self.indices[column] {
91+
if let Some(rids) = tree.get_mut(&key) {
92+
// Find the position of the RID to remove
93+
if let Some(pos) = rids.iter().position(|&p| p == rid) {
94+
rids.remove(pos);
95+
}
96+
// If no more RID's exist for this key, remove the key
97+
if rids.is_empty() {
98+
tree.remove(&key);
99+
}
100+
}
101+
}
102+
}
103+
104+
/// Drop index of specific column
105+
pub fn drop_index(&mut self, column: usize) {
106+
self.indices[column] = None;
107+
}
108+
}
109+
7110
#[derive(Clone)]
8111
pub struct PageRange {
9112
base_container: BaseContainer,
@@ -80,7 +183,9 @@ pub struct RTable {
80183
pub num_records: u64,
81184

82185
#[pyo3(get)]
83-
pub num_columns: i64,
186+
pub num_columns: usize,
187+
188+
pub index: RIndex,
84189
}
85190

86191
impl RTable {
@@ -154,19 +259,15 @@ impl RDatabase {
154259
unreachable!("Not used in milestone 1");
155260
}
156261

157-
fn create_table(
158-
&mut self,
159-
name: String,
160-
num_columns: i64,
161-
primary_key_column: usize,
162-
) -> RTable {
262+
fn create_table(&mut self, name: String, num_columns: u64, primary_key_column: u64) -> RTable {
163263
let t = RTable {
164264
name: name.clone(),
165265
page_range: PageRange::new(num_columns as u64),
166-
primary_key_column,
266+
primary_key_column: primary_key_column as usize,
167267
page_directory: HashMap::new(),
168-
num_columns: 1,
268+
num_columns: num_columns as usize,
169269
num_records: 0,
270+
index: RIndex::new(primary_key_column, num_columns as usize),
170271
};
171272

172273
let i = self.tables.len();

0 commit comments

Comments
 (0)