module data.sqlite; import d2sqlite3; import slf4d; import data.base; import model; class SqliteDataSource : DataSource { const SCHEMA = import("schema.sql"); private const string dbPath; private Database db; this(string path) { this.dbPath = path; import std.file : exists; bool needsInit = !exists(path); this.db = Database(path); if (needsInit) { infoF!"Initializing database: %s"(dbPath); db.run(SCHEMA); } } PropertiesRepository getPropertiesRepository() { return new SqlitePropertiesRepository(db); } } class SqliteRepository { private Database db; this(Database db) { this.db = db; } } class SqlitePropertiesRepository : SqliteRepository, PropertiesRepository { this(Database db) { super(db); } Optional!string findProperty(string propertyName) { Statement stmt = this.db.prepare("SELECT value FROM profile_property WHERE property = ?"); stmt.bind(1, propertyName); ResultRange result = stmt.execute(); if (result.empty) return Optional!string.empty; return Optional!string.of(result.front.peek!string(0)); } void setProperty(string name, string value) { if (findProperty(name).isNull) { Statement stmt = this.db.prepare("INSERT INTO profile_property (property, value) VALUES (?, ?)"); stmt.bind(1, name); stmt.bind(2, value); stmt.execute(); } else { Statement stmt = this.db.prepare("UPDATE profile_property SET value = ? WHERE property = ?"); stmt.bind(1, value); stmt.bind(2, name); stmt.execute(); } } void deleteProperty(string name) { Statement stmt = this.db.prepare("DELETE FROM profile_property WHERE property = ?"); stmt.bind(1, name); stmt.execute(); } ProfileProperty[] findAll() { Statement stmt = this.db.prepare("SELECT * FROM profile_property ORDER BY property ASC"); ResultRange result = stmt.execute(); ProfileProperty[] props; foreach (Row row; result) { ProfileProperty prop; prop.property = row.peek!string("property"); prop.value = row.peek!string("value"); props ~= prop; } return props; } }