create and delete

main
Ziyang Hu 1 year ago
parent 662c59c967
commit 57a326918d

@ -135,10 +135,11 @@ limit_option = {":limit" ~ expr}
offset_option = {":offset" ~ expr} offset_option = {":offset" ~ expr}
sort_option = {(":sort" | ":order") ~ (sort_arg ~ ",")* ~ sort_arg } sort_option = {(":sort" | ":order") ~ (sort_arg ~ ",")* ~ sort_arg }
relation_option = {relation_op ~ (compound_ident | underscore_ident) ~ table_schema?} relation_option = {relation_op ~ (compound_ident | underscore_ident) ~ table_schema?}
relation_op = _{relation_create | relation_replace | relation_insert | relation_put | relation_update | relation_rm | relation_ensure_not | relation_ensure } relation_op = _{relation_create | relation_replace | relation_insert | relation_put | relation_update | relation_rm | relation_delete | relation_ensure_not | relation_ensure }
relation_create = {":create"} relation_create = {":create"}
relation_replace = {":replace"} relation_replace = {":replace"}
relation_insert = {":insert"} relation_insert = {":insert"}
relation_delete = {":delete"}
relation_put = {":put"} relation_put = {":put"}
relation_update = {":update"} relation_update = {":update"}
relation_rm = {":rm"} relation_rm = {":rm"}

@ -105,6 +105,9 @@ impl Display for QueryOutOptions {
RelationOp::Rm => { RelationOp::Rm => {
write!(f, ":rm ")?; write!(f, ":rm ")?;
} }
RelationOp::Delete => {
write!(f, ":delete ")?;
}
RelationOp::Ensure => { RelationOp::Ensure => {
write!(f, ":ensure ")?; write!(f, ":ensure ")?;
} }
@ -184,6 +187,7 @@ pub(crate) enum RelationOp {
Insert, Insert,
Update, Update,
Rm, Rm,
Delete,
Ensure, Ensure,
EnsureNot, EnsureNot,
} }

@ -320,6 +320,7 @@ pub(crate) fn parse_query(
Rule::relation_insert => RelationOp::Insert, Rule::relation_insert => RelationOp::Insert,
Rule::relation_update => RelationOp::Update, Rule::relation_update => RelationOp::Update,
Rule::relation_rm => RelationOp::Rm, Rule::relation_rm => RelationOp::Rm,
Rule::relation_delete => RelationOp::Delete,
Rule::relation_ensure => RelationOp::Ensure, Rule::relation_ensure => RelationOp::Ensure,
Rule::relation_ensure_not => RelationOp::EnsureNot, Rule::relation_ensure_not => RelationOp::EnsureNot,
_ => unreachable!(), _ => unreachable!(),

@ -44,7 +44,7 @@ impl<'a> SessionTx<'a> {
pub(crate) fn execute_relation<'s, S: Storage<'s>>( pub(crate) fn execute_relation<'s, S: Storage<'s>>(
&mut self, &mut self,
db: &Db<S>, db: &Db<S>,
res_iter: impl Iterator<Item=Tuple>, res_iter: impl Iterator<Item = Tuple>,
op: RelationOp, op: RelationOp,
meta: &InputRelationHandle, meta: &InputRelationHandle,
headers: &[Symbol], headers: &[Symbol],
@ -88,7 +88,7 @@ impl<'a> SessionTx<'a> {
&db.fixed_rules.read().unwrap(), &db.fixed_rules.read().unwrap(),
cur_vld, cur_vld,
)? )?
.get_single_program()?; .get_single_program()?;
let (_, cleanups) = db let (_, cleanups) = db
.run_query( .run_query(
@ -132,7 +132,7 @@ impl<'a> SessionTx<'a> {
} = meta; } = meta;
match op { match op {
RelationOp::Rm => self.remove_from_relation( RelationOp::Rm | RelationOp::Delete => self.remove_from_relation(
db, db,
res_iter, res_iter,
headers, headers,
@ -144,6 +144,7 @@ impl<'a> SessionTx<'a> {
&mut relation_store, &mut relation_store,
metadata, metadata,
key_bindings, key_bindings,
op == RelationOp::Delete,
*span, *span,
)?, )?,
RelationOp::Ensure => self.ensure_in_relation( RelationOp::Ensure => self.ensure_in_relation(
@ -178,22 +179,23 @@ impl<'a> SessionTx<'a> {
key_bindings, key_bindings,
*span, *span,
)?, )?,
RelationOp::Create | RelationOp::Replace | RelationOp::Put | RelationOp::Insert => self.put_into_relation( RelationOp::Create | RelationOp::Replace | RelationOp::Put | RelationOp::Insert => self
db, .put_into_relation(
res_iter, db,
headers, res_iter,
cur_vld, headers,
callback_targets, cur_vld,
callback_collector, callback_targets,
propagate_triggers, callback_collector,
&mut to_clear, propagate_triggers,
&mut relation_store, &mut to_clear,
metadata, &mut relation_store,
key_bindings, metadata,
dep_bindings, key_bindings,
op == RelationOp::Insert, dep_bindings,
*span, op == RelationOp::Insert,
)?, *span,
)?,
}; };
Ok(to_clear) Ok(to_clear)
@ -202,7 +204,7 @@ impl<'a> SessionTx<'a> {
fn put_into_relation<'s, S: Storage<'s>>( fn put_into_relation<'s, S: Storage<'s>>(
&mut self, &mut self,
db: &Db<S>, db: &Db<S>,
res_iter: impl Iterator<Item=Tuple>, res_iter: impl Iterator<Item = Tuple>,
headers: &[Symbol], headers: &[Symbol],
cur_vld: ValidityTs, cur_vld: ValidityTs,
callback_targets: &BTreeSet<SmartString<LazyCompact>>, callback_targets: &BTreeSet<SmartString<LazyCompact>>,
@ -235,7 +237,7 @@ impl<'a> SessionTx<'a> {
let need_to_collect = !relation_store.is_temp let need_to_collect = !relation_store.is_temp
&& (is_callback_target && (is_callback_target
|| (propagate_triggers && !relation_store.put_triggers.is_empty())); || (propagate_triggers && !relation_store.put_triggers.is_empty()));
let has_indices = !relation_store.indices.is_empty(); let has_indices = !relation_store.indices.is_empty();
let has_hnsw_indices = !relation_store.hnsw_indices.is_empty(); let has_hnsw_indices = !relation_store.hnsw_indices.is_empty();
let has_fts_indices = !relation_store.fts_indices.is_empty(); let has_fts_indices = !relation_store.fts_indices.is_empty();
@ -270,8 +272,16 @@ impl<'a> SessionTx<'a> {
.map(|ex| ex.extract_data(&tuple, cur_vld)) .map(|ex| ex.extract_data(&tuple, cur_vld))
.try_collect()?; .try_collect()?;
let key = relation_store.encode_key_for_store(&extracted, span)?;
if is_insert { if is_insert {
if relation_store.exists(self, &extracted[..relation_store.metadata.keys.len()])? { let already_exists = if relation_store.is_temp {
self.temp_store_tx.exists(&key, true)?
} else {
self.store_tx.exists(&key, true)?
};
if already_exists {
bail!(TransactAssertionFailure { bail!(TransactAssertionFailure {
relation: relation_store.name.to_string(), relation: relation_store.name.to_string(),
key: extracted, key: extracted,
@ -280,7 +290,6 @@ impl<'a> SessionTx<'a> {
} }
} }
let key = relation_store.encode_key_for_store(&extracted, span)?;
let val = relation_store.encode_val_for_store(&extracted, span)?; let val = relation_store.encode_val_for_store(&extracted, span)?;
if need_to_collect if need_to_collect
@ -508,7 +517,7 @@ impl<'a> SessionTx<'a> {
fn update_in_relation<'s, S: Storage<'s>>( fn update_in_relation<'s, S: Storage<'s>>(
&mut self, &mut self,
db: &Db<S>, db: &Db<S>,
res_iter: impl Iterator<Item=Tuple>, res_iter: impl Iterator<Item = Tuple>,
headers: &[Symbol], headers: &[Symbol],
cur_vld: ValidityTs, cur_vld: ValidityTs,
callback_targets: &BTreeSet<SmartString<LazyCompact>>, callback_targets: &BTreeSet<SmartString<LazyCompact>>,
@ -539,7 +548,7 @@ impl<'a> SessionTx<'a> {
let need_to_collect = !relation_store.is_temp let need_to_collect = !relation_store.is_temp
&& (is_callback_target && (is_callback_target
|| (propagate_triggers && !relation_store.put_triggers.is_empty())); || (propagate_triggers && !relation_store.put_triggers.is_empty()));
let has_indices = !relation_store.indices.is_empty(); let has_indices = !relation_store.indices.is_empty();
let has_hnsw_indices = !relation_store.hnsw_indices.is_empty(); let has_hnsw_indices = !relation_store.hnsw_indices.is_empty();
let has_fts_indices = !relation_store.fts_indices.is_empty(); let has_fts_indices = !relation_store.fts_indices.is_empty();
@ -686,7 +695,7 @@ impl<'a> SessionTx<'a> {
&db.fixed_rules.read().unwrap(), &db.fixed_rules.read().unwrap(),
cur_vld, cur_vld,
)? )?
.get_single_program()?; .get_single_program()?;
make_const_rule( make_const_rule(
&mut program, &mut program,
@ -782,7 +791,7 @@ impl<'a> SessionTx<'a> {
fn ensure_not_in_relation( fn ensure_not_in_relation(
&mut self, &mut self,
res_iter: impl Iterator<Item=Tuple>, res_iter: impl Iterator<Item = Tuple>,
headers: &[Symbol], headers: &[Symbol],
cur_vld: ValidityTs, cur_vld: ValidityTs,
relation_store: &mut RelationHandle, relation_store: &mut RelationHandle,
@ -829,7 +838,7 @@ impl<'a> SessionTx<'a> {
fn ensure_in_relation( fn ensure_in_relation(
&mut self, &mut self,
res_iter: impl Iterator<Item=Tuple>, res_iter: impl Iterator<Item = Tuple>,
headers: &[Symbol], headers: &[Symbol],
cur_vld: ValidityTs, cur_vld: ValidityTs,
relation_store: &mut RelationHandle, relation_store: &mut RelationHandle,
@ -899,7 +908,7 @@ impl<'a> SessionTx<'a> {
fn remove_from_relation<'s, S: Storage<'s>>( fn remove_from_relation<'s, S: Storage<'s>>(
&mut self, &mut self,
db: &Db<S>, db: &Db<S>,
res_iter: impl Iterator<Item=Tuple>, res_iter: impl Iterator<Item = Tuple>,
headers: &[Symbol], headers: &[Symbol],
cur_vld: ValidityTs, cur_vld: ValidityTs,
callback_targets: &BTreeSet<SmartString<LazyCompact>>, callback_targets: &BTreeSet<SmartString<LazyCompact>>,
@ -909,6 +918,7 @@ impl<'a> SessionTx<'a> {
relation_store: &mut RelationHandle, relation_store: &mut RelationHandle,
metadata: &StoredRelationMetadata, metadata: &StoredRelationMetadata,
key_bindings: &[Symbol], key_bindings: &[Symbol],
check_exists: bool,
span: SourceSpan, span: SourceSpan,
) -> Result<()> { ) -> Result<()> {
let is_callback_target = callback_targets.contains(&relation_store.name); let is_callback_target = callback_targets.contains(&relation_store.name);
@ -929,7 +939,7 @@ impl<'a> SessionTx<'a> {
let need_to_collect = !relation_store.is_temp let need_to_collect = !relation_store.is_temp
&& (is_callback_target && (is_callback_target
|| (propagate_triggers && !relation_store.rm_triggers.is_empty())); || (propagate_triggers && !relation_store.rm_triggers.is_empty()));
let has_indices = !relation_store.indices.is_empty(); let has_indices = !relation_store.indices.is_empty();
let has_hnsw_indices = !relation_store.hnsw_indices.is_empty(); let has_hnsw_indices = !relation_store.hnsw_indices.is_empty();
let has_fts_indices = !relation_store.fts_indices.is_empty(); let has_fts_indices = !relation_store.fts_indices.is_empty();
@ -944,6 +954,20 @@ impl<'a> SessionTx<'a> {
.map(|ex| ex.extract_data(&tuple, cur_vld)) .map(|ex| ex.extract_data(&tuple, cur_vld))
.try_collect()?; .try_collect()?;
let key = relation_store.encode_key_for_store(&extracted, span)?; let key = relation_store.encode_key_for_store(&extracted, span)?;
if check_exists {
let exists = if relation_store.is_temp {
self.temp_store_tx.exists(&key, false)?
} else {
self.store_tx.exists(&key, false)?
};
if !exists {
bail!(TransactAssertionFailure {
relation: relation_store.name.to_string(),
key: extracted,
notice: "key does not exists in database".to_string()
});
}
}
if need_to_collect || has_indices || has_hnsw_indices || has_fts_indices { if need_to_collect || has_indices || has_hnsw_indices || has_fts_indices {
if let Some(existing) = self.store_tx.get(&key, false)? { if let Some(existing) = self.store_tx.get(&key, false)? {
let mut tup = extracted.clone(); let mut tup = extracted.clone();
@ -1004,7 +1028,7 @@ impl<'a> SessionTx<'a> {
&db.fixed_rules.read().unwrap(), &db.fixed_rules.read().unwrap(),
cur_vld, cur_vld,
)? )?
.get_single_program()?; .get_single_program()?;
make_const_rule(&mut program, "_new", k_bindings.clone(), new_tuples.clone()); make_const_rule(&mut program, "_new", k_bindings.clone(), new_tuples.clone());

@ -1377,8 +1377,10 @@ impl<'s, S: Storage<'s>> Db<S> {
StoreRelationNotFoundError(meta.name.to_string()) StoreRelationNotFoundError(meta.name.to_string())
); );
existing existing.ensure_compatible(
.ensure_compatible(meta, *op == RelationOp::Rm || *op == RelationOp::Update)?; meta,
*op == RelationOp::Rm || *op == RelationOp::Delete || *op == RelationOp::Update,
)?;
} }
}; };

@ -122,7 +122,7 @@ fn test_conditions() {
"#, "#,
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
debug!("real test begins"); debug!("real test begins");
let res = db let res = db
.run_script( .run_script(
@ -168,7 +168,7 @@ fn default_columns() {
"#, "#,
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r#" r#"
@ -177,7 +177,7 @@ fn default_columns() {
"#, "#,
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
} }
#[test] #[test]
@ -391,12 +391,12 @@ fn test_trigger() {
":create friends {fr: Int, to: Int => data: Any}", ":create friends {fr: Int, to: Int => data: Any}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
":create friends.rev {to: Int, fr: Int => data: Any}", ":create friends.rev {to: Int, fr: Int => data: Any}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r#" r#"
::set_triggers friends ::set_triggers friends
@ -414,12 +414,12 @@ fn test_trigger() {
"#, "#,
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r"?[fr, to, data] <- [[1,2,3]] :put friends {fr, to => data}", r"?[fr, to, data] <- [[1,2,3]] :put friends {fr, to => data}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
let ret = db let ret = db
.export_relations(["friends", "friends.rev"].into_iter()) .export_relations(["friends", "friends.rev"].into_iter())
.unwrap(); .unwrap();
@ -438,7 +438,7 @@ fn test_trigger() {
r"?[fr, to] <- [[1,2], [2,3]] :rm friends {fr, to}", r"?[fr, to] <- [[1,2], [2,3]] :rm friends {fr, to}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
let ret = db let ret = db
.export_relations(["friends", "friends.rev"].into_iter()) .export_relations(["friends", "friends.rev"].into_iter())
.unwrap(); .unwrap();
@ -455,22 +455,22 @@ fn test_callback() {
":create friends {fr: Int, to: Int => data: Any}", ":create friends {fr: Int, to: Int => data: Any}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r"?[fr, to, data] <- [[1,2,3],[4,5,6]] :put friends {fr, to => data}", r"?[fr, to, data] <- [[1,2,3],[4,5,6]] :put friends {fr, to => data}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r"?[fr, to, data] <- [[1,2,4],[4,7,6]] :put friends {fr, to => data}", r"?[fr, to, data] <- [[1,2,4],[4,7,6]] :put friends {fr, to => data}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r"?[fr, to] <- [[1,9],[4,5]] :rm friends {fr, to}", r"?[fr, to] <- [[1,9],[4,5]] :rm friends {fr, to}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
std::thread::sleep(Duration::from_secs_f64(0.01)); std::thread::sleep(Duration::from_secs_f64(0.01));
while let Ok(d) = receiver.try_recv() { while let Ok(d) = receiver.try_recv() {
collected.push(d); collected.push(d);
@ -502,12 +502,12 @@ fn test_update() {
":create friends {fr: Int, to: Int => a: Any, b: Any, c: Any}", ":create friends {fr: Int, to: Int => a: Any, b: Any, c: Any}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
"?[fr, to, a, b, c] <- [[1,2,3,4,5]] :put friends {fr, to => a, b, c}", "?[fr, to, a, b, c] <- [[1,2,3,4,5]] :put friends {fr, to => a, b, c}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
let res = db let res = db
.run_script( .run_script(
"?[fr, to, a, b, c] := *friends{fr, to, a, b, c}", "?[fr, to, a, b, c] := *friends{fr, to, a, b, c}",
@ -520,7 +520,7 @@ fn test_update() {
"?[fr, to, b] <- [[1, 2, 100]] :update friends {fr, to => b}", "?[fr, to, b] <- [[1, 2, 100]] :update friends {fr, to => b}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
let res = db let res = db
.run_script( .run_script(
"?[fr, to, a, b, c] := *friends{fr, to, a, b, c}", "?[fr, to, a, b, c] := *friends{fr, to, a, b, c}",
@ -538,13 +538,13 @@ fn test_index() {
":create friends {fr: Int, to: Int => data: Any}", ":create friends {fr: Int, to: Int => data: Any}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r"?[fr, to, data] <- [[1,2,3],[4,5,6]] :put friends {fr, to, data}", r"?[fr, to, data] <- [[1,2,3],[4,5,6]] :put friends {fr, to, data}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
assert!(db assert!(db
.run_script("::index create friends:rev {to, no}", Default::default()) .run_script("::index create friends:rev {to, no}", Default::default())
@ -556,12 +556,12 @@ fn test_index() {
r"?[fr, to, data] <- [[1,2,5],[6,5,7]] :put friends {fr, to => data}", r"?[fr, to, data] <- [[1,2,5],[6,5,7]] :put friends {fr, to => data}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r"?[fr, to] <- [[4,5]] :rm friends {fr, to}", r"?[fr, to] <- [[4,5]] :rm friends {fr, to}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
let rels_data = db let rels_data = db
.export_relations(["friends", "friends:rev"].into_iter()) .export_relations(["friends", "friends:rev"].into_iter())
@ -629,7 +629,7 @@ fn test_json_objects() {
}", }",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
} }
#[test] #[test]
@ -690,13 +690,13 @@ fn test_index_short() {
":create friends {fr: Int, to: Int => data: Any}", ":create friends {fr: Int, to: Int => data: Any}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r"?[fr, to, data] <- [[1,2,3],[4,5,6]] :put friends {fr, to => data}", r"?[fr, to, data] <- [[1,2,3],[4,5,6]] :put friends {fr, to => data}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script("::index create friends:rev {to}", Default::default()) db.run_script("::index create friends:rev {to}", Default::default())
.unwrap(); .unwrap();
@ -705,12 +705,12 @@ fn test_index_short() {
r"?[fr, to, data] <- [[1,2,5],[6,5,7]] :put friends {fr, to => data}", r"?[fr, to, data] <- [[1,2,5],[6,5,7]] :put friends {fr, to => data}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r"?[fr, to] <- [[4,5]] :rm friends {fr, to}", r"?[fr, to] <- [[4,5]] :rm friends {fr, to}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
let rels_data = db let rels_data = db
.export_relations(["friends", "friends:rev"].into_iter()) .export_relations(["friends", "friends:rev"].into_iter())
@ -806,7 +806,7 @@ fn test_vec_types() {
"?[k, v] <- [['k', [1,2,3,4,5,6,7,8]]] :put a {k => v}", "?[k, v] <- [['k', [1,2,3,4,5,6,7,8]]] :put a {k => v}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
let res = db let res = db
.run_script("?[k, v] := *a{k, v}", Default::default()) .run_script("?[k, v] := *a{k, v}", Default::default())
.unwrap(); .unwrap();
@ -851,7 +851,7 @@ fn test_vec_index() {
", ",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r" r"
::hnsw create a:vec { ::hnsw create a:vec {
@ -867,7 +867,7 @@ fn test_vec_index() {
}", }",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r" r"
?[k, v] <- [ ?[k, v] <- [
@ -882,7 +882,7 @@ fn test_vec_index() {
", ",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
println!("all links"); println!("all links");
for (_, nrows) in db.export_relations(["a:vec"].iter()).unwrap() { for (_, nrows) in db.export_relations(["a:vec"].iter()).unwrap() {
@ -917,7 +917,7 @@ fn test_fts_indexing() {
r"?[k, v] <- [['a', 'hello world!'], ['b', 'the world is round']] :put a {k => v}", r"?[k, v] <- [['a', 'hello world!'], ['b', 'the world is round']] :put a {k => v}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r"::fts create a:fts { r"::fts create a:fts {
extractor: v, extractor: v,
@ -926,7 +926,7 @@ fn test_fts_indexing() {
}", }",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r"?[k, v] <- [ r"?[k, v] <- [
['b', 'the world is square!'], ['b', 'the world is square!'],
@ -935,7 +935,7 @@ fn test_fts_indexing() {
] :put a {k => v}", ] :put a {k => v}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
let res = db let res = db
.run_script( .run_script(
r" r"
@ -969,12 +969,12 @@ fn test_lsh_indexing() {
r"?[k, v] <- [['a', 'hello world!'], ['b', 'the world is round']] :put a {k => v}", r"?[k, v] <- [['a', 'hello world!'], ['b', 'the world is round']] :put a {k => v}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r"::lsh create a:lsh {extractor: v, tokenizer: Simple, n_gram: 3, target_threshold: 0.3 }", r"::lsh create a:lsh {extractor: v, tokenizer: Simple, n_gram: 3, target_threshold: 0.3 }",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r"?[k, v] <- [ r"?[k, v] <- [
['b', 'the world is square!'], ['b', 'the world is square!'],
@ -984,7 +984,7 @@ fn test_lsh_indexing() {
] :put a {k => v}", ] :put a {k => v}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
let res = db let res = db
.run_script("::columns a:lsh", Default::default()) .run_script("::columns a:lsh", Default::default())
.unwrap(); .unwrap();
@ -1043,7 +1043,7 @@ fn test_insertions() {
r":create a {k => v: <F32; 1536> default rand_vec(1536)}", r":create a {k => v: <F32; 1536> default rand_vec(1536)}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script(r"?[k] <- [[1]] :put a {k}", Default::default()) db.run_script(r"?[k] <- [[1]] :put a {k}", Default::default())
.unwrap(); .unwrap();
db.run_script(r"?[k, v] := *a{k, v}", Default::default()) db.run_script(r"?[k, v] := *a{k, v}", Default::default())
@ -1055,7 +1055,7 @@ fn test_insertions() {
}", }",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script(r"?[count(fr_k)] := *a:i{fr_k}", Default::default()) db.run_script(r"?[count(fr_k)] := *a:i{fr_k}", Default::default())
.unwrap(); .unwrap();
db.run_script(r"?[k] <- [[1]] :put a {k}", Default::default()) db.run_script(r"?[k] <- [[1]] :put a {k}", Default::default())
@ -1064,7 +1064,7 @@ fn test_insertions() {
r"?[k] := k in int_range(300) :put a {k}", r"?[k] := k in int_range(300) :put a {k}",
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
let res = db let res = db
.run_script( .run_script(
r"?[dist, k] := ~a:i{k | query: v, bind_distance: dist, k:10, ef: 50, filter: k % 2 == 0, radius: 245}, *a{k: 96, v}", r"?[dist, k] := ~a:i{k | query: v, bind_distance: dist, k:10, ef: 50, filter: k % 2 == 0, radius: 245}, *a{k: 96, v}",
@ -1136,7 +1136,7 @@ fn multi_index_vec() {
"#, "#,
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r#" r#"
::hnsw create product:semantic{ ::hnsw create product:semantic{
@ -1148,7 +1148,7 @@ fn multi_index_vec() {
"#, "#,
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script( db.run_script(
r#" r#"
?[id, name, description, price, name_vec, description_vec] <- [[1, "name", "description", 100, [1], [1]]] ?[id, name, description, price, name_vec, description_vec] <- [[1, "name", "description", 100, [1], [1]]]
@ -1168,23 +1168,54 @@ fn multi_index_vec() {
#[test] #[test]
fn ensure_not() { fn ensure_not() {
let db = DbInstance::new("mem", "", "").unwrap(); let db = DbInstance::new("mem", "", "").unwrap();
db.run_script(r" db.run_script(
r"
%ignore_error { :create id_alloc{id: Int => next_id: Int, last_id: Int}} %ignore_error { :create id_alloc{id: Int => next_id: Int, last_id: Int}}
%ignore_error { %ignore_error {
?[id, next_id, last_id] <- [[0, 1, 1000]]; ?[id, next_id, last_id] <- [[0, 1, 1000]];
:ensure_not id_alloc{id => next_id, last_id} :ensure_not id_alloc{id => next_id, last_id}
} }
", Default::default()).unwrap(); ",
Default::default(),
)
.unwrap();
} }
#[test] #[test]
fn insertion() { fn insertion() {
let db = DbInstance::new("mem", "", "").unwrap(); let db = DbInstance::new("mem", "", "").unwrap();
db.run_script(r":create a {x => y}", Default::default()).unwrap(); db.run_script(r":create a {x => y}", Default::default())
assert!(db.run_script(r"?[x, y] <- [[1, 2]] :insert a {x => y}", Default::default()) .unwrap();
assert!(db
.run_script(
r"?[x, y] <- [[1, 2]] :insert a {x => y}",
Default::default()
)
.is_ok()); .is_ok());
assert!(db.run_script(r"?[x, y] <- [[1, 3]] :insert a {x => y}", Default::default()) assert!(db
.run_script(
r"?[x, y] <- [[1, 3]] :insert a {x => y}",
Default::default()
)
.is_err());
}
#[test]
fn deletion() {
let db = DbInstance::new("mem", "", "").unwrap();
db.run_script(r":create a {x => y}", Default::default())
.unwrap();
assert!(db
.run_script(r"?[x] <- [[1]] :delete a {x}", Default::default())
.is_err()); .is_err());
assert!(db
.run_script(
r"?[x, y] <- [[1, 2]] :insert a {x => y}",
Default::default()
)
.is_ok());
db
.run_script(r"?[x] <- [[1]] :delete a {x}", Default::default()).unwrap();
} }
#[test] #[test]
@ -1198,12 +1229,12 @@ fn parser_corner_case() {
r#"?[C] := C = true, C inx[C] := C = 1"#, r#"?[C] := C = true, C inx[C] := C = 1"#,
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
db.run_script(r#"?[k] := k in int_range(300)"#, Default::default()) db.run_script(r#"?[k] := k in int_range(300)"#, Default::default())
.unwrap(); .unwrap();
db.run_script( db.run_script(
r#"ywcc[a] <- [[1]] noto[A] := ywcc[A] ?[A] := noto[A]"#, r#"ywcc[a] <- [[1]] noto[A] := ywcc[A] ?[A] := noto[A]"#,
Default::default(), Default::default(),
) )
.unwrap(); .unwrap();
} }

Loading…
Cancel
Save