gdb_model_select.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  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/container/gvar"
  11. "github.com/gogf/gf/internal/json"
  12. "github.com/gogf/gf/text/gstr"
  13. "github.com/gogf/gf/util/gconv"
  14. "reflect"
  15. )
  16. // Select is alias of Model.All.
  17. // See Model.All.
  18. // Deprecated.
  19. func (m *Model) Select(where ...interface{}) (Result, error) {
  20. return m.All(where...)
  21. }
  22. // All does "SELECT FROM ..." statement for the model.
  23. // It retrieves the records from table and returns the result as slice type.
  24. // It returns nil if there's no record retrieved with the given conditions from table.
  25. //
  26. // The optional parameter <where> is the same as the parameter of Model.Where function,
  27. // see Model.Where.
  28. func (m *Model) All(where ...interface{}) (Result, error) {
  29. return m.doGetAll(false, where...)
  30. }
  31. // doGetAll does "SELECT FROM ..." statement for the model.
  32. // It retrieves the records from table and returns the result as slice type.
  33. // It returns nil if there's no record retrieved with the given conditions from table.
  34. //
  35. // The parameter <limit1> specifies whether limits querying only one record if m.limit is not set.
  36. // The optional parameter <where> is the same as the parameter of Model.Where function,
  37. // see Model.Where.
  38. func (m *Model) doGetAll(limit1 bool, where ...interface{}) (Result, error) {
  39. if len(where) > 0 {
  40. return m.Where(where[0], where[1:]...).All()
  41. }
  42. var (
  43. softDeletingCondition = m.getConditionForSoftDeleting()
  44. conditionWhere, conditionExtra, conditionArgs = m.formatCondition(limit1, false)
  45. )
  46. if !m.unscoped && softDeletingCondition != "" {
  47. if conditionWhere == "" {
  48. conditionWhere = " WHERE "
  49. } else {
  50. conditionWhere += " AND "
  51. }
  52. conditionWhere += softDeletingCondition
  53. }
  54. // DO NOT quote the m.fields where, in case of fields like:
  55. // DISTINCT t.user_id uid
  56. return m.doGetAllBySql(
  57. fmt.Sprintf(
  58. "SELECT %s FROM %s%s",
  59. m.getFieldsFiltered(),
  60. m.tables,
  61. conditionWhere+conditionExtra,
  62. ),
  63. conditionArgs...,
  64. )
  65. }
  66. // getFieldsFiltered checks the fields and fieldsEx attributes, filters and returns the fields that will
  67. // really be committed to underlying database driver.
  68. func (m *Model) getFieldsFiltered() string {
  69. if m.fieldsEx == "" {
  70. // No filtering.
  71. if !gstr.Contains(m.fields, ".") && !gstr.Contains(m.fields, " ") {
  72. return m.db.QuoteString(m.fields)
  73. }
  74. return m.fields
  75. }
  76. var (
  77. fieldsArray []string
  78. fieldsExSet = gset.NewStrSetFrom(gstr.SplitAndTrim(m.fieldsEx, ","))
  79. )
  80. if m.fields != "*" {
  81. // Filter custom fields with fieldEx.
  82. fieldsArray = make([]string, 0, 8)
  83. for _, v := range gstr.SplitAndTrim(m.fields, ",") {
  84. fieldsArray = append(fieldsArray, v[gstr.PosR(v, "-")+1:])
  85. }
  86. } else {
  87. if gstr.Contains(m.tables, " ") {
  88. panic("function FieldsEx supports only single table operations")
  89. }
  90. // Filter table fields with fieldEx.
  91. tableFields, err := m.db.TableFields(m.tables)
  92. if err != nil {
  93. panic(err)
  94. }
  95. if len(tableFields) == 0 {
  96. panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables))
  97. }
  98. fieldsArray = make([]string, len(tableFields))
  99. for k, v := range tableFields {
  100. fieldsArray[v.Index] = k
  101. }
  102. }
  103. newFields := ""
  104. for _, k := range fieldsArray {
  105. if fieldsExSet.Contains(k) {
  106. continue
  107. }
  108. if len(newFields) > 0 {
  109. newFields += ","
  110. }
  111. newFields += m.db.QuoteWord(k)
  112. }
  113. return newFields
  114. }
  115. // Chunk iterates the query result with given size and callback function.
  116. func (m *Model) Chunk(limit int, callback func(result Result, err error) bool) {
  117. page := m.start
  118. if page <= 0 {
  119. page = 1
  120. }
  121. model := m
  122. for {
  123. model = model.Page(page, limit)
  124. data, err := model.All()
  125. if err != nil {
  126. callback(nil, err)
  127. break
  128. }
  129. if len(data) == 0 {
  130. break
  131. }
  132. if callback(data, err) == false {
  133. break
  134. }
  135. if len(data) < limit {
  136. break
  137. }
  138. page++
  139. }
  140. }
  141. // One retrieves one record from table and returns the result as map type.
  142. // It returns nil if there's no record retrieved with the given conditions from table.
  143. //
  144. // The optional parameter <where> is the same as the parameter of Model.Where function,
  145. // see Model.Where.
  146. func (m *Model) One(where ...interface{}) (Record, error) {
  147. if len(where) > 0 {
  148. return m.Where(where[0], where[1:]...).One()
  149. }
  150. all, err := m.doGetAll(true)
  151. if err != nil {
  152. return nil, err
  153. }
  154. if len(all) > 0 {
  155. return all[0], nil
  156. }
  157. return nil, nil
  158. }
  159. // Value retrieves a specified record value from table and returns the result as interface type.
  160. // It returns nil if there's no record found with the given conditions from table.
  161. //
  162. // If the optional parameter <fieldsAndWhere> is given, the fieldsAndWhere[0] is the selected fields
  163. // and fieldsAndWhere[1:] is treated as where condition fields.
  164. // Also see Model.Fields and Model.Where functions.
  165. func (m *Model) Value(fieldsAndWhere ...interface{}) (Value, error) {
  166. if len(fieldsAndWhere) > 0 {
  167. if len(fieldsAndWhere) > 2 {
  168. return m.Fields(gconv.String(fieldsAndWhere[0])).Where(fieldsAndWhere[1], fieldsAndWhere[2:]...).Value()
  169. } else if len(fieldsAndWhere) == 2 {
  170. return m.Fields(gconv.String(fieldsAndWhere[0])).Where(fieldsAndWhere[1]).Value()
  171. } else {
  172. return m.Fields(gconv.String(fieldsAndWhere[0])).Value()
  173. }
  174. }
  175. one, err := m.One()
  176. if err != nil {
  177. return gvar.New(nil), err
  178. }
  179. for _, v := range one {
  180. return v, nil
  181. }
  182. return gvar.New(nil), nil
  183. }
  184. // Array queries and returns data values as slice from database.
  185. // Note that if there're multiple columns in the result, it returns just one column values randomly.
  186. //
  187. // If the optional parameter <fieldsAndWhere> is given, the fieldsAndWhere[0] is the selected fields
  188. // and fieldsAndWhere[1:] is treated as where condition fields.
  189. // Also see Model.Fields and Model.Where functions.
  190. func (m *Model) Array(fieldsAndWhere ...interface{}) ([]Value, error) {
  191. if len(fieldsAndWhere) > 0 {
  192. if len(fieldsAndWhere) > 2 {
  193. return m.Fields(gconv.String(fieldsAndWhere[0])).Where(fieldsAndWhere[1], fieldsAndWhere[2:]...).Array()
  194. } else if len(fieldsAndWhere) == 2 {
  195. return m.Fields(gconv.String(fieldsAndWhere[0])).Where(fieldsAndWhere[1]).Array()
  196. } else {
  197. return m.Fields(gconv.String(fieldsAndWhere[0])).Array()
  198. }
  199. }
  200. all, err := m.All()
  201. if err != nil {
  202. return nil, err
  203. }
  204. return all.Array(), nil
  205. }
  206. // Struct retrieves one record from table and converts it into given struct.
  207. // The parameter <pointer> should be type of *struct/**struct. If type **struct is given,
  208. // it can create the struct internally during converting.
  209. //
  210. // The optional parameter <where> is the same as the parameter of Model.Where function,
  211. // see Model.Where.
  212. //
  213. // Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
  214. // from table and <pointer> is not nil.
  215. //
  216. // Eg:
  217. // user := new(User)
  218. // err := db.Model("user").Where("id", 1).Struct(user)
  219. //
  220. // user := (*User)(nil)
  221. // err := db.Model("user").Where("id", 1).Struct(&user)
  222. func (m *Model) Struct(pointer interface{}, where ...interface{}) error {
  223. one, err := m.One(where...)
  224. if err != nil {
  225. return err
  226. }
  227. return one.Struct(pointer)
  228. }
  229. // Structs retrieves records from table and converts them into given struct slice.
  230. // The parameter <pointer> should be type of *[]struct/*[]*struct. It can create and fill the struct
  231. // slice internally during converting.
  232. //
  233. // The optional parameter <where> is the same as the parameter of Model.Where function,
  234. // see Model.Where.
  235. //
  236. // Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
  237. // from table and <pointer> is not empty.
  238. //
  239. // Eg:
  240. // users := ([]User)(nil)
  241. // err := db.Model("user").Structs(&users)
  242. //
  243. // users := ([]*User)(nil)
  244. // err := db.Model("user").Structs(&users)
  245. func (m *Model) Structs(pointer interface{}, where ...interface{}) error {
  246. all, err := m.All(where...)
  247. if err != nil {
  248. return err
  249. }
  250. return all.Structs(pointer)
  251. }
  252. // Scan automatically calls Struct or Structs function according to the type of parameter <pointer>.
  253. // It calls function Struct if <pointer> is type of *struct/**struct.
  254. // It calls function Structs if <pointer> is type of *[]struct/*[]*struct.
  255. //
  256. // The optional parameter <where> is the same as the parameter of Model.Where function,
  257. // see Model.Where.
  258. //
  259. // Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
  260. // from table.
  261. //
  262. // Eg:
  263. // user := new(User)
  264. // err := db.Model("user").Where("id", 1).Scan(user)
  265. //
  266. // user := (*User)(nil)
  267. // err := db.Model("user").Where("id", 1).Scan(&user)
  268. //
  269. // users := ([]User)(nil)
  270. // err := db.Model("user").Scan(&users)
  271. //
  272. // users := ([]*User)(nil)
  273. // err := db.Model("user").Scan(&users)
  274. func (m *Model) Scan(pointer interface{}, where ...interface{}) error {
  275. t := reflect.TypeOf(pointer)
  276. k := t.Kind()
  277. if k != reflect.Ptr {
  278. return fmt.Errorf("params should be type of pointer, but got: %v", k)
  279. }
  280. switch t.Elem().Kind() {
  281. case reflect.Array, reflect.Slice:
  282. return m.Structs(pointer, where...)
  283. default:
  284. return m.Struct(pointer, where...)
  285. }
  286. }
  287. // ScanList converts <r> to struct slice which contains other complex struct attributes.
  288. // Note that the parameter <listPointer> should be type of *[]struct/*[]*struct.
  289. // Usage example:
  290. //
  291. // type Entity struct {
  292. // User *EntityUser
  293. // UserDetail *EntityUserDetail
  294. // UserScores []*EntityUserScores
  295. // }
  296. // var users []*Entity
  297. // or
  298. // var users []Entity
  299. //
  300. // ScanList(&users, "User")
  301. // ScanList(&users, "UserDetail", "User", "uid:Uid")
  302. // ScanList(&users, "UserScores", "User", "uid:Uid")
  303. // The parameters "User"/"UserDetail"/"UserScores" in the example codes specify the target attribute struct
  304. // that current result will be bound to.
  305. // The "uid" in the example codes is the table field name of the result, and the "Uid" is the relational
  306. // struct attribute name. It automatically calculates the HasOne/HasMany relationship with given <relation>
  307. // parameter.
  308. // See the example or unit testing cases for clear understanding for this function.
  309. func (m *Model) ScanList(listPointer interface{}, attributeName string, relation ...string) (err error) {
  310. all, err := m.All()
  311. if err != nil {
  312. return err
  313. }
  314. return all.ScanList(listPointer, attributeName, relation...)
  315. }
  316. // Count does "SELECT COUNT(x) FROM ..." statement for the model.
  317. // The optional parameter <where> is the same as the parameter of Model.Where function,
  318. // see Model.Where.
  319. func (m *Model) Count(where ...interface{}) (int, error) {
  320. if len(where) > 0 {
  321. return m.Where(where[0], where[1:]...).Count()
  322. }
  323. countFields := "COUNT(1)"
  324. if m.fields != "" && m.fields != "*" {
  325. // DO NOT quote the m.fields here, in case of fields like:
  326. // DISTINCT t.user_id uid
  327. countFields = fmt.Sprintf(`COUNT(%s)`, m.fields)
  328. }
  329. var (
  330. softDeletingCondition = m.getConditionForSoftDeleting()
  331. conditionWhere, conditionExtra, conditionArgs = m.formatCondition(false, true)
  332. )
  333. if !m.unscoped && softDeletingCondition != "" {
  334. if conditionWhere == "" {
  335. conditionWhere = " WHERE "
  336. } else {
  337. conditionWhere += " AND "
  338. }
  339. conditionWhere += softDeletingCondition
  340. }
  341. s := fmt.Sprintf("SELECT %s FROM %s%s", countFields, m.tables, conditionWhere+conditionExtra)
  342. if len(m.groupBy) > 0 {
  343. s = fmt.Sprintf("SELECT COUNT(1) FROM (%s) count_alias", s)
  344. }
  345. list, err := m.doGetAllBySql(s, conditionArgs...)
  346. if err != nil {
  347. return 0, err
  348. }
  349. if len(list) > 0 {
  350. for _, v := range list[0] {
  351. return v.Int(), nil
  352. }
  353. }
  354. return 0, nil
  355. }
  356. // FindOne retrieves and returns a single Record by Model.WherePri and Model.One.
  357. // Also see Model.WherePri and Model.One.
  358. func (m *Model) FindOne(where ...interface{}) (Record, error) {
  359. if len(where) > 0 {
  360. return m.WherePri(where[0], where[1:]...).One()
  361. }
  362. return m.One()
  363. }
  364. // FindAll retrieves and returns Result by by Model.WherePri and Model.All.
  365. // Also see Model.WherePri and Model.All.
  366. func (m *Model) FindAll(where ...interface{}) (Result, error) {
  367. if len(where) > 0 {
  368. return m.WherePri(where[0], where[1:]...).All()
  369. }
  370. return m.All()
  371. }
  372. // FindValue retrieves and returns single field value by Model.WherePri and Model.Value.
  373. // Also see Model.WherePri and Model.Value.
  374. func (m *Model) FindValue(fieldsAndWhere ...interface{}) (Value, error) {
  375. if len(fieldsAndWhere) >= 2 {
  376. return m.WherePri(fieldsAndWhere[1], fieldsAndWhere[2:]...).Fields(gconv.String(fieldsAndWhere[0])).Value()
  377. }
  378. if len(fieldsAndWhere) == 1 {
  379. return m.Fields(gconv.String(fieldsAndWhere[0])).Value()
  380. }
  381. return m.Value()
  382. }
  383. // FindArray queries and returns data values as slice from database.
  384. // Note that if there're multiple columns in the result, it returns just one column values randomly.
  385. // Also see Model.WherePri and Model.Value.
  386. func (m *Model) FindArray(fieldsAndWhere ...interface{}) ([]Value, error) {
  387. if len(fieldsAndWhere) >= 2 {
  388. return m.WherePri(fieldsAndWhere[1], fieldsAndWhere[2:]...).Fields(gconv.String(fieldsAndWhere[0])).Array()
  389. }
  390. if len(fieldsAndWhere) == 1 {
  391. return m.Fields(gconv.String(fieldsAndWhere[0])).Array()
  392. }
  393. return m.Array()
  394. }
  395. // FindCount retrieves and returns the record number by Model.WherePri and Model.Count.
  396. // Also see Model.WherePri and Model.Count.
  397. func (m *Model) FindCount(where ...interface{}) (int, error) {
  398. if len(where) > 0 {
  399. return m.WherePri(where[0], where[1:]...).Count()
  400. }
  401. return m.Count()
  402. }
  403. // FindScan retrieves and returns the record/records by Model.WherePri and Model.Scan.
  404. // Also see Model.WherePri and Model.Scan.
  405. func (m *Model) FindScan(pointer interface{}, where ...interface{}) error {
  406. if len(where) > 0 {
  407. return m.WherePri(where[0], where[1:]...).Scan(pointer)
  408. }
  409. return m.Scan(pointer)
  410. }
  411. // doGetAllBySql does the select statement on the database.
  412. func (m *Model) doGetAllBySql(sql string, args ...interface{}) (result Result, err error) {
  413. cacheKey := ""
  414. cacheObj := m.db.GetCache()
  415. // Retrieve from cache.
  416. if m.cacheEnabled && m.tx == nil {
  417. cacheKey = m.cacheName
  418. if len(cacheKey) == 0 {
  419. cacheKey = sql + ", @PARAMS:" + gconv.String(args)
  420. }
  421. if v, _ := cacheObj.GetVar(cacheKey); !v.IsNil() {
  422. if result, ok := v.Val().(Result); ok {
  423. // In-memory cache.
  424. return result, nil
  425. } else {
  426. // Other cache, it needs conversion.
  427. var result Result
  428. if err = json.Unmarshal(v.Bytes(), &result); err != nil {
  429. return nil, err
  430. } else {
  431. return result, nil
  432. }
  433. }
  434. }
  435. }
  436. result, err = m.db.DoGetAll(m.getLink(false), sql, m.mergeArguments(args)...)
  437. // Cache the result.
  438. if cacheKey != "" && err == nil {
  439. if m.cacheDuration < 0 {
  440. cacheObj.Remove(cacheKey)
  441. } else {
  442. cacheObj.Set(cacheKey, result, m.cacheDuration)
  443. }
  444. }
  445. return result, err
  446. }