gdb_model_utility.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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. "fmt"
  9. "github.com/gogf/gf/container/gset"
  10. "github.com/gogf/gf/internal/empty"
  11. "github.com/gogf/gf/os/gtime"
  12. "github.com/gogf/gf/text/gregex"
  13. "github.com/gogf/gf/text/gstr"
  14. "github.com/gogf/gf/util/gconv"
  15. "github.com/gogf/gf/util/gutil"
  16. "time"
  17. )
  18. // getModel creates and returns a cloned model of current model if <safe> is true, or else it returns
  19. // the current model.
  20. func (m *Model) getModel() *Model {
  21. if !m.safe {
  22. return m
  23. } else {
  24. return m.Clone()
  25. }
  26. }
  27. // mappingAndFilterToTableFields mappings and changes given field name to really table field name.
  28. func (m *Model) mappingAndFilterToTableFields(fields []string) []string {
  29. fieldsMap, err := m.db.TableFields(m.tables)
  30. if err != nil || len(fieldsMap) == 0 {
  31. return fields
  32. }
  33. var (
  34. inputFieldsArray = gstr.SplitAndTrim(gstr.Join(fields, ","), ",")
  35. outputFieldsArray = make([]string, 0, len(inputFieldsArray))
  36. )
  37. fieldsKeyMap := make(map[string]interface{}, len(fieldsMap))
  38. for k, _ := range fieldsMap {
  39. fieldsKeyMap[k] = nil
  40. }
  41. for _, field := range inputFieldsArray {
  42. if _, ok := fieldsKeyMap[field]; !ok {
  43. if !gregex.IsMatchString(regularFieldNameRegPattern, field) {
  44. outputFieldsArray = append(outputFieldsArray, field)
  45. continue
  46. } else {
  47. if foundKey, _ := gutil.MapPossibleItemByKey(fieldsKeyMap, field); foundKey != "" {
  48. outputFieldsArray = append(outputFieldsArray, foundKey)
  49. }
  50. }
  51. } else {
  52. outputFieldsArray = append(outputFieldsArray, field)
  53. }
  54. }
  55. return outputFieldsArray
  56. }
  57. // filterDataForInsertOrUpdate does filter feature with data for inserting/updating operations.
  58. // Note that, it does not filter list item, which is also type of map, for "omit empty" feature.
  59. func (m *Model) filterDataForInsertOrUpdate(data interface{}) (interface{}, error) {
  60. var err error
  61. switch value := data.(type) {
  62. case List:
  63. for k, item := range value {
  64. value[k], err = m.doMappingAndFilterForInsertOrUpdateDataMap(item, false)
  65. if err != nil {
  66. return nil, err
  67. }
  68. }
  69. return value, nil
  70. case Map:
  71. return m.doMappingAndFilterForInsertOrUpdateDataMap(value, true)
  72. default:
  73. return data, nil
  74. }
  75. }
  76. // doMappingAndFilterForInsertOrUpdateDataMap does the filter features for map.
  77. // Note that, it does not filter list item, which is also type of map, for "omit empty" feature.
  78. func (m *Model) doMappingAndFilterForInsertOrUpdateDataMap(data Map, allowOmitEmpty bool) (Map, error) {
  79. var err error
  80. data, err = m.db.mappingAndFilterData(m.schema, m.tables, data, m.filter)
  81. if err != nil {
  82. return nil, err
  83. }
  84. // Remove key-value pairs of which the value is empty.
  85. if allowOmitEmpty && m.option&OPTION_OMITEMPTY > 0 {
  86. tempMap := make(Map, len(data))
  87. for k, v := range data {
  88. if empty.IsEmpty(v) {
  89. continue
  90. }
  91. // Special type filtering.
  92. switch r := v.(type) {
  93. case time.Time:
  94. if r.IsZero() {
  95. continue
  96. }
  97. case *time.Time:
  98. if r.IsZero() {
  99. continue
  100. }
  101. case gtime.Time:
  102. if r.IsZero() {
  103. continue
  104. }
  105. case *gtime.Time:
  106. if r.IsZero() {
  107. continue
  108. }
  109. }
  110. tempMap[k] = v
  111. }
  112. data = tempMap
  113. }
  114. if len(m.fields) > 0 && m.fields != "*" {
  115. // Keep specified fields.
  116. var (
  117. set = gset.NewStrSetFrom(gstr.SplitAndTrim(m.fields, ","))
  118. charL, charR = m.db.GetChars()
  119. chars = charL + charR
  120. )
  121. set.Walk(func(item string) string {
  122. return gstr.Trim(item, chars)
  123. })
  124. for k := range data {
  125. k = gstr.Trim(k, chars)
  126. if !set.Contains(k) {
  127. delete(data, k)
  128. }
  129. }
  130. } else if len(m.fieldsEx) > 0 {
  131. // Filter specified fields.
  132. for _, v := range gstr.SplitAndTrim(m.fieldsEx, ",") {
  133. delete(data, v)
  134. }
  135. }
  136. return data, nil
  137. }
  138. // getLink returns the underlying database link object with configured <linkType> attribute.
  139. // The parameter <master> specifies whether using the master node if master-slave configured.
  140. func (m *Model) getLink(master bool) Link {
  141. if m.tx != nil {
  142. return m.tx.tx
  143. }
  144. linkType := m.linkType
  145. if linkType == 0 {
  146. if master {
  147. linkType = linkTypeMaster
  148. } else {
  149. linkType = linkTypeSlave
  150. }
  151. }
  152. switch linkType {
  153. case linkTypeMaster:
  154. link, err := m.db.GetMaster(m.schema)
  155. if err != nil {
  156. panic(err)
  157. }
  158. return link
  159. case linkTypeSlave:
  160. link, err := m.db.GetSlave(m.schema)
  161. if err != nil {
  162. panic(err)
  163. }
  164. return link
  165. }
  166. return nil
  167. }
  168. // getPrimaryKey retrieves and returns the primary key name of the model table.
  169. // It parses m.tables to retrieve the primary table name, supporting m.tables like:
  170. // "user", "user u", "user as u, user_detail as ud".
  171. func (m *Model) getPrimaryKey() string {
  172. table := gstr.SplitAndTrim(m.tables, " ")[0]
  173. tableFields, err := m.db.TableFields(table)
  174. if err != nil {
  175. return ""
  176. }
  177. for name, field := range tableFields {
  178. if gstr.ContainsI(field.Key, "pri") {
  179. return name
  180. }
  181. }
  182. return ""
  183. }
  184. // formatCondition formats where arguments of the model and returns a new condition sql and its arguments.
  185. // Note that this function does not change any attribute value of the <m>.
  186. //
  187. // The parameter <limit1> specifies whether limits querying only one record if m.limit is not set.
  188. func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWhere string, conditionExtra string, conditionArgs []interface{}) {
  189. if len(m.whereHolder) > 0 {
  190. for _, v := range m.whereHolder {
  191. switch v.operator {
  192. case whereHolderWhere:
  193. if conditionWhere == "" {
  194. newWhere, newArgs := formatWhere(
  195. m.db, v.where, v.args, m.option&OPTION_OMITEMPTY > 0,
  196. )
  197. if len(newWhere) > 0 {
  198. conditionWhere = newWhere
  199. conditionArgs = newArgs
  200. }
  201. continue
  202. }
  203. fallthrough
  204. case whereHolderAnd:
  205. newWhere, newArgs := formatWhere(
  206. m.db, v.where, v.args, m.option&OPTION_OMITEMPTY > 0,
  207. )
  208. if len(newWhere) > 0 {
  209. if len(conditionWhere) == 0 {
  210. conditionWhere = newWhere
  211. } else if conditionWhere[0] == '(' {
  212. conditionWhere = fmt.Sprintf(`%s AND (%s)`, conditionWhere, newWhere)
  213. } else {
  214. conditionWhere = fmt.Sprintf(`(%s) AND (%s)`, conditionWhere, newWhere)
  215. }
  216. conditionArgs = append(conditionArgs, newArgs...)
  217. }
  218. case whereHolderOr:
  219. newWhere, newArgs := formatWhere(
  220. m.db, v.where, v.args, m.option&OPTION_OMITEMPTY > 0,
  221. )
  222. if len(newWhere) > 0 {
  223. if len(conditionWhere) == 0 {
  224. conditionWhere = newWhere
  225. } else if conditionWhere[0] == '(' {
  226. conditionWhere = fmt.Sprintf(`%s OR (%s)`, conditionWhere, newWhere)
  227. } else {
  228. conditionWhere = fmt.Sprintf(`(%s) OR (%s)`, conditionWhere, newWhere)
  229. }
  230. conditionArgs = append(conditionArgs, newArgs...)
  231. }
  232. }
  233. }
  234. }
  235. if conditionWhere != "" {
  236. conditionWhere = " WHERE " + conditionWhere
  237. }
  238. if m.groupBy != "" {
  239. conditionExtra += " GROUP BY " + m.groupBy
  240. }
  241. if len(m.having) > 0 {
  242. havingStr, havingArgs := formatWhere(
  243. m.db, m.having[0], gconv.Interfaces(m.having[1]), m.option&OPTION_OMITEMPTY > 0,
  244. )
  245. if len(havingStr) > 0 {
  246. conditionExtra += " HAVING " + havingStr
  247. conditionArgs = append(conditionArgs, havingArgs...)
  248. }
  249. }
  250. if m.orderBy != "" {
  251. conditionExtra += " ORDER BY " + m.orderBy
  252. }
  253. if !isCountStatement {
  254. if m.limit != 0 {
  255. if m.start >= 0 {
  256. conditionExtra += fmt.Sprintf(" LIMIT %d,%d", m.start, m.limit)
  257. } else {
  258. conditionExtra += fmt.Sprintf(" LIMIT %d", m.limit)
  259. }
  260. } else if limit1 {
  261. conditionExtra += " LIMIT 1"
  262. }
  263. if m.offset >= 0 {
  264. conditionExtra += fmt.Sprintf(" OFFSET %d", m.offset)
  265. }
  266. }
  267. if m.lockInfo != "" {
  268. conditionExtra += " " + m.lockInfo
  269. }
  270. return
  271. }
  272. // mergeArguments creates and returns new arguments by merging <m.extraArgs> and given <args>.
  273. func (m *Model) mergeArguments(args []interface{}) []interface{} {
  274. if len(m.extraArgs) > 0 {
  275. newArgs := make([]interface{}, len(m.extraArgs)+len(args))
  276. copy(newArgs, m.extraArgs)
  277. copy(newArgs[len(m.extraArgs):], args)
  278. return newArgs
  279. }
  280. return args
  281. }