stufflog graphql server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
6.2 KiB

4 years ago
  1. package mysqldriver
  2. import (
  3. "context"
  4. "database/sql"
  5. "git.aiterp.net/stufflog/server/internal/generate"
  6. "git.aiterp.net/stufflog/server/internal/slerrors"
  7. "git.aiterp.net/stufflog/server/models"
  8. sq "github.com/Masterminds/squirrel"
  9. "github.com/jmoiron/sqlx"
  10. )
  11. type logRepository struct {
  12. db *sqlx.DB
  13. }
  14. func (r *logRepository) Find(ctx context.Context, id string) (*models.Log, error) {
  15. log := models.Log{}
  16. err := r.db.GetContext(ctx, &log, "SELECT * FROM log WHERE log_id=?", id)
  17. if err != nil {
  18. if err == sql.ErrNoRows {
  19. return nil, slerrors.NotFound("Log")
  20. }
  21. return nil, err
  22. }
  23. err = r.db.SelectContext(ctx, &log.Items, "SELECT * FROM log_item WHERE log_id=?", id)
  24. if err != nil {
  25. return nil, err
  26. }
  27. err = r.db.SelectContext(ctx, &log.Tasks, "SELECT * FROM log_task WHERE log_id=?", id)
  28. if err != nil {
  29. return nil, err
  30. }
  31. return &log, nil
  32. }
  33. func (r *logRepository) List(ctx context.Context, filter models.LogFilter) ([]*models.Log, error) {
  34. q := sq.Select("log.*").From("log").GroupBy("log.log_id").OrderBy("log.date")
  35. if len(filter.IssueItemIDs) > 0 || len(filter.IssueIDs) > 0 {
  36. q = q.LeftJoin("log_item ON log_item.log_id = log.log_id")
  37. }
  38. if len(filter.IssueTaskIDs) > 0 || len(filter.IssueIDs) > 0 {
  39. q = q.LeftJoin("log_task ON log_task.log_id = log.log_id")
  40. }
  41. if len(filter.IssueIDs) > 0 {
  42. q = q.Where(sq.Or{
  43. sq.Eq{"log_task.issue_id": filter.IssueIDs},
  44. sq.Eq{"log_item.issue_id": filter.IssueIDs},
  45. })
  46. }
  47. if len(filter.IssueItemIDs) > 0 {
  48. q = q.Where(sq.Eq{"log_item.issue_item_id": filter.IssueItemIDs})
  49. }
  50. if len(filter.IssueTaskIDs) > 0 {
  51. q = q.Where(sq.Eq{"log_task.issue_task_id": filter.IssueTaskIDs})
  52. }
  53. if len(filter.LogIDs) > 0 {
  54. q = q.Where(sq.Eq{"log.log_id": filter.LogIDs})
  55. }
  56. if len(filter.UserIDs) > 0 {
  57. q = q.Where(sq.Eq{"log.user_id": filter.UserIDs})
  58. }
  59. if filter.FromDate != nil {
  60. q = q.Where(sq.GtOrEq{"log.date": *filter.FromDate})
  61. }
  62. if filter.ToDate != nil {
  63. q = q.Where(sq.LtOrEq{"log.date": *filter.ToDate})
  64. }
  65. query, args, err := q.ToSql()
  66. if err != nil {
  67. return nil, err
  68. }
  69. results := make([]*models.Log, 0, 16)
  70. err = r.db.SelectContext(ctx, &results, query, args...)
  71. if err != nil {
  72. if err == sql.ErrNoRows {
  73. return []*models.Log{}, nil
  74. }
  75. return nil, err
  76. }
  77. err = r.fill(ctx, results)
  78. if err != nil {
  79. return nil, err
  80. }
  81. return results, nil
  82. }
  83. func (r *logRepository) Insert(ctx context.Context, log models.Log) (*models.Log, error) {
  84. tx, err := r.db.BeginTxx(ctx, nil)
  85. if err != nil {
  86. return nil, err
  87. }
  88. log.ID = generate.LogID()
  89. _, err = tx.NamedExecContext(ctx, `
  90. INSERT INTO log (
  91. log_id, user_id, date, description
  92. ) VALUES (
  93. :log_id, :user_id, :date, :description
  94. )
  95. `, log)
  96. if err != nil {
  97. _ = tx.Rollback()
  98. return nil, err
  99. }
  100. for _, item := range log.Items {
  101. item.LogID = log.ID
  102. _, err = tx.NamedExecContext(ctx, `
  103. INSERT INTO log_item (
  104. log_id, issue_id, issue_item_id, amount
  105. ) VALUES (
  106. :log_id, :issue_id, :issue_item_id, :amount
  107. )
  108. `, item)
  109. if err != nil {
  110. _ = tx.Rollback()
  111. return nil, err
  112. }
  113. }
  114. for _, task := range log.Tasks {
  115. task.LogID = log.ID
  116. _, err = tx.NamedExecContext(ctx, `
  117. INSERT INTO log_task (
  118. log_id, issue_id, issue_task_id, units, duration
  119. ) VALUES (
  120. :log_id, :issue_id, :issue_task_id, :units, :duration
  121. )
  122. `, task)
  123. if err != nil {
  124. _ = tx.Rollback()
  125. return nil, err
  126. }
  127. }
  128. err = tx.Commit()
  129. if err != nil {
  130. _ = tx.Rollback()
  131. return nil, err
  132. }
  133. return &log, nil
  134. }
  135. func (r *logRepository) Save(ctx context.Context, log models.Log) error {
  136. tx, err := r.db.BeginTxx(ctx, nil)
  137. if err != nil {
  138. return err
  139. }
  140. _, err = tx.NamedExecContext(ctx, `
  141. UPDATE log SET
  142. date=:date,
  143. description=:description
  144. WHERE log_id=:log_id
  145. `, log)
  146. if err != nil {
  147. _ = tx.Rollback()
  148. return err
  149. }
  150. _, err = tx.ExecContext(ctx, "DELETE FROM log_item WHERE log_id=?", log.ID)
  151. if err != nil {
  152. _ = tx.Rollback()
  153. return err
  154. }
  155. _, err = tx.ExecContext(ctx, "DELETE FROM log_task WHERE log_id=?", log.ID)
  156. if err != nil {
  157. _ = tx.Rollback()
  158. return err
  159. }
  160. for _, item := range log.Items {
  161. _, err = tx.NamedExecContext(ctx, `
  162. INSERT INTO log_item (
  163. log_id, issue_id, issue_item_id, amount
  164. ) VALUES (
  165. :log_id, :issue_id, :issue_item_id, :amount
  166. )
  167. `, item)
  168. if err != nil {
  169. _ = tx.Rollback()
  170. return err
  171. }
  172. }
  173. for _, task := range log.Tasks {
  174. _, err = tx.NamedExecContext(ctx, `
  175. INSERT INTO log_task (
  176. log_id, issue_id, issue_task_id, units, duration
  177. ) VALUES (
  178. :log_id, :issue_id, :issue_task_id, :units, :duration
  179. )
  180. `, task)
  181. if err != nil {
  182. _ = tx.Rollback()
  183. return err
  184. }
  185. }
  186. err = tx.Commit()
  187. if err != nil {
  188. _ = tx.Rollback()
  189. return err
  190. }
  191. return nil
  192. }
  193. func (r *logRepository) Delete(ctx context.Context, log models.Log) error {
  194. tx, err := r.db.BeginTxx(ctx, nil)
  195. if err != nil {
  196. return err
  197. }
  198. _, err = tx.ExecContext(ctx, "DELETE FROM log WHERE log_id=?", log.ID)
  199. if err != nil {
  200. _ = tx.Rollback()
  201. return err
  202. }
  203. _, err = tx.ExecContext(ctx, "DELETE FROM log_item WHERE log_id=?", log.ID)
  204. if err != nil {
  205. _ = tx.Rollback()
  206. return err
  207. }
  208. _, err = tx.ExecContext(ctx, "DELETE FROM log_task WHERE log_id=?", log.ID)
  209. if err != nil {
  210. _ = tx.Rollback()
  211. return err
  212. }
  213. return tx.Commit()
  214. }
  215. func (r *logRepository) fill(ctx context.Context, logs []*models.Log) error {
  216. logMap := make(map[string]int, len(logs))
  217. ids := make([]string, len(logs))
  218. for i, log := range logs {
  219. ids[i] = log.ID
  220. logMap[log.ID] = i
  221. }
  222. itemsQuery, itemsArgs, err := sq.Select("*").From("log_item").Where(sq.Eq{"log_id": ids}).ToSql()
  223. if err != nil {
  224. return err
  225. }
  226. tasksQuery, tasksArgs, err := sq.Select("*").From("log_task").Where(sq.Eq{"log_id": ids}).ToSql()
  227. if err != nil {
  228. return err
  229. }
  230. items := make([]models.LogItem, 0, len(logs)*3)
  231. err = r.db.SelectContext(ctx, &items, itemsQuery, itemsArgs...)
  232. if err != nil {
  233. return err
  234. }
  235. for _, item := range items {
  236. log := logs[logMap[item.LogID]]
  237. log.Items = append(log.Items, item)
  238. }
  239. tasks := make([]models.LogTask, 0, len(logs)*3)
  240. err = r.db.SelectContext(ctx, &tasks, tasksQuery, tasksArgs...)
  241. if err != nil {
  242. return err
  243. }
  244. for _, task := range tasks {
  245. log := logs[logMap[task.LogID]]
  246. log.Tasks = append(log.Tasks, task)
  247. }
  248. return nil
  249. }