|
@@ -1,6 +1,7 @@
|
|
|
package importer
|
|
|
|
|
|
import (
|
|
|
+ "encoding/base64"
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
"strings"
|
|
@@ -69,10 +70,100 @@ func (odbci *ODBCImporter) ReviseClassStruct() (err error) {
|
|
|
}
|
|
|
|
|
|
func (odbci *ODBCImporter) InsertEdge(data map[string]any) (err error) {
|
|
|
-
|
|
|
+ extraattr := map[string]string{}
|
|
|
+ fromuid := ""
|
|
|
+ touid := ""
|
|
|
+ edgetype := ""
|
|
|
+ for k, v := range data {
|
|
|
+ switch k {
|
|
|
+ case "FROMUNIQUEID":
|
|
|
+ fromuid = cast.ToString(v)
|
|
|
+ case "TOUNIQUEID":
|
|
|
+ touid = cast.ToString(v)
|
|
|
+ case "EDGETYPE":
|
|
|
+ edgetype = cast.ToString(v)
|
|
|
+ default:
|
|
|
+ extraattr[k] = cast.ToString(v)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if fromuid == "" {
|
|
|
+ databs, _ := json.MarshalIndent(data, "", " ")
|
|
|
+ return merrs.NewError("not found valid fromuniqueid in data ", merrs.SSMap{"data": string(databs)})
|
|
|
+ }
|
|
|
+ if touid == "" {
|
|
|
+ databs, _ := json.MarshalIndent(data, "", " ")
|
|
|
+ return merrs.NewError("not found valid touniqueid in data ", merrs.SSMap{"data": string(databs)})
|
|
|
+ }
|
|
|
+ if edgetype == "" {
|
|
|
+ databs, _ := json.MarshalIndent(data, "", " ")
|
|
|
+ return merrs.NewError("not found valid edgetype in data ", merrs.SSMap{"data": string(databs)})
|
|
|
+ }
|
|
|
+ edgetype = relations[edgetype]
|
|
|
+ if edgetype == "" {
|
|
|
+ databs, _ := json.MarshalIndent(data, "", " ")
|
|
|
+ return merrs.NewError("not found valid edgetype in data ", merrs.SSMap{"data": string(databs)})
|
|
|
+ }
|
|
|
+ if odbci.client != nil {
|
|
|
+ foid := get_object_id_from_cache(fromuid)
|
|
|
+ toid := get_object_id_from_cache(touid)
|
|
|
+ eabs, _ := json.Marshal(extraattr)
|
|
|
+ quadmql := `quad "` + foid + `" ` + edgetype + ` + "` + toid + `" ` + string(eabs)
|
|
|
+ _, err = odbci.client.Query(quadmql).Do()
|
|
|
+ if err != nil {
|
|
|
+ err = merrs.NewError(err, merrs.SSMaps{{"mql": quadmql}})
|
|
|
+ logger.Error(err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+var cm_object_id_cache = cmap.New[string, chan string]()
|
|
|
+
|
|
|
+func object_id_cache(suid string) chan string {
|
|
|
+ choid, _ := cm_object_id_cache.GetWithNew(suid,
|
|
|
+ func() (chan string, error) {
|
|
|
+ ch := make(chan string, 2)
|
|
|
+ return ch, nil
|
|
|
+ })
|
|
|
+ return choid
|
|
|
+}
|
|
|
+
|
|
|
+func get_object_id_from_cache(suid string) string {
|
|
|
+ choid := object_id_cache(suid)
|
|
|
+ oid := <-choid
|
|
|
+ push_object_id_into_cache(choid, oid)
|
|
|
+ return oid
|
|
|
+}
|
|
|
+
|
|
|
+func push_object_id_into_cache(choid chan string, oid string) {
|
|
|
+ choid <- oid
|
|
|
+ if len(choid) == 2 {
|
|
|
+ // 最多保留 1 个
|
|
|
+ // chan cap = 2,第三个元素进不来
|
|
|
+ // 进第二个元素的协程,清除第一个元素,允许其它协程后续进入新元素
|
|
|
+ <-choid
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func object_id(classaliasname string, data map[string]any) (oid, suid string, err error) {
|
|
|
+ uid := data["uniqueId"]
|
|
|
+ if uid == nil {
|
|
|
+ uid = data["UNIQUEID"]
|
|
|
+ if uid == nil {
|
|
|
+ databs, _ := json.MarshalIndent(data, "", " ")
|
|
|
+ return "", "", merrs.NewError("not found uniqueid in data ", merrs.SSMap{"data": string(databs)})
|
|
|
+ }
|
|
|
+ }
|
|
|
+ suid = cast.ToString(uid)
|
|
|
+ if suid == "" {
|
|
|
+ databs, _ := json.MarshalIndent(data, "", " ")
|
|
|
+ return "", "", merrs.NewError("not found valid uniqueid in data ", merrs.SSMap{"data": string(databs)})
|
|
|
+ }
|
|
|
+ suid64 := base64.RawURLEncoding.EncodeToString([]byte(suid))
|
|
|
+ return classaliasname + ":" + suid64, suid, nil
|
|
|
+}
|
|
|
+
|
|
|
// 插入数据
|
|
|
func (odbci *ODBCImporter) InsertData(classname string, data map[string]any) (err error) {
|
|
|
cdi := classdatainfos.GetIFPresent(classname)
|
|
@@ -82,8 +173,16 @@ func (odbci *ODBCImporter) InsertData(classname string, data map[string]any) (er
|
|
|
if cdi.insertmql == "" {
|
|
|
return merrs.NewError("class no fields to insert " + classname)
|
|
|
}
|
|
|
+ oid, suid, e := object_id(cdi.aliasname, data)
|
|
|
+ if e != nil {
|
|
|
+ return e
|
|
|
+ }
|
|
|
values := []any{}
|
|
|
for _, fn := range cdi.fieldslist {
|
|
|
+ if fn == "id" {
|
|
|
+ values = append(values, oid)
|
|
|
+ continue
|
|
|
+ }
|
|
|
fi := cdi.fieldinfos[fn]
|
|
|
if fi.datakey == "" {
|
|
|
td := map[string]any{}
|
|
@@ -110,6 +209,9 @@ func (odbci *ODBCImporter) InsertData(classname string, data map[string]any) (er
|
|
|
}
|
|
|
v = tv.Format("2006-01-02 15:04:05.000000")
|
|
|
}
|
|
|
+ if fn == "tags" {
|
|
|
+ v = append(cast.ToStringSlice(v), classname)
|
|
|
+ }
|
|
|
values = append(values, v)
|
|
|
}
|
|
|
if odbci.client != nil {
|
|
@@ -119,6 +221,7 @@ func (odbci *ODBCImporter) InsertData(classname string, data map[string]any) (er
|
|
|
logger.Error(err)
|
|
|
return
|
|
|
}
|
|
|
+ push_object_id_into_cache(object_id_cache(suid), oid)
|
|
|
}
|
|
|
atomic.AddInt64(&cdi.insertcount, 1)
|
|
|
cdi.mutex.Lock()
|