2017-05-24 19:14:39 -04:00
package sqlstore
import (
2021-11-17 10:57:37 +01:00
"context"
2018-03-21 20:26:27 +03:00
"strings"
2017-11-14 13:34:27 +03:00
2020-02-29 13:35:15 +01:00
"github.com/grafana/grafana/pkg/models"
2017-11-14 13:34:27 +03:00
"github.com/grafana/grafana/pkg/setting"
2017-05-24 19:14:39 -04:00
)
2017-06-07 14:21:40 +02:00
// GetDashboardVersion gets the dashboard version for the given dashboard ID and version number.
2021-11-17 10:57:37 +01:00
func ( ss * SQLStore ) GetDashboardVersion ( ctx context . Context , query * models . GetDashboardVersionQuery ) error {
return ss . WithDbSession ( ctx , func ( sess * DBSession ) error {
version := models . DashboardVersion {}
has , err := sess . Where ( "dashboard_version.dashboard_id=? AND dashboard_version.version=? AND dashboard.org_id=?" , query . DashboardId , query . Version , query . OrgId ).
Join ( "LEFT" , "dashboard" , `dashboard.id = dashboard_version.dashboard_id` ).
Get ( & version )
2017-06-07 14:21:40 +02:00
2021-11-17 10:57:37 +01:00
if err != nil {
return err
}
2017-05-24 19:14:39 -04:00
2021-11-17 10:57:37 +01:00
if ! has {
return models . ErrDashboardVersionNotFound
}
2017-06-07 14:21:40 +02:00
2021-11-17 10:57:37 +01:00
version . Data . Set ( "id" , version . DashboardId )
query . Result = & version
return nil
})
2017-05-24 19:14:39 -04:00
}
// GetDashboardVersions gets all dashboard versions for the given dashboard ID.
2021-11-17 10:57:37 +01:00
func ( ss * SQLStore ) GetDashboardVersions ( ctx context . Context , query * models . GetDashboardVersionsQuery ) error {
return ss . WithDbSession ( ctx , func ( sess * DBSession ) error {
if query . Limit == 0 {
query . Limit = 1000
}
2017-06-17 18:24:38 -04:00
2021-11-17 10:57:37 +01:00
err := sess . Table ( "dashboard_version" ).
Select ( `dashboard_version.id,
2017-06-01 17:57:09 -04:00
dashboard_version.dashboard_id,
dashboard_version.parent_version,
dashboard_version.restored_from,
dashboard_version.version,
dashboard_version.created,
dashboard_version.created_by as created_by_id,
dashboard_version.message,
2017-06-06 15:40:10 +02:00
dashboard_version.data,` +
2021-11-17 10:57:37 +01:00
dialect . Quote ( "user" ) + `.login as created_by` ).
Join ( "LEFT" , dialect . Quote ( "user" ), `dashboard_version.created_by = ` + dialect . Quote ( "user" ) + `.id` ).
Join ( "LEFT" , "dashboard" , `dashboard.id = dashboard_version.dashboard_id` ).
Where ( "dashboard_version.dashboard_id=? AND dashboard.org_id=?" , query . DashboardId , query . OrgId ).
OrderBy ( "dashboard_version.version DESC" ).
Limit ( query . Limit , query . Start ).
Find ( & query . Result )
if err != nil {
return err
}
2017-05-24 19:14:39 -04:00
2021-11-17 10:57:37 +01:00
if len ( query . Result ) < 1 {
return models . ErrNoVersionsForDashboardId
}
return nil
})
2017-05-24 19:14:39 -04:00
}
2017-11-14 13:34:27 +03:00
2020-04-06 11:44:14 -04:00
const MAX_VERSIONS_TO_DELETE_PER_BATCH = 100
const MAX_VERSION_DELETION_BATCHES = 50
2018-03-22 15:18:05 +03:00
2021-11-17 10:57:37 +01:00
func ( ss * SQLStore ) DeleteExpiredVersions ( ctx context . Context , cmd * models . DeleteExpiredVersionsCommand ) error {
return ss . deleteExpiredVersions ( ctx , cmd , MAX_VERSIONS_TO_DELETE_PER_BATCH , MAX_VERSION_DELETION_BATCHES )
2020-04-06 11:44:14 -04:00
}
2017-11-17 14:41:44 +01:00
2021-11-17 10:57:37 +01:00
func ( ss * SQLStore ) deleteExpiredVersions ( ctx context . Context , cmd * models . DeleteExpiredVersionsCommand , perBatch int , maxBatches int ) error {
2020-04-06 11:44:14 -04:00
versionsToKeep := setting . DashboardVersionsToKeep
if versionsToKeep < 1 {
versionsToKeep = 1
}
2018-03-21 20:26:27 +03:00
2020-04-06 11:44:14 -04:00
for batch := 0 ; batch < maxBatches ; batch ++ {
deleted := int64 ( 0 )
2021-11-17 10:57:37 +01:00
batchErr := ss . WithTransactionalDbSession ( ctx , func ( sess * DBSession ) error {
2020-04-06 11:44:14 -04:00
// Idea of this query is finding version IDs to delete based on formula:
// min_version_to_keep = min_version + (versions_count - versions_to_keep)
// where version stats is processed for each dashboard. This guarantees that we keep at least versions_to_keep
// versions, but in some cases (when versions are sparse) this number may be more.
versionIdsToDeleteQuery := `SELECT id
FROM dashboard_version, (
SELECT dashboard_id, count(version) as count, min(version) as min
FROM dashboard_version
GROUP BY dashboard_id
) AS vtd
WHERE dashboard_version.dashboard_id=vtd.dashboard_id
AND version < vtd.min + vtd.count - ?
LIMIT ?`
var versionIdsToDelete [] interface {}
err := sess . SQL ( versionIdsToDeleteQuery , versionsToKeep , perBatch ). Find ( & versionIdsToDelete )
if err != nil {
return err
}
if len ( versionIdsToDelete ) < 1 {
return nil
}
2018-03-21 21:01:15 +03:00
2020-11-11 06:21:08 +01:00
deleteExpiredSQL := `DELETE FROM dashboard_version WHERE id IN (?` + strings . Repeat ( ",?" , len ( versionIdsToDelete ) - 1 ) + `)`
sqlOrArgs := append ([] interface {}{ deleteExpiredSQL }, versionIdsToDelete ... )
2019-03-04 16:57:29 +01:00
expiredResponse , err := sess . Exec ( sqlOrArgs ... )
2018-03-21 21:01:15 +03:00
if err != nil {
return err
}
2020-04-06 11:44:14 -04:00
deleted , err = expiredResponse . RowsAffected ()
return err
})
if batchErr != nil {
return batchErr
2017-11-17 14:41:44 +01:00
}
2017-11-14 13:34:27 +03:00
2020-04-06 11:44:14 -04:00
cmd . DeletedRows += deleted
if deleted < int64 ( perBatch ) {
break
}
}
return nil
2017-11-14 13:34:27 +03:00
}