diff --git a/kernel/sql/database.go b/kernel/sql/database.go index ee79e1618..30f509ab4 100644 --- a/kernel/sql/database.go +++ b/kernel/sql/database.go @@ -102,12 +102,7 @@ func InitDatabase(forceRebuild bool) (err error) { // 不存在库或者版本不一致都会走到这里 closeDatabase() - if gulu.File.IsExist(util.DBPath) { - if err = removeDatabaseFile(); err != nil { - logging.LogErrorf("remove database file failed: %s", err) - err = nil - } - } + util.RemoveDatabaseFile(util.DBPath) initDBConnection() initDBTables() @@ -1486,13 +1481,14 @@ func prepareExecInsertTx(tx *sql.Tx, stmtSQL string, args []interface{}) (err er } if _, err = stmt.Exec(args...); err != nil { + tx.Rollback() + logging.LogErrorf("exec database stmt [%s] failed: %s\n %s", stmtSQL, err, logging.ShortStack()) + if strings.Contains(err.Error(), "database disk image is malformed") { - tx.Rollback() closeDatabase() - removeDatabaseFile() + util.RemoveDatabaseFile(util.DBPath) logging.LogFatalf(logging.ExitCodeUnavailableDatabase, "database disk image [%s] is malformed, please restart SiYuan kernel to rebuild it\n\t%s\n\t%v", util.DBPath, stmtSQL, args) } - logging.LogErrorf("exec database stmt [%s] failed: %s\n %s", stmtSQL, err, logging.ShortStack()) return } return @@ -1500,13 +1496,14 @@ func prepareExecInsertTx(tx *sql.Tx, stmtSQL string, args []interface{}) (err er func execStmtTx(tx *sql.Tx, stmt string, args ...interface{}) (err error) { if _, err = tx.Exec(stmt, args...); err != nil { + tx.Rollback() + logging.LogErrorf("exec database stmt [%s] failed: %s\n %s", stmt, err, logging.ShortStack()) + if strings.Contains(err.Error(), "database disk image is malformed") { - tx.Rollback() closeDatabase() - removeDatabaseFile() + util.RemoveDatabaseFile(util.DBPath) logging.LogFatalf(logging.ExitCodeUnavailableDatabase, "database disk image [%s] is malformed, please restart SiYuan kernel to rebuild it\n\t%s\n\t%v", util.DBPath, stmt, args) } - logging.LogErrorf("exec database stmt [%s] failed: %s\n %s", stmt, err, logging.ShortStack()) return } return @@ -1559,22 +1556,6 @@ func ialAttr(ial, name string) (ret string) { return } -func removeDatabaseFile() (err error) { - err = os.RemoveAll(util.DBPath) - if err != nil { - return - } - err = os.RemoveAll(util.DBPath + "-shm") - if err != nil { - return - } - err = os.RemoveAll(util.DBPath + "-wal") - if err != nil { - return - } - return -} - func closeDatabase() { if nil == db { return diff --git a/kernel/treenode/blocktree.go b/kernel/treenode/blocktree.go index 229d833e2..ffcac8d89 100644 --- a/kernel/treenode/blocktree.go +++ b/kernel/treenode/blocktree.go @@ -62,12 +62,7 @@ func initDatabase(forceRebuild bool) (err error) { } closeDatabase() - if gulu.File.IsExist(util.BlockTreeDBPath) { - if err = removeDatabaseFile(); err != nil { - logging.LogErrorf("remove database file [%s] failed: %s", util.BlockTreeDBPath, err) - err = nil - } - } + util.RemoveDatabaseFile(util.BlockTreeDBPath) initDBConnection() initDBTables() @@ -141,22 +136,6 @@ func closeDatabase() { return } -func removeDatabaseFile() (err error) { - err = os.RemoveAll(util.BlockTreeDBPath) - if err != nil { - return - } - err = os.RemoveAll(util.BlockTreeDBPath + "-shm") - if err != nil { - return - } - err = os.RemoveAll(util.BlockTreeDBPath + "-wal") - if err != nil { - return - } - return -} - func GetBlockTreesByType(typ string) (ret []*BlockTree) { sqlStmt := "SELECT * FROM blocktrees WHERE type = ?" rows, err := db.Query(sqlStmt, typ) @@ -643,7 +622,13 @@ func execInsertBlocktrees(tx *sql.Tx, tree *parse.Tree, changedNodes []*ast.Node stmt, err := tx.Prepare(sqlStmt) if err != nil { tx.Rollback() - logging.LogErrorf("prepare statement [%s] failed: %s", sqlStmt, err) + logging.LogErrorf("exec database stmt [%s] failed: %s\n %s", sqlStmt, err, logging.ShortStack()) + + if strings.Contains(err.Error(), "database disk image is malformed") { + closeDatabase() + util.RemoveDatabaseFile(util.BlockTreeDBPath) + logging.LogFatalf(logging.ExitCodeUnavailableDatabase, "database disk image [%s] is malformed, please restart SiYuan kernel to rebuild it\n\t%s", util.BlockTreeDBPath, err) + } return } defer stmt.Close() @@ -655,7 +640,13 @@ func execInsertBlocktrees(tx *sql.Tx, tree *parse.Tree, changedNodes []*ast.Node } if _, err = tx.Exec(sqlStmt, n.ID, tree.ID, parentID, tree.Box, tree.Path, tree.HPath, n.IALAttr("updated"), TypeAbbr(n.Type.String())); err != nil { tx.Rollback() - logging.LogErrorf("sql exec [%s] failed: %s", sqlStmt, err) + logging.LogErrorf("exec database stmt [%s] failed: %s\n %s", stmt, err, logging.ShortStack()) + + if strings.Contains(err.Error(), "database disk image is malformed") { + closeDatabase() + util.RemoveDatabaseFile(util.BlockTreeDBPath) + logging.LogFatalf(logging.ExitCodeUnavailableDatabase, "database disk image [%s] is malformed, please restart SiYuan kernel to rebuild it\n\t%s", util.BlockTreeDBPath, err) + } return } } diff --git a/kernel/util/working.go b/kernel/util/working.go index 192b0af6f..c1a76acb0 100644 --- a/kernel/util/working.go +++ b/kernel/util/working.go @@ -559,3 +559,30 @@ func LogDatabaseSize(dbPath string) { dbSize := humanize.BytesCustomCeil(uint64(dbFile.Size()), 2) logging.LogInfof("database [%s] size [%s]", dbPath, dbSize) } + +func RemoveDatabaseFile(dbPath string) { + if gulu.File.IsExist(dbPath) { + err := os.RemoveAll(dbPath) + if err != nil { + logging.LogFatalf(logging.ExitCodeUnavailableDatabase, "remove database file [%s] failed: %s", dbPath, err) + return + } + } + + if gulu.File.IsExist(dbPath + "-shm") { + err := os.RemoveAll(dbPath + "-shm") + if err != nil { + logging.LogFatalf(logging.ExitCodeUnavailableDatabase, "remove database file [%s] failed: %s", dbPath+"-shm", err) + return + } + } + + if gulu.File.IsExist(dbPath + "-wal") { + err := os.RemoveAll(dbPath + "-wal") + if err != nil { + logging.LogFatalf(logging.ExitCodeUnavailableDatabase, "remove database file [%s] failed: %s", dbPath+"-wal", err) + return + } + } + return +}