meerkat_sqlite/
json_column.rs1use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ValueRef};
14
15pub struct JsonColumnBytes(Vec<u8>);
18
19impl JsonColumnBytes {
20 pub fn into_bytes(self) -> Vec<u8> {
21 self.0
22 }
23}
24
25impl FromSql for JsonColumnBytes {
26 fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
27 match value {
28 ValueRef::Text(bytes) | ValueRef::Blob(bytes) => Ok(Self(bytes.to_vec())),
29 ValueRef::Null | ValueRef::Integer(_) | ValueRef::Real(_) => {
30 Err(FromSqlError::InvalidType)
31 }
32 }
33 }
34}
35
36#[cfg(test)]
37#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
38mod tests {
39 use super::*;
40 use rusqlite::Connection;
41
42 #[test]
43 fn accepts_text_and_blob_rejects_others() {
44 let conn = Connection::open_in_memory().expect("open");
45 conn.execute_batch(
46 "CREATE TABLE t (v);
47 INSERT INTO t VALUES (CAST('{\"a\":1}' AS BLOB));
48 INSERT INTO t VALUES ('{\"a\":2}');
49 INSERT INTO t VALUES (42);",
50 )
51 .expect("seed");
52 let mut stmt = conn
53 .prepare("SELECT v FROM t ORDER BY rowid")
54 .expect("prepare");
55 let mut rows = stmt.query([]).expect("query");
56
57 let blob_row = rows.next().expect("row").expect("present");
58 let blob: JsonColumnBytes = blob_row.get(0).expect("blob accepted");
59 assert_eq!(blob.into_bytes(), b"{\"a\":1}");
60
61 let text_row = rows.next().expect("row").expect("present");
62 let text: JsonColumnBytes = text_row.get(0).expect("text accepted");
63 assert_eq!(text.into_bytes(), b"{\"a\":2}");
64
65 let int_row = rows.next().expect("row").expect("present");
66 match int_row.get::<_, JsonColumnBytes>(0) {
67 Err(rusqlite::Error::InvalidColumnType(..)) => {}
68 Err(other) => panic!("wrong error for integer column: {other}"),
69 Ok(_) => panic!("integer column must be rejected"),
70 }
71 }
72}