Skip to content

Commit

Permalink
[db] Remove nodes and edges #447 (#448)
Browse files Browse the repository at this point in the history
* remove id implementation

* fix tests
  • Loading branch information
michaelvlach authored Feb 19, 2023
1 parent 9c939f1 commit a708779
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
- uses: actions/checkout@v3
- uses: taiki-e/install-action@cargo-llvm-cov
- run: rustup component add llvm-tools-preview
- run: cargo llvm-cov --workspace --fail-uncovered-functions 0 --fail-uncovered-lines 14
- run: cargo llvm-cov --workspace --fail-uncovered-functions 0 --fail-uncovered-lines 12

format:
runs-on: ubuntu-latest
Expand Down
13 changes: 10 additions & 3 deletions src/agdb/commands/remove_edge.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
use crate::query::query_id::QueryId;

#[derive(Debug, PartialEq)]
pub struct RemoveEdge {}
pub struct RemoveEdge {
pub id: QueryId,
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn derived_from_debug() {
format!("{:?}", RemoveEdge {});
format!("{:?}", RemoveEdge { id: QueryId::Id(0) });
}

#[test]
fn derived_from_partial_eq() {
assert_eq!(RemoveEdge {}, RemoveEdge {});
assert_eq!(
RemoveEdge { id: QueryId::Id(0) },
RemoveEdge { id: QueryId::Id(0) }
);
}
}
19 changes: 5 additions & 14 deletions src/agdb/commands/remove_node.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::graph::graph_index::GraphIndex;
use crate::query::query_id::QueryId;

#[derive(Debug, PartialEq)]
pub struct RemoveNode {
pub id: GraphIndex,
pub id: QueryId,
}

#[cfg(test)]
Expand All @@ -11,23 +11,14 @@ mod tests {

#[test]
fn derived_from_debug() {
format!(
"{:?}",
RemoveNode {
id: GraphIndex { index: 0 }
}
);
format!("{:?}", RemoveNode { id: QueryId::Id(0) });
}

#[test]
fn derived_from_partial_eq() {
assert_eq!(
RemoveNode {
id: GraphIndex { index: 0 }
},
RemoveNode {
id: GraphIndex { index: 0 }
}
RemoveNode { id: QueryId::Id(0) },
RemoveNode { id: QueryId::Id(0) }
);
}
}
34 changes: 28 additions & 6 deletions src/agdb/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,36 @@ impl Db {
result: &mut QueryResult,
) -> Result<(), QueryError> {
match command {
Commands::InsertAlias(data) => self.insert_alias(data, context)?,
Commands::InsertEdge(data) => self.insert_edge(data, context, result)?,
Commands::InsertNode(_) => self.insert_node(context, result)?,
Commands::InsertAlias(data) => self.insert_alias(data, context),
Commands::InsertEdge(data) => self.insert_edge(data, context, result),
Commands::InsertNode(_) => self.insert_node(context, result),
Commands::RemoveAlias(_) => todo!(),
Commands::RemoveEdge(_) => todo!(),
Commands::RemoveNode(_) => todo!(),
Commands::RemoveEdge(data) => self.remove_edge(data, result),
Commands::RemoveNode(data) => self.remove_node(data, result),
}
}

fn remove_node(
&self,
data: crate::commands::remove_node::RemoveNode,
result: &mut QueryResult,
) -> Result<(), QueryError> {
let mut db_data = self.data.write()?;
let index = Self::graph_index_from_query_id(&data.id, &db_data.aliases, &db_data.indexes)?;
db_data.graph.remove_node(&index)?;
result.result += 1;
Ok(())
}

fn remove_edge(
&self,
data: crate::commands::remove_edge::RemoveEdge,
result: &mut QueryResult,
) -> Result<(), QueryError> {
let mut db_data = self.data.write()?;
let index = Self::graph_index_from_query_id(&data.id, &db_data.aliases, &db_data.indexes)?;
db_data.graph.remove_edge(&index)?;
result.result += 1;
Ok(())
}

Expand Down Expand Up @@ -130,7 +152,7 @@ impl Db {
) -> Result<(), QueryError> {
let mut mut_data = self.data.write()?;
let graph_index = mut_data.graph.insert_edge(&from, &to)?.index;
mut_data.next_edge += 1;
mut_data.next_edge -= 1;
Ok(mut_data.indexes.insert(&context.index, &graph_index)?)
}

Expand Down
2 changes: 1 addition & 1 deletion src/agdb/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl Query {
Query::InsertNodes(query) => query.commands(),
Query::InsertValues(_) => todo!(),
Query::RemoveAliases(_) => todo!(),
Query::Remove(_) => todo!(),
Query::Remove(query) => query.commands(),
Query::RemoveValues(_) => todo!(),
Query::Search(_) => todo!(),
Query::SelectAliases(_) => todo!(),
Expand Down
28 changes: 14 additions & 14 deletions src/agdb/query/insert_edges_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ pub struct InsertEdgesQuery {
}

impl InsertEdgesQuery {
pub(crate) fn commands(&self) -> Vec<Commands> {
match &self.from {
QueryIds::All | QueryIds::Search(_) => panic!("Invalid query"),
QueryIds::Id(id) => self.one_to_many(id),
QueryIds::Ids(ids) => {
if self.each {
self.many_to_many_each(ids)
} else {
self.many_to_many(ids)
}
}
}
}

fn one_to_many(&self, from: &QueryId) -> Vec<Commands> {
let mut commands = Vec::<Commands>::new();

Expand Down Expand Up @@ -87,20 +101,6 @@ impl InsertEdgesQuery {

commands
}

pub(crate) fn commands(&self) -> Vec<Commands> {
match &self.from {
QueryIds::All | QueryIds::Search(_) => panic!("Invalid query"),
QueryIds::Id(id) => self.one_to_many(id),
QueryIds::Ids(ids) => {
if self.each {
self.many_to_many_each(ids)
} else {
self.many_to_many(ids)
}
}
}
}
}

#[cfg(test)]
Expand Down
21 changes: 21 additions & 0 deletions src/agdb/query/query_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,24 @@ impl From<i64> for QueryId {
Self::Id(value)
}
}

impl QueryId {
pub fn is_node(&self) -> bool {
match self {
QueryId::Id(id) => 0 < *id,
QueryId::Alias(_) => true,
}
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn is_node() {
assert!(QueryId::Id(1).is_node());
assert!(!QueryId::Id(0).is_node());
assert!(!QueryId::Id(-1).is_node());
}
}
55 changes: 55 additions & 0 deletions src/agdb/query/remove_query.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,58 @@
use super::query_id::QueryId;
use super::query_ids::QueryIds;
use crate::commands::remove_edge::RemoveEdge;
use crate::commands::remove_node::RemoveNode;
use crate::commands::Commands;

pub struct RemoveQuery(pub QueryIds);

impl RemoveQuery {
pub(crate) fn commands(&self) -> Vec<Commands> {
match &self.0 {
QueryIds::All | QueryIds::Search(_) => panic!("Invalid query"),
QueryIds::Id(id) => Self::id(id),
QueryIds::Ids(ids) => Self::ids(ids),
}
}

fn id(id: &QueryId) -> Vec<Commands> {
if id.is_node() {
vec![Commands::RemoveNode(RemoveNode { id: id.clone() })]
} else {
vec![Commands::RemoveEdge(RemoveEdge { id: id.clone() })]
}
}

fn ids(ids: &Vec<QueryId>) -> Vec<Commands> {
let mut commands = Vec::<Commands>::new();

for id in ids {
if id.is_node() {
commands.push(Commands::RemoveNode(RemoveNode { id: id.clone() }));
} else {
commands.push(Commands::RemoveEdge(RemoveEdge { id: id.clone() }));
}
}

commands
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::test_utilities::catch_unwidn_silent::catch_unwind_silent;

#[test]
fn invalid_query_preprocessing_many_many() {
let result = catch_unwind_silent(|| {
let query = RemoveQuery(QueryIds::All);
query.commands();
});

assert_eq!(
*result.unwrap_err().downcast_ref::<&str>().unwrap(),
"Invalid query"
);
}
}
1 change: 0 additions & 1 deletion tests/insert_edges_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ fn insert_edge_from_to() {
let db = Db::new(test_file.file_name()).unwrap();
db.exec(&QueryBuilder::insert().node().alias("alias1").query())
.unwrap();

db.exec(&QueryBuilder::insert().node().query()).unwrap();

let query = QueryBuilder::insert()
Expand Down
87 changes: 83 additions & 4 deletions tests/remove_ids_test.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,94 @@
#[path = "../src/agdb/test_utilities/test_file.rs"]
mod test_file;

use agdb::Db;
use agdb::QueryBuilder;
use test_file::TestFile;

#[test]
pub fn remove_id() {
let _query = QueryBuilder::remove().id("alias".into()).query();
pub fn remove_node() {
let test_file = TestFile::new();

let db = Db::new(test_file.file_name()).unwrap();
db.exec(&QueryBuilder::insert().node().query()).unwrap();

let query = QueryBuilder::remove().id(1.into()).query();
let result = db.exec(&query).unwrap();

assert_eq!(result.result, 1);
assert_eq!(result.elements, vec![]);
}

#[test]
pub fn remove_ids() {
let _query = QueryBuilder::remove()
pub fn remove_nodes() {
let test_file = TestFile::new();

let db = Db::new(test_file.file_name()).unwrap();
db.exec(
&QueryBuilder::insert()
.nodes()
.aliases(&["alias".to_string(), "alias2".to_string()])
.query(),
)
.unwrap();

let query = QueryBuilder::remove()
.ids(&["alias".into(), "alias2".into()])
.query();
let result = db.exec(&query).unwrap();

assert_eq!(result.result, 2);
assert_eq!(result.elements, vec![]);
}

#[test]
pub fn remove_edge() {
let test_file = TestFile::new();

let db = Db::new(test_file.file_name()).unwrap();
db.exec(&QueryBuilder::insert().node().alias("alias1").query())
.unwrap();
db.exec(&QueryBuilder::insert().node().query()).unwrap();
db.exec(
&QueryBuilder::insert()
.edge()
.from("alias1".into())
.to(2.into())
.query(),
)
.unwrap();

let query = QueryBuilder::remove().id((-1).into()).query();
let result = db.exec(&query).unwrap();

assert_eq!(result.result, 1);
assert_eq!(result.elements, vec![]);
}

#[test]
pub fn remove_edges() {
let test_file = TestFile::new();

let db = Db::new(test_file.file_name()).unwrap();
db.exec(&QueryBuilder::insert().node().alias("alias1").query())
.unwrap();
db.exec(&QueryBuilder::insert().node().query()).unwrap();
db.exec(
&QueryBuilder::insert()
.edges()
.from(&["alias1".into(), 2.into()])
.to(&[2.into(), "alias1".into()])
.query(),
)
.unwrap();

let query = QueryBuilder::remove()
.ids(&[(-1).into(), (-2).into()])
.query();
let result = db.exec(&query).unwrap();

assert_eq!(result.result, 2);
assert_eq!(result.elements, vec![]);
}

#[test]
Expand Down

0 comments on commit a708779

Please sign in to comment.