The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/storage/unified/sql/queries.go

386 lines
9.5 KiB

package sql
import (
"database/sql"
"embed"
"fmt"
"text/template"
"time"
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/storage/unified/resource"
"github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate"
)
// Templates setup.
var (
//go:embed data/*.sql
sqlTemplatesFS embed.FS
sqlTemplates = template.Must(template.New("sql").ParseFS(sqlTemplatesFS, `data/*.sql`))
)
func mustTemplate(filename string) *template.Template {
if t := sqlTemplates.Lookup(filename); t != nil {
return t
}
panic(fmt.Sprintf("template file not found: %s", filename))
}
// Templates.
var (
sqlResourceDelete = mustTemplate("resource_delete.sql")
sqlResourceInsert = mustTemplate("resource_insert.sql")
sqlResourceUpdate = mustTemplate("resource_update.sql")
sqlResourceRead = mustTemplate("resource_read.sql")
sqlResourceStats = mustTemplate("resource_stats.sql")
sqlResourceList = mustTemplate("resource_list.sql")
sqlResourceHistoryList = mustTemplate("resource_history_list.sql")
sqlResourceUpdateRV = mustTemplate("resource_update_rv.sql")
sqlResourceHistoryRead = mustTemplate("resource_history_read.sql")
sqlResourceHistoryUpdateRV = mustTemplate("resource_history_update_rv.sql")
sqlResoureceHistoryUpdateUid = mustTemplate("resource_history_update_uid.sql")
sqlResourceHistoryInsert = mustTemplate("resource_history_insert.sql")
sqlResourceHistoryPoll = mustTemplate("resource_history_poll.sql")
sqlResourceHistoryGet = mustTemplate("resource_history_get.sql")
sqlResourceHistoryDelete = mustTemplate("resource_history_delete.sql")
sqlResourceHistoryPrune = mustTemplate("resource_history_prune.sql")
sqlResourceInsertFromHistory = mustTemplate("resource_insert_from_history.sql")
// sqlResourceLabelsInsert = mustTemplate("resource_labels_insert.sql")
sqlResourceVersionGet = mustTemplate("resource_version_get.sql")
sqlResourceVersionUpdate = mustTemplate("resource_version_update.sql")
sqlResourceVersionInsert = mustTemplate("resource_version_insert.sql")
sqlResourceVersionList = mustTemplate("resource_version_list.sql")
sqlResourceBlobInsert = mustTemplate("resource_blob_insert.sql")
sqlResourceBlobQuery = mustTemplate("resource_blob_query.sql")
)
// TxOptions.
var (
ReadCommitted = &sql.TxOptions{
Isolation: sql.LevelReadCommitted,
}
ReadCommittedRO = &sql.TxOptions{
Isolation: sql.LevelReadCommitted,
ReadOnly: true,
}
RepeatableRead = &sql.TxOptions{
Isolation: sql.LevelRepeatableRead,
}
)
type sqlResourceRequest struct {
sqltemplate.SQLTemplate
GUID string
WriteEvent resource.WriteEvent
Folder string
// Useful when batch writing
ResourceVersion int64
}
func (r sqlResourceRequest) Validate() error {
return nil // TODO
}
type sqlResourceInsertFromHistoryRequest struct {
sqltemplate.SQLTemplate
Key *resource.ResourceKey
}
func (r sqlResourceInsertFromHistoryRequest) Validate() error {
if r.Key == nil {
return fmt.Errorf("missing key")
}
return nil
}
type sqlStatsRequest struct {
sqltemplate.SQLTemplate
Namespace string
Group string
Resource string
Folder string
MinCount int
}
func (r sqlStatsRequest) Validate() error {
if r.Folder != "" && r.Namespace == "" {
return fmt.Errorf("folder constraint requires a namespace")
}
return nil
}
type historyPollResponse struct {
Key resource.ResourceKey
ResourceVersion int64
PreviousRV *int64
Value []byte
Action int
Folder string
}
func (r *historyPollResponse) Results() (*historyPollResponse, error) {
return r, nil
}
type groupResourceRV map[string]map[string]int64
type sqlResourceHistoryPollRequest struct {
sqltemplate.SQLTemplate
Resource string
Group string
SinceResourceVersion int64
Response *historyPollResponse
}
func (r *sqlResourceHistoryPollRequest) Validate() error {
return nil // TODO
}
func (r *sqlResourceHistoryPollRequest) Results() (*historyPollResponse, error) {
prevRV := r.Response.PreviousRV
if prevRV == nil {
prevRV = new(int64)
}
return &historyPollResponse{
Key: resource.ResourceKey{
Namespace: r.Response.Key.Namespace,
Group: r.Response.Key.Group,
Resource: r.Response.Key.Resource,
Name: r.Response.Key.Name,
},
Folder: r.Response.Folder,
ResourceVersion: r.Response.ResourceVersion,
PreviousRV: prevRV,
Value: r.Response.Value,
Action: r.Response.Action,
}, nil
}
// sqlResourceReadRequest can be used to retrieve a row fromthe "resource" tables.
func NewReadResponse() *resource.BackendReadResponse {
return &resource.BackendReadResponse{
Key: &resource.ResourceKey{},
}
}
type sqlResourceReadRequest struct {
sqltemplate.SQLTemplate
Request *resource.ReadRequest
Response *resource.BackendReadResponse
}
func (r *sqlResourceReadRequest) Validate() error {
return nil // TODO
}
func (r *sqlResourceReadRequest) Results() (*resource.BackendReadResponse, error) {
return r.Response, nil
}
// List
type sqlResourceListRequest struct {
sqltemplate.SQLTemplate
Request *resource.ListRequest
}
func (r sqlResourceListRequest) Validate() error {
return nil // TODO
}
type historyListRequest struct {
ResourceVersion, Limit, Offset int64
Folder string
Options *resource.ListOptions
}
type sqlResourceHistoryListRequest struct {
sqltemplate.SQLTemplate
Request *historyListRequest
Response *resource.ResourceWrapper
}
func (r sqlResourceHistoryListRequest) Validate() error {
return nil // TODO
}
func (r sqlResourceHistoryListRequest) Results() (*resource.ResourceWrapper, error) {
// sqlResourceHistoryListRequest is a set-returning query. As such, it
// should not return its *Response, since that will be overwritten in the
// next call to `Scan`, so it needs to return a copy of it. Note, though,
// that it is safe to return the same `Response.Value` since `Scan`
// allocates a new slice of bytes each time.
return &resource.ResourceWrapper{
ResourceVersion: r.Response.ResourceVersion,
Value: r.Response.Value,
}, nil
}
type sqlResourceHistoryDeleteRequest struct {
sqltemplate.SQLTemplate
GUID string
Namespace string
Group string
Resource string
}
func (r *sqlResourceHistoryDeleteRequest) Validate() error {
if r.Namespace == "" {
return fmt.Errorf("missing namespace")
}
if r.GUID == "" {
if r.Group == "" {
return fmt.Errorf("missing group")
}
if r.Resource == "" {
return fmt.Errorf("missing resource")
}
}
return nil
}
type sqlGetHistoryRequest struct {
sqltemplate.SQLTemplate
Key *resource.ResourceKey
Trash bool // only deleted items
StartRV int64 // from NextPageToken
}
func (r sqlGetHistoryRequest) Validate() error {
return nil // TODO
}
// prune resource history
type sqlPruneHistoryRequest struct {
sqltemplate.SQLTemplate
Key *resource.ResourceKey
HistoryLimit int64
}
func (r *sqlPruneHistoryRequest) Validate() error {
if r.HistoryLimit <= 0 {
return fmt.Errorf("history limit must be greater than zero")
}
if r.Key == nil {
return fmt.Errorf("missing key")
}
if r.Key.Namespace == "" {
return fmt.Errorf("missing namespace")
}
if r.Key.Group == "" {
return fmt.Errorf("missing group")
}
if r.Key.Resource == "" {
return fmt.Errorf("missing resource")
}
return nil
}
// update resource history
type sqlResourceHistoryUpdateRequest struct {
sqltemplate.SQLTemplate
WriteEvent resource.WriteEvent
OldUID string
NewUID string
}
func (r sqlResourceHistoryUpdateRequest) Validate() error {
return nil // TODO
}
type sqlResourceBlobInsertRequest struct {
sqltemplate.SQLTemplate
Now time.Time
Info *utils.BlobInfo
Key *resource.ResourceKey
Value []byte
ContentType string
}
func (r sqlResourceBlobInsertRequest) Validate() error {
if len(r.Value) < 1 {
return fmt.Errorf("missing body")
}
return nil
}
type sqlResourceBlobQueryRequest struct {
sqltemplate.SQLTemplate
Key *resource.ResourceKey
UID string
}
func (r sqlResourceBlobQueryRequest) Validate() error {
return nil
}
// update RV
type sqlResourceUpdateRVRequest struct {
sqltemplate.SQLTemplate
GUIDToRV map[string]int64
}
func (r sqlResourceUpdateRVRequest) Validate() error {
return nil // TODO
}
// resource_version table requests.
type resourceVersionResponse struct {
ResourceVersion int64
CurrentEpoch int64
}
func (r *resourceVersionResponse) Results() (*resourceVersionResponse, error) {
return r, nil
}
type groupResourceVersion struct {
Group, Resource string
ResourceVersion int64
}
type sqlResourceVersionUpsertRequest struct {
sqltemplate.SQLTemplate
Group, Resource string
ResourceVersion int64
}
func (r sqlResourceVersionUpsertRequest) Validate() error {
return nil // TODO
}
type sqlResourceVersionGetRequest struct {
sqltemplate.SQLTemplate
Group, Resource string
ReadOnly bool
Response *resourceVersionResponse
}
func (r sqlResourceVersionGetRequest) Validate() error {
return nil // TODO
}
func (r sqlResourceVersionGetRequest) Results() (*resourceVersionResponse, error) {
return &resourceVersionResponse{
ResourceVersion: r.Response.ResourceVersion,
CurrentEpoch: r.Response.CurrentEpoch,
}, nil
}
type sqlResourceVersionListRequest struct {
sqltemplate.SQLTemplate
*groupResourceVersion
}
func (r *sqlResourceVersionListRequest) Validate() error {
return nil // TODO
}
func (r *sqlResourceVersionListRequest) Results() (*groupResourceVersion, error) {
x := *r.groupResourceVersion
return &x, nil
}