gdb_model_insert.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. "github.com/gogf/gf/errors/gerror"
  10. "github.com/gogf/gf/os/gtime"
  11. "github.com/gogf/gf/text/gstr"
  12. "github.com/gogf/gf/util/gconv"
  13. "github.com/gogf/gf/util/gutil"
  14. "reflect"
  15. )
  16. // Batch sets the batch operation number for the model.
  17. func (m *Model) Batch(batch int) *Model {
  18. model := m.getModel()
  19. model.batch = batch
  20. return model
  21. }
  22. // Data sets the operation data for the model.
  23. // The parameter <data> can be type of string/map/gmap/slice/struct/*struct, etc.
  24. // Note that, it uses shallow value copying for `data` if `data` is type of map/slice
  25. // to avoid changing it inside function.
  26. // Eg:
  27. // Data("uid=10000")
  28. // Data("uid", 10000)
  29. // Data("uid=? AND name=?", 10000, "john")
  30. // Data(g.Map{"uid": 10000, "name":"john"})
  31. // Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
  32. func (m *Model) Data(data ...interface{}) *Model {
  33. model := m.getModel()
  34. if len(data) > 1 {
  35. if s := gconv.String(data[0]); gstr.Contains(s, "?") {
  36. model.data = s
  37. model.extraArgs = data[1:]
  38. } else {
  39. m := make(map[string]interface{})
  40. for i := 0; i < len(data); i += 2 {
  41. m[gconv.String(data[i])] = data[i+1]
  42. }
  43. model.data = m
  44. }
  45. } else {
  46. switch params := data[0].(type) {
  47. case Result:
  48. model.data = params.List()
  49. case Record:
  50. model.data = params.Map()
  51. case List:
  52. list := make(List, len(params))
  53. for k, v := range params {
  54. list[k] = gutil.MapCopy(v)
  55. }
  56. model.data = list
  57. case Map:
  58. model.data = gutil.MapCopy(params)
  59. default:
  60. var (
  61. rv = reflect.ValueOf(params)
  62. kind = rv.Kind()
  63. )
  64. if kind == reflect.Ptr {
  65. rv = rv.Elem()
  66. kind = rv.Kind()
  67. }
  68. switch kind {
  69. case reflect.Slice, reflect.Array:
  70. list := make(List, rv.Len())
  71. for i := 0; i < rv.Len(); i++ {
  72. list[i] = ConvertDataForTableRecord(rv.Index(i).Interface())
  73. }
  74. model.data = list
  75. case reflect.Map:
  76. model.data = ConvertDataForTableRecord(data[0])
  77. case reflect.Struct:
  78. if v, ok := data[0].(apiInterfaces); ok {
  79. var (
  80. array = v.Interfaces()
  81. list = make(List, len(array))
  82. )
  83. for i := 0; i < len(array); i++ {
  84. list[i] = ConvertDataForTableRecord(array[i])
  85. }
  86. model.data = list
  87. } else {
  88. model.data = ConvertDataForTableRecord(data[0])
  89. }
  90. default:
  91. model.data = data[0]
  92. }
  93. }
  94. }
  95. return model
  96. }
  97. // Insert does "INSERT INTO ..." statement for the model.
  98. // The optional parameter <data> is the same as the parameter of Model.Data function,
  99. // see Model.Data.
  100. func (m *Model) Insert(data ...interface{}) (result sql.Result, err error) {
  101. if len(data) > 0 {
  102. return m.Data(data...).Insert()
  103. }
  104. return m.doInsertWithOption(insertOptionDefault)
  105. }
  106. // InsertIgnore does "INSERT IGNORE INTO ..." statement for the model.
  107. // The optional parameter <data> is the same as the parameter of Model.Data function,
  108. // see Model.Data.
  109. func (m *Model) InsertIgnore(data ...interface{}) (result sql.Result, err error) {
  110. if len(data) > 0 {
  111. return m.Data(data...).InsertIgnore()
  112. }
  113. return m.doInsertWithOption(insertOptionIgnore)
  114. }
  115. // Replace does "REPLACE INTO ..." statement for the model.
  116. // The optional parameter <data> is the same as the parameter of Model.Data function,
  117. // see Model.Data.
  118. func (m *Model) Replace(data ...interface{}) (result sql.Result, err error) {
  119. if len(data) > 0 {
  120. return m.Data(data...).Replace()
  121. }
  122. return m.doInsertWithOption(insertOptionReplace)
  123. }
  124. // Save does "INSERT INTO ... ON DUPLICATE KEY UPDATE..." statement for the model.
  125. // The optional parameter <data> is the same as the parameter of Model.Data function,
  126. // see Model.Data.
  127. //
  128. // It updates the record if there's primary or unique index in the saving data,
  129. // or else it inserts a new record into the table.
  130. func (m *Model) Save(data ...interface{}) (result sql.Result, err error) {
  131. if len(data) > 0 {
  132. return m.Data(data...).Save()
  133. }
  134. return m.doInsertWithOption(insertOptionSave)
  135. }
  136. // doInsertWithOption inserts data with option parameter.
  137. func (m *Model) doInsertWithOption(option int) (result sql.Result, err error) {
  138. defer func() {
  139. if err == nil {
  140. m.checkAndRemoveCache()
  141. }
  142. }()
  143. if m.data == nil {
  144. return nil, gerror.New("inserting into table with empty data")
  145. }
  146. var (
  147. nowString = gtime.Now().String()
  148. fieldNameCreate = m.getSoftFieldNameCreated()
  149. fieldNameUpdate = m.getSoftFieldNameUpdated()
  150. fieldNameDelete = m.getSoftFieldNameDeleted()
  151. )
  152. // Batch operation.
  153. if list, ok := m.data.(List); ok {
  154. batch := defaultBatchNumber
  155. if m.batch > 0 {
  156. batch = m.batch
  157. }
  158. // Automatic handling for creating/updating time.
  159. if !m.unscoped && (fieldNameCreate != "" || fieldNameUpdate != "") {
  160. for k, v := range list {
  161. gutil.MapDelete(v, fieldNameCreate, fieldNameUpdate, fieldNameDelete)
  162. if fieldNameCreate != "" {
  163. v[fieldNameCreate] = nowString
  164. }
  165. if fieldNameUpdate != "" {
  166. v[fieldNameUpdate] = nowString
  167. }
  168. list[k] = v
  169. }
  170. }
  171. newData, err := m.filterDataForInsertOrUpdate(list)
  172. if err != nil {
  173. return nil, err
  174. }
  175. return m.db.DoBatchInsert(
  176. m.getLink(true),
  177. m.tables,
  178. newData,
  179. option,
  180. batch,
  181. )
  182. }
  183. // Single operation.
  184. if data, ok := m.data.(Map); ok {
  185. // Automatic handling for creating/updating time.
  186. if !m.unscoped && (fieldNameCreate != "" || fieldNameUpdate != "") {
  187. gutil.MapDelete(data, fieldNameCreate, fieldNameUpdate, fieldNameDelete)
  188. if fieldNameCreate != "" {
  189. data[fieldNameCreate] = nowString
  190. }
  191. if fieldNameUpdate != "" {
  192. data[fieldNameUpdate] = nowString
  193. }
  194. }
  195. newData, err := m.filterDataForInsertOrUpdate(data)
  196. if err != nil {
  197. return nil, err
  198. }
  199. return m.db.DoInsert(
  200. m.getLink(true),
  201. m.tables,
  202. newData,
  203. option,
  204. )
  205. }
  206. return nil, gerror.New("inserting into table with invalid data type")
  207. }