Native DB

Native DB is a high performance, distributed, and embedded key-value store for multi-platform applications (server, desktop, mobile). It provides a simple API to sync Rust types effortlessly and supports real-time subscriptions.

Key Features

Simple API

Native DB offers a straightforward API for ease of use, minimizing boilerplate code.

Multiple Indexes

Supports multiple indexes including primary, secondary, unique, non-unique, and optional indexes.

Serialization and Deserialization

Transparent serialization and deserialization using native_model.

Automatic Model Migration

Automatically handles model migrations, reducing manual effort.

Thread-Safe and ACID-Compliant

Provides thread-safe operations and fully ACID-compliant transactions powered by redb.

Real-Time Subscription

Supports real-time subscriptions with filters for insert, update, and delete operations.

Rust Type Compatibility

Compatible with all Rust types including enum, struct, and tuple.

Hot Snapshots

Allows creating hot snapshots of the database for backup or cloning purposes.

Installation

Add the following dependencies to your Cargo.toml file:

[dependencies]
native_db = "0.6.1"
native_model = "0.4.14"

Note: native_db requires native_model to work.

Status

Native DB is under active development. The API is not stable yet and may change in the future.

Getting Started

With Tauri

Check out the example repository: native_db_tauri_vanilla.

Usual API

Models

Builder

Database

  • snapshot the database.
  • rw_transaction open a read-write transaction.
  • r_transaction open a read-only transaction.
    • get
    • scan
      • primary
        • all items.
        • start_with items with a primary key starting with a given value.
        • range items with a primary key in a given range.
      • secondary
        • all items with a given secondary key.
        • start_with items with a secondary key starting with a given value.
        • range items with a secondary key in a given range.
    • len
      • primary the number of items.
      • secondary the number of items with a given secondary key.
  • watch real-time subscriptions via std channel based or tokio channel based depending on the feature tokio.
    • get
    • scan
      • primary
        • all items.
        • start_with items with a primary key starting with a given value.
        • range items with a primary key in a given range.
      • secondary
        • all items with a given secondary key.
        • start_with items with a secondary key starting with a given value.
        • range items with a secondary key in a given range.

Example

Here's a basic example of using Native DB:

use serde::{Deserialize, Serialize};
use native_db::*;
use native_model::{native_model, Model};
 
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[native_model(id = 1, version = 1)]
#[native_db]
struct Item {
    #[primary_key]
    id: u32,
    #[secondary_key]
    name: String,
}
 
fn main() -> Result<(), db_type::Error> {
    let mut models = Models::new();
    // Initialize the model
    models.define::<Item>()?;
 
    // Create a database in memory
    let mut db = Builder::new().create_in_memory(&models)?;
 
    // Insert data (open a read-write transaction)
    let rw = db.rw_transaction().unwrap();
    rw.insert(Item { id: 1, name: "red".to_string() })?;
    rw.insert(Item { id: 2, name: "green".to_string() })?;
    rw.insert(Item { id: 3, name: "blue".to_string() })?;
    rw.commit()?;
 
    // Open a read-only transaction
    let r = db.r_transaction()?;
    // Retrieve data with id=3
    let retrieve_data: Item = r.get().primary(3_u32)?.unwrap();
    println!("data id='3': {:?}", retrieve_data);
    // Iterate items with name starting with "red"
    for item in r.scan().secondary::<Item>(ItemKey::name)?.start_with("red") {
        println!("data name=\"red\": {:?}", item);
    }
 
    // Remove data (open a read-write transaction)
    let rw = db.rw_transaction()?;
    rw.remove(retrieve_data)?;
    rw.commit()?;
    Ok(())
}

Similar Projects