package schema import ( "strings" "github.com/scylladb/go-set/strset" "github.com/wecisecode/util/cmap" ) type FieldInfo struct { Fieldname string Fieldtype string Keyidx int // 主键顺序值,0为非主键 Datakey []string // 对应数据中的键名 } type ClassInfo struct { Classaliasname string Classfullname string Fieldslist []string Keyfields []string Fieldinfos map[string]*FieldInfo DatakeyFieldinfos map[string]*FieldInfo WithOptions [][2]string Insertmql string Createmql string Addtagmql string } var ClassInfos = cmap.NewSingle[string, *ClassInfo]() var ClassAliasNames = []string{} func NewClassinfo(classaliasname, classsimplename, baseclassaliasname string, fieldinfoslist []*FieldInfo, withoptions ...[2]string) (ci *ClassInfo) { fieldinfos := map[string]*FieldInfo{} datakey_fieldinfos := map[string]*FieldInfo{} fieldslist := []string{} fieldsset := strset.New() keyfields := []string{} createmql := `create class if not exists ` + classsimplename + `:` + baseclassaliasname + `(` classfullname := "" bci := ClassInfos.GetIFPresent(baseclassaliasname) if bci != nil { classfullname = bci.Classfullname + "/" + classsimplename for fn, fi := range bci.Fieldinfos { fieldinfos[fn] = fi for _, dk := range fi.Datakey { datakey_fieldinfos[dk] = fi } } fieldslist = append(fieldslist, bci.Fieldslist...) fieldsset.Add(bci.Fieldslist...) keyfields = append(keyfields, bci.Keyfields...) } else { if baseclassaliasname != "/" && baseclassaliasname != "" { panic("baseclassname not defined " + baseclassaliasname) } classfullname = "/" + classsimplename } defer func() { ClassAliasNames = append(ClassAliasNames, classaliasname) ClassInfos.Set(classaliasname, ci) ClassInfos.Set(classfullname, ci) }() keyfield_defines := []string{} if len(fieldinfoslist) > 0 { field_defines := []string{} for _, fi := range fieldinfoslist { field_define := fi.Fieldname + ` ` + fi.Fieldtype if !fieldsset.Has(fi.Fieldname) { fieldslist = append(fieldslist, fi.Fieldname) fieldsset.Add(fi.Fieldname) } else { for _, dk := range bci.Fieldinfos[fi.Fieldname].Datakey { if !strset.New(fi.Datakey...).Has(dk) { fi.Datakey = append(fi.Datakey, dk) } } } field_define += `"` + strings.Join(fi.Datakey, ",") + `"` field_defines = append(field_defines, field_define) if fi.Keyidx > 0 { for len(keyfield_defines) < fi.Keyidx { keyfield_defines = append(keyfield_defines, "") } keyfield_defines[fi.Keyidx-1] = fi.Fieldname } fieldinfos[fi.Fieldname] = fi for _, dk := range fi.Datakey { datakey_fieldinfos[dk] = fi } } createmql += strings.Join(field_defines, ",") } if len(keyfield_defines) > 0 { createmql += ", keys(" + strings.Join(keyfield_defines, ",") + ")" keyfields = append(keyfields, keyfield_defines...) } createmql += `)with alias='` + classaliasname + `'` for _, withoption := range withoptions { if withoption[0] == "alias" { continue } createmql += " and " + withoption[0] + "=" + withoption[1] if withoption[0] == "key" && withoption[1] == "manu" { if !fieldsset.Has("id") { fieldslist = append([]string{"id"}, fieldslist...) fieldsset.Add("id") } } } if !fieldsset.Has("contain") { fieldslist = append(fieldslist, "contain") fieldsset.Add("contain") } if !fieldsset.Has("depend") { fieldslist = append(fieldslist, "depend") fieldsset.Add("depend") } if !fieldsset.Has("topology") { fieldslist = append(fieldslist, "topology") fieldsset.Add("topology") } var insertmql string if len(fieldslist) > 0 { insertmql = `insert into ` + classfullname + "(" + strings.Join(fieldslist, ",") + ")values(" + strings.Repeat(",?", len(fieldslist))[1:] + ")" } addtagmql := `insert into /matrix/tagdir (name,path,tags,domain,creater) values(?,?,?,'graph','system')` ci = &ClassInfo{ Classaliasname: classaliasname, Classfullname: classfullname, Fieldinfos: fieldinfos, WithOptions: withoptions, DatakeyFieldinfos: datakey_fieldinfos, Keyfields: keyfields, Fieldslist: fieldslist, Insertmql: insertmql, Createmql: createmql, Addtagmql: addtagmql, } return } var Relations = map[string]string{ "contains": "contain", "contain": "contain", "depend": "depend", "topology": "topology", }