dashboard.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. package sqlstore
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/go-xorm/xorm"
  6. "github.com/grafana/grafana/pkg/bus"
  7. "github.com/grafana/grafana/pkg/metrics"
  8. m "github.com/grafana/grafana/pkg/models"
  9. )
  10. func init() {
  11. bus.AddHandler("sql", SaveDashboard)
  12. bus.AddHandler("sql", GetDashboard)
  13. bus.AddHandler("sql", DeleteDashboard)
  14. bus.AddHandler("sql", SearchDashboards)
  15. bus.AddHandler("sql", GetDashboardTags)
  16. }
  17. func SaveDashboard(cmd *m.SaveDashboardCommand) error {
  18. return inTransaction(func(sess *xorm.Session) error {
  19. dash := cmd.GetDashboardModel()
  20. // try get existing dashboard
  21. var existing, sameTitle m.Dashboard
  22. if dash.Id > 0 {
  23. dashWithIdExists, err := sess.Where("id=? AND org_id=?", dash.Id, dash.OrgId).Get(&existing)
  24. if err != nil {
  25. return err
  26. }
  27. if !dashWithIdExists {
  28. return m.ErrDashboardNotFound
  29. }
  30. // check for is someone else has written in between
  31. if dash.Version != existing.Version {
  32. if cmd.Overwrite {
  33. dash.Version = existing.Version
  34. } else {
  35. return m.ErrDashboardVersionMismatch
  36. }
  37. }
  38. }
  39. sameTitleExists, err := sess.Where("org_id=? AND slug=?", dash.OrgId, dash.Slug).Get(&sameTitle)
  40. if err != nil {
  41. return err
  42. }
  43. if sameTitleExists {
  44. // another dashboard with same name
  45. if dash.Id != sameTitle.Id {
  46. if cmd.Overwrite {
  47. dash.Id = sameTitle.Id
  48. } else {
  49. return m.ErrDashboardWithSameNameExists
  50. }
  51. }
  52. }
  53. affectedRows := int64(0)
  54. if dash.Id == 0 {
  55. metrics.M_Models_Dashboard_Insert.Inc(1)
  56. affectedRows, err = sess.Insert(dash)
  57. } else {
  58. dash.Version += 1
  59. dash.Data["version"] = dash.Version
  60. affectedRows, err = sess.Id(dash.Id).Update(dash)
  61. }
  62. if affectedRows == 0 {
  63. return m.ErrDashboardNotFound
  64. }
  65. // delete existing tabs
  66. _, err = sess.Exec("DELETE FROM dashboard_tag WHERE dashboard_id=?", dash.Id)
  67. if err != nil {
  68. return err
  69. }
  70. // insert new tags
  71. tags := dash.GetTags()
  72. if len(tags) > 0 {
  73. for _, tag := range tags {
  74. if _, err := sess.Insert(&DashboardTag{DashboardId: dash.Id, Term: tag}); err != nil {
  75. return err
  76. }
  77. }
  78. }
  79. cmd.Result = dash
  80. return err
  81. })
  82. }
  83. func GetDashboard(query *m.GetDashboardQuery) error {
  84. dashboard := m.Dashboard{Slug: query.Slug, OrgId: query.OrgId}
  85. has, err := x.Get(&dashboard)
  86. if err != nil {
  87. return err
  88. } else if has == false {
  89. return m.ErrDashboardNotFound
  90. }
  91. dashboard.Data["id"] = dashboard.Id
  92. query.Result = &dashboard
  93. return nil
  94. }
  95. type DashboardSearchProjection struct {
  96. Id int64
  97. Title string
  98. Slug string
  99. Term string
  100. }
  101. func SearchDashboards(query *m.SearchDashboardsQuery) error {
  102. var sql bytes.Buffer
  103. params := make([]interface{}, 0)
  104. sql.WriteString(`SELECT
  105. dashboard.id,
  106. dashboard.title,
  107. dashboard.slug,
  108. dashboard_tag.term
  109. FROM dashboard
  110. LEFT OUTER JOIN dashboard_tag on dashboard_tag.dashboard_id = dashboard.id`)
  111. if query.IsStarred {
  112. sql.WriteString(" INNER JOIN star on star.dashboard_id = dashboard.id")
  113. }
  114. sql.WriteString(` WHERE dashboard.org_id=?`)
  115. params = append(params, query.OrgId)
  116. if query.IsStarred {
  117. sql.WriteString(` AND star.user_id=?`)
  118. params = append(params, query.UserId)
  119. }
  120. if len(query.Title) > 0 {
  121. sql.WriteString(" AND dashboard.title LIKE ?")
  122. params = append(params, "%"+query.Title+"%")
  123. }
  124. if len(query.Tag) > 0 {
  125. sql.WriteString(" AND dashboard_tag.term=?")
  126. params = append(params, query.Tag)
  127. }
  128. if query.Limit == 0 || query.Limit > 10000 {
  129. query.Limit = 300
  130. }
  131. sql.WriteString(fmt.Sprintf(" ORDER BY dashboard.title ASC LIMIT %d", query.Limit))
  132. var res []DashboardSearchProjection
  133. err := x.Sql(sql.String(), params...).Find(&res)
  134. if err != nil {
  135. return err
  136. }
  137. query.Result = make([]*m.DashboardSearchHit, 0)
  138. hits := make(map[int64]*m.DashboardSearchHit)
  139. for _, item := range res {
  140. hit, exists := hits[item.Id]
  141. if !exists {
  142. hit = &m.DashboardSearchHit{
  143. Id: item.Id,
  144. Title: item.Title,
  145. Uri: "db/" + item.Slug,
  146. Type: m.DashTypeDB,
  147. Tags: []string{},
  148. }
  149. query.Result = append(query.Result, hit)
  150. hits[item.Id] = hit
  151. }
  152. if len(item.Term) > 0 {
  153. hit.Tags = append(hit.Tags, item.Term)
  154. }
  155. }
  156. return err
  157. }
  158. func GetDashboardTags(query *m.GetDashboardTagsQuery) error {
  159. sql := `SELECT
  160. COUNT(*) as count,
  161. term
  162. FROM dashboard
  163. INNER JOIN dashboard_tag on dashboard_tag.dashboard_id = dashboard.id
  164. WHERE dashboard.org_id=?
  165. GROUP BY term`
  166. query.Result = make([]*m.DashboardTagCloudItem, 0)
  167. sess := x.Sql(sql, query.OrgId)
  168. err := sess.Find(&query.Result)
  169. return err
  170. }
  171. func DeleteDashboard(cmd *m.DeleteDashboardCommand) error {
  172. sess := x.NewSession()
  173. defer sess.Close()
  174. rawSql := "DELETE FROM dashboard WHERE org_id=? and slug=?"
  175. _, err := sess.Exec(rawSql, cmd.OrgId, cmd.Slug)
  176. return err
  177. }