
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.
104 lines
3.4 KiB
Go
104 lines
3.4 KiB
Go
package gorm
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Dialect interface contains behaviors that differ across SQL database
|
|
type Dialect interface {
|
|
// GetName get dialect's name
|
|
GetName() string
|
|
|
|
// SetDB set db for dialect
|
|
SetDB(db *sql.DB)
|
|
|
|
// BindVar return the placeholder for actual values in SQL statements, in many dbs it is "?", Postgres using $1
|
|
BindVar(i int) string
|
|
// Quote quotes field name to avoid SQL parsing exceptions by using a reserved word as a field name
|
|
Quote(key string) string
|
|
// DataTypeOf return data's sql type
|
|
DataTypeOf(field *StructField) string
|
|
|
|
// HasIndex check has index or not
|
|
HasIndex(tableName string, indexName string) bool
|
|
// HasForeignKey check has foreign key or not
|
|
HasForeignKey(tableName string, foreignKeyName string) bool
|
|
// RemoveIndex remove index
|
|
RemoveIndex(tableName string, indexName string) error
|
|
// HasTable check has table or not
|
|
HasTable(tableName string) bool
|
|
// HasColumn check has column or not
|
|
HasColumn(tableName string, columnName string) bool
|
|
|
|
// LimitAndOffsetSQL return generated SQL with Limit and Offset, as mssql has special case
|
|
LimitAndOffsetSQL(limit, offset int) string
|
|
// SelectFromDummyTable return select values, for most dbs, `SELECT values` just works, mysql needs `SELECT value FROM DUAL`
|
|
SelectFromDummyTable() string
|
|
// LastInsertIdReturningSuffix most dbs support LastInsertId, but postgres needs to use `RETURNING`
|
|
LastInsertIDReturningSuffix(tableName, columnName string) string
|
|
|
|
// BuildForeignKeyName returns a foreign key name for the given table, field and reference
|
|
BuildForeignKeyName(tableName, field, dest string) string
|
|
}
|
|
|
|
var dialectsMap = map[string]Dialect{}
|
|
|
|
func newDialect(name string, db *sql.DB) Dialect {
|
|
if value, ok := dialectsMap[name]; ok {
|
|
dialect := reflect.New(reflect.TypeOf(value).Elem()).Interface().(Dialect)
|
|
dialect.SetDB(db)
|
|
return dialect
|
|
}
|
|
|
|
fmt.Printf("`%v` is not officially supported, running under compatibility mode.\n", name)
|
|
commontDialect := &commonDialect{}
|
|
commontDialect.SetDB(db)
|
|
return commontDialect
|
|
}
|
|
|
|
// RegisterDialect register new dialect
|
|
func RegisterDialect(name string, dialect Dialect) {
|
|
dialectsMap[name] = dialect
|
|
}
|
|
|
|
// ParseFieldStructForDialect parse field struct for dialect
|
|
func ParseFieldStructForDialect(field *StructField) (fieldValue reflect.Value, sqlType string, size int, additionalType string) {
|
|
// Get redirected field type
|
|
var reflectType = field.Struct.Type
|
|
for reflectType.Kind() == reflect.Ptr {
|
|
reflectType = reflectType.Elem()
|
|
}
|
|
|
|
// Get redirected field value
|
|
fieldValue = reflect.Indirect(reflect.New(reflectType))
|
|
|
|
// Get scanner's real value
|
|
var getScannerValue func(reflect.Value)
|
|
getScannerValue = func(value reflect.Value) {
|
|
fieldValue = value
|
|
if _, isScanner := reflect.New(fieldValue.Type()).Interface().(sql.Scanner); isScanner && fieldValue.Kind() == reflect.Struct {
|
|
getScannerValue(fieldValue.Field(0))
|
|
}
|
|
}
|
|
getScannerValue(fieldValue)
|
|
|
|
// Default Size
|
|
if num, ok := field.TagSettings["SIZE"]; ok {
|
|
size, _ = strconv.Atoi(num)
|
|
} else {
|
|
size = 255
|
|
}
|
|
|
|
// Default type from tag setting
|
|
additionalType = field.TagSettings["NOT NULL"] + " " + field.TagSettings["UNIQUE"]
|
|
if value, ok := field.TagSettings["DEFAULT"]; ok {
|
|
additionalType = additionalType + " DEFAULT " + value
|
|
}
|
|
|
|
return fieldValue, field.TagSettings["TYPE"], size, strings.TrimSpace(additionalType)
|
|
}
|