mysql_dialect.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package migrator
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. "github.com/VividCortex/mysqlerr"
  7. "github.com/go-sql-driver/mysql"
  8. "github.com/go-xorm/xorm"
  9. )
  10. type Mysql struct {
  11. BaseDialect
  12. }
  13. func NewMysqlDialect(engine *xorm.Engine) *Mysql {
  14. d := Mysql{}
  15. d.BaseDialect.dialect = &d
  16. d.BaseDialect.engine = engine
  17. d.BaseDialect.driverName = MYSQL
  18. return &d
  19. }
  20. func (db *Mysql) SupportEngine() bool {
  21. return true
  22. }
  23. func (db *Mysql) Quote(name string) string {
  24. return "`" + name + "`"
  25. }
  26. func (db *Mysql) AutoIncrStr() string {
  27. return "AUTO_INCREMENT"
  28. }
  29. func (db *Mysql) BooleanStr(value bool) string {
  30. if value {
  31. return "1"
  32. }
  33. return "0"
  34. }
  35. func (db *Mysql) SqlType(c *Column) string {
  36. var res string
  37. switch c.Type {
  38. case DB_Bool:
  39. res = DB_TinyInt
  40. c.Length = 1
  41. case DB_Serial:
  42. c.IsAutoIncrement = true
  43. c.IsPrimaryKey = true
  44. c.Nullable = false
  45. res = DB_Int
  46. case DB_BigSerial:
  47. c.IsAutoIncrement = true
  48. c.IsPrimaryKey = true
  49. c.Nullable = false
  50. res = DB_BigInt
  51. case DB_Bytea:
  52. res = DB_Blob
  53. case DB_TimeStampz:
  54. res = DB_Char
  55. c.Length = 64
  56. case DB_NVarchar:
  57. res = DB_Varchar
  58. default:
  59. res = c.Type
  60. }
  61. var hasLen1 = (c.Length > 0)
  62. var hasLen2 = (c.Length2 > 0)
  63. if res == DB_BigInt && !hasLen1 && !hasLen2 {
  64. c.Length = 20
  65. hasLen1 = true
  66. }
  67. if hasLen2 {
  68. res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
  69. } else if hasLen1 {
  70. res += "(" + strconv.Itoa(c.Length) + ")"
  71. }
  72. switch c.Type {
  73. case DB_Char, DB_Varchar, DB_NVarchar, DB_TinyText, DB_Text, DB_MediumText, DB_LongText:
  74. res += " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
  75. }
  76. return res
  77. }
  78. func (db *Mysql) UpdateTableSql(tableName string, columns []*Column) string {
  79. var statements = []string{}
  80. statements = append(statements, "DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci")
  81. for _, col := range columns {
  82. statements = append(statements, "MODIFY "+col.StringNoPk(db))
  83. }
  84. return "ALTER TABLE " + db.Quote(tableName) + " " + strings.Join(statements, ", ") + ";"
  85. }
  86. func (db *Mysql) IndexCheckSql(tableName, indexName string) (string, []interface{}) {
  87. args := []interface{}{tableName, indexName}
  88. sql := "SELECT 1 FROM " + db.Quote("INFORMATION_SCHEMA") + "." + db.Quote("STATISTICS") + " WHERE " + db.Quote("TABLE_SCHEMA") + " = DATABASE() AND " + db.Quote("TABLE_NAME") + "=? AND " + db.Quote("INDEX_NAME") + "=?"
  89. return sql, args
  90. }
  91. func (db *Mysql) ColumnCheckSql(tableName, columnName string) (string, []interface{}) {
  92. args := []interface{}{tableName, columnName}
  93. sql := "SELECT 1 FROM " + db.Quote("INFORMATION_SCHEMA") + "." + db.Quote("COLUMNS") + " WHERE " + db.Quote("TABLE_SCHEMA") + " = DATABASE() AND " + db.Quote("TABLE_NAME") + "=? AND " + db.Quote("COLUMN_NAME") + "=?"
  94. return sql, args
  95. }
  96. func (db *Mysql) CleanDB() error {
  97. tables, _ := db.engine.DBMetas()
  98. sess := db.engine.NewSession()
  99. defer sess.Close()
  100. for _, table := range tables {
  101. if _, err := sess.Exec("set foreign_key_checks = 0"); err != nil {
  102. return fmt.Errorf("failed to disable foreign key checks")
  103. }
  104. if _, err := sess.Exec("drop table " + table.Name + " ;"); err != nil {
  105. return fmt.Errorf("failed to delete table: %v, err: %v", table.Name, err)
  106. }
  107. if _, err := sess.Exec("set foreign_key_checks = 1"); err != nil {
  108. return fmt.Errorf("failed to disable foreign key checks")
  109. }
  110. }
  111. return nil
  112. }
  113. func (db *Mysql) isThisError(err error, errcode uint16) bool {
  114. if driverErr, ok := err.(*mysql.MySQLError); ok {
  115. if driverErr.Number == errcode {
  116. return true
  117. }
  118. }
  119. return false
  120. }
  121. func (db *Mysql) IsUniqueConstraintViolation(err error) bool {
  122. return db.isThisError(err, mysqlerr.ER_DUP_ENTRY)
  123. }
  124. func (db *Mysql) IsDeadlock(err error) bool {
  125. return db.isThisError(err, mysqlerr.ER_LOCK_DEADLOCK)
  126. }