class database+ { private import lib::sqlite3; struct database { db void; } func constructor() { this.db = null; } func destructor() { this->close(); } func open(filename+ char, flags int = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE) bool { this->close(); return sqlite3_open_v2(filename, &this.db, flags, null) == SQLITE_OK; } func close() { if this.db ~= null; sqlite3_close_v2(this.db), this.db = null; } inline exec(sql+ char) bool { return sqlite3_exec(this.db, sql, null, null, null) == SQLITE_OK; } func execf(sql+ char, ...) bool { if (sql = sqlite3_vmprintf(sql, va_start(this))) == null; return false; func = this->exec(sql); sqlite3_free(sql); } inline prepare(stmt. stmt, sql+ char) bool { return sqlite3_prepare_v2(this.db, sql, -1, &stmt.obj, null) == SQLITE_OK; } func preparef(stmt. stmt, sql+ char, ...) bool { if (sql = sqlite3_vmprintf(sql, va_start(this))) == null; return false; func = this->prepare(stmt, sql); sqlite3_free(sql); } func prepare_step(stmt. stmt, sql+ char) bool { if !this->prepare(stmt, sql); return false; return stmt->step(); } func preparef_step(stmt. stmt, sql+ char, ...) bool { if (sql = sqlite3_vmprintf(sql, va_start(this))) == null; return false; defer sqlite3_free(sql); if !this->prepare(stmt, sql); return false; return stmt->step(); } inline last_insert_rowid() int64 { return sqlite3_last_insert_rowid(this.db); } // static inline free(ptr void) { sqlite3_free(ptr); } } class database+, stmt { private import lib::sqlite3; struct stmt { obj void; step_error bool; } func constructor() { this.obj = null; this.step_error = false; } func destructor() { this->finalize(); } inline bind_blob(index int, blob void, blob_size int, callback void) bool { return sqlite3_bind_blob(this.obj, index, blob, blob_size, callback) == SQLITE_OK; } inline bind_double(index int, data double) bool { return sqlite3_bind_double(this.obj, index, data) == SQLITE_OK; } inline bind_int(index int, data int) bool { return sqlite3_bind_int(this.obj, index, data) == SQLITE_OK; } inline bind_null(index int) bool { return sqlite3_bind_null(this.obj, index) == SQLITE_OK; } inline bind_text(index int, text+ char, text_len int, callback void) bool { return sqlite3_bind_text(this.obj, index, text, text_len, callback) == SQLITE_OK; } inline bind_text16(index int, text void, text_len int, callback void) bool { return sqlite3_bind_text16(this.obj, index, text, text_len, callback) == SQLITE_OK; } inline bind_text64(index int, text+ char, text_len int64, callback void, encoding char) bool { return sqlite3_bind_text64(this.obj, index, text, text_len, callback, encoding) == SQLITE_OK; } inline bind_value(index int, value void) bool { return sqlite3_bind_value(this.obj, index, value) == SQLITE_OK; } inline bind_zeroblob(index int, size int) bool { return sqlite3_bind_zeroblob(this.obj, index, size) == SQLITE_OK; } inline bind_param_count() int { return sqlite3_bind_parameter_count(this.obj); } inline bind_param_name(index int) +char { return sqlite3_bind_parameter_name(this.obj, index); } inline bind_param_index(name+ char) int { return sqlite3_bind_parameter_index(this.obj, name); } inline clear_bind() bool { return sqlite3_clear_bindings(this.obj) == SQLITE_OK; } inline data_count() int { return sqlite3_data_count(this.obj); } inline column_count() int { return sqlite3_column_count(this.obj); } inline column_name(index int) +char { return sqlite3_column_name(this.obj, index); } inline column_name16(index int) void { return sqlite3_column_name16(this.obj, index); } func step() bool { var result int = sqlite3_step(this.obj); if result ~= SQLITE_ROW { /* SQLITE_BUSY SQLITE_ERROR SQLITE_MISUSE */ this.step_error = result ~= SQLITE_DONE; return false; } return true; } inline step_error?() bool { return this.step_error; } inline reset() bool { return sqlite3_reset(this.obj) == SQLITE_OK; } inline column_blob(col int) void { return sqlite3_column_blob(this.obj, col); } inline column_double(col int) double { return sqlite3_column_double(this.obj, col); } inline column_int(col int) int { return sqlite3_column_int(this.obj, col); } inline column_text(col int) +char { return sqlite3_column_text(this.obj, col); } inline column_text16(col int) void { return sqlite3_column_text16(this.obj, col); } inline column_value(col int) void { return sqlite3_column_value(this.obj, col); } inline column_bytes(col int) int { return sqlite3_column_bytes(this.obj, col); } inline column_bytes16(col int) int { return sqlite3_column_bytes16(this.obj, col); } inline column_type(col int) int { return sqlite3_column_type(this.obj, col); } func finalize() bool { if this.obj ~= null { if sqlite3_finalize(this.obj) ~= SQLITE_OK; return false; this.obj = null; } return true; } }