Developer Guide v1.4

Welcome to the complete OverDrive-DB developer guide. This page covers everything from installation to advanced features.

OverDrive-DB is serverless. Your database is a single .odb file. No daemon, no network, no config. Import the library and go.

Installation

Python
Node.js
Java
Go
Rust
C / C++
pip install overdrive-db

Requires Python 3.8+. The native library is bundled in the package.

npm install overdrive-db

Requires Node.js 14+. The native library is bundled in the package.

<dependency>
    <groupId>com.afot</groupId>
    <artifactId>overdrive-db</artifactId>
    <version>1.4.0</version>
</dependency>

Requires Java 11+. Add to your pom.xml.

go get github.com/ALL-FOR-ONE-TECH/OverDrive-DB_IncodeSDK/go@v1.4.0

Requires Go 1.21+. Uses CGo — native library must be in your library path.

# Cargo.toml
[dependencies]
overdrive-db = "1.4.0"
serde_json = "1.0"

The crate dynamically loads the native library at runtime. Download overdrive.dll / liboverdrive.so / liboverdrive.dylib from GitHub Releases and place it in your project directory.

Download the C header and native library from GitHub Releases:

# Linux
gcc -o myapp myapp.c -L./lib -loverdrive -Wl,-rpath,./lib

# macOS
clang -o myapp myapp.c -L./lib -loverdrive

# Windows (MSVC)
cl myapp.c /link /LIBPATH:lib overdrive.dll.lib

Quick Start

Open a database, insert a document, query it. Tables are auto-created on first insert — no createTable() needed.

Python
Node.js
Java
Go
from overdrive import OverDrive

# Open or create a database
db = OverDrive.open("myapp.odb")

# Insert — "users" table auto-created
id = db.insert("users", {"name": "Alice", "age": 30, "city": "London"})
print(f"Inserted: {id}")  # users_1

# SQL query
results = db.query("SELECT * FROM users WHERE age > 25 ORDER BY name")
for user in results:
    print(f"  {user['name']} — age {user['age']}")

# Get by ID
user = db.get("users", id)
print(user)

# Update
db.update("users", id, {"age": 31})

# Delete
db.delete("users", id)

# Count
print(db.count("users"))  # 0

db.close()
const { OverDrive } = require('overdrive-db');

const db = OverDrive.open('myapp.odb');

// Insert — "users" table auto-created
const id = db.insert('users', { name: 'Alice', age: 30, city: 'London' });
console.log(`Inserted: ${id}`);  // users_1

// SQL query
const results = db.query('SELECT * FROM users WHERE age > 25 ORDER BY name');
results.forEach(u => console.log(`  ${u.name} — age ${u.age}`));

// Get, update, delete
const user = db.get('users', id);
db.update('users', id, { age: 31 });
db.delete('users', id);
console.log(db.count('users'));  // 0

db.close();
import com.afot.overdrive.OverDrive;
import java.util.Map;

try (OverDrive db = OverDrive.open("myapp.odb")) {
    // Insert — "users" table auto-created
    String id = db.insert("users", Map.of("name", "Alice", "age", 30));
    System.out.println("Inserted: " + id);  // users_1

    // SQL query
    var results = db.query("SELECT * FROM users WHERE age > 25");
    results.forEach(u -> System.out.println("  " + u.get("name")));

    // Get, update, delete
    var user = db.get("users", id);
    db.update("users", id, Map.of("age", 31));
    db.delete("users", id);
    System.out.println(db.count("users"));  // 0
}
import overdrive "github.com/ALL-FOR-ONE-TECH/OverDrive-DB_IncodeSDK/go"

db, _ := overdrive.Open("myapp.odb")
defer db.Close()

// Insert — "users" table auto-created
id, _ := db.Insert("users", map[string]any{"name": "Alice", "age": 30})
fmt.Printf("Inserted: %s\n", id)  // users_1

// SQL query
result, _ := db.Query("SELECT * FROM users WHERE age > 25")
for _, u := range result.Rows {
    fmt.Printf("  %s — age %v\n", u["name"], u["age"])
}

// Get, update, delete
user, _ := db.Get("users", id)
db.Update("users", id, map[string]any{"age": 31})
db.Delete("users", id)
count, _ := db.Count("users")
fmt.Println(count)  // 0

Core Concepts

The Database File

Your entire database lives in one .odb file. Copy it = backup. Delete it = gone. Move it = database moves with it.

Schemaless Documents

Tables have no fixed columns. Each document is a JSON object. Different documents in the same table can have different fields.

# All valid in the same "users" table
db.insert("users", {"name": "Alice", "age": 30})
db.insert("users", {"name": "Bob", "email": "bob@example.com", "premium": True})
db.insert("users", {"name": "Carol", "tags": ["admin"], "score": 9.5})

Auto-generated _id

Every document gets an _id automatically: users_1, users_2, orders_1, etc.

SQL on JSON

OverDrive has a built-in SQL engine. Write SQL, it runs on your JSON documents — no schema needed.

Storage Engines

OverDrive has 6 storage engines. Pick the right one for your use case.

EngineLatencyBest For
Disk (default)~1msGeneral-purpose persistent storage
RAM<1µsCaching, sessions, hot data
Vector~5msAI embeddings, similarity search
Time-Series~2msMetrics, IoT, logs
Graph~3msSocial networks, knowledge graphs
Streaming~1msEvent queues, message brokers

RAM Engine v1.4

Sub-microsecond reads. Full MVCC. Snapshot to disk and restore on startup.

Python
Node.js
# Full RAM database
cache = OverDrive.open("cache.odb", engine="RAM")
cache.insert("sessions", {"user_id": 123, "token": "abc"})

# Memory usage
usage = cache.memoryUsage()
print(f"Using {usage['mb']:.1f} MB ({usage['percent']:.1f}%)")

# Persist to disk
cache.snapshot("./backup/cache.odb")

# Restore later
cache2 = OverDrive.open("cache2.odb", engine="RAM")
cache2.restore("./backup/cache.odb")

# Per-table RAM in a disk database
db = OverDrive.open("app.odb")
db.createTable("sessions", engine="RAM")   # RAM table
db.insert("users", {"name": "Alice"})      # Disk table (auto-created)
// Full RAM database
const cache = OverDrive.open('cache.odb', { engine: 'RAM' });
cache.insert('sessions', { userId: 123, token: 'abc' });

// Memory usage
const usage = cache.memoryUsage();
console.log(`Using ${usage.mb.toFixed(1)} MB (${usage.percent.toFixed(1)}%)`);

// Persist to disk
cache.snapshot('./backup/cache.odb');

// Per-table RAM in a disk database
const db = OverDrive.open('app.odb');
db.createTable('sessions', { engine: 'RAM' });
db.insert('users', { name: 'Alice' });

Transactions

OverDrive uses MVCC (Multi-Version Concurrency Control). Transactions are ACID-compliant.

Callback Pattern v1.4

Pass a function — auto-commits on success, auto-rolls back on any exception.

Python
Node.js
Java
Go
# Callback pattern — recommended
def transfer(txn):
    db.updateMany("accounts", "id = 'alice'", {"balance": 900})
    db.updateMany("accounts", "id = 'bob'",   {"balance": 600})
    return "done"

result = db.transaction(transfer)

# With isolation level
result = db.transaction(transfer, isolation=OverDrive.SERIALIZABLE)

# With retry on conflict
result = db.transaction_with_retry(transfer, max_retries=3)

# Auto-rollback on exception
try:
    def bad(txn):
        db.insert("orders", {"item": "widget"})
        raise ValueError("oops")  # triggers rollback
    db.transaction(bad)
except ValueError:
    pass  # insert was rolled back

# Manual pattern (v1.3 — still works)
txn_id = db.begin_transaction()
db.insert("users", {"name": "Alice"})
db.commit_transaction(txn_id)
// Sync callback
const result = db.transaction((txn) => {
    db.updateMany('accounts', "id = 'alice'", { balance: 900 });
    return 'done';
});

// Async callback — returns Promise
const result = await db.transaction(async (txn) => {
    const id = db.insert('orders', { item: 'widget' });
    await someExternalCall();
    return id;
});

// With retry
const result = await db.transactionWithRetry(
    async (txn) => db.insert('orders', { item: 'widget' }),
    OverDrive.READ_COMMITTED, 3
);
// Generic callback — returns any type
String result = db.transaction(txn -> {
    db.updateMany("accounts", "id = 'alice'", Map.of("balance", 900));
    return "done";
});

// With isolation level
Integer count = db.transaction(txn -> {
    db.insert("logs", Map.of("event", "test"));
    return db.count("logs");
}, OverDrive.SERIALIZABLE);

// With retry
String r = db.transactionWithRetry(txn -> {
    db.insert("orders", Map.of("item", "widget"));
    return "done";
}, OverDrive.READ_COMMITTED, 3);
err := db.Transaction(func(txn *overdrive.TransactionHandle) error {
    _, err := db.UpdateMany("accounts", "id = 'alice'",
        map[string]any{"balance": 900})
    return err
}, overdrive.ReadCommitted)

// With retry
err = db.TransactionWithRetry(func(txn *overdrive.TransactionHandle) error {
    _, err := db.Insert("orders", map[string]any{"item": "widget"})
    return err
}, overdrive.ReadCommitted, 3)

Isolation Levels

LevelConstantDefaultUse When
Read UncommittedREAD_UNCOMMITTED (0)Maximum performance, minimal safety
Read CommittedREAD_COMMITTED (1)Most web apps, APIs
Repeatable ReadREPEATABLE_READ (2)Reports, analytics
SerializableSERIALIZABLE (3)Financial transactions, inventory

Helper Methods v1.4

Convenient wrappers for common patterns. All use the SQL engine internally.

# Python examples (Node.js, Java, Go have identical methods)

db = OverDrive.open("app.odb")

# findOne — first match or None/null
user = db.findOne("users", "age > 25")
first = db.findOne("users")  # no filter

# findAll — all matches with optional sorting and limit
users = db.findAll("users", "age > 25", order_by="name ASC", limit=10)

# updateMany — bulk update, returns count
count = db.updateMany("users", "status = 'trial'", {"status": "active"})
print(f"Updated {count} users")

# deleteMany — bulk delete, returns count
count = db.deleteMany("logs", "created_at < '2025-01-01'")

# countWhere — count matching documents
n = db.countWhere("users", "age > 25")
total = db.countWhere("users")  # count all

# exists — check by _id
found = db.exists("users", "users_1")  # True or False

Security

Password-Protected Databases v1.4

AES-256-GCM encryption with Argon2id key derivation (64MB memory, 3 iterations). Minimum 8 characters.

Never hardcode passwords. Always load from environment variables or a secrets manager.

# Python
import os
db = OverDrive.open("secure.odb", password=os.environ["DB_PASSWORD"])

# Node.js
const db = OverDrive.open('secure.odb', { password: process.env.DB_PASSWORD });

# Java
OverDrive db = OverDrive.open("secure.odb",
    new OverDrive.OpenOptions().password(System.getenv("DB_PASSWORD")));

# Go
db, _ := overdrive.Open("secure.odb",
    overdrive.WithPassword(os.Getenv("DB_PASSWORD")))

SQL Injection Prevention

Use querySafe() with ? placeholders for any user input.

# Python — SAFE
results = db.querySafe("SELECT * FROM users WHERE name = ?", user_input)
results = db.querySafe("SELECT * FROM users WHERE age > ? AND city = ?", "25", "London")

# Node.js — SAFE
const results = db.querySafe('SELECT * FROM users WHERE name = ?', [userInput]);

# DANGEROUS — never do this
db.query(f"SELECT * FROM users WHERE name = '{user_input}'")

Watchdog — File Integrity v1.4

# Python
report = OverDrive.watchdog("app.odb")
print(report.integrity_status)   # "valid", "corrupted", "missing"
print(report.file_size_bytes)
print(report.page_count)
if report.integrity_status == "corrupted":
    print(f"Details: {report.corruption_details}")

# Node.js
const report = OverDrive.watchdog('app.odb');
console.log(report.integrityStatus);  // "valid", "corrupted", "missing"

Backup and WAL Cleanup

# Python
db.backup("backups/app_2026-04-16.odb")  # encrypted backup

# After commit — prevent WAL replay attacks
txn_id = db.begin_transaction()
db.insert("users", {"name": "Alice"})
db.commit_transaction(txn_id)
db.cleanup_wal()

Python SDK

Install: pip install overdrive-db | Requires Python 3.8+

from overdrive import OverDrive, WatchdogReport, OverDriveError, AuthenticationError

# Open
db = OverDrive.open("app.odb")
db = OverDrive.open("app.odb", password="secret123", engine="Disk", auto_create_tables=True)
db = OverDrive.open("cache.odb", engine="RAM")

# CRUD
id = db.insert("users", {"name": "Alice", "age": 30})
ids = db.insert_many("users", [{"name": "Bob"}, {"name": "Carol"}])
user = db.get("users", id)          # dict or None
updated = db.update("users", id, {"age": 31})  # bool
deleted = db.delete("users", id)    # bool
count = db.count("users")           # int

# Query
results = db.query("SELECT * FROM users WHERE age > 25")
results = db.querySafe("SELECT * FROM users WHERE name = ?", user_input)
matches = db.search("users", "alice")

# Helpers (v1.4)
user = db.findOne("users", "age > 25")
users = db.findAll("users", "age > 25", order_by="name", limit=10)
n = db.updateMany("users", "status = 'trial'", {"status": "active"})
n = db.deleteMany("logs", "old = true")
n = db.countWhere("users", "active = true")
found = db.exists("users", "users_1")

# Transactions (v1.4)
result = db.transaction(lambda txn: db.insert("orders", {"item": "widget"}))
result = db.transaction_with_retry(my_fn, max_retries=3)

# RAM engine (v1.4)
db.snapshot("./backup.odb")
db.restore("./backup.odb")
usage = db.memoryUsage()  # {"bytes", "mb", "limit_bytes", "percent"}

# Watchdog (v1.4)
report = OverDrive.watchdog("app.odb")
# report.integrity_status, .file_size_bytes, .page_count, .magic_valid

# Security
db.backup("backups/app.odb")
db.cleanup_wal()

# Error handling
try:
    db = OverDrive.open("secure.odb", password="wrong")
except AuthenticationError as e:
    print(e.code, e.message, e.suggestions)

Node.js SDK

Install: npm install overdrive-db | Requires Node.js 14+

const { OverDrive, SharedOverDrive, OverDriveError, AuthenticationError } = require('overdrive-db');

// Open
const db = OverDrive.open('app.odb');
const db = OverDrive.open('app.odb', { password: 'secret123', engine: 'Disk', autoCreateTables: true });
const cache = OverDrive.open('cache.odb', { engine: 'RAM' });

// CRUD
const id = db.insert('users', { name: 'Alice', age: 30 });
const ids = db.insertMany('users', [{ name: 'Bob' }, { name: 'Carol' }]);
const user = db.get('users', id);          // object or null
const updated = db.update('users', id, { age: 31 });  // bool
const deleted = db.delete('users', id);    // bool
const count = db.count('users');           // number

// Query
const results = db.query('SELECT * FROM users WHERE age > 25');
const results = db.querySafe('SELECT * FROM users WHERE name = ?', [userInput]);
const matches = db.search('users', 'alice');

// Helpers (v1.4)
const user = db.findOne('users', 'age > 25');
const users = db.findAll('users', 'age > 25', 'name ASC', 10);
const n = db.updateMany('users', "status = 'trial'", { status: 'active' });
const n = db.deleteMany('logs', 'old = true');
const n = db.countWhere('users', 'active = true');
const found = db.exists('users', 'users_1');

// Transactions (v1.4)
const result = db.transaction((txn) => db.insert('orders', { item: 'widget' }));
const result = await db.transaction(async (txn) => { /* async work */ });
const result = await db.transactionWithRetry(async (txn) => { /* ... */ }, OverDrive.READ_COMMITTED, 3);

// RAM engine (v1.4)
db.snapshot('./backup.odb');
db.restore('./backup.odb');
const usage = db.memoryUsage();  // { bytes, mb, limit_bytes, percent }

// Watchdog (v1.4)
const report = OverDrive.watchdog('app.odb');
// report.integrityStatus, .fileSizeBytes, .pageCount, .magicValid

// Async-safe
const shared = new SharedOverDrive('app.odb');
await shared.insert('users', { name: 'Alice' });

// Error handling
try {
    OverDrive.open('secure.odb', { password: 'wrong' });
} catch (e) {
    if (e instanceof AuthenticationError) console.log(e.code, e.message);
}

Java SDK

Install: Maven dependency com.afot:overdrive-db:1.4.0 | Requires Java 11+

import com.afot.overdrive.OverDrive;
import com.afot.overdrive.OverDriveException.*;

// Open
OverDrive db = OverDrive.open("app.odb");
OverDrive db = OverDrive.open("app.odb", new OverDrive.OpenOptions()
    .password("secret123").engine("Disk").autoCreateTables(true));

// try-with-resources
try (OverDrive db = OverDrive.open("app.odb")) {
    // CRUD
    String id = db.insert("users", Map.of("name", "Alice", "age", 30));
    List<String> ids = db.insertMany("users", List.of(Map.of("name", "Bob")));
    Map<String, Object> user = db.get("users", id);
    boolean updated = db.update("users", id, Map.of("age", 31));
    boolean deleted = db.delete("users", id);
    int count = db.count("users");

    // Query
    List<Map<String, Object>> results = db.query("SELECT * FROM users WHERE age > 25");
    List<Map<String, Object>> results = db.querySafe("SELECT * FROM users WHERE name = ?", userName);

    // Helpers (v1.4)
    Map<String, Object> user = db.findOne("users", "age > 25");
    List<Map<String, Object>> users = db.findAll("users", "age > 25", "name ASC", 10);
    int n = db.updateMany("users", "status = 'trial'", Map.of("status", "active"));
    int n = db.deleteMany("logs", "old = true");
    int n = db.countWhere("users", "active = true");
    boolean found = db.exists("users", "users_1");

    // Transactions (v1.4)
    String result = db.transaction(txn -> {
        db.insert("orders", Map.of("item", "widget"));
        return "done";
    });
    String result = db.transactionWithRetry(txn -> "done", OverDrive.READ_COMMITTED, 3);

    // RAM engine (v1.4)
    db.snapshot("./backup.odb");
    db.restore("./backup.odb");
    OverDrive.MemoryUsage usage = db.memoryUsage();

    // Watchdog (v1.4)
    OverDrive.WatchdogReport report = OverDrive.watchdog("app.odb");
} catch (AuthenticationException e) {
    System.out.println(e.getCode() + ": " + e.getMessage());
}

Go SDK

Install: go get github.com/ALL-FOR-ONE-TECH/OverDrive-DB_IncodeSDK/go@v1.4.0 | Requires Go 1.21+

import overdrive "github.com/ALL-FOR-ONE-TECH/OverDrive-DB_IncodeSDK/go"

// Open
db, err := overdrive.Open("app.odb")
db, err := overdrive.Open("app.odb",
    overdrive.WithPassword("secret123"),
    overdrive.WithEngine("Disk"),
    overdrive.WithAutoCreateTables(true))
defer db.Close()

// CRUD
id, err := db.Insert("users", map[string]any{"name": "Alice", "age": 30})
user, err := db.Get("users", id)          // map or nil
updated, err := db.Update("users", id, map[string]any{"age": 31})
deleted, err := db.Delete("users", id)
count, err := db.Count("users")

// Query
result, err := db.Query("SELECT * FROM users WHERE age > 25")
result, err := db.QuerySafe("SELECT * FROM users WHERE name = ?", userName)
matches, err := db.Search("users", "alice")

// Helpers (v1.4)
user, err := db.FindOne("users", "age > 25")
users, err := db.FindAll("users", "age > 25", "name ASC", 10)
n, err := db.UpdateMany("users", "status = 'trial'", map[string]any{"status": "active"})
n, err := db.DeleteMany("logs", "old = true")
n, err := db.CountWhere("users", "active = true")
found, err := db.Exists("users", "users_1")

// Transactions (v1.4)
err = db.Transaction(func(txn *overdrive.TransactionHandle) error {
    _, err := db.Insert("orders", map[string]any{"item": "widget"})
    return err
}, overdrive.ReadCommitted)
err = db.TransactionWithRetry(myFn, overdrive.ReadCommitted, 3)

// RAM engine (v1.4)
err = db.Snapshot("./backup.odb")
err = db.Restore("./backup.odb")
usage, err := db.MemoryUsageStats()

// Watchdog (v1.4)
report, err := overdrive.Watchdog("app.odb")
// report.IntegrityStatus, .FileSizeBytes, .PageCount, .MagicValid

// Thread-safe
safeDB, err := overdrive.OpenSafe("app.odb")

Rust SDK

Install: overdrive-db = "1.4.0" in Cargo.toml | Requires Rust 2021 edition

The Rust crate dynamically loads the native library at runtime. Download overdrive.dll / liboverdrive.so / liboverdrive.dylib from GitHub Releases and place it next to your binary.

use overdrive::{OverDriveDB, IsolationLevel};
use overdrive::shared::SharedDB;
use serde_json::json;

let mut db = OverDriveDB::open("app.odb")?;
let mut db = OverDriveDB::open_encrypted("app.odb", "ODB_KEY")?;

db.create_table("users")?;
let id = db.insert("users", &json!({"name": "Alice", "age": 30}))?;
let user: Option<Value> = db.get("users", &id)?;
let updated: bool = db.update("users", &id, &json!({"age": 31}))?;
let deleted: bool = db.delete("users", &id)?;
let count: usize = db.count("users")?;

let result = db.query("SELECT * FROM users WHERE age > 25")?;
println!("{} rows in {:.2}ms", result.rows.len(), result.execution_time_ms);

let result = db.query_safe("SELECT * FROM users WHERE name = ?", &[user_input])?;

let txn = db.begin_transaction(IsolationLevel::ReadCommitted)?;
db.insert("orders", &json!({"item": "widget"}))?;
db.commit_transaction(&txn)?;
db.cleanup_wal()?;

db.backup("backups/app.odb")?;
db.close()?;

C / C++ SDK

Include overdrive.h and link against the native library.

Memory rule: Every char* returned by overdrive_* functions must be freed with overdrive_free_string(). The ODB* handle must be closed with overdrive_close().

#include "overdrive.h"
#include <stdio.h>

int main() {
    ODB* db = overdrive_open("myapp.odb");
    if (!db) { printf("Error: %s\n", overdrive_last_error()); return 1; }

    overdrive_create_table(db, "users");

    char* id = overdrive_insert(db, "users", "{\"name\":\"Alice\",\"age\":30}");
    printf("Inserted: %s\n", id);
    overdrive_free_string(id);  // must free!

    char* result = overdrive_query(db, "SELECT * FROM users WHERE age > 25");
    printf("Results: %s\n", result);
    overdrive_free_string(result);  // must free!

    uint64_t txn = overdrive_begin_transaction(db, 1);  // ReadCommitted
    overdrive_insert(db, "logs", "{\"event\":\"test\"}");
    overdrive_commit_transaction(db, txn);

    overdrive_sync(db);
    overdrive_close(db);
    return 0;
}

SQL Reference

-- SELECT
SELECT * FROM users
SELECT name, age FROM users
SELECT * FROM users WHERE age > 25
SELECT * FROM users WHERE age > 18 AND active = true
SELECT * FROM users WHERE city = 'London' OR city = 'Paris'
SELECT * FROM users WHERE name LIKE 'Al%'
SELECT * FROM users ORDER BY age DESC
SELECT * FROM users LIMIT 10 OFFSET 20

-- Aggregations
SELECT COUNT(*) FROM users
SELECT COUNT(*) FROM users WHERE active = true
SELECT AVG(age), MIN(age), MAX(age) FROM users
SELECT SUM(price) FROM orders

-- INSERT
INSERT INTO users VALUES {"name": "Alice", "age": 30}

-- UPDATE
UPDATE users SET {"age": 31} WHERE name = 'Alice'

-- DELETE
DELETE FROM users WHERE age < 18

-- DDL
CREATE TABLE users
DROP TABLE old_data
SHOW TABLES

WHERE Operators

OperatorExample
=WHERE name = 'Alice'
!=WHERE status != 'deleted'
> < >= <=WHERE age > 25
ANDWHERE age > 18 AND active = true
ORWHERE city = 'London' OR city = 'Paris'
LIKEWHERE name LIKE 'Al%' (% = any chars, _ = one char)

Error Codes

Format: ODB-{CATEGORY}-{NUMBER}

CodeMeaningSolution
ODB-AUTH-001Incorrect passwordVerify the password is correct
ODB-AUTH-002Password too shortUse at least 8 characters
ODB-TABLE-001Table not foundCreate table or enable auto_create_tables
ODB-TABLE-002Table already existsUse tableExists() before creating
ODB-QUERY-001SQL syntax errorCheck your SQL syntax
ODB-TXN-001Transaction deadlockUse transactionWithRetry()
ODB-TXN-002Transaction conflictUse transactionWithRetry()
ODB-IO-001File not foundCheck the database path
ODB-IO-003File corruptedRestore from backup
ODB-FFI-001Native library not foundDownload from GitHub Releases

Error Hierarchy

OverDriveError (base)
├── AuthenticationError   ODB-AUTH-*
├── TableError            ODB-TABLE-*
├── QueryError            ODB-QUERY-*
├── TransactionError      ODB-TXN-*
├── IOError               ODB-IO-*
└── FFIError              ODB-FFI-*

Migration Guide: v1.3 → v1.4

v1.4 is 100% backward compatible. All v1.3 code works without any changes.

Constructor → open()

# Before (v1.3) — still works
db = OverDrive("app.odb")

# After (v1.4) — recommended
db = OverDrive.open("app.odb")

openEncrypted() → open() with password

# Before (v1.3) — still works
db = OverDrive.open_encrypted("app.odb", "ODB_KEY")

# After (v1.4) — simpler
db = OverDrive.open("app.odb", password=os.environ["DB_PASSWORD"])

Manual transactions → callback pattern

# Before (v1.3) — still works
txn_id = db.begin_transaction()
try:
    db.insert("users", {"name": "Alice"})
    db.commit_transaction(txn_id)
except:
    db.abort_transaction(txn_id)
    raise

# After (v1.4) — recommended
db.transaction(lambda txn: db.insert("users", {"name": "Alice"}))

Manual table creation → auto-creation

# Before (v1.3) — still works
db = OverDrive("app.odb")
db.create_table("users")
db.insert("users", {"name": "Alice"})

# After (v1.4) — table auto-created
db = OverDrive.open("app.odb")
db.insert("users", {"name": "Alice"})  # table created automatically

GitHub · Releases · AFOT

#afot #OverDriveDb #InCodeSDK #EmbeddedDB