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

Commit

Permalink
Wired the primary key system in further. Found out my array support h…
Browse files Browse the repository at this point in the history
…ad major bugs in it.
  • Loading branch information
chotchki committed Sep 4, 2021
1 parent ca25b2d commit c65cef8
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 23 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ Reasonable application error type creation: https://github.com/dtolnay/anyhow

Library Errors: https://github.com/dtolnay/thiserror

Rust's inability to treat enum variants as a type is a HUGE pain. I cheated and separated serialization from deserialization.
Rust's inability to treat enum variants as a type is a HUGE pain. I end up having an enum to hold data and another enum to validate and match the sub type. The [RFC](https://github.com/rust-lang/rfcs/pull/2593) to fix this was postponed indefinately.


## Legal Stuff (Note I'm not a lawyer!)

Expand Down
46 changes: 45 additions & 1 deletion src/engine/executor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::constants::SystemTables;
use crate::engine::objects::types::BaseSqlTypes;
use crate::engine::objects::SqlTuple;
use crate::engine::objects::{ConstraintMapper, SqlTuple};

use super::io::{ConstraintManager, ConstraintManagerError};
use super::objects::types::SqlTypeDefinition;
Expand Down Expand Up @@ -149,6 +149,8 @@ impl Executor {

cm.insert_row(tran_id, pg_class, table_row).await?;

let mut primary_key_cols = vec![];

let pg_attribute = SystemTables::PgAttribute.value();
for i in 0..create_table.provided_columns.len() {
let cm = self.cons_man.clone();
Expand All @@ -168,7 +170,49 @@ impl Executor {
cm.clone()
.insert_row(tran_id, pg_attribute.clone(), table_row)
.await?;

if create_table.provided_columns[i].primary_key {
primary_key_cols.push(BaseSqlTypes::Integer(i_u32));
}
}

if !primary_key_cols.is_empty() {
//We assume the the order that columns with primary key were defined are the order desired
let pk_id = Uuid::new_v4();
let primary_key_index = SqlTuple(vec![
Some(BaseSqlTypes::Uuid(pk_id)),
Some(BaseSqlTypes::Uuid(table_id)),
Some(BaseSqlTypes::Text(format!(
"{}_primary_key_index",
create_table.table_name
))),
Some(BaseSqlTypes::Array(primary_key_cols)),
Some(BaseSqlTypes::Bool(true)),
]);
let pg_index = SystemTables::PgIndex.value();
self.cons_man
.clone()
.insert_row(tran_id, pg_index, primary_key_index)
.await?;

//Now we can insert the constraint
let primary_key_constraint = SqlTuple(vec![
Some(BaseSqlTypes::Uuid(Uuid::new_v4())),
Some(BaseSqlTypes::Uuid(table_id)),
Some(BaseSqlTypes::Uuid(pk_id)),
Some(BaseSqlTypes::Text(format!(
"{}_primary_key",
create_table.table_name
))),
Some(BaseSqlTypes::Text(ConstraintMapper::PrimaryKey.to_string())),
]);
let pg_constraint = SystemTables::PgConstraint.value();
self.cons_man
.clone()
.insert_row(tran_id, pg_constraint, primary_key_constraint)
.await?;
}

Ok(vec![])
}
}
Expand Down
10 changes: 7 additions & 3 deletions src/engine/io/row_formats/row_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ mod tests {
),
Attribute::new(
"header3".to_string(),
BaseSqlTypesMapper::Text,
BaseSqlTypesMapper::Array(Arc::new(BaseSqlTypesMapper::Integer)),
Nullable::NotNull,
None,
),
Expand All @@ -452,14 +452,18 @@ mod tests {
vec![],
));

let test = RowData::new(table.sql_type.clone(),
let test = RowData::new(
table.sql_type.clone(),
TransactionId::new(1),
None,
get_item_pointer(),
SqlTuple(vec![
Some(BaseSqlTypes::Text("this is a test".to_string())),
None,
Some(BaseSqlTypes::Text("blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah".to_string())),
Some(BaseSqlTypes::Array(vec![
BaseSqlTypes::Integer(1),
BaseSqlTypes::Integer(2),
])),
]),
);

Expand Down
7 changes: 4 additions & 3 deletions src/engine/objects.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
mod attribute;
pub use attribute::Attribute;

mod constraint;
pub use constraint::Constraint;
pub use constraint::PrimaryKeyConstraint;
mod constraints;
pub use constraints::Constraint;
pub use constraints::ConstraintMapper;
pub use constraints::PrimaryKeyConstraint;

mod index;
pub use index::Index;
Expand Down
13 changes: 0 additions & 13 deletions src/engine/objects/constraint.rs

This file was deleted.

36 changes: 36 additions & 0 deletions src/engine/objects/constraints.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use super::Index;
use std::{
fmt::{self, Display, Formatter},
sync::Arc,
};

mod parse_constraint;

#[derive(Clone, Debug, PartialEq)]
pub enum Constraint {
PrimaryKey(PrimaryKeyConstraint),
}

/// ConstraintMapper exists to map to SqlType without imposing the cost of an empty version
///
/// This will exist until this RFC is brought back: https://github.com/rust-lang/rfcs/pull/2593
#[derive(Clone, Debug, PartialEq)]
pub enum ConstraintMapper {
PrimaryKey,
}

impl Display for ConstraintMapper {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
PrimaryKey => {
write!(f, "PrimaryKey")
}
}
}
}

#[derive(Clone, Debug, PartialEq)]
pub struct PrimaryKeyConstraint {
pub name: String,
pub index: Arc<Index>,
}
21 changes: 21 additions & 0 deletions src/engine/objects/constraints/parse_constraint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use nom::{
bytes::complete::tag_no_case,
error::{make_error, ContextError, ErrorKind, ParseError},
IResult,
};

use super::ConstraintMapper;

pub fn parse_constraint<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
input: &'a str,
) -> IResult<&'a str, ConstraintMapper, E> {
let (input, matched) = tag_no_case("PrimaryKey")(input)?;

let constraint_type = match matched {
"PrimaryKey" => ConstraintMapper::PrimaryKey,
_ => {
return Err(nom::Err::Failure(make_error(input, ErrorKind::Fix)));
}
};
Ok((input, constraint_type))
}
46 changes: 44 additions & 2 deletions src/engine/objects/types/base_sql_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub enum BaseSqlTypes {

/// BaseSqlTypesMapper exists to map to SqlType without imposing the cost of an empty version
///
/// This will exist until this RFC is fixed: https://github.com/rust-lang/rfcs/pull/2593
/// This will exist until this RFC is brought back: https://github.com/rust-lang/rfcs/pull/2593
#[derive(Clone, Debug, PartialEq)]
pub enum BaseSqlTypesMapper {
Array(Arc<BaseSqlTypesMapper>),
Expand Down Expand Up @@ -240,7 +240,9 @@ impl SelfEncodedSize for BaseSqlTypes {
/// is not needed to find space.
fn encoded_size(&self) -> usize {
match self {
Self::Array(ref a) => a.iter().fold(0, |acc, x| acc + x.encoded_size()),
Self::Array(ref a) => {
expected_encoded_size(a.len()) + a.iter().fold(0, |acc, x| acc + x.encoded_size())
}
Self::Bool(_) => size_of::<bool>(),
Self::Integer(_) => size_of::<u32>(),
Self::Uuid(_) => size_of::<Uuid>(),
Expand Down Expand Up @@ -372,6 +374,25 @@ mod tests {
Ok(())
}

#[test]
fn test_array_roundtrip() -> Result<(), Box<dyn std::error::Error>> {
let array = BaseSqlTypes::Array(vec![BaseSqlTypes::Integer(1), BaseSqlTypes::Integer(2)]);

let mut buffer = BytesMut::new();
array.serialize(&mut buffer);

let mut buffer = buffer.freeze();

let parse = BaseSqlTypes::deserialize(
&BaseSqlTypesMapper::Array(Arc::new(BaseSqlTypesMapper::Integer)),
&mut buffer,
)?;

assert_eq!(parse, array);

Ok(())
}

#[test]
//Used to map if we have the types linked up right
pub fn test_type_matches() {
Expand All @@ -397,4 +418,25 @@ mod tests {
assert!(!BaseSqlTypes::Text("foo".to_string()).type_matches(&BaseSqlTypesMapper::Uuid));
assert!(BaseSqlTypes::Text("foo".to_string()).type_matches(&BaseSqlTypesMapper::Text));
}

#[test]
pub fn test_encoded_size() {
assert_eq!(
BaseSqlTypes::Array(vec![BaseSqlTypes::Integer(1), BaseSqlTypes::Integer(2)])
.encoded_size(),
9
);
assert_eq!(
BaseSqlTypes::Array(vec![
BaseSqlTypes::Text("Test".to_string()),
BaseSqlTypes::Text("Test".to_string())
])
.encoded_size(),
11
);
assert_eq!(BaseSqlTypes::Bool(true).encoded_size(), 1);
assert_eq!(BaseSqlTypes::Integer(1).encoded_size(), 4);
assert_eq!(BaseSqlTypes::Text("Test".to_string()).encoded_size(), 5);
assert_eq!(BaseSqlTypes::Uuid(Uuid::new_v4()).encoded_size(), 16);
}
}

0 comments on commit c65cef8

Please sign in to comment.