-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathdatabase.rs
More file actions
135 lines (128 loc) · 4.24 KB
/
Copy pathdatabase.rs
File metadata and controls
135 lines (128 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use super::{
BinaryAssociationRecord, BinaryRecord, CombiningRule, IdentifierOption, Parameters, PureRecord,
};
use crate::FeosResult;
use rusqlite::{Connection, ToSql, params_from_iter};
use serde::de::DeserializeOwned;
use std::path::Path;
/// Load pure and binary parameter records from a SQLite database.
#[allow(clippy::type_complexity, clippy::allow_attributes)]
pub fn records_from_database<P, B, A, F, S>(
substances: &[S],
file: F,
identifier_option: IdentifierOption,
) -> FeosResult<(Vec<PureRecord<P, A>>, Vec<BinaryRecord<usize, B, A>>)>
where
F: AsRef<Path>,
S: ToSql,
P: DeserializeOwned,
B: DeserializeOwned,
A: DeserializeOwned,
{
let conn = Connection::open(file)?;
let pure_records = PureRecord::from_database(substances, &conn, identifier_option)?;
let binary_records = BinaryRecord::from_database(substances, &conn, identifier_option)?;
Ok((pure_records, binary_records))
}
impl<P: Clone, B: Clone, A: CombiningRule<P> + Clone> Parameters<P, B, A> {
pub fn from_database<F, S>(
substances: &[S],
file: F,
identifier_option: IdentifierOption,
) -> FeosResult<Self>
where
F: AsRef<Path>,
S: ToSql,
P: DeserializeOwned + Clone,
B: DeserializeOwned + Clone,
A: DeserializeOwned + Clone,
{
let (pure_records, binary_records) =
records_from_database(substances, file, identifier_option)?;
Self::new(pure_records, binary_records)
}
}
impl<M, A> PureRecord<M, A> {
pub fn from_database<S>(
substances: &[S],
connection: &Connection,
identifier_option: IdentifierOption,
) -> FeosResult<Vec<Self>>
where
S: ToSql,
M: DeserializeOwned,
A: DeserializeOwned,
{
let values = (0..substances.len())
.map(|i| format!("({i},?)"))
.collect::<Vec<_>>()
.join(",");
let query = format!(
"
WITH input(idx, ident) AS (
VALUES {values}
)
SELECT pr.pure_record
FROM input
JOIN pure_records pr
ON pr.{identifier_option} = input.ident
"
);
let mut stmt = connection.prepare(&query)?;
stmt.query_and_then(params_from_iter(substances), |r| {
Ok(serde_json::from_str(&r.get::<_, String>("pure_record")?)?)
})?
.collect()
}
}
impl<B, A> BinaryRecord<usize, B, A> {
pub fn from_database<S>(
substances: &[S],
connection: &Connection,
identifier_option: IdentifierOption,
) -> FeosResult<Vec<Self>>
where
S: ToSql,
B: DeserializeOwned,
A: DeserializeOwned,
{
let values = (0..substances.len())
.map(|i| format!("({i},?)"))
.collect::<Vec<_>>()
.join(",");
let query = format!(
"
WITH input(idx, ident) AS (
VALUES {values}
)
SELECT i1.idx AS comp1, i2.idx AS comp2, br.model_record, br.association_sites
FROM binary_records br
JOIN pure_records p1 ON br.id1 = p1.id
JOIN pure_records p2 ON br.id2 = p2.id
JOIN input i1 ON p1.{identifier_option} = i1.ident
JOIN input i2 ON p2.{identifier_option} = i2.ident
"
);
let mut stmt = connection.prepare(&query)?;
stmt.query_and_then(params_from_iter(substances), |r| {
let mut id1: i32 = r.get("comp1")?;
let mut id2: i32 = r.get("comp2")?;
let model_record = serde_json::from_str(&r.get::<_, String>("model_record")?)?;
let mut association_sites: Vec<BinaryAssociationRecord<_>> =
serde_json::from_str(&r.get::<_, String>("association_sites")?)?;
if id1 > id2 {
association_sites
.iter_mut()
.for_each(|a| std::mem::swap(&mut a.id1, &mut a.id2));
std::mem::swap(&mut id1, &mut id2);
};
Ok(BinaryRecord::with_association(
id1 as usize,
id2 as usize,
model_record,
association_sites,
))
})?
.collect()
}
}