123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- package schema
- import (
- "crypto/sha1"
- "fmt"
- "strings"
- "sync"
- "unicode/utf8"
- "github.com/jinzhu/inflection"
- )
- // Namer namer interface
- type Namer interface {
- TableName(table string) string
- ColumnName(table, column string) string
- JoinTableName(joinTable string) string
- RelationshipFKName(Relationship) string
- CheckerName(table, column string) string
- IndexName(table, column string) string
- }
- // NamingStrategy tables, columns naming strategy
- type NamingStrategy struct {
- TablePrefix string
- SingularTable bool
- NameReplacer *strings.Replacer
- }
- // TableName convert string to table name
- func (ns NamingStrategy) TableName(str string) string {
- if ns.SingularTable {
- return ns.TablePrefix + ns.toDBName(str)
- }
- return ns.TablePrefix + inflection.Plural(ns.toDBName(str))
- }
- // ColumnName convert string to column name
- func (ns NamingStrategy) ColumnName(table, column string) string {
- return ns.toDBName(column)
- }
- // JoinTableName convert string to join table name
- func (ns NamingStrategy) JoinTableName(str string) string {
- if strings.ToLower(str) == str {
- return ns.TablePrefix + str
- }
- if ns.SingularTable {
- return ns.TablePrefix + ns.toDBName(str)
- }
- return ns.TablePrefix + inflection.Plural(ns.toDBName(str))
- }
- // RelationshipFKName generate fk name for relation
- func (ns NamingStrategy) RelationshipFKName(rel Relationship) string {
- return strings.Replace(fmt.Sprintf("fk_%s_%s", rel.Schema.Table, ns.toDBName(rel.Name)), ".", "_", -1)
- }
- // CheckerName generate checker name
- func (ns NamingStrategy) CheckerName(table, column string) string {
- return strings.Replace(fmt.Sprintf("chk_%s_%s", table, column), ".", "_", -1)
- }
- // IndexName generate index name
- func (ns NamingStrategy) IndexName(table, column string) string {
- idxName := fmt.Sprintf("idx_%v_%v", table, ns.toDBName(column))
- idxName = strings.Replace(idxName, ".", "_", -1)
- if utf8.RuneCountInString(idxName) > 64 {
- h := sha1.New()
- h.Write([]byte(idxName))
- bs := h.Sum(nil)
- idxName = fmt.Sprintf("idx%v%v", table, column)[0:56] + string(bs)[:8]
- }
- return idxName
- }
- var (
- smap sync.Map
- // https://github.com/golang/lint/blob/master/lint.go#L770
- commonInitialisms = []string{"API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "LHS", "QPS", "RAM", "RHS", "RPC", "SLA", "SMTP", "SSH", "TLS", "TTL", "UID", "UI", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XSRF", "XSS"}
- commonInitialismsReplacer *strings.Replacer
- )
- func init() {
- var commonInitialismsForReplacer []string
- for _, initialism := range commonInitialisms {
- commonInitialismsForReplacer = append(commonInitialismsForReplacer, initialism, strings.Title(strings.ToLower(initialism)))
- }
- commonInitialismsReplacer = strings.NewReplacer(commonInitialismsForReplacer...)
- }
- func (ns NamingStrategy) toDBName(name string) string {
- if name == "" {
- return ""
- } else if v, ok := smap.Load(name); ok {
- return v.(string)
- }
- if ns.NameReplacer != nil {
- name = ns.NameReplacer.Replace(name)
- }
- var (
- value = commonInitialismsReplacer.Replace(name)
- buf strings.Builder
- lastCase, nextCase, nextNumber bool // upper case == true
- curCase = value[0] <= 'Z' && value[0] >= 'A'
- )
- for i, v := range value[:len(value)-1] {
- nextCase = value[i+1] <= 'Z' && value[i+1] >= 'A'
- nextNumber = value[i+1] >= '0' && value[i+1] <= '9'
- if curCase {
- if lastCase && (nextCase || nextNumber) {
- buf.WriteRune(v + 32)
- } else {
- if i > 0 && value[i-1] != '_' && value[i+1] != '_' {
- buf.WriteByte('_')
- }
- buf.WriteRune(v + 32)
- }
- } else {
- buf.WriteRune(v)
- }
- lastCase = curCase
- curCase = nextCase
- }
- if curCase {
- if !lastCase && len(value) > 1 {
- buf.WriteByte('_')
- }
- buf.WriteByte(value[len(value)-1] + 32)
- } else {
- buf.WriteByte(value[len(value)-1])
- }
- ret := buf.String()
- smap.Store(name, ret)
- return ret
- }
|