Skip to main content

Crate sqlite_pages

Crate sqlite_pages 

Source
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 SQLite database 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 SQLite behavior)
  • Only one writer at a time (enforced by SQLite locks)
  • Use TransactionType::Immediate for writes to avoid SQLITE_BUSY errors
  • 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§

AsyncSqliteIo
Async interface for page-level SQLite database access.
Page
Represents a single database page.
SqliteIo
Main interface for page-level SQLite database access.

Enums§

Error
TransactionType
The type of transaction to begin.