
The dialect must define its own foreign key generator method. The previous default is available as a method on gorm.DefaultForeignKeyNamer and can be embedded in other dialects. The mysql dialect uses the first 24 characters plus an sha1 hash of the full key name if the key name is more than 64 characters.
150 lines
3.9 KiB
Go
150 lines
3.9 KiB
Go
package gorm
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"reflect"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// DefaultForeignKeyNamer contains the default foreign key name generator method
|
|
type DefaultForeignKeyNamer struct {
|
|
}
|
|
|
|
type commonDialect struct {
|
|
db *sql.DB
|
|
DefaultForeignKeyNamer
|
|
}
|
|
|
|
func init() {
|
|
RegisterDialect("common", &commonDialect{})
|
|
}
|
|
|
|
func (commonDialect) GetName() string {
|
|
return "common"
|
|
}
|
|
|
|
func (s *commonDialect) SetDB(db *sql.DB) {
|
|
s.db = db
|
|
}
|
|
|
|
func (commonDialect) BindVar(i int) string {
|
|
return "$$" // ?
|
|
}
|
|
|
|
func (commonDialect) Quote(key string) string {
|
|
return fmt.Sprintf(`"%s"`, key)
|
|
}
|
|
|
|
func (commonDialect) DataTypeOf(field *StructField) string {
|
|
var dataValue, sqlType, size, additionalType = ParseFieldStructForDialect(field)
|
|
|
|
if sqlType == "" {
|
|
switch dataValue.Kind() {
|
|
case reflect.Bool:
|
|
sqlType = "BOOLEAN"
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr:
|
|
if _, ok := field.TagSettings["AUTO_INCREMENT"]; ok {
|
|
sqlType = "INTEGER AUTO_INCREMENT"
|
|
} else {
|
|
sqlType = "INTEGER"
|
|
}
|
|
case reflect.Int64, reflect.Uint64:
|
|
if _, ok := field.TagSettings["AUTO_INCREMENT"]; ok {
|
|
sqlType = "BIGINT AUTO_INCREMENT"
|
|
} else {
|
|
sqlType = "BIGINT"
|
|
}
|
|
case reflect.Float32, reflect.Float64:
|
|
sqlType = "FLOAT"
|
|
case reflect.String:
|
|
if size > 0 && size < 65532 {
|
|
sqlType = fmt.Sprintf("VARCHAR(%d)", size)
|
|
} else {
|
|
sqlType = "VARCHAR(65532)"
|
|
}
|
|
case reflect.Struct:
|
|
if _, ok := dataValue.Interface().(time.Time); ok {
|
|
sqlType = "TIMESTAMP"
|
|
}
|
|
default:
|
|
if _, ok := dataValue.Interface().([]byte); ok {
|
|
if size > 0 && size < 65532 {
|
|
sqlType = fmt.Sprintf("BINARY(%d)", size)
|
|
} else {
|
|
sqlType = "BINARY(65532)"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if sqlType == "" {
|
|
panic(fmt.Sprintf("invalid sql type %s (%s) for commonDialect", dataValue.Type().Name(), dataValue.Kind().String()))
|
|
}
|
|
|
|
if strings.TrimSpace(additionalType) == "" {
|
|
return sqlType
|
|
}
|
|
return fmt.Sprintf("%v %v", sqlType, additionalType)
|
|
}
|
|
|
|
func (s commonDialect) HasIndex(tableName string, indexName string) bool {
|
|
var count int
|
|
s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema = ? AND table_name = ? AND index_name = ?", s.currentDatabase(), tableName, indexName).Scan(&count)
|
|
return count > 0
|
|
}
|
|
|
|
func (s commonDialect) RemoveIndex(tableName string, indexName string) error {
|
|
_, err := s.db.Exec(fmt.Sprintf("DROP INDEX %v", indexName))
|
|
return err
|
|
}
|
|
|
|
func (s commonDialect) HasForeignKey(tableName string, foreignKeyName string) bool {
|
|
return false
|
|
}
|
|
|
|
func (s commonDialect) HasTable(tableName string) bool {
|
|
var count int
|
|
s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = ? AND table_name = ?", s.currentDatabase(), tableName).Scan(&count)
|
|
return count > 0
|
|
}
|
|
|
|
func (s commonDialect) HasColumn(tableName string, columnName string) bool {
|
|
var count int
|
|
s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = ? AND table_name = ? AND column_name = ?", s.currentDatabase(), tableName, columnName).Scan(&count)
|
|
return count > 0
|
|
}
|
|
|
|
func (s commonDialect) currentDatabase() (name string) {
|
|
s.db.QueryRow("SELECT DATABASE()").Scan(&name)
|
|
return
|
|
}
|
|
|
|
func (commonDialect) LimitAndOffsetSQL(limit, offset int) (sql string) {
|
|
if limit > 0 || offset > 0 {
|
|
if limit >= 0 {
|
|
sql += fmt.Sprintf(" LIMIT %d", limit)
|
|
}
|
|
if offset >= 0 {
|
|
sql += fmt.Sprintf(" OFFSET %d", offset)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (commonDialect) SelectFromDummyTable() string {
|
|
return ""
|
|
}
|
|
|
|
func (commonDialect) LastInsertIDReturningSuffix(tableName, columnName string) string {
|
|
return ""
|
|
}
|
|
|
|
func (DefaultForeignKeyNamer) BuildForeignKeyName(tableName, field, dest string) string {
|
|
keyName := fmt.Sprintf("%s_%s_%s_foreign", tableName, field, dest)
|
|
keyName = regexp.MustCompile("(_*[^a-zA-Z]+_*|_+)").ReplaceAllString(keyName, "_")
|
|
return keyName
|
|
}
|