perf: query data AS OF SYSTEM TIME (#5231)

Queries the data in the storage layser at the timestamp when the call hit the API layer
This commit is contained in:
Silvan
2023-02-27 22:36:43 +01:00
committed by GitHub
parent 80003939ad
commit e38abdcdf3
170 changed files with 3101 additions and 3169 deletions

View File

@@ -1,6 +1,7 @@
package query
import (
"context"
"database/sql"
"database/sql/driver"
"errors"
@@ -19,14 +20,14 @@ var (
testNow = time.Now()
)
//assertPrepare checks if the prepare func executes the correct sql query and returns the correct object
//prepareFunc must be of type
// assertPrepare checks if the prepare func executes the correct sql query and returns the correct object
// prepareFunc must be of type
// func() (sq.SelectBuilder, func(*sql.Rows) (*struct, error))
// or
// func() (sq.SelectBuilder, func(*sql.Row) (*struct, error))
//expectedObject represents the return value of scan
//sqlExpectation represents the query executed on the database
func assertPrepare(t *testing.T, prepareFunc, expectedObject interface{}, sqlExpectation sqlExpectation, isErr checkErr) bool {
// expectedObject represents the return value of scan
// sqlExpectation represents the query executed on the database
func assertPrepare(t *testing.T, prepareFunc, expectedObject interface{}, sqlExpectation sqlExpectation, isErr checkErr, prepareArgs ...reflect.Value) bool {
t.Helper()
client, mock, err := sqlmock.New()
@@ -36,7 +37,7 @@ func assertPrepare(t *testing.T, prepareFunc, expectedObject interface{}, sqlExp
mock = sqlExpectation(mock)
builder, scan, err := execPrepare(prepareFunc)
builder, scan, err := execPrepare(prepareFunc, prepareArgs)
if err != nil {
t.Error(err)
return false
@@ -177,12 +178,12 @@ func validateScan(scanType reflect.Type) error {
return nil
}
func execPrepare(prepare interface{}) (builder sq.SelectBuilder, scan interface{}, err error) {
func execPrepare(prepare interface{}, args []reflect.Value) (builder sq.SelectBuilder, scan interface{}, err error) {
prepareVal := reflect.ValueOf(prepare)
if err := validatePrepare(prepareVal.Type()); err != nil {
return sq.SelectBuilder{}, nil, err
}
res := prepareVal.Call([]reflect.Value{})
res := prepareVal.Call(args)
return res[0].Interface().(sq.SelectBuilder), res[1].Interface(), nil
}
@@ -191,7 +192,7 @@ func validatePrepare(prepareType reflect.Type) error {
if prepareType.Kind() != reflect.Func {
return errors.New("prepare is not a function")
}
if prepareType.NumIn() != 0 {
if prepareType.NumIn() < 2 {
return fmt.Errorf("prepare: invalid number of inputs: want: 0 got %d", prepareType.NumIn())
}
if prepareType.NumOut() != 2 {
@@ -297,7 +298,7 @@ func TestValidatePrepare(t *testing.T) {
},
{
name: "correct",
t: reflect.TypeOf(func() (sq.SelectBuilder, func(*sql.Rows) (interface{}, error)) {
t: reflect.TypeOf(func(context.Context, prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (interface{}, error)) {
log.Fatal("should not be executed")
return sq.SelectBuilder{}, nil
}),
@@ -313,3 +314,15 @@ func TestValidatePrepare(t *testing.T) {
})
}
}
type prepareDB struct{}
func (_ *prepareDB) Timetravel(time.Duration) string { return " AS OF SYSTEM TIME '-1 ms' " }
var defaultPrepareArgs = []reflect.Value{reflect.ValueOf(context.Background()), reflect.ValueOf(new(prepareDB))}
func (*prepareDB) DatabaseName() string { return "db" }
func (*prepareDB) Username() string { return "user" }
func (*prepareDB) Type() string { return "type" }