annotation.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. package sqlstore
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "strings"
  7. "time"
  8. "github.com/grafana/grafana/pkg/models"
  9. "github.com/grafana/grafana/pkg/services/annotations"
  10. )
  11. type SqlAnnotationRepo struct {
  12. }
  13. func (r *SqlAnnotationRepo) Save(item *annotations.Item) error {
  14. return inTransaction(func(sess *DBSession) error {
  15. tags := models.ParseTagPairs(item.Tags)
  16. item.Tags = models.JoinTagPairs(tags)
  17. item.Created = time.Now().UnixNano() / int64(time.Millisecond)
  18. item.Updated = item.Created
  19. if item.Epoch == 0 {
  20. item.Epoch = item.Created
  21. }
  22. if _, err := sess.Table("annotation").Insert(item); err != nil {
  23. return err
  24. }
  25. if item.Tags != nil {
  26. tags, err := EnsureTagsExist(sess, tags)
  27. if err != nil {
  28. return err
  29. }
  30. for _, tag := range tags {
  31. if _, err := sess.Exec("INSERT INTO annotation_tag (annotation_id, tag_id) VALUES(?,?)", item.Id, tag.Id); err != nil {
  32. return err
  33. }
  34. }
  35. }
  36. return nil
  37. })
  38. }
  39. func (r *SqlAnnotationRepo) Update(item *annotations.Item) error {
  40. return inTransaction(func(sess *DBSession) error {
  41. var (
  42. isExist bool
  43. err error
  44. )
  45. existing := new(annotations.Item)
  46. if item.Id == 0 && item.RegionId != 0 {
  47. // Update region end time
  48. isExist, err = sess.Table("annotation").Where("region_id=? AND id!=? AND org_id=?", item.RegionId, item.RegionId, item.OrgId).Get(existing)
  49. } else {
  50. isExist, err = sess.Table("annotation").Where("id=? AND org_id=?", item.Id, item.OrgId).Get(existing)
  51. }
  52. if err != nil {
  53. return err
  54. }
  55. if !isExist {
  56. return errors.New("Annotation not found")
  57. }
  58. existing.Updated = time.Now().UnixNano() / int64(time.Millisecond)
  59. existing.Epoch = item.Epoch
  60. existing.Text = item.Text
  61. if item.RegionId != 0 {
  62. existing.RegionId = item.RegionId
  63. }
  64. if item.Tags != nil {
  65. tags, err := EnsureTagsExist(sess, models.ParseTagPairs(item.Tags))
  66. if err != nil {
  67. return err
  68. }
  69. if _, err := sess.Exec("DELETE FROM annotation_tag WHERE annotation_id = ?", existing.Id); err != nil {
  70. return err
  71. }
  72. for _, tag := range tags {
  73. if _, err := sess.Exec("INSERT INTO annotation_tag (annotation_id, tag_id) VALUES(?,?)", existing.Id, tag.Id); err != nil {
  74. return err
  75. }
  76. }
  77. }
  78. existing.Tags = item.Tags
  79. _, err = sess.Table("annotation").ID(existing.Id).Cols("epoch", "text", "region_id", "updated", "tags").Update(existing)
  80. return err
  81. })
  82. }
  83. func (r *SqlAnnotationRepo) Find(query *annotations.ItemQuery) ([]*annotations.ItemDTO, error) {
  84. var sql bytes.Buffer
  85. params := make([]interface{}, 0)
  86. sql.WriteString(`
  87. SELECT
  88. annotation.id,
  89. annotation.epoch as time,
  90. annotation.dashboard_id,
  91. annotation.panel_id,
  92. annotation.new_state,
  93. annotation.prev_state,
  94. annotation.alert_id,
  95. annotation.region_id,
  96. annotation.text,
  97. annotation.tags,
  98. annotation.data,
  99. annotation.created,
  100. annotation.updated,
  101. usr.email,
  102. usr.login,
  103. alert.name as alert_name
  104. FROM annotation
  105. LEFT OUTER JOIN ` + dialect.Quote("user") + ` as usr on usr.id = annotation.user_id
  106. LEFT OUTER JOIN alert on alert.id = annotation.alert_id
  107. `)
  108. sql.WriteString(`WHERE annotation.org_id = ?`)
  109. params = append(params, query.OrgId)
  110. if query.AnnotationId != 0 {
  111. // fmt.Print("annotation query")
  112. sql.WriteString(` AND annotation.id = ?`)
  113. params = append(params, query.AnnotationId)
  114. }
  115. if query.RegionId != 0 {
  116. sql.WriteString(` AND annotation.region_id = ?`)
  117. params = append(params, query.RegionId)
  118. }
  119. if query.AlertId != 0 {
  120. sql.WriteString(` AND annotation.alert_id = ?`)
  121. params = append(params, query.AlertId)
  122. }
  123. if query.DashboardId != 0 {
  124. sql.WriteString(` AND annotation.dashboard_id = ?`)
  125. params = append(params, query.DashboardId)
  126. }
  127. if query.PanelId != 0 {
  128. sql.WriteString(` AND annotation.panel_id = ?`)
  129. params = append(params, query.PanelId)
  130. }
  131. if query.UserId != 0 {
  132. sql.WriteString(` AND annotation.user_id = ?`)
  133. params = append(params, query.UserId)
  134. }
  135. if query.From > 0 && query.To > 0 {
  136. sql.WriteString(` AND annotation.epoch BETWEEN ? AND ?`)
  137. params = append(params, query.From, query.To)
  138. }
  139. if query.Type == "alert" {
  140. sql.WriteString(` AND annotation.alert_id > 0`)
  141. } else if query.Type == "annotation" {
  142. sql.WriteString(` AND annotation.alert_id = 0`)
  143. }
  144. if len(query.Tags) > 0 {
  145. keyValueFilters := []string{}
  146. tags := models.ParseTagPairs(query.Tags)
  147. for _, tag := range tags {
  148. if tag.Value == "" {
  149. keyValueFilters = append(keyValueFilters, "(tag."+dialect.Quote("key")+" = ?)")
  150. params = append(params, tag.Key)
  151. } else {
  152. keyValueFilters = append(keyValueFilters, "(tag."+dialect.Quote("key")+" = ? AND tag."+dialect.Quote("value")+" = ?)")
  153. params = append(params, tag.Key, tag.Value)
  154. }
  155. }
  156. if len(tags) > 0 {
  157. tagsSubQuery := fmt.Sprintf(`
  158. SELECT SUM(1) FROM annotation_tag at
  159. INNER JOIN tag on tag.id = at.tag_id
  160. WHERE at.annotation_id = annotation.id
  161. AND (
  162. %s
  163. )
  164. `, strings.Join(keyValueFilters, " OR "))
  165. if query.MatchAny {
  166. sql.WriteString(fmt.Sprintf(" AND (%s) > 0 ", tagsSubQuery))
  167. } else {
  168. sql.WriteString(fmt.Sprintf(" AND (%s) = %d ", tagsSubQuery, len(tags)))
  169. }
  170. }
  171. }
  172. if query.Limit == 0 {
  173. query.Limit = 100
  174. }
  175. sql.WriteString(" ORDER BY epoch DESC" + dialect.Limit(query.Limit))
  176. items := make([]*annotations.ItemDTO, 0)
  177. if err := x.SQL(sql.String(), params...).Find(&items); err != nil {
  178. return nil, err
  179. }
  180. return items, nil
  181. }
  182. func (r *SqlAnnotationRepo) Delete(params *annotations.DeleteParams) error {
  183. return inTransaction(func(sess *DBSession) error {
  184. var (
  185. sql string
  186. annoTagSql string
  187. queryParams []interface{}
  188. )
  189. sqlog.Info("delete", "orgId", params.OrgId)
  190. if params.RegionId != 0 {
  191. annoTagSql = "DELETE FROM annotation_tag WHERE annotation_id IN (SELECT id FROM annotation WHERE region_id = ? AND org_id = ?)"
  192. sql = "DELETE FROM annotation WHERE region_id = ? AND org_id = ?"
  193. queryParams = []interface{}{params.RegionId, params.OrgId}
  194. } else if params.Id != 0 {
  195. annoTagSql = "DELETE FROM annotation_tag WHERE annotation_id IN (SELECT id FROM annotation WHERE id = ? AND org_id = ?)"
  196. sql = "DELETE FROM annotation WHERE id = ? AND org_id = ?"
  197. queryParams = []interface{}{params.Id, params.OrgId}
  198. } else {
  199. annoTagSql = "DELETE FROM annotation_tag WHERE annotation_id IN (SELECT id FROM annotation WHERE dashboard_id = ? AND panel_id = ? AND org_id = ?)"
  200. sql = "DELETE FROM annotation WHERE dashboard_id = ? AND panel_id = ? AND org_id = ?"
  201. queryParams = []interface{}{params.DashboardId, params.PanelId, params.OrgId}
  202. }
  203. sqlOrArgs := append([]interface{}{annoTagSql}, queryParams...)
  204. if _, err := sess.Exec(sqlOrArgs...); err != nil {
  205. return err
  206. }
  207. sqlOrArgs = append([]interface{}{sql}, queryParams...)
  208. if _, err := sess.Exec(sqlOrArgs...); err != nil {
  209. return err
  210. }
  211. return nil
  212. })
  213. }