Always assign UUIDs

next
Sayan Nandan 1 year ago
parent 29457c6b89
commit a619ea635c
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -37,6 +37,7 @@ use {
data::{
cell::Datacell,
tag::{DataTag, FullTag, TagClass, TagSelector},
uuid::Uuid,
},
error::{DatabaseError, DatabaseResult},
idx::{IndexBaseSpec, IndexSTSeqCns, STIndex, STIndexSeq},
@ -55,6 +56,7 @@ pub(in crate::engine::core) type Fields = IndexSTSeqCns<Box<str>, Field>;
#[derive(Debug)]
pub struct ModelData {
uuid: Uuid,
p_key: Box<str>,
p_tag: FullTag,
fields: UnsafeCell<Fields>,
@ -68,11 +70,16 @@ impl PartialEq for ModelData {
fn eq(&self, m: &Self) -> bool {
let mdl1 = self.intent_read_model();
let mdl2 = m.intent_read_model();
self.p_key == m.p_key && self.p_tag == m.p_tag && mdl1.fields() == mdl2.fields()
((self.p_key == m.p_key) & (self.p_tag == m.p_tag))
&& self.uuid == m.uuid
&& mdl1.fields() == mdl2.fields()
}
}
impl ModelData {
pub fn get_uuid(&self) -> Uuid {
self.uuid
}
pub fn p_key(&self) -> &str {
&self.p_key
}
@ -157,6 +164,7 @@ impl ModelData {
let tag = fields.st_get(last_pk).unwrap().layers()[0].tag;
if tag.tag_unique().is_unique() {
return Ok(Self {
uuid: Uuid::new(),
p_key: last_pk.into(),
p_tag: tag,
fields: UnsafeCell::new(fields),

@ -27,7 +27,7 @@
use {
crate::engine::{
core::{model::ModelData, RWLIdx},
data::{dict, DictEntryGeneric, MetaDict},
data::{dict, uuid::Uuid, DictEntryGeneric, MetaDict},
error::{DatabaseError, DatabaseResult},
idx::{IndexST, STIndex},
ql::ddl::{alt::AlterSpace, crt::CreateSpace, drop::DropSpace},
@ -38,6 +38,7 @@ use {
#[derive(Debug)]
/// A space with the model namespace
pub struct Space {
uuid: Uuid,
mns: RWLIdx<Box<str>, ModelData>,
pub(super) meta: SpaceMeta,
}
@ -85,6 +86,9 @@ impl Space {
Err(DatabaseError::DdlModelAlreadyExists)
}
}
pub fn get_uuid(&self) -> Uuid {
self.uuid
}
pub(super) fn models(&self) -> &RWLIdx<Box<str>, ModelData> {
&self.mns
}
@ -103,15 +107,23 @@ impl Space {
impl Space {
pub fn empty() -> Self {
Space::new(Default::default(), SpaceMeta::with_env(into_dict! {}))
Space::new_auto(Default::default(), SpaceMeta::with_env(into_dict! {}))
}
#[inline(always)]
pub fn new(mns: IndexST<Box<str>, ModelData>, meta: SpaceMeta) -> Self {
pub fn new_auto(mns: IndexST<Box<str>, ModelData>, meta: SpaceMeta) -> Self {
Self {
uuid: Uuid::new(),
mns: RWLIdx::new(mns),
meta,
}
}
pub fn new_with_uuid(mns: IndexST<Box<str>, ModelData>, meta: SpaceMeta, uuid: Uuid) -> Self {
Self {
uuid,
meta,
mns: RwLock::new(mns),
}
}
#[inline]
/// Validate a `create` stmt
fn process_create(
@ -132,7 +144,7 @@ impl Space {
};
Ok(ProcedureCreate {
space_name,
space: Self::new(
space: Self::new_auto(
IndexST::default(),
SpaceMeta::with_env(
// FIXME(@ohsayan): see this is bad. attempt to do it at AST build time
@ -211,6 +223,6 @@ impl PartialEq for Space {
fn eq(&self, other: &Self) -> bool {
let self_mns = self.mns.read();
let other_mns = other.mns.read();
self.meta == other.meta && *self_mns == *other_mns
self.meta == other.meta && *self_mns == *other_mns && self.uuid == other.uuid
}
}

@ -53,7 +53,13 @@ fn exec_plan(
plan: &str,
f: impl Fn(&ModelData),
) -> DatabaseResult<()> {
exec_create(gns, model, new_space)?;
let mdl_name = exec_create(gns, model, new_space)?;
let prev_uuid = {
let gns = gns.spaces().read();
let space = gns.get("myspace").unwrap();
let space_read = space.models().read();
space_read.get(mdl_name.as_str()).unwrap().get_uuid()
};
let tok = lex_insecure(plan.as_bytes()).unwrap();
let alter = parse_ast_node_full::<AlterModel>(&tok[2..]).unwrap();
let (_space, model_name) = alter.model.into_full().unwrap();
@ -61,7 +67,9 @@ fn exec_plan(
let gns_read = gns.spaces().read();
let space = gns_read.st_get("myspace").unwrap();
let model = space.models().read();
f(model.st_get(model_name.as_str()).unwrap());
let model = model.st_get(model_name.as_str()).unwrap();
assert_eq!(prev_uuid, model.get_uuid());
f(model);
Ok(())
}

@ -32,7 +32,11 @@ use crate::engine::{
core::{model::ModelData, space::Space, GlobalNS},
error::DatabaseResult,
idx::STIndex,
ql::{ast::parse_ast_node_full, ddl::crt::CreateModel, tests::lex_insecure},
ql::{
ast::{parse_ast_node_full, Entity},
ddl::crt::CreateModel,
tests::lex_insecure,
},
};
fn create(s: &str) -> DatabaseResult<ModelData> {
@ -45,21 +49,24 @@ pub fn exec_create(
gns: &GlobalNS,
create_stmt: &str,
create_new_space: bool,
) -> DatabaseResult<()> {
) -> DatabaseResult<String> {
let tok = lex_insecure(create_stmt.as_bytes()).unwrap();
let create_model = parse_ast_node_full::<CreateModel>(&tok[2..]).unwrap();
let name = match create_model.model_name {
Entity::Single(tbl) | Entity::Full(_, tbl) => tbl.to_string(),
};
if create_new_space {
gns.test_new_empty_space(&create_model.model_name.into_full().unwrap().0);
}
ModelData::exec_create(gns, create_model)
ModelData::exec_create(gns, create_model).map(|_| name)
}
pub fn exec_create_new_space(gns: &GlobalNS, create_stmt: &str) -> DatabaseResult<()> {
exec_create(gns, create_stmt, true)
exec_create(gns, create_stmt, true).map(|_| ())
}
pub fn exec_create_no_create(gns: &GlobalNS, create_stmt: &str) -> DatabaseResult<()> {
exec_create(gns, create_stmt, false)
exec_create(gns, create_stmt, false).map(|_| ())
}
fn with_space(gns: &GlobalNS, space_name: &str, f: impl Fn(&Space)) {

@ -36,18 +36,20 @@ use crate::engine::{
#[test]
fn alter_add_prop_env_var() {
let gns = GlobalNS::empty();
super::exec_create_empty_verify(&gns, "create space myspace");
let uuid = super::exec_create_empty_verify(&gns, "create space myspace").unwrap();
super::exec_alter_and_verify(
&gns,
"alter space myspace with { env: { MY_NEW_PROP: 100 } }",
|space| {
let space = space.unwrap();
assert_eq!(
space.unwrap(),
&Space::new(
space,
&Space::new_with_uuid(
into_dict!(),
SpaceMeta::with_env(into_dict! ("MY_NEW_PROP" => Datacell::new_uint(100)))
SpaceMeta::with_env(into_dict! ("MY_NEW_PROP" => Datacell::new_uint(100))),
uuid
)
)
);
},
)
}
@ -71,7 +73,7 @@ fn alter_update_prop_env_var() {
|space| {
assert_eq!(
space.unwrap(),
&Space::new(
&Space::new_auto(
into_dict!(),
SpaceMeta::with_env(into_dict! ("MY_NEW_PROP" => Datacell::new_uint(200)))
)
@ -99,7 +101,7 @@ fn alter_remove_prop_env_var() {
|space| {
assert_eq!(
space.unwrap(),
&Space::new(into_dict!(), SpaceMeta::with_env(into_dict!()))
&Space::new_auto(into_dict!(), SpaceMeta::with_env(into_dict!()))
)
},
)

@ -36,7 +36,7 @@ use crate::engine::{
#[test]
fn exec_create_space_simple() {
let gns = GlobalNS::empty();
super::exec_create_empty_verify(&gns, "create space myspace");
super::exec_create_empty_verify(&gns, "create space myspace").unwrap();
}
#[test]
@ -54,7 +54,7 @@ fn exec_create_space_with_env() {
|space| {
assert_eq!(
space.unwrap(),
&Space::new(
&Space::new_auto(
into_dict! {},
SpaceMeta::with_env(into_dict! {
"MAX_MODELS" => Datacell::new_uint(100)

@ -40,8 +40,8 @@ use crate::engine::{
fn exec_verify(
gns: &GlobalNS,
query: &str,
exec: impl Fn(&GlobalNS, Statement<'_>) -> (DatabaseResult<()>, Box<str>),
verify: impl Fn(DatabaseResult<&Space>),
mut exec: impl FnMut(&GlobalNS, Statement<'_>) -> (DatabaseResult<()>, Box<str>),
mut verify: impl FnMut(DatabaseResult<&Space>),
) {
let tok = lex(query.as_bytes()).unwrap();
let ast_node = compile_test(&tok).unwrap();
@ -68,7 +68,7 @@ fn exec_alter_and_verify(gns: &GlobalNS, tok: &str, verify: impl Fn(DatabaseResu
}
/// Creates a space using the given tokens and allows the caller to verify it
fn exec_create_and_verify(gns: &GlobalNS, tok: &str, verify: impl Fn(DatabaseResult<&Space>)) {
fn exec_create_and_verify(gns: &GlobalNS, tok: &str, verify: impl FnMut(DatabaseResult<&Space>)) {
exec_verify(
gns,
tok,
@ -83,8 +83,14 @@ fn exec_create_and_verify(gns: &GlobalNS, tok: &str, verify: impl Fn(DatabaseRes
}
/// Creates an empty space with the given tokens
fn exec_create_empty_verify(gns: &GlobalNS, tok: &str) {
fn exec_create_empty_verify(
gns: &GlobalNS,
tok: &str,
) -> DatabaseResult<crate::engine::data::uuid::Uuid> {
let mut name = None;
self::exec_create_and_verify(gns, tok, |space| {
assert_eq!(space.unwrap(), &Space::empty());
name = Some(space.unwrap().get_uuid());
});
Ok(name.unwrap())
}

@ -31,6 +31,8 @@ pub mod dict;
pub mod lit;
pub mod spec;
pub mod tag;
pub mod uuid;
// test
#[cfg(test)]
mod tests;

@ -0,0 +1,47 @@
/*
* Created on Mon Aug 14 2023
*
* This file is a part of Skytable
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
* NoSQL database written by Sayan Nandan ("the Author") with the
* vision to provide flexibility in data modelling without compromising
* on performance, queryability or scalability.
*
* Copyright (c) 2023, Sayan Nandan <ohsayan@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Uuid {
data: uuid::Uuid,
}
impl Uuid {
pub fn new() -> Self {
Self {
data: uuid::Uuid::new_v4(),
}
}
pub fn as_slice(&self) -> &[u8] {
self.data.as_bytes()
}
}
impl ToString for Uuid {
fn to_string(&self) -> String {
self.data.to_string()
}
}
Loading…
Cancel
Save