Require full entity path in `alter model`

next
Sayan Nandan 1 year ago
parent 30d1be4862
commit 45ef72e400
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -36,6 +36,7 @@ use {
error::{DatabaseError, DatabaseResult}, error::{DatabaseError, DatabaseResult},
idx::{IndexST, IndexSTSeqCns, STIndex}, idx::{IndexST, IndexSTSeqCns, STIndex},
ql::{ ql::{
ast::Entity,
ddl::{ ddl::{
alt::{AlterKind, AlterModel}, alt::{AlterKind, AlterModel},
syn::{ExpandedField, LayerSpec}, syn::{ExpandedField, LayerSpec},
@ -50,7 +51,7 @@ use {
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub(in crate::engine::core) struct AlterPlan<'a> { pub(in crate::engine::core) struct AlterPlan<'a> {
pub(in crate::engine::core) model: Ident<'a>, pub(in crate::engine::core) model: Entity<'a>,
pub(in crate::engine::core) no_lock: bool, pub(in crate::engine::core) no_lock: bool,
pub(in crate::engine::core) action: AlterAction<'a>, pub(in crate::engine::core) action: AlterAction<'a>,
} }
@ -246,13 +247,16 @@ impl<'a> AlterPlan<'a> {
} }
impl ModelView { impl ModelView {
pub fn exec_alter(gns: &GlobalNS, space: &[u8], alter: AlterModel) -> DatabaseResult<()> { pub fn exec_alter(gns: &GlobalNS, alter: AlterModel) -> DatabaseResult<()> {
let Some((space, model)) = alter.model.into_full() else {
return Err(DatabaseError::ExpectedEntity);
};
let gns = gns.spaces().read(); let gns = gns.spaces().read();
let Some(space) = gns.st_get(space) else { let Some(space) = gns.st_get(space.as_bytes()) else {
return Err(DatabaseError::DdlSpaceNotFound) return Err(DatabaseError::DdlSpaceNotFound)
}; };
let space = space.models().read(); let space = space.models().read();
let Some(model) = space.st_get(alter.model.as_bytes()) else { let Some(model) = space.st_get(model.as_bytes()) else {
return Err(DatabaseError::DdlModelNotFound); return Err(DatabaseError::DdlModelNotFound);
}; };
// make intent // make intent

@ -56,8 +56,8 @@ fn exec_plan(
exec_create(gns, model, "myspace", new_space)?; exec_create(gns, model, "myspace", new_space)?;
let tok = lex_insecure(plan.as_bytes()).unwrap(); let tok = lex_insecure(plan.as_bytes()).unwrap();
let alter = parse_ast_node_full::<AlterModel>(&tok[2..]).unwrap(); let alter = parse_ast_node_full::<AlterModel>(&tok[2..]).unwrap();
let model_name = alter.model; let (_space, model_name) = alter.model.into_full().unwrap();
ModelView::exec_alter(gns, "myspace".as_bytes(), alter)?; ModelView::exec_alter(gns, alter)?;
let gns_read = gns.spaces().read(); let gns_read = gns.spaces().read();
let space = gns_read.st_get("myspace".as_bytes()).unwrap(); let space = gns_read.st_get("myspace".as_bytes()).unwrap();
let model = space.models().read(); let model = space.models().read();
@ -80,9 +80,9 @@ mod plan {
fn simple_add() { fn simple_add() {
super::plan( super::plan(
"create model mymodel(username: string, password: binary)", "create model mymodel(username: string, password: binary)",
"alter model mymodel add myfield { type: string, nullable: true }", "alter model myspace.mymodel add myfield { type: string, nullable: true }",
|plan| { |plan| {
assert_eq!(plan.model.as_str(), "mymodel"); assert_eq!(plan.model.into_full().unwrap().1.as_str(), "mymodel");
assert!(plan.no_lock); assert!(plan.no_lock);
assert_eq!( assert_eq!(
plan.action, plan.action,
@ -97,9 +97,9 @@ mod plan {
fn simple_remove() { fn simple_remove() {
super::plan( super::plan(
"create model mymodel(username: string, password: binary, useless_field: uint8)", "create model mymodel(username: string, password: binary, useless_field: uint8)",
"alter model mymodel remove useless_field", "alter model myspace.mymodel remove useless_field",
|plan| { |plan| {
assert_eq!(plan.model.as_str(), "mymodel"); assert_eq!(plan.model.into_full().unwrap().1.as_str(), "mymodel");
assert!(plan.no_lock); assert!(plan.no_lock);
assert_eq!( assert_eq!(
plan.action, plan.action,
@ -113,9 +113,9 @@ mod plan {
// FREEDOM! DAMN THE PASSWORD! // FREEDOM! DAMN THE PASSWORD!
super::plan( super::plan(
"create model mymodel(username: string, password: binary)", "create model mymodel(username: string, password: binary)",
"alter model mymodel update password { nullable: true }", "alter model myspace.mymodel update password { nullable: true }",
|plan| { |plan| {
assert_eq!(plan.model.as_str(), "mymodel"); assert_eq!(plan.model.into_full().unwrap().1.as_str(), "mymodel");
assert!(plan.no_lock); assert!(plan.no_lock);
assert_eq!( assert_eq!(
plan.action, plan.action,
@ -131,9 +131,9 @@ mod plan {
// FIGHT THE NULL // FIGHT THE NULL
super::plan( super::plan(
"create model mymodel(username: string, null password: binary)", "create model mymodel(username: string, null password: binary)",
"alter model mymodel update password { nullable: false }", "alter model myspace.mymodel update password { nullable: false }",
|plan| { |plan| {
assert_eq!(plan.model.as_str(), "mymodel"); assert_eq!(plan.model.into_full().unwrap().1.as_str(), "mymodel");
assert!(!plan.no_lock); assert!(!plan.no_lock);
assert_eq!( assert_eq!(
plan.action, plan.action,
@ -152,7 +152,7 @@ mod plan {
assert_eq!( assert_eq!(
super::with_plan( super::with_plan(
"create model mymodel(username: string, password: binary)", "create model mymodel(username: string, password: binary)",
"alter model mymodel remove password_e2e", "alter model myspace.mymodel remove password_e2e",
|_| {} |_| {}
) )
.unwrap_err(), .unwrap_err(),
@ -164,7 +164,7 @@ mod plan {
assert_eq!( assert_eq!(
super::with_plan( super::with_plan(
"create model mymodel(username: string, password: binary)", "create model mymodel(username: string, password: binary)",
"alter model mymodel remove username", "alter model myspace.mymodel remove username",
|_| {} |_| {}
) )
.unwrap_err(), .unwrap_err(),
@ -176,7 +176,7 @@ mod plan {
assert_eq!( assert_eq!(
super::with_plan( super::with_plan(
"create model mymodel(username: string, password: binary)", "create model mymodel(username: string, password: binary)",
"alter model mymodel add username { type: string }", "alter model myspace.mymodel add username { type: string }",
|_| {} |_| {}
) )
.unwrap_err(), .unwrap_err(),
@ -188,7 +188,7 @@ mod plan {
assert_eq!( assert_eq!(
super::with_plan( super::with_plan(
"create model mymodel(username: string, password: binary)", "create model mymodel(username: string, password: binary)",
"alter model mymodel add password { type: string }", "alter model myspace.mymodel add password { type: string }",
|_| {} |_| {}
) )
.unwrap_err(), .unwrap_err(),
@ -200,7 +200,7 @@ mod plan {
assert_eq!( assert_eq!(
super::with_plan( super::with_plan(
"create model mymodel(username: string, password: binary)", "create model mymodel(username: string, password: binary)",
"alter model mymodel update username { type: string }", "alter model myspace.mymodel update username { type: string }",
|_| {} |_| {}
) )
.unwrap_err(), .unwrap_err(),
@ -212,7 +212,7 @@ mod plan {
assert_eq!( assert_eq!(
super::with_plan( super::with_plan(
"create model mymodel(username: string, password: binary)", "create model mymodel(username: string, password: binary)",
"alter model mymodel update username_secret { type: string }", "alter model myspace.mymodel update username_secret { type: string }",
|_| {} |_| {}
) )
.unwrap_err(), .unwrap_err(),
@ -221,7 +221,7 @@ mod plan {
} }
fn bad_type_cast(orig_ty: &str, new_ty: &str) { fn bad_type_cast(orig_ty: &str, new_ty: &str) {
let create = format!("create model mymodel(username: string, silly_field: {orig_ty})"); let create = format!("create model mymodel(username: string, silly_field: {orig_ty})");
let alter = format!("alter model mymodel update silly_field {{ type: {new_ty} }}"); let alter = format!("alter model myspace.mymodel update silly_field {{ type: {new_ty} }}");
assert_eq!( assert_eq!(
super::with_plan(&create, &alter, |_| {}).expect_err(&format!( super::with_plan(&create, &alter, |_| {}).expect_err(&format!(
"found no error in transformation: {orig_ty} -> {new_ty}" "found no error in transformation: {orig_ty} -> {new_ty}"
@ -350,7 +350,7 @@ mod exec {
&gns, &gns,
true, true,
"create model mymodel(username: string, password: binary)", "create model mymodel(username: string, password: binary)",
"alter model mymodel update password { nullable: true }", "alter model myspace.mymodel update password { nullable: true }",
|model| { |model| {
let schema = model.intent_read_model(); let schema = model.intent_read_model();
assert!(schema.fields().st_get("password").unwrap().is_nullable()); assert!(schema.fields().st_get("password").unwrap().is_nullable());

@ -88,6 +88,8 @@ pub enum DatabaseError {
// query generic // query generic
/// this needs an explicit lock /// this needs an explicit lock
NeedLock, NeedLock,
/// expected a full entity, but found a single implicit entity
ExpectedEntity,
// ddl: create space // ddl: create space
/// unknown property or bad type for property /// unknown property or bad type for property
DdlSpaceBadProperty, DdlSpaceBadProperty,

@ -354,7 +354,7 @@ impl<'a> QueryData<'a> for SubstitutedData<'a> {
AST AST
*/ */
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq, Clone, Copy)]
/// An [`Entity`] represents the location for a specific structure, such as a model /// An [`Entity`] represents the location for a specific structure, such as a model
pub enum Entity<'a> { pub enum Entity<'a> {
/// A single entity is used when switching to a model wrt the currently set space (commonly used /// A single entity is used when switching to a model wrt the currently set space (commonly used
@ -376,6 +376,20 @@ pub enum Entity<'a> {
} }
impl<'a> Entity<'a> { impl<'a> Entity<'a> {
pub fn into_full(self) -> Option<(Ident<'a>, Ident<'a>)> {
if let Self::Full(a, b) = self {
Some((a, b))
} else {
None
}
}
pub fn into_single(self) -> Option<Ident<'a>> {
if let Self::Single(a) = self {
Some(a)
} else {
None
}
}
#[inline(always)] #[inline(always)]
/// Parse a full entity from the given slice /// Parse a full entity from the given slice
/// ///

@ -31,7 +31,7 @@ use {
data::DictGeneric, data::DictGeneric,
error::{LangError, LangResult}, error::{LangError, LangResult},
ql::{ ql::{
ast::{QueryData, State}, ast::{Entity, QueryData, State},
lex::{Ident, Token}, lex::{Ident, Token},
}, },
}, },
@ -89,13 +89,13 @@ impl<'a> AlterSpace<'a> {
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct AlterModel<'a> { pub struct AlterModel<'a> {
pub(in crate::engine) model: Ident<'a>, pub(in crate::engine) model: Entity<'a>,
pub(in crate::engine) kind: AlterKind<'a>, pub(in crate::engine) kind: AlterKind<'a>,
} }
impl<'a> AlterModel<'a> { impl<'a> AlterModel<'a> {
#[inline(always)] #[inline(always)]
pub fn new(model: Ident<'a>, kind: AlterKind<'a>) -> Self { pub fn new(model: Entity<'a>, kind: AlterKind<'a>) -> Self {
Self { model, kind } Self { model, kind }
} }
} }
@ -117,10 +117,7 @@ impl<'a> AlterModel<'a> {
return compiler::cold_rerr(LangError::BadSyntax); return compiler::cold_rerr(LangError::BadSyntax);
// FIXME(@ohsayan): bad because no specificity // FIXME(@ohsayan): bad because no specificity
} }
let model_name = unsafe { let model_name = Entity::parse_from_state_rounded_result(state)?;
// UNSAFE(@ohsayan): did rounded check for ident in the above branch
state.fw_read().uck_read_ident()
};
let kind = match state.fw_read() { let kind = match state.fw_read() {
Token![add] => AlterKind::alter_add(state), Token![add] => AlterKind::alter_add(state),
Token![remove] => AlterKind::alter_remove(state), Token![remove] => AlterKind::alter_remove(state),

@ -765,7 +765,7 @@ mod dict_field_syntax {
mod alter_model_remove { mod alter_model_remove {
use super::*; use super::*;
use crate::engine::ql::{ use crate::engine::ql::{
ast::parse_ast_node_full, ast::{parse_ast_node_full, Entity},
ddl::alt::{AlterKind, AlterModel}, ddl::alt::{AlterKind, AlterModel},
lex::Ident, lex::Ident,
}; };
@ -776,7 +776,7 @@ mod alter_model_remove {
assert_eq!( assert_eq!(
remove, remove,
AlterModel::new( AlterModel::new(
Ident::from("mymodel"), Entity::Single(Ident::from("mymodel")),
AlterKind::Remove(Box::from([Ident::from("myfield")])) AlterKind::Remove(Box::from([Ident::from("myfield")]))
) )
); );
@ -788,7 +788,7 @@ mod alter_model_remove {
assert_eq!( assert_eq!(
remove, remove,
AlterModel::new( AlterModel::new(
Ident::from("mymodel"), Entity::Single(Ident::from("mymodel")),
AlterKind::Remove(Box::from([Ident::from("myfield")])) AlterKind::Remove(Box::from([Ident::from("myfield")]))
) )
); );
@ -802,7 +802,7 @@ mod alter_model_remove {
assert_eq!( assert_eq!(
remove, remove,
AlterModel::new( AlterModel::new(
Ident::from("mymodel"), Entity::Single(Ident::from("mymodel")),
AlterKind::Remove(Box::from([ AlterKind::Remove(Box::from([
Ident::from("myfield1"), Ident::from("myfield1"),
Ident::from("myfield2"), Ident::from("myfield2"),
@ -816,7 +816,7 @@ mod alter_model_remove {
mod alter_model_add { mod alter_model_add {
use super::*; use super::*;
use crate::engine::ql::{ use crate::engine::ql::{
ast::parse_ast_node_full, ast::{parse_ast_node_full, Entity},
ddl::{ ddl::{
alt::{AlterKind, AlterModel}, alt::{AlterKind, AlterModel},
syn::{ExpandedField, LayerSpec}, syn::{ExpandedField, LayerSpec},
@ -833,7 +833,7 @@ mod alter_model_add {
assert_eq!( assert_eq!(
parse_ast_node_full::<AlterModel>(&tok[2..]).unwrap(), parse_ast_node_full::<AlterModel>(&tok[2..]).unwrap(),
AlterModel::new( AlterModel::new(
Ident::from("mymodel"), Entity::Single(Ident::from("mymodel")),
AlterKind::Add( AlterKind::Add(
[ExpandedField::new( [ExpandedField::new(
Ident::from("myfield"), Ident::from("myfield"),
@ -857,7 +857,7 @@ mod alter_model_add {
assert_eq!( assert_eq!(
r, r,
AlterModel::new( AlterModel::new(
Ident::from("mymodel"), Entity::Single(Ident::from("mymodel")),
AlterKind::Add( AlterKind::Add(
[ExpandedField::new( [ExpandedField::new(
Ident::from("myfield"), Ident::from("myfield"),
@ -883,7 +883,7 @@ mod alter_model_add {
assert_eq!( assert_eq!(
r, r,
AlterModel::new( AlterModel::new(
Ident::from("mymodel"), Entity::Single(Ident::from("mymodel")),
AlterKind::Add( AlterKind::Add(
[ExpandedField::new( [ExpandedField::new(
Ident::from("myfield"), Ident::from("myfield"),
@ -923,7 +923,7 @@ mod alter_model_add {
assert_eq!( assert_eq!(
r, r,
AlterModel::new( AlterModel::new(
Ident::from("mymodel"), Entity::Single(Ident::from("mymodel")),
AlterKind::Add( AlterKind::Add(
[ [
ExpandedField::new( ExpandedField::new(
@ -964,7 +964,7 @@ mod alter_model_add {
mod alter_model_update { mod alter_model_update {
use super::*; use super::*;
use crate::engine::ql::{ use crate::engine::ql::{
ast::parse_ast_node_full, ast::{parse_ast_node_full, Entity},
ddl::{ ddl::{
alt::{AlterKind, AlterModel}, alt::{AlterKind, AlterModel},
syn::{ExpandedField, LayerSpec}, syn::{ExpandedField, LayerSpec},
@ -983,7 +983,7 @@ mod alter_model_update {
assert_eq!( assert_eq!(
r, r,
AlterModel::new( AlterModel::new(
Ident::from("mymodel"), Entity::Single(Ident::from("mymodel")),
AlterKind::Update( AlterKind::Update(
[ExpandedField::new( [ExpandedField::new(
Ident::from("myfield"), Ident::from("myfield"),
@ -1007,7 +1007,7 @@ mod alter_model_update {
assert_eq!( assert_eq!(
r, r,
AlterModel::new( AlterModel::new(
Ident::from("mymodel"), Entity::Single(Ident::from("mymodel")),
AlterKind::Update( AlterKind::Update(
[ExpandedField::new( [ExpandedField::new(
Ident::from("myfield"), Ident::from("myfield"),
@ -1036,7 +1036,7 @@ mod alter_model_update {
assert_eq!( assert_eq!(
r, r,
AlterModel::new( AlterModel::new(
Ident::from("mymodel"), Entity::Single(Ident::from("mymodel")),
AlterKind::Update( AlterKind::Update(
[ExpandedField::new( [ExpandedField::new(
Ident::from("myfield"), Ident::from("myfield"),
@ -1070,7 +1070,7 @@ mod alter_model_update {
assert_eq!( assert_eq!(
r, r,
AlterModel::new( AlterModel::new(
Ident::from("mymodel"), Entity::Single(Ident::from("mymodel")),
AlterKind::Update( AlterKind::Update(
[ [
ExpandedField::new( ExpandedField::new(
@ -1113,7 +1113,7 @@ mod alter_model_update {
assert_eq!( assert_eq!(
r, r,
AlterModel::new( AlterModel::new(
Ident::from("mymodel"), Entity::Single(Ident::from("mymodel")),
AlterKind::Update( AlterKind::Update(
[ [
ExpandedField::new( ExpandedField::new(

Loading…
Cancel
Save