Skip to content

JEleniel/epiloglite

EpilogLite

Rust SQLite

EpilogLite is a pure Rust implementation of SQLite, designed for safety, reliability, and performance. Built with 100% safe Rust (no unsafe code), it provides a drop-in compatible alternative to SQLite with modern Rust idioms.

✨ Features

Currently Implemented

Core Database Operations

  • βœ… Full SQL Support - CREATE TABLE, INSERT, SELECT, UPDATE, DELETE
  • βœ… Disk Persistence - Data automatically saves to and loads from files
  • βœ… In-Memory Databases - Fast :memory: mode for temporary data
  • βœ… Transactions - BEGIN, COMMIT, ROLLBACK, SAVEPOINT, RELEASE support
  • βœ… Multiple Tables - Create and manage multiple tables simultaneously

Query Builder Pattern

  • βœ… Fluent Interface - Type-safe query construction
  • βœ… SelectBuilder - Build SELECT queries with WHERE, ORDER BY, LIMIT
  • βœ… InsertBuilder - Build INSERT statements with column specification
  • βœ… UpdateBuilder - Build UPDATE statements with SET clauses
  • βœ… DeleteBuilder - Build DELETE statements with conditions
  • βœ… CreateTableBuilder - Build CREATE TABLE with columns and constraints

Type System

  • βœ… 17+ Native Rust Types - Bool, I8-I128, U8-U128, F32/F64, String, Vec
  • βœ… SQL Type Mapping - INTEGER, TEXT, REAL, BLOB, BOOLEAN
  • βœ… NULL Support - Proper NULL value handling
  • βœ… Type Checking - Built-in type validation

Architecture

  • βœ… 100% Safe Rust - No unsafe code blocks
  • βœ… Modular Design - Clean separation of concerns
  • βœ… Error Handling - Comprehensive Result types
  • βœ… Test Coverage - 152 tests (124 unit + 18 adversarial + 10 integration)
  • βœ… Security Tested - SQL injection resistance, malformed input handling
  • βœ… Idiomatic Rust - Clippy-approved, modern patterns
  • βœ… Type Safety - ColumnType enum eliminates hardcoded strings

In Progress

  • 🚧 WHERE clause filtering
  • 🚧 JOIN operations
  • 🚧 Aggregate functions (COUNT, SUM, AVG, MIN, MAX)
  • 🚧 ORDER BY and GROUP BY implementation
  • 🚧 Index support

Platform Support

  • βœ… No-std Compatible - Works without standard library for embedded systems
  • βœ… In-memory Mode - Available in no-std environments
  • βœ… Custom Allocators - Bring your own allocator support

Planned

  • πŸ“‹ Unicode 16 support
  • πŸ“‹ Graph data structures
  • πŸ“‹ Role-based permissions
  • πŸ“‹ Lightweight ORM
  • πŸ“‹ REST/GraphQL API
  • πŸ“‹ SQLite C API compatibility
  • πŸ“‹ Embedded VFS for flash storage

πŸš€ Quick Start

Installation

Add to your Cargo.toml:

[dependencies]
epiloglite = "0.1"

Basic Usage

use epiloglite::{Database, ExecutionResult, Result};

fn main() -> Result<()> {
    // Open or create a database file
    let mut db = Database::open("mydata.db")?;
    
    // Create a table
    db.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)")?;
    
    // Insert data
    db.execute("INSERT INTO users VALUES (1, 'Alice', 30)")?;
    db.execute("INSERT INTO users VALUES (2, 'Bob', 25)")?;
    
    // Query data
    let result = db.execute("SELECT * FROM users")?;
    match result {
        ExecutionResult::Select { rows, columns } => {
            println!("Found {} rows", rows.len());
            for row in rows {
                println!("{:?}", row);
            }
        }
        _ => {}
    }
    
    // Update data
    db.execute("UPDATE users SET age = 31 WHERE id = 1")?;
    
    // Delete data
    db.execute("DELETE FROM users WHERE id = 2")?;
    
    // Close database (auto-saves)
    db.close()?;
    
    Ok(())
}

Query Builder Pattern

use epiloglite::{Database, SelectBuilder, InsertBuilder, UpdateBuilder, Result};

fn main() -> Result<()> {
    let mut db = Database::open("mydata.db")?;
    
    // Create table with builder
    let sql = CreateTableBuilder::new()
        .table("products")
        .column("id", "INTEGER", &["PRIMARY KEY"])
        .simple_column("name", "TEXT")
        .simple_column("price", "INTEGER")
        .build()?;
    db.execute(&sql)?;
    
    // Insert with builder
    let sql = InsertBuilder::new()
        .into("products")
        .columns(&["id", "name", "price"])
        .values(&["1", "'Widget'", "100"])
        .build()?;
    db.execute(&sql)?;
    
    // Query with builder
    let sql = SelectBuilder::new()
        .select_all()
        .from("products")
        .where_clause("price > 50")
        .order_by("name")
        .limit(10)
        .build()?;
    let result = db.execute(&sql)?;
    
    // Update with builder
    let sql = UpdateBuilder::new()
        .table("products")
        .set("price", "120")
        .where_clause("id = 1")
        .build()?;
    db.execute(&sql)?;
    
    db.close()?;
    Ok(())
}

In-Memory Database

use epiloglite::{Database, Result};

fn main() -> Result<()> {
    // Create in-memory database (faster, no disk I/O)
    let mut db = Database::open(":memory:")?;
    
    // Use like a regular database
    db.execute("CREATE TABLE temp_data (id INTEGER, value TEXT)")?;
    db.execute("INSERT INTO temp_data VALUES (1, 'test')")?;
    
    // Data is lost when database is closed
    db.close()?;
    
    Ok(())
}

No-std / Embedded Usage

EpilogLite can run without the standard library for embedded systems:

[dependencies]
epiloglite = { version = "0.1", default-features = false, features = ["no-std"] }
#![no_std]

extern crate alloc;

fn main() -> Result<(), epiloglite::Error> {
    // Create an in-memory database (no file I/O in no-std)
    let mut db = epiloglite::Database::new()?;
    
    db.execute("CREATE TABLE sensors (id INTEGER, value INTEGER)")?;
    db.execute("INSERT INTO sensors VALUES (1, 23)")?;
    
    let result = db.execute("SELECT * FROM sensors")?;
    
    Ok(())
}

See docs/NO_STD.md for detailed documentation and examples/embedded/ for more examples.

πŸ“š Examples

The examples/ directory contains several examples:

  • basic_usage.rs - Complete workflow demonstration
  • query_builder_example.rs - Query builder pattern examples
  • savepoint_example.rs - Transaction savepoint operations
  • embedded/no_std_basic.rs - No-std embedded example

Run examples with:

cargo run --example basic_usage
cargo run --example query_builder_example
cargo run --example savepoint_example

# No-std build (won't run but demonstrates compilation)
cargo build --example no_std_basic --no-default-features --features no-std

πŸ—οΈ Architecture

EpilogLite follows a modular architecture:

eplite/
β”œβ”€β”€ command/         # SQL parsing and execution
β”‚   β”œβ”€β”€ tokenizer    # Lexical analysis
β”‚   β”œβ”€β”€ parser       # Syntax analysis
β”‚   β”œβ”€β”€ processor    # Query execution
β”‚   └── virtual_machine # Bytecode VM
β”œβ”€β”€ persistence/     # Storage engine
β”‚   β”œβ”€β”€ pager        # Page cache management
β”‚   β”œβ”€β”€ btree        # B-tree implementation
β”‚   └── header       # Database header
β”œβ”€β”€ storage/         # Table and row management
β”œβ”€β”€ query_builder/   # Fluent query interface
β”œβ”€β”€ os/              # OS abstraction layer
└── types/           # Type system

πŸ§ͺ Testing

Run the test suite:

# Run all tests
cargo test

# Run specific test category
cargo test integration
cargo test query_builder

# Run with output
cargo test -- --nocapture

Current test coverage: 93 tests passing (88 unit + 5 integration)

πŸ“– Documentation

πŸ”’ Safety & Security

  • 100% Safe Rust - No unsafe blocks anywhere
  • Comprehensive Error Handling - All errors properly handled
  • No Panics - Graceful error returns
  • Memory Safe - Rust's ownership system prevents common bugs
  • Thread Safe - Designed for concurrent access

🎯 Goals

EpilogLite aims to:

  1. Provide a safe alternative to SQLite using pure Rust
  2. Maintain SQLite 3 compatibility for existing databases
  3. Offer modern Rust idioms (builders, async, etc.)
  4. Support all major platforms (Windows, Linux, macOS, mobile, embedded)
  5. Achieve high performance without sacrificing safety

🀝 Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.

πŸ“„ License

EpilogLite is licensed under the LGPL-3.0-only license.

Copyright (C) 2024 Tony M. Bishop

πŸ™ Acknowledgments

  • SQLite project for the original design and inspiration
  • Rust community for excellent tooling and libraries

πŸ“¬ Contact

For questions, issues, or contributions, please use GitHub Issues.

About

EpilogLite is an implementation of the SQLite library in pure Rust.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages