Skip to content

Commit 7becb51

Browse files
committed
add sqlite serialize/deserialize example
- Use SqliteOwnedBuf with serialize/deserialize to snapshot an in-memory database as raw bytes - Embed the bytes in a custom container format (magic header + db) - Round-trip: create → serialize → write → read → deserialize → query
1 parent f5cdf33 commit 7becb51

File tree

4 files changed

+92
-0
lines changed

4 files changed

+92
-0
lines changed

Cargo.lock

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ members = [
2424
"examples/postgres/transaction",
2525
"examples/sqlite/todos",
2626
"examples/sqlite/extension",
27+
"examples/sqlite/serialize",
2728
]
2829

2930
[workspace.package]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "sqlx-example-sqlite-serialize"
3+
version = "0.1.0"
4+
edition = "2024"
5+
workspace = "../../../"
6+
7+
[dependencies]
8+
anyhow = "1.0"
9+
sqlx = { path = "../../../", features = ["sqlite", "sqlite-deserialize", "runtime-tokio"] }
10+
tokio = { version = "1", features = ["rt", "macros"] }
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/// Demonstrates serialize/deserialize by embedding a SQLite database inside a custom
2+
/// binary container format.
3+
///
4+
/// The container prepends a magic header to the raw SQLite bytes, making it impossible
5+
/// to open directly with `SqliteConnectOptions::filename()`. This is the whole point:
6+
/// `sqlite3_serialize` / `sqlite3_deserialize` let you treat a database as an opaque
7+
/// byte slice that can live inside any format you control.
8+
///
9+
/// Container layout:
10+
/// [4 bytes] magic: b"SQLX"
11+
/// [n bytes] SQLite database bytes
12+
use sqlx::sqlite::SqliteOwnedBuf;
13+
use sqlx::{Connection, SqliteConnection};
14+
use std::io::{self, Write};
15+
use std::path::Path;
16+
17+
const MAGIC: &[u8; 4] = b"SQLX";
18+
19+
fn write_container(path: &Path, db_bytes: &[u8]) -> io::Result<()> {
20+
let mut file = std::fs::File::create(path)?;
21+
file.write_all(MAGIC)?;
22+
file.write_all(db_bytes)?;
23+
Ok(())
24+
}
25+
26+
fn read_container(path: &Path) -> io::Result<Vec<u8>> {
27+
let raw = std::fs::read(path)?;
28+
assert_eq!(&raw[..4], MAGIC, "not a valid container file");
29+
Ok(raw[4..].to_vec())
30+
}
31+
32+
#[tokio::main(flavor = "current_thread")]
33+
async fn main() -> anyhow::Result<()> {
34+
let container_path = Path::new("notes.sqlx");
35+
36+
let mut conn = SqliteConnection::connect("sqlite::memory:").await?;
37+
38+
sqlx::raw_sql(
39+
"create table notes(id integer primary key, body text not null);
40+
insert into notes(body) values ('hello'), ('world');",
41+
)
42+
.execute(&mut conn)
43+
.await?;
44+
45+
// serialize and persist inside the custom container
46+
let snapshot: SqliteOwnedBuf = conn.serialize(None).await?;
47+
write_container(container_path, snapshot.as_ref())?;
48+
conn.close().await?;
49+
50+
// restore into a fresh in-memory connection
51+
let db_bytes = read_container(container_path)?;
52+
let owned = SqliteOwnedBuf::try_from(db_bytes.as_slice())?;
53+
let mut restored = SqliteConnection::connect("sqlite::memory:").await?;
54+
restored.deserialize(None, owned, false).await?;
55+
56+
let rows = sqlx::query_as::<_, (i64, String)>("select id, body from notes order by id")
57+
.fetch_all(&mut restored)
58+
.await?;
59+
assert_eq!(rows.len(), 2);
60+
61+
sqlx::query("insert into notes(body) values ('from restored connection')")
62+
.execute(&mut restored)
63+
.await?;
64+
65+
// serialize the updated database back into the container
66+
let updated: SqliteOwnedBuf = restored.serialize(None).await?;
67+
write_container(container_path, updated.as_ref())?;
68+
69+
std::fs::remove_file(container_path)?;
70+
71+
Ok(())
72+
}

0 commit comments

Comments
 (0)