diff options
author | Brendan Long <self@brendanlong.com> | 2017-10-29 03:42:51 +0300 |
---|---|---|
committer | Brendan Long <self@brendanlong.com> | 2017-10-29 05:00:27 +0300 |
commit | 364648271ead9a6d30f272d3cf4f734ca68bc830 (patch) | |
tree | abc1d1db8bbf63fea8c5ef301db06986e79ce3fb | |
parent | da3bef21eca0e57ad9a26a5a4017f9c4cf8b1ea1 (diff) |
Start on a simpler SQLite interface
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/DataBaseReadOnly.vala | 746 | ||||
-rw-r--r-- | src/DataBaseWriteAccess.vala | 269 | ||||
-rw-r--r-- | src/SQLite.vala | 153 |
4 files changed, 389 insertions, 780 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fae0670..5829988a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,6 +161,7 @@ vala_precompile(FEEDREADER ${FEEDREADER_NAME} src/Structs.vala src/Utils.vala src/QueryBuilder.vala + src/SQLite.vala src/ContentGrabber/grabberUtils.vala src/ContentGrabber/stringPair.vala src/Model/Feed.vala diff --git a/src/DataBaseReadOnly.vala b/src/DataBaseReadOnly.vala index 7a0b97d0..19fbaed0 100644 --- a/src/DataBaseReadOnly.vala +++ b/src/DataBaseReadOnly.vala @@ -15,289 +15,154 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { - protected Sqlite.Database sqlite_db; + protected SQLite m_db; - public DataBaseReadOnly(string dbFile = "feedreader-%01i.db".printf(Constants.DB_SCHEMA_VERSION)) + public DataBaseReadOnly(string db_file = "feedreader-%01i.db".printf(Constants.DB_SCHEMA_VERSION)) { Sqlite.config(Sqlite.Config.LOG, errorLogCallback); - string db_path = GLib.Environment.get_user_data_dir() + "/feedreader/data/"; - var path = GLib.File.new_for_path(db_path); - if(!path.query_exists()) - { - try - { - path.make_directory_with_parents(); - } - catch(GLib.Error e) - { - Logger.error("Can't create directory for database: %s".printf(e.message)); - } - } + string db_path = GLib.Environment.get_user_data_dir() + "/feedreader/data/" + db_file; - Logger.debug(@"Opening Database: $db_path$dbFile"); - int rc = Sqlite.Database.open_v2(db_path + dbFile, out sqlite_db); - if(rc != Sqlite.OK) - Logger.error("Can't open database: %d: %s".printf(sqlite_db.errcode(), sqlite_db.errmsg())); - - sqlite_db.busy_timeout(1000); - sqlite_db.update_hook(watchDog); + Logger.debug(@"Opening Database: $db_path"); + m_db = new SQLite(db_path); } - private void watchDog(Sqlite.Action action, string dbname, string table, int64 rowID) + private void errorLogCallback(int code, string msg) { - if(action == Sqlite.Action.DELETE && !table.has_prefix("fts_")) - { - Logger.warning("DELETING rowID: %s from table: %s and db: %s".printf(rowID.to_string(), table, dbname)); - } + Logger.error(@"dbErrorLog: $code: $msg"); } - private void errorLogCallback(int eCode, string msg) + // Generate enough placeholders for n parameters + private static string n_params(int n) { - Logger.error("dbErrorLog: " + eCode.to_string() + ": " + msg); + StringBuilder s = new StringBuilder.sized(n * 2 - 1); + for(int i = 0; i < n; ++i) + { + if(i != 0) + s.append(","); + s.append("?"); + } + return s.str; } public void init() { Logger.debug("init database"); - executeSQL("PRAGMA journal_mode = WAL"); - executeSQL("PRAGMA page_size = 4096"); - - executeSQL( """CREATE TABLE IF NOT EXISTS "main"."feeds" - ( - "feed_id" TEXT PRIMARY KEY NOT NULL UNIQUE, - "name" TEXT NOT NULL, - "url" TEXT NOT NULL, - "category_id" TEXT, - "subscribed" INTEGER DEFAULT 1, - "xmlURL" TEXT, - "iconURL" TEXT - )"""); - - executeSQL( """CREATE TABLE IF NOT EXISTS "main"."categories" - ( - "categorieID" TEXT PRIMARY KEY NOT NULL UNIQUE, - "title" TEXT NOT NULL, - "orderID" INTEGER, - "exists" INTEGER, - "Parent" TEXT, - "Level" INTEGER - )"""); - - executeSQL( """CREATE TABLE IF NOT EXISTS "main"."articles" - ( - "articleID" TEXT PRIMARY KEY NOT NULL UNIQUE, - "feedID" TEXT NOT NULL, - "title" TEXT NOT NULL, - "author" TEXT, - "url" TEXT NOT NULL, - "html" TEXT NOT NULL, - "preview" TEXT NOT NULL, - "unread" INTEGER NOT NULL, - "marked" INTEGER NOT NULL, - "tags" TEXT, - "date" INTEGER NOT NULL, - "guidHash" TEXT, - "lastModified" INTEGER, - "media" TEXT, - "contentFetched" INTEGER NOT NULL - )"""); - - executeSQL( """CREATE TABLE IF NOT EXISTS "main"."tags" - ( - "tagID" TEXT PRIMARY KEY NOT NULL UNIQUE, - "title" TEXT NOT NULL, - "exists" INTEGER, - "color" INTEGER - )"""); - - executeSQL( """CREATE TABLE IF NOT EXISTS "main"."CachedActions" - ( - "action" INTEGER NOT NULL, - "id" TEXT NOT NULL, - "argument" INTEGER - )"""); - - executeSQL( """CREATE INDEX IF NOT EXISTS "index_articles" ON "articles" ("feedID" DESC, "unread" ASC, "marked" ASC)"""); - executeSQL( """CREATE VIRTUAL TABLE IF NOT EXISTS fts_table USING fts4 (content='articles', articleID, preview, title, author)"""); - } - - protected void executeSQL(string sql, Sqlite.Callback? callback = null) - { - string errmsg; - int ec = sqlite_db.exec(sql, null, out errmsg); - if (ec != Sqlite.OK) - { - Logger.error(sql); - Logger.error(errmsg); - } + m_db.simple_query("PRAGMA journal_mode = WAL"); + m_db.simple_query("PRAGMA page_size = 4096"); + + m_db.simple_query(""" + CREATE TABLE IF NOT EXISTS "main"."feeds" + ( + "feed_id" TEXT PRIMARY KEY NOT NULL UNIQUE, + "name" TEXT NOT NULL, + "url" TEXT NOT NULL, + "category_id" TEXT, + "subscribed" INTEGER DEFAULT 1, + "xmlURL" TEXT, + "iconURL" TEXT + ) + """); + + m_db.simple_query(""" + CREATE TABLE IF NOT EXISTS "main"."categories" + ( + "categorieID" TEXT PRIMARY KEY NOT NULL UNIQUE, + "title" TEXT NOT NULL, + "orderID" INTEGER, + "exists" INTEGER, + "Parent" TEXT, + "Level" INTEGER + ) + """); + + m_db.simple_query(""" + CREATE TABLE IF NOT EXISTS "main"."articles" + ( + "articleID" TEXT PRIMARY KEY NOT NULL UNIQUE, + "feedID" TEXT NOT NULL, + "title" TEXT NOT NULL, + "author" TEXT, + "url" TEXT NOT NULL, + "html" TEXT NOT NULL, + "preview" TEXT NOT NULL, + "unread" INTEGER NOT NULL, + "marked" INTEGER NOT NULL, + "tags" TEXT, + "date" INTEGER NOT NULL, + "guidHash" TEXT, + "lastModified" INTEGER, + "media" TEXT, + "contentFetched" INTEGER NOT NULL + ) + """); + + m_db.simple_query(""" + CREATE TABLE IF NOT EXISTS "main"."tags" + ( + "tagID" TEXT PRIMARY KEY NOT NULL UNIQUE, + "title" TEXT NOT NULL, + "exists" INTEGER, + "color" INTEGER + ) + """); + + m_db.simple_query(""" + CREATE TABLE IF NOT EXISTS "main"."CachedActions" + ( + "action" INTEGER NOT NULL, + "id" TEXT NOT NULL, + "argument" INTEGER + ) + """); + + m_db.simple_query(""" + CREATE INDEX IF NOT EXISTS "index_articles" + ON "articles" ("feedID" DESC, "unread" ASC, "marked" ASC) + """); + m_db.simple_query(""" + CREATE VIRTUAL TABLE IF NOT EXISTS fts_table + USING fts4 (content='articles', articleID, preview, title, author) + """); } public bool uninitialized() { string query = "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='articles'"; - - int count = -1; - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query, query.length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query); - Logger.error(sqlite_db.errmsg()); - } - - while(stmt.step() == Sqlite.ROW) - { - count = stmt.column_int(0); - } - stmt.reset(); - - if(count == 0) - { - Logger.warning("database uninitialized"); - return true; - } - else if(count == 1) - { - Logger.debug("database already initialized"); - return false; - } - - return true; + var rows = m_db.execute(query); + assert(rows.size == 1 && rows[0].size == 1); + return (int)rows[0][0] == 0; } public bool isEmpty() { - if(!isTableEmpty("articles")) - { - return false; - } - - if(!isTableEmpty("categories")) - { - return false; - } - - if(!isTableEmpty("feeds")) - { - return false; - } - - if(!isTableEmpty("tags")) - { - return false; - } - - return true; + return isTableEmpty("articles") + && isTableEmpty("categories") + && isTableEmpty("feeds") + && isTableEmpty("tags"); } public bool isTableEmpty(string table) { - var query = new QueryBuilder(QueryType.SELECT, table); - query.selectField("count(*)"); - query.build(); - - int count = -1; - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } - - while(stmt.step() == Sqlite.ROW) - { - count = stmt.column_int(0); - } - stmt.reset(); - - if(count > 0) - { - Logger.debug(@"Table $table is not empty"); - return false; - } - else - { - Logger.debug(@"Table $table is empty"); - return true; - } - } - - public int getArticelCount() - { - int count = -1; - - var query = new QueryBuilder(QueryType.SELECT, "articles"); - query.selectField("count(*)"); - query.build(); - - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } - - int cols = stmt.column_count (); - while(stmt.step() == Sqlite.ROW) - { - for(int i = 0; i < cols; i++) - { - count = stmt.column_int(i); - } - } - stmt.reset(); - - return count; + var query = @"SELECT COUNT(*) FROM $table"; + var rows = m_db.execute(query); + assert(rows.size == 1 && rows[0].size == 1); + return (int)rows[0][0] == 0; } public uint get_unread_total() { - var query = new QueryBuilder(QueryType.SELECT, "articles"); - query.selectField("count(*)"); - query.addEqualsCondition("unread", ArticleStatus.UNREAD.to_string()); - query.build(); - - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } - - uint unread = 0; - while (stmt.step () == Sqlite.ROW) { - unread = stmt.column_int(0); - } - - stmt.reset (); - return unread; + var query = "SELECT COUNT(*) FROM articles WHERE unread = ?"; + var rows = m_db.execute(query, ArticleStatus.UNREAD.to_string()); + assert(rows.size == 1 && rows[0].size == 1); + return (int)rows[0][0]; } public uint get_marked_total() { - var query = new QueryBuilder(QueryType.SELECT, "articles"); - query.selectField("count(*)"); - query.addEqualsCondition("marked", ArticleStatus.MARKED.to_string()); - query.build(); - - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } - - uint marked = 0; - while (stmt.step () == Sqlite.ROW) { - marked = stmt.column_int(0); - } - - stmt.reset (); - return marked; + var query = "SELECT COUNT(*) FROM articles WHERE marked = ?"; + var rows = m_db.execute(query, ArticleStatus.MARKED.to_string()); + assert(rows.size == 1 && rows[0].size == 1); + return (int)rows[0][0]; } public uint get_unread_uncategorized() @@ -308,13 +173,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addCustomCondition(getUncategorizedFeedsQuery()); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); int unread = 0; while (stmt.step() == Sqlite.ROW) { @@ -332,13 +191,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addCustomCondition(getUncategorizedFeedsQuery()); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); int marked = 0; while (stmt.step() == Sqlite.ROW) { @@ -355,13 +208,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addCustomCondition("instr(tagID, \"global.\") = 0"); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); int tagCount = 0; while (stmt.step () == Sqlite.ROW) { @@ -374,102 +221,30 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { public bool tag_still_used(Tag tag) { - var query = new QueryBuilder(QueryType.SELECT, "main.articles"); - query.selectField("count(*)"); - query.addCustomCondition("instr(tags, \"%s\") > 0".printf(tag.getTagID())); - query.limit(2); - query.build(); - - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error("tag_still_used: " + sqlite_db.errmsg()); - } - - while (stmt.step () == Sqlite.ROW) { - if(stmt.column_int(0) > 1) - return true; - } - - return false; - } - - public string getFeedName(string feedID) - { - string result = _("unknown Feed"); - - if(feedID == "") - return result; - - var query = new QueryBuilder(QueryType.SELECT, "feeds"); - query.selectField("name"); - query.addEqualsCondition("feed_id", feedID, true, true); - query.build(); - - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } - - while(stmt.step() == Sqlite.ROW) - { - result = stmt.column_text(0); - } - - return result; + var query = "SELECT 1 FROM main.articles WHERE instr(tagID, ?) > 0 LIMIT 1"; + var rows = m_db.execute(query, tag.getTagID()); + return rows.size > 0; } - - public string? getTagName(string tagID) + public string? getTagName(string tag_id) { - var query = new QueryBuilder(QueryType.SELECT, "tags"); - query.selectField("title"); - query.addEqualsCondition("tagID", tagID, true, true); - query.build(); - - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } - - string result = null; - - while (stmt.step () == Sqlite.ROW) { - result = stmt.column_text(0); - } - - return result; + var query = "SELECT title FROM tags WHERE tagID = ?"; + var rows = m_db.execute(query, tag_id); + assert(rows.size == 0 || (rows.size == 1 && rows[0].size == 1)); + if(rows.size == 1) + return (string)rows[0][0]; + return _("Unknown tag"); } public int getLastModified() { - var query = new QueryBuilder(QueryType.SELECT, "articles"); - query.selectField("MAX(lastModified)"); - query.build(); - - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } - - int result = 0; - - while (stmt.step () == Sqlite.ROW) { - result = stmt.column_int(0); - } - - return result; + var query = "SELECT MAX(lastModified) FROM articles"; + var rows = m_db.execute(query); + assert(rows.size == 0 || (rows.size == 1 && rows[0].size == 1)); + if(rows.size == 1 && rows[0][0] != null) + return (int)rows[0][0]; + else + return 0; } @@ -483,13 +258,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addEqualsCondition("categorieID", catID, true, true); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); string result = ""; @@ -511,13 +280,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addEqualsCondition("title", catname, true, true); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); string? result = null; @@ -537,13 +300,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addEqualsCondition("preview", "", false, true); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); int result = 1; @@ -583,13 +340,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { } query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); var articles = new Gee.ArrayList<Article>(); while (stmt.step () == Sqlite.ROW) @@ -626,13 +377,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addRangeConditionString("articleID", ids); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); var articles = new Gee.HashMap<string, Article>(); @@ -656,13 +401,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addEqualsCondition("articleID", articleID, true, true); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while(stmt.step() == Sqlite.ROW) { @@ -696,14 +435,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.selectField("max(Level)"); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } - + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { maxCatLevel = stmt.column_int(0); } @@ -723,13 +455,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addCustomCondition(getUncategorizedQuery()); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { int count = stmt.column_int(0); @@ -746,14 +472,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.selectField("count(*)"); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } - + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { int count = stmt.column_int(0); @@ -768,13 +487,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { { int result = 0; string query = "SELECT EXISTS(SELECT 1 FROM articles WHERE articleID = \"" + articleID + "\" LIMIT 1)"; - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query, query.length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query); while (stmt.step () == Sqlite.ROW) { result = stmt.column_int(0); @@ -789,14 +502,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { { int result = 0; string query = "SELECT EXISTS(SELECT 1 FROM categories WHERE categorieID = \"" + catID + "\" LIMIT 1)"; - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query, query.length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query); - Logger.error(sqlite_db.errmsg()); - } - + Sqlite.Statement stmt = m_db.prepare(query); while (stmt.step () == Sqlite.ROW) { result = stmt.column_int(0); } @@ -816,13 +522,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addCustomCondition("date > \"%s\"".printf(date)); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { result = stmt.column_int(0); @@ -911,15 +611,8 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query2.orderBy(orderBy, desc); query2.build(); - query2.print(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query2.get(), query2.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query2.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query2.get()); while (stmt.step () == Sqlite.ROW) { result = stmt.column_int(0); @@ -928,7 +621,6 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { return result; } - public Gee.List<string> getFeedIDofCategorie(string categorieID) { var feedIDs = new Gee.ArrayList<string>(); @@ -937,13 +629,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.selectField("feed_id, category_id"); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step() == Sqlite.ROW) { string catString = stmt.column_text(1); @@ -996,13 +682,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addCustomCondition(getUncategorizedQuery()); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); string feedIDs = ""; while (stmt.step () == Sqlite.ROW) { @@ -1016,13 +696,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { public string getFeedIDofArticle(string articleID) { string query = "SELECT feedID FROM \"main\".\"articles\" WHERE \"articleID\" = " + "\"" + articleID + "\""; - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query, query.length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query); string id = ""; while (stmt.step () == Sqlite.ROW) { @@ -1041,13 +715,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addEqualsCondition("rowid", "%s".printf(getMaxID("articles", "rowid"))); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { result = stmt.column_text(0); @@ -1062,13 +730,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.selectField("max(%s)".printf(field)); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { @@ -1086,13 +748,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.limit(1); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error("feed_exists: " + sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { if(stmt.column_int(0) > 1) @@ -1109,13 +765,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addEqualsCondition("feed_id", feedID, true, true); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while(stmt.step () == Sqlite.ROW) { @@ -1146,13 +796,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { } query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { string feedID = stmt.column_text(0); @@ -1187,13 +831,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addEqualsCondition("feedID", feedID, true, true); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { count = (uint)stmt.column_int(0); @@ -1211,13 +849,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addEqualsCondition("feedID", feedID, true, true); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { count = (uint)stmt.column_int(0); @@ -1239,13 +871,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { } query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { string feedID = stmt.column_text(0); @@ -1269,13 +895,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addEqualsCondition("categorieID", catID, true, true); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { var tmpcategory = new Category( @@ -1303,13 +923,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addCustomCondition("instr(tagID, \"global.\") = 0"); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { tmpTag = new Tag(stmt.column_text(0), stmt.column_text(1), stmt.column_int(3)); @@ -1328,13 +942,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addEqualsCondition("tagID", tagID, true, true); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { tmpTag = new Tag(stmt.column_text(0), stmt.column_text(1), stmt.column_int(3)); @@ -1364,13 +972,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.selectField("count(*)"); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { count = stmt.column_int(0); @@ -1413,13 +1015,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while(stmt.step () == Sqlite.ROW) { @@ -1455,14 +1051,7 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.addEqualsCondition("contentFetched", "0", true, false); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } - + Sqlite.Statement stmt = m_db.prepare(query.get()); var tmp = new Gee.LinkedList<Article>(); while (stmt.step () == Sqlite.ROW) @@ -1574,17 +1163,8 @@ public class FeedReader.DataBaseReadOnly : GLib.Object { query.limit(limit); query.offset(offset); query.build(); - query.print(); - - - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); var tmp = new Gee.LinkedList<Article>(); while (stmt.step () == Sqlite.ROW) diff --git a/src/DataBaseWriteAccess.vala b/src/DataBaseWriteAccess.vala index 29d77d7e..c987a19c 100644 --- a/src/DataBaseWriteAccess.vala +++ b/src/DataBaseWriteAccess.vala @@ -41,28 +41,21 @@ public class FeedReader.DataBase : DataBaseReadOnly { public void checkpoint() { - sqlite_db.wal_checkpoint(""); + m_db.checkpoint(); } public bool resetDB() { Logger.warning("resetDB"); - executeSQL("DROP TABLE main.feeds"); - executeSQL("DROP TABLE main.categories"); - executeSQL("DROP TABLE main.articles"); - executeSQL("DROP TABLE main.tags"); - executeSQL("DROP TABLE main.fts_table"); - executeSQL("VACUUM"); + m_db.simple_query("DROP TABLE main.feeds"); + m_db.simple_query("DROP TABLE main.categories"); + m_db.simple_query("DROP TABLE main.articles"); + m_db.simple_query("DROP TABLE main.tags"); + m_db.simple_query("DROP TABLE main.fts_table"); + m_db.simple_query("VACUUM"); string query = "PRAGMA INTEGRITY_CHECK"; - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query, query.length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query); - Logger.error(sqlite_db.errmsg()); - } - + Sqlite.Statement stmt = m_db.prepare(query); int cols = stmt.column_count (); while (stmt.step () == Sqlite.ROW) { @@ -80,12 +73,12 @@ public class FeedReader.DataBase : DataBaseReadOnly { public void updateFTS() { - executeSQL("INSERT INTO fts_table(fts_table) VALUES('rebuild')"); + m_db.simple_query("INSERT INTO fts_table(fts_table) VALUES('rebuild')"); } public void springCleaning() { - executeSQL("VACUUM"); + m_db.simple_query("VACUUM"); var now = new DateTime.now_local(); Settings.state().set_int("last-spring-cleaning", (int)now.to_unix()); } @@ -103,16 +96,8 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.addCustomCondition(@"rowid BETWEEN 1 AND (SELECT rowid FROM articles ORDER BY rowid DESC LIMIT 1 OFFSET $syncCount)"); } query.build(); - query.print(); - - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while (stmt.step () == Sqlite.ROW) { delete_article(stmt.column_text(0), stmt.column_text(1)); } @@ -121,7 +106,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { private void delete_article(string articleID, string feedID) { Logger.info("Deleting article \"%s\"".printf(articleID)); - executeSQL("DELETE FROM main.articles WHERE articleID = \"" + articleID + "\""); + m_db.simple_query("DELETE FROM main.articles WHERE articleID = \"" + articleID + "\""); string folder_path = GLib.Environment.get_user_data_dir() + "/feedreader/data/images/%s/%s/".printf(feedID, articleID); Utils.remove_directory(folder_path); } @@ -130,7 +115,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { { var query = new QueryBuilder(QueryType.DELETE, "main.tags"); query.addEqualsCondition("tagID", tag.getTagID(), true, true); - executeSQL(query.build()); + m_db.simple_query(query.build()); query = new QueryBuilder(QueryType.SELECT, "main.articles"); query.selectField("tags"); @@ -138,13 +123,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.addCustomCondition("instr(tags, \"%s\") > 0".printf(tag.getTagID())); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while(stmt.step () == Sqlite.ROW) { @@ -156,13 +135,13 @@ public class FeedReader.DataBase : DataBaseReadOnly { query = new QueryBuilder(QueryType.UPDATE, "main.articles"); query.updateValuePair("tags", "\"%s\"".printf(StringUtils.join(tags, ","))); query.addEqualsCondition("articleID", articleID, true, true); - executeSQL(query.build()); + m_db.simple_query(query.build()); } } public void write_feeds(Gee.List<Feed> feeds) { - executeSQL("BEGIN TRANSACTION"); + m_db.simple_query("BEGIN TRANSACTION"); var query = new QueryBuilder(QueryType.INSERT_OR_REPLACE, "main.feeds"); query.insertValuePair("feed_id", "$FEEDID"); @@ -174,15 +153,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.insertValuePair("iconURL", "$ICONURL"); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error("DataBase: write_feeds - " + query.get()); - Logger.error(sqlite_db.errmsg()); - } - - + Sqlite.Statement stmt = m_db.prepare(query.get()); int feedID_pos = stmt.bind_parameter_index("$FEEDID"); int feedName_pos = stmt.bind_parameter_index("$FEEDNAME"); @@ -218,7 +189,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { stmt.reset(); } - executeSQL("COMMIT TRANSACTION"); + m_db.simple_query("COMMIT TRANSACTION"); } public void write_tag(Tag tag) @@ -230,7 +201,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { public void write_tags(Gee.List<Tag> tags) { - executeSQL("BEGIN TRANSACTION"); + m_db.simple_query("BEGIN TRANSACTION"); var query = new QueryBuilder(QueryType.INSERT_OR_IGNORE, "main.tags"); query.insertValuePair("tagID", "$TAGID"); @@ -239,13 +210,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.insertValuePair("color", "$COLOR"); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error("DataBase: write_tags - " + query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); int tagID_position = stmt.bind_parameter_index("$TAGID"); int label_position = stmt.bind_parameter_index("$LABEL"); @@ -265,7 +230,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { stmt.reset (); } - executeSQL("COMMIT TRANSACTION"); + m_db.simple_query("COMMIT TRANSACTION"); } public void update_tag(Tag tag) @@ -280,20 +245,20 @@ public class FeedReader.DataBase : DataBaseReadOnly { var query2 = new QueryBuilder(QueryType.UPDATE, "tags"); query2.updateValuePair("tagID", newID, true); query2.addEqualsCondition("tagID", tag.getTagID(), true, true); - executeSQL(query2.build()); + m_db.simple_query(query2.build()); query2.print(); var query3 = new QueryBuilder(QueryType.UPDATE, "articles"); query3.updateValuePair("tags", "replace(tags, '%s', '%s')".printf(tag.getTagID(), newID)); query3.addCustomCondition("instr(tags, '%s')".printf(tag.getTagID())); - executeSQL(query3.build()); + m_db.simple_query(query3.build()); query3.print(); } } public void update_tags(Gee.List<Tag> tags) { - executeSQL("BEGIN TRANSACTION"); + m_db.simple_query("BEGIN TRANSACTION"); var query = new QueryBuilder(QueryType.UPDATE, "main.tags"); query.updateValuePair("title", "$TITLE"); @@ -301,13 +266,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.addEqualsCondition("tagID", "$TAGID"); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error("DataBase: update_tags - " + query.get()); - Logger.error(sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); int title_position = stmt.bind_parameter_index("$TITLE"); int tagID_position = stmt.bind_parameter_index("$TAGID"); @@ -322,13 +281,13 @@ public class FeedReader.DataBase : DataBaseReadOnly { stmt.reset (); } - executeSQL("COMMIT TRANSACTION"); + m_db.simple_query("COMMIT TRANSACTION"); } public void write_categories(Gee.List<Category> categories) { - executeSQL("BEGIN TRANSACTION"); + m_db.simple_query("BEGIN TRANSACTION"); var query = new QueryBuilder(QueryType.INSERT_OR_REPLACE, "main.categories"); query.insertValuePair("categorieID", "$CATID"); @@ -339,14 +298,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.insertValuePair("Level", "$LEVEL"); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error("DataBase: write_categories - " + query.get()); - Logger.error(sqlite_db.errmsg()); - } - + Sqlite.Statement stmt = m_db.prepare(query.get()); int catID_position = stmt.bind_parameter_index("$CATID"); int feedName_position = stmt.bind_parameter_index("$FEEDNAME"); @@ -371,7 +323,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { stmt.reset (); } - executeSQL("COMMIT TRANSACTION"); + m_db.simple_query("COMMIT TRANSACTION"); } public void updateArticlesByID(Gee.List<string> ids, string field) @@ -382,10 +334,10 @@ public class FeedReader.DataBase : DataBaseReadOnly { reset_query.updateValuePair(field, ArticleStatus.READ.to_string()); else if(field == "marked") reset_query.updateValuePair(field, ArticleStatus.UNMARKED.to_string()); - executeSQL(reset_query.build()); + m_db.simple_query(reset_query.build()); - executeSQL("BEGIN TRANSACTION"); + m_db.simple_query("BEGIN TRANSACTION"); // then reapply states of the synced articles var update_query = new QueryBuilder(QueryType.UPDATE, "main.articles"); @@ -398,14 +350,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { update_query.addEqualsCondition("articleID", "$ARTICLEID"); update_query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (update_query.get(), update_query.get().length, out stmt); - - if (ec != Sqlite.OK) - { - Logger.error(update_query.get()); - Logger.error("updateArticlesByID: " + sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(update_query.get()); int articleID_position = stmt.bind_parameter_index("$ARTICLEID"); assert (articleID_position > 0); @@ -418,7 +363,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { stmt.reset(); } - executeSQL("COMMIT TRANSACTION"); + m_db.simple_query("COMMIT TRANSACTION"); } public void writeContent(Article article) @@ -430,14 +375,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { update_query.addEqualsCondition("articleID", article.getArticleID(), true, true); update_query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(update_query.get(), update_query.get().length, out stmt); - - if(ec != Sqlite.OK) - { - Logger.error(update_query.get()); - Logger.error("writeContent: " + sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(update_query.get()); int html_position = stmt.bind_parameter_index("$HTML"); int preview_position = stmt.bind_parameter_index("$PREVIEW"); @@ -459,17 +397,9 @@ public class FeedReader.DataBase : DataBaseReadOnly { update_articles(list); } - // public void update_article(Article article, string field, int field_value) - // { - // var query = new QueryBuilder(QueryType.UPDATE, "main.articles"); - // query.updateValuePair(field, field_value.to_string()); - // query.addEqualsCondition("articleID", article.getArticleID(), true, true); - // executeSQL(query.build()); - // } - public void update_articles(Gee.List<Article> articles) { - executeSQL("BEGIN TRANSACTION"); + m_db.simple_query("BEGIN TRANSACTION"); var update_query = new QueryBuilder(QueryType.UPDATE, "main.articles"); update_query.updateValuePair("unread", "$UNREAD"); @@ -479,14 +409,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { update_query.addEqualsCondition("articleID", "$ARTICLEID", true, false); update_query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(update_query.get(), update_query.get().length, out stmt); - - if(ec != Sqlite.OK) - { - Logger.error(update_query.get()); - Logger.error("update_articles: " + sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(update_query.get()); int unread_position = stmt.bind_parameter_index("$UNREAD"); int marked_position = stmt.bind_parameter_index("$MARKED"); @@ -521,7 +444,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { stmt.reset(); } - executeSQL("COMMIT TRANSACTION"); + m_db.simple_query("COMMIT TRANSACTION"); } @@ -530,7 +453,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { Utils.generatePreviews(articles); Utils.checkHTML(articles); - executeSQL("BEGIN TRANSACTION"); + m_db.simple_query("BEGIN TRANSACTION"); var query = new QueryBuilder(QueryType.INSERT_OR_IGNORE, "main.articles"); query.insertValuePair("articleID", "$ARTICLEID"); @@ -550,16 +473,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.insertValuePair("contentFetched", "0"); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error("write_articles: " + sqlite_db.errmsg()); - } - - + Sqlite.Statement stmt = m_db.prepare(query.get()); int articleID_position = stmt.bind_parameter_index("$ARTICLEID"); int feedID_position = stmt.bind_parameter_index("$FEEDID"); @@ -636,7 +550,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { stmt.reset(); } - executeSQL("COMMIT TRANSACTION"); + m_db.simple_query("COMMIT TRANSACTION"); } public void markCategorieRead(string catID) @@ -644,7 +558,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { var query = new QueryBuilder(QueryType.UPDATE, "main.articles"); query.updateValuePair("unread", ArticleStatus.READ.to_string()); query.addRangeConditionString("feedID", getFeedIDofCategorie(catID)); - executeSQL(query.build()); + m_db.simple_query(query.build()); } public void markFeedRead(string feedID) @@ -652,48 +566,48 @@ public class FeedReader.DataBase : DataBaseReadOnly { var query = new QueryBuilder(QueryType.UPDATE, "main.articles"); query.updateValuePair("unread", ArticleStatus.READ.to_string()); query.addEqualsCondition("feedID", feedID, true, true); - executeSQL(query.build()); + m_db.simple_query(query.build()); } public void markAllRead() { var query1 = new QueryBuilder(QueryType.UPDATE, "main.articles"); query1.updateValuePair("unread", ArticleStatus.READ.to_string()); - executeSQL(query1.build()); + m_db.simple_query(query1.build()); } public void reset_subscribed_flag() { - executeSQL("UPDATE main.feeds SET \"subscribed\" = 0"); + m_db.simple_query("UPDATE main.feeds SET \"subscribed\" = 0"); } public void reset_exists_tag() { - executeSQL("UPDATE main.tags SET \"exists\" = 0"); + m_db.simple_query("UPDATE main.tags SET \"exists\" = 0"); } public void reset_exists_flag() { - executeSQL("UPDATE main.categories SET \"exists\" = 0"); + m_db.simple_query("UPDATE main.categories SET \"exists\" = 0"); } public void delete_unsubscribed_feeds() { Logger.warning("DataBase: Deleting unsubscribed feeds"); - executeSQL("DELETE FROM main.feeds WHERE \"subscribed\" = 0"); + m_db.simple_query("DELETE FROM main.feeds WHERE \"subscribed\" = 0"); } public void delete_nonexisting_categories() { Logger.warning("DataBase: Deleting nonexisting categories"); - executeSQL("DELETE FROM main.categories WHERE \"exists\" = 0"); + m_db.simple_query("DELETE FROM main.categories WHERE \"exists\" = 0"); } public void delete_nonexisting_tags() { Logger.warning("DataBase: Deleting nonexisting tags"); - executeSQL("DELETE FROM main.tags WHERE \"exists\" = 0"); + m_db.simple_query("DELETE FROM main.tags WHERE \"exists\" = 0"); } public void delete_articles_without_feed() @@ -704,14 +618,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.addEqualsCondition("subscribed", "0", true, false); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error("DataBase: delete_articles_without_feed: %d: %s".printf(sqlite_db.errcode(), sqlite_db.errmsg())); - } - + Sqlite.Statement stmt = m_db.prepare(query.get()); while(stmt.step () == Sqlite.ROW) { delete_articles(stmt.column_text(0)); @@ -721,14 +628,14 @@ public class FeedReader.DataBase : DataBaseReadOnly { public void delete_articles(string feedID) { Logger.warning("DataBase: Deleting all articles of feed \"%s\"".printf(feedID)); - executeSQL("DELETE FROM main.articles WHERE feedID = \"" + feedID + "\""); + m_db.simple_query("DELETE FROM main.articles WHERE feedID = \"" + feedID + "\""); string folder_path = GLib.Environment.get_user_data_dir() + "/feedreader/data/images/%s/".printf(feedID); Utils.remove_directory(folder_path); } public void delete_category(string catID) { - executeSQL("DELETE FROM main.categories WHERE categorieID = \"" + catID + "\""); + m_db.simple_query("DELETE FROM main.categories WHERE categorieID = \"" + catID + "\""); if(FeedServer.get_default().supportMultiCategoriesPerFeed()) { @@ -737,29 +644,22 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.addCustomCondition("instr(category_id, \"%s\") > 0".printf(catID)); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error("delete_articles: " + sqlite_db.errmsg()); - } - + Sqlite.Statement stmt = m_db.prepare(query.get()); while(stmt.step () == Sqlite.ROW) { string feedID = stmt.column_text(0); string catIDs = stmt.column_text(0).replace(catID + ",", ""); - executeSQL("UPDATE main.feeds set category_id = \"" + catIDs + "\" WHERE feed_id = \"" + feedID + "\""); + m_db.simple_query("UPDATE main.feeds set category_id = \"" + catIDs + "\" WHERE feed_id = \"" + feedID + "\""); } } else { - executeSQL("UPDATE main.feeds set category_id = \"%s\" WHERE category_id = \"%s\"".printf(FeedServer.get_default().uncategorizedID(), catID)); + m_db.simple_query("UPDATE main.feeds set category_id = \"%s\" WHERE category_id = \"%s\"".printf(FeedServer.get_default().uncategorizedID(), catID)); if(FeedServer.get_default().supportMultiLevelCategories()) { - executeSQL("UPDATE main.categories set Parent = \"-2\" WHERE categorieID = \"" + catID + "\""); + m_db.simple_query("UPDATE main.categories set Parent = \"-2\" WHERE categorieID = \"" + catID + "\""); } } } @@ -774,29 +674,25 @@ public class FeedReader.DataBase : DataBaseReadOnly { var query2 = new QueryBuilder(QueryType.UPDATE, "categories"); query2.updateValuePair("categorieID", newID, true); query2.addEqualsCondition("categorieID", catID, true, true); - executeSQL(query2.build()); - query2.print(); + m_db.simple_query(query2.build()); var query3 = new QueryBuilder(QueryType.UPDATE, "feeds"); query3.updateValuePair("category_id", "replace(category_id, '%s', '%s')".printf(catID, newID)); query3.addCustomCondition("instr(category_id, '%s')".printf(catID)); - executeSQL(query3.build()); - query3.print(); + m_db.simple_query(query3.build()); var query = new QueryBuilder(QueryType.UPDATE, "categories"); query.updateValuePair("title", newName, true); query.addEqualsCondition("categorieID", newID, true, true); - executeSQL(query.build()); + m_db.simple_query(query.build()); } else { var query = new QueryBuilder(QueryType.UPDATE, "categories"); query.updateValuePair("title", newName, true); query.addEqualsCondition("categorieID", catID, true, true); - executeSQL(query.build()); + m_db.simple_query(query.build()); } - - } public void move_category(string catID, string newParentID) @@ -806,7 +702,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.updateValuePair("Parent", newParentID); query.updateValuePair("Level", "%i".printf(parent.getLevel()+1)); query.addEqualsCondition("categorieID", catID); - executeSQL(query.build()); + m_db.simple_query(query.build()); } public void rename_feed(string feedID, string newName) @@ -814,7 +710,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { var query = new QueryBuilder(QueryType.UPDATE, "feeds"); query.updateValuePair("name", newName, true); query.addEqualsCondition("feed_id", feedID, true, true); - executeSQL(query.build()); + m_db.simple_query(query.build()); } public void move_feed(string feedID, string currentCatID, string? newCatID = null) @@ -831,7 +727,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { var query = new QueryBuilder(QueryType.UPDATE, "feeds"); query.updateValuePair("category_id", catString, true); query.addEqualsCondition("feed_id", feedID, true, true); - executeSQL(query.build()); + m_db.simple_query(query.build()); } public void removeCatFromFeed(string feedID, string catID) @@ -840,18 +736,18 @@ public class FeedReader.DataBase : DataBaseReadOnly { var query = new QueryBuilder(QueryType.UPDATE, "feeds"); query.updateValuePair("category_id", feed.getCatString().replace(catID + ",", ""), true); query.addEqualsCondition("feed_id", feedID, true, true); - executeSQL(query.build()); + m_db.simple_query(query.build()); } public void delete_feed(string feedID) { - executeSQL("DELETE FROM feeds WHERE feed_id = \"%s\"".printf(feedID)); + m_db.simple_query("DELETE FROM feeds WHERE feed_id = \"%s\"".printf(feedID)); delete_articles(feedID); } public void addCachedAction(CachedActions action, string id, string? argument = "") { - executeSQL("BEGIN TRANSACTION"); + m_db.simple_query("BEGIN TRANSACTION"); var query = new QueryBuilder(QueryType.INSERT_OR_IGNORE, "main.CachedActions"); query.insertValuePair("action", "$ACTION"); @@ -859,14 +755,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.insertValuePair("argument", "$ARGUMENT"); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2 (query.get(), query.get().length, out stmt); - if (ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error("addCachedAction: " + sqlite_db.errmsg()); - } - + Sqlite.Statement stmt = m_db.prepare(query.get()); int action_position = stmt.bind_parameter_index("$ACTION"); int id_position = stmt.bind_parameter_index("$ID"); @@ -882,7 +771,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { while (stmt.step () == Sqlite.ROW) {} stmt.reset (); - executeSQL("COMMIT TRANSACTION"); + m_db.simple_query("COMMIT TRANSACTION"); } @@ -893,15 +782,8 @@ public class FeedReader.DataBase : DataBaseReadOnly { var query = new QueryBuilder(QueryType.SELECT, "CachedActions"); query.selectField("*"); query.build(); - query.print(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error(query.get()); - Logger.error("readCachedActions: " + sqlite_db.errmsg()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while(stmt.step () == Sqlite.ROW) { @@ -916,7 +798,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { public void resetCachedActions() { Logger.warning("resetCachedActions"); - executeSQL("DELETE FROM CachedActions"); + m_db.simple_query("DELETE FROM CachedActions"); } public bool cachedActionNecessary(CachedAction action) @@ -928,13 +810,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.addEqualsCondition("action", "%i".printf(action.opposite())); query.build(); - Sqlite.Statement stmt; - int ec = sqlite_db.prepare_v2(query.get(), query.get().length, out stmt); - if(ec != Sqlite.OK) - { - Logger.error("cachedActionNecessary - %s".printf(sqlite_db.errmsg())); - Logger.error(query.get()); - } + Sqlite.Statement stmt = m_db.prepare(query.get()); while(stmt.step () == Sqlite.ROW) { @@ -951,8 +827,7 @@ public class FeedReader.DataBase : DataBaseReadOnly { query.addEqualsCondition("argument", action.getArgument(), true, true); query.addEqualsCondition("id", action.getID(), true, true); query.addEqualsCondition("action", "%i".printf(action.opposite())); - executeSQL(query.build()); - query.print(); + m_db.simple_query(query.build()); } } diff --git a/src/SQLite.vala b/src/SQLite.vala new file mode 100644 index 00000000..2652a056 --- /dev/null +++ b/src/SQLite.vala @@ -0,0 +1,153 @@ +// This file is part of FeedReader. +// +// FeedReader is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// FeedReader is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with FeedReader. If not, see <http://www.gnu.org/licenses/>. + +public errordomain SQLiteError +{ + FAIL +} + +/* A wrapper around the low-level SQLite API */ +public class SQLite : GLib.Object { + private Sqlite.Database m_db; + + public SQLite(string db_path, int busy_timeout = 1000) + { + var path = GLib.File.new_for_path(db_path); + var parent = path.get_parent(); + if(!parent.query_exists()) + { + try + { + parent.make_directory_with_parents(); + } + catch(IOError.EXISTS e) + { + } + } + + int rc = Sqlite.Database.open_v2(db_path, out m_db); + if(rc != Sqlite.OK) + throw new SQLiteError.FAIL("Can't open database: %d: %s".printf(m_db.errcode(), m_db.errmsg())); + + m_db.busy_timeout(busy_timeout); + } + + // Backwards compatibility interface + public Sqlite.Statement prepare(string query) + { + Sqlite.Statement stmt; + int rc = m_db.prepare_v2(query, query.length, out stmt); + if(rc != Sqlite.OK) + throw new SQLiteError.FAIL("Can't prepare statement: %d: %s\nSQL is %s".printf(m_db.errcode(), m_db.errmsg(), query)); + return stmt; + } + + public string errmsg() + { + return m_db.errmsg(); + } + + public void checkpoint() + { + m_db.wal_checkpoint(""); + } + + public void simple_query(string query) + { + string errmsg; + int ec = m_db.exec(query, null, out errmsg); + if (ec != Sqlite.OK) + { + throw new SQLiteError.FAIL("Failed to execute simple query: %d: %s\nSQL is: %s".printf(ec, errmsg, query)); + } + } + + public Gee.List<Gee.List<Value?>> execute(string query, ...) + { + var l = va_list(); + Gee.List<string?> params = null; + while(true) + { + string? param = l.arg(); + if(param == null) + break; + if(params == null) + params = new Gee.ArrayList<string?>(); + params.add(param); + } + return executev(query, params); + } + + public Gee.List<Gee.List<Value?>> executev(string query, Gee.List<string?>? params = null) + { + Sqlite.Statement stmt; + int rc = m_db.prepare_v2(query, query.length, out stmt); + if (rc != Sqlite.OK) + { + throw new SQLiteError.FAIL("Can't prepare statement: %d: %s\nSQL is: %s".printf(m_db.errcode(), m_db.errmsg(), query)); + } + + if(params != null) + { + for(int i = 1; i < params.size; ++i) + { + var param = params[i]; + if(param == null) + stmt.bind_null(i); + else + stmt.bind_text(i, param); + } + } + + var rows = new Gee.ArrayList<Gee.List<Value?>>(); + while(stmt.step() == Sqlite.ROW) + { + var row = new Gee.ArrayList<Value?>(); + for(int i = 0; i < stmt.column_count(); ++i) + { + Value? value; + switch(stmt.column_type(i)) + { + case Sqlite.INTEGER: + value = Value(typeof(int)); + value.set_int(stmt.column_int(i)); + break; + case Sqlite.FLOAT: + value = Value(typeof(double)); + value.set_double(stmt.column_double(i)); + break; + case Sqlite.BLOB: + value = Value(typeof(void*)); + value.set_pointer(stmt.column_blob(i)); + break; + case Sqlite.NULL: + value = null; + break; + case Sqlite.TEXT: + value = Value(typeof(string)); + value.take_string(stmt.column_text(i)); + break; + default: + throw new SQLiteError.FAIL("Unknown column return type: %d".printf(stmt.column_type(i))); + } + row.add(value); + } + rows.add(row); + } + stmt.reset (); + + return rows; + } +} |