classstruct.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. "git.wecise.com/wecise/odb-go/dbo"
  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. *dbo.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, e := odbci.schema.NewClassinfo(oci)
  76. if e != nil {
  77. return e
  78. }
  79. // add graph tags
  80. _, e = odbci.client.Query(aci.Addtagmql, aci.Classaliasname, aci.Classaliasname, []string{aci.Classaliasname}).Do()
  81. if e != nil {
  82. return e
  83. }
  84. cdi := &classdatainfo{ClassInfoHelper: aci}
  85. classdatainfos.Set(aci.Classaliasname, cdi)
  86. classdatainfos.Set(aci.Classfullname, cdi)
  87. logger.Info("created class", aci.Classfullname)
  88. return
  89. }
  90. func (odbci *ODBCImporter) createedgetype(edgetypename, mql string) (err error) {
  91. _, e := odbci.client.Query(mql).Do()
  92. if e != nil {
  93. if strings.Contains(e.Error(), "already exist") {
  94. return nil
  95. }
  96. return e
  97. }
  98. logger.Info("created edge type", edgetypename)
  99. return nil
  100. }
  101. func (odbci *ODBCImporter) getClassinfos() (err error) {
  102. odbci.schema.Clear()
  103. classinfos, e := odbci.client.ClassInfo("/m3cnet", true)
  104. if e != nil {
  105. return merrs.New(e)
  106. }
  107. for _, oci := range classinfos {
  108. aci, e := odbci.schema.NewClassinfo(oci)
  109. if e != nil {
  110. return e
  111. }
  112. cdi := &classdatainfo{ClassInfoHelper: aci}
  113. classdatainfos.Set(aci.Classaliasname, cdi)
  114. classdatainfos.Set(aci.Classfullname, cdi)
  115. }
  116. return nil
  117. }
  118. func (odbci *ODBCImporter) init(rebuild bool) (err error) {
  119. err = odbci.getClassinfos()
  120. if err != nil {
  121. if !merrs.NotExistError.Contains(err) {
  122. return
  123. }
  124. }
  125. // bs, _ := json.MarshalIndent(schema.ClassInfos, "", " ")
  126. // fmt.Println(string(bs))
  127. if rebuild {
  128. // 清除已有类
  129. err = odbci.rebuild()
  130. if err != nil {
  131. return
  132. }
  133. odbci.schema.Clear()
  134. }
  135. if odbci.schema.ClassCount() == 0 {
  136. // 建类
  137. err = odbci.ReviseClassStruct()
  138. if err != nil {
  139. return
  140. }
  141. }
  142. err = odbci.getClassinfos()
  143. if err != nil {
  144. return
  145. }
  146. return nil
  147. }
  148. func (odbci *ODBCImporter) rebuild() error {
  149. if odbci.client != nil {
  150. classaliasnames := odbci.schema.ClassAliasNames()
  151. for i := len(classaliasnames) - 1; i >= 0; i-- {
  152. classaliasname := classaliasnames[i]
  153. ci := odbci.schema.GetClassInfo(classaliasname)
  154. if ci == nil {
  155. continue
  156. }
  157. e := odbci.dropclass(ci.Classfullname)
  158. if e != nil {
  159. return e
  160. }
  161. }
  162. }
  163. return nil
  164. }
  165. func (odbci *ODBCImporter) dropclass(classnames ...string) error {
  166. for _, classname := range classnames {
  167. for retry := 2; retry >= 0; retry-- {
  168. // 强制多次删除,避免drop失败导致后续错误
  169. _, e := odbci.client.Query(`delete from /matrix/tagdir where tags='` + classname + `'`).Do()
  170. _ = e
  171. _, e = odbci.client.Query(`delete from "` + classname + `" with version`).Do()
  172. _ = e
  173. _, e = odbci.client.Query(`drop class if exists "` + classname + `"`).Do()
  174. if e != nil {
  175. matchstr := regexp.MustCompile(`refer by ([^,]+)`).FindStringSubmatch(e.Error())
  176. if len(matchstr) >= 2 {
  177. e = odbci.dropclass(matchstr[1])
  178. if e != nil {
  179. return e
  180. }
  181. } else {
  182. matchstr := regexp.MustCompile(`has children \[([^\]]+)\]`).FindStringSubmatch(e.Error())
  183. if len(matchstr) >= 2 {
  184. e = odbci.dropclass(strings.Split(matchstr[1], " ")...)
  185. if e != nil {
  186. return e
  187. }
  188. }
  189. }
  190. if retry > 0 {
  191. continue
  192. }
  193. return e
  194. }
  195. }
  196. logger.Info("drop class " + classname)
  197. odbci.schema.RemoveClassInfo(classname)
  198. }
  199. return nil
  200. }