Skip to content

Commit

Permalink
Add new edge and path models
Browse files Browse the repository at this point in the history
  • Loading branch information
dkhofer committed Aug 19, 2024
1 parent 5951795 commit b1a09d9
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 3 deletions.
27 changes: 26 additions & 1 deletion migrations/01-initial/up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,29 @@ CREATE TABLE change_log (
FOREIGN KEY(path_id) REFERENCES path(id),
FOREIGN KEY(sequence_hash) REFERENCES sequence(hash)
);
CREATE UNIQUE INDEX change_log_uidx ON change_log(hash);
CREATE UNIQUE INDEX change_log_uidx ON change_log(hash);

CREATE TABLE new_edges (
id INTEGER PRIMARY KEY NOT NULL,
source_hash TEXT,
source_coordinate INTEGER,
target_hash TEXT,
target_coordinate INTEGER,
chromosome_index INTEGER NOT NULL,
phased INTEGER NOT NULL,
FOREIGN KEY(source_hash) REFERENCES sequence(hash),
FOREIGN KEY(target_hash) REFERENCES sequence(hash),
constraint chk_phased check (phased in (0, 1))
);
CREATE UNIQUE INDEX new_edge_uidx ON new_edges(source_hash, source_coordinate, target_hash, target_coordinate, chromosome_index, phased);

CREATE TABLE path_edges (
id INTEGER PRIMARY KEY NOT NULL,
path_id INTEGER NOT NULL,
source_edge_id INTEGER,
target_edge_id INTEGER,
FOREIGN KEY(source_edge_id) REFERENCES new_edges(id),
FOREIGN KEY(target_edge_id) REFERENCES new_edges(id),
FOREIGN KEY(path_id) REFERENCES path(id)
);
CREATE UNIQUE INDEX path_edges_uidx ON path_edges(path_id, source_edge_id, target_edge_id);
2 changes: 2 additions & 0 deletions src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use std::fmt::*;

pub mod block;
pub mod edge;
pub mod new_edge;
pub mod path;
pub mod path_edge;
pub mod sequence;

use crate::graph::all_simple_paths;
Expand Down
88 changes: 88 additions & 0 deletions src/models/new_edge.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use rusqlite::types::Value;
use rusqlite::{params_from_iter, Connection};

#[derive(Debug)]
pub struct NewEdge {
pub id: i32,
pub source_hash: Option<String>,
pub source_coordinate: Option<i32>,
pub target_hash: Option<String>,
pub target_coordinate: Option<i32>,
pub chromosome_index: i32,
pub phased: i32,
}

impl NewEdge {
pub fn create(
conn: &Connection,
source_hash: Option<String>,
source_coordinate: Option<i32>,
target_hash: Option<String>,
target_coordinate: Option<i32>,
chromosome_index: i32,
phased: i32,
) -> NewEdge {
let query;
let id_query;
let mut placeholders: Vec<Value> = vec![];
if target_hash.is_some() && source_hash.is_some() {
query = "INSERT INTO new_edges (source_hash, source_coordinate, target_hash, target_coordinate, chromosome_index, phased) VALUES (?1, ?2, ?3, ?4, ?5, ?6) RETURNING *";
id_query = "select id from new_edges where source_hash = ?1 and source_coordinate = ?2 and target_hash = ?3 and target_coordinate = ?4 and chromosome_index = ?5 and phased = ?6";
placeholders.push(source_hash.clone().unwrap().into());
placeholders.push(source_coordinate.unwrap().into());
placeholders.push(target_hash.clone().unwrap().into());
placeholders.push(target_coordinate.unwrap().into());
placeholders.push(chromosome_index.into());
placeholders.push(phased.into());
} else if target_hash.is_some() {
id_query = "select id from new_edges where target_hash = ?1 and target_coordinate = ?2 and source_hash is null and chromosome_index = ?3 and phased = ?4";
query = "INSERT INTO new_edges (target_hash, target_coordinate, chromosome_index, phased) VALUES (?1, ?2, ?3, ?4) RETURNING *";
placeholders.push(target_hash.clone().unwrap().into());
placeholders.push(target_coordinate.unwrap().into());
placeholders.push(chromosome_index.into());
placeholders.push(phased.into());
} else {
id_query = "select id from new_edges where source_hash = ?1 and source_coordinate = ?2 and target_id is null and chromosome_index = ?3 and phased = ?4";
query = "INSERT INTO new_edges (source_hash, source_coordinate, chromosome_index, phased) VALUES (?1, ?2, ?3, ?4) RETURNING *";
placeholders.push(source_hash.clone().unwrap().into());
placeholders.push(source_coordinate.unwrap().into());
placeholders.push(chromosome_index.into());
placeholders.push(phased.into());
}
let mut stmt = conn.prepare(query).unwrap();
match stmt.query_row(params_from_iter(&placeholders), |row| {
Ok(NewEdge {
id: row.get(0)?,
source_hash: row.get(1)?,
source_coordinate: row.get(2)?,
target_hash: row.get(3)?,
target_coordinate: row.get(4)?,
chromosome_index: row.get(5)?,
phased: row.get(6)?,
})
}) {
Ok(edge) => edge,
Err(rusqlite::Error::SqliteFailure(err, details)) => {
if err.code == rusqlite::ErrorCode::ConstraintViolation {
println!("{err:?} {details:?}");
NewEdge {
id: conn
.query_row(id_query, params_from_iter(&placeholders), |row| row.get(0))
.unwrap(),
source_hash,
source_coordinate,
target_hash,
target_coordinate,
chromosome_index,
phased,
}
} else {
panic!("something bad happened querying the database")
}
}
Err(_) => {
panic!("something bad happened querying the database")
}
}
}
}
19 changes: 17 additions & 2 deletions src/models/path.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::models::block::Block;
use crate::models::edge::Edge;
use crate::models::{block::Block, edge::Edge, path_edge::PathEdge};
use petgraph::graphmap::DiGraphMap;
use petgraph::prelude::Dfs;
use petgraph::Direction;
Expand Down Expand Up @@ -47,6 +46,16 @@ pub fn revcomp(seq: &str) -> String {
.unwrap()
}

#[derive(Clone, Debug)]
pub struct NewBlock {
pub id: i32,
pub sequence_hash: String,
pub block_sequence: String,
pub start: i32,
pub end: i32,
pub strand: String,
}

impl Path {
pub fn create(conn: &Connection, name: &str, block_group_id: i32, blocks: Vec<i32>) -> Path {
let query = "INSERT INTO path (name, block_group_id) VALUES (?1, ?2) RETURNING (id)";
Expand Down Expand Up @@ -124,6 +133,12 @@ impl Path {
}
sequence
}

pub fn get_new_blocks(conn: &Connection, path_id: i32) -> Vec<NewBlock> {
let mut new_blocks = vec![];
let edges = PathEdge::edges_for(conn, path_id);
new_blocks
}
}

#[derive(Debug)]
Expand Down
102 changes: 102 additions & 0 deletions src/models/path_edge.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use crate::models::new_edge::NewEdge;
use rusqlite::types::Value;
use rusqlite::{params_from_iter, Connection};

#[derive(Debug)]
pub struct PathEdge {
pub id: i32,
pub path_id: i32,
pub source_edge_id: Option<i32>,
pub target_edge_id: Option<i32>,
}

impl PathEdge {
pub fn create(
conn: &Connection,
path_id: i32,
source_edge_id: Option<i32>,
target_edge_id: Option<i32>,
) -> PathEdge {
let query =
"INSERT INTO path_edges (path_id, source_edge_id, target_edge_id) VALUES (?1, ?2, ?3) RETURNING (id)";
let mut stmt = conn.prepare(query).unwrap();
let mut rows = stmt
.query_map((path_id, source_edge_id, target_edge_id), |row| {
Ok(PathEdge {
id: row.get(0)?,
path_id,
source_edge_id,
target_edge_id,
})
})
.unwrap();
match rows.next().unwrap() {
Ok(res) => res,
Err(rusqlite::Error::SqliteFailure(err, details)) => {
if err.code == rusqlite::ErrorCode::ConstraintViolation {
println!("{err:?} {details:?}");
let query;
let mut placeholders = vec![path_id];
if let Some(s) = source_edge_id {
if let Some(t) = target_edge_id {
query = "SELECT id from path_edges where path_id = ?1 AND source_edge_id = ?2 AND target_edge_id = ?3;";
placeholders.push(s);
placeholders.push(t);
} else {
query = "SELECT id from path_edges where path_id = ?1 AND source_edge_id = ?2 AND target_edge_id is null;";
placeholders.push(s);
}
} else if let Some(t) = target_edge_id {
query = "SELECT id from path_edges where path_id = ?1 AND source_edge_id is null AND target_edge_id = ?2;";
placeholders.push(t);
} else {
panic!("No edge ids passed");
}
println!("{query} {placeholders:?}");
PathEdge {
id: conn
.query_row(query, params_from_iter(&placeholders), |row| row.get(0))
.unwrap(),
path_id,
source_edge_id,
target_edge_id,
}
} else {
panic!("something bad happened querying the database")
}
}
Err(_) => {
panic!("something bad happened querying the database")
}
}
}

pub fn query(conn: &Connection, query: &str, placeholders: Vec<Value>) -> Vec<PathEdge> {
let mut stmt = conn.prepare(query).unwrap();
let rows = stmt
.query_map(params_from_iter(placeholders), |row| {
Ok(PathEdge {
id: row.get(0)?,
path_id: row.get(1)?,
source_edge_id: row.get(2)?,
target_edge_id: row.get(3)?,
})
})
.unwrap();
let mut objs = vec![];
for row in rows {
objs.push(row.unwrap());
}
objs
}

pub fn edges_for(conn: &Connection, path_id: i32) -> Vec<NewEdge> {
let edges = vec![];
let path_edges = PathEdge::query(
conn,
"select * from path_edges where path_id = ?1",
vec![Value::from(path_id)],
);
edges
}
}

0 comments on commit b1a09d9

Please sign in to comment.