annotation.go 6.5 KB

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