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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
use super::*;
impl Connection {
pub fn fetch_templates(&self) -> Result<Vec<DbVal<Template>>> {
let mut stmt = self.connection.prepare("SELECT * FROM templates;")?;
let iter = stmt.query_map(rusqlite::params![], |row| {
let pk = row.get("pk")?;
Ok(DbVal(
Template {
pk,
name: row.get("name")?,
list: row.get("list")?,
subject: row.get("subject")?,
headers_json: row.get("headers_json")?,
body: row.get("body")?,
},
pk,
))
})?;
let mut ret = vec![];
for templ in iter {
let templ = templ?;
ret.push(templ);
}
Ok(ret)
}
pub fn fetch_template(
&self,
template: &str,
list_pk: Option<i64>,
) -> Result<Option<DbVal<Template>>> {
let mut stmt = self
.connection
.prepare("SELECT * FROM templates WHERE name = ? AND list IS ?;")?;
let ret = stmt
.query_row(rusqlite::params![&template, &list_pk], |row| {
let pk = row.get("pk")?;
Ok(DbVal(
Template {
pk,
name: row.get("name")?,
list: row.get("list")?,
subject: row.get("subject")?,
headers_json: row.get("headers_json")?,
body: row.get("body")?,
},
pk,
))
})
.optional()?;
if ret.is_none() && list_pk.is_some() {
let mut stmt = self
.connection
.prepare("SELECT * FROM templates WHERE name = ? AND list IS NULL;")?;
Ok(stmt
.query_row(rusqlite::params![&template], |row| {
let pk = row.get("pk")?;
Ok(DbVal(
Template {
pk,
name: row.get("name")?,
list: row.get("list")?,
subject: row.get("subject")?,
headers_json: row.get("headers_json")?,
body: row.get("body")?,
},
pk,
))
})
.optional()?)
} else {
Ok(ret)
}
}
pub fn add_template(&self, template: Template) -> Result<DbVal<Template>> {
let mut stmt = self.connection.prepare(
"INSERT INTO templates(name, list, subject, headers_json, body) VALUES(?, ?, ?, ?, ?) \
RETURNING *;",
)?;
let ret = stmt
.query_row(
rusqlite::params![
&template.name,
&template.list,
&template.subject,
&template.headers_json,
&template.body
],
|row| {
let pk = row.get("pk")?;
Ok(DbVal(
Template {
pk,
name: row.get("name")?,
list: row.get("list")?,
subject: row.get("subject")?,
headers_json: row.get("headers_json")?,
body: row.get("body")?,
},
pk,
))
},
)
.map_err(|err| {
if matches!(
err,
rusqlite::Error::SqliteFailure(
rusqlite::ffi::Error {
code: rusqlite::ffi::ErrorCode::ConstraintViolation,
extended_code: 787
},
_
)
) {
Error::from(err).chain_err(|| NotFound("Could not find a list with this pk."))
} else {
err.into()
}
})?;
trace!("add_template {:?}.", &ret);
Ok(ret)
}
pub fn remove_template(&self, template: &str, list_pk: Option<i64>) -> Result<Template> {
let mut stmt = self
.connection
.prepare("DELETE FROM templates WHERE name = ? AND list IS ? RETURNING *;")?;
let ret = stmt.query_row(rusqlite::params![&template, &list_pk], |row| {
Ok(Template {
pk: -1,
name: row.get("name")?,
list: row.get("list")?,
subject: row.get("subject")?,
headers_json: row.get("headers_json")?,
body: row.get("body")?,
})
})?;
trace!(
"remove_template {} list_pk {:?} {:?}.",
template,
&list_pk,
&ret
);
Ok(ret)
}
}