DDL: return bool only if EX/NX used

next
Sayan Nandan 10 months ago
parent 8c4009f2b8
commit 179fb09544
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -43,7 +43,7 @@ use crate::{
pub use {
del::delete,
ins::insert,
sel::{select_custom, select_all},
sel::{select_all, select_custom},
upd::{collect_trace_path as update_flow_trace, update},
};
pub use {

@ -93,6 +93,14 @@ fn _callgcs<A: ASTNode<'static> + core::fmt::Debug, T>(
f(&g, cstate, a)
}
#[inline(always)]
fn translate_ddl_result(x: Option<bool>) -> Response {
match x {
Some(b) => Response::Bool(b),
None => Response::Empty,
}
}
async fn run_blocking_stmt(
global: &Global,
cstate: &mut ClientLocalState,
@ -132,12 +140,26 @@ async fn run_blocking_stmt(
) -> QueryResult<Response>; 8] = [
|_, _, _| Err(QueryError::QLUnknownStatement),
blocking_exec_sysctl,
|g, _, t| _callgs_map(&g, t, Space::transactional_exec_create, Response::Bool),
|g, _, t| _callgs_map(&g, t, Model::transactional_exec_create, Response::Bool),
|g, _, t| {
_callgs_map(
&g,
t,
Space::transactional_exec_create,
translate_ddl_result,
)
},
|g, _, t| {
_callgs_map(
&g,
t,
Model::transactional_exec_create,
translate_ddl_result,
)
},
|g, _, t| _callgs_map(&g, t, Space::transactional_exec_alter, |_| Response::Empty),
|g, _, t| _callgs_map(&g, t, Model::transactional_exec_alter, |_| Response::Empty),
|g, _, t| _callgs_map(&g, t, Space::transactional_exec_drop, Response::Bool),
|g, _, t| _callgs_map(&g, t, Model::transactional_exec_drop, Response::Bool),
|g, _, t| _callgs_map(&g, t, Space::transactional_exec_drop, translate_ddl_result),
|g, _, t| _callgs_map(&g, t, Model::transactional_exec_drop, translate_ddl_result),
];
let r = unsafe {
// UNSAFE(@ohsayan): the only await is within this block

@ -267,7 +267,7 @@ impl Model {
pub fn transactional_exec_create<G: GlobalInstanceLike>(
global: &G,
stmt: CreateModel,
) -> QueryResult<bool> {
) -> QueryResult<Option<bool>> {
let (space_name, model_name) = (stmt.model_name.space(), stmt.model_name.entity());
let if_nx = stmt.if_not_exists;
let model = Self::process_create(stmt)?;
@ -275,7 +275,7 @@ impl Model {
// TODO(@ohsayan): be extra cautious with post-transactional tasks (memck)
if space.models().contains(model_name) {
if if_nx {
return Ok(false);
return Ok(Some(false));
} else {
return Err(QueryError::QExecDdlObjectAlreadyExists);
}
@ -320,18 +320,22 @@ impl Model {
.idx_models()
.write()
.insert(EntityID::new(&space_name, &model_name), model);
Ok(true)
if if_nx {
Ok(Some(true))
} else {
Ok(None)
}
})
}
pub fn transactional_exec_drop<G: GlobalInstanceLike>(
global: &G,
stmt: DropModel,
) -> QueryResult<bool> {
) -> QueryResult<Option<bool>> {
let (space_name, model_name) = (stmt.entity.space(), stmt.entity.entity());
global.namespace().ddl_with_space_mut(&space_name, |space| {
if !space.models().contains(model_name) {
if stmt.if_exists {
return Ok(false);
return Ok(Some(false));
} else {
// the model isn't even present
return Err(QueryError::QExecObjectNotFound);
@ -370,7 +374,11 @@ impl Model {
// update global state
let _ = models_idx.remove(&EntityIDRef::new(&space_name, &model_name));
let _ = space.models_mut().remove(model_name);
Ok(true)
if stmt.if_exists {
Ok(Some(true))
} else {
Ok(None)
}
})
}
}

@ -148,7 +148,7 @@ impl Space {
pub fn transactional_exec_create<G: GlobalInstanceLike>(
global: &G,
space: CreateSpace,
) -> QueryResult<bool> {
) -> QueryResult<Option<bool>> {
// process create
let ProcedureCreate {
space_name,
@ -159,7 +159,7 @@ impl Space {
global.namespace().ddl_with_spaces_write(|spaces| {
if spaces.st_contains(&space_name) {
if if_not_exists {
return Ok(false);
return Ok(Some(false));
} else {
return Err(QueryError::QExecDdlObjectAlreadyExists);
}
@ -187,7 +187,11 @@ impl Space {
}
// update global state
let _ = spaces.st_insert(space_name, space);
Ok(true)
if if_not_exists {
Ok(Some(true))
} else {
Ok(None)
}
})
}
#[allow(unused)]
@ -234,12 +238,12 @@ impl Space {
force,
if_exists,
}: DropSpace,
) -> QueryResult<bool> {
) -> QueryResult<Option<bool>> {
if force {
global.namespace().ddl_with_all_mut(|spaces, models| {
let Some(space) = spaces.remove(space_name.as_str()) else {
if if_exists {
return Ok(false);
return Ok(Some(false));
} else {
return Err(QueryError::QExecObjectNotFound);
}
@ -272,13 +276,17 @@ impl Space {
);
}
let _ = spaces.st_delete(space_name.as_str());
Ok(true)
if if_exists {
Ok(Some(true))
} else {
Ok(None)
}
})
} else {
global.namespace().ddl_with_spaces_write(|spaces| {
let Some(space) = spaces.get(space_name.as_str()) else {
if if_exists {
return Ok(false);
return Ok(Some(false));
} else {
return Err(QueryError::QExecObjectNotFound);
}
@ -300,7 +308,11 @@ impl Space {
));
}
let _ = spaces.st_delete(space_name.as_str());
Ok(true)
if if_exists {
Ok(Some(true))
} else {
Ok(None)
}
})
}
}

@ -84,7 +84,6 @@ where
i: RawIter<'t, 'g, 'v, T, C, CfgIterEntry>,
}
impl<'t, 'g, 'v, T, C> IterEntry<'t, 'g, 'v, T, C>
where
't: 'v,

@ -143,23 +143,14 @@ fn lex_string_escape_bs() {
#[test]
fn lex_string_bad_escape() {
let wth = br#" '\a should be an alert on windows apparently' "#;
assert_eq!(
lex_insecure(wth).unwrap_err(),
QueryError::LexInvalidInput
);
assert_eq!(lex_insecure(wth).unwrap_err(), QueryError::LexInvalidInput);
}
#[test]
fn lex_string_unclosed() {
let wth = br#" 'omg where did the end go "#;
assert_eq!(
lex_insecure(wth).unwrap_err(),
QueryError::LexInvalidInput
);
assert_eq!(lex_insecure(wth).unwrap_err(), QueryError::LexInvalidInput);
let wth = br#" 'see, we escaped the end\' "#;
assert_eq!(
lex_insecure(wth).unwrap_err(),
QueryError::LexInvalidInput
);
assert_eq!(lex_insecure(wth).unwrap_err(), QueryError::LexInvalidInput);
}
#[test]
fn lex_unsafe_literal_mini() {

@ -23,4 +23,3 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

Loading…
Cancel
Save