diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts index 38ad5b284..92393141b 100644 --- a/app/src/protyle/gutter/index.ts +++ b/app/src/protyle/gutter/index.ts @@ -16,7 +16,8 @@ import { isInHarmony, isMac, isOnlyMeta, - openByMobile, updateHotkeyAfterTip, + openByMobile, + updateHotkeyAfterTip, updateHotkeyTip, writeText } from "../util/compatibility"; @@ -829,7 +830,6 @@ export class Gutter { cb: (toPath) => { hintMoveBlock(toPath[0], selectsElement, protyle); }, - rootIDs: [protyle.block.rootID], flashcard: false }); } @@ -1430,7 +1430,6 @@ export class Gutter { hintMoveBlock(toPath[0], [nodeElement], protyle); }, flashcard: false, - rootIDs: [protyle.block.rootID], }); } }).element); diff --git a/kernel/go.mod b/kernel/go.mod index 633f84526..c33dd1151 100644 --- a/kernel/go.mod +++ b/kernel/go.mod @@ -8,7 +8,7 @@ require ( github.com/88250/epub v0.0.0-20230830085737-c19055cd1f48 github.com/88250/go-humanize v0.0.0-20240424102817-4f78fac47ea7 github.com/88250/gulu v1.2.3-0.20251208021445-f93f2666eaac - github.com/88250/lute v1.7.7-0.20251210093658-a1dde8c26225 + github.com/88250/lute v1.7.7-0.20251211025459-2369d8fec936 github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 github.com/ClarkThan/ahocorasick v0.0.0-20231011042242-30d1ef1347f4 github.com/ConradIrwin/font v0.2.1 diff --git a/kernel/go.sum b/kernel/go.sum index bc7946d03..395f001c0 100644 --- a/kernel/go.sum +++ b/kernel/go.sum @@ -14,8 +14,8 @@ github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950 h1:Pa5hMiBceT github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/88250/gulu v1.2.3-0.20251208021445-f93f2666eaac h1:EC80pY8zyR0gbL8ZLIBB4IPG/ia3ZHScrR/xt8zU8qU= github.com/88250/gulu v1.2.3-0.20251208021445-f93f2666eaac/go.mod h1:IQ5dXW9CjVmx6B7OfK1Y4ZBKTPMe9q1AkVoLGGzRbS8= -github.com/88250/lute v1.7.7-0.20251210093658-a1dde8c26225 h1:3fNwyxGGAqNZMybTrHXzcN//PF6Qvu0pwaRa8+borVY= -github.com/88250/lute v1.7.7-0.20251210093658-a1dde8c26225/go.mod h1:WYyUw//5yVw9BJnoVjx7rI/3szsISxNZCYGOqTIrV0o= +github.com/88250/lute v1.7.7-0.20251211025459-2369d8fec936 h1:biJKwd+Zku08gNg5QvXtVJPoVa0nS//77QQcsui5CmY= +github.com/88250/lute v1.7.7-0.20251211025459-2369d8fec936/go.mod h1:WYyUw//5yVw9BJnoVjx7rI/3szsISxNZCYGOqTIrV0o= github.com/88250/pdfcpu v0.3.14-0.20250424122812-f10e8d9d8d46 h1:Bq1JsDfVbHKUxNL/B2JXd8cC/1h6aFjrlXpGycnh0Hk= github.com/88250/pdfcpu v0.3.14-0.20250424122812-f10e8d9d8d46/go.mod h1:fVfOloBzs2+W2VJCCbq60XIxc3yJHAZ0Gahv1oO0gyI= github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 h1:48T899JQDwyyRu9yXHePYlPdHtpJfrJEUGBMH3SMBWY= diff --git a/kernel/sql/database.go b/kernel/sql/database.go index dc706a2bd..dad061965 100644 --- a/kernel/sql/database.go +++ b/kernel/sql/database.go @@ -1358,6 +1358,8 @@ func commitTx(tx *sql.Tx) (err error) { if err = tx.Commit(); err != nil { logging.LogErrorf("commit tx failed: %s\n %s", err, logging.ShortStack()) } + + closeTxPreparedStmts(tx) return } @@ -1380,6 +1382,8 @@ func commitHistoryTx(tx *sql.Tx) (err error) { if err = tx.Commit(); err != nil { logging.LogErrorf("commit tx failed: %s\n %s", err, logging.ShortStack()) } + + closeTxPreparedStmts(tx) return } @@ -1402,16 +1406,80 @@ func commitAssetContentTx(tx *sql.Tx) (err error) { if err = tx.Commit(); err != nil { logging.LogErrorf("commit tx failed: %s\n %s", err, logging.ShortStack()) } + + closeTxPreparedStmts(tx) return } -func prepareExecInsertTx(tx *sql.Tx, stmtSQL string, args []interface{}) (err error) { - stmt, err := tx.Prepare(stmtSQL) - if err != nil { +func closeTxPreparedStmts(tx *sql.Tx) { + if tx == nil { return } + cacheKey := txCacheKey(tx) + + txStmtCacheLock.Lock() + stmtMap, ok := txStmtCache[cacheKey] + if ok { + delete(txStmtCache, cacheKey) + } + txStmtCacheLock.Unlock() + + if !ok { + return + } + for _, stmt := range stmtMap { + _ = stmt.Close() + } +} + +var ( + txStmtCache = make(map[string]map[string]*sql.Stmt) + txStmtCacheLock = sync.Mutex{} +) + +func txCacheKey(tx *sql.Tx) string { + return fmt.Sprintf("%p", tx) +} + +func prepareExecInsertTx(tx *sql.Tx, stmtSQL string, args []interface{}) (err error) { + if tx == nil { + return fmt.Errorf("tx is nil") + } + + cacheKey := txCacheKey(tx) + + txStmtCacheLock.Lock() + stmtMap, ok := txStmtCache[cacheKey] + if !ok { + stmtMap = make(map[string]*sql.Stmt) + txStmtCache[cacheKey] = stmtMap + } + stmt, ok := stmtMap[stmtSQL] + txStmtCacheLock.Unlock() + + if !ok { + stmt, err = tx.Prepare(stmtSQL) + if err != nil { + return + } + txStmtCacheLock.Lock() + if existing, exists := txStmtCache[cacheKey][stmtSQL]; exists { + stmt.Close() + stmt = existing + } else { + txStmtCache[cacheKey][stmtSQL] = stmt + } + txStmtCacheLock.Unlock() + } + if _, err = stmt.Exec(args...); err != nil { - logging.LogErrorf("exec database stmt [%s] failed: %s", stmtSQL, err) + if strings.Contains(err.Error(), "database disk image is malformed") { + tx.Rollback() + closeDatabase() + removeDatabaseFile() + logging.LogFatalf(logging.ExitCodeReadOnlyDatabase, "database disk image [%s] is malformed, please restart SiYuan kernel to rebuild it", util.DBPath) + } + logging.LogErrorf("exec database stmt [%s] failed: %s\n %s", stmtSQL, err, logging.ShortStack()) return } return