index.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package schema
  2. import (
  3. "strconv"
  4. "strings"
  5. )
  6. type Index struct {
  7. Name string
  8. Class string // UNIQUE | FULLTEXT | SPATIAL
  9. Fields []IndexOption
  10. }
  11. type IndexOption struct {
  12. *Field
  13. Expression string
  14. Sort string // DESC, ASC
  15. Collate string
  16. Length int
  17. Type string // btree, hash, gist, spgist, gin, and brin
  18. Where string
  19. Comment string
  20. }
  21. // ParseIndexes parse schema indexes
  22. func (schema *Schema) ParseIndexes() map[string]Index {
  23. var indexes = map[string]Index{}
  24. for _, field := range schema.FieldsByDBName {
  25. if field.TagSettings["INDEX"] != "" || field.TagSettings["UNIQUE_INDEX"] != "" {
  26. for _, index := range parseFieldIndexes(field) {
  27. idx := indexes[index.Name]
  28. idx.Name = index.Name
  29. if idx.Class == "" {
  30. idx.Class = index.Class
  31. }
  32. idx.Fields = append(idx.Fields, index.Fields...)
  33. indexes[index.Name] = idx
  34. }
  35. }
  36. }
  37. return indexes
  38. }
  39. func parseFieldIndexes(field *Field) (indexes []Index) {
  40. for _, value := range strings.Split(field.Tag.Get("gorm"), ";") {
  41. if value != "" {
  42. v := strings.Split(value, ":")
  43. k := strings.TrimSpace(strings.ToUpper(v[0]))
  44. if k == "INDEX" || k == "UNIQUE_INDEX" {
  45. var (
  46. name string
  47. tag = strings.Join(v[1:], ":")
  48. settings = map[string]string{}
  49. )
  50. names := strings.Split(tag, ",")
  51. for i := 0; i < len(names); i++ {
  52. if len(names[i]) > 0 {
  53. j := i
  54. for {
  55. if names[j][len(names[j])-1] == '\\' {
  56. i++
  57. names[j] = names[j][0:len(names[j])-1] + names[i]
  58. names[i] = ""
  59. } else {
  60. break
  61. }
  62. }
  63. }
  64. if i == 0 {
  65. name = names[0]
  66. }
  67. values := strings.Split(names[i], ":")
  68. k := strings.TrimSpace(strings.ToUpper(values[0]))
  69. if len(values) >= 2 {
  70. settings[k] = strings.Join(values[1:], ":")
  71. } else if k != "" {
  72. settings[k] = k
  73. }
  74. }
  75. if name == "" {
  76. name = field.Schema.namer.IndexName(field.Schema.Table, field.Name)
  77. }
  78. length, _ := strconv.Atoi(settings["LENGTH"])
  79. if (k == "UNIQUE_INDEX") || settings["UNIQUE"] != "" {
  80. settings["CLASS"] = "UNIQUE"
  81. }
  82. indexes = append(indexes, Index{
  83. Name: name,
  84. Class: settings["CLASS"],
  85. Fields: []IndexOption{{
  86. Field: field,
  87. Expression: settings["EXPRESSION"],
  88. Sort: settings["SORT"],
  89. Collate: settings["COLLATE"],
  90. Type: settings["TYPE"],
  91. Length: length,
  92. Where: settings["WHERE"],
  93. Comment: settings["COMMENT"],
  94. }},
  95. })
  96. }
  97. }
  98. }
  99. return
  100. }