diff --git a/pkg/api/search.go b/pkg/api/search.go index a28d0275a3b..042a008ef82 100644 --- a/pkg/api/search.go +++ b/pkg/api/search.go @@ -39,6 +39,8 @@ func (hs *HTTPServer) Search(c *models.ReqContext) response.Response { } } + dbUIDs := c.QueryStrings("dashboardUID") + folderIDs := make([]int64, 0) for _, id := range c.QueryStrings("folderIds") { folderID, err := strconv.ParseInt(id, 10, 64) @@ -47,19 +49,24 @@ func (hs *HTTPServer) Search(c *models.ReqContext) response.Response { } } + if len(dbIDs) > 0 && len(dbUIDs) > 0 { + return response.Error(400, "search supports UIDs or IDs, not both", nil) + } + searchQuery := search.Query{ - Title: query, - Tags: tags, - SignedInUser: c.SignedInUser, - Limit: limit, - Page: page, - IsStarred: starred == "true", - OrgId: c.OrgId, - DashboardIds: dbIDs, - Type: dashboardType, - FolderIds: folderIDs, - Permission: permission, - Sort: sort, + Title: query, + Tags: tags, + SignedInUser: c.SignedInUser, + Limit: limit, + Page: page, + IsStarred: starred == "true", + OrgId: c.OrgId, + DashboardIds: dbIDs, + DashboardUIDs: dbUIDs, + Type: dashboardType, + FolderIds: folderIDs, + Permission: permission, + Sort: sort, } err := hs.SearchService.SearchHandler(c.Req.Context(), &searchQuery) diff --git a/pkg/models/search.go b/pkg/models/search.go index 2bc351678e7..db6f9090c2a 100644 --- a/pkg/models/search.go +++ b/pkg/models/search.go @@ -20,18 +20,19 @@ type SortOptionFilter interface { } type FindPersistedDashboardsQuery struct { - Title string - OrgId int64 - SignedInUser *SignedInUser - IsStarred bool - DashboardIds []int64 - Type string - FolderIds []int64 - Tags []string - Limit int64 - Page int64 - Permission PermissionType - Sort SortOption + Title string + OrgId int64 + SignedInUser *SignedInUser + IsStarred bool + DashboardIds []int64 + DashboardUIDs []string + Type string + FolderIds []int64 + Tags []string + Limit int64 + Page int64 + Permission PermissionType + Sort SortOption Filters []interface{} diff --git a/pkg/services/dashboards/database/database.go b/pkg/services/dashboards/database/database.go index 80a4d450f22..de18a96b1f2 100644 --- a/pkg/services/dashboards/database/database.go +++ b/pkg/services/dashboards/database/database.go @@ -964,8 +964,10 @@ func (d *DashboardStore) FindDashboards(ctx context.Context, query *models.FindP filters = append(filters, searchstore.TagsFilter{Tags: query.Tags}) } - if len(query.DashboardIds) > 0 { - filters = append(filters, searchstore.DashboardFilter{IDs: query.DashboardIds}) + if len(query.DashboardUIDs) > 0 { + filters = append(filters, searchstore.DashboardFilter{UIDs: query.DashboardUIDs}) + } else if len(query.DashboardIds) > 0 { + filters = append(filters, searchstore.DashboardIDFilter{IDs: query.DashboardIds}) } if query.IsStarred { diff --git a/pkg/services/search/service.go b/pkg/services/search/service.go index 6cfddb57eb7..23d640b67e5 100644 --- a/pkg/services/search/service.go +++ b/pkg/services/search/service.go @@ -27,18 +27,19 @@ func ProvideService(cfg *setting.Cfg, sqlstore *sqlstore.SQLStore, starService s } type Query struct { - Title string - Tags []string - OrgId int64 - SignedInUser *models.SignedInUser - Limit int64 - Page int64 - IsStarred bool - Type string - DashboardIds []int64 - FolderIds []int64 - Permission models.PermissionType - Sort string + Title string + Tags []string + OrgId int64 + SignedInUser *models.SignedInUser + Limit int64 + Page int64 + IsStarred bool + Type string + DashboardUIDs []string + DashboardIds []int64 + FolderIds []int64 + Permission models.PermissionType + Sort string Result models.HitList } @@ -58,16 +59,17 @@ type SearchService struct { func (s *SearchService) SearchHandler(ctx context.Context, query *Query) error { dashboardQuery := models.FindPersistedDashboardsQuery{ - Title: query.Title, - SignedInUser: query.SignedInUser, - IsStarred: query.IsStarred, - DashboardIds: query.DashboardIds, - Type: query.Type, - FolderIds: query.FolderIds, - Tags: query.Tags, - Limit: query.Limit, - Page: query.Page, - Permission: query.Permission, + Title: query.Title, + SignedInUser: query.SignedInUser, + IsStarred: query.IsStarred, + DashboardUIDs: query.DashboardUIDs, + DashboardIds: query.DashboardIds, + Type: query.Type, + FolderIds: query.FolderIds, + Tags: query.Tags, + Limit: query.Limit, + Page: query.Page, + Permission: query.Permission, } if sortOpt, exists := s.sortOptions[query.Sort]; exists { diff --git a/pkg/services/sqlstore/searchstore/filters.go b/pkg/services/sqlstore/searchstore/filters.go index 99810190c38..5d82e1720f9 100644 --- a/pkg/services/sqlstore/searchstore/filters.go +++ b/pkg/services/sqlstore/searchstore/filters.go @@ -95,14 +95,22 @@ func (f FolderFilter) Where() (string, []interface{}) { return sqlIDin("dashboard.folder_id", f.IDs) } -type DashboardFilter struct { +type DashboardIDFilter struct { IDs []int64 } -func (f DashboardFilter) Where() (string, []interface{}) { +func (f DashboardIDFilter) Where() (string, []interface{}) { return sqlIDin("dashboard.id", f.IDs) } +type DashboardFilter struct { + UIDs []string +} + +func (f DashboardFilter) Where() (string, []interface{}) { + return sqlUIDin("dashboard.uid", f.UIDs) +} + type TagsFilter struct { Tags []string } @@ -150,6 +158,21 @@ func sqlIDin(column string, ids []int64) (string, []interface{}) { return fmt.Sprintf("%s IN %s", column, sqlArray), params } +func sqlUIDin(column string, uids []string) (string, []interface{}) { + length := len(uids) + if length < 1 { + return "", nil + } + + sqlArray := "(?" + strings.Repeat(",?", length-1) + ")" + + params := []interface{}{} + for _, id := range uids { + params = append(params, id) + } + return fmt.Sprintf("%s IN %s", column, sqlArray), params +} + // FolderWithAlertsFilter applies a filter that makes the result contain only folders that contain alert rules type FolderWithAlertsFilter struct { } diff --git a/public/app/features/search/service/sql.ts b/public/app/features/search/service/sql.ts index 96e68ac6946..d20b38b7001 100644 --- a/public/app/features/search/service/sql.ts +++ b/public/app/features/search/service/sql.ts @@ -16,11 +16,9 @@ interface APIQuery { page?: number; type?: string; // DashboardIds []int64 + dashboardUID?: string[]; folderIds?: number[]; sort?: string; - - // NEW!!!! TODO TODO: needs backend support? - dashboardUIDs?: string[]; } // Internal object to hold folderId @@ -57,8 +55,7 @@ export class SQLSearcher implements GrafanaSearcher { } if (query.uid) { - q.query = query.uid.join(', '); // TODO! this will return nothing - q.dashboardUIDs = query.uid; + q.dashboardUID = query.uid; } else if (query.location?.length) { let info = this.locationInfo[query.location]; if (!info) {