Refactor orm filter

This commit is contained in:
Ming Deng 2020-08-18 14:31:06 +00:00
parent 63599c0032
commit 7fe4eaef50
54 changed files with 269 additions and 256 deletions

View File

@ -1,6 +1,6 @@
goimports -l pkg
goimports -l examples
goimports -w -format-only pkg
goimports -w -format-only examples
ineffassign .

View File

@ -1,4 +1,4 @@
// Copyright 2020
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -17,5 +17,4 @@ package bean
// ApplicationContext define for future
// when we decide to support DI, IoC, this will be core API
type ApplicationContext interface {
}

View File

@ -1,4 +1,4 @@
// Copyright 2020
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -22,4 +22,4 @@ import (
type AutoWireBeanFactory interface {
// AutoWire will wire the bean.
AutoWire(ctx context.Context, appCtx ApplicationContext, bean interface{}) error
}
}

View File

@ -1,4 +1,4 @@
// Copyright 2020
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@ package bean
import (
"context"
"time"
)
// TimeTypeAdapter process the time.Time
@ -29,7 +28,7 @@ type TimeTypeAdapter struct {
// and if the DftValue == now
// time.Now() is returned
func (t *TimeTypeAdapter) DefaultValue(ctx context.Context, dftValue string) (interface{}, error) {
if dftValue == "now"{
if dftValue == "now" {
return time.Now(), nil
}
return time.Parse(t.Layout, dftValue)

View File

@ -1,4 +1,4 @@
// Copyright 2020
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@ -1,8 +1,10 @@
package param
import "testing"
import "reflect"
import "time"
import (
"reflect"
"testing"
"time"
)
type testDefinition struct {
strValue string

View File

@ -21,9 +21,10 @@ import (
"github.com/stretchr/testify/assert"
"github.com/astaxie/beego/pkg/context"
"os"
"path/filepath"
"github.com/astaxie/beego/pkg/context"
)
func TestGetInt(t *testing.T) {

View File

@ -18,10 +18,11 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
"reflect"
"strings"
"time"
"github.com/astaxie/beego/pkg/orm/hints"
)
const (
@ -490,7 +491,7 @@ func (d *dbBase) InsertValue(q dbQuerier, mi *modelInfo, isMulti bool, names []s
if err != nil {
DebugLog.Println(ErrLastInsertIdUnavailable, ':', err)
return lastInsertId, ErrLastInsertIdUnavailable
}else{
} else {
return lastInsertId, nil
}
}
@ -598,7 +599,7 @@ func (d *dbBase) InsertOrUpdate(q dbQuerier, mi *modelInfo, ind reflect.Value, a
if err != nil {
DebugLog.Println(ErrLastInsertIdUnavailable, ':', err)
return lastInsertId, ErrLastInsertIdUnavailable
}else{
} else {
return lastInsertId, nil
}
}
@ -1954,5 +1955,3 @@ func (d *dbBase) GenerateSpecifyIndex(tableName string, useIndex int, indexes []
return fmt.Sprintf(` %s INDEX(%s) `, useWay, strings.Join(s, `,`))
}

View File

@ -18,10 +18,11 @@ import (
"context"
"database/sql"
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
"sync"
"time"
"github.com/astaxie/beego/pkg/orm/hints"
lru "github.com/hashicorp/golang-lru"
"github.com/astaxie/beego/pkg/common"

View File

@ -15,10 +15,11 @@
package orm
import (
"github.com/astaxie/beego/pkg/orm/hints"
"testing"
"time"
"github.com/astaxie/beego/pkg/orm/hints"
"github.com/stretchr/testify/assert"
)

View File

@ -169,7 +169,7 @@ func (d *dbBaseMysql) InsertOrUpdate(q dbQuerier, mi *modelInfo, ind reflect.Val
if err != nil {
DebugLog.Println(ErrLastInsertIdUnavailable, ':', err)
return lastInsertId, ErrLastInsertIdUnavailable
}else{
} else {
return lastInsertId, nil
}
}

View File

@ -16,8 +16,9 @@ package orm
import (
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
"strings"
"github.com/astaxie/beego/pkg/orm/hints"
)
// oracle operators.
@ -155,7 +156,7 @@ func (d *dbBaseOracle) InsertValue(q dbQuerier, mi *modelInfo, isMulti bool, nam
if err != nil {
DebugLog.Println(ErrLastInsertIdUnavailable, ':', err)
return lastInsertId, ErrLastInsertIdUnavailable
}else{
} else {
return lastInsertId, nil
}
}

View File

@ -92,7 +92,6 @@ func (d *dbBasePostgres) MaxLimit() uint64 {
return 0
}
// postgresql quote is ".
func (d *dbBasePostgres) TableQuote() string {
return `"`

View File

@ -17,10 +17,11 @@ package orm
import (
"database/sql"
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
"reflect"
"strings"
"time"
"github.com/astaxie/beego/pkg/orm/hints"
)
// sqlite operators.
@ -173,7 +174,6 @@ func (d *dbBaseSqlite) GenerateSpecifyIndex(tableName string, useIndex int, inde
}
}
// create new sqlite dbBaser.
func newdbBaseSqlite() dbBaser {
b := new(dbBaseSqlite)

View File

@ -473,7 +473,7 @@ func (t *dbTables) getLimitSQL(mi *modelInfo, offset int64, limit int64) (limits
}
// getIndexSql generate index sql.
func (t *dbTables) getIndexSql(tableName string,useIndex int, indexes []string) (clause string) {
func (t *dbTables) getIndexSql(tableName string, useIndex int, indexes []string) (clause string) {
if len(indexes) == 0 {
return
}

View File

@ -17,6 +17,7 @@ package orm
import (
"context"
"database/sql"
"github.com/astaxie/beego/pkg/common"
)
@ -27,7 +28,6 @@ import (
var _ Ormer = new(DoNothingOrm)
type DoNothingOrm struct {
}
func (d *DoNothingOrm) Read(md interface{}, cols ...string) error {
@ -54,11 +54,11 @@ func (d *DoNothingOrm) ReadOrCreateWithCtx(ctx context.Context, md interface{},
return false, 0, nil
}
func (d *DoNothingOrm) LoadRelated(md interface{}, name string, args ...common.KV) (int64, error) {
func (d *DoNothingOrm) LoadRelated(md interface{}, name string, args ...common.KV) (int64, error) {
return 0, nil
}
func (d *DoNothingOrm) LoadRelatedWithCtx(ctx context.Context, md interface{}, name string, args ...common.KV) (int64, error) {
func (d *DoNothingOrm) LoadRelatedWithCtx(ctx context.Context, md interface{}, name string, args ...common.KV) (int64, error) {
return 0, nil
}

View File

@ -24,7 +24,11 @@ type FilterChain func(next Filter) Filter
// Filter's behavior is a little big strange.
// it's only be called when users call methods of Ormer
type Filter func(ctx context.Context, inv *Invocation)
// return value is an array. it's a little bit hard to understand,
// for example, the Ormer's Read method only return error
// so the filter processing this method should return an array whose first element is error
// and, Ormer's ReadOrCreateWithCtx return three values, so the Filter's result should contains three values
type Filter func(ctx context.Context, inv *Invocation) []interface{}
var globalFilterChains = make([]FilterChain, 0, 4)

View File

@ -1,4 +1,4 @@
// Copyright 2020
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -76,7 +76,7 @@ func NewDefaultValueFilterChainBuilder(typeAdapters map[string]bean.TypeAdapter,
}
func (d *DefaultValueFilterChainBuilder) FilterChain(next orm.Filter) orm.Filter {
return func(ctx context.Context, inv *orm.Invocation) {
return func(ctx context.Context, inv *orm.Invocation) []interface{} {
switch inv.Method {
case "Insert", "InsertWithCtx":
d.handleInsert(ctx, inv)
@ -88,7 +88,7 @@ func (d *DefaultValueFilterChainBuilder) FilterChain(next orm.Filter) orm.Filter
d.handleInsertMulti(ctx, inv)
break
}
next(ctx, inv)
return next(ctx, inv)
}
}

View File

@ -1,4 +1,4 @@
// Copyright 2020
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@ -36,17 +36,17 @@ type FilterChainBuilder struct {
}
func (builder *FilterChainBuilder) FilterChain(next orm.Filter) orm.Filter {
return func(ctx context.Context, inv *orm.Invocation) {
return func(ctx context.Context, inv *orm.Invocation) []interface{} {
operationName := builder.operationName(ctx, inv)
if strings.HasPrefix(inv.Method, "Begin") || inv.Method == "Commit" || inv.Method == "Rollback" {
next(ctx, inv)
return
return next(ctx, inv)
}
span, spanCtx := opentracing.StartSpanFromContext(ctx, operationName)
defer span.Finish()
next(spanCtx, inv)
res := next(spanCtx, inv)
builder.buildSpan(span, spanCtx, inv)
return res
}
}

View File

@ -25,8 +25,9 @@ import (
)
func TestFilterChainBuilder_FilterChain(t *testing.T) {
next := func(ctx context.Context, inv *orm.Invocation) {
next := func(ctx context.Context, inv *orm.Invocation) []interface{} {
inv.TxName = "Hello"
return []interface{}{}
}
builder := &FilterChainBuilder{

View File

@ -56,15 +56,16 @@ func NewFilterChainBuilder() *FilterChainBuilder {
}
func (builder *FilterChainBuilder) FilterChain(next orm.Filter) orm.Filter {
return func(ctx context.Context, inv *orm.Invocation) {
return func(ctx context.Context, inv *orm.Invocation) []interface{} {
startTime := time.Now()
next(ctx, inv)
res := next(ctx, inv)
endTime := time.Now()
dur := (endTime.Sub(startTime)) / time.Millisecond
// if the TPS is too large, here may be some problem
// thinking about using goroutine pool
go builder.report(ctx, inv, dur)
return res
}
}

View File

@ -28,8 +28,9 @@ func TestFilterChainBuilder_FilterChain(t *testing.T) {
builder := NewFilterChainBuilder()
assert.NotNil(t, builder.summaryVec)
filter := builder.FilterChain(func(ctx context.Context, inv *orm.Invocation) {
filter := builder.FilterChain(func(ctx context.Context, inv *orm.Invocation) []interface{} {
inv.Method = "coming"
return []interface{}{}
})
assert.NotNil(t, filter)

View File

@ -17,13 +17,14 @@ package orm
import (
"context"
"database/sql"
"github.com/astaxie/beego/pkg/common"
"reflect"
"time"
"github.com/astaxie/beego/pkg/common"
)
const (
TxNameKey = "TxName"
TxNameKey = "TxName"
)
var _ Ormer = new(filterOrmDecorator)
@ -45,8 +46,8 @@ func NewFilterOrmDecorator(delegate Ormer, filterChains ...FilterChain) Ormer {
res := &filterOrmDecorator{
ormer: delegate,
TxBeginner: delegate,
root: func(ctx context.Context, inv *Invocation) {
inv.execute(ctx)
root: func(ctx context.Context, inv *Invocation) []interface{} {
return inv.execute(ctx)
},
}
@ -73,7 +74,7 @@ func (f *filterOrmDecorator) Read(md interface{}, cols ...string) error {
return f.ReadWithCtx(context.Background(), md, cols...)
}
func (f *filterOrmDecorator) ReadWithCtx(ctx context.Context, md interface{}, cols ...string) (err error) {
func (f *filterOrmDecorator) ReadWithCtx(ctx context.Context, md interface{}, cols ...string) error {
mi, _ := modelCache.getByMd(md)
inv := &Invocation{
Method: "ReadWithCtx",
@ -82,12 +83,13 @@ func (f *filterOrmDecorator) ReadWithCtx(ctx context.Context, md interface{}, co
mi: mi,
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
err = f.ormer.ReadWithCtx(c, md, cols...)
f: func(c context.Context) []interface{} {
err := f.ormer.ReadWithCtx(c, md, cols...)
return []interface{}{err}
},
}
f.root(ctx, inv)
return err
res := f.root(ctx, inv)
return f.convertError(res[0])
}
func (f *filterOrmDecorator) ReadForUpdate(md interface{}, cols ...string) error {
@ -95,7 +97,6 @@ func (f *filterOrmDecorator) ReadForUpdate(md interface{}, cols ...string) error
}
func (f *filterOrmDecorator) ReadForUpdateWithCtx(ctx context.Context, md interface{}, cols ...string) error {
var err error
mi, _ := modelCache.getByMd(md)
inv := &Invocation{
Method: "ReadForUpdateWithCtx",
@ -104,12 +105,13 @@ func (f *filterOrmDecorator) ReadForUpdateWithCtx(ctx context.Context, md interf
mi: mi,
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
err = f.ormer.ReadForUpdateWithCtx(c, md, cols...)
f: func(c context.Context) []interface{} {
err := f.ormer.ReadForUpdateWithCtx(c, md, cols...)
return []interface{}{err}
},
}
f.root(ctx, inv)
return err
res := f.root(ctx, inv)
return f.convertError(res[0])
}
func (f *filterOrmDecorator) ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) {
@ -117,11 +119,6 @@ func (f *filterOrmDecorator) ReadOrCreate(md interface{}, col1 string, cols ...s
}
func (f *filterOrmDecorator) ReadOrCreateWithCtx(ctx context.Context, md interface{}, col1 string, cols ...string) (bool, int64, error) {
var (
ok bool
res int64
err error
)
mi, _ := modelCache.getByMd(md)
inv := &Invocation{
@ -131,12 +128,13 @@ func (f *filterOrmDecorator) ReadOrCreateWithCtx(ctx context.Context, md interfa
mi: mi,
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
ok, res, err = f.ormer.ReadOrCreateWithCtx(c, md, col1, cols...)
f: func(c context.Context) []interface{} {
ok, res, err := f.ormer.ReadOrCreateWithCtx(c, md, col1, cols...)
return []interface{}{ok, res, err}
},
}
f.root(ctx, inv)
return ok, res, err
res := f.root(ctx, inv)
return res[0].(bool), res[1].(int64), f.convertError(res[2])
}
func (f *filterOrmDecorator) LoadRelated(md interface{}, name string, args ...common.KV) (int64, error) {
@ -144,10 +142,6 @@ func (f *filterOrmDecorator) LoadRelated(md interface{}, name string, args ...co
}
func (f *filterOrmDecorator) LoadRelatedWithCtx(ctx context.Context, md interface{}, name string, args ...common.KV) (int64, error) {
var (
res int64
err error
)
mi, _ := modelCache.getByMd(md)
inv := &Invocation{
@ -157,12 +151,13 @@ func (f *filterOrmDecorator) LoadRelatedWithCtx(ctx context.Context, md interfac
mi: mi,
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
res, err = f.ormer.LoadRelatedWithCtx(c, md, name, args...)
f: func(c context.Context) []interface{} {
res, err := f.ormer.LoadRelatedWithCtx(c, md, name, args...)
return []interface{}{res, err}
},
}
f.root(ctx, inv)
return res, err
res := f.root(ctx, inv)
return res[0].(int64), f.convertError(res[1])
}
func (f *filterOrmDecorator) QueryM2M(md interface{}, name string) QueryM2Mer {
@ -170,9 +165,6 @@ func (f *filterOrmDecorator) QueryM2M(md interface{}, name string) QueryM2Mer {
}
func (f *filterOrmDecorator) QueryM2MWithCtx(ctx context.Context, md interface{}, name string) QueryM2Mer {
var (
res QueryM2Mer
)
mi, _ := modelCache.getByMd(md)
inv := &Invocation{
@ -182,12 +174,16 @@ func (f *filterOrmDecorator) QueryM2MWithCtx(ctx context.Context, md interface{}
mi: mi,
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
res = f.ormer.QueryM2MWithCtx(c, md, name)
f: func(c context.Context) []interface{} {
res := f.ormer.QueryM2MWithCtx(c, md, name)
return []interface{}{res}
},
}
f.root(ctx, inv)
return res
res := f.root(ctx, inv)
if res[0] == nil {
return nil
}
return res[0].(QueryM2Mer)
}
func (f *filterOrmDecorator) QueryTable(ptrStructOrTableName interface{}) QuerySeter {
@ -196,7 +192,6 @@ func (f *filterOrmDecorator) QueryTable(ptrStructOrTableName interface{}) QueryS
func (f *filterOrmDecorator) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter {
var (
res QuerySeter
name string
md interface{}
mi *modelInfo
@ -220,28 +215,36 @@ func (f *filterOrmDecorator) QueryTableWithCtx(ctx context.Context, ptrStructOrT
TxStartTime: f.txStartTime,
Md: md,
mi: mi,
f: func(c context.Context) {
res = f.ormer.QueryTableWithCtx(c, ptrStructOrTableName)
f: func(c context.Context) []interface{} {
res := f.ormer.QueryTableWithCtx(c, ptrStructOrTableName)
return []interface{}{res}
},
}
f.root(ctx, inv)
return res
res := f.root(ctx, inv)
if res[0] == nil {
return nil
}
return res[0].(QuerySeter)
}
func (f *filterOrmDecorator) DBStats() *sql.DBStats {
var (
res *sql.DBStats
)
inv := &Invocation{
Method: "DBStats",
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
res = f.ormer.DBStats()
f: func(c context.Context) []interface{} {
res := f.ormer.DBStats()
return []interface{}{res}
},
}
f.root(context.Background(), inv)
return res
res := f.root(context.Background(), inv)
if res[0] == nil {
return nil
}
return res[0].(*sql.DBStats)
}
func (f *filterOrmDecorator) Insert(md interface{}) (int64, error) {
@ -249,10 +252,6 @@ func (f *filterOrmDecorator) Insert(md interface{}) (int64, error) {
}
func (f *filterOrmDecorator) InsertWithCtx(ctx context.Context, md interface{}) (int64, error) {
var (
res int64
err error
)
mi, _ := modelCache.getByMd(md)
inv := &Invocation{
Method: "InsertWithCtx",
@ -261,12 +260,13 @@ func (f *filterOrmDecorator) InsertWithCtx(ctx context.Context, md interface{})
mi: mi,
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
res, err = f.ormer.InsertWithCtx(c, md)
f: func(c context.Context) []interface{} {
res, err := f.ormer.InsertWithCtx(c, md)
return []interface{}{res, err}
},
}
f.root(ctx, inv)
return res, err
res := f.root(ctx, inv)
return res[0].(int64), f.convertError(res[1])
}
func (f *filterOrmDecorator) InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error) {
@ -274,10 +274,6 @@ func (f *filterOrmDecorator) InsertOrUpdate(md interface{}, colConflitAndArgs ..
}
func (f *filterOrmDecorator) InsertOrUpdateWithCtx(ctx context.Context, md interface{}, colConflitAndArgs ...string) (int64, error) {
var (
res int64
err error
)
mi, _ := modelCache.getByMd(md)
inv := &Invocation{
Method: "InsertOrUpdateWithCtx",
@ -286,12 +282,13 @@ func (f *filterOrmDecorator) InsertOrUpdateWithCtx(ctx context.Context, md inter
mi: mi,
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
res, err = f.ormer.InsertOrUpdateWithCtx(c, md, colConflitAndArgs...)
f: func(c context.Context) []interface{} {
res, err := f.ormer.InsertOrUpdateWithCtx(c, md, colConflitAndArgs...)
return []interface{}{res, err}
},
}
f.root(ctx, inv)
return res, err
res := f.root(ctx, inv)
return res[0].(int64), f.convertError(res[1])
}
func (f *filterOrmDecorator) InsertMulti(bulk int, mds interface{}) (int64, error) {
@ -301,10 +298,8 @@ func (f *filterOrmDecorator) InsertMulti(bulk int, mds interface{}) (int64, erro
// InsertMultiWithCtx uses the first element's model info
func (f *filterOrmDecorator) InsertMultiWithCtx(ctx context.Context, bulk int, mds interface{}) (int64, error) {
var (
res int64
err error
md interface{}
mi *modelInfo
md interface{}
mi *modelInfo
)
sind := reflect.Indirect(reflect.ValueOf(mds))
@ -322,12 +317,13 @@ func (f *filterOrmDecorator) InsertMultiWithCtx(ctx context.Context, bulk int, m
mi: mi,
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
res, err = f.ormer.InsertMultiWithCtx(c, bulk, mds)
f: func(c context.Context) []interface{} {
res, err := f.ormer.InsertMultiWithCtx(c, bulk, mds)
return []interface{}{res, err}
},
}
f.root(ctx, inv)
return res, err
res := f.root(ctx, inv)
return res[0].(int64), f.convertError(res[1])
}
func (f *filterOrmDecorator) Update(md interface{}, cols ...string) (int64, error) {
@ -335,10 +331,6 @@ func (f *filterOrmDecorator) Update(md interface{}, cols ...string) (int64, erro
}
func (f *filterOrmDecorator) UpdateWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error) {
var (
res int64
err error
)
mi, _ := modelCache.getByMd(md)
inv := &Invocation{
Method: "UpdateWithCtx",
@ -347,12 +339,13 @@ func (f *filterOrmDecorator) UpdateWithCtx(ctx context.Context, md interface{},
mi: mi,
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
res, err = f.ormer.UpdateWithCtx(c, md, cols...)
f: func(c context.Context) []interface{} {
res, err := f.ormer.UpdateWithCtx(c, md, cols...)
return []interface{}{res, err}
},
}
f.root(ctx, inv)
return res, err
res := f.root(ctx, inv)
return res[0].(int64), f.convertError(res[1])
}
func (f *filterOrmDecorator) Delete(md interface{}, cols ...string) (int64, error) {
@ -360,10 +353,6 @@ func (f *filterOrmDecorator) Delete(md interface{}, cols ...string) (int64, erro
}
func (f *filterOrmDecorator) DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error) {
var (
res int64
err error
)
mi, _ := modelCache.getByMd(md)
inv := &Invocation{
Method: "DeleteWithCtx",
@ -372,12 +361,13 @@ func (f *filterOrmDecorator) DeleteWithCtx(ctx context.Context, md interface{},
mi: mi,
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
res, err = f.ormer.DeleteWithCtx(c, md, cols...)
f: func(c context.Context) []interface{} {
res, err := f.ormer.DeleteWithCtx(c, md, cols...)
return []interface{}{res, err}
},
}
f.root(ctx, inv)
return res, err
res := f.root(ctx, inv)
return res[0].(int64), f.convertError(res[1])
}
func (f *filterOrmDecorator) Raw(query string, args ...interface{}) RawSeter {
@ -385,36 +375,39 @@ func (f *filterOrmDecorator) Raw(query string, args ...interface{}) RawSeter {
}
func (f *filterOrmDecorator) RawWithCtx(ctx context.Context, query string, args ...interface{}) RawSeter {
var (
res RawSeter
)
inv := &Invocation{
Method: "RawWithCtx",
Args: []interface{}{query, args},
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
res = f.ormer.RawWithCtx(c, query, args...)
f: func(c context.Context) []interface{} {
res := f.ormer.RawWithCtx(c, query, args...)
return []interface{}{res}
},
}
f.root(ctx, inv)
return res
res := f.root(ctx, inv)
if res[0] == nil {
return nil
}
return res[0].(RawSeter)
}
func (f *filterOrmDecorator) Driver() Driver {
var (
res Driver
)
inv := &Invocation{
Method: "Driver",
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
res = f.ormer.Driver()
f: func(c context.Context) []interface{} {
res := f.ormer.Driver()
return []interface{}{res}
},
}
f.root(context.Background(), inv)
return res
res := f.root(context.Background(), inv)
if res[0] == nil {
return nil
}
return res[0].(Driver)
}
func (f *filterOrmDecorator) Begin() (TxOrmer, error) {
@ -430,22 +423,19 @@ func (f *filterOrmDecorator) BeginWithOpts(opts *sql.TxOptions) (TxOrmer, error)
}
func (f *filterOrmDecorator) BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions) (TxOrmer, error) {
var (
res TxOrmer
err error
)
inv := &Invocation{
Method: "BeginWithCtxAndOpts",
Args: []interface{}{opts},
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
f: func(c context.Context) {
res, err = f.TxBeginner.BeginWithCtxAndOpts(c, opts)
f: func(c context.Context) []interface{} {
res, err := f.TxBeginner.BeginWithCtxAndOpts(c, opts)
res = NewFilterTxOrmDecorator(res, f.root, getTxNameFromCtx(c))
return []interface{}{res, err}
},
}
f.root(ctx, inv)
return res, err
res := f.root(ctx, inv)
return res[0].(TxOrmer), f.convertError(res[1])
}
func (f *filterOrmDecorator) DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error {
@ -461,58 +451,58 @@ func (f *filterOrmDecorator) DoTxWithOpts(opts *sql.TxOptions, task func(ctx con
}
func (f *filterOrmDecorator) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
var (
err error
)
inv := &Invocation{
Method: "DoTxWithCtxAndOpts",
Args: []interface{}{opts, task},
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
TxName: getTxNameFromCtx(ctx),
f: func(c context.Context) {
err = doTxTemplate(f, c, opts, task)
f: func(c context.Context) []interface{} {
err := doTxTemplate(f, c, opts, task)
return []interface{}{err}
},
}
f.root(ctx, inv)
return err
res := f.root(ctx, inv)
return f.convertError(res[0])
}
func (f *filterOrmDecorator) Commit() error {
var (
err error
)
inv := &Invocation{
Method: "Commit",
Args: []interface{}{},
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
TxName: f.txName,
f: func(c context.Context) {
err = f.TxCommitter.Commit()
f: func(c context.Context) []interface{} {
err := f.TxCommitter.Commit()
return []interface{}{err}
},
}
f.root(context.Background(), inv)
return err
res := f.root(context.Background(), inv)
return f.convertError(res[0])
}
func (f *filterOrmDecorator) Rollback() error {
var (
err error
)
inv := &Invocation{
Method: "Rollback",
Args: []interface{}{},
InsideTx: f.insideTx,
TxStartTime: f.txStartTime,
TxName: f.txName,
f: func(c context.Context) {
err = f.TxCommitter.Rollback()
f: func(c context.Context) []interface{} {
err := f.TxCommitter.Rollback()
return []interface{}{err}
},
}
f.root(context.Background(), inv)
return err
res := f.root(context.Background(), inv)
return f.convertError(res[0])
}
func (f *filterOrmDecorator) convertError(v interface{}) error {
if v == nil {
return nil
}
return v.(error)
}
func getTxNameFromCtx(ctx context.Context) string {

View File

@ -18,10 +18,11 @@ import (
"context"
"database/sql"
"errors"
"github.com/astaxie/beego/pkg/common"
"sync"
"testing"
"github.com/astaxie/beego/pkg/common"
"github.com/stretchr/testify/assert"
)
@ -31,11 +32,11 @@ func TestFilterOrmDecorator_Read(t *testing.T) {
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "ReadWithCtx", inv.Method)
assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName())
next(ctx, inv)
return next(ctx, inv)
}
})
@ -50,7 +51,7 @@ func TestFilterOrmDecorator_BeginTx(t *testing.T) {
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
if inv.Method == "BeginWithCtxAndOpts" {
assert.Equal(t, 1, len(inv.Args))
assert.Equal(t, "", inv.GetTableName())
@ -69,7 +70,7 @@ func TestFilterOrmDecorator_BeginTx(t *testing.T) {
t.Fail()
}
next(ctx, inv)
return next(ctx, inv)
}
})
to, err := od.Begin()
@ -98,11 +99,11 @@ func TestFilterOrmDecorator_BeginTx(t *testing.T) {
func TestFilterOrmDecorator_DBStats(t *testing.T) {
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "DBStats", inv.Method)
assert.Equal(t, 0, len(inv.Args))
assert.Equal(t, "", inv.GetTableName())
next(ctx, inv)
return next(ctx, inv)
}
})
res := od.DBStats()
@ -114,11 +115,11 @@ func TestFilterOrmDecorator_Delete(t *testing.T) {
register()
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "DeleteWithCtx", inv.Method)
assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName())
next(ctx, inv)
return next(ctx, inv)
}
})
res, err := od.Delete(&FilterTestEntity{})
@ -130,14 +131,13 @@ func TestFilterOrmDecorator_Delete(t *testing.T) {
func TestFilterOrmDecorator_DoTx(t *testing.T) {
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
if inv.Method == "DoTxWithCtxAndOpts" {
assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "", inv.GetTableName())
assert.False(t, inv.InsideTx)
}
next(ctx, inv)
return next(ctx, inv)
}
})
@ -156,16 +156,15 @@ func TestFilterOrmDecorator_DoTx(t *testing.T) {
})
assert.NotNil(t, err)
od = NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
if inv.Method == "DoTxWithCtxAndOpts" {
assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "", inv.GetTableName())
assert.Equal(t, "do tx name", inv.TxName)
assert.False(t, inv.InsideTx)
}
next(ctx, inv)
return next(ctx, inv)
}
})
@ -179,12 +178,12 @@ func TestFilterOrmDecorator_DoTx(t *testing.T) {
func TestFilterOrmDecorator_Driver(t *testing.T) {
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "Driver", inv.Method)
assert.Equal(t, 0, len(inv.Args))
assert.Equal(t, "", inv.GetTableName())
assert.False(t, inv.InsideTx)
next(ctx, inv)
return next(ctx, inv)
}
})
res := od.Driver()
@ -195,12 +194,12 @@ func TestFilterOrmDecorator_Insert(t *testing.T) {
register()
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "InsertWithCtx", inv.Method)
assert.Equal(t, 1, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName())
assert.False(t, inv.InsideTx)
next(ctx, inv)
return next(ctx, inv)
}
})
@ -214,12 +213,12 @@ func TestFilterOrmDecorator_InsertMulti(t *testing.T) {
register()
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "InsertMultiWithCtx", inv.Method)
assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName())
assert.False(t, inv.InsideTx)
next(ctx, inv)
return next(ctx, inv)
}
})
@ -234,12 +233,12 @@ func TestFilterOrmDecorator_InsertOrUpdate(t *testing.T) {
register()
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "InsertOrUpdateWithCtx", inv.Method)
assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName())
assert.False(t, inv.InsideTx)
next(ctx, inv)
return next(ctx, inv)
}
})
i, err := od.InsertOrUpdate(&FilterTestEntity{})
@ -251,12 +250,12 @@ func TestFilterOrmDecorator_InsertOrUpdate(t *testing.T) {
func TestFilterOrmDecorator_LoadRelated(t *testing.T) {
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "LoadRelatedWithCtx", inv.Method)
assert.Equal(t, 3, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName())
assert.False(t, inv.InsideTx)
next(ctx, inv)
return next(ctx, inv)
}
})
i, err := od.LoadRelated(&FilterTestEntity{}, "hello")
@ -268,12 +267,12 @@ func TestFilterOrmDecorator_LoadRelated(t *testing.T) {
func TestFilterOrmDecorator_QueryM2M(t *testing.T) {
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "QueryM2MWithCtx", inv.Method)
assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName())
assert.False(t, inv.InsideTx)
next(ctx, inv)
return next(ctx, inv)
}
})
res := od.QueryM2M(&FilterTestEntity{}, "hello")
@ -284,12 +283,12 @@ func TestFilterOrmDecorator_QueryTable(t *testing.T) {
register()
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "QueryTableWithCtx", inv.Method)
assert.Equal(t, 1, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName())
assert.False(t, inv.InsideTx)
next(ctx, inv)
return next(ctx, inv)
}
})
res := od.QueryTable(&FilterTestEntity{})
@ -300,28 +299,28 @@ func TestFilterOrmDecorator_Raw(t *testing.T) {
register()
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "RawWithCtx", inv.Method)
assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "", inv.GetTableName())
assert.False(t, inv.InsideTx)
next(ctx, inv)
return next(ctx, inv)
}
})
res := od.Raw("hh")
assert.Nil(t, res)
}
func TestFilterOrmDecorator_ReadForUpdate(t *testing.T) {
func TestFilterOrmDecorator_ReadForUpdate(t *testing.T) {
register()
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "ReadForUpdateWithCtx", inv.Method)
assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName())
assert.False(t, inv.InsideTx)
next(ctx, inv)
return next(ctx, inv)
}
})
err := od.ReadForUpdate(&FilterTestEntity{})
@ -333,12 +332,12 @@ func TestFilterOrmDecorator_ReadOrCreate(t *testing.T) {
register()
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "ReadOrCreateWithCtx", inv.Method)
assert.Equal(t, 3, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName())
assert.False(t, inv.InsideTx)
next(ctx, inv)
return next(ctx, inv)
}
})
ok, i, err := od.ReadOrCreate(&FilterTestEntity{}, "name")

View File

@ -23,8 +23,8 @@ import (
func TestAddGlobalFilterChain(t *testing.T) {
AddGlobalFilterChain(func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) {
return func(ctx context.Context, inv *Invocation) []interface{} {
return next(ctx, inv)
}
})
assert.Equal(t, 1, len(globalFilterChains))

View File

@ -15,8 +15,9 @@
package hints
import (
"github.com/astaxie/beego/pkg/common"
"time"
"github.com/astaxie/beego/pkg/common"
)
const (

View File

@ -15,9 +15,10 @@
package hints
import (
"github.com/stretchr/testify/assert"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestNewHint_time(t *testing.T) {
@ -151,4 +152,4 @@ func TestOrderBy(t *testing.T) {
hint := OrderBy(`-ID`)
assert.Equal(t, hint.GetValue(), `-ID`)
assert.Equal(t, hint.GetKey(), KeyOrderBy)
}
}

View File

@ -29,7 +29,7 @@ type Invocation struct {
mi *modelInfo
// f is the Orm operation
f func(ctx context.Context)
f func(ctx context.Context) []interface{}
// insideTx indicates whether this is inside a transaction
InsideTx bool
@ -44,8 +44,8 @@ func (inv *Invocation) GetTableName() string {
return ""
}
func (inv *Invocation) execute(ctx context.Context) {
inv.f(ctx)
func (inv *Invocation) execute(ctx context.Context) []interface{} {
return inv.f(ctx)
}
// GetPkFieldName return the primary key of this table

View File

@ -18,11 +18,12 @@ import (
"database/sql"
"encoding/json"
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
"os"
"strings"
"time"
"github.com/astaxie/beego/pkg/orm/hints"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
@ -430,7 +431,7 @@ type PtrPk struct {
}
type StrPk struct {
Id string `orm:"column(id);size(64);pk"`
Id string `orm:"column(id);size(64);pk"`
Value string
}

View File

@ -58,12 +58,13 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/astaxie/beego/pkg/common"
"github.com/astaxie/beego/pkg/orm/hints"
"os"
"reflect"
"time"
"github.com/astaxie/beego/pkg/common"
"github.com/astaxie/beego/pkg/orm/hints"
"github.com/astaxie/beego/pkg/logs"
)

View File

@ -17,6 +17,7 @@ package orm
import (
"context"
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
)

View File

@ -17,9 +17,10 @@ package orm
import (
"database/sql"
"fmt"
"github.com/pkg/errors"
"reflect"
"time"
"github.com/pkg/errors"
)
// raw sql string prepared statement

View File

@ -21,7 +21,6 @@ import (
"context"
"database/sql"
"fmt"
"github.com/astaxie/beego/pkg/orm/hints"
"io/ioutil"
"math"
"os"
@ -32,6 +31,8 @@ import (
"testing"
"time"
"github.com/astaxie/beego/pkg/orm/hints"
"github.com/stretchr/testify/assert"
)
@ -2565,7 +2566,7 @@ func TestStrPkInsert(t *testing.T) {
Id: pk,
Value: value2,
}
_, err = dORM.InsertOrUpdate(strPkForUpsert, `id`)
if err != nil {
fmt.Println(err)

View File

@ -17,9 +17,10 @@ package orm
import (
"context"
"database/sql"
"github.com/astaxie/beego/pkg/common"
"reflect"
"time"
"github.com/astaxie/beego/pkg/common"
)
// TableNaming is usually used by model
@ -579,5 +580,5 @@ type dbBaser interface {
collectFieldValue(*modelInfo, *fieldInfo, reflect.Value, bool, *time.Location) (interface{}, error)
setval(dbQuerier, *modelInfo, []string) error
GenerateSpecifyIndex(tableName string,useIndex int ,indexes []string) string
GenerateSpecifyIndex(tableName string, useIndex int, indexes []string) string
}

View File

@ -19,7 +19,6 @@ import (
"errors"
"fmt"
"go/ast"
"golang.org/x/tools/go/packages"
"io/ioutil"
"os"
"path/filepath"
@ -29,6 +28,8 @@ import (
"strings"
"unicode"
"golang.org/x/tools/go/packages"
"github.com/astaxie/beego/pkg/context/param"
"github.com/astaxie/beego/pkg/logs"
"github.com/astaxie/beego/pkg/utils"

View File

@ -40,7 +40,7 @@ import (
"net/http"
"strings"
"github.com/astaxie/beego/pkg"
beego "github.com/astaxie/beego/pkg"
"github.com/astaxie/beego/pkg/context"
)

View File

@ -40,10 +40,11 @@
package authz
import (
"github.com/astaxie/beego/pkg"
"net/http"
beego "github.com/astaxie/beego/pkg"
"github.com/astaxie/beego/pkg/context"
"github.com/casbin/casbin"
"net/http"
)
// NewAuthorizer returns the authorizer.

View File

@ -15,13 +15,14 @@
package authz
import (
"github.com/astaxie/beego/pkg"
"github.com/astaxie/beego/pkg/context"
"github.com/astaxie/beego/pkg/plugins/auth"
"github.com/casbin/casbin"
"net/http"
"net/http/httptest"
"testing"
beego "github.com/astaxie/beego/pkg"
"github.com/astaxie/beego/pkg/context"
"github.com/astaxie/beego/pkg/plugins/auth"
"github.com/casbin/casbin"
)
func testRequest(t *testing.T, handler *beego.ControllerRegister, user string, path string, method string, code int) {

View File

@ -42,7 +42,7 @@ import (
"strings"
"time"
"github.com/astaxie/beego/pkg"
beego "github.com/astaxie/beego/pkg"
"github.com/astaxie/beego/pkg/context"
)

View File

@ -21,7 +21,7 @@ import (
"testing"
"time"
"github.com/astaxie/beego/pkg"
beego "github.com/astaxie/beego/pkg"
"github.com/astaxie/beego/pkg/context"
)

View File

@ -224,7 +224,7 @@ func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error)
c.Do(c.Context(), "SET", sid, "", "EX", rp.maxlifetime)
} else {
c.Rename(oldsid, sid)
c.Expire(sid, time.Duration(rp.maxlifetime) * time.Second)
c.Expire(sid, time.Duration(rp.maxlifetime)*time.Second)
}
return rp.SessionRead(sid)
}

View File

@ -33,13 +33,14 @@
package redis_cluster
import (
"github.com/astaxie/beego/pkg/session"
rediss "github.com/go-redis/redis/v7"
"net/http"
"strconv"
"strings"
"sync"
"time"
"github.com/astaxie/beego/pkg/session"
rediss "github.com/go-redis/redis/v7"
)
var redispder = &Provider{}

View File

@ -33,13 +33,14 @@
package redis_sentinel
import (
"github.com/astaxie/beego/pkg/session"
"github.com/go-redis/redis/v7"
"net/http"
"strconv"
"strings"
"sync"
"time"
"github.com/astaxie/beego/pkg/session"
"github.com/go-redis/redis/v7"
)
var redispder = &Provider{}

View File

@ -28,7 +28,7 @@ import (
"github.com/astaxie/beego/pkg/context"
"github.com/astaxie/beego/pkg/logs"
"github.com/hashicorp/golang-lru"
lru "github.com/hashicorp/golang-lru"
)
var errNotStaticRequest = errors.New("request not a static file request")

View File

@ -21,7 +21,7 @@ import (
"path/filepath"
"testing"
"github.com/elazarl/go-bindata-assetfs"
assetfs "github.com/elazarl/go-bindata-assetfs"
"github.com/stretchr/testify/assert"
"github.com/astaxie/beego/test"

View File

@ -66,7 +66,7 @@ import (
"strings"
"time"
"github.com/astaxie/beego/pkg"
beego "github.com/astaxie/beego/pkg"
"github.com/astaxie/beego/pkg/cache"
"github.com/astaxie/beego/pkg/context"
"github.com/astaxie/beego/pkg/logs"

View File

@ -16,13 +16,14 @@ package validation
import (
"fmt"
"github.com/astaxie/beego/pkg/logs"
"reflect"
"regexp"
"strings"
"sync"
"time"
"unicode/utf8"
"github.com/astaxie/beego/pkg/logs"
)
// CanSkipFuncs will skip valid if RequiredFirst is true and the struct field's value is empty

View File

@ -11,13 +11,14 @@ import (
"bytes"
"compress/gzip"
"fmt"
"github.com/elazarl/go-bindata-assetfs"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"time"
assetfs "github.com/elazarl/go-bindata-assetfs"
)
func bindataRead(data []byte, name string) ([]byte, error) {