gdb_model_condition.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. // Copyright GoFrame Author(https://goframe.org). 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/text/gstr"
  10. "github.com/gogf/gf/util/gconv"
  11. "strings"
  12. )
  13. // Where sets the condition statement for the model. The parameter `where` can be type of
  14. // string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
  15. // multiple conditions will be joined into where statement using "AND".
  16. // Eg:
  17. // Where("uid=10000")
  18. // Where("uid", 10000)
  19. // Where("money>? AND name like ?", 99999, "vip_%")
  20. // Where("uid", 1).Where("name", "john")
  21. // Where("status IN (?)", g.Slice{1,2,3})
  22. // Where("age IN(?,?)", 18, 50)
  23. // Where(User{ Id : 1, UserName : "john"})
  24. func (m *Model) Where(where interface{}, args ...interface{}) *Model {
  25. model := m.getModel()
  26. if model.whereHolder == nil {
  27. model.whereHolder = make([]ModelWhereHolder, 0)
  28. }
  29. model.whereHolder = append(model.whereHolder, ModelWhereHolder{
  30. Operator: whereHolderOperatorWhere,
  31. Where: where,
  32. Args: args,
  33. })
  34. return model
  35. }
  36. // Having sets the having statement for the model.
  37. // The parameters of this function usage are as the same as function Where.
  38. // See Where.
  39. func (m *Model) Having(having interface{}, args ...interface{}) *Model {
  40. model := m.getModel()
  41. model.having = []interface{}{
  42. having, args,
  43. }
  44. return model
  45. }
  46. // WherePri does the same logic as Model.Where except that if the parameter `where`
  47. // is a single condition like int/string/float/slice, it treats the condition as the primary
  48. // key value. That is, if primary key is "id" and given `where` parameter as "123", the
  49. // WherePri function treats the condition as "id=123", but Model.Where treats the condition
  50. // as string "123".
  51. func (m *Model) WherePri(where interface{}, args ...interface{}) *Model {
  52. if len(args) > 0 {
  53. return m.Where(where, args...)
  54. }
  55. newWhere := GetPrimaryKeyCondition(m.getPrimaryKey(), where)
  56. return m.Where(newWhere[0], newWhere[1:]...)
  57. }
  58. // Wheref builds condition string using fmt.Sprintf and arguments.
  59. // Note that if the number of `args` is more than the place holder in `format`,
  60. // the extra `args` will be used as the where condition arguments of the Model.
  61. func (m *Model) Wheref(format string, args ...interface{}) *Model {
  62. var (
  63. placeHolderCount = gstr.Count(format, "?")
  64. conditionStr = fmt.Sprintf(format, args[:len(args)-placeHolderCount]...)
  65. )
  66. return m.Where(conditionStr, args[len(args)-placeHolderCount:]...)
  67. }
  68. // WhereLT builds `column < value` statement.
  69. func (m *Model) WhereLT(column string, value interface{}) *Model {
  70. return m.Wheref(`%s < ?`, column, value)
  71. }
  72. // WhereLTE builds `column <= value` statement.
  73. func (m *Model) WhereLTE(column string, value interface{}) *Model {
  74. return m.Wheref(`%s <= ?`, column, value)
  75. }
  76. // WhereGT builds `column > value` statement.
  77. func (m *Model) WhereGT(column string, value interface{}) *Model {
  78. return m.Wheref(`%s > ?`, column, value)
  79. }
  80. // WhereGTE builds `column >= value` statement.
  81. func (m *Model) WhereGTE(column string, value interface{}) *Model {
  82. return m.Wheref(`%s >= ?`, column, value)
  83. }
  84. // WhereBetween builds `column BETWEEN min AND max` statement.
  85. func (m *Model) WhereBetween(column string, min, max interface{}) *Model {
  86. return m.Wheref(`%s BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
  87. }
  88. // WhereLike builds `column LIKE like` statement.
  89. func (m *Model) WhereLike(column string, like interface{}) *Model {
  90. return m.Wheref(`%s LIKE ?`, m.db.GetCore().QuoteWord(column), like)
  91. }
  92. // WhereIn builds `column IN (in)` statement.
  93. func (m *Model) WhereIn(column string, in interface{}) *Model {
  94. return m.Wheref(`%s IN (?)`, m.db.GetCore().QuoteWord(column), in)
  95. }
  96. // WhereNull builds `columns[0] IS NULL AND columns[1] IS NULL ...` statement.
  97. func (m *Model) WhereNull(columns ...string) *Model {
  98. model := m
  99. for _, column := range columns {
  100. model = m.Wheref(`%s IS NULL`, m.db.GetCore().QuoteWord(column))
  101. }
  102. return model
  103. }
  104. // WhereNotBetween builds `column NOT BETWEEN min AND max` statement.
  105. func (m *Model) WhereNotBetween(column string, min, max interface{}) *Model {
  106. return m.Wheref(`%s NOT BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
  107. }
  108. // WhereNotLike builds `column NOT LIKE like` statement.
  109. func (m *Model) WhereNotLike(column string, like interface{}) *Model {
  110. return m.Wheref(`%s NOT LIKE ?`, m.db.GetCore().QuoteWord(column), like)
  111. }
  112. // WhereNot builds `column != value` statement.
  113. func (m *Model) WhereNot(column string, value interface{}) *Model {
  114. return m.Wheref(`%s != ?`, m.db.GetCore().QuoteWord(column), value)
  115. }
  116. // WhereNotIn builds `column NOT IN (in)` statement.
  117. func (m *Model) WhereNotIn(column string, in interface{}) *Model {
  118. return m.Wheref(`%s NOT IN (?)`, m.db.GetCore().QuoteWord(column), in)
  119. }
  120. // WhereNotNull builds `columns[0] IS NOT NULL AND columns[1] IS NOT NULL ...` statement.
  121. func (m *Model) WhereNotNull(columns ...string) *Model {
  122. model := m
  123. for _, column := range columns {
  124. model = m.Wheref(`%s IS NOT NULL`, m.db.GetCore().QuoteWord(column))
  125. }
  126. return model
  127. }
  128. // WhereOr adds "OR" condition to the where statement.
  129. func (m *Model) WhereOr(where interface{}, args ...interface{}) *Model {
  130. model := m.getModel()
  131. if model.whereHolder == nil {
  132. model.whereHolder = make([]ModelWhereHolder, 0)
  133. }
  134. model.whereHolder = append(model.whereHolder, ModelWhereHolder{
  135. Operator: whereHolderOperatorOr,
  136. Where: where,
  137. Args: args,
  138. })
  139. return model
  140. }
  141. // WhereOrf builds `OR` condition string using fmt.Sprintf and arguments.
  142. func (m *Model) WhereOrf(format string, args ...interface{}) *Model {
  143. var (
  144. placeHolderCount = gstr.Count(format, "?")
  145. conditionStr = fmt.Sprintf(format, args[:len(args)-placeHolderCount]...)
  146. )
  147. return m.WhereOr(conditionStr, args[len(args)-placeHolderCount:]...)
  148. }
  149. // WhereOrLT builds `column < value` statement in `OR` conditions..
  150. func (m *Model) WhereOrLT(column string, value interface{}) *Model {
  151. return m.WhereOrf(`%s < ?`, column, value)
  152. }
  153. // WhereOrLTE builds `column <= value` statement in `OR` conditions..
  154. func (m *Model) WhereOrLTE(column string, value interface{}) *Model {
  155. return m.WhereOrf(`%s <= ?`, column, value)
  156. }
  157. // WhereOrGT builds `column > value` statement in `OR` conditions..
  158. func (m *Model) WhereOrGT(column string, value interface{}) *Model {
  159. return m.WhereOrf(`%s > ?`, column, value)
  160. }
  161. // WhereOrGTE builds `column >= value` statement in `OR` conditions..
  162. func (m *Model) WhereOrGTE(column string, value interface{}) *Model {
  163. return m.WhereOrf(`%s >= ?`, column, value)
  164. }
  165. // WhereOrBetween builds `column BETWEEN min AND max` statement in `OR` conditions.
  166. func (m *Model) WhereOrBetween(column string, min, max interface{}) *Model {
  167. return m.WhereOrf(`%s BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
  168. }
  169. // WhereOrLike builds `column LIKE like` statement in `OR` conditions.
  170. func (m *Model) WhereOrLike(column string, like interface{}) *Model {
  171. return m.WhereOrf(`%s LIKE ?`, m.db.GetCore().QuoteWord(column), like)
  172. }
  173. // WhereOrIn builds `column IN (in)` statement in `OR` conditions.
  174. func (m *Model) WhereOrIn(column string, in interface{}) *Model {
  175. return m.WhereOrf(`%s IN (?)`, m.db.GetCore().QuoteWord(column), in)
  176. }
  177. // WhereOrNull builds `columns[0] IS NULL OR columns[1] IS NULL ...` statement in `OR` conditions.
  178. func (m *Model) WhereOrNull(columns ...string) *Model {
  179. model := m
  180. for _, column := range columns {
  181. model = m.WhereOrf(`%s IS NULL`, m.db.GetCore().QuoteWord(column))
  182. }
  183. return model
  184. }
  185. // WhereOrNotBetween builds `column NOT BETWEEN min AND max` statement in `OR` conditions.
  186. func (m *Model) WhereOrNotBetween(column string, min, max interface{}) *Model {
  187. return m.WhereOrf(`%s NOT BETWEEN ? AND ?`, m.db.GetCore().QuoteWord(column), min, max)
  188. }
  189. // WhereOrNotLike builds `column NOT LIKE like` statement in `OR` conditions.
  190. func (m *Model) WhereOrNotLike(column string, like interface{}) *Model {
  191. return m.WhereOrf(`%s NOT LIKE ?`, m.db.GetCore().QuoteWord(column), like)
  192. }
  193. // WhereOrNotIn builds `column NOT IN (in)` statement.
  194. func (m *Model) WhereOrNotIn(column string, in interface{}) *Model {
  195. return m.WhereOrf(`%s NOT IN (?)`, m.db.GetCore().QuoteWord(column), in)
  196. }
  197. // WhereOrNotNull builds `columns[0] IS NOT NULL OR columns[1] IS NOT NULL ...` statement in `OR` conditions.
  198. func (m *Model) WhereOrNotNull(columns ...string) *Model {
  199. model := m
  200. for _, column := range columns {
  201. model = m.WhereOrf(`%s IS NOT NULL`, m.db.GetCore().QuoteWord(column))
  202. }
  203. return model
  204. }
  205. // Group sets the "GROUP BY" statement for the model.
  206. func (m *Model) Group(groupBy ...string) *Model {
  207. if len(groupBy) > 0 {
  208. model := m.getModel()
  209. model.groupBy = m.db.GetCore().QuoteString(gstr.Join(groupBy, ","))
  210. return model
  211. }
  212. return m
  213. }
  214. // And adds "AND" condition to the where statement.
  215. // Deprecated, use Where instead.
  216. func (m *Model) And(where interface{}, args ...interface{}) *Model {
  217. model := m.getModel()
  218. if model.whereHolder == nil {
  219. model.whereHolder = make([]ModelWhereHolder, 0)
  220. }
  221. model.whereHolder = append(model.whereHolder, ModelWhereHolder{
  222. Operator: whereHolderOperatorAnd,
  223. Where: where,
  224. Args: args,
  225. })
  226. return model
  227. }
  228. // Or adds "OR" condition to the where statement.
  229. // Deprecated, use WhereOr instead.
  230. func (m *Model) Or(where interface{}, args ...interface{}) *Model {
  231. return m.WhereOr(where, args...)
  232. }
  233. // GroupBy is alias of Model.Group.
  234. // See Model.Group.
  235. // Deprecated, use Group instead.
  236. func (m *Model) GroupBy(groupBy string) *Model {
  237. return m.Group(groupBy)
  238. }
  239. // Order sets the "ORDER BY" statement for the model.
  240. func (m *Model) Order(orderBy ...string) *Model {
  241. if len(orderBy) == 0 {
  242. return m
  243. }
  244. model := m.getModel()
  245. if model.orderBy != "" {
  246. model.orderBy += ","
  247. }
  248. model.orderBy = m.db.GetCore().QuoteString(strings.Join(orderBy, " "))
  249. return model
  250. }
  251. // OrderAsc sets the "ORDER BY xxx ASC" statement for the model.
  252. func (m *Model) OrderAsc(column string) *Model {
  253. if len(column) == 0 {
  254. return m
  255. }
  256. model := m.getModel()
  257. if model.orderBy != "" {
  258. model.orderBy += ","
  259. }
  260. model.orderBy = m.db.GetCore().QuoteWord(column) + " ASC"
  261. return model
  262. }
  263. // OrderDesc sets the "ORDER BY xxx DESC" statement for the model.
  264. func (m *Model) OrderDesc(column string) *Model {
  265. if len(column) == 0 {
  266. return m
  267. }
  268. model := m.getModel()
  269. if model.orderBy != "" {
  270. model.orderBy += ","
  271. }
  272. model.orderBy = m.db.GetCore().QuoteWord(column) + " DESC"
  273. return model
  274. }
  275. // OrderRandom sets the "ORDER BY RANDOM()" statement for the model.
  276. func (m *Model) OrderRandom() *Model {
  277. model := m.getModel()
  278. model.orderBy = "RAND()"
  279. return model
  280. }
  281. // OrderBy is alias of Model.Order.
  282. // See Model.Order.
  283. // Deprecated, use Order instead.
  284. func (m *Model) OrderBy(orderBy string) *Model {
  285. return m.Order(orderBy)
  286. }
  287. // Limit sets the "LIMIT" statement for the model.
  288. // The parameter `limit` can be either one or two number, if passed two number is passed,
  289. // it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
  290. // statement.
  291. func (m *Model) Limit(limit ...int) *Model {
  292. model := m.getModel()
  293. switch len(limit) {
  294. case 1:
  295. model.limit = limit[0]
  296. case 2:
  297. model.start = limit[0]
  298. model.limit = limit[1]
  299. }
  300. return model
  301. }
  302. // Offset sets the "OFFSET" statement for the model.
  303. // It only makes sense for some databases like SQLServer, PostgreSQL, etc.
  304. func (m *Model) Offset(offset int) *Model {
  305. model := m.getModel()
  306. model.offset = offset
  307. return model
  308. }
  309. // Distinct forces the query to only return distinct results.
  310. func (m *Model) Distinct() *Model {
  311. model := m.getModel()
  312. model.distinct = "DISTINCT "
  313. return model
  314. }
  315. // Page sets the paging number for the model.
  316. // The parameter `page` is started from 1 for paging.
  317. // Note that, it differs that the Limit function starts from 0 for "LIMIT" statement.
  318. func (m *Model) Page(page, limit int) *Model {
  319. model := m.getModel()
  320. if page <= 0 {
  321. page = 1
  322. }
  323. model.start = (page - 1) * limit
  324. model.limit = limit
  325. return model
  326. }
  327. // ForPage is alias of Model.Page.
  328. // See Model.Page.
  329. // Deprecated, use Page instead.
  330. func (m *Model) ForPage(page, limit int) *Model {
  331. return m.Page(page, limit)
  332. }
  333. // formatCondition formats where arguments of the model and returns a new condition sql and its arguments.
  334. // Note that this function does not change any attribute value of the `m`.
  335. //
  336. // The parameter `limit1` specifies whether limits querying only one record if m.limit is not set.
  337. func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWhere string, conditionExtra string, conditionArgs []interface{}) {
  338. if len(m.whereHolder) > 0 {
  339. for _, v := range m.whereHolder {
  340. switch v.Operator {
  341. case whereHolderOperatorWhere:
  342. if conditionWhere == "" {
  343. newWhere, newArgs := formatWhere(m.db, formatWhereInput{
  344. Where: v.Where,
  345. Args: v.Args,
  346. OmitNil: m.option&optionOmitNilWhere > 0,
  347. OmitEmpty: m.option&optionOmitEmptyWhere > 0,
  348. Schema: m.schema,
  349. Table: m.tables,
  350. })
  351. if len(newWhere) > 0 {
  352. conditionWhere = newWhere
  353. conditionArgs = newArgs
  354. }
  355. continue
  356. }
  357. fallthrough
  358. case whereHolderOperatorAnd:
  359. newWhere, newArgs := formatWhere(m.db, formatWhereInput{
  360. Where: v.Where,
  361. Args: v.Args,
  362. OmitNil: m.option&optionOmitNilWhere > 0,
  363. OmitEmpty: m.option&optionOmitEmptyWhere > 0,
  364. Schema: m.schema,
  365. Table: m.tables,
  366. })
  367. if len(newWhere) > 0 {
  368. if len(conditionWhere) == 0 {
  369. conditionWhere = newWhere
  370. } else if conditionWhere[0] == '(' {
  371. conditionWhere = fmt.Sprintf(`%s AND (%s)`, conditionWhere, newWhere)
  372. } else {
  373. conditionWhere = fmt.Sprintf(`(%s) AND (%s)`, conditionWhere, newWhere)
  374. }
  375. conditionArgs = append(conditionArgs, newArgs...)
  376. }
  377. case whereHolderOperatorOr:
  378. newWhere, newArgs := formatWhere(m.db, formatWhereInput{
  379. Where: v.Where,
  380. Args: v.Args,
  381. OmitNil: m.option&optionOmitNilWhere > 0,
  382. OmitEmpty: m.option&optionOmitEmptyWhere > 0,
  383. Schema: m.schema,
  384. Table: m.tables,
  385. })
  386. if len(newWhere) > 0 {
  387. if len(conditionWhere) == 0 {
  388. conditionWhere = newWhere
  389. } else if conditionWhere[0] == '(' {
  390. conditionWhere = fmt.Sprintf(`%s OR (%s)`, conditionWhere, newWhere)
  391. } else {
  392. conditionWhere = fmt.Sprintf(`(%s) OR (%s)`, conditionWhere, newWhere)
  393. }
  394. conditionArgs = append(conditionArgs, newArgs...)
  395. }
  396. }
  397. }
  398. }
  399. // Soft deletion.
  400. softDeletingCondition := m.getConditionForSoftDeleting()
  401. if m.rawSql != "" && conditionWhere != "" {
  402. if gstr.ContainsI(m.rawSql, " WHERE ") {
  403. conditionWhere = " AND " + conditionWhere
  404. } else {
  405. conditionWhere = " WHERE " + conditionWhere
  406. }
  407. } else if !m.unscoped && softDeletingCondition != "" {
  408. if conditionWhere == "" {
  409. conditionWhere = fmt.Sprintf(` WHERE %s`, softDeletingCondition)
  410. } else {
  411. conditionWhere = fmt.Sprintf(` WHERE (%s) AND %s`, conditionWhere, softDeletingCondition)
  412. }
  413. } else {
  414. if conditionWhere != "" {
  415. conditionWhere = " WHERE " + conditionWhere
  416. }
  417. }
  418. // GROUP BY.
  419. if m.groupBy != "" {
  420. conditionExtra += " GROUP BY " + m.groupBy
  421. }
  422. // HAVING.
  423. if len(m.having) > 0 {
  424. havingStr, havingArgs := formatWhere(m.db, formatWhereInput{
  425. Where: m.having[0],
  426. Args: gconv.Interfaces(m.having[1]),
  427. OmitNil: m.option&optionOmitNilWhere > 0,
  428. OmitEmpty: m.option&optionOmitEmptyWhere > 0,
  429. Schema: m.schema,
  430. Table: m.tables,
  431. })
  432. if len(havingStr) > 0 {
  433. conditionExtra += " HAVING " + havingStr
  434. conditionArgs = append(conditionArgs, havingArgs...)
  435. }
  436. }
  437. // ORDER BY.
  438. if m.orderBy != "" {
  439. conditionExtra += " ORDER BY " + m.orderBy
  440. }
  441. // LIMIT.
  442. if !isCountStatement {
  443. if m.limit != 0 {
  444. if m.start >= 0 {
  445. conditionExtra += fmt.Sprintf(" LIMIT %d,%d", m.start, m.limit)
  446. } else {
  447. conditionExtra += fmt.Sprintf(" LIMIT %d", m.limit)
  448. }
  449. } else if limit1 {
  450. conditionExtra += " LIMIT 1"
  451. }
  452. if m.offset >= 0 {
  453. conditionExtra += fmt.Sprintf(" OFFSET %d", m.offset)
  454. }
  455. }
  456. if m.lockInfo != "" {
  457. conditionExtra += " " + m.lockInfo
  458. }
  459. return
  460. }