A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
1// SiYuan - Refactor your thinking
2// Copyright (c) 2020-present, b3log.org
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Affero General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Affero General Public License for more details.
13//
14// You should have received a copy of the GNU Affero General Public License
15// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17package treenode
18
19import (
20 "github.com/88250/gulu"
21 "github.com/siyuan-note/logging"
22)
23
24func ClearRedundantBlockTrees(boxID string, paths []string) {
25 redundantPaths := getRedundantPaths(boxID, paths)
26 for _, p := range redundantPaths {
27 removeBlockTreesByPath(boxID, p)
28 }
29}
30
31func getRedundantPaths(boxID string, paths []string) (ret []string) {
32 pathsMap := map[string]bool{}
33 for _, path := range paths {
34 pathsMap[path] = true
35 }
36
37 btPathsMap := map[string]bool{}
38 sqlStmt := "SELECT path FROM blocktrees WHERE box_id = ?"
39 rows, err := db.Query(sqlStmt, boxID)
40 if err != nil {
41 logging.LogErrorf("query block tree failed: %s", err)
42 return
43 }
44 defer rows.Close()
45 for rows.Next() {
46 var path string
47 if err = rows.Scan(&path); err != nil {
48 logging.LogErrorf("scan block tree failed: %s", err)
49 return
50 }
51 btPathsMap[path] = true
52 }
53
54 for p, _ := range btPathsMap {
55 if !pathsMap[p] {
56 ret = append(ret, p)
57 }
58 }
59 ret = gulu.Str.RemoveDuplicatedElem(ret)
60 return
61}
62
63func removeBlockTreesByPath(boxID, path string) {
64 sqlStmt := "DELETE FROM blocktrees WHERE box_id = ? AND path = ?"
65 _, err := db.Exec(sqlStmt, boxID, path)
66 if err != nil {
67 logging.LogErrorf("delete block tree failed: %s", err)
68 }
69}
70
71func GetNotExistPaths(boxID string, paths []string) (ret []string) {
72 pathsMap := map[string]bool{}
73 for _, path := range paths {
74 pathsMap[path] = true
75 }
76
77 btPathsMap := map[string]bool{}
78 sqlStmt := "SELECT path FROM blocktrees WHERE box_id = ?"
79 rows, err := db.Query(sqlStmt, boxID)
80 if err != nil {
81 logging.LogErrorf("query block tree failed: %s", err)
82 return
83 }
84 defer rows.Close()
85 for rows.Next() {
86 var path string
87 if err = rows.Scan(&path); err != nil {
88 logging.LogErrorf("scan block tree failed: %s", err)
89 return
90 }
91 btPathsMap[path] = true
92 }
93
94 for p, _ := range pathsMap {
95 if !btPathsMap[p] {
96 ret = append(ret, p)
97 }
98 }
99 ret = gulu.Str.RemoveDuplicatedElem(ret)
100 return
101}
102
103func GetRootUpdated() (ret map[string]string) {
104 ret = map[string]string{}
105 sqlStmt := "SELECT root_id, updated FROM blocktrees WHERE root_id = id AND type = 'd'"
106 rows, err := db.Query(sqlStmt)
107 if err != nil {
108 logging.LogErrorf("query block tree failed: %s", err)
109 return
110 }
111 defer rows.Close()
112 for rows.Next() {
113 var rootID, updated string
114 if err = rows.Scan(&rootID, &updated); err != nil {
115 logging.LogErrorf("scan block tree failed: %s", err)
116 return
117 }
118 ret[rootID] = updated
119 }
120 return
121}