Require full entity in `create model`

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

@ -115,7 +115,8 @@ impl ModelView {
props,
}: CreateModel,
) -> DatabaseResult<Self> {
let mut okay = props.is_empty() & !fields.is_empty() & ItemID::check(&model_name);
let mut okay =
props.is_empty() & !fields.is_empty() & ItemID::check(model_name.any_single().as_str());
// validate fields
let mut field_spec = fields.into_iter();
let mut fields = IndexSTSeqCns::with_capacity(field_spec.len());
@ -154,18 +155,17 @@ impl ModelView {
}
impl ModelView {
pub fn exec_create(
gns: &super::GlobalNS,
space: &[u8],
stmt: CreateModel,
) -> DatabaseResult<()> {
pub fn exec_create(gns: &super::GlobalNS, stmt: CreateModel) -> DatabaseResult<()> {
let name = stmt.model_name;
let model = Self::process_create(stmt)?;
let space_rl = gns.spaces().read();
let Some(space) = space_rl.get(space) else {
let Some((space_name, model_name)) = name.into_full() else {
return Err(DatabaseError::ExpectedEntity);
};
let Some(space) = space_rl.get(space_name.as_bytes()) else {
return Err(DatabaseError::DdlSpaceNotFound)
};
space._create_model(ItemID::new(&name), model)
space._create_model(ItemID::new(model_name.as_str()), model)
}
}

@ -53,7 +53,7 @@ fn exec_plan(
plan: &str,
f: impl Fn(&ModelView),
) -> DatabaseResult<()> {
exec_create(gns, model, "myspace", new_space)?;
exec_create(gns, model, new_space)?;
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();
@ -79,7 +79,7 @@ mod plan {
#[test]
fn simple_add() {
super::plan(
"create model mymodel(username: string, password: binary)",
"create model myspace.mymodel(username: string, password: binary)",
"alter model myspace.mymodel add myfield { type: string, nullable: true }",
|plan| {
assert_eq!(plan.model.into_full().unwrap().1.as_str(), "mymodel");
@ -96,7 +96,7 @@ mod plan {
#[test]
fn simple_remove() {
super::plan(
"create model mymodel(username: string, password: binary, useless_field: uint8)",
"create model myspace.mymodel(username: string, password: binary, useless_field: uint8)",
"alter model myspace.mymodel remove useless_field",
|plan| {
assert_eq!(plan.model.into_full().unwrap().1.as_str(), "mymodel");
@ -112,7 +112,7 @@ mod plan {
fn simple_update() {
// FREEDOM! DAMN THE PASSWORD!
super::plan(
"create model mymodel(username: string, password: binary)",
"create model myspace.mymodel(username: string, password: binary)",
"alter model myspace.mymodel update password { nullable: true }",
|plan| {
assert_eq!(plan.model.into_full().unwrap().1.as_str(), "mymodel");
@ -130,7 +130,7 @@ mod plan {
fn update_need_lock() {
// FIGHT THE NULL
super::plan(
"create model mymodel(username: string, null password: binary)",
"create model myspace.mymodel(username: string, null password: binary)",
"alter model myspace.mymodel update password { nullable: false }",
|plan| {
assert_eq!(plan.model.into_full().unwrap().1.as_str(), "mymodel");
@ -151,7 +151,7 @@ mod plan {
fn illegal_remove_nx() {
assert_eq!(
super::with_plan(
"create model mymodel(username: string, password: binary)",
"create model myspace.mymodel(username: string, password: binary)",
"alter model myspace.mymodel remove password_e2e",
|_| {}
)
@ -163,7 +163,7 @@ mod plan {
fn illegal_remove_pk() {
assert_eq!(
super::with_plan(
"create model mymodel(username: string, password: binary)",
"create model myspace.mymodel(username: string, password: binary)",
"alter model myspace.mymodel remove username",
|_| {}
)
@ -175,7 +175,7 @@ mod plan {
fn illegal_add_pk() {
assert_eq!(
super::with_plan(
"create model mymodel(username: string, password: binary)",
"create model myspace.mymodel(username: string, password: binary)",
"alter model myspace.mymodel add username { type: string }",
|_| {}
)
@ -187,7 +187,7 @@ mod plan {
fn illegal_add_ex() {
assert_eq!(
super::with_plan(
"create model mymodel(username: string, password: binary)",
"create model myspace.mymodel(username: string, password: binary)",
"alter model myspace.mymodel add password { type: string }",
|_| {}
)
@ -199,7 +199,7 @@ mod plan {
fn illegal_update_pk() {
assert_eq!(
super::with_plan(
"create model mymodel(username: string, password: binary)",
"create model myspace.mymodel(username: string, password: binary)",
"alter model myspace.mymodel update username { type: string }",
|_| {}
)
@ -211,7 +211,7 @@ mod plan {
fn illegal_update_nx() {
assert_eq!(
super::with_plan(
"create model mymodel(username: string, password: binary)",
"create model myspace.mymodel(username: string, password: binary)",
"alter model myspace.mymodel update username_secret { type: string }",
|_| {}
)
@ -220,7 +220,8 @@ mod plan {
);
}
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 myspace.mymodel(username: string, silly_field: {orig_ty})");
let alter = format!("alter model myspace.mymodel update silly_field {{ type: {new_ty} }}");
assert_eq!(
super::with_plan(&create, &alter, |_| {}).expect_err(&format!(
@ -349,7 +350,7 @@ mod exec {
super::exec_plan(
&gns,
true,
"create model mymodel(username: string, password: binary)",
"create model myspace.mymodel(username: string, password: binary)",
"alter model myspace.mymodel update password { nullable: true }",
|model| {
let schema = model.intent_read_model();

@ -140,8 +140,7 @@ mod exec {
let gns = GlobalNS::empty();
exec_create_new_space(
&gns,
"create model mymodel(username: string, password: binary)",
SPACE,
"create model myspace.mymodel(username: string, password: binary)",
)
.unwrap();
with_model(&gns, SPACE, "mymodel", |model| {

@ -32,7 +32,7 @@ use crate::engine::{
core::{model::ModelView, space::Space, GlobalNS},
error::DatabaseResult,
idx::STIndex,
ql::{ast::parse_ast_node_full, tests::lex_insecure},
ql::{ast::parse_ast_node_full, ddl::crt::CreateModel, tests::lex_insecure},
};
fn create(s: &str) -> DatabaseResult<ModelView> {
@ -44,31 +44,22 @@ fn create(s: &str) -> DatabaseResult<ModelView> {
pub fn exec_create(
gns: &GlobalNS,
create_stmt: &str,
space_id: &str,
create_new_space: bool,
) -> DatabaseResult<()> {
let tok = lex_insecure(create_stmt.as_bytes()).unwrap();
let create_model = parse_ast_node_full::<CreateModel>(&tok[2..]).unwrap();
if create_new_space {
assert!(gns.test_new_empty_space(space_id));
gns.test_new_empty_space(&create_model.model_name.into_full().unwrap().0);
}
let tok = lex_insecure(create_stmt.as_bytes()).unwrap();
let create_model = parse_ast_node_full(&tok[2..]).unwrap();
ModelView::exec_create(gns, space_id.as_bytes(), create_model)
ModelView::exec_create(gns, create_model)
}
pub fn exec_create_new_space(
gns: &GlobalNS,
create_stmt: &str,
space_id: &str,
) -> DatabaseResult<()> {
exec_create(gns, create_stmt, space_id, true)
pub fn exec_create_new_space(gns: &GlobalNS, create_stmt: &str) -> DatabaseResult<()> {
exec_create(gns, create_stmt, true)
}
pub fn exec_create_no_create(
gns: &GlobalNS,
create_stmt: &str,
space_id: &str,
) -> DatabaseResult<()> {
exec_create(gns, create_stmt, space_id, false)
pub fn exec_create_no_create(gns: &GlobalNS, create_stmt: &str) -> DatabaseResult<()> {
exec_create(gns, create_stmt, false)
}
fn with_space(gns: &GlobalNS, space_name: &str, f: impl Fn(&Space)) {

@ -376,6 +376,12 @@ pub enum Entity<'a> {
}
impl<'a> Entity<'a> {
pub fn any_single(self) -> Ident<'a> {
match self {
Self::Full(_, e) => e,
Self::Single(e) => e,
}
}
pub fn into_full(self) -> Option<(Ident<'a>, Ident<'a>)> {
if let Self::Full(a, b) = self {
Some((a, b))

@ -31,11 +31,11 @@ use {
data::DictGeneric,
error::{LangError, LangResult},
ql::{
ast::{QueryData, State},
ast::{Entity, QueryData, State},
lex::Ident,
},
},
util::compiler,
util::{compiler, MaybeInit},
},
};
@ -85,7 +85,7 @@ impl<'a> CreateSpace<'a> {
/// A model definition
pub struct CreateModel<'a> {
/// the model name
pub(in crate::engine) model_name: Ident<'a>,
pub(in crate::engine) model_name: Entity<'a>,
/// the fields
pub(in crate::engine) fields: Vec<FieldSpec<'a>>,
/// properties
@ -100,7 +100,7 @@ pub struct CreateModel<'a> {
*/
impl<'a> CreateModel<'a> {
pub fn new(model_name: Ident<'a>, fields: Vec<FieldSpec<'a>>, props: DictGeneric) -> Self {
pub fn new(model_name: Entity<'a>, fields: Vec<FieldSpec<'a>>, props: DictGeneric) -> Self {
Self {
model_name,
fields,
@ -113,8 +113,8 @@ impl<'a> CreateModel<'a> {
return compiler::cold_rerr(LangError::UnexpectedEOS);
}
// model name; ignore errors
let model_name = state.fw_read();
state.poison_if_not(model_name.is_ident());
let mut model_uninit = MaybeInit::uninit();
Entity::parse_from_state_len_unchecked(state, &mut model_uninit);
state.poison_if_not(state.cursor_eq(Token![() open]));
state.cursor_ahead();
// fields
@ -140,8 +140,8 @@ impl<'a> CreateModel<'a> {
if state.okay() {
Ok(Self {
model_name: unsafe {
// UNSAFE(@ohsayan): we verified if `model_name` returns `is_ident`
model_name.uck_read_ident()
// UNSAFE(@ohsayan): we verified if `model_name` is initialized through the state
model_uninit.assume_init()
},
fields,
props,

@ -414,7 +414,7 @@ mod fields {
mod schemas {
use super::*;
use crate::engine::ql::{
ast::parse_ast_node_full,
ast::{parse_ast_node_full, Entity},
ddl::{
crt::CreateModel,
syn::{FieldSpec, LayerSpec},
@ -439,7 +439,7 @@ mod schemas {
assert_eq!(
model,
CreateModel::new(
Ident::from("mymodel"),
Entity::Single(Ident::from("mymodel")),
vec![
FieldSpec::new(
Ident::from("username"),
@ -478,7 +478,7 @@ mod schemas {
assert_eq!(
model,
CreateModel::new(
Ident::from("mymodel"),
Entity::Single(Ident::from("mymodel")),
vec![
FieldSpec::new(
Ident::from("username"),
@ -528,7 +528,7 @@ mod schemas {
assert_eq!(
model,
CreateModel::new(
Ident::from("mymodel"),
Entity::Single(Ident::from("mymodel")),
vec![
FieldSpec::new(
Ident::from("username"),
@ -597,7 +597,7 @@ mod schemas {
assert_eq!(
model,
CreateModel::new(
Ident::from("mymodel"),
Entity::Single(Ident::from("mymodel")),
vec![
FieldSpec::new(
Ident::from("username"),

Loading…
Cancel
Save