dashboard.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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. "github.com/grafana/grafana/pkg/services/search"
  10. )
  11. func init() {
  12. bus.AddHandler("sql", SaveDashboard)
  13. bus.AddHandler("sql", GetDashboard)
  14. bus.AddHandler("sql", GetDashboards)
  15. bus.AddHandler("sql", DeleteDashboard)
  16. bus.AddHandler("sql", SearchDashboards)
  17. bus.AddHandler("sql", GetDashboardTags)
  18. bus.AddHandler("sql", GetDashboardSlugById)
  19. }
  20. func SaveDashboard(cmd *m.SaveDashboardCommand) error {
  21. return inTransaction(func(sess *xorm.Session) error {
  22. dash := cmd.GetDashboardModel()
  23. // try get existing dashboard
  24. var existing, sameTitle m.Dashboard
  25. if dash.Id > 0 {
  26. dashWithIdExists, err := sess.Where("id=? AND org_id=?", dash.Id, dash.OrgId).Get(&existing)
  27. if err != nil {
  28. return err
  29. }
  30. if !dashWithIdExists {
  31. return m.ErrDashboardNotFound
  32. }
  33. // check for is someone else has written in between
  34. if dash.Version != existing.Version {
  35. if cmd.Overwrite {
  36. dash.Version = existing.Version
  37. } else {
  38. return m.ErrDashboardVersionMismatch
  39. }
  40. }
  41. }
  42. sameTitleExists, err := sess.Where("org_id=? AND slug=?", dash.OrgId, dash.Slug).Get(&sameTitle)
  43. if err != nil {
  44. return err
  45. }
  46. if sameTitleExists {
  47. // another dashboard with same name
  48. if dash.Id != sameTitle.Id {
  49. if cmd.Overwrite {
  50. dash.Id = sameTitle.Id
  51. } else {
  52. return m.ErrDashboardWithSameNameExists
  53. }
  54. }
  55. }
  56. affectedRows := int64(0)
  57. if dash.Id == 0 {
  58. metrics.M_Models_Dashboard_Insert.Inc(1)
  59. affectedRows, err = sess.Insert(dash)
  60. } else {
  61. dash.Version += 1
  62. dash.Data.Set("version", dash.Version)
  63. affectedRows, err = sess.Id(dash.Id).Update(dash)
  64. }
  65. if affectedRows == 0 {
  66. return m.ErrDashboardNotFound
  67. }
  68. // delete existing tabs
  69. _, err = sess.Exec("DELETE FROM dashboard_tag WHERE dashboard_id=?", dash.Id)
  70. if err != nil {
  71. return err
  72. }
  73. // insert new tags
  74. tags := dash.GetTags()
  75. if len(tags) > 0 {
  76. for _, tag := range tags {
  77. if _, err := sess.Insert(&DashboardTag{DashboardId: dash.Id, Term: tag}); err != nil {
  78. return err
  79. }
  80. }
  81. }
  82. cmd.Result = dash
  83. return err
  84. })
  85. }
  86. func GetDashboard(query *m.GetDashboardQuery) error {
  87. dashboard := m.Dashboard{Slug: query.Slug, OrgId: query.OrgId}
  88. has, err := x.Get(&dashboard)
  89. if err != nil {
  90. return err
  91. } else if has == false {
  92. return m.ErrDashboardNotFound
  93. }
  94. dashboard.Data.Set("id", dashboard.Id)
  95. query.Result = &dashboard
  96. return nil
  97. }
  98. type DashboardSearchProjection struct {
  99. Id int64
  100. Title string
  101. Slug string
  102. Term string
  103. }
  104. func SearchDashboards(query *search.FindPersistedDashboardsQuery) error {
  105. var sql bytes.Buffer
  106. params := make([]interface{}, 0)
  107. sql.WriteString(`SELECT
  108. dashboard.id,
  109. dashboard.title,
  110. dashboard.slug,
  111. dashboard_tag.term
  112. FROM dashboard
  113. LEFT OUTER JOIN dashboard_tag on dashboard_tag.dashboard_id = dashboard.id`)
  114. if query.IsStarred {
  115. sql.WriteString(" INNER JOIN star on star.dashboard_id = dashboard.id")
  116. }
  117. sql.WriteString(` WHERE dashboard.org_id=?`)
  118. params = append(params, query.OrgId)
  119. if query.IsStarred {
  120. sql.WriteString(` AND star.user_id=?`)
  121. params = append(params, query.UserId)
  122. }
  123. if len(query.DashboardIds) > 0 {
  124. sql.WriteString(" AND (")
  125. for i, dashboardId := range query.DashboardIds {
  126. if i != 0 {
  127. sql.WriteString(" OR")
  128. }
  129. sql.WriteString(" dashboard.id = ?")
  130. params = append(params, dashboardId)
  131. }
  132. sql.WriteString(")")
  133. }
  134. if len(query.Title) > 0 {
  135. sql.WriteString(" AND dashboard.title " + dialect.LikeStr() + " ?")
  136. params = append(params, "%"+query.Title+"%")
  137. }
  138. sql.WriteString(fmt.Sprintf(" ORDER BY dashboard.title ASC LIMIT 1000"))
  139. var res []DashboardSearchProjection
  140. err := x.Sql(sql.String(), params...).Find(&res)
  141. if err != nil {
  142. return err
  143. }
  144. query.Result = make([]*search.Hit, 0)
  145. hits := make(map[int64]*search.Hit)
  146. for _, item := range res {
  147. hit, exists := hits[item.Id]
  148. if !exists {
  149. hit = &search.Hit{
  150. Id: item.Id,
  151. Title: item.Title,
  152. Uri: "db/" + item.Slug,
  153. Type: search.DashHitDB,
  154. Tags: []string{},
  155. }
  156. query.Result = append(query.Result, hit)
  157. hits[item.Id] = hit
  158. }
  159. if len(item.Term) > 0 {
  160. hit.Tags = append(hit.Tags, item.Term)
  161. }
  162. }
  163. return err
  164. }
  165. func GetDashboardTags(query *m.GetDashboardTagsQuery) error {
  166. sql := `SELECT
  167. COUNT(*) as count,
  168. term
  169. FROM dashboard
  170. INNER JOIN dashboard_tag on dashboard_tag.dashboard_id = dashboard.id
  171. WHERE dashboard.org_id=?
  172. GROUP BY term`
  173. query.Result = make([]*m.DashboardTagCloudItem, 0)
  174. sess := x.Sql(sql, query.OrgId)
  175. err := sess.Find(&query.Result)
  176. return err
  177. }
  178. func DeleteDashboard(cmd *m.DeleteDashboardCommand) error {
  179. return inTransaction2(func(sess *session) error {
  180. dashboard := m.Dashboard{Slug: cmd.Slug, OrgId: cmd.OrgId}
  181. has, err := x.Get(&dashboard)
  182. if err != nil {
  183. return err
  184. } else if has == false {
  185. return m.ErrDashboardNotFound
  186. }
  187. deletes := []string{
  188. "DELETE FROM dashboard_tag WHERE dashboard_id = ? ",
  189. "DELETE FROM star WHERE dashboard_id = ? ",
  190. "DELETE FROM dashboard WHERE id = ?",
  191. }
  192. for _, sql := range deletes {
  193. _, err := sess.Exec(sql, dashboard.Id)
  194. if err != nil {
  195. return err
  196. }
  197. }
  198. return nil
  199. })
  200. }
  201. func GetDashboards(query *m.GetDashboardsQuery) error {
  202. if len(query.DashboardIds) == 0 {
  203. return m.ErrCommandValidationFailed
  204. }
  205. var dashboards = make([]m.Dashboard, 0)
  206. err := x.In("id", query.DashboardIds).Find(&dashboards)
  207. query.Result = &dashboards
  208. if err != nil {
  209. return err
  210. }
  211. return nil
  212. }
  213. func GetDashboardSlugById(query *m.GetDashboardSlugByIdQuery) error {
  214. dashboard := m.Dashboard{Id: query.Id}
  215. has, err := x.Get(&dashboard)
  216. query.Result = dashboard.Slug
  217. if err != nil {
  218. return err
  219. } else if has == false {
  220. return m.ErrDashboardNotFound
  221. }
  222. return nil
  223. }