naming.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package gorm
  2. import (
  3. "bytes"
  4. "strings"
  5. )
  6. // Namer is a function type which is given a string and return a string
  7. type Namer func(string) string
  8. // NamingStrategy represents naming strategies
  9. type NamingStrategy struct {
  10. DB Namer
  11. Table Namer
  12. Column Namer
  13. }
  14. // TheNamingStrategy is being initialized with defaultNamingStrategy
  15. var TheNamingStrategy = &NamingStrategy{
  16. DB: defaultNamer,
  17. Table: defaultNamer,
  18. Column: defaultNamer,
  19. }
  20. // AddNamingStrategy sets the naming strategy
  21. func AddNamingStrategy(ns *NamingStrategy) {
  22. if ns.DB == nil {
  23. ns.DB = defaultNamer
  24. }
  25. if ns.Table == nil {
  26. ns.Table = defaultNamer
  27. }
  28. if ns.Column == nil {
  29. ns.Column = defaultNamer
  30. }
  31. TheNamingStrategy = ns
  32. }
  33. // DBName alters the given name by DB
  34. func (ns *NamingStrategy) DBName(name string) string {
  35. return ns.DB(name)
  36. }
  37. // TableName alters the given name by Table
  38. func (ns *NamingStrategy) TableName(name string) string {
  39. return ns.Table(name)
  40. }
  41. // ColumnName alters the given name by Column
  42. func (ns *NamingStrategy) ColumnName(name string) string {
  43. return ns.Column(name)
  44. }
  45. // ToDBName convert string to db name
  46. func ToDBName(name string) string {
  47. return TheNamingStrategy.DBName(name)
  48. }
  49. // ToTableName convert string to table name
  50. func ToTableName(name string) string {
  51. return TheNamingStrategy.TableName(name)
  52. }
  53. // ToColumnName convert string to db name
  54. func ToColumnName(name string) string {
  55. return TheNamingStrategy.ColumnName(name)
  56. }
  57. var smap = newSafeMap()
  58. func defaultNamer(name string) string {
  59. const (
  60. lower = false
  61. upper = true
  62. )
  63. if v := smap.Get(name); v != "" {
  64. return v
  65. }
  66. if name == "" {
  67. return ""
  68. }
  69. var (
  70. value = commonInitialismsReplacer.Replace(name)
  71. buf = bytes.NewBufferString("")
  72. lastCase, currCase, nextCase, nextNumber bool
  73. )
  74. for i, v := range value[:len(value)-1] {
  75. nextCase = bool(value[i+1] >= 'A' && value[i+1] <= 'Z')
  76. nextNumber = bool(value[i+1] >= '0' && value[i+1] <= '9')
  77. if i > 0 {
  78. if currCase == upper {
  79. if lastCase == upper && (nextCase == upper || nextNumber == upper) {
  80. buf.WriteRune(v)
  81. } else {
  82. if value[i-1] != '_' && value[i+1] != '_' {
  83. buf.WriteRune('_')
  84. }
  85. buf.WriteRune(v)
  86. }
  87. } else {
  88. buf.WriteRune(v)
  89. if i == len(value)-2 && (nextCase == upper && nextNumber == lower) {
  90. buf.WriteRune('_')
  91. }
  92. }
  93. } else {
  94. currCase = upper
  95. buf.WriteRune(v)
  96. }
  97. lastCase = currCase
  98. currCase = nextCase
  99. }
  100. buf.WriteByte(value[len(value)-1])
  101. s := strings.ToLower(buf.String())
  102. smap.Set(name, s)
  103. return s
  104. }