Query history: Add search functionality (#45932)
* Query history: Add search functionality * Add more tests * Add documentation * Fix spell errors * Update docs * Update docs * Fix lint error * Update docs/sources/http_api/query_history.md Co-authored-by: Piotr Jamróz <pm.jamroz@gmail.com> * Document limit * Run tests with postgres and mysql * Use CASE insted of IIF * Use BooleanStr instead of 1 * Change LIKE to LikeStr() * Return back integration tests * Update SQL to use Bool() everywhere * Create new tests for sorting * Update docs/sources/http_api/query_history.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/http_api/query_history.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/http_api/query_history.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/http_api/query_history.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/http_api/query_history.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Add page, count and limit to results * Remove newline * Update documentation * Update docs Co-authored-by: Piotr Jamróz <pm.jamroz@gmail.com> Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com>
This commit is contained in:
co-authored by
Piotr Jamróz
achatterjee-grafana
parent
801d751b20
commit
6e96506c23
@@ -14,6 +14,7 @@ import (
|
||||
func (s *QueryHistoryService) registerAPIEndpoints() {
|
||||
s.RouteRegister.Group("/api/query-history", func(entities routing.RouteRegister) {
|
||||
entities.Post("/", middleware.ReqSignedIn, routing.Wrap(s.createHandler))
|
||||
entities.Get("/", middleware.ReqSignedIn, routing.Wrap(s.searchHandler))
|
||||
entities.Delete("/:uid", middleware.ReqSignedIn, routing.Wrap(s.deleteHandler))
|
||||
entities.Post("/star/:uid", middleware.ReqSignedIn, routing.Wrap(s.starHandler))
|
||||
entities.Delete("/star/:uid", middleware.ReqSignedIn, routing.Wrap(s.unstarHandler))
|
||||
@@ -35,6 +36,24 @@ func (s *QueryHistoryService) createHandler(c *models.ReqContext) response.Respo
|
||||
return response.JSON(http.StatusOK, QueryHistoryResponse{Result: query})
|
||||
}
|
||||
|
||||
func (s *QueryHistoryService) searchHandler(c *models.ReqContext) response.Response {
|
||||
query := SearchInQueryHistoryQuery{
|
||||
DatasourceUIDs: c.QueryStrings("datasourceUid"),
|
||||
SearchString: c.Query("searchString"),
|
||||
OnlyStarred: c.QueryBoolWithDefault("onlyStarred", false),
|
||||
Sort: c.Query("sort"),
|
||||
Page: c.QueryInt("page"),
|
||||
Limit: c.QueryInt("limit"),
|
||||
}
|
||||
|
||||
result, err := s.SearchInQueryHistory(c.Req.Context(), c.SignedInUser, query)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "Failed to get query history", err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, QueryHistorySearchResponse{Result: result})
|
||||
}
|
||||
|
||||
func (s *QueryHistoryService) deleteHandler(c *models.ReqContext) response.Response {
|
||||
queryUID := web.Params(c.Req)[":uid"]
|
||||
if len(queryUID) > 0 && !util.IsValidShortUID(queryUID) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package queryhistory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -41,6 +42,70 @@ func (s QueryHistoryService) createQuery(ctx context.Context, user *models.Signe
|
||||
return dto, nil
|
||||
}
|
||||
|
||||
func (s QueryHistoryService) searchQueries(ctx context.Context, user *models.SignedInUser, query SearchInQueryHistoryQuery) (QueryHistorySearchResult, error) {
|
||||
var dtos []QueryHistoryDTO
|
||||
var allQueries []interface{}
|
||||
|
||||
if len(query.DatasourceUIDs) == 0 {
|
||||
return QueryHistorySearchResult{}, errors.New("no selected data source for query history search")
|
||||
}
|
||||
|
||||
if query.Page <= 0 {
|
||||
query.Page = 1
|
||||
}
|
||||
|
||||
if query.Limit <= 0 {
|
||||
query.Limit = 100
|
||||
}
|
||||
|
||||
if query.Sort == "" {
|
||||
query.Sort = "time-desc"
|
||||
}
|
||||
|
||||
err := s.SQLStore.WithDbSession(ctx, func(session *sqlstore.DBSession) error {
|
||||
dtosBuilder := sqlstore.SQLBuilder{}
|
||||
dtosBuilder.Write(`SELECT
|
||||
query_history.uid,
|
||||
query_history.datasource_uid,
|
||||
query_history.created_by,
|
||||
query_history.created_at AS created_at,
|
||||
query_history.comment,
|
||||
query_history.queries,
|
||||
`)
|
||||
writeStarredSQL(query, s.SQLStore, &dtosBuilder)
|
||||
writeFiltersSQL(query, user, s.SQLStore, &dtosBuilder)
|
||||
writeSortSQL(query, s.SQLStore, &dtosBuilder)
|
||||
writeLimitSQL(query, s.SQLStore, &dtosBuilder)
|
||||
writeOffsetSQL(query, s.SQLStore, &dtosBuilder)
|
||||
|
||||
err := session.SQL(dtosBuilder.GetSQLString(), dtosBuilder.GetParams()...).Find(&dtos)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
countBuilder := sqlstore.SQLBuilder{}
|
||||
countBuilder.Write(`SELECT
|
||||
`)
|
||||
writeStarredSQL(query, s.SQLStore, &countBuilder)
|
||||
writeFiltersSQL(query, user, s.SQLStore, &countBuilder)
|
||||
err = session.SQL(countBuilder.GetSQLString(), countBuilder.GetParams()...).Find(&allQueries)
|
||||
return err
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return QueryHistorySearchResult{}, err
|
||||
}
|
||||
|
||||
response := QueryHistorySearchResult{
|
||||
QueryHistory: dtos,
|
||||
TotalCount: len(allQueries),
|
||||
Page: query.Page,
|
||||
PerPage: query.Limit,
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s QueryHistoryService) deleteQuery(ctx context.Context, user *models.SignedInUser, UID string) (int64, error) {
|
||||
var queryID int64
|
||||
err := s.SQLStore.WithTransactionalDbSession(ctx, func(session *sqlstore.DBSession) error {
|
||||
|
||||
@@ -34,13 +34,22 @@ type CreateQueryInQueryHistoryCommand struct {
|
||||
Queries *simplejson.Json `json:"queries"`
|
||||
}
|
||||
|
||||
type SearchInQueryHistoryQuery struct {
|
||||
DatasourceUIDs []string `json:"datasourceUids"`
|
||||
SearchString string `json:"searchString"`
|
||||
OnlyStarred bool `json:"onlyStarred"`
|
||||
Sort string `json:"sort"`
|
||||
Page int `json:"page"`
|
||||
Limit int `json:"limit"`
|
||||
}
|
||||
|
||||
type PatchQueryCommentInQueryHistoryCommand struct {
|
||||
Comment string `json:"comment"`
|
||||
}
|
||||
|
||||
type QueryHistoryDTO struct {
|
||||
UID string `json:"uid"`
|
||||
DatasourceUID string `json:"datasourceUid"`
|
||||
UID string `json:"uid" xorm:"uid"`
|
||||
DatasourceUID string `json:"datasourceUid" xorm:"datasource_uid"`
|
||||
CreatedBy int64 `json:"createdBy"`
|
||||
CreatedAt int64 `json:"createdAt"`
|
||||
Comment string `json:"comment"`
|
||||
@@ -53,6 +62,17 @@ type QueryHistoryResponse struct {
|
||||
Result QueryHistoryDTO `json:"result"`
|
||||
}
|
||||
|
||||
type QueryHistorySearchResult struct {
|
||||
TotalCount int `json:"totalCount"`
|
||||
QueryHistory []QueryHistoryDTO `json:"queryHistory"`
|
||||
Page int `json:"page"`
|
||||
PerPage int `json:"perPage"`
|
||||
}
|
||||
|
||||
type QueryHistorySearchResponse struct {
|
||||
Result QueryHistorySearchResult `json:"result"`
|
||||
}
|
||||
|
||||
// DeleteQueryFromQueryHistoryResponse is the response struct for deleting a query from query history
|
||||
type DeleteQueryFromQueryHistoryResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
|
||||
@@ -28,6 +28,7 @@ func ProvideService(cfg *setting.Cfg, sqlStore *sqlstore.SQLStore, routeRegister
|
||||
|
||||
type Service interface {
|
||||
CreateQueryInQueryHistory(ctx context.Context, user *models.SignedInUser, cmd CreateQueryInQueryHistoryCommand) (QueryHistoryDTO, error)
|
||||
SearchInQueryHistory(ctx context.Context, user *models.SignedInUser, query SearchInQueryHistoryQuery) (QueryHistorySearchResult, error)
|
||||
DeleteQueryFromQueryHistory(ctx context.Context, user *models.SignedInUser, UID string) (int64, error)
|
||||
PatchQueryCommentInQueryHistory(ctx context.Context, user *models.SignedInUser, UID string, cmd PatchQueryCommentInQueryHistoryCommand) (QueryHistoryDTO, error)
|
||||
StarQueryInQueryHistory(ctx context.Context, user *models.SignedInUser, UID string) (QueryHistoryDTO, error)
|
||||
@@ -45,6 +46,10 @@ func (s QueryHistoryService) CreateQueryInQueryHistory(ctx context.Context, user
|
||||
return s.createQuery(ctx, user, cmd)
|
||||
}
|
||||
|
||||
func (s QueryHistoryService) SearchInQueryHistory(ctx context.Context, user *models.SignedInUser, query SearchInQueryHistoryQuery) (QueryHistorySearchResult, error) {
|
||||
return s.searchQueries(ctx, user, query)
|
||||
}
|
||||
|
||||
func (s QueryHistoryService) DeleteQueryFromQueryHistory(ctx context.Context, user *models.SignedInUser, UID string) (int64, error) {
|
||||
return s.deleteQuery(ctx, user, UID)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package queryhistory
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package queryhistory
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package queryhistory
|
||||
|
||||
import (
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package queryhistory
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetQueriesFromQueryHistory(t *testing.T) {
|
||||
testScenario(t, "When users tries to get query without datasourceUid, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
require.Equal(t, 500, resp.Status())
|
||||
})
|
||||
|
||||
testScenario(t, "When users tries to get query in empty query history, it should return empty result",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", "test")
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 0, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithQueryInQueryHistory(t, "When users tries to get query with valid datasourceUid, it should succeed",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", sc.initialResult.Result.DatasourceUID)
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 1, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries with datasourceUid, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", sc.initialResult.Result.DatasourceUID)
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 2, response.Result.TotalCount)
|
||||
require.Equal(t, true, response.Result.QueryHistory[0].Starred)
|
||||
require.Equal(t, false, response.Result.QueryHistory[1].Starred)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries with datasourceUid and sort, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", sc.initialResult.Result.DatasourceUID)
|
||||
sc.reqContext.Req.Form.Add("sort", "time-asc")
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 2, response.Result.TotalCount)
|
||||
require.Equal(t, false, response.Result.QueryHistory[0].Starred)
|
||||
require.Equal(t, true, response.Result.QueryHistory[1].Starred)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries with invalid datasourceUid, it should return empty result",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", "non-existent")
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 0, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries with multiple datasourceUid, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", testDsUID1)
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", testDsUID2)
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 3, response.Result.TotalCount)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get starred queries, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", testDsUID1)
|
||||
sc.reqContext.Req.Form.Add("onlyStarred", "true")
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 1, response.Result.TotalCount)
|
||||
require.Equal(t, true, response.Result.QueryHistory[0].Starred)
|
||||
})
|
||||
|
||||
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries including search string, it should return correct queries",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
sc.reqContext.Req.Form.Add("datasourceUid", testDsUID1)
|
||||
sc.reqContext.Req.Form.Add("searchString", "2")
|
||||
resp := sc.service.searchHandler(sc.reqContext)
|
||||
var response QueryHistorySearchResponse
|
||||
err := json.Unmarshal(resp.Body(), &response)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
require.Equal(t, 1, response.Result.TotalCount)
|
||||
require.Equal(t, true, response.Result.QueryHistory[0].Starred)
|
||||
})
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package queryhistory
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package queryhistory
|
||||
|
||||
import (
|
||||
@@ -6,6 +9,7 @@ import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -21,6 +25,8 @@ import (
|
||||
var (
|
||||
testOrgID = int64(1)
|
||||
testUserID = int64(1)
|
||||
testDsUID1 = "NCzh67i"
|
||||
testDsUID2 = "ABch1a1"
|
||||
)
|
||||
|
||||
type scenarioContext struct {
|
||||
@@ -37,6 +43,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
||||
t.Run(desc, func(t *testing.T) {
|
||||
ctx := web.Context{Req: &http.Request{
|
||||
Header: http.Header{},
|
||||
Form: url.Values{},
|
||||
}}
|
||||
ctx.Req.Header.Add("Content-Type", "application/json")
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
@@ -82,7 +89,7 @@ func testScenarioWithQueryInQueryHistory(t *testing.T, desc string, fn func(t *t
|
||||
|
||||
testScenario(t, desc, func(t *testing.T, sc scenarioContext) {
|
||||
command := CreateQueryInQueryHistoryCommand{
|
||||
DatasourceUID: "NCzh67i",
|
||||
DatasourceUID: testDsUID1,
|
||||
Queries: simplejson.NewFromAny(map[string]interface{}{
|
||||
"expr": "test",
|
||||
}),
|
||||
@@ -94,6 +101,50 @@ func testScenarioWithQueryInQueryHistory(t *testing.T, desc string, fn func(t *t
|
||||
})
|
||||
}
|
||||
|
||||
func testScenarioWithMultipleQueriesInQueryHistory(t *testing.T, desc string, fn func(t *testing.T, sc scenarioContext)) {
|
||||
t.Helper()
|
||||
|
||||
testScenario(t, desc, func(t *testing.T, sc scenarioContext) {
|
||||
command1 := CreateQueryInQueryHistoryCommand{
|
||||
DatasourceUID: testDsUID1,
|
||||
Queries: simplejson.NewFromAny(map[string]interface{}{
|
||||
"expr": "test",
|
||||
}),
|
||||
}
|
||||
sc.reqContext.Req.Body = mockRequestBody(command1)
|
||||
resp1 := sc.service.createHandler(sc.reqContext)
|
||||
sc.initialResult = validateAndUnMarshalResponse(t, resp1)
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
command2 := CreateQueryInQueryHistoryCommand{
|
||||
DatasourceUID: testDsUID1,
|
||||
Queries: simplejson.NewFromAny(map[string]interface{}{
|
||||
"expr": "test2",
|
||||
}),
|
||||
}
|
||||
sc.reqContext.Req.Body = mockRequestBody(command2)
|
||||
resp2 := sc.service.createHandler(sc.reqContext)
|
||||
result2 := validateAndUnMarshalResponse(t, resp2)
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result2.Result.UID})
|
||||
sc.service.starHandler(sc.reqContext)
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
command3 := CreateQueryInQueryHistoryCommand{
|
||||
DatasourceUID: testDsUID2,
|
||||
Queries: simplejson.NewFromAny(map[string]interface{}{
|
||||
"expr": "test2",
|
||||
}),
|
||||
}
|
||||
sc.reqContext.Req.Body = mockRequestBody(command3)
|
||||
resp3 := sc.service.createHandler(sc.reqContext)
|
||||
result3 := validateAndUnMarshalResponse(t, resp3)
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result3.Result.UID})
|
||||
sc.service.starHandler(sc.reqContext)
|
||||
|
||||
fn(t, sc)
|
||||
})
|
||||
}
|
||||
|
||||
func mockRequestBody(v interface{}) io.ReadCloser {
|
||||
b, _ := json.Marshal(v)
|
||||
return io.NopCloser(bytes.NewReader(b))
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package queryhistory
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
@@ -20,7 +22,6 @@ func TestUnstarQueryInQueryHistory(t *testing.T) {
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
sc.service.starHandler(sc.reqContext)
|
||||
resp := sc.service.unstarHandler(sc.reqContext)
|
||||
fmt.Println(resp)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package queryhistory
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
)
|
||||
|
||||
func writeStarredSQL(query SearchInQueryHistoryQuery, sqlStore *sqlstore.SQLStore, builder *sqlstore.SQLBuilder) {
|
||||
if query.OnlyStarred {
|
||||
builder.Write(sqlStore.Dialect.BooleanStr(true) + ` AS starred
|
||||
FROM query_history
|
||||
INNER JOIN query_history_star ON query_history_star.query_uid = query_history.uid
|
||||
`)
|
||||
} else {
|
||||
builder.Write(` CASE WHEN query_history_star.query_uid IS NULL THEN ` + sqlStore.Dialect.BooleanStr(false) + ` ELSE ` + sqlStore.Dialect.BooleanStr(true) + ` END AS starred
|
||||
FROM query_history
|
||||
LEFT JOIN query_history_star ON query_history_star.query_uid = query_history.uid
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
func writeFiltersSQL(query SearchInQueryHistoryQuery, user *models.SignedInUser, sqlStore *sqlstore.SQLStore, builder *sqlstore.SQLBuilder) {
|
||||
params := []interface{}{user.OrgId, user.UserId, "%" + query.SearchString + "%"}
|
||||
for _, uid := range query.DatasourceUIDs {
|
||||
params = append(params, uid)
|
||||
}
|
||||
var sql bytes.Buffer
|
||||
sql.WriteString(" WHERE query_history.org_id = ? AND query_history.created_by = ? AND query_history.queries " + sqlStore.Dialect.LikeStr() + " ? AND query_history.datasource_uid IN (? " + strings.Repeat(",?", len(query.DatasourceUIDs)-1) + ") ")
|
||||
builder.Write(sql.String(), params...)
|
||||
}
|
||||
|
||||
func writeSortSQL(query SearchInQueryHistoryQuery, sqlStore *sqlstore.SQLStore, builder *sqlstore.SQLBuilder) {
|
||||
if query.Sort == "time-asc" {
|
||||
builder.Write(" ORDER BY created_at ASC ")
|
||||
} else {
|
||||
builder.Write(" ORDER BY created_at DESC ")
|
||||
}
|
||||
}
|
||||
|
||||
func writeLimitSQL(query SearchInQueryHistoryQuery, sqlStore *sqlstore.SQLStore, builder *sqlstore.SQLBuilder) {
|
||||
builder.Write(" LIMIT ? ", query.Limit)
|
||||
}
|
||||
|
||||
func writeOffsetSQL(query SearchInQueryHistoryQuery, sqlStore *sqlstore.SQLStore, builder *sqlstore.SQLBuilder) {
|
||||
builder.Write(" OFFSET ? ", query.Limit*(query.Page-1))
|
||||
}
|
||||
Reference in New Issue
Block a user