module history.data_impl_sqlite; import std.datetime; import handy_httpd.components.optional; import d2sqlite3; import history.data; import history.model; class SqliteHistoryRepository : HistoryRepository { private Database db; this(Database db) { this.db = db; } Optional!History findById(ulong id) { Statement stmt = db.prepare("SELECT * FROM history WHERE id = ?"); stmt.bind(1, id); ResultRange result = stmt.execute(); if (result.empty) return Optional!History.empty; return Optional!History.of(parseHistory(result.front)); } HistoryItem[] findItemsBefore(ulong historyId, SysTime timestamp, uint limit) { import std.conv; import std.algorithm; import std.array; const query = q"SQL SELECT * FROM history_item WHERE history_id = ? AND timestamp <= ? ORDER BY timestamp DESC LIMIT SQL"; Statement stmt = db.prepare(query ~ " " ~ to!string(limit)); stmt.bind(1, historyId); stmt.bind(2, timestamp.toISOExtString()); ResultRange result = stmt.execute(); return result.map!(r => parseItem(r)).array; } HistoryItemText getTextItem(ulong itemId) { Statement stmt = db.prepare("SELECT * FROM history_item_text WHERE item_id = ?"); stmt.bind(1, itemId); ResultRange result = stmt.execute(); if (result.empty) throw new Exception("No history item exists."); return parseTextItem(result.front); } void deleteById(ulong id) { Statement stmt = db.prepare("DELETE FROM history WHERE id = ?"); stmt.bind(1, id); stmt.execute(); } static History parseHistory(Row row) { return History(row.peek!ulong(0)); } static HistoryItem parseItem(Row row) { HistoryItem item; item.id = row.peek!ulong(0); item.historyId = row.peek!ulong(1); item.timestamp = SysTime.fromISOExtString(row.peek!string(2)); item.type = getHistoryItemType(row.peek!string(3)); return item; } static HistoryItemText parseTextItem(Row row) { HistoryItemText item; item.itemId = row.peek!ulong(0); item.content = row.peek!string(1); return item; } }