mirror of https://github.com/go-gorm/gorm.git
125 lines
2.6 KiB
Go
125 lines
2.6 KiB
Go
|
package gorm
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// Namer is a function type which is given a string and return a string
|
||
|
type Namer func(string) string
|
||
|
|
||
|
// NamingStrategy represents naming strategies
|
||
|
type NamingStrategy struct {
|
||
|
DB Namer
|
||
|
Table Namer
|
||
|
Column Namer
|
||
|
}
|
||
|
|
||
|
// TheNamingStrategy is being initialized with defaultNamingStrategy
|
||
|
var TheNamingStrategy = &NamingStrategy{
|
||
|
DB: defaultNamer,
|
||
|
Table: defaultNamer,
|
||
|
Column: defaultNamer,
|
||
|
}
|
||
|
|
||
|
// AddNamingStrategy sets the naming strategy
|
||
|
func AddNamingStrategy(ns *NamingStrategy) {
|
||
|
if ns.DB == nil {
|
||
|
ns.DB = defaultNamer
|
||
|
}
|
||
|
if ns.Table == nil {
|
||
|
ns.Table = defaultNamer
|
||
|
}
|
||
|
if ns.Column == nil {
|
||
|
ns.Column = defaultNamer
|
||
|
}
|
||
|
TheNamingStrategy = ns
|
||
|
}
|
||
|
|
||
|
// DBName alters the given name by DB
|
||
|
func (ns *NamingStrategy) DBName(name string) string {
|
||
|
return ns.DB(name)
|
||
|
}
|
||
|
|
||
|
// TableName alters the given name by Table
|
||
|
func (ns *NamingStrategy) TableName(name string) string {
|
||
|
return ns.Table(name)
|
||
|
}
|
||
|
|
||
|
// ColumnName alters the given name by Column
|
||
|
func (ns *NamingStrategy) ColumnName(name string) string {
|
||
|
return ns.Column(name)
|
||
|
}
|
||
|
|
||
|
// ToDBName convert string to db name
|
||
|
func ToDBName(name string) string {
|
||
|
return TheNamingStrategy.DBName(name)
|
||
|
}
|
||
|
|
||
|
// ToTableName convert string to table name
|
||
|
func ToTableName(name string) string {
|
||
|
return TheNamingStrategy.TableName(name)
|
||
|
}
|
||
|
|
||
|
// ToColumnName convert string to db name
|
||
|
func ToColumnName(name string) string {
|
||
|
return TheNamingStrategy.ColumnName(name)
|
||
|
}
|
||
|
|
||
|
var smap = newSafeMap()
|
||
|
|
||
|
func defaultNamer(name string) string {
|
||
|
const (
|
||
|
lower = false
|
||
|
upper = true
|
||
|
)
|
||
|
|
||
|
if v := smap.Get(name); v != "" {
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
if name == "" {
|
||
|
return ""
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
value = commonInitialismsReplacer.Replace(name)
|
||
|
buf = bytes.NewBufferString("")
|
||
|
lastCase, currCase, nextCase, nextNumber bool
|
||
|
)
|
||
|
|
||
|
for i, v := range value[:len(value)-1] {
|
||
|
nextCase = bool(value[i+1] >= 'A' && value[i+1] <= 'Z')
|
||
|
nextNumber = bool(value[i+1] >= '0' && value[i+1] <= '9')
|
||
|
|
||
|
if i > 0 {
|
||
|
if currCase == upper {
|
||
|
if lastCase == upper && (nextCase == upper || nextNumber == upper) {
|
||
|
buf.WriteRune(v)
|
||
|
} else {
|
||
|
if value[i-1] != '_' && value[i+1] != '_' {
|
||
|
buf.WriteRune('_')
|
||
|
}
|
||
|
buf.WriteRune(v)
|
||
|
}
|
||
|
} else {
|
||
|
buf.WriteRune(v)
|
||
|
if i == len(value)-2 && (nextCase == upper && nextNumber == lower) {
|
||
|
buf.WriteRune('_')
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
currCase = upper
|
||
|
buf.WriteRune(v)
|
||
|
}
|
||
|
lastCase = currCase
|
||
|
currCase = nextCase
|
||
|
}
|
||
|
|
||
|
buf.WriteByte(value[len(value)-1])
|
||
|
|
||
|
s := strings.ToLower(buf.String())
|
||
|
smap.Set(name, s)
|
||
|
return s
|
||
|
}
|