🎨 Add Rollup column to database table view https://github.com/siyuan-note/siyuan/issues/9958

This commit is contained in:
Daniel 2023-12-31 10:30:39 +08:00
parent 89158e77e2
commit 2d6900eafa
No known key found for this signature in database
GPG key ID: 86211BA83DF03017
2 changed files with 165 additions and 35 deletions

102
kernel/av/relation.go Normal file
View file

@ -0,0 +1,102 @@
package av
import (
"os"
"path/filepath"
"sync"
"github.com/88250/gulu"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/util"
"github.com/vmihailenco/msgpack/v5"
)
var (
attributeViewRelationsLock = sync.Mutex{}
)
func RemoveAvRel(avID, destAvID string) {
attributeViewRelationsLock.Lock()
defer attributeViewRelationsLock.Unlock()
relations := filepath.Join(util.DataDir, "storage", "av", "relations.msgpack")
if !filelock.IsExist(relations) {
return
}
data, err := filelock.ReadFile(relations)
if nil != err {
logging.LogErrorf("read attribute view relations failed: %s", err)
return
}
avRels := map[string][]string{}
if err = msgpack.Unmarshal(data, &avRels); nil != err {
logging.LogErrorf("unmarshal attribute view relations failed: %s", err)
return
}
destAvIDs := avRels[avID]
if nil == destAvIDs {
return
}
var newAvIDs []string
for _, v := range destAvIDs {
if v != destAvID {
newAvIDs = append(newAvIDs, v)
}
}
avRels[avID] = newAvIDs
data, err = msgpack.Marshal(avRels)
if nil != err {
logging.LogErrorf("marshal attribute view relations failed: %s", err)
return
}
if err = filelock.WriteFile(relations, data); nil != err {
logging.LogErrorf("write attribute view relations failed: %s", err)
return
}
}
func UpsertAvRel(avID, destAvID string) {
attributeViewRelationsLock.Lock()
defer attributeViewRelationsLock.Unlock()
avRelations := map[string][]string{}
relations := filepath.Join(util.DataDir, "storage", "av", "relations.msgpack")
if !filelock.IsExist(relations) {
if err := os.MkdirAll(filepath.Dir(relations), 0755); nil != err {
logging.LogErrorf("create attribute view dir failed: %s", err)
return
}
} else {
data, err := filelock.ReadFile(relations)
if nil != err {
logging.LogErrorf("read attribute view relations failed: %s", err)
return
}
if err = msgpack.Unmarshal(data, &avRelations); nil != err {
logging.LogErrorf("unmarshal attribute view relations failed: %s", err)
return
}
}
destAvIDs := avRelations[avID]
destAvIDs = append(destAvIDs, destAvID)
destAvIDs = gulu.Str.RemoveDuplicatedElem(destAvIDs)
avRelations[avID] = destAvIDs
data, err := msgpack.Marshal(avRelations)
if nil != err {
logging.LogErrorf("marshal attribute view relations failed: %s", err)
return
}
if err = filelock.WriteFile(relations, data); nil != err {
logging.LogErrorf("write attribute view relations failed: %s", err)
return
}
}

View file

@ -980,27 +980,31 @@ func updateAttributeViewColRelation(operation *Operation) (err error) {
srcRel := keyValues.Key.Relation
// 已经设置过双向关联的话需要先断开双向关联
if nil != srcRel && srcRel.IsTwoWay {
oldDestAv, _ := av.ParseAttributeView(srcRel.AvID)
if nil != oldDestAv {
isOldSameAv := oldDestAv.ID == destAv.ID
if isOldSameAv {
oldDestAv = destAv
}
if nil != srcRel {
if srcRel.IsTwoWay {
oldDestAv, _ := av.ParseAttributeView(srcRel.AvID)
if nil != oldDestAv {
isOldSameAv := oldDestAv.ID == destAv.ID
if isOldSameAv {
oldDestAv = destAv
}
oldDestKey, _ := oldDestAv.GetKey(srcRel.BackKeyID)
if nil != oldDestKey && nil != oldDestKey.Relation && oldDestKey.Relation.AvID == srcAv.ID && oldDestKey.Relation.IsTwoWay {
oldDestKey.Relation.IsTwoWay = false
oldDestKey.Relation.BackKeyID = ""
}
oldDestKey, _ := oldDestAv.GetKey(srcRel.BackKeyID)
if nil != oldDestKey && nil != oldDestKey.Relation && oldDestKey.Relation.AvID == srcAv.ID && oldDestKey.Relation.IsTwoWay {
oldDestKey.Relation.IsTwoWay = false
oldDestKey.Relation.BackKeyID = ""
}
if !isOldSameAv {
err = av.SaveAttributeView(oldDestAv)
if nil != err {
return
if !isOldSameAv {
err = av.SaveAttributeView(oldDestAv)
if nil != err {
return
}
}
}
}
av.RemoveAvRel(srcAv.ID, srcRel.AvID)
}
srcRel = &av.Relation{
@ -1069,6 +1073,8 @@ func updateAttributeViewColRelation(operation *Operation) (err error) {
err = av.SaveAttributeView(destAv)
util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID})
}
av.UpsertAvRel(srcAv.ID, destAv.ID)
return
}
@ -2116,31 +2122,53 @@ func removeAttributeViewColumn(operation *Operation) (err error) {
}
}
// 删除双向关联的目标列
if nil != removedKey && nil != removedKey.Relation && removedKey.Relation.IsTwoWay {
destAv, _ := av.ParseAttributeView(removedKey.Relation.AvID)
if nil != destAv {
for i, keyValues := range destAv.KeyValues {
if keyValues.Key.ID == removedKey.Relation.BackKeyID {
destAv.KeyValues = append(destAv.KeyValues[:i], destAv.KeyValues[i+1:]...)
break
}
}
if nil != removedKey && av.KeyTypeRelation == removedKey.Type && nil != removedKey.Relation {
if removedKey.Relation.IsTwoWay {
// 删除双向关联的目标列
for _, view := range destAv.Views {
switch view.LayoutType {
case av.LayoutTypeTable:
for i, column := range view.Table.Columns {
if column.ID == removedKey.Relation.BackKeyID {
view.Table.Columns = append(view.Table.Columns[:i], view.Table.Columns[i+1:]...)
break
destAv, _ := av.ParseAttributeView(removedKey.Relation.AvID)
if nil != destAv {
destAvRelSrcAv := false
for i, keyValues := range destAv.KeyValues {
if keyValues.Key.ID == removedKey.Relation.BackKeyID {
destAv.KeyValues = append(destAv.KeyValues[:i], destAv.KeyValues[i+1:]...)
continue
}
if av.KeyTypeRelation == keyValues.Key.Type && keyValues.Key.Relation.AvID == attrView.ID {
destAvRelSrcAv = true
}
}
for _, view := range destAv.Views {
switch view.LayoutType {
case av.LayoutTypeTable:
for i, column := range view.Table.Columns {
if column.ID == removedKey.Relation.BackKeyID {
view.Table.Columns = append(view.Table.Columns[:i], view.Table.Columns[i+1:]...)
break
}
}
}
}
av.SaveAttributeView(destAv)
util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID})
if !destAvRelSrcAv {
av.RemoveAvRel(destAv.ID, attrView.ID)
}
}
av.SaveAttributeView(destAv)
util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID})
srcAvRelDestAv := false
for _, keyValues := range attrView.KeyValues {
if av.KeyTypeRelation == keyValues.Key.Type && keyValues.Key.Relation.AvID == removedKey.Relation.AvID {
srcAvRelDestAv = true
}
}
if !srcAvRelDestAv {
av.RemoveAvRel(attrView.ID, removedKey.Relation.AvID)
}
}
}