mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Unistore Chore: Add OTEL testing harness (#94835)
* add testing harness * fix mockery and linters * fix data race in tests * fix data race in tests * reduce cardinality of data
This commit is contained in:
parent
8b9bb2acf6
commit
cf08f6762d
@ -357,7 +357,7 @@ func (b *backend) ListIterator(ctx context.Context, req *resource.ListRequest, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
type listIter struct {
|
type listIter struct {
|
||||||
rows *sql.Rows
|
rows db.Rows
|
||||||
offset int64
|
offset int64
|
||||||
listRV int64
|
listRV int64
|
||||||
|
|
||||||
|
@ -28,6 +28,30 @@ func (d sqlDB) DriverName() string {
|
|||||||
return d.driverName
|
return d.driverName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d sqlDB) BeginTx(ctx context.Context, opts *sql.TxOptions) (db.Tx, error) {
|
func (d sqlDB) QueryContext(ctx context.Context, query string, args ...any) (db.Rows, error) {
|
||||||
return d.DB.BeginTx(ctx, opts)
|
return d.DB.QueryContext(ctx, query, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d sqlDB) QueryRowContext(ctx context.Context, query string, args ...any) db.Row {
|
||||||
|
return d.DB.QueryRowContext(ctx, query, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d sqlDB) BeginTx(ctx context.Context, opts *sql.TxOptions) (db.Tx, error) {
|
||||||
|
tx, err := d.DB.BeginTx(ctx, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return sqlTx{tx}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type sqlTx struct {
|
||||||
|
*sql.Tx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d sqlTx) QueryContext(ctx context.Context, query string, args ...any) (db.Rows, error) {
|
||||||
|
return d.Tx.QueryContext(ctx, query, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d sqlTx) QueryRowContext(ctx context.Context, query string, args ...any) db.Row {
|
||||||
|
return d.Tx.QueryRowContext(ctx, query, args...)
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
func TestDB_BeginTx(t *testing.T) {
|
func TestDB_BeginTx(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
registerTestSQLDrivers()
|
||||||
ctx := testutil.NewDefaultTestContext(t)
|
ctx := testutil.NewDefaultTestContext(t)
|
||||||
|
|
||||||
sqlDB, err := sql.Open(driverWithIsolationLevelName, "")
|
sqlDB, err := sql.Open(driverWithIsolationLevelName, "")
|
||||||
|
@ -60,6 +60,7 @@ type resourceDBProvider struct {
|
|||||||
cfg *setting.Cfg
|
cfg *setting.Cfg
|
||||||
log log.Logger
|
log log.Logger
|
||||||
migrateFunc func(context.Context, *xorm.Engine, *setting.Cfg) error
|
migrateFunc func(context.Context, *xorm.Engine, *setting.Cfg) error
|
||||||
|
tracer trace.Tracer
|
||||||
registerMetrics bool
|
registerMetrics bool
|
||||||
logQueries bool
|
logQueries bool
|
||||||
}
|
}
|
||||||
@ -77,6 +78,7 @@ func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer trace.
|
|||||||
log: log.New("entity-db"),
|
log: log.New("entity-db"),
|
||||||
logQueries: getter.Bool("log_queries"),
|
logQueries: getter.Bool("log_queries"),
|
||||||
migrateFunc: migrations.MigrateResourceStore,
|
migrateFunc: migrations.MigrateResourceStore,
|
||||||
|
tracer: tracer,
|
||||||
}
|
}
|
||||||
|
|
||||||
dbType := getter.String("type")
|
dbType := getter.String("type")
|
||||||
@ -145,5 +147,7 @@ func (p *resourceDBProvider) init(ctx context.Context) (db.DB, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewDB(p.engine.DB().DB, p.engine.Dialect().DriverName()), nil
|
d := NewDB(p.engine.DB().DB, p.engine.Dialect().DriverName())
|
||||||
|
|
||||||
|
return d, nil
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@ -111,8 +112,18 @@ func newTestInfraDB(t *testing.T, m cfgMap) infraDB.DB {
|
|||||||
return sqlstoreDB
|
return sqlstoreDB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// globalUnprotectedMutableState controls access to global mutable state found
|
||||||
|
// in the `setting` package that is not appropriately protected. This would
|
||||||
|
// ideally be a part of some struct instead of being global, be protected if it
|
||||||
|
// needs to change, and be unmutable once it no longer needs to change. Example:
|
||||||
|
// `setting.AppUrl`. Nothing can run in parallel because of this.
|
||||||
|
// TODO: fix that.
|
||||||
|
var globalUnprotectedMutableState sync.Mutex
|
||||||
|
|
||||||
func newCfgFromIniMap(t *testing.T, m cfgMap) *setting.Cfg {
|
func newCfgFromIniMap(t *testing.T, m cfgMap) *setting.Cfg {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
globalUnprotectedMutableState.Lock()
|
||||||
|
defer globalUnprotectedMutableState.Unlock()
|
||||||
cfg, err := setting.NewCfgFromINIFile(newTestINIFile(t, m))
|
cfg, err := setting.NewCfgFromINIFile(newTestINIFile(t, m))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return cfg
|
return cfg
|
||||||
|
@ -245,7 +245,7 @@ func (_c *DB_PingContext_Call) RunAndReturn(run func(context.Context) error) *DB
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryContext provides a mock function with given fields: ctx, query, args
|
// QueryContext provides a mock function with given fields: ctx, query, args
|
||||||
func (_m *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
|
func (_m *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (db.Rows, error) {
|
||||||
var _ca []interface{}
|
var _ca []interface{}
|
||||||
_ca = append(_ca, ctx, query)
|
_ca = append(_ca, ctx, query)
|
||||||
_ca = append(_ca, args...)
|
_ca = append(_ca, args...)
|
||||||
@ -255,16 +255,16 @@ func (_m *DB) QueryContext(ctx context.Context, query string, args ...interface{
|
|||||||
panic("no return value specified for QueryContext")
|
panic("no return value specified for QueryContext")
|
||||||
}
|
}
|
||||||
|
|
||||||
var r0 *sql.Rows
|
var r0 db.Rows
|
||||||
var r1 error
|
var r1 error
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (*sql.Rows, error)); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (db.Rows, error)); ok {
|
||||||
return rf(ctx, query, args...)
|
return rf(ctx, query, args...)
|
||||||
}
|
}
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) *sql.Rows); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) db.Rows); ok {
|
||||||
r0 = rf(ctx, query, args...)
|
r0 = rf(ctx, query, args...)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).(*sql.Rows)
|
r0 = ret.Get(0).(db.Rows)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,18 +304,18 @@ func (_c *DB_QueryContext_Call) Run(run func(ctx context.Context, query string,
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *DB_QueryContext_Call) Return(_a0 *sql.Rows, _a1 error) *DB_QueryContext_Call {
|
func (_c *DB_QueryContext_Call) Return(_a0 db.Rows, _a1 error) *DB_QueryContext_Call {
|
||||||
_c.Call.Return(_a0, _a1)
|
_c.Call.Return(_a0, _a1)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *DB_QueryContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (*sql.Rows, error)) *DB_QueryContext_Call {
|
func (_c *DB_QueryContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (db.Rows, error)) *DB_QueryContext_Call {
|
||||||
_c.Call.Return(run)
|
_c.Call.Return(run)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryRowContext provides a mock function with given fields: ctx, query, args
|
// QueryRowContext provides a mock function with given fields: ctx, query, args
|
||||||
func (_m *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
|
func (_m *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) db.Row {
|
||||||
var _ca []interface{}
|
var _ca []interface{}
|
||||||
_ca = append(_ca, ctx, query)
|
_ca = append(_ca, ctx, query)
|
||||||
_ca = append(_ca, args...)
|
_ca = append(_ca, args...)
|
||||||
@ -325,12 +325,12 @@ func (_m *DB) QueryRowContext(ctx context.Context, query string, args ...interfa
|
|||||||
panic("no return value specified for QueryRowContext")
|
panic("no return value specified for QueryRowContext")
|
||||||
}
|
}
|
||||||
|
|
||||||
var r0 *sql.Row
|
var r0 db.Row
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) *sql.Row); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) db.Row); ok {
|
||||||
r0 = rf(ctx, query, args...)
|
r0 = rf(ctx, query, args...)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).(*sql.Row)
|
r0 = ret.Get(0).(db.Row)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,12 +364,12 @@ func (_c *DB_QueryRowContext_Call) Run(run func(ctx context.Context, query strin
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *DB_QueryRowContext_Call) Return(_a0 *sql.Row) *DB_QueryRowContext_Call {
|
func (_c *DB_QueryRowContext_Call) Return(_a0 db.Row) *DB_QueryRowContext_Call {
|
||||||
_c.Call.Return(_a0)
|
_c.Call.Return(_a0)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *DB_QueryRowContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) *sql.Row) *DB_QueryRowContext_Call {
|
func (_c *DB_QueryRowContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) db.Row) *DB_QueryRowContext_Call {
|
||||||
_c.Call.Return(run)
|
_c.Call.Return(run)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
132
pkg/storage/unified/sql/db/mocks/Row.go
Normal file
132
pkg/storage/unified/sql/db/mocks/Row.go
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
// Code generated by mockery v2.43.1. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
// Row is an autogenerated mock type for the Row type
|
||||||
|
type Row struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type Row_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *Row) EXPECT() *Row_Expecter {
|
||||||
|
return &Row_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Err provides a mock function with given fields:
|
||||||
|
func (_m *Row) Err() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for Err")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Row_Err_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Err'
|
||||||
|
type Row_Err_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// Err is a helper method to define mock.On call
|
||||||
|
func (_e *Row_Expecter) Err() *Row_Err_Call {
|
||||||
|
return &Row_Err_Call{Call: _e.mock.On("Err")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Row_Err_Call) Run(run func()) *Row_Err_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run()
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Row_Err_Call) Return(_a0 error) *Row_Err_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Row_Err_Call) RunAndReturn(run func() error) *Row_Err_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan provides a mock function with given fields: dest
|
||||||
|
func (_m *Row) Scan(dest ...interface{}) error {
|
||||||
|
var _ca []interface{}
|
||||||
|
_ca = append(_ca, dest...)
|
||||||
|
ret := _m.Called(_ca...)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for Scan")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(...interface{}) error); ok {
|
||||||
|
r0 = rf(dest...)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Row_Scan_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Scan'
|
||||||
|
type Row_Scan_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan is a helper method to define mock.On call
|
||||||
|
// - dest ...interface{}
|
||||||
|
func (_e *Row_Expecter) Scan(dest ...interface{}) *Row_Scan_Call {
|
||||||
|
return &Row_Scan_Call{Call: _e.mock.On("Scan",
|
||||||
|
append([]interface{}{}, dest...)...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Row_Scan_Call) Run(run func(dest ...interface{})) *Row_Scan_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
variadicArgs := make([]interface{}, len(args)-0)
|
||||||
|
for i, a := range args[0:] {
|
||||||
|
if a != nil {
|
||||||
|
variadicArgs[i] = a.(interface{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run(variadicArgs...)
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Row_Scan_Call) Return(_a0 error) *Row_Scan_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Row_Scan_Call) RunAndReturn(run func(...interface{}) error) *Row_Scan_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRow creates a new instance of Row. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewRow(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *Row {
|
||||||
|
mock := &Row{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
267
pkg/storage/unified/sql/db/mocks/Rows.go
Normal file
267
pkg/storage/unified/sql/db/mocks/Rows.go
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
// Code generated by mockery v2.43.1. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
// Rows is an autogenerated mock type for the Rows type
|
||||||
|
type Rows struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type Rows_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *Rows) EXPECT() *Rows_Expecter {
|
||||||
|
return &Rows_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close provides a mock function with given fields:
|
||||||
|
func (_m *Rows) Close() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for Close")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rows_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
|
||||||
|
type Rows_Close_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close is a helper method to define mock.On call
|
||||||
|
func (_e *Rows_Expecter) Close() *Rows_Close_Call {
|
||||||
|
return &Rows_Close_Call{Call: _e.mock.On("Close")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_Close_Call) Run(run func()) *Rows_Close_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run()
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_Close_Call) Return(_a0 error) *Rows_Close_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_Close_Call) RunAndReturn(run func() error) *Rows_Close_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Err provides a mock function with given fields:
|
||||||
|
func (_m *Rows) Err() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for Err")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rows_Err_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Err'
|
||||||
|
type Rows_Err_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// Err is a helper method to define mock.On call
|
||||||
|
func (_e *Rows_Expecter) Err() *Rows_Err_Call {
|
||||||
|
return &Rows_Err_Call{Call: _e.mock.On("Err")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_Err_Call) Run(run func()) *Rows_Err_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run()
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_Err_Call) Return(_a0 error) *Rows_Err_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_Err_Call) RunAndReturn(run func() error) *Rows_Err_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next provides a mock function with given fields:
|
||||||
|
func (_m *Rows) Next() bool {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for Next")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 bool
|
||||||
|
if rf, ok := ret.Get(0).(func() bool); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rows_Next_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Next'
|
||||||
|
type Rows_Next_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next is a helper method to define mock.On call
|
||||||
|
func (_e *Rows_Expecter) Next() *Rows_Next_Call {
|
||||||
|
return &Rows_Next_Call{Call: _e.mock.On("Next")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_Next_Call) Run(run func()) *Rows_Next_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run()
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_Next_Call) Return(_a0 bool) *Rows_Next_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_Next_Call) RunAndReturn(run func() bool) *Rows_Next_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextResultSet provides a mock function with given fields:
|
||||||
|
func (_m *Rows) NextResultSet() bool {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for NextResultSet")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 bool
|
||||||
|
if rf, ok := ret.Get(0).(func() bool); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rows_NextResultSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NextResultSet'
|
||||||
|
type Rows_NextResultSet_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextResultSet is a helper method to define mock.On call
|
||||||
|
func (_e *Rows_Expecter) NextResultSet() *Rows_NextResultSet_Call {
|
||||||
|
return &Rows_NextResultSet_Call{Call: _e.mock.On("NextResultSet")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_NextResultSet_Call) Run(run func()) *Rows_NextResultSet_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run()
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_NextResultSet_Call) Return(_a0 bool) *Rows_NextResultSet_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_NextResultSet_Call) RunAndReturn(run func() bool) *Rows_NextResultSet_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan provides a mock function with given fields: dest
|
||||||
|
func (_m *Rows) Scan(dest ...interface{}) error {
|
||||||
|
var _ca []interface{}
|
||||||
|
_ca = append(_ca, dest...)
|
||||||
|
ret := _m.Called(_ca...)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for Scan")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(...interface{}) error); ok {
|
||||||
|
r0 = rf(dest...)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rows_Scan_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Scan'
|
||||||
|
type Rows_Scan_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan is a helper method to define mock.On call
|
||||||
|
// - dest ...interface{}
|
||||||
|
func (_e *Rows_Expecter) Scan(dest ...interface{}) *Rows_Scan_Call {
|
||||||
|
return &Rows_Scan_Call{Call: _e.mock.On("Scan",
|
||||||
|
append([]interface{}{}, dest...)...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_Scan_Call) Run(run func(dest ...interface{})) *Rows_Scan_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
variadicArgs := make([]interface{}, len(args)-0)
|
||||||
|
for i, a := range args[0:] {
|
||||||
|
if a != nil {
|
||||||
|
variadicArgs[i] = a.(interface{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run(variadicArgs...)
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_Scan_Call) Return(_a0 error) *Rows_Scan_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Rows_Scan_Call) RunAndReturn(run func(...interface{}) error) *Rows_Scan_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRows creates a new instance of Rows. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewRows(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *Rows {
|
||||||
|
mock := &Rows{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
@ -5,6 +5,7 @@ package mocks
|
|||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
|
|
||||||
|
db "github.com/grafana/grafana/pkg/storage/unified/sql/db"
|
||||||
mock "github.com/stretchr/testify/mock"
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
sql "database/sql"
|
sql "database/sql"
|
||||||
@ -139,7 +140,7 @@ func (_c *Tx_ExecContext_Call) RunAndReturn(run func(context.Context, string, ..
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryContext provides a mock function with given fields: ctx, query, args
|
// QueryContext provides a mock function with given fields: ctx, query, args
|
||||||
func (_m *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
|
func (_m *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (db.Rows, error) {
|
||||||
var _ca []interface{}
|
var _ca []interface{}
|
||||||
_ca = append(_ca, ctx, query)
|
_ca = append(_ca, ctx, query)
|
||||||
_ca = append(_ca, args...)
|
_ca = append(_ca, args...)
|
||||||
@ -149,16 +150,16 @@ func (_m *Tx) QueryContext(ctx context.Context, query string, args ...interface{
|
|||||||
panic("no return value specified for QueryContext")
|
panic("no return value specified for QueryContext")
|
||||||
}
|
}
|
||||||
|
|
||||||
var r0 *sql.Rows
|
var r0 db.Rows
|
||||||
var r1 error
|
var r1 error
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (*sql.Rows, error)); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (db.Rows, error)); ok {
|
||||||
return rf(ctx, query, args...)
|
return rf(ctx, query, args...)
|
||||||
}
|
}
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) *sql.Rows); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) db.Rows); ok {
|
||||||
r0 = rf(ctx, query, args...)
|
r0 = rf(ctx, query, args...)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).(*sql.Rows)
|
r0 = ret.Get(0).(db.Rows)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,18 +199,18 @@ func (_c *Tx_QueryContext_Call) Run(run func(ctx context.Context, query string,
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *Tx_QueryContext_Call) Return(_a0 *sql.Rows, _a1 error) *Tx_QueryContext_Call {
|
func (_c *Tx_QueryContext_Call) Return(_a0 db.Rows, _a1 error) *Tx_QueryContext_Call {
|
||||||
_c.Call.Return(_a0, _a1)
|
_c.Call.Return(_a0, _a1)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *Tx_QueryContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (*sql.Rows, error)) *Tx_QueryContext_Call {
|
func (_c *Tx_QueryContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (db.Rows, error)) *Tx_QueryContext_Call {
|
||||||
_c.Call.Return(run)
|
_c.Call.Return(run)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryRowContext provides a mock function with given fields: ctx, query, args
|
// QueryRowContext provides a mock function with given fields: ctx, query, args
|
||||||
func (_m *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
|
func (_m *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) db.Row {
|
||||||
var _ca []interface{}
|
var _ca []interface{}
|
||||||
_ca = append(_ca, ctx, query)
|
_ca = append(_ca, ctx, query)
|
||||||
_ca = append(_ca, args...)
|
_ca = append(_ca, args...)
|
||||||
@ -219,12 +220,12 @@ func (_m *Tx) QueryRowContext(ctx context.Context, query string, args ...interfa
|
|||||||
panic("no return value specified for QueryRowContext")
|
panic("no return value specified for QueryRowContext")
|
||||||
}
|
}
|
||||||
|
|
||||||
var r0 *sql.Row
|
var r0 db.Row
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) *sql.Row); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) db.Row); ok {
|
||||||
r0 = rf(ctx, query, args...)
|
r0 = rf(ctx, query, args...)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).(*sql.Row)
|
r0 = ret.Get(0).(db.Row)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,12 +259,12 @@ func (_c *Tx_QueryRowContext_Call) Run(run func(ctx context.Context, query strin
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *Tx_QueryRowContext_Call) Return(_a0 *sql.Row) *Tx_QueryRowContext_Call {
|
func (_c *Tx_QueryRowContext_Call) Return(_a0 db.Row) *Tx_QueryRowContext_Call {
|
||||||
_c.Call.Return(_a0)
|
_c.Call.Return(_a0)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *Tx_QueryRowContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) *sql.Row) *Tx_QueryRowContext_Call {
|
func (_c *Tx_QueryRowContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) db.Row) *Tx_QueryRowContext_Call {
|
||||||
_c.Call.Return(run)
|
_c.Call.Return(run)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
142
pkg/storage/unified/sql/db/mocks/result.go
Normal file
142
pkg/storage/unified/sql/db/mocks/result.go
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
// Code generated by mockery v2.43.1. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
// Result is an autogenerated mock type for the result type
|
||||||
|
type Result struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type Result_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *Result) EXPECT() *Result_Expecter {
|
||||||
|
return &Result_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastInsertId provides a mock function with given fields:
|
||||||
|
func (_m *Result) LastInsertId() (int64, error) {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for LastInsertId")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 int64
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func() (int64, error)); ok {
|
||||||
|
return rf()
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func() int64); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func() error); ok {
|
||||||
|
r1 = rf()
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result_LastInsertId_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LastInsertId'
|
||||||
|
type Result_LastInsertId_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastInsertId is a helper method to define mock.On call
|
||||||
|
func (_e *Result_Expecter) LastInsertId() *Result_LastInsertId_Call {
|
||||||
|
return &Result_LastInsertId_Call{Call: _e.mock.On("LastInsertId")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Result_LastInsertId_Call) Run(run func()) *Result_LastInsertId_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run()
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Result_LastInsertId_Call) Return(_a0 int64, _a1 error) *Result_LastInsertId_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Result_LastInsertId_Call) RunAndReturn(run func() (int64, error)) *Result_LastInsertId_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// RowsAffected provides a mock function with given fields:
|
||||||
|
func (_m *Result) RowsAffected() (int64, error) {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for RowsAffected")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 int64
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func() (int64, error)); ok {
|
||||||
|
return rf()
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func() int64); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func() error); ok {
|
||||||
|
r1 = rf()
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result_RowsAffected_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RowsAffected'
|
||||||
|
type Result_RowsAffected_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// RowsAffected is a helper method to define mock.On call
|
||||||
|
func (_e *Result_Expecter) RowsAffected() *Result_RowsAffected_Call {
|
||||||
|
return &Result_RowsAffected_Call{Call: _e.mock.On("RowsAffected")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Result_RowsAffected_Call) Run(run func()) *Result_RowsAffected_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run()
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Result_RowsAffected_Call) Return(_a0 int64, _a1 error) *Result_RowsAffected_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *Result_RowsAffected_Call) RunAndReturn(run func() (int64, error)) *Result_RowsAffected_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewResult creates a new instance of Result. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewResult(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *Result {
|
||||||
|
mock := &Result{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
56
pkg/storage/unified/sql/db/mocks/util.go
Normal file
56
pkg/storage/unified/sql/db/mocks/util.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewRowWithValues(t *testing.T, values ...any) *Row {
|
||||||
|
row := NewRow(t)
|
||||||
|
row.EXPECT().Err().Return(nil).Once() // should check error
|
||||||
|
ExpectRowValues(t, row, values...)
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExpectRowValues(t *testing.T, row *Row, values ...any) *Row_Scan_Call {
|
||||||
|
return row.EXPECT().Scan(mock.Anything).RunAndReturn(func(dsts ...any) error {
|
||||||
|
scan(t, dsts, values)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func scan(t *testing.T, dsts, srcs []any) {
|
||||||
|
t.Helper()
|
||||||
|
if len(dsts) > len(srcs) {
|
||||||
|
t.Fatalf("%d destination values, but only %d source values", len(dsts),
|
||||||
|
len(srcs))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range dsts {
|
||||||
|
src := reflect.ValueOf(srcs[i])
|
||||||
|
if !src.IsValid() {
|
||||||
|
t.Fatalf("%d-eth value to be returned by the mocked db is"+
|
||||||
|
" invalid: %#v", i, srcs[i])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dst := reflect.ValueOf(dsts[i])
|
||||||
|
if !dst.IsValid() || dst.Kind() != reflect.Pointer {
|
||||||
|
t.Fatalf("%d-eth argument passed to Scan is invalid or not"+
|
||||||
|
" a pointer: %#v", i, dsts[i])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dst = dst.Elem() // get element to which the pointer points to
|
||||||
|
if !dst.CanSet() || !src.Type().AssignableTo(dst.Type()) {
|
||||||
|
t.Fatalf("%d-eth destination cannot be set, orcannot be assigned "+
|
||||||
|
"the value; type of destination: %T; value that would be "+
|
||||||
|
"assigned: %#v", i, dsts[i], srcs[i])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dst.Set(src)
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,9 @@ import (
|
|||||||
|
|
||||||
//go:generate mockery --with-expecter --name DB
|
//go:generate mockery --with-expecter --name DB
|
||||||
//go:generate mockery --with-expecter --name Tx
|
//go:generate mockery --with-expecter --name Tx
|
||||||
|
//go:generate mockery --with-expecter --name Row
|
||||||
|
//go:generate mockery --with-expecter --name Rows
|
||||||
|
//go:generate mockery --with-expecter --exported --name result
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DriverPostgres = "postgres"
|
DriverPostgres = "postgres"
|
||||||
@ -59,9 +62,34 @@ type Tx interface {
|
|||||||
// ContextExecer is a set of database operation methods that take
|
// ContextExecer is a set of database operation methods that take
|
||||||
// context.Context.
|
// context.Context.
|
||||||
type ContextExecer interface {
|
type ContextExecer interface {
|
||||||
ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
|
ExecContext(ctx context.Context, query string, args ...any) (Result, error)
|
||||||
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
|
QueryContext(ctx context.Context, query string, args ...any) (Rows, error)
|
||||||
QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
|
QueryRowContext(ctx context.Context, query string, args ...any) Row
|
||||||
|
}
|
||||||
|
|
||||||
|
// Row is the set of methods from *sql.Row that we use.
|
||||||
|
type Row interface {
|
||||||
|
Err() error
|
||||||
|
Scan(dest ...any) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rows is the set of methods from *sql.Rows that we use.
|
||||||
|
type Rows interface {
|
||||||
|
Close() error
|
||||||
|
Err() error
|
||||||
|
Next() bool
|
||||||
|
NextResultSet() bool
|
||||||
|
Scan(dest ...any) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result is the standard sql.Result interface, for convenience.
|
||||||
|
type Result = sql.Result
|
||||||
|
|
||||||
|
// result is needed for mockery, since it doesn't support type aliases.
|
||||||
|
//
|
||||||
|
//nolint:unused
|
||||||
|
type result interface {
|
||||||
|
Result
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithTxFunc is an adapter to be able to provide the DB.WithTx method as an
|
// WithTxFunc is an adapter to be able to provide the DB.WithTx method as an
|
||||||
|
@ -14,6 +14,17 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate"
|
"github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//nolint:unused
|
||||||
|
const (
|
||||||
|
otelAttrBaseKey = "dbutil_"
|
||||||
|
otelAttrTemplateNameKey = otelAttrBaseKey + "template"
|
||||||
|
otelAttrDialectKey = otelAttrBaseKey + "dialect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func withOtelAttrs(ctx context.Context, tmplName, dialectName string) context.Context {
|
||||||
|
return ctx // TODO: in next PR
|
||||||
|
}
|
||||||
|
|
||||||
// SQLError is an error returned by the database, which includes additionally
|
// SQLError is an error returned by the database, which includes additionally
|
||||||
// debugging information about what was sent to the database.
|
// debugging information about what was sent to the database.
|
||||||
type SQLError struct {
|
type SQLError struct {
|
||||||
@ -79,7 +90,7 @@ func Debug(err error) error {
|
|||||||
|
|
||||||
// Exec uses `req` as input for a non-data returning query generated with
|
// Exec uses `req` as input for a non-data returning query generated with
|
||||||
// `tmpl`, and executed in `x`.
|
// `tmpl`, and executed in `x`.
|
||||||
func Exec(ctx context.Context, x db.ContextExecer, tmpl *template.Template, req sqltemplate.SQLTemplate) (sql.Result, error) {
|
func Exec(ctx context.Context, x db.ContextExecer, tmpl *template.Template, req sqltemplate.SQLTemplate) (db.Result, error) {
|
||||||
if err := req.Validate(); err != nil {
|
if err := req.Validate(); err != nil {
|
||||||
return nil, fmt.Errorf("Exec: invalid request for template %q: %w",
|
return nil, fmt.Errorf("Exec: invalid request for template %q: %w",
|
||||||
tmpl.Name(), err)
|
tmpl.Name(), err)
|
||||||
@ -91,13 +102,15 @@ func Exec(ctx context.Context, x db.ContextExecer, tmpl *template.Template, req
|
|||||||
}
|
}
|
||||||
query := sqltemplate.FormatSQL(rawQuery)
|
query := sqltemplate.FormatSQL(rawQuery)
|
||||||
|
|
||||||
res, err := x.ExecContext(ctx, query, req.GetArgs()...)
|
args := req.GetArgs()
|
||||||
|
ctx = withOtelAttrs(ctx, tmpl.Name(), req.DialectName())
|
||||||
|
res, err := x.ExecContext(ctx, query, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, SQLError{
|
return nil, SQLError{
|
||||||
Err: err,
|
Err: err,
|
||||||
CallType: "Exec",
|
CallType: "Exec",
|
||||||
TemplateName: tmpl.Name(),
|
TemplateName: tmpl.Name(),
|
||||||
arguments: req.GetArgs(),
|
arguments: args,
|
||||||
Query: query,
|
Query: query,
|
||||||
RawQuery: rawQuery,
|
RawQuery: rawQuery,
|
||||||
}
|
}
|
||||||
@ -108,7 +121,7 @@ func Exec(ctx context.Context, x db.ContextExecer, tmpl *template.Template, req
|
|||||||
|
|
||||||
// Query uses `req` as input for a single-statement, set-returning query
|
// Query uses `req` as input for a single-statement, set-returning query
|
||||||
// generated with `tmpl`, and executed in `x`.
|
// generated with `tmpl`, and executed in `x`.
|
||||||
func QueryRows(ctx context.Context, x db.ContextExecer, tmpl *template.Template, req sqltemplate.SQLTemplate) (*sql.Rows, error) {
|
func QueryRows(ctx context.Context, x db.ContextExecer, tmpl *template.Template, req sqltemplate.SQLTemplate) (db.Rows, error) {
|
||||||
if err := req.Validate(); err != nil {
|
if err := req.Validate(); err != nil {
|
||||||
return nil, fmt.Errorf("Query: invalid request for template %q: %w",
|
return nil, fmt.Errorf("Query: invalid request for template %q: %w",
|
||||||
tmpl.Name(), err)
|
tmpl.Name(), err)
|
||||||
@ -120,13 +133,15 @@ func QueryRows(ctx context.Context, x db.ContextExecer, tmpl *template.Template,
|
|||||||
}
|
}
|
||||||
query := sqltemplate.FormatSQL(rawQuery)
|
query := sqltemplate.FormatSQL(rawQuery)
|
||||||
|
|
||||||
rows, err := x.QueryContext(ctx, query, req.GetArgs()...)
|
args := req.GetArgs()
|
||||||
|
ctx = withOtelAttrs(ctx, tmpl.Name(), req.DialectName())
|
||||||
|
rows, err := x.QueryContext(ctx, query, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, SQLError{
|
return nil, SQLError{
|
||||||
Err: err,
|
Err: err,
|
||||||
CallType: "Query",
|
CallType: "Query",
|
||||||
TemplateName: tmpl.Name(),
|
TemplateName: tmpl.Name(),
|
||||||
arguments: req.GetArgs(),
|
arguments: args,
|
||||||
ScanDest: req.GetScanDest(),
|
ScanDest: req.GetScanDest(),
|
||||||
Query: query,
|
Query: query,
|
||||||
RawQuery: rawQuery,
|
RawQuery: rawQuery,
|
||||||
@ -186,13 +201,13 @@ func QueryRow[T any](ctx context.Context, x db.ContextExecer, tmpl *template.Tem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiscardRows discards all the ResultSets in the given *sql.Rows and returns
|
// DiscardRows discards all the ResultSets in the given db.Rows and returns
|
||||||
// the final rows error and the number of times NextResultSet was called. This
|
// the final rows error and the number of times NextResultSet was called. This
|
||||||
// is useful to check for errors in queries with multiple SQL statements where
|
// is useful to check for errors in queries with multiple SQL statements where
|
||||||
// there is no interesting output, since some drivers may omit an error returned
|
// there is no interesting output, since some drivers may omit an error returned
|
||||||
// by a SQL statement found in a statement that is not the first one. Note that
|
// by a SQL statement found in a statement that is not the first one. Note that
|
||||||
// not all drivers support multi-statement calls, though.
|
// not all drivers support multi-statement calls, though.
|
||||||
func DiscardRows(rows *sql.Rows) (int, error) {
|
func DiscardRows(rows db.Rows) (int, error) {
|
||||||
discardedResultSets := 1
|
discardedResultSets := 1
|
||||||
for ; rows.NextResultSet(); discardedResultSets++ {
|
for ; rows.NextResultSet(); discardedResultSets++ {
|
||||||
}
|
}
|
||||||
@ -203,7 +218,7 @@ type scanner interface {
|
|||||||
Scan(dest ...any) error
|
Scan(dest ...any) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// scanRow is used on *sql.Row and *sql.Rows, and is factored out here not to
|
// scanRow is used on db.Row and db.Rows, and is factored out here not to
|
||||||
// improving code reuse, but rather for ease of testing.
|
// improving code reuse, but rather for ease of testing.
|
||||||
func scanRow[T any](sc scanner, req sqltemplate.WithResults[T]) (zero T, err error) {
|
func scanRow[T any](sc scanner, req sqltemplate.WithResults[T]) (zero T, err error) {
|
||||||
if err = sc.Scan(req.GetScanDest()...); err != nil {
|
if err = sc.Scan(req.GetScanDest()...); err != nil {
|
||||||
|
@ -87,6 +87,8 @@ func TestQuery(t *testing.T) {
|
|||||||
rdb := test.NewDBProviderNopSQL(t)
|
rdb := test.NewDBProviderNopSQL(t)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil)
|
req.EXPECT().GetArgs().Return(nil)
|
||||||
req.EXPECT().GetScanDest().Return(nil).Maybe()
|
req.EXPECT().GetScanDest().Return(nil).Maybe()
|
||||||
@ -108,6 +110,8 @@ func TestQuery(t *testing.T) {
|
|||||||
rows := newReturnsRow(rdb.SQLMock, req)
|
rows := newReturnsRow(rdb.SQLMock, req)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil).Once()
|
req.EXPECT().GetArgs().Return(nil).Once()
|
||||||
rows.Add(1, nil)
|
rows.Add(1, nil)
|
||||||
@ -131,6 +135,8 @@ func TestQuery(t *testing.T) {
|
|||||||
rdb := test.NewDBProviderNopSQL(t)
|
rdb := test.NewDBProviderNopSQL(t)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(errTest).Once()
|
req.EXPECT().Validate().Return(errTest).Once()
|
||||||
|
|
||||||
// execute and assert
|
// execute and assert
|
||||||
@ -152,6 +158,8 @@ func TestQuery(t *testing.T) {
|
|||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
|
|
||||||
// execute and assert
|
// execute and assert
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
res, err := Query(ctx, rdb.DB, invalidTestTmpl, req)
|
res, err := Query(ctx, rdb.DB, invalidTestTmpl, req)
|
||||||
require.Zero(t, res)
|
require.Zero(t, res)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
@ -167,6 +175,8 @@ func TestQuery(t *testing.T) {
|
|||||||
rdb := test.NewDBProviderNopSQL(t)
|
rdb := test.NewDBProviderNopSQL(t)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil)
|
req.EXPECT().GetArgs().Return(nil)
|
||||||
req.EXPECT().GetScanDest().Return(nil).Maybe()
|
req.EXPECT().GetScanDest().Return(nil).Maybe()
|
||||||
@ -189,6 +199,8 @@ func TestQuery(t *testing.T) {
|
|||||||
rows := newReturnsRow(rdb.SQLMock, req)
|
rows := newReturnsRow(rdb.SQLMock, req)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil).Once()
|
req.EXPECT().GetArgs().Return(nil).Once()
|
||||||
rows.Add(0, errTest)
|
rows.Add(0, errTest)
|
||||||
@ -211,6 +223,8 @@ func TestQuery(t *testing.T) {
|
|||||||
rows := newReturnsRow(rdb.SQLMock, req)
|
rows := newReturnsRow(rdb.SQLMock, req)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil).Once()
|
req.EXPECT().GetArgs().Return(nil).Once()
|
||||||
rows.Rows.AddRow() // we don't expect GetScanDest or Results here
|
rows.Rows.AddRow() // we don't expect GetScanDest or Results here
|
||||||
@ -235,6 +249,8 @@ func TestQuery(t *testing.T) {
|
|||||||
rows2 := newReturnsRow(rdb.SQLMock, req)
|
rows2 := newReturnsRow(rdb.SQLMock, req)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil).Once()
|
req.EXPECT().GetArgs().Return(nil).Once()
|
||||||
rows1.Add(1, nil)
|
rows1.Add(1, nil)
|
||||||
@ -262,6 +278,8 @@ func TestQueryRow(t *testing.T) {
|
|||||||
rows := newReturnsRow(rdb.SQLMock, req)
|
rows := newReturnsRow(rdb.SQLMock, req)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil).Once()
|
req.EXPECT().GetArgs().Return(nil).Once()
|
||||||
rows.Add(1, nil)
|
rows.Add(1, nil)
|
||||||
@ -282,6 +300,8 @@ func TestQueryRow(t *testing.T) {
|
|||||||
rdb := test.NewDBProviderNopSQL(t)
|
rdb := test.NewDBProviderNopSQL(t)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil).Once()
|
req.EXPECT().GetArgs().Return(nil).Once()
|
||||||
rdb.SQLMock.ExpectQuery("").WillReturnRows(rdb.SQLMock.NewRows(nil))
|
rdb.SQLMock.ExpectQuery("").WillReturnRows(rdb.SQLMock.NewRows(nil))
|
||||||
@ -302,6 +322,8 @@ func TestQueryRow(t *testing.T) {
|
|||||||
rdb := test.NewDBProviderNopSQL(t)
|
rdb := test.NewDBProviderNopSQL(t)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil)
|
req.EXPECT().GetArgs().Return(nil)
|
||||||
req.EXPECT().GetScanDest().Return(nil).Maybe()
|
req.EXPECT().GetScanDest().Return(nil).Maybe()
|
||||||
@ -324,6 +346,8 @@ func TestQueryRow(t *testing.T) {
|
|||||||
rows := newReturnsRow(rdb.SQLMock, req)
|
rows := newReturnsRow(rdb.SQLMock, req)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil).Once()
|
req.EXPECT().GetArgs().Return(nil).Once()
|
||||||
rows.Add(1, nil)
|
rows.Add(1, nil)
|
||||||
@ -348,6 +372,8 @@ func TestQueryRow(t *testing.T) {
|
|||||||
rows2 := newReturnsRow(rdb.SQLMock, req)
|
rows2 := newReturnsRow(rdb.SQLMock, req)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil).Once()
|
req.EXPECT().GetArgs().Return(nil).Once()
|
||||||
rows1.Add(1, nil)
|
rows1.Add(1, nil)
|
||||||
@ -445,6 +471,8 @@ func TestExec(t *testing.T) {
|
|||||||
rdb := test.NewDBProviderNopSQL(t)
|
rdb := test.NewDBProviderNopSQL(t)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil).Once()
|
req.EXPECT().GetArgs().Return(nil).Once()
|
||||||
rdb.SQLMock.ExpectExec("").WillReturnResult(sqlmock.NewResult(0, 0))
|
rdb.SQLMock.ExpectExec("").WillReturnResult(sqlmock.NewResult(0, 0))
|
||||||
@ -464,6 +492,8 @@ func TestExec(t *testing.T) {
|
|||||||
rdb := test.NewDBProviderNopSQL(t)
|
rdb := test.NewDBProviderNopSQL(t)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(errTest).Once()
|
req.EXPECT().Validate().Return(errTest).Once()
|
||||||
|
|
||||||
// execute and assert
|
// execute and assert
|
||||||
@ -482,6 +512,8 @@ func TestExec(t *testing.T) {
|
|||||||
rdb := test.NewDBProviderNopSQL(t)
|
rdb := test.NewDBProviderNopSQL(t)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
|
|
||||||
// execute and assert
|
// execute and assert
|
||||||
@ -500,6 +532,8 @@ func TestExec(t *testing.T) {
|
|||||||
rdb := test.NewDBProviderNopSQL(t)
|
rdb := test.NewDBProviderNopSQL(t)
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
req.EXPECT().DialectName().Return("test").Maybe()
|
||||||
|
req.EXPECT().GetColNames().Return(nil).Maybe()
|
||||||
req.EXPECT().Validate().Return(nil).Once()
|
req.EXPECT().Validate().Return(nil).Once()
|
||||||
req.EXPECT().GetArgs().Return(nil)
|
req.EXPECT().GetArgs().Return(nil)
|
||||||
rdb.SQLMock.ExpectExec("").WillReturnError(errTest)
|
rdb.SQLMock.ExpectExec("").WillReturnError(errTest)
|
||||||
|
Loading…
Reference in New Issue
Block a user