fix: delete sqlite db when prepare failed

resolved #7467
pull/9222/head
Tienson Qin 2023-04-26 15:18:18 +08:00
parent ac44c245a6
commit 44b373159e
1 changed files with 49 additions and 49 deletions

View File

@ -28,14 +28,21 @@
[repo]
(get @databases (sanitize-db-name repo)))
(declare delete-db!)
(defn prepare
[^object db sql]
[db-name ^object db sql]
(when db
(.prepare db sql)))
(try
(.prepare db sql)
(catch :default e
;; case 1: vtable constructor failed: blocks_fts https://github.com/logseq/logseq/issues/7467
(delete-db! db-name)
(throw e)))))
(defn add-blocks-fts-triggers!
"Table bindings of blocks tables and the blocks FTS virtual tables"
[db]
[db db-name]
(let [triggers [;; add
"CREATE TRIGGER IF NOT EXISTS blocks_ad AFTER DELETE ON blocks
BEGIN
@ -55,12 +62,12 @@
VALUES (new.id, new.uuid, new.content, new.page);
END;"]]
(doseq [trigger triggers]
(let [stmt (prepare db trigger)]
(let [stmt (prepare db-name db trigger)]
(.run ^object stmt)))))
(defn add-pages-fts-triggers!
"Table bindings of pages tables and the pages FTS virtual tables"
[db]
[db db-name]
(let [triggers [;; add
"CREATE TRIGGER IF NOT EXISTS pages_ad AFTER DELETE ON pages
BEGIN
@ -80,12 +87,12 @@
VALUES (new.id, new.uuid, new.content);
END;"]]
(doseq [trigger triggers]
(let [stmt (prepare db trigger)]
(let [stmt (prepare db-name db trigger)]
(.run ^object stmt)))))
(defn create-blocks-table!
[db]
(let [stmt (prepare db "CREATE TABLE IF NOT EXISTS blocks (
[db db-name]
(let [stmt (prepare db-name db "CREATE TABLE IF NOT EXISTS blocks (
id INTEGER PRIMARY KEY,
uuid TEXT NOT NULL,
content TEXT NOT NULL,
@ -93,21 +100,21 @@
(.run ^object stmt)))
(defn create-blocks-fts-table!
[db]
(let [stmt (prepare db "CREATE VIRTUAL TABLE IF NOT EXISTS blocks_fts USING fts5(uuid, content, page)")]
[db db-name]
(let [stmt (prepare db-name db "CREATE VIRTUAL TABLE IF NOT EXISTS blocks_fts USING fts5(uuid, content, page)")]
(.run ^object stmt)))
(defn create-pages-table!
[db]
(let [stmt (prepare db "CREATE TABLE IF NOT EXISTS pages (
[db db-name]
(let [stmt (prepare db-name db "CREATE TABLE IF NOT EXISTS pages (
id INTEGER PRIMARY KEY,
uuid TEXT NOT NULL,
content TEXT NOT NULL)")]
(.run ^object stmt)))
(defn create-pages-fts-table!
[db]
(let [stmt (prepare db "CREATE VIRTUAL TABLE IF NOT EXISTS pages_fts USING fts5(uuid, content)")]
[db db-name]
(let [stmt (prepare db-name db "CREATE VIRTUAL TABLE IF NOT EXISTS pages_fts USING fts5(uuid, content)")]
(.run ^object stmt)))
(defn get-search-dir
@ -136,12 +143,12 @@
[db-name]
(let [[db-sanitized-name db-full-path] (get-db-full-path db-name)]
(try (let [db (sqlite3 db-full-path nil)]
(create-blocks-table! db)
(create-blocks-fts-table! db)
(create-pages-table! db)
(create-pages-fts-table! db)
(add-blocks-fts-triggers! db)
(add-pages-fts-triggers! db)
(create-blocks-table! db db-name)
(create-blocks-fts-table! db db-name)
(create-pages-table! db db-name)
(create-pages-fts-table! db db-name)
(add-blocks-fts-triggers! db db-name)
(add-pages-fts-triggers! db db-name)
(swap! databases assoc db-sanitized-name db))
(catch :default e
(logger/error (str e ": " db-name))
@ -170,7 +177,7 @@
(if-let [db (get-db repo)]
;; TODO: what if a CONFLICT on uuid
;; Should update all values on id conflict
(let [insert (prepare db "INSERT INTO pages (id, uuid, content) VALUES (@id, @uuid, @content) ON CONFLICT (id) DO UPDATE SET (uuid, content) = (@uuid, @content)")
(let [insert (prepare repo db "INSERT INTO pages (id, uuid, content) VALUES (@id, @uuid, @content) ON CONFLICT (id) DO UPDATE SET (uuid, content) = (@uuid, @content)")
insert-many (.transaction ^object db
(fn [pages]
(doseq [page pages]
@ -184,7 +191,7 @@
[repo ids]
(when-let [db (get-db repo)]
(let [sql (str "DELETE from pages WHERE id IN " (clj-list->sql ids))
stmt (prepare db sql)]
stmt (prepare repo db sql)]
(.run ^object stmt))))
(defn upsert-blocks!
@ -192,7 +199,7 @@
(if-let [db (get-db repo)]
;; TODO: what if a CONFLICT on uuid
;; Should update all values on id conflict
(let [insert (prepare db "INSERT INTO blocks (id, uuid, content, page) VALUES (@id, @uuid, @content, @page) ON CONFLICT (id) DO UPDATE SET (uuid, content, page) = (@uuid, @content, @page)")
(let [insert (prepare repo db "INSERT INTO blocks (id, uuid, content, page) VALUES (@id, @uuid, @content, @page) ON CONFLICT (id) DO UPDATE SET (uuid, content, page) = (@uuid, @content, @page)")
insert-many (.transaction ^object db
(fn [blocks]
(doseq [block blocks]
@ -206,20 +213,13 @@
[repo ids]
(when-let [db (get-db repo)]
(let [sql (str "DELETE from blocks WHERE id IN " (clj-list->sql ids))
stmt (prepare db sql)]
stmt (prepare repo db sql)]
(.run ^object stmt))))
;; (defn search-blocks-fts
;; [q]
;; (when-not (string/blank? q)
;; (let [stmt (prepare @database
;; "select id, uuid, content from blocks_fts where content match ? ORDER BY rank")]
;; (js->clj (.all ^object stmt q) :keywordize-keys true))))
(defn- search-blocks-aux
[database sql input page limit]
[repo database sql input page limit]
(try
(let [stmt (prepare database sql)]
(let [stmt (prepare repo database sql)]
(js->clj
(if page
(.all ^object stmt (int page) input limit)
@ -264,12 +264,12 @@
matched-result (->>
(map
(fn [match-input]
(search-blocks-aux database match-sql match-input page limit))
(search-blocks-aux repo database match-sql match-input page limit))
match-inputs)
(apply concat))]
(->>
(concat matched-result
(search-blocks-aux database non-match-sql non-match-input page limit))
(search-blocks-aux repo database non-match-sql non-match-input page limit))
(distinct-by :rowid)
(take limit)
(vec))))))
@ -299,8 +299,8 @@
snippet)}))
(defn- search-pages-aux
[database sql input limit]
(let [stmt (prepare database sql)]
[repo database sql input limit]
(let [stmt (prepare repo database sql)]
(try
(doall
(map search-pages-res-unpack (-> (.raw ^object stmt)
@ -329,12 +329,12 @@
matched-result (->>
(map
(fn [match-input]
(search-pages-aux database match-sql match-input limit))
(search-pages-aux repo database match-sql match-input limit))
match-inputs)
(apply concat))]
(->>
(concat matched-result
(search-pages-aux database non-match-sql non-match-input limit))
(search-pages-aux repo database non-match-sql non-match-input limit))
(distinct-by :id)
(take limit)
(vec))))))
@ -342,23 +342,29 @@
(defn truncate-blocks-table!
[repo]
(when-let [database (get-db repo)]
(let [stmt (prepare database
(let [stmt (prepare repo database
"delete from blocks;")
_ (.run ^object stmt)
stmt (prepare database
stmt (prepare repo database
"delete from blocks_fts;")]
(.run ^object stmt))))
(defn truncate-pages-table!
[repo]
(when-let [database (get-db repo)]
(let [stmt (prepare database
(let [stmt (prepare repo database
"delete from pages;")
_ (.run ^object stmt)
stmt (prepare database
stmt (prepare repo database
"delete from pages_fts;")]
(.run ^object stmt))))
(defn query
[repo sql]
(when-let [database (get-db repo)]
(let [stmt (prepare repo database sql)]
(.all ^object stmt))))
(defn delete-db!
[repo]
(when-let [database (get-db repo)]
@ -367,9 +373,3 @@
(logger/info "Delete search indice: " db-full-path)
(fs/unlinkSync db-full-path)
(swap! databases dissoc db-name))))
(defn query
[repo sql]
(when-let [database (get-db repo)]
(let [stmt (prepare database sql)]
(.all ^object stmt))))