gdb_driver_mysql.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Copyright GoFrame Author(https://github.com/gogf/gf). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package gdb
  7. import (
  8. "database/sql"
  9. "fmt"
  10. "github.com/gogf/gf/errors/gerror"
  11. "github.com/gogf/gf/internal/intlog"
  12. "github.com/gogf/gf/text/gregex"
  13. "github.com/gogf/gf/text/gstr"
  14. _ "github.com/go-sql-driver/mysql"
  15. )
  16. // DriverMysql is the driver for mysql database.
  17. type DriverMysql struct {
  18. *Core
  19. }
  20. // New creates and returns a database object for mysql.
  21. // It implements the interface of gdb.Driver for extra database driver installation.
  22. func (d *DriverMysql) New(core *Core, node *ConfigNode) (DB, error) {
  23. return &DriverMysql{
  24. Core: core,
  25. }, nil
  26. }
  27. // Open creates and returns a underlying sql.DB object for mysql.
  28. // Note that it converts time.Time argument to local timezone in default.
  29. func (d *DriverMysql) Open(config *ConfigNode) (*sql.DB, error) {
  30. var source string
  31. if config.LinkInfo != "" {
  32. source = config.LinkInfo
  33. // Custom changing the schema in runtime.
  34. if config.Name != "" {
  35. source, _ = gregex.ReplaceString(`/([\w\.\-]+)+`, "/"+config.Name, source)
  36. }
  37. } else {
  38. source = fmt.Sprintf(
  39. "%s:%s@tcp(%s:%s)/%s?charset=%s&multiStatements=true&parseTime=true",
  40. config.User, config.Pass, config.Host, config.Port, config.Name, config.Charset,
  41. )
  42. }
  43. intlog.Printf("Open: %s", source)
  44. if db, err := sql.Open("mysql", source); err == nil {
  45. return db, nil
  46. } else {
  47. return nil, err
  48. }
  49. }
  50. // GetChars returns the security char for this type of database.
  51. func (d *DriverMysql) GetChars() (charLeft string, charRight string) {
  52. return "`", "`"
  53. }
  54. // HandleSqlBeforeCommit handles the sql before posts it to database.
  55. func (d *DriverMysql) HandleSqlBeforeCommit(link Link, sql string, args []interface{}) (string, []interface{}) {
  56. return sql, args
  57. }
  58. // Tables retrieves and returns the tables of current schema.
  59. // It's mainly used in cli tool chain for automatically generating the models.
  60. func (d *DriverMysql) Tables(schema ...string) (tables []string, err error) {
  61. var result Result
  62. link, err := d.DB.GetSlave(schema...)
  63. if err != nil {
  64. return nil, err
  65. }
  66. result, err = d.DB.DoGetAll(link, `SHOW TABLES`)
  67. if err != nil {
  68. return
  69. }
  70. for _, m := range result {
  71. for _, v := range m {
  72. tables = append(tables, v.String())
  73. }
  74. }
  75. return
  76. }
  77. // TableFields retrieves and returns the fields information of specified table of current
  78. // schema.
  79. //
  80. // Note that it returns a map containing the field name and its corresponding fields.
  81. // As a map is unsorted, the TableField struct has a "Index" field marks its sequence in
  82. // the fields.
  83. //
  84. // It's using cache feature to enhance the performance, which is never expired util the
  85. // process restarts.
  86. func (d *DriverMysql) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) {
  87. charL, charR := d.GetChars()
  88. table = gstr.Trim(table, charL+charR)
  89. if gstr.Contains(table, " ") {
  90. return nil, gerror.New("function TableFields supports only single table operations")
  91. }
  92. checkSchema := d.schema.Val()
  93. if len(schema) > 0 && schema[0] != "" {
  94. checkSchema = schema[0]
  95. }
  96. v, _ := internalCache.GetOrSetFunc(
  97. fmt.Sprintf(`mysql_table_fields_%s_%s@group:%s`, table, checkSchema, d.GetGroup()),
  98. func() (interface{}, error) {
  99. var (
  100. result Result
  101. link *sql.DB
  102. )
  103. link, err = d.DB.GetSlave(checkSchema)
  104. if err != nil {
  105. return nil, err
  106. }
  107. result, err = d.DB.DoGetAll(
  108. link,
  109. fmt.Sprintf(`SHOW FULL COLUMNS FROM %s`, d.DB.QuoteWord(table)),
  110. )
  111. if err != nil {
  112. return nil, err
  113. }
  114. fields = make(map[string]*TableField)
  115. for i, m := range result {
  116. fields[m["Field"].String()] = &TableField{
  117. Index: i,
  118. Name: m["Field"].String(),
  119. Type: m["Type"].String(),
  120. Null: m["Null"].Bool(),
  121. Key: m["Key"].String(),
  122. Default: m["Default"].Val(),
  123. Extra: m["Extra"].String(),
  124. Comment: m["Comment"].String(),
  125. }
  126. }
  127. return fields, nil
  128. }, 0)
  129. if err == nil {
  130. fields = v.(map[string]*TableField)
  131. }
  132. return
  133. }