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/sqltemplate/args.go

85 lines
1.8 KiB

package sqltemplate
import (
"errors"
"reflect"
"strings"
)
// Args errors.
var (
ErrInvalidArgList = errors.New("invalid arglist")
)
// Args keeps the data that needs to be passed to the engine for execution in
// the right order. Add it to your data types passed to SQLTemplate, either by
// embedding or with a named struct field if its Arg method would clash with
// another struct field.
type args struct {
d interface{ ArgPlaceholder(argNum int) string }
values []any
}
func NewArgs(d Dialect) Args {
return &args{
d: d,
}
}
// Arg can be called from within templates to pass arguments to the SQL driver
// to use in the execution of the query.
func (a *args) Arg(x any) string {
a.values = append(a.values, x)
return a.d.ArgPlaceholder(len(a.values))
}
// ArgList returns a comma separated list of `?` placeholders for each element
// in the provided slice argument, calling Arg for each of them.
// Example struct:
//
// type sqlMyRequest struct {
// *sqltemplate.SQLTemplate
// IDs []int64
// }
//
// Example usage in a SQL template:
//
// DELETE FROM {{ .Ident "mytab" }}
// WHERE id IN ( {{ argList . .IDs }} )
// ;
func (a *args) ArgList(slice reflect.Value) (string, error) {
if !slice.IsValid() || slice.Kind() != reflect.Slice {
return "", ErrInvalidArgList
}
sliceLen := slice.Len()
if sliceLen == 0 {
return "", nil
}
var b strings.Builder
b.Grow(3*sliceLen - 2) // the list will be ?, ?, ?
for i, l := 0, slice.Len(); i < l; i++ {
if i > 0 {
b.WriteString(", ")
}
b.WriteString(a.Arg(slice.Index(i).Interface()))
}
return b.String(), nil
}
func (a *args) Reset() {
a.values = nil
}
func (a *args) GetArgs() []any {
return a.values
}
type Args interface {
Arg(x any) string
ArgList(slice reflect.Value) (string, error)
GetArgs() []any
Reset()
}