dialect.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package gorm
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "reflect"
  6. "strconv"
  7. "strings"
  8. )
  9. // Dialect interface contains behaviors that differ across SQL database
  10. type Dialect interface {
  11. // GetName get dialect's name
  12. GetName() string
  13. // SetDB set db for dialect
  14. SetDB(db SQLCommon)
  15. // BindVar return the placeholder for actual values in SQL statements, in many dbs it is "?", Postgres using $1
  16. BindVar(i int) string
  17. // Quote quotes field name to avoid SQL parsing exceptions by using a reserved word as a field name
  18. Quote(key string) string
  19. // DataTypeOf return data's sql type
  20. DataTypeOf(field *StructField) string
  21. // HasIndex check has index or not
  22. HasIndex(tableName string, indexName string) bool
  23. // HasForeignKey check has foreign key or not
  24. HasForeignKey(tableName string, foreignKeyName string) bool
  25. // RemoveIndex remove index
  26. RemoveIndex(tableName string, indexName string) error
  27. // HasTable check has table or not
  28. HasTable(tableName string) bool
  29. // HasColumn check has column or not
  30. HasColumn(tableName string, columnName string) bool
  31. // ModifyColumn modify column's type
  32. ModifyColumn(tableName string, columnName string, typ string) error
  33. // LimitAndOffsetSQL return generated SQL with Limit and Offset, as mssql has special case
  34. LimitAndOffsetSQL(limit, offset interface{}) string
  35. // SelectFromDummyTable return select values, for most dbs, `SELECT values` just works, mysql needs `SELECT value FROM DUAL`
  36. SelectFromDummyTable() string
  37. // LastInsertIdReturningSuffix most dbs support LastInsertId, but postgres needs to use `RETURNING`
  38. LastInsertIDReturningSuffix(tableName, columnName string) string
  39. // DefaultValueStr
  40. DefaultValueStr() string
  41. // BuildKeyName returns a valid key name (foreign key, index key) for the given table, field and reference
  42. BuildKeyName(kind, tableName string, fields ...string) string
  43. // CurrentDatabase return current database name
  44. CurrentDatabase() string
  45. }
  46. var dialectsMap = map[string]Dialect{}
  47. func newDialect(name string, db SQLCommon) Dialect {
  48. if value, ok := dialectsMap[name]; ok {
  49. dialect := reflect.New(reflect.TypeOf(value).Elem()).Interface().(Dialect)
  50. dialect.SetDB(db)
  51. return dialect
  52. }
  53. fmt.Printf("`%v` is not officially supported, running under compatibility mode.\n", name)
  54. commontDialect := &commonDialect{}
  55. commontDialect.SetDB(db)
  56. return commontDialect
  57. }
  58. // RegisterDialect register new dialect
  59. func RegisterDialect(name string, dialect Dialect) {
  60. dialectsMap[name] = dialect
  61. }
  62. // ParseFieldStructForDialect get field's sql data type
  63. var ParseFieldStructForDialect = func(field *StructField, dialect Dialect) (fieldValue reflect.Value, sqlType string, size int, additionalType string) {
  64. // Get redirected field type
  65. var (
  66. reflectType = field.Struct.Type
  67. dataType = field.TagSettings["TYPE"]
  68. )
  69. for reflectType.Kind() == reflect.Ptr {
  70. reflectType = reflectType.Elem()
  71. }
  72. // Get redirected field value
  73. fieldValue = reflect.Indirect(reflect.New(reflectType))
  74. if gormDataType, ok := fieldValue.Interface().(interface {
  75. GormDataType(Dialect) string
  76. }); ok {
  77. dataType = gormDataType.GormDataType(dialect)
  78. }
  79. // Get scanner's real value
  80. if dataType == "" {
  81. var getScannerValue func(reflect.Value)
  82. getScannerValue = func(value reflect.Value) {
  83. fieldValue = value
  84. if _, isScanner := reflect.New(fieldValue.Type()).Interface().(sql.Scanner); isScanner && fieldValue.Kind() == reflect.Struct {
  85. getScannerValue(fieldValue.Field(0))
  86. }
  87. }
  88. getScannerValue(fieldValue)
  89. }
  90. // Default Size
  91. if num, ok := field.TagSettings["SIZE"]; ok {
  92. size, _ = strconv.Atoi(num)
  93. } else {
  94. size = 255
  95. }
  96. // Default type from tag setting
  97. additionalType = field.TagSettings["NOT NULL"] + " " + field.TagSettings["UNIQUE"]
  98. if value, ok := field.TagSettings["DEFAULT"]; ok {
  99. additionalType = additionalType + " DEFAULT " + value
  100. }
  101. return fieldValue, dataType, size, strings.TrimSpace(additionalType)
  102. }
  103. func currentDatabaseAndTable(dialect Dialect, tableName string) (string, string) {
  104. if strings.Contains(tableName, ".") {
  105. splitStrings := strings.SplitN(tableName, ".", 2)
  106. return splitStrings[0], splitStrings[1]
  107. }
  108. return dialect.CurrentDatabase(), tableName
  109. }