http urls monitor.

result.go 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. // Copyright (c) 2012-present The upper.io/db authors. All rights reserved.
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining
  4. // a copy of this software and associated documentation files (the
  5. // "Software"), to deal in the Software without restriction, including
  6. // without limitation the rights to use, copy, modify, merge, publish,
  7. // distribute, sublicense, and/or sell copies of the Software, and to
  8. // permit persons to whom the Software is furnished to do so, subject to
  9. // the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be
  12. // included in all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  18. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  19. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  20. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. package sqladapter
  22. import (
  23. "sync"
  24. "sync/atomic"
  25. "upper.io/db.v3"
  26. "upper.io/db.v3/internal/immutable"
  27. "upper.io/db.v3/lib/sqlbuilder"
  28. )
  29. type Result struct {
  30. builder sqlbuilder.SQLBuilder
  31. err atomic.Value
  32. iter sqlbuilder.Iterator
  33. iterMu sync.Mutex
  34. prev *Result
  35. fn func(*result) error
  36. }
  37. // result represents a delimited set of items bound by a condition.
  38. type result struct {
  39. table string
  40. limit int
  41. offset int
  42. pageSize uint
  43. pageNumber uint
  44. cursorColumn string
  45. nextPageCursorValue interface{}
  46. prevPageCursorValue interface{}
  47. fields []interface{}
  48. columns []interface{}
  49. orderBy []interface{}
  50. groupBy []interface{}
  51. conds [][]interface{}
  52. }
  53. func filter(conds []interface{}) []interface{} {
  54. return conds
  55. }
  56. // NewResult creates and Results a new Result set on the given table, this set
  57. // is limited by the given exql.Where conditions.
  58. func NewResult(builder sqlbuilder.SQLBuilder, table string, conds []interface{}) *Result {
  59. r := &Result{
  60. builder: builder,
  61. }
  62. return r.from(table).where(conds)
  63. }
  64. func (r *Result) frame(fn func(*result) error) *Result {
  65. return &Result{prev: r, fn: fn}
  66. }
  67. func (r *Result) SQLBuilder() sqlbuilder.SQLBuilder {
  68. if r.prev == nil {
  69. return r.builder
  70. }
  71. return r.prev.SQLBuilder()
  72. }
  73. func (r *Result) from(table string) *Result {
  74. return r.frame(func(res *result) error {
  75. res.table = table
  76. return nil
  77. })
  78. }
  79. func (r *Result) where(conds []interface{}) *Result {
  80. return r.frame(func(res *result) error {
  81. res.conds = [][]interface{}{conds}
  82. return nil
  83. })
  84. }
  85. func (r *Result) setErr(err error) error {
  86. if err == nil {
  87. return nil
  88. }
  89. r.err.Store(err)
  90. return err
  91. }
  92. // Err returns the last error that has happened with the result set,
  93. // nil otherwise
  94. func (r *Result) Err() error {
  95. if errV := r.err.Load(); errV != nil {
  96. return errV.(error)
  97. }
  98. return nil
  99. }
  100. // Where sets conditions for the result set.
  101. func (r *Result) Where(conds ...interface{}) db.Result {
  102. return r.where(conds)
  103. }
  104. // And adds more conditions on top of the existing ones.
  105. func (r *Result) And(conds ...interface{}) db.Result {
  106. return r.frame(func(res *result) error {
  107. res.conds = append(res.conds, conds)
  108. return nil
  109. })
  110. }
  111. // Limit determines the maximum limit of Results to be returned.
  112. func (r *Result) Limit(n int) db.Result {
  113. return r.frame(func(res *result) error {
  114. res.limit = n
  115. return nil
  116. })
  117. }
  118. func (r *Result) Paginate(pageSize uint) db.Result {
  119. return r.frame(func(res *result) error {
  120. res.pageSize = pageSize
  121. return nil
  122. })
  123. }
  124. func (r *Result) Page(pageNumber uint) db.Result {
  125. return r.frame(func(res *result) error {
  126. res.pageNumber = pageNumber
  127. res.nextPageCursorValue = nil
  128. res.prevPageCursorValue = nil
  129. return nil
  130. })
  131. }
  132. func (r *Result) Cursor(cursorColumn string) db.Result {
  133. return r.frame(func(res *result) error {
  134. res.cursorColumn = cursorColumn
  135. return nil
  136. })
  137. }
  138. func (r *Result) NextPage(cursorValue interface{}) db.Result {
  139. return r.frame(func(res *result) error {
  140. res.nextPageCursorValue = cursorValue
  141. res.prevPageCursorValue = nil
  142. return nil
  143. })
  144. }
  145. func (r *Result) PrevPage(cursorValue interface{}) db.Result {
  146. return r.frame(func(res *result) error {
  147. res.nextPageCursorValue = nil
  148. res.prevPageCursorValue = cursorValue
  149. return nil
  150. })
  151. }
  152. // Offset determines how many documents will be skipped before starting to grab
  153. // Results.
  154. func (r *Result) Offset(n int) db.Result {
  155. return r.frame(func(res *result) error {
  156. res.offset = n
  157. return nil
  158. })
  159. }
  160. // Group is used to group Results that have the same value in the same column
  161. // or columns.
  162. func (r *Result) Group(fields ...interface{}) db.Result {
  163. return r.frame(func(res *result) error {
  164. res.groupBy = fields
  165. return nil
  166. })
  167. }
  168. // OrderBy determines sorting of Results according to the provided names. Fields
  169. // may be prefixed by - (minus) which means descending order, ascending order
  170. // would be used otherwise.
  171. func (r *Result) OrderBy(fields ...interface{}) db.Result {
  172. return r.frame(func(res *result) error {
  173. res.orderBy = fields
  174. return nil
  175. })
  176. }
  177. // Select determines which fields to return.
  178. func (r *Result) Select(fields ...interface{}) db.Result {
  179. return r.frame(func(res *result) error {
  180. res.fields = fields
  181. return nil
  182. })
  183. }
  184. // String satisfies fmt.Stringer
  185. func (r *Result) String() string {
  186. query, err := r.buildPaginator()
  187. if err != nil {
  188. panic(err.Error())
  189. }
  190. return query.String()
  191. }
  192. // All dumps all Results into a pointer to an slice of structs or maps.
  193. func (r *Result) All(dst interface{}) error {
  194. query, err := r.buildPaginator()
  195. if err != nil {
  196. return r.setErr(err)
  197. }
  198. err = query.Iterator().All(dst)
  199. return r.setErr(err)
  200. }
  201. // One fetches only one Result from the set.
  202. func (r *Result) One(dst interface{}) error {
  203. query, err := r.buildPaginator()
  204. if err != nil {
  205. return r.setErr(err)
  206. }
  207. err = query.Iterator().One(dst)
  208. return r.setErr(err)
  209. }
  210. // Next fetches the next Result from the set.
  211. func (r *Result) Next(dst interface{}) bool {
  212. r.iterMu.Lock()
  213. defer r.iterMu.Unlock()
  214. if r.iter == nil {
  215. query, err := r.buildPaginator()
  216. if err != nil {
  217. r.setErr(err)
  218. return false
  219. }
  220. r.iter = query.Iterator()
  221. }
  222. if r.iter.Next(dst) {
  223. return true
  224. }
  225. if err := r.iter.Err(); err != db.ErrNoMoreRows {
  226. r.setErr(err)
  227. }
  228. return false
  229. }
  230. // Delete deletes all matching items from the collection.
  231. func (r *Result) Delete() error {
  232. query, err := r.buildDelete()
  233. if err != nil {
  234. return r.setErr(err)
  235. }
  236. _, err = query.Exec()
  237. return r.setErr(err)
  238. }
  239. // Close closes the Result set.
  240. func (r *Result) Close() error {
  241. if r.iter != nil {
  242. return r.setErr(r.iter.Close())
  243. }
  244. return nil
  245. }
  246. // Update updates matching items from the collection with values of the given
  247. // map or struct.
  248. func (r *Result) Update(values interface{}) error {
  249. query, err := r.buildUpdate(values)
  250. if err != nil {
  251. return r.setErr(err)
  252. }
  253. _, err = query.Exec()
  254. return r.setErr(err)
  255. }
  256. func (r *Result) TotalPages() (uint, error) {
  257. query, err := r.buildPaginator()
  258. if err != nil {
  259. return 0, r.setErr(err)
  260. }
  261. total, err := query.TotalPages()
  262. if err != nil {
  263. return 0, r.setErr(err)
  264. }
  265. return total, nil
  266. }
  267. func (r *Result) TotalEntries() (uint64, error) {
  268. query, err := r.buildPaginator()
  269. if err != nil {
  270. return 0, r.setErr(err)
  271. }
  272. total, err := query.TotalEntries()
  273. if err != nil {
  274. return 0, r.setErr(err)
  275. }
  276. return total, nil
  277. }
  278. // Exists returns true if at least one item on the collection exists.
  279. func (r *Result) Exists() (bool, error) {
  280. query, err := r.buildCount()
  281. if err != nil {
  282. return false, r.setErr(err)
  283. }
  284. query = query.Limit(1)
  285. value := struct {
  286. Exists uint64 `db:"_t"`
  287. }{}
  288. if err := query.One(&value); err != nil {
  289. if err == db.ErrNoMoreRows {
  290. return false, nil
  291. }
  292. return false, r.setErr(err)
  293. }
  294. if value.Exists > 0 {
  295. return true, nil
  296. }
  297. return false, nil
  298. }
  299. // Count counts the elements on the set.
  300. func (r *Result) Count() (uint64, error) {
  301. query, err := r.buildCount()
  302. if err != nil {
  303. return 0, r.setErr(err)
  304. }
  305. counter := struct {
  306. Count uint64 `db:"_t"`
  307. }{}
  308. if err := query.One(&counter); err != nil {
  309. if err == db.ErrNoMoreRows {
  310. return 0, nil
  311. }
  312. return 0, r.setErr(err)
  313. }
  314. return counter.Count, nil
  315. }
  316. func (r *Result) buildPaginator() (sqlbuilder.Paginator, error) {
  317. if err := r.Err(); err != nil {
  318. return nil, err
  319. }
  320. res, err := r.fastForward()
  321. if err != nil {
  322. return nil, err
  323. }
  324. sel := r.SQLBuilder().Select(res.fields...).
  325. From(res.table).
  326. Limit(res.limit).
  327. Offset(res.offset).
  328. GroupBy(res.groupBy...).
  329. OrderBy(res.orderBy...)
  330. for i := range res.conds {
  331. sel = sel.And(filter(res.conds[i])...)
  332. }
  333. pag := sel.Paginate(res.pageSize).
  334. Page(res.pageNumber).
  335. Cursor(res.cursorColumn)
  336. if res.nextPageCursorValue != nil {
  337. pag = pag.NextPage(res.nextPageCursorValue)
  338. }
  339. if res.prevPageCursorValue != nil {
  340. pag = pag.PrevPage(res.prevPageCursorValue)
  341. }
  342. return pag, nil
  343. }
  344. func (r *Result) buildDelete() (sqlbuilder.Deleter, error) {
  345. if err := r.Err(); err != nil {
  346. return nil, err
  347. }
  348. res, err := r.fastForward()
  349. if err != nil {
  350. return nil, err
  351. }
  352. del := r.SQLBuilder().DeleteFrom(res.table).
  353. Limit(res.limit)
  354. for i := range res.conds {
  355. del = del.And(filter(res.conds[i])...)
  356. }
  357. return del, nil
  358. }
  359. func (r *Result) buildUpdate(values interface{}) (sqlbuilder.Updater, error) {
  360. if err := r.Err(); err != nil {
  361. return nil, err
  362. }
  363. res, err := r.fastForward()
  364. if err != nil {
  365. return nil, err
  366. }
  367. upd := r.SQLBuilder().Update(res.table).
  368. Set(values).
  369. Limit(res.limit)
  370. for i := range res.conds {
  371. upd = upd.And(filter(res.conds[i])...)
  372. }
  373. return upd, nil
  374. }
  375. func (r *Result) buildCount() (sqlbuilder.Selector, error) {
  376. if err := r.Err(); err != nil {
  377. return nil, err
  378. }
  379. res, err := r.fastForward()
  380. if err != nil {
  381. return nil, err
  382. }
  383. sel := r.SQLBuilder().Select(db.Raw("count(1) AS _t")).
  384. From(res.table).
  385. GroupBy(res.groupBy...)
  386. for i := range res.conds {
  387. sel = sel.And(filter(res.conds[i])...)
  388. }
  389. return sel, nil
  390. }
  391. func (r *Result) Prev() immutable.Immutable {
  392. if r == nil {
  393. return nil
  394. }
  395. return r.prev
  396. }
  397. func (r *Result) Fn(in interface{}) error {
  398. if r.fn == nil {
  399. return nil
  400. }
  401. return r.fn(in.(*result))
  402. }
  403. func (r *Result) Base() interface{} {
  404. return &result{}
  405. }
  406. func (r *Result) fastForward() (*result, error) {
  407. ff, err := immutable.FastForward(r)
  408. if err != nil {
  409. return nil, err
  410. }
  411. return ff.(*result), nil
  412. }
  413. var _ = immutable.Immutable(&Result{})