Skip to content
This repository has been archived by the owner on Apr 15, 2023. It is now read-only.

Commit

Permalink
Implementation of primary key controls and switch to using self refer…
Browse files Browse the repository at this point in the history
…ences
  • Loading branch information
chotchki committed Oct 10, 2021
1 parent e18cfd1 commit 9ebdc21
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 20 deletions.
18 changes: 10 additions & 8 deletions benches/feophant_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use criterion::Criterion;
use criterion::{criterion_group, criterion_main};
use feophantlib::engine::get_row;
use feophantlib::engine::get_table;
use feophantlib::engine::io::block_layer::file_manager::FileManager;
use feophantlib::engine::io::block_layer::lock_cache_manager::LockCacheManager;
use feophantlib::engine::io::block_layer::file_manager2::FileManager2;
use feophantlib::engine::io::block_layer::free_space_manager::FreeSpaceManager;
use feophantlib::engine::io::row_formats::RowData;
use feophantlib::engine::io::RowManager;
use feophantlib::engine::transactions::TransactionId;
Expand All @@ -20,27 +20,29 @@ async fn row_manager_mass_insert(row_count: usize) -> Result<(), Box<dyn std::er
let tmp_dir = tmp.path().as_os_str().to_os_string();

let table = get_table();
let fm = Arc::new(FileManager::new(tmp_dir.clone())?);
let rm = RowManager::new(LockCacheManager::new(fm));
let fm = Arc::new(FileManager2::new(tmp_dir.clone())?);
let fsm = FreeSpaceManager::new(fm.clone());
let rm = RowManager::new(fm, fsm);

let tran_id = TransactionId::new(1);

for i in 0..row_count {
rm.clone()
.insert_row(tran_id, table.clone(), get_row(i.to_string()))
.insert_row(tran_id, &table, get_row(i.to_string()))
.await?;
}

drop(rm);

//Now let's make sure they're really in the table, persisting across restarts
let fm = Arc::new(FileManager::new(tmp_dir)?);
let rm = RowManager::new(LockCacheManager::new(fm));
let fm = Arc::new(FileManager2::new(tmp_dir.clone())?);
let fsm = FreeSpaceManager::new(fm.clone());
let rm = RowManager::new(fm, fsm);

pin_mut!(rm);
let result_rows: Vec<RowData> = rm
.clone()
.get_stream(table.clone())
.get_stream(&table)
.map(Result::unwrap)
.collect()
.await;
Expand Down
4 changes: 2 additions & 2 deletions src/engine/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,11 @@ impl Executor {

//Bypass planning since there isn't anything optimize
pub async fn execute_utility(
&self,
&mut self,
tran_id: TransactionId,
parse_tree: ParseTree,
) -> Result<Vec<SqlTuple>, ExecutorError> {
let cm = self.cons_man.clone();
let mut cm = self.cons_man.clone();

let create_table = match parse_tree {
ParseTree::CreateTable(t) => t,
Expand Down
38 changes: 35 additions & 3 deletions src/engine/io/constraint_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ use crate::{
engine::{
objects::{
types::{BaseSqlTypes, BaseSqlTypesMapper},
SqlTuple, Table,
SqlTuple, SqlTupleError, Table,
},
transactions::TransactionId,
},
};

use super::{
index_manager::IndexManagerError,
row_formats::{ItemPointer, RowData},
IndexManager, VisibleRowManager, VisibleRowManagerError,
};

/// The goal of the constraint manager is to ensure all constrainst are satisfied
/// The goal of the constraint manager is to ensure all constraints are satisfied
/// before we hand it off deeper into the stack. For now its taking on the null checks
/// of RowData
#[derive(Clone)]
Expand All @@ -37,7 +38,7 @@ impl ConstraintManager {
}

pub async fn insert_row(
self,
&mut self,
current_tran_id: TransactionId,
table: &Arc<Table>,
user_data: SqlTuple,
Expand Down Expand Up @@ -73,6 +74,31 @@ impl ConstraintManager {
for c in &table.constraints {
match c {
crate::engine::objects::Constraint::PrimaryKey(p) => {
match self
.index_manager
.search_for_key(
&p.index,
&user_data
.clone()
.filter_map(&table.sql_type, &p.index.columns)?,
)
.await?
{
Some(rows) => {
//We need to check if each of these rows are alive
if self
.vis_row_man
.any_visible(&table, current_tran_id, &rows)
.await?
{
return Err(ConstraintManagerError::PrimaryKeyViolation());
}
}
None => {
continue;
}
}

//TODO So for a primary key we have to check for no other dups in the table

//So what I want to do is ask the index manager to to get active rows matching the key
Expand Down Expand Up @@ -114,6 +140,12 @@ impl ConstraintManager {

#[derive(Error, Debug)]
pub enum ConstraintManagerError {
#[error(transparent)]
IndexManagerError(#[from] IndexManagerError),
#[error("Primary Key violation")]
PrimaryKeyViolation(),
#[error(transparent)]
SqlTupleError(#[from] SqlTupleError),
#[error("Table definition length {0} does not match columns passed {1}")]
TableRowSizeMismatch(usize, usize),
#[error("Table definition type {0} does not match column passed {1}")]
Expand Down
6 changes: 0 additions & 6 deletions src/engine/io/row_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,6 @@ mod tests {
use crate::engine::get_row;
use crate::engine::get_table;
use futures::pin_mut;
use log::LevelFilter;
use simplelog::ColorChoice;
use simplelog::CombinedLogger;
use simplelog::Config;
use simplelog::TermLogger;
use simplelog::TerminalMode;
use tempfile::TempDir;
use tokio_stream::StreamExt;

Expand Down
20 changes: 19 additions & 1 deletion src/engine/io/visible_row_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use super::{
};
use async_stream::try_stream;
use futures::stream::Stream;
use log::debug;
use std::sync::Arc;
use thiserror::Error;

Expand Down Expand Up @@ -79,6 +78,24 @@ impl VisibleRowManager {
}
}

pub async fn any_visible(
&mut self,
table: &Arc<Table>,
tran_id: TransactionId,
ptrs: &Vec<ItemPointer>,
) -> Result<bool, VisibleRowManagerError> {
for p in ptrs {
match self.get(tran_id, table, *p).await {
Ok(o) => return Ok(true),
Err(VisibleRowManagerError::NotVisibleRow(_)) => continue,
Err(e) => {
return Err(e);
}
}
}
return Ok(false);
}

//TODO I want to find a way to NOT depend on tm
async fn is_visible(
tm: &mut TransactionManager,
Expand All @@ -100,6 +117,7 @@ impl VisibleRowManager {
}

//TODO check hint bits

if row_data.min > tran_id {
return Ok(false);
}
Expand Down

0 comments on commit 9ebdc21

Please sign in to comment.