1
0
Fork 0

Named parameters helpers

This commit is contained in:
Gregory Eremin 2018-07-07 14:11:33 +02:00
parent 6c6ccaf0b3
commit e40d7a236c
No known key found for this signature in database
GPG Key ID: 8CB79D42167BEB7F
2 changed files with 146 additions and 0 deletions

66
dbc/named.go Normal file
View File

@ -0,0 +1,66 @@
package dbc
import (
"fmt"
"reflect"
"github.com/localhots/gobelt/reflect2"
)
type namedParams interface {
Get(name string) (val interface{}, ok bool)
}
var (
_ namedParams = namedParamsMap{}
_ namedParams = &namedParamsStruct{}
)
func newNamedParams(val interface{}) (namedParams, error) {
switch tval := val.(type) {
case map[string]interface{}:
return newNamedParamsMap(tval)
default:
return newNamedParamsStruct(val)
}
}
type namedParamsMap struct {
m map[string]interface{}
}
func newNamedParamsMap(m map[string]interface{}) (namedParamsMap, error) {
return namedParamsMap{m}, nil
}
func (p namedParamsMap) Get(name string) (val interface{}, ok bool) {
val, ok = p.m[name]
return
}
type namedParamsStruct struct {
s reflect.Value
idx map[string]int
}
func newNamedParamsStruct(s interface{}) (*namedParamsStruct, error) {
val := reflect.ValueOf(s)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
if val.Kind() != reflect.Struct {
return nil, fmt.Errorf("Unsupported named parameters type: %T", s)
}
return &namedParamsStruct{
s: val,
idx: reflect2.TagIndex(val.Type(), tagName),
}, nil
}
func (p *namedParamsStruct) Get(name string) (val interface{}, ok bool) {
i, ok := p.idx[name]
if !ok {
return nil, false
}
return p.s.Field(i).Interface(), true
}

80
dbc/named_test.go Normal file
View File

@ -0,0 +1,80 @@
package dbc
import "testing"
func TestNamedParamsMap(t *testing.T) {
m, err := newNamedParamsMap(map[string]interface{}{
"num": 1,
"str": "foo",
})
if err != nil {
t.Fatalf("Failed to create named params map: %v", err)
}
testNamedParams(t, m)
}
func TestNamedParamsStruct(t *testing.T) {
type dummy struct {
Num int `db:"num"`
Str string `db:"str"`
}
m, err := newNamedParamsStruct(&dummy{Num: 1, Str: "foo"})
if err != nil {
t.Fatalf("Failed to create named params struct: %v", err)
}
testNamedParams(t, m)
}
func testNamedParams(t *testing.T, p namedParams) {
t.Helper()
v, ok := p.Get("num")
if !ok {
t.Error("num was not found")
}
if v != 1 {
t.Errorf("Expected num to equal 1, got %d", v)
}
v, ok = p.Get("str")
if !ok {
t.Error("num was not found")
}
if v != "foo" {
t.Errorf("Expected num to equal 'foo', got %q", v)
}
_, ok = p.Get("missing")
if ok {
t.Error("missing value reportedly found")
}
}
func BenchmarkNamedParamsMap(b *testing.B) {
m, err := newNamedParamsMap(map[string]interface{}{"foo": 1})
if err != nil {
b.Fatalf("Failed to create named params map: %v", err)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
m.Get("foo")
}
}
func BenchmarkNamedParamsStruct(b *testing.B) {
type dummy struct {
Foo int `db:"foo"`
}
m, err := newNamedParamsStruct(&dummy{Foo: 1})
if err != nil {
b.Fatalf("Failed to create named params struct: %v", err)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
m.Get("foo")
}
}