mirror of
https://github.com/grafana/grafana.git
synced 2025-08-01 01:31:50 +08:00
86 lines
1.8 KiB
Go
86 lines
1.8 KiB
Go
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()
|
|
}
|