gdb_model.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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. "context"
  9. "fmt"
  10. "github.com/gogf/gf/text/gregex"
  11. "time"
  12. "github.com/gogf/gf/text/gstr"
  13. )
  14. // Model is the DAO for ORM.
  15. type Model struct {
  16. db DB // Underlying DB interface.
  17. tx *TX // Underlying TX interface.
  18. schema string // Custom database schema.
  19. linkType int // Mark for operation on master or slave.
  20. tablesInit string // Table names when model initialization.
  21. tables string // Operation table names, which can be more than one table names and aliases, like: "user", "user u", "user u, user_detail ud".
  22. fields string // Operation fields, multiple fields joined using char ','.
  23. fieldsEx string // Excluded operation fields, multiple fields joined using char ','.
  24. extraArgs []interface{} // Extra custom arguments for sql.
  25. whereHolder []*whereHolder // Condition strings for where operation.
  26. groupBy string // Used for "group by" statement.
  27. orderBy string // Used for "order by" statement.
  28. having []interface{} // Used for "having..." statement.
  29. start int // Used for "select ... start, limit ..." statement.
  30. limit int // Used for "select ... start, limit ..." statement.
  31. option int // Option for extra operation features.
  32. offset int // Offset statement for some databases grammar.
  33. data interface{} // Data for operation, which can be type of map/[]map/struct/*struct/string, etc.
  34. batch int // Batch number for batch Insert/Replace/Save operations.
  35. filter bool // Filter data and where key-value pairs according to the fields of the table.
  36. lockInfo string // Lock for update or in shared lock.
  37. cacheEnabled bool // Enable sql result cache feature.
  38. cacheDuration time.Duration // Cache TTL duration.
  39. cacheName string // Cache name for custom operation.
  40. unscoped bool // Disables soft deleting features when select/delete operations.
  41. safe bool // If true, it clones and returns a new model object whenever operation done; or else it changes the attribute of current model.
  42. }
  43. // whereHolder is the holder for where condition preparing.
  44. type whereHolder struct {
  45. operator int // Operator for this holder.
  46. where interface{} // Where parameter.
  47. args []interface{} // Arguments for where parameter.
  48. }
  49. const (
  50. OPTION_OMITEMPTY = 1
  51. OPTION_ALLOWEMPTY = 2
  52. linkTypeMaster = 1
  53. linkTypeSlave = 2
  54. whereHolderWhere = 1
  55. whereHolderAnd = 2
  56. whereHolderOr = 3
  57. )
  58. // Table creates and returns a new ORM model from given schema.
  59. // The parameter <table> can be more than one table names, and also alias name, like:
  60. // 1. Table names:
  61. // Table("user")
  62. // Table("user u")
  63. // Table("user, user_detail")
  64. // Table("user u, user_detail ud")
  65. // 2. Table name with alias: Table("user", "u")
  66. func (c *Core) Table(table ...string) *Model {
  67. tables := ""
  68. if len(table) > 1 {
  69. tables = fmt.Sprintf(
  70. `%s AS %s`, c.DB.QuotePrefixTableName(table[0]), c.DB.QuoteWord(table[1]),
  71. )
  72. } else if len(table) == 1 {
  73. tables = c.DB.QuotePrefixTableName(table[0])
  74. } else {
  75. panic("table cannot be empty")
  76. }
  77. return &Model{
  78. db: c.DB,
  79. tablesInit: tables,
  80. tables: tables,
  81. fields: "*",
  82. start: -1,
  83. offset: -1,
  84. option: OPTION_ALLOWEMPTY,
  85. }
  86. }
  87. // Model is alias of Core.Table.
  88. // See Core.Table.
  89. func (c *Core) Model(table ...string) *Model {
  90. return c.DB.Table(table...)
  91. }
  92. // Table acts like Core.Table except it operates on transaction.
  93. // See Core.Table.
  94. func (tx *TX) Table(table ...string) *Model {
  95. model := tx.db.Table(table...)
  96. model.db = tx.db
  97. model.tx = tx
  98. return model
  99. }
  100. // Model is alias of tx.Table.
  101. // See tx.Table.
  102. func (tx *TX) Model(table ...string) *Model {
  103. return tx.Table(table...)
  104. }
  105. // Ctx sets the context for current operation.
  106. func (m *Model) Ctx(ctx context.Context) *Model {
  107. if ctx == nil {
  108. return m
  109. }
  110. model := m.getModel()
  111. model.db = model.db.Ctx(ctx)
  112. return model
  113. }
  114. // As sets an alias name for current table.
  115. func (m *Model) As(as string) *Model {
  116. if m.tables != "" {
  117. model := m.getModel()
  118. split := " JOIN "
  119. if gstr.Contains(model.tables, split) {
  120. // For join table.
  121. array := gstr.Split(model.tables, split)
  122. array[len(array)-1], _ = gregex.ReplaceString(`(.+) ON`, fmt.Sprintf(`$1 AS %s ON`, as), array[len(array)-1])
  123. model.tables = gstr.Join(array, split)
  124. } else {
  125. // For base table.
  126. model.tables = gstr.TrimRight(model.tables) + " AS " + as
  127. }
  128. return model
  129. }
  130. return m
  131. }
  132. // DB sets/changes the db object for current operation.
  133. func (m *Model) DB(db DB) *Model {
  134. model := m.getModel()
  135. model.db = db
  136. return model
  137. }
  138. // TX sets/changes the transaction for current operation.
  139. func (m *Model) TX(tx *TX) *Model {
  140. model := m.getModel()
  141. model.db = tx.db
  142. model.tx = tx
  143. return model
  144. }
  145. // Schema sets the schema for current operation.
  146. func (m *Model) Schema(schema string) *Model {
  147. model := m.getModel()
  148. model.schema = schema
  149. return model
  150. }
  151. // Clone creates and returns a new model which is a clone of current model.
  152. // Note that it uses deep-copy for the clone.
  153. func (m *Model) Clone() *Model {
  154. newModel := (*Model)(nil)
  155. if m.tx != nil {
  156. newModel = m.tx.Table(m.tablesInit)
  157. } else {
  158. newModel = m.db.Table(m.tablesInit)
  159. }
  160. *newModel = *m
  161. // Deep copy slice attributes.
  162. if n := len(m.extraArgs); n > 0 {
  163. newModel.extraArgs = make([]interface{}, n)
  164. copy(newModel.extraArgs, m.extraArgs)
  165. }
  166. if n := len(m.whereHolder); n > 0 {
  167. newModel.whereHolder = make([]*whereHolder, n)
  168. copy(newModel.whereHolder, m.whereHolder)
  169. }
  170. return newModel
  171. }
  172. // Master marks the following operation on master node.
  173. func (m *Model) Master() *Model {
  174. model := m.getModel()
  175. model.linkType = linkTypeMaster
  176. return model
  177. }
  178. // Slave marks the following operation on slave node.
  179. // Note that it makes sense only if there's any slave node configured.
  180. func (m *Model) Slave() *Model {
  181. model := m.getModel()
  182. model.linkType = linkTypeSlave
  183. return model
  184. }
  185. // Safe marks this model safe or unsafe. If safe is true, it clones and returns a new model object
  186. // whenever the operation done, or else it changes the attribute of current model.
  187. func (m *Model) Safe(safe ...bool) *Model {
  188. if len(safe) > 0 {
  189. m.safe = safe[0]
  190. } else {
  191. m.safe = true
  192. }
  193. return m
  194. }
  195. // Args sets custom arguments for model operation.
  196. func (m *Model) Args(args ...interface{}) *Model {
  197. model := m.getModel()
  198. model.extraArgs = append(model.extraArgs, args)
  199. return model
  200. }