This document maps the first LeoRM building blocks before implementation starts.
The goal is to keep the V1 API small, explicit, Leopard-native, and SQLite-honest.
LeoRM is not a full ORM framework. These classes are storage helpers, not a new object world.
Domain Store / Application
-> LRMRepository
-> LRMDatabase
-> LRMStatement / LRMResultSet / LRMRow
-> sqlite3 / sqlite3_stmt
Responsible for owning an SQLite database connection.
Responsibilities:
- open database at path,
- close database safely,
- expose database path,
- create prepared statements,
- begin transactions,
- report SQLite errors as NSError,
- provide low-level access only where explicitly needed.
Does not:
- define schemas,
- know domain objects,
- hide SQL,
- act as a global singleton.
Likely wraps:
sqlite3 *Possible API shape:
+ (id)databaseWithPath:(NSString *)path error:(NSError **)error;
- (id)initWithPath:(NSString *)path error:(NSError **)error;
- (BOOL)open:(NSError **)error;
- (void)close;
- (LRMStatement *)prepareStatement:(NSString *)sql error:(NSError **)error;
- (LRMTransaction *)beginTransaction:(NSError **)error;Responsible for owning a prepared SQLite statement.
Responsibilities:
- prepare SQL,
- bind values,
- step through execution,
- reset statement,
- finalize statement,
- expose SQL for debugging.
Does not:
- generate SQL,
- map rows into domain objects,
- own transactions.
Likely wraps:
sqlite3_stmt *Possible API shape:
- (BOOL)bindObject:(id)value atIndex:(NSInteger)index error:(NSError **)error;
- (BOOL)execute:(NSError **)error;
- (LRMResultSet *)executeQuery:(NSError **)error;
- (void)reset;
- (void)finalizeStatement;Responsible for iterating over rows returned by a query.
Responsibilities:
- advance to next row,
- provide the current row,
- close/finalize when finished,
- report step errors.
Does not:
- store all rows by default,
- map objects automatically,
- hide column names or indexes.
Possible API shape:
- (BOOL)next:(NSError **)error;
- (LRMRow *)currentRow;
- (void)close;Responsible for reading typed values from the current SQLite row.
Responsibilities:
- read values by column index,
- read values by column name where available,
- convert SQLite values to Foundation values,
- expose null handling clearly.
Does not:
- know domain classes,
- validate domain rules,
- retain statement lifetime beyond its valid scope.
Possible API shape:
- (id)objectForColumn:(NSString *)name;
- (id)objectAtIndex:(NSInteger)index;
- (NSString *)stringForColumn:(NSString *)name;
- (NSNumber *)numberForColumn:(NSString *)name;
- (NSData *)dataForColumn:(NSString *)name;
- (BOOL)isNullForColumn:(NSString *)name;Responsible for explicit transaction boundaries.
Responsibilities:
- begin transaction,
- commit transaction,
- rollback transaction,
- report errors,
- prevent double commit / rollback where possible.
Does not:
- silently start transactions,
- hide write boundaries,
- implement nested transactions in V1.
Possible API shape:
- (BOOL)commit:(NSError **)error;
- (BOOL)rollback:(NSError **)error;
- (BOOL)isActive;Nested transaction behavior is out of scope for V1 unless implemented through documented SQLite savepoints.
Responsible for describing schema metadata.
Responsibilities:
- expose schema name,
- expose target version,
- provide migration list,
- identify LeoRM metadata keys.
Does not:
- define domain schemas inside LeoRM,
- generate application tables automatically.
Possible API shape:
- (NSString *)schemaName;
- (NSInteger)targetVersion;
- (NSArray *)migrations;Responsible for one explicit schema migration step.
Responsibilities:
- define source version,
- define target version,
- execute migration SQL or callback,
- report failure through NSError.
Does not:
- infer migrations automatically,
- hide destructive changes,
- know application semantics beyond the migration owner.
Possible API shape:
- (NSInteger)fromVersion;
- (NSInteger)toVersion;
- (BOOL)applyToDatabase:(LRMDatabase *)database error:(NSError **)error;Responsible for applying migrations in order.
Responsibilities:
- read current schema version,
- compare against target version,
- run missing migrations,
- update metadata after successful migration,
- stop on first failure.
Does not:
- invent migrations,
- skip failed migrations,
- modify domain tables except through supplied migration steps.
Possible API shape:
- (BOOL)migrateDatabase:(LRMDatabase *)database
schema:(LRMSchema *)schema
error:(NSError **)error;Base class or helper for DAO-style access.
Responsibilities:
- hold database reference,
- centralize SQL for one table or aggregate,
- provide small query/update methods,
- map rows to domain objects through explicit code.
Does not:
- become ActiveRecord,
- require domain objects to inherit from LeoRM classes,
- hide SQL as the default model.
Possible API shape:
- (id)initWithDatabase:(LRMDatabase *)database;
- (NSArray *)findWhere:(NSString *)whereSQL
arguments:(NSArray *)arguments
error:(NSError **)error;Subclasses or domain repositories should implement object mapping.
Responsible for consistent error reporting.
Responsibilities:
- define LeoRM error domain,
- map SQLite result codes,
- include SQL and database path where useful,
- preserve underlying SQLite message.
Possible API shape:
extern NSString * const LRMErrorDomain;
NSError *LRMErrorMake(NSInteger code, NSString *message);
NSError *LRMSQLiteErrorMake(sqlite3 *db, NSString *sql);Recommended V1 mapping:
SQLITE_TEXT -> NSString
SQLITE_INTEGER -> NSNumber
SQLITE_FLOAT -> NSNumber
SQLITE_BLOB -> NSData
SQLITE_NULL -> nil or NSNull, depending on method contract
Date handling is explicit and not magical in V1.
LeoRM V1 should depend on:
- Foundation.framework,
- libsqlite3,
- Objective-C runtime available on Leopard.
LeoRM V1 should not require:
- AppKit,
- Core Data,
- Cocoa Bindings,
- Swift,
- ARC,
- blocks,
- Grand Central Dispatch,
- modern package managers.
Public classes use the LRM prefix.
Internal helper functions may use the LRM prefix as well.
No domain-specific prefix belongs in LeoRM.
Recommended implementation order:
- LRMError
- LRMDatabase
- LRMStatement
- LRMResultSet
- LRMRow
- LRMTransaction
- LRMSchema / LRMMigration
- LRMMigrationRunner
- LRMRepository
This order keeps the low-level SQLite bridge testable before repository helpers are added.