浏览代码

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

Daniel 1 年之前
父节点
当前提交
290df47a1e
共有 2 个文件被更改,包括 97 次插入55 次删除
  1. 39 11
      kernel/av/relation.go
  2. 58 44
      kernel/model/attribute_view.go

+ 39 - 11
kernel/av/relation.go

@@ -16,7 +16,35 @@ var (
 	attributeViewRelationsLock = sync.Mutex{}
 	attributeViewRelationsLock = sync.Mutex{}
 )
 )
 
 
-func RemoveAvRel(avID, destAvID string) {
+func GetSrcAvIDs(destAvID string) []string {
+	attributeViewRelationsLock.Lock()
+	defer attributeViewRelationsLock.Unlock()
+
+	relations := filepath.Join(util.DataDir, "storage", "av", "relations.msgpack")
+	if !filelock.IsExist(relations) {
+		return nil
+	}
+
+	data, err := filelock.ReadFile(relations)
+	if nil != err {
+		logging.LogErrorf("read attribute view relations failed: %s", err)
+		return nil
+	}
+
+	avRels := map[string][]string{}
+	if err = msgpack.Unmarshal(data, &avRels); nil != err {
+		logging.LogErrorf("unmarshal attribute view relations failed: %s", err)
+		return nil
+	}
+
+	srcAvIDs := avRels[destAvID]
+	if nil == srcAvIDs {
+		return nil
+	}
+	return srcAvIDs
+}
+
+func RemoveAvRel(srcAvID, destAvID string) {
 	attributeViewRelationsLock.Lock()
 	attributeViewRelationsLock.Lock()
 	defer attributeViewRelationsLock.Unlock()
 	defer attributeViewRelationsLock.Unlock()
 
 
@@ -37,18 +65,18 @@ func RemoveAvRel(avID, destAvID string) {
 		return
 		return
 	}
 	}
 
 
-	destAvIDs := avRels[avID]
-	if nil == destAvIDs {
+	srcAvIDs := avRels[destAvID]
+	if nil == srcAvIDs {
 		return
 		return
 	}
 	}
 
 
 	var newAvIDs []string
 	var newAvIDs []string
-	for _, v := range destAvIDs {
-		if v != destAvID {
+	for _, v := range srcAvIDs {
+		if v != srcAvID {
 			newAvIDs = append(newAvIDs, v)
 			newAvIDs = append(newAvIDs, v)
 		}
 		}
 	}
 	}
-	avRels[avID] = newAvIDs
+	avRels[destAvID] = newAvIDs
 
 
 	data, err = msgpack.Marshal(avRels)
 	data, err = msgpack.Marshal(avRels)
 	if nil != err {
 	if nil != err {
@@ -61,7 +89,7 @@ func RemoveAvRel(avID, destAvID string) {
 	}
 	}
 }
 }
 
 
-func UpsertAvRel(avID, destAvID string) {
+func UpsertAvBackRel(srcAvID, destAvID string) {
 	attributeViewRelationsLock.Lock()
 	attributeViewRelationsLock.Lock()
 	defer attributeViewRelationsLock.Unlock()
 	defer attributeViewRelationsLock.Unlock()
 
 
@@ -85,10 +113,10 @@ func UpsertAvRel(avID, destAvID string) {
 		}
 		}
 	}
 	}
 
 
-	destAvIDs := avRelations[avID]
-	destAvIDs = append(destAvIDs, destAvID)
-	destAvIDs = gulu.Str.RemoveDuplicatedElem(destAvIDs)
-	avRelations[avID] = destAvIDs
+	srcAvIDs := avRelations[destAvID]
+	srcAvIDs = append(srcAvIDs, srcAvID)
+	srcAvIDs = gulu.Str.RemoveDuplicatedElem(srcAvIDs)
+	avRelations[destAvID] = srcAvIDs
 
 
 	data, err := msgpack.Marshal(avRelations)
 	data, err := msgpack.Marshal(avRelations)
 	if nil != err {
 	if nil != err {

+ 58 - 44
kernel/model/attribute_view.go

@@ -693,6 +693,14 @@ func renderAttributeViewTable(attrView *av.AttributeView, view *av.View) (ret *a
 			}
 			}
 			rows[val.BlockID] = values
 			rows[val.BlockID] = values
 		}
 		}
+
+		// 数据订正,补全关联
+		if av.KeyTypeRelation == keyValues.Key.Type && nil != keyValues.Key.Relation {
+			av.UpsertAvBackRel(attrView.ID, keyValues.Key.Relation.AvID)
+			if keyValues.Key.Relation.IsTwoWay {
+				av.UpsertAvBackRel(keyValues.Key.Relation.AvID, attrView.ID)
+			}
+		}
 	}
 	}
 
 
 	// 过滤掉不存在的行
 	// 过滤掉不存在的行
@@ -1074,7 +1082,7 @@ func updateAttributeViewColRelation(operation *Operation) (err error) {
 		util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID})
 		util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID})
 	}
 	}
 
 
-	av.UpsertAvRel(srcAv.ID, destAv.ID)
+	av.UpsertAvBackRel(srcAv.ID, destAv.ID)
 	return
 	return
 }
 }
 
 
@@ -2332,7 +2340,7 @@ func UpdateAttributeViewCell(tx *Transaction, avID, keyID, rowID, cellID string,
 		// 关联列得 content 是自动渲染的,所以不需要保存
 		// 关联列得 content 是自动渲染的,所以不需要保存
 		val.Relation.Contents = nil
 		val.Relation.Contents = nil
 
 
-		// 计算关联排序模式
+		// 计算关联变更模式
 		if len(oldRelationBlockIDs) == len(val.Relation.BlockIDs) {
 		if len(oldRelationBlockIDs) == len(val.Relation.BlockIDs) {
 			relationChangeMode = 0
 			relationChangeMode = 0
 		} else {
 		} else {
@@ -2377,64 +2385,70 @@ func UpdateAttributeViewCell(tx *Transaction, avID, keyID, rowID, cellID string,
 	}
 	}
 
 
 	key, _ := attrView.GetKey(val.KeyID)
 	key, _ := attrView.GetKey(val.KeyID)
-	if nil != key && av.KeyTypeRelation == key.Type && nil != key.Relation && key.Relation.IsTwoWay {
+	if nil != key && av.KeyTypeRelation == key.Type && nil != key.Relation {
 		destAv, _ := av.ParseAttributeView(key.Relation.AvID)
 		destAv, _ := av.ParseAttributeView(key.Relation.AvID)
 		if nil != destAv {
 		if nil != destAv {
-			// relationChangeMode
-			// 0:关联列值不变(仅排序),不影响目标值
-			// 1:关联列值增加,增加目标值
-			// 2:关联列值减少,减少目标值
-
-			if 1 == relationChangeMode {
-				addBlockIDs := val.Relation.BlockIDs
-				for _, bID := range oldRelationBlockIDs {
-					addBlockIDs = gulu.Str.RemoveElem(addBlockIDs, bID)
-				}
+			if key.Relation.IsTwoWay {
+				// relationChangeMode
+				// 0:关联列值不变(仅排序),不影响目标值
+				// 1:关联列值增加,增加目标值
+				// 2:关联列值减少,减少目标值
+
+				if 1 == relationChangeMode {
+					addBlockIDs := val.Relation.BlockIDs
+					for _, bID := range oldRelationBlockIDs {
+						addBlockIDs = gulu.Str.RemoveElem(addBlockIDs, bID)
+					}
 
 
-				for _, blockID := range addBlockIDs {
-					for _, keyValues := range destAv.KeyValues {
-						if keyValues.Key.ID != key.Relation.BackKeyID {
-							continue
-						}
+					for _, blockID := range addBlockIDs {
+						for _, keyValues := range destAv.KeyValues {
+							if keyValues.Key.ID != key.Relation.BackKeyID {
+								continue
+							}
 
 
-						destVal := keyValues.GetValue(blockID)
-						if nil == destVal {
-							destVal = &av.Value{ID: ast.NewNodeID(), KeyID: keyValues.Key.ID, BlockID: blockID, Type: keyValues.Key.Type, Relation: &av.ValueRelation{}}
-							keyValues.Values = append(keyValues.Values, destVal)
-						}
+							destVal := keyValues.GetValue(blockID)
+							if nil == destVal {
+								destVal = &av.Value{ID: ast.NewNodeID(), KeyID: keyValues.Key.ID, BlockID: blockID, Type: keyValues.Key.Type, Relation: &av.ValueRelation{}}
+								keyValues.Values = append(keyValues.Values, destVal)
+							}
 
 
-						destVal.Relation.BlockIDs = append(destVal.Relation.BlockIDs, rowID)
-						destVal.Relation.BlockIDs = gulu.Str.RemoveDuplicatedElem(destVal.Relation.BlockIDs)
-						break
+							destVal.Relation.BlockIDs = append(destVal.Relation.BlockIDs, rowID)
+							destVal.Relation.BlockIDs = gulu.Str.RemoveDuplicatedElem(destVal.Relation.BlockIDs)
+							break
+						}
+					}
+				} else if 2 == relationChangeMode {
+					removeBlockIDs := oldRelationBlockIDs
+					for _, bID := range val.Relation.BlockIDs {
+						removeBlockIDs = gulu.Str.RemoveElem(removeBlockIDs, bID)
 					}
 					}
-				}
-			} else if 2 == relationChangeMode {
-				removeBlockIDs := oldRelationBlockIDs
-				for _, bID := range val.Relation.BlockIDs {
-					removeBlockIDs = gulu.Str.RemoveElem(removeBlockIDs, bID)
-				}
 
 
-				for _, blockID := range removeBlockIDs {
-					for _, keyValues := range destAv.KeyValues {
-						if keyValues.Key.ID != key.Relation.BackKeyID {
-							continue
-						}
+					for _, blockID := range removeBlockIDs {
+						for _, keyValues := range destAv.KeyValues {
+							if keyValues.Key.ID != key.Relation.BackKeyID {
+								continue
+							}
 
 
-						for _, value := range keyValues.Values {
-							if value.BlockID == blockID {
-								value.Relation.BlockIDs = gulu.Str.RemoveElem(value.Relation.BlockIDs, rowID)
-								break
+							for _, value := range keyValues.Values {
+								if value.BlockID == blockID {
+									value.Relation.BlockIDs = gulu.Str.RemoveElem(value.Relation.BlockIDs, rowID)
+									break
+								}
 							}
 							}
 						}
 						}
 					}
 					}
 				}
 				}
-			}
 
 
-			av.SaveAttributeView(destAv)
-			util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID})
+				av.SaveAttributeView(destAv)
+			}
 		}
 		}
 	}
 	}
 
 
+	relatedAvIDs := av.GetSrcAvIDs(avID)
+	for _, relatedAvID := range relatedAvIDs {
+		util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": relatedAvID})
+	}
+
 	if err = av.SaveAttributeView(attrView); nil != err {
 	if err = av.SaveAttributeView(attrView); nil != err {
 		return
 		return
 	}
 	}