Expand description
SQLite page-level I/O library
This library provides direct access to SQLite’s raw database pages. It operates
below SQLite’s query layer and is not for normal database operations - use
standard SQLite queries for reading and writing data.
§Build Configuration
Add the following to your .cargo/config.toml:
[env]
LIBSQLITE3_FLAGS = "-DSQLITE_ENABLE_DBPAGE_VTAB"Without this flag, operations will fail with “no such table: sqlite_dbpage”.
§Page Numbering
All page numbers in this API are 1-based to match SQLite’s internal format.
The first page is page 1, not page 0.
§⚠️ Safety and Database Corruption Risk
This API bypasses SQLite’s safety mechanisms. Improper use will corrupt your database.
§What Constitutes Valid Page Data
Valid page data must:
- Come from another
SQLitedatabase with the same page size - Maintain internal consistency (page checksums, freelist pointers, etc.)
- Match the target database’s page size (typically 4096 bytes)
- Preserve the database file format (header page must be valid)
§What Will Cause Corruption
- Writing arbitrary/random data to pages
- Modifying individual bytes within a page
- Mixing pages from databases with different page sizes
- Writing pages out of order without maintaining internal consistency
- Modifying the database header page (page 1) incorrectly
§Safe Use Cases
This library is designed for:
- Database cloning: Copying all pages from one database to another
- Database repair: Copying valid pages from a backup
- Low-level analysis: Reading pages to understand database internals
§Concurrent Access
- Multiple readers are safe (standard
SQLitebehavior) - Only one writer at a time (enforced by
SQLitelocks) - Use
TransactionType::Immediatefor writes to avoidSQLITE_BUSYerrors - Do not access the same database file from multiple processes while writing pages
§Backup Recommendations
Always backup your database before using this library for writes.
use std::fs;
// Create a backup before modifying pages
fs::copy(&db_path, &backup_path)?;§How to Use
§Reading Pages
use sqlite_pages::SqliteIo;
let db = SqliteIo::open(&db_path.to_string_lossy())?;
// Iterate over all pages
db.page_map(.., |page_num, data| {
println!("Page {}: {} bytes", page_num, data.len());
})?;§Writing Pages
use sqlite_pages::{SqliteIo, TransactionType};
let db = SqliteIo::open(&db_path.to_string_lossy())?;
let mut tx = db.transaction(TransactionType::Immediate)?;
for (page_num, data) in pages {
tx.set_page_data(page_num, &data)?;
}
tx.commit()?;§Async API
For async contexts, use AsyncSqliteIo:
use sqlite_pages::{AsyncSqliteIo, TransactionType};
let db = AsyncSqliteIo::open(&db_path.to_string_lossy()).await?;
let tx = db.transaction(TransactionType::Immediate).await?;
tx.set_page_data(1, &page_data).await?;
tx.commit().await?;Structs§
- Async
Sqlite Io - Async interface for page-level
SQLitedatabase access. - Page
- Represents a single database page.
- Sqlite
Io - Main interface for page-level
SQLitedatabase access.
Enums§
- Error
- Transaction
Type - The type of transaction to begin.