classstruct.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. package importer
  2. import (
  3. "os"
  4. "path/filepath"
  5. "regexp"
  6. "strings"
  7. "sync"
  8. "time"
  9. "git.wecise.com/wecise/cgimport/schema"
  10. ci "git.wecise.com/wecise/odb-go/schema"
  11. "github.com/wecisecode/util/cmap"
  12. "github.com/wecisecode/util/merrs"
  13. "github.com/wecisecode/util/mio"
  14. "github.com/wecisecode/util/spliter"
  15. )
  16. type classdatainfo struct {
  17. *ci.ClassInfoHelper
  18. insertcount int64
  19. lastlogtime time.Time
  20. lastlogicount int64
  21. mutex sync.Mutex
  22. }
  23. var classdatainfos = cmap.NewSingle[string, *classdatainfo]()
  24. var recreatestatement = regexp.MustCompile(`(?is)create\s+(class|edge\s+type)\s+(?:if\s+not\s+exists\s+)?([\/@\.\w]+)`)
  25. var respace = regexp.MustCompile(`\s*`)
  26. // 根据数据修正类定义
  27. func (odbci *ODBCImporter) ReviseClassStruct() (err error) {
  28. if odbci.client == nil {
  29. return
  30. }
  31. mqlfile := filepath.Join(filepath.Dir(os.Args[0]), "cgimport.mql")
  32. bs, e := mio.ReadFile(mqlfile)
  33. if e != nil {
  34. return e
  35. }
  36. schema_mqls := schema.MQLs
  37. if len(bs) > 0 {
  38. logger.Info("read schema mql from file", mqlfile)
  39. schema_mqls = string(bs)
  40. }
  41. mqls := spliter.MQLSplit(schema_mqls)
  42. for _, mql := range mqls {
  43. sstn := recreatestatement.FindStringSubmatch(mql)
  44. if len(sstn) > 2 {
  45. switch strings.ToLower(respace.ReplaceAllString(sstn[1], "")) {
  46. case "class":
  47. e := odbci.createclass(sstn[2], mql)
  48. if e != nil {
  49. return e
  50. }
  51. case "edgetype":
  52. e := odbci.createedgetype(sstn[2], mql)
  53. if e != nil {
  54. return e
  55. }
  56. }
  57. }
  58. }
  59. return
  60. }
  61. func (odbci *ODBCImporter) createclass(classname, mql string) (err error) {
  62. logger.Debug("create class " + classname)
  63. _, e := odbci.client.Query(mql).Do()
  64. if e != nil {
  65. return e
  66. }
  67. cis, e := odbci.client.ClassInfo(classname, false)
  68. if e != nil {
  69. return e
  70. }
  71. if len(cis) != 1 {
  72. return merrs.New("len(cis) != 1")
  73. }
  74. oci := cis[0]
  75. aci := odbci.schema.NewClassinfo(oci)
  76. // add graph tags
  77. _, e = odbci.client.Query(aci.Addtagmql, aci.Classaliasname, aci.Classaliasname, []string{aci.Classaliasname}).Do()
  78. if e != nil {
  79. return e
  80. }
  81. cdi := &classdatainfo{ClassInfoHelper: aci}
  82. classdatainfos.Set(aci.Classaliasname, cdi)
  83. classdatainfos.Set(aci.Classfullname, cdi)
  84. logger.Info("created class", aci.Classfullname)
  85. return
  86. }
  87. func (odbci *ODBCImporter) createedgetype(edgetypename, mql string) (err error) {
  88. _, e := odbci.client.Query(mql).Do()
  89. if e != nil {
  90. if strings.Contains(e.Error(), "already exist") {
  91. return nil
  92. }
  93. return e
  94. }
  95. logger.Info("created edge type", edgetypename)
  96. return nil
  97. }
  98. func (odbci *ODBCImporter) getClassinfos() (err error) {
  99. odbci.schema.Clear()
  100. classinfos, e := odbci.client.ClassInfo("/m3cnet", true)
  101. if e != nil {
  102. return e
  103. }
  104. for _, oci := range classinfos {
  105. aci := odbci.schema.NewClassinfo(oci)
  106. cdi := &classdatainfo{ClassInfoHelper: aci}
  107. classdatainfos.Set(aci.Classaliasname, cdi)
  108. classdatainfos.Set(aci.Classfullname, cdi)
  109. }
  110. return nil
  111. }
  112. func (odbci *ODBCImporter) init(rebuild bool) (err error) {
  113. err = odbci.getClassinfos()
  114. if err != nil {
  115. return
  116. }
  117. // bs, _ := json.MarshalIndent(schema.ClassInfos, "", " ")
  118. // fmt.Println(string(bs))
  119. if rebuild {
  120. // 清除已有类
  121. err = odbci.rebuild()
  122. if err != nil {
  123. return
  124. }
  125. odbci.schema.Clear()
  126. }
  127. if odbci.schema.ClassCount() == 0 {
  128. // 建类
  129. err = odbci.ReviseClassStruct()
  130. if err != nil {
  131. return
  132. }
  133. }
  134. return nil
  135. }
  136. func (odbci *ODBCImporter) rebuild() error {
  137. if odbci.client != nil {
  138. classaliasnames := odbci.schema.ClassAliasNames()
  139. for i := len(classaliasnames) - 1; i >= 0; i-- {
  140. classaliasname := classaliasnames[i]
  141. ci := odbci.schema.GetClassInfo(classaliasname)
  142. if ci == nil {
  143. continue
  144. }
  145. e := odbci.dropclass(ci.Classfullname)
  146. if e != nil {
  147. return e
  148. }
  149. }
  150. }
  151. return nil
  152. }
  153. func (odbci *ODBCImporter) dropclass(classnames ...string) error {
  154. for _, classname := range classnames {
  155. for retry := 2; retry >= 0; retry-- {
  156. // 强制多次删除,避免drop失败导致后续错误
  157. _, e := odbci.client.Query(`delete from /matrix/tagdir where tags='` + classname + `'`).Do()
  158. _ = e
  159. _, e = odbci.client.Query(`delete from "` + classname + `" with version`).Do()
  160. _ = e
  161. _, e = odbci.client.Query(`drop class if exists "` + classname + `"`).Do()
  162. if e != nil {
  163. matchstr := regexp.MustCompile(`refer by ([^,]+)`).FindStringSubmatch(e.Error())
  164. if len(matchstr) >= 2 {
  165. e = odbci.dropclass(matchstr[1])
  166. if e != nil {
  167. return e
  168. }
  169. } else {
  170. matchstr := regexp.MustCompile(`has children \[([^\]]+)\]`).FindStringSubmatch(e.Error())
  171. if len(matchstr) >= 2 {
  172. e = odbci.dropclass(strings.Split(matchstr[1], " ")...)
  173. if e != nil {
  174. return e
  175. }
  176. }
  177. }
  178. if retry > 0 {
  179. continue
  180. }
  181. return e
  182. }
  183. }
  184. logger.Info("drop class " + classname)
  185. odbci.schema.RemoveClassInfo(classname)
  186. }
  187. return nil
  188. }