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
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.
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.
| Engine | Latency | Best For |
|---|---|---|
Disk (default) | ~1ms | General-purpose persistent storage |
RAM | <1µs | Caching, sessions, hot data |
Vector | ~5ms | AI embeddings, similarity search |
Time-Series | ~2ms | Metrics, IoT, logs |
Graph | ~3ms | Social networks, knowledge graphs |
Streaming | ~1ms | Event queues, message brokers |
RAM Engine v1.4
Sub-microsecond reads. Full MVCC. Snapshot to disk and restore on startup.
# 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.
# 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
| Level | Constant | Default | Use When |
|---|---|---|---|
| Read Uncommitted | READ_UNCOMMITTED (0) | Maximum performance, minimal safety | |
| Read Committed | READ_COMMITTED (1) | ✓ | Most web apps, APIs |
| Repeatable Read | REPEATABLE_READ (2) | Reports, analytics | |
| Serializable | SERIALIZABLE (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
| Operator | Example |
|---|---|
= | WHERE name = 'Alice' |
!= | WHERE status != 'deleted' |
> < >= <= | WHERE age > 25 |
AND | WHERE age > 18 AND active = true |
OR | WHERE city = 'London' OR city = 'Paris' |
LIKE | WHERE name LIKE 'Al%' (% = any chars, _ = one char) |
Error Codes
Format: ODB-{CATEGORY}-{NUMBER}
| Code | Meaning | Solution |
|---|---|---|
ODB-AUTH-001 | Incorrect password | Verify the password is correct |
ODB-AUTH-002 | Password too short | Use at least 8 characters |
ODB-TABLE-001 | Table not found | Create table or enable auto_create_tables |
ODB-TABLE-002 | Table already exists | Use tableExists() before creating |
ODB-QUERY-001 | SQL syntax error | Check your SQL syntax |
ODB-TXN-001 | Transaction deadlock | Use transactionWithRetry() |
ODB-TXN-002 | Transaction conflict | Use transactionWithRetry() |
ODB-IO-001 | File not found | Check the database path |
ODB-IO-003 | File corrupted | Restore from backup |
ODB-FFI-001 | Native library not found | Download 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
#afot #OverDriveDb #InCodeSDK #EmbeddedDB