Move DatabaseError handling into Qlite
This commit is contained in:
parent
d9b91206c0
commit
b9df78e449
|
@ -186,7 +186,7 @@ public class Database : Qlite.Database {
|
||||||
public Map<string, int> jid_table_reverse = new HashMap<string, int>();
|
public Map<string, int> jid_table_reverse = new HashMap<string, int>();
|
||||||
public Map<int, Account> account_table_cache = new HashMap<int, Account>();
|
public Map<int, Account> account_table_cache = new HashMap<int, Account>();
|
||||||
|
|
||||||
public Database(string fileName) throws DatabaseError {
|
public Database(string fileName) {
|
||||||
base(fileName, VERSION);
|
base(fileName, VERSION);
|
||||||
account = new AccountTable(this);
|
account = new AccountTable(this);
|
||||||
jid = new JidTable(this);
|
jid = new JidTable(this);
|
||||||
|
|
|
@ -9,7 +9,6 @@ public class Plugin : RootInterface, Object {
|
||||||
public FileProvider file_provider;
|
public FileProvider file_provider;
|
||||||
|
|
||||||
public void registered(Dino.Application app) {
|
public void registered(Dino.Application app) {
|
||||||
try {
|
|
||||||
this.app = app;
|
this.app = app;
|
||||||
Manager.start(this.app.stream_interactor, app.db);
|
Manager.start(this.app.stream_interactor, app.db);
|
||||||
|
|
||||||
|
@ -21,9 +20,6 @@ public class Plugin : RootInterface, Object {
|
||||||
|
|
||||||
app.stream_interactor.get_module(FileManager.IDENTITY).add_provider(file_provider);
|
app.stream_interactor.get_module(FileManager.IDENTITY).add_provider(file_provider);
|
||||||
app.plugin_registry.register_message_display(new FileMessageFilterDisplay(app.db));
|
app.plugin_registry.register_message_display(new FileMessageFilterDisplay(app.db));
|
||||||
} catch (Error e) {
|
|
||||||
print(@"Error initializing http-files: $(e.message)\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
|
|
@ -36,7 +36,6 @@ public class AccountSettingWidget : Plugins.AccountSettingsWidget, Box {
|
||||||
public void set_account(Account account) {
|
public void set_account(Account account) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
btn.visible = false;
|
btn.visible = false;
|
||||||
try {
|
|
||||||
Qlite.Row? row = plugin.db.identity.row_with(plugin.db.identity.account_id, account.id).inner;
|
Qlite.Row? row = plugin.db.identity.row_with(plugin.db.identity.account_id, account.id).inner;
|
||||||
if (row == null) {
|
if (row == null) {
|
||||||
fingerprint.set_markup("%s\n<span font='8'>%s</span>".printf(_("Own fingerprint"), _("Will be generated on first connect")));
|
fingerprint.set_markup("%s\n<span font='8'>%s</span>".printf(_("Own fingerprint"), _("Will be generated on first connect")));
|
||||||
|
@ -45,9 +44,6 @@ public class AccountSettingWidget : Plugins.AccountSettingsWidget, Box {
|
||||||
fingerprint.set_markup("%s\n<span font_family='monospace' font='8'>%s</span>".printf(_("Own fingerprint"), res));
|
fingerprint.set_markup("%s\n<span font_family='monospace' font='8'>%s</span>".printf(_("Own fingerprint"), res));
|
||||||
btn.visible = true;
|
btn.visible = true;
|
||||||
}
|
}
|
||||||
} catch (Qlite.DatabaseError e) {
|
|
||||||
fingerprint.set_markup("%s\n<span font='8'>%s</span>".printf(_("Own fingerprint"), _("Database error")));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deactivate() {
|
public void deactivate() {
|
||||||
|
|
|
@ -23,11 +23,11 @@ public class Database : Qlite.Database {
|
||||||
index("identity_meta_list_idx", {address_name});
|
index("identity_meta_list_idx", {address_name});
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryBuilder with_address(string address_name) throws DatabaseError {
|
public QueryBuilder with_address(string address_name) {
|
||||||
return select().with(this.address_name, "=", address_name);
|
return select().with(this.address_name, "=", address_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insert_device_list(string address_name, ArrayList<int32> devices) throws DatabaseError {
|
public void insert_device_list(string address_name, ArrayList<int32> devices) {
|
||||||
update().with(this.address_name, "=", address_name).set(now_active, false).perform();
|
update().with(this.address_name, "=", address_name).set(now_active, false).perform();
|
||||||
foreach (int32 device_id in devices) {
|
foreach (int32 device_id in devices) {
|
||||||
upsert()
|
upsert()
|
||||||
|
@ -39,7 +39,7 @@ public class Database : Qlite.Database {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int64 insert_device_bundle(string address_name, int device_id, Bundle bundle) throws DatabaseError {
|
public int64 insert_device_bundle(string address_name, int device_id, Bundle bundle) {
|
||||||
if (bundle == null || bundle.identity_key == null) return -1;
|
if (bundle == null || bundle.identity_key == null) return -1;
|
||||||
return upsert()
|
return upsert()
|
||||||
.value(this.address_name, address_name, true)
|
.value(this.address_name, address_name, true)
|
||||||
|
@ -108,7 +108,7 @@ public class Database : Qlite.Database {
|
||||||
public PreKeyTable pre_key { get; private set; }
|
public PreKeyTable pre_key { get; private set; }
|
||||||
public SessionTable session { get; private set; }
|
public SessionTable session { get; private set; }
|
||||||
|
|
||||||
public Database(string fileName) throws DatabaseError {
|
public Database(string fileName) {
|
||||||
base(fileName, VERSION);
|
base(fileName, VERSION);
|
||||||
identity_meta = new IdentityMetaTable(this);
|
identity_meta = new IdentityMetaTable(this);
|
||||||
identity = new IdentityTable(this);
|
identity = new IdentityTable(this);
|
||||||
|
|
|
@ -196,7 +196,6 @@ public class Manager : StreamInteractionModule, Object {
|
||||||
if (module == null) {
|
if (module == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
ArrayList<int32> device_list = module.get_device_list(jid);
|
ArrayList<int32> device_list = module.get_device_list(jid);
|
||||||
db.identity_meta.insert_device_list(jid, device_list);
|
db.identity_meta.insert_device_list(jid, device_list);
|
||||||
int inc = 0;
|
int inc = 0;
|
||||||
|
@ -207,28 +206,14 @@ public class Manager : StreamInteractionModule, Object {
|
||||||
if (inc > 0) {
|
if (inc > 0) {
|
||||||
if (Plugin.DEBUG) print(@"OMEMO: new bundles $inc/$(device_list.size) for $jid\n");
|
if (Plugin.DEBUG) print(@"OMEMO: new bundles $inc/$(device_list.size) for $jid\n");
|
||||||
}
|
}
|
||||||
} catch (DatabaseError e) {
|
|
||||||
// Ignore
|
|
||||||
print(@"OMEMO: failed to use database: $(e.message)\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void on_bundle_fetched(Account account, string jid, int32 device_id, Bundle bundle) {
|
public void on_bundle_fetched(Account account, string jid, int32 device_id, Bundle bundle) {
|
||||||
try {
|
|
||||||
db.identity_meta.insert_device_bundle(jid, device_id, bundle);
|
db.identity_meta.insert_device_bundle(jid, device_id, bundle);
|
||||||
} catch (DatabaseError e) {
|
|
||||||
// Ignore
|
|
||||||
print(@"OMEMO: failed to use database: $(e.message)\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_store_created(Account account, Store store) {
|
private void on_store_created(Account account, Store store) {
|
||||||
Qlite.Row? row = null;
|
Qlite.Row? row = db.identity.row_with(db.identity.account_id, account.id).inner;
|
||||||
try {
|
|
||||||
row = db.identity.row_with(db.identity.account_id, account.id).inner;
|
|
||||||
} catch (Error e) {
|
|
||||||
// Ignore error
|
|
||||||
}
|
|
||||||
int identity_id = -1;
|
int identity_id = -1;
|
||||||
|
|
||||||
if (row == null) {
|
if (row == null) {
|
||||||
|
|
|
@ -30,7 +30,6 @@ public class Plugin : RootInterface, Object {
|
||||||
public ContactDetailsProvider contact_details_provider;
|
public ContactDetailsProvider contact_details_provider;
|
||||||
|
|
||||||
public void registered(Dino.Application app) {
|
public void registered(Dino.Application app) {
|
||||||
try {
|
|
||||||
ensure_context();
|
ensure_context();
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.db = new Database(Path.build_filename(Application.get_storage_dir(), "omemo.db"));
|
this.db = new Database(Path.build_filename(Application.get_storage_dir(), "omemo.db"));
|
||||||
|
@ -52,9 +51,6 @@ public class Plugin : RootInterface, Object {
|
||||||
locales_dir = LOCALE_INSTALL_DIR;
|
locales_dir = LOCALE_INSTALL_DIR;
|
||||||
}
|
}
|
||||||
internationalize(GETTEXT_PACKAGE, locales_dir);
|
internationalize(GETTEXT_PACKAGE, locales_dir);
|
||||||
} catch (Error e) {
|
|
||||||
print(@"Error initializing OMEMO: $(e.message)\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
|
|
@ -27,26 +27,18 @@ private class BackedPreKeyStore : SimplePreKeyStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void on_pre_key_stored(PreKeyStore.Key key) {
|
public void on_pre_key_stored(PreKeyStore.Key key) {
|
||||||
try {
|
|
||||||
db.pre_key.insert().or("REPLACE")
|
db.pre_key.insert().or("REPLACE")
|
||||||
.value(db.pre_key.identity_id, identity_id)
|
.value(db.pre_key.identity_id, identity_id)
|
||||||
.value(db.pre_key.pre_key_id, (int) key.key_id)
|
.value(db.pre_key.pre_key_id, (int) key.key_id)
|
||||||
.value(db.pre_key.record_base64, Base64.encode(key.record))
|
.value(db.pre_key.record_base64, Base64.encode(key.record))
|
||||||
.perform();
|
.perform();
|
||||||
} catch (Error e) {
|
|
||||||
print(@"OMEMO: Error while updating pre key store: $(e.message)\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void on_pre_key_deleted(PreKeyStore.Key key) {
|
public void on_pre_key_deleted(PreKeyStore.Key key) {
|
||||||
try {
|
|
||||||
db.pre_key.delete()
|
db.pre_key.delete()
|
||||||
.with(db.pre_key.identity_id, "=", identity_id)
|
.with(db.pre_key.identity_id, "=", identity_id)
|
||||||
.with(db.pre_key.pre_key_id, "=", (int) key.key_id)
|
.with(db.pre_key.pre_key_id, "=", (int) key.key_id)
|
||||||
.perform();
|
.perform();
|
||||||
} catch (Error e) {
|
|
||||||
print(@"OMEMO: Error while updating pre key store: $(e.message)\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,28 +29,20 @@ private class BackedSessionStore : SimpleSessionStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void on_session_stored(SessionStore.Session session) {
|
public void on_session_stored(SessionStore.Session session) {
|
||||||
try {
|
|
||||||
db.session.insert().or("REPLACE")
|
db.session.insert().or("REPLACE")
|
||||||
.value(db.session.identity_id, identity_id)
|
.value(db.session.identity_id, identity_id)
|
||||||
.value(db.session.address_name, session.name)
|
.value(db.session.address_name, session.name)
|
||||||
.value(db.session.device_id, session.device_id)
|
.value(db.session.device_id, session.device_id)
|
||||||
.value(db.session.record_base64, Base64.encode(session.record))
|
.value(db.session.record_base64, Base64.encode(session.record))
|
||||||
.perform();
|
.perform();
|
||||||
} catch (Error e) {
|
|
||||||
print(@"OMEMO: Error while updating session store: $(e.message)\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void on_session_deleted(SessionStore.Session session) {
|
public void on_session_deleted(SessionStore.Session session) {
|
||||||
try {
|
|
||||||
db.session.delete()
|
db.session.delete()
|
||||||
.with(db.session.identity_id, "=", identity_id)
|
.with(db.session.identity_id, "=", identity_id)
|
||||||
.with(db.session.address_name, "=", session.name)
|
.with(db.session.address_name, "=", session.name)
|
||||||
.with(db.session.device_id, "=", session.device_id)
|
.with(db.session.device_id, "=", session.device_id)
|
||||||
.perform();
|
.perform();
|
||||||
} catch (Error e) {
|
|
||||||
print(@"OMEMO: Error while updating session store: $(e.message)\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,27 +27,18 @@ private class BackedSignedPreKeyStore : SimpleSignedPreKeyStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void on_signed_pre_key_stored(SignedPreKeyStore.Key key) {
|
public void on_signed_pre_key_stored(SignedPreKeyStore.Key key) {
|
||||||
try {
|
|
||||||
db.signed_pre_key.insert().or("REPLACE")
|
db.signed_pre_key.insert().or("REPLACE")
|
||||||
.value(db.signed_pre_key.identity_id, identity_id)
|
.value(db.signed_pre_key.identity_id, identity_id)
|
||||||
.value(db.signed_pre_key.signed_pre_key_id, (int) key.key_id)
|
.value(db.signed_pre_key.signed_pre_key_id, (int) key.key_id)
|
||||||
.value(db.signed_pre_key.record_base64, Base64.encode(key.record))
|
.value(db.signed_pre_key.record_base64, Base64.encode(key.record))
|
||||||
.perform();
|
.perform();
|
||||||
} catch (Error e) {
|
|
||||||
print(@"OMEMO: Error while updating signed pre key store: $(e.message)\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void on_signed_pre_key_deleted(SignedPreKeyStore.Key key) {
|
public void on_signed_pre_key_deleted(SignedPreKeyStore.Key key) {
|
||||||
try {
|
|
||||||
db.signed_pre_key.delete()
|
db.signed_pre_key.delete()
|
||||||
.with(db.signed_pre_key.identity_id, "=", identity_id)
|
.with(db.signed_pre_key.identity_id, "=", identity_id)
|
||||||
.with(db.signed_pre_key.signed_pre_key_id, "=", (int) key.key_id)
|
.with(db.signed_pre_key.signed_pre_key_id, "=", (int) key.key_id)
|
||||||
.perform();
|
.perform();
|
||||||
} catch (Error e) {
|
|
||||||
print(@"OMEMO: Error while updating signed pre key store: $(e.message)\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,6 @@ using Sqlite;
|
||||||
|
|
||||||
namespace Qlite {
|
namespace Qlite {
|
||||||
|
|
||||||
public errordomain DatabaseError {
|
|
||||||
ILLEGAL_QUERY,
|
|
||||||
NOT_SUPPORTED,
|
|
||||||
OPEN_ERROR,
|
|
||||||
PREPARE_ERROR,
|
|
||||||
EXEC_ERROR,
|
|
||||||
NON_UNIQUE,
|
|
||||||
ILLEGAL_REFERENCE,
|
|
||||||
NOT_INITIALIZED
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Database {
|
public class Database {
|
||||||
private string file_name;
|
private string file_name;
|
||||||
private Sqlite.Database db;
|
private Sqlite.Database db;
|
||||||
|
@ -33,29 +22,25 @@ public class Database {
|
||||||
meta_table.init({meta_name, meta_int_val, meta_text_val});
|
meta_table.init({meta_name, meta_int_val, meta_text_val});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(Table[] tables) throws DatabaseError {
|
public void init(Table[] tables) {
|
||||||
Sqlite.config(Config.SERIALIZED);
|
Sqlite.config(Config.SERIALIZED);
|
||||||
int ec = Sqlite.Database.open_v2(file_name, out db, OPEN_READWRITE | OPEN_CREATE | 0x00010000);
|
int ec = Sqlite.Database.open_v2(file_name, out db, OPEN_READWRITE | OPEN_CREATE | 0x00010000);
|
||||||
if (ec != Sqlite.OK) {
|
if (ec != Sqlite.OK) {
|
||||||
throw new DatabaseError.OPEN_ERROR(@"SQLite error: $(db.errcode()) - $(db.errmsg())");
|
error(@"SQLite error: %d - %s", db.errcode(), db.errmsg());
|
||||||
}
|
}
|
||||||
this.tables = tables;
|
this.tables = tables;
|
||||||
start_migration();
|
start_migration();
|
||||||
if (debug) db.trace((message) => print(@"Qlite trace: $message\n"));
|
if (debug) db.trace((message) => print(@"Qlite trace: $message\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ensure_init() throws DatabaseError {
|
public void ensure_init() {
|
||||||
if (tables == null) throw new DatabaseError.NOT_INITIALIZED(@"Database $file_name was not initialized, call init()");
|
if (tables == null) error(@"Database $file_name was not initialized, call init()");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void start_migration() throws DatabaseError {
|
private void start_migration() {
|
||||||
meta_table.create_table_at_version(expected_version);
|
meta_table.create_table_at_version(expected_version);
|
||||||
long old_version = 0;
|
long old_version = 0;
|
||||||
try {
|
|
||||||
old_version = meta_table.row_with(meta_name, "version")[meta_int_val, -1];
|
old_version = meta_table.row_with(meta_name, "version")[meta_int_val, -1];
|
||||||
} catch (DatabaseError e) {
|
|
||||||
old_version = -1;
|
|
||||||
}
|
|
||||||
if (old_version == -1) {
|
if (old_version == -1) {
|
||||||
foreach (Table t in tables) {
|
foreach (Table t in tables) {
|
||||||
t.create_table_at_version(expected_version);
|
t.create_table_at_version(expected_version);
|
||||||
|
@ -97,61 +82,61 @@ public class Database {
|
||||||
|
|
||||||
// To be implemented by actual implementation if required
|
// To be implemented by actual implementation if required
|
||||||
// new table columns are added, outdated columns are still present and will be removed afterwards
|
// new table columns are added, outdated columns are still present and will be removed afterwards
|
||||||
public virtual void migrate(long old_version) throws DatabaseError {
|
public virtual void migrate(long old_version) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryBuilder select(Column[]? columns = null) throws DatabaseError {
|
public QueryBuilder select(Column[]? columns = null) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
return new QueryBuilder(this).select(columns);
|
return new QueryBuilder(this).select(columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InsertBuilder insert() throws DatabaseError {
|
public InsertBuilder insert() {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
return new InsertBuilder(this);
|
return new InsertBuilder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateBuilder update(Table table) throws DatabaseError {
|
public UpdateBuilder update(Table table) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
return new UpdateBuilder(this, table);
|
return new UpdateBuilder(this, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpsertBuilder upsert(Table table) throws DatabaseError {
|
public UpsertBuilder upsert(Table table) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
return new UpsertBuilder(this, table);
|
return new UpsertBuilder(this, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateBuilder update_named(string table) throws DatabaseError {
|
public UpdateBuilder update_named(string table) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
return new UpdateBuilder.for_name(this, table);
|
return new UpdateBuilder.for_name(this, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteBuilder delete() throws DatabaseError {
|
public DeleteBuilder delete() {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
return new DeleteBuilder(this);
|
return new DeleteBuilder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RowIterator query_sql(string sql, string[]? args = null) throws DatabaseError {
|
public RowIterator query_sql(string sql, string[]? args = null) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
return new RowIterator(this, sql, args);
|
return new RowIterator(this, sql, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Statement prepare(string sql) throws DatabaseError {
|
internal Statement prepare(string sql) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
Sqlite.Statement statement;
|
Sqlite.Statement statement;
|
||||||
if (db.prepare_v2(sql, sql.length, out statement) != OK) {
|
if (db.prepare_v2(sql, sql.length, out statement) != OK) {
|
||||||
throw new DatabaseError.PREPARE_ERROR(@"SQLite error: $(db.errcode()) - $(db.errmsg())");
|
error("SQLite error: %d - %s", db.errcode(), db.errmsg());
|
||||||
}
|
}
|
||||||
return statement;
|
return statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exec(string sql) throws DatabaseError {
|
public void exec(string sql) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
if (db.exec(sql) != OK) {
|
if (db.exec(sql) != OK) {
|
||||||
throw new DatabaseError.EXEC_ERROR(@"SQLite error: $(db.errcode()) - $(db.errmsg())");
|
throw new Error(-1, 0, @"SQLite error: $(db.errcode()) - $(db.errmsg())");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool is_known_column(string table, string field) throws DatabaseError {
|
public bool is_known_column(string table, string field) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
foreach (Table t in tables) {
|
foreach (Table t in tables) {
|
||||||
if (t.is_known_column(field)) return true;
|
if (t.is_known_column(field)) return true;
|
||||||
|
|
|
@ -16,8 +16,8 @@ public class DeleteBuilder : StatementBuilder {
|
||||||
base(db);
|
base(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteBuilder from(Table table) throws DatabaseError {
|
public DeleteBuilder from(Table table) {
|
||||||
if (this.table != null) throw new DatabaseError.ILLEGAL_QUERY("cannot use from() multiple times.");
|
if (this.table != null) error("Qlite Error: ILLEGAL QUERY: cannot use from() multiple times.");
|
||||||
this.table = table;
|
this.table = table;
|
||||||
this.table_name = table.name;
|
this.table_name = table.name;
|
||||||
return this;
|
return this;
|
||||||
|
@ -28,8 +28,8 @@ public class DeleteBuilder : StatementBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteBuilder where(string selection, string[]? selection_args = null) throws DatabaseError {
|
public DeleteBuilder where(string selection, string[]? selection_args = null) {
|
||||||
if (this.selection != "1") throw new DatabaseError.ILLEGAL_QUERY("selection was already done, but where() was called.");
|
if (this.selection != "1") error("selection was already done, but where() was called.");
|
||||||
this.selection = selection;
|
this.selection = selection;
|
||||||
foreach (string arg in selection_args) {
|
foreach (string arg in selection_args) {
|
||||||
this.selection_args += new StatementBuilder.StringField(arg);
|
this.selection_args += new StatementBuilder.StringField(arg);
|
||||||
|
@ -43,7 +43,7 @@ public class DeleteBuilder : StatementBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override Statement prepare() throws DatabaseError {
|
internal override Statement prepare() {
|
||||||
Statement stmt = db.prepare(@"DELETE FROM $table_name WHERE $selection");
|
Statement stmt = db.prepare(@"DELETE FROM $table_name WHERE $selection");
|
||||||
for (int i = 0; i < selection_args.length; i++) {
|
for (int i = 0; i < selection_args.length; i++) {
|
||||||
selection_args[i].bind(stmt, i+1);
|
selection_args[i].bind(stmt, i+1);
|
||||||
|
@ -51,9 +51,9 @@ public class DeleteBuilder : StatementBuilder {
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void perform() throws DatabaseError {
|
public void perform() {
|
||||||
if (prepare().step() != DONE) {
|
if (prepare().step() != DONE) {
|
||||||
throw new DatabaseError.EXEC_ERROR(@"SQLite error: $(db.errcode()) - $(db.errmsg())");
|
error(@"SQLite error: %d - %s", db.errcode(), db.errmsg());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,13 +45,13 @@ public class InsertBuilder : StatementBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InsertBuilder value_null<T>(Column<T> column) throws DatabaseError {
|
public InsertBuilder value_null<T>(Column<T> column) {
|
||||||
if (column.not_null) throw new DatabaseError.ILLEGAL_QUERY(@"Can't set non-null column $(column.name) to null");
|
if (column.not_null) error("Qlite Error: ILLEGAL QUERY: Can't set non-null column %s to null", column.name);
|
||||||
fields += new NullField<T>(column);
|
fields += new NullField<T>(column);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override Statement prepare() throws DatabaseError {
|
internal override Statement prepare() {
|
||||||
string fields_text = "";
|
string fields_text = "";
|
||||||
string value_qs = "";
|
string value_qs = "";
|
||||||
for (int i = 0; i < fields.length; i++) {
|
for (int i = 0; i < fields.length; i++) {
|
||||||
|
@ -72,9 +72,9 @@ public class InsertBuilder : StatementBuilder {
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int64 perform() throws DatabaseError {
|
public int64 perform() {
|
||||||
if (prepare().step() != DONE) {
|
if (prepare().step() != DONE) {
|
||||||
throw new DatabaseError.EXEC_ERROR(@"SQLite error: $(db.errcode()) - $(db.errmsg())");
|
error(@"SQLite error: %d - %s", db.errcode(), db.errmsg());
|
||||||
}
|
}
|
||||||
return db.last_insert_rowid();
|
return db.last_insert_rowid();
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,8 @@ public class QueryBuilder : StatementBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryBuilder from(Table table) throws DatabaseError {
|
public QueryBuilder from(Table table) {
|
||||||
if (this.table_name != null) throw new DatabaseError.ILLEGAL_QUERY("cannot use from() multiple times.");
|
if (this.table_name != null) error("cannot use from() multiple times.");
|
||||||
this.table = table;
|
this.table = table;
|
||||||
this.table_name = table.name;
|
this.table_name = table.name;
|
||||||
return this;
|
return this;
|
||||||
|
@ -61,8 +61,8 @@ public class QueryBuilder : StatementBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryBuilder where(string selection, string[] selection_args = {}) throws DatabaseError {
|
public QueryBuilder where(string selection, string[] selection_args = {}) {
|
||||||
if (this.selection != "1") throw new DatabaseError.ILLEGAL_QUERY("selection was already done, but where() was called.");
|
if (this.selection != "1") error("selection was already done, but where() was called.");
|
||||||
this.selection = selection;
|
this.selection = selection;
|
||||||
foreach (string arg in selection_args) {
|
foreach (string arg in selection_args) {
|
||||||
this.selection_args += new StatementBuilder.StringField(arg);
|
this.selection_args += new StatementBuilder.StringField(arg);
|
||||||
|
@ -102,26 +102,26 @@ public class QueryBuilder : StatementBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int64 count() throws DatabaseError {
|
public int64 count() {
|
||||||
this.column_selector = @"COUNT($column_selector) AS count";
|
this.column_selector = @"COUNT($column_selector) AS count";
|
||||||
this.single_result = true;
|
this.single_result = true;
|
||||||
return row().get_integer("count");
|
return row().get_integer("count");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Row? row_() throws DatabaseError {
|
private Row? row_() {
|
||||||
if (!single_result) throw new DatabaseError.NON_UNIQUE("query is not suited to return a single row, but row() was called.");
|
if (!single_result) error("query is not suited to return a single row, but row() was called.");
|
||||||
return iterator().get_next();
|
return iterator().get_next();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RowOption row() throws DatabaseError {
|
public RowOption row() {
|
||||||
return new RowOption(row_());
|
return new RowOption(row_());
|
||||||
}
|
}
|
||||||
|
|
||||||
public T get<T>(Column<T> field) throws DatabaseError {
|
public T get<T>(Column<T> field) {
|
||||||
return row()[field];
|
return row()[field];
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override Statement prepare() throws DatabaseError {
|
internal override Statement prepare() {
|
||||||
Statement stmt = db.prepare(@"SELECT $column_selector $(table_name == null ? "" : @"FROM $((!) table_name)") WHERE $selection $(OrderingTerm.all_to_string(order_by_terms)) $(limit_val > 0 ? @" LIMIT $limit_val" : "")");
|
Statement stmt = db.prepare(@"SELECT $column_selector $(table_name == null ? "" : @"FROM $((!) table_name)") WHERE $selection $(OrderingTerm.all_to_string(order_by_terms)) $(limit_val > 0 ? @" LIMIT $limit_val" : "")");
|
||||||
for (int i = 0; i < selection_args.length; i++) {
|
for (int i = 0; i < selection_args.length; i++) {
|
||||||
selection_args[i].bind(stmt, i+1);
|
selection_args[i].bind(stmt, i+1);
|
||||||
|
@ -129,7 +129,7 @@ public class QueryBuilder : StatementBuilder {
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RowIterator iterator() throws DatabaseError {
|
public RowIterator iterator() {
|
||||||
return new RowIterator.from_query_builder(db, this);
|
return new RowIterator.from_query_builder(db, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,12 +56,12 @@ public class RowIterator {
|
||||||
private Database db;
|
private Database db;
|
||||||
private Statement stmt;
|
private Statement stmt;
|
||||||
|
|
||||||
public RowIterator.from_query_builder(Database db, QueryBuilder query) throws DatabaseError {
|
public RowIterator.from_query_builder(Database db, QueryBuilder query) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.stmt = query.prepare();
|
this.stmt = query.prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RowIterator(Database db, string sql, string[]? args = null) throws DatabaseError {
|
public RowIterator(Database db, string sql, string[]? args = null) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.stmt = db.prepare(sql);
|
this.stmt = db.prepare(sql);
|
||||||
if (args != null) {
|
if (args != null) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ public abstract class StatementBuilder {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract Statement prepare() throws DatabaseError;
|
internal abstract Statement prepare();
|
||||||
|
|
||||||
internal abstract class AbstractField<T> {
|
internal abstract class AbstractField<T> {
|
||||||
public T value;
|
public T value;
|
||||||
|
|
|
@ -49,42 +49,42 @@ public class Table {
|
||||||
add_post_statement(stmt);
|
add_post_statement(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensure_init() throws DatabaseError {
|
private void ensure_init() {
|
||||||
if (columns == null) throw new DatabaseError.NOT_INITIALIZED(@"Table $name was not initialized, call init()");
|
if (columns == null) error("Table %s was not initialized, call init()", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryBuilder select(Column[]? columns = null) throws DatabaseError {
|
public QueryBuilder select(Column[]? columns = null) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
return db.select(columns).from(this);
|
return db.select(columns).from(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InsertBuilder insert() throws DatabaseError {
|
public InsertBuilder insert() {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
return db.insert().into(this);
|
return db.insert().into(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateBuilder update() throws DatabaseError {
|
public UpdateBuilder update() {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
return db.update(this);
|
return db.update(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpsertBuilder upsert() throws DatabaseError {
|
public UpsertBuilder upsert() {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
return db.upsert(this);
|
return db.upsert(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteBuilder delete() throws DatabaseError {
|
public DeleteBuilder delete() {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
return db.delete().from(this);
|
return db.delete().from(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RowOption row_with<T>(Column<T> column, T value) throws DatabaseError {
|
public RowOption row_with<T>(Column<T> column, T value) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
if (!column.unique && !column.primary_key) throw new DatabaseError.NON_UNIQUE(@"$(column.name) is not suited to identify a row, but used with row_with()");
|
if (!column.unique && !column.primary_key) error("%s is not suited to identify a row, but used with row_with()", column.name);
|
||||||
return select().with(column, "=", value).row();
|
return select().with(column, "=", value).row();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool is_known_column(string column) throws DatabaseError {
|
public bool is_known_column(string column) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
foreach (Column c in columns) {
|
foreach (Column c in columns) {
|
||||||
if (c.name == column) return true;
|
if (c.name == column) return true;
|
||||||
|
@ -92,7 +92,7 @@ public class Table {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void create_table_at_version(long version) throws DatabaseError {
|
public void create_table_at_version(long version) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
string sql = @"CREATE TABLE IF NOT EXISTS $name (";
|
string sql = @"CREATE TABLE IF NOT EXISTS $name (";
|
||||||
for (int i = 0; i < columns.length; i++) {
|
for (int i = 0; i < columns.length; i++) {
|
||||||
|
@ -105,7 +105,7 @@ public class Table {
|
||||||
db.exec(sql);
|
db.exec(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add_columns_for_version(long old_version, long new_version) throws DatabaseError {
|
public void add_columns_for_version(long old_version, long new_version) {
|
||||||
ensure_init();
|
ensure_init();
|
||||||
foreach (Column c in columns) {
|
foreach (Column c in columns) {
|
||||||
if (c.min_version <= new_version && c.max_version >= new_version && c.min_version > old_version) {
|
if (c.min_version <= new_version && c.max_version >= new_version && c.min_version > old_version) {
|
||||||
|
@ -114,7 +114,7 @@ public class Table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete_columns_for_version(long old_version, long new_version) throws DatabaseError {
|
public void delete_columns_for_version(long old_version, long new_version) {
|
||||||
bool column_deletion_required = false;
|
bool column_deletion_required = false;
|
||||||
string column_list = "";
|
string column_list = "";
|
||||||
foreach (Column c in columns) {
|
foreach (Column c in columns) {
|
||||||
|
@ -137,7 +137,7 @@ public class Table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void post() throws DatabaseError {
|
internal void post() {
|
||||||
foreach (string stmt in post_statements) {
|
foreach (string stmt in post_statements) {
|
||||||
db.exec(stmt);
|
db.exec(stmt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,14 +39,14 @@ public class UpdateBuilder : StatementBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateBuilder set_null<T>(Column<T> column) throws DatabaseError {
|
public UpdateBuilder set_null<T>(Column<T> column) {
|
||||||
if (column.not_null) throw new DatabaseError.ILLEGAL_QUERY(@"Can't set non-null column $(column.name) to null");
|
if (column.not_null) error("Can't set non-null column %s to null", column.name);
|
||||||
fields += new NullField<T>(column);
|
fields += new NullField<T>(column);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateBuilder where(string selection, string[] selection_args = {}) throws DatabaseError {
|
public UpdateBuilder where(string selection, string[] selection_args = {}) {
|
||||||
if (this.selection != "1") throw new DatabaseError.ILLEGAL_QUERY("selection was already done, but where() was called.");
|
if (this.selection != "1") error("selection was already done, but where() was called.");
|
||||||
this.selection = selection;
|
this.selection = selection;
|
||||||
foreach (string arg in selection_args) {
|
foreach (string arg in selection_args) {
|
||||||
this.selection_args += new StatementBuilder.StringField(arg);
|
this.selection_args += new StatementBuilder.StringField(arg);
|
||||||
|
@ -70,7 +70,7 @@ public class UpdateBuilder : StatementBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override Statement prepare() throws DatabaseError {
|
internal override Statement prepare() {
|
||||||
string sql = "UPDATE";
|
string sql = "UPDATE";
|
||||||
if (or_val != null) sql += @" OR $((!)or_val)";
|
if (or_val != null) sql += @" OR $((!)or_val)";
|
||||||
sql += @" $table_name SET ";
|
sql += @" $table_name SET ";
|
||||||
|
@ -91,10 +91,10 @@ public class UpdateBuilder : StatementBuilder {
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void perform() throws DatabaseError {
|
public void perform() {
|
||||||
if (fields.length == 0) return;
|
if (fields.length == 0) return;
|
||||||
if (prepare().step() != DONE) {
|
if (prepare().step() != DONE) {
|
||||||
throw new DatabaseError.EXEC_ERROR(@"SQLite error: $(db.errcode()) - $(db.errmsg())");
|
error("SQLite error: %d - %s", db.errcode(), db.errmsg());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,14 +26,14 @@ public class UpsertBuilder : StatementBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpsertBuilder value_null<T>(Column<T> column) throws DatabaseError {
|
public UpsertBuilder value_null<T>(Column<T> column) {
|
||||||
if (column.not_null) throw new DatabaseError.ILLEGAL_QUERY(@"Can't set non-null column $(column.name) to null");
|
if (column.not_null) error("Can't set non-null column %s to null", column.name);
|
||||||
fields += new NullField<T>(column);
|
fields += new NullField<T>(column);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override Statement prepare() throws DatabaseError {
|
internal override Statement prepare() {
|
||||||
throw new DatabaseError.NOT_SUPPORTED("prepare() not available for upsert.");
|
error("prepare() not available for upsert.");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Statement prepare_update() {
|
internal Statement prepare_update() {
|
||||||
|
@ -98,9 +98,9 @@ public class UpsertBuilder : StatementBuilder {
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int64 perform() throws DatabaseError {
|
public int64 perform() {
|
||||||
if (prepare_update().step() != DONE || prepare_insert().step() != DONE) {
|
if (prepare_update().step() != DONE || prepare_insert().step() != DONE) {
|
||||||
throw new DatabaseError.EXEC_ERROR(@"SQLite error: $(db.errcode()) - $(db.errmsg())");
|
error(@"SQLite error: %d - %s", db.errcode(), db.errmsg());
|
||||||
}
|
}
|
||||||
return db.last_insert_rowid();
|
return db.last_insert_rowid();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue