Skip to content

Commit 21f33d1

Browse files
committed
refactor(sql): do not expose rusqlite Error type in query_map methods
We use query_and_then() instead of query_map() function now. The difference is that row processing function returns anyhow::Result, so simple fallible processing like JSON parsing can be done inside of it when calling query_map_vec() and query_map_collect() without having to resort to query_map() and iterating over all rows again afterwards.
1 parent 7f05914 commit 21f33d1

File tree

11 files changed

+95
-49
lines changed

11 files changed

+95
-49
lines changed

src/chat.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,7 +2029,10 @@ impl Chat {
20292029
ON c.id=cc.contact_id \
20302030
WHERE cc.chat_id=? AND cc.add_timestamp >= cc.remove_timestamp",
20312031
(self.id,),
2032-
|row| row.get::<_, String>(0),
2032+
|row| {
2033+
let addr: String = row.get(0)?;
2034+
Ok(addr)
2035+
},
20332036
)
20342037
.await?;
20352038
self.sync(context, SyncAction::SetContacts(addrs)).await?;
@@ -3038,7 +3041,7 @@ pub async fn get_chat_msgs_ex(
30383041
))
30393042
}
30403043
};
3041-
let process_rows = |rows: rusqlite::MappedRows<_>| {
3044+
let process_rows = |rows: rusqlite::AndThenRows<_>| {
30423045
// It is faster to sort here rather than
30433046
// let sqlite execute an ORDER BY clause.
30443047
let mut sorted_rows = Vec::new();
@@ -3120,7 +3123,10 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<()>
31203123
LEFT JOIN chats c ON m.chat_id=c.id
31213124
WHERE m.state=10 AND m.hidden=0 AND m.chat_id>9 AND c.archived=1",
31223125
(),
3123-
|row| row.get::<_, ChatId>(0),
3126+
|row| {
3127+
let chat_id: ChatId = row.get(0)?;
3128+
Ok(chat_id)
3129+
},
31243130
)
31253131
.await?;
31263132
if chat_ids_in_archive.is_empty() {
@@ -3298,7 +3304,10 @@ pub async fn get_chat_media(
32983304
DC_CHAT_ID_TRASH,
32993305
Viewtype::Webxdc,
33003306
),
3301-
|row| row.get::<_, MsgId>(0),
3307+
|row| {
3308+
let msg_id: MsgId = row.get(0)?;
3309+
Ok(msg_id)
3310+
},
33023311
)
33033312
.await?
33043313
} else {
@@ -3328,7 +3337,10 @@ pub async fn get_chat_media(
33283337
msg_type
33293338
},
33303339
),
3331-
|row| row.get::<_, MsgId>(0),
3340+
|row| {
3341+
let msg_id: MsgId = row.get(0)?;
3342+
Ok(msg_id)
3343+
},
33323344
)
33333345
.await?
33343346
};
@@ -3349,7 +3361,10 @@ pub async fn get_chat_contacts(context: &Context, chat_id: ChatId) -> Result<Vec
33493361
WHERE cc.chat_id=? AND cc.add_timestamp >= cc.remove_timestamp
33503362
ORDER BY c.id=1, c.last_seen DESC, c.id DESC;",
33513363
(chat_id,),
3352-
|row| row.get::<_, ContactId>(0),
3364+
|row| {
3365+
let contact_id: ContactId = row.get(0)?;
3366+
Ok(contact_id)
3367+
},
33533368
)
33543369
.await
33553370
}
@@ -3371,7 +3386,10 @@ pub async fn get_past_chat_contacts(context: &Context, chat_id: ChatId) -> Resul
33713386
AND ? < cc.remove_timestamp
33723387
ORDER BY c.id=1, cc.remove_timestamp DESC, c.id DESC",
33733388
(chat_id, now.saturating_sub(60 * 24 * 3600)),
3374-
|row| row.get::<_, ContactId>(0),
3389+
|row| {
3390+
let contact_id: ContactId = row.get(0)?;
3391+
Ok(contact_id)
3392+
},
33753393
)
33763394
.await
33773395
}
@@ -3734,11 +3752,13 @@ pub(crate) async fn shall_attach_selfavatar(context: &Context, chat_id: ChatId)
37343752
LEFT JOIN contacts c ON c.id=cc.contact_id
37353753
WHERE cc.chat_id=? AND cc.contact_id!=? AND cc.add_timestamp >= cc.remove_timestamp",
37363754
(chat_id, ContactId::SELF),
3737-
|row| Ok(row.get::<_, i64>(0)),
3755+
|row| {
3756+
let selfavatar_sent: i64 = row.get(0)?;
3757+
Ok(selfavatar_sent)
3758+
},
37383759
|rows| {
37393760
let mut needs_attach = false;
37403761
for row in rows {
3741-
let row = row?;
37423762
let selfavatar_sent = row?;
37433763
if selfavatar_sent < timestamp_some_days_ago {
37443764
needs_attach = true;

src/chatlist.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ impl Chatlist {
107107
Ok((chat_id, msg_id))
108108
};
109109

110-
let process_rows = |rows: rusqlite::MappedRows<_>| {
110+
let process_rows = |rows: rusqlite::AndThenRows<_>| {
111111
rows.collect::<std::result::Result<Vec<_>, _>>()
112112
.map_err(Into::into)
113113
};
@@ -229,7 +229,7 @@ impl Chatlist {
229229
let msg_id: Option<MsgId> = row.get(3)?;
230230
Ok((chat_id, typ, param, msg_id))
231231
};
232-
let process_rows = |rows: rusqlite::MappedRows<_>| {
232+
let process_rows = |rows: rusqlite::AndThenRows<_>| {
233233
rows.filter_map(|row: std::result::Result<(_, _, Params, _), _>| match row {
234234
Ok((chat_id, typ, param, msg_id)) => {
235235
if typ == Chattype::Mailinglist

src/configure.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -192,16 +192,11 @@ impl Context {
192192
pub async fn list_transports(&self) -> Result<Vec<EnteredLoginParam>> {
193193
let transports = self
194194
.sql
195-
.query_map(
196-
"SELECT entered_param FROM transports",
197-
(),
198-
|row| row.get::<_, String>(0),
199-
|rows| {
200-
rows.flatten()
201-
.map(|s| Ok(serde_json::from_str(&s)?))
202-
.collect::<Result<Vec<EnteredLoginParam>>>()
203-
},
204-
)
195+
.query_map_vec("SELECT entered_param FROM transports", (), |row| {
196+
let entered_param: String = row.get(0)?;
197+
let transport: EnteredLoginParam = serde_json::from_str(&entered_param)?;
198+
Ok(transport)
199+
})
205200
.await?;
206201

207202
Ok(transports)

src/contact.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,7 +1285,10 @@ impl Contact {
12851285
.query_map_vec(
12861286
"SELECT id FROM contacts WHERE id>? AND blocked!=0 ORDER BY last_seen DESC, id DESC;",
12871287
(ContactId::LAST_SPECIAL,),
1288-
|row| row.get::<_, ContactId>(0),
1288+
|row| {
1289+
let contact_id: ContactId = row.get(0)?;
1290+
Ok(contact_id)
1291+
}
12891292
)
12901293
.await?;
12911294
Ok(list)
@@ -2044,7 +2047,7 @@ impl RecentlySeenLoop {
20442047
// become unseen in the future.
20452048
let mut unseen_queue: BinaryHeap<MyHeapElem> = context
20462049
.sql
2047-
.query_map(
2050+
.query_map_collect(
20482051
"SELECT id, last_seen FROM contacts
20492052
WHERE last_seen > ?",
20502053
(now_ts - SEEN_RECENTLY_SECONDS,),
@@ -2053,10 +2056,6 @@ impl RecentlySeenLoop {
20532056
let last_seen: i64 = row.get("last_seen")?;
20542057
Ok((Reverse(last_seen + SEEN_RECENTLY_SECONDS), contact_id))
20552058
},
2056-
|rows| {
2057-
rows.collect::<std::result::Result<BinaryHeap<MyHeapElem>, _>>()
2058-
.map_err(Into::into)
2059-
},
20602059
)
20612060
.await
20622061
.unwrap_or_default();

src/context.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,10 @@ impl Context {
11001100
" ORDER BY m.timestamp DESC,m.id DESC;"
11011101
),
11021102
(MessageState::InFresh, time()),
1103-
|row| row.get::<_, MsgId>(0),
1103+
|row| {
1104+
let msg_id: MsgId = row.get(0)?;
1105+
Ok(msg_id)
1106+
},
11041107
)
11051108
.await?;
11061109
Ok(list)
@@ -1204,7 +1207,10 @@ impl Context {
12041207
AND IFNULL(txt_normalized, txt) LIKE ?
12051208
ORDER BY m.timestamp,m.id;",
12061209
(chat_id, str_like_in_text),
1207-
|row| row.get::<_, MsgId>("id"),
1210+
|row| {
1211+
let msg_id: MsgId = row.get("id")?;
1212+
Ok(msg_id)
1213+
},
12081214
)
12091215
.await?
12101216
} else {
@@ -1233,7 +1239,10 @@ impl Context {
12331239
AND IFNULL(txt_normalized, txt) LIKE ?
12341240
ORDER BY m.id DESC LIMIT 1000",
12351241
(str_like_in_text,),
1236-
|row| row.get::<_, MsgId>("id"),
1242+
|row| {
1243+
let msg_id: MsgId = row.get("id")?;
1244+
Ok(msg_id)
1245+
},
12371246
)
12381247
.await?
12391248
};

src/key.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,15 @@ pub(crate) async fn load_self_public_key(context: &Context) -> Result<SignedPubl
159159
pub(crate) async fn load_self_public_keyring(context: &Context) -> Result<Vec<SignedPublicKey>> {
160160
let keys = context
161161
.sql
162-
.query_map(
162+
.query_map_vec(
163163
r#"SELECT public_key
164164
FROM keypairs
165165
ORDER BY id=(SELECT value FROM config WHERE keyname='key_id') DESC"#,
166166
(),
167-
|row| row.get::<_, Vec<u8>>(0),
168-
|keys| keys.collect::<Result<Vec<_>, _>>().map_err(Into::into),
167+
|row| {
168+
let public_key_bytes: Vec<u8> = row.get(0)?;
169+
Ok(public_key_bytes)
170+
},
169171
)
170172
.await?
171173
.into_iter()
@@ -232,13 +234,15 @@ pub(crate) async fn load_self_secret_key(context: &Context) -> Result<SignedSecr
232234
pub(crate) async fn load_self_secret_keyring(context: &Context) -> Result<Vec<SignedSecretKey>> {
233235
let keys = context
234236
.sql
235-
.query_map(
237+
.query_map_vec(
236238
r#"SELECT private_key
237239
FROM keypairs
238240
ORDER BY id=(SELECT value FROM config WHERE keyname='key_id') DESC"#,
239241
(),
240-
|row| row.get::<_, Vec<u8>>(0),
241-
|keys| keys.collect::<Result<Vec<_>, _>>().map_err(Into::into),
242+
|row| {
243+
let bytes: Vec<u8> = row.get(0)?;
244+
Ok(bytes)
245+
},
242246
)
243247
.await?
244248
.into_iter()

src/location.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,10 @@ pub async fn set(context: &Context, latitude: f64, longitude: f64, accuracy: f64
348348
.query_map_vec(
349349
"SELECT id FROM chats WHERE locations_send_until>?;",
350350
(now,),
351-
|row| row.get::<_, i32>(0),
351+
|row| {
352+
let id: i32 = row.get(0)?;
353+
Ok(id)
354+
},
352355
)
353356
.await?;
354357

src/sql.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -373,14 +373,14 @@ impl Sql {
373373
g: G,
374374
) -> Result<H>
375375
where
376-
F: Send + FnMut(&rusqlite::Row) -> rusqlite::Result<T>,
377-
G: Send + FnOnce(rusqlite::MappedRows<F>) -> Result<H>,
376+
F: Send + FnMut(&rusqlite::Row) -> Result<T>,
377+
G: Send + FnOnce(rusqlite::AndThenRows<F>) -> Result<H>,
378378
H: Send + 'static,
379379
{
380380
let query_only = true;
381381
self.call(query_only, move |conn| {
382382
let mut stmt = conn.prepare(sql)?;
383-
let res = stmt.query_map(params, f)?;
383+
let res = stmt.query_and_then(params, f)?;
384384
g(res)
385385
})
386386
.await
@@ -398,7 +398,7 @@ impl Sql {
398398
where
399399
T: Send + 'static,
400400
C: Send + 'static + std::iter::FromIterator<T>,
401-
F: Send + FnMut(&rusqlite::Row) -> rusqlite::Result<T>,
401+
F: Send + FnMut(&rusqlite::Row) -> Result<T>,
402402
{
403403
self.query_map(sql, params, f, |rows| {
404404
rows.collect::<std::result::Result<C, _>>()
@@ -418,7 +418,7 @@ impl Sql {
418418
) -> Result<Vec<T>>
419419
where
420420
T: Send + 'static,
421-
F: Send + FnMut(&rusqlite::Row) -> rusqlite::Result<T>,
421+
F: Send + FnMut(&rusqlite::Row) -> Result<T>,
422422
{
423423
self.query_map_collect(sql, params, f).await
424424
}
@@ -969,7 +969,10 @@ pub async fn remove_unused_files(context: &Context) -> Result<()> {
969969
.query_map(
970970
"SELECT value FROM config;",
971971
(),
972-
|row| row.get::<_, String>(0),
972+
|row| {
973+
let row: String = row.get(0)?;
974+
Ok(row)
975+
},
973976
|rows| {
974977
for row in rows {
975978
maybe_add_file(&mut files_in_use, &row?);
@@ -985,7 +988,10 @@ pub async fn remove_unused_files(context: &Context) -> Result<()> {
985988
.query_map(
986989
"SELECT blobname FROM http_cache",
987990
(),
988-
|row| row.get::<_, String>(0),
991+
|row| {
992+
let row: String = row.get(0)?;
993+
Ok(row)
994+
},
989995
|rows| {
990996
for row in rows {
991997
maybe_add_file(&mut files_in_use, &row?);
@@ -1125,7 +1131,10 @@ async fn maybe_add_from_param(
11251131
sql.query_map(
11261132
query,
11271133
(),
1128-
|row| row.get::<_, String>(0),
1134+
|row| {
1135+
let row: String = row.get(0)?;
1136+
Ok(row)
1137+
},
11291138
|rows| {
11301139
for row in rows {
11311140
let param: Params = row?.parse().unwrap_or_default();

src/stats.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,10 @@ async fn get_timestamps(context: &Context, sql_table: &str) -> Result<Vec<i64>>
377377
.query_map_vec(
378378
&format!("SELECT timestamp FROM {sql_table} LIMIT 1000"),
379379
(),
380-
|row| row.get(0),
380+
|row| {
381+
let timestamp: i64 = row.get(0)?;
382+
Ok(timestamp)
383+
},
381384
)
382385
.await
383386
}

src/sync.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,11 @@ impl Context {
202202
.query_map(
203203
"SELECT id, item FROM multi_device_sync ORDER BY id;",
204204
(),
205-
|row| Ok((row.get::<_, u32>(0)?, row.get::<_, String>(1)?)),
205+
|row| {
206+
let id: u32 = row.get(0)?;
207+
let item: String = row.get(1)?;
208+
Ok((id, item))
209+
},
206210
|rows| {
207211
let mut ids = vec![];
208212
let mut serialized = String::default();

0 commit comments

Comments
 (0)