Deprecate QueryM2MWithCtx and QueryTableWithCtx

- Add methods with `WithCtx` suffix and remove ctx fileld from QueryStter
and QueryM2M.
- Deprecate QueryTableWithCtx and QueryM2MWithCtx.

Signed-off-by: Penghui Liao <liaoishere@gmail.com>
This commit is contained in:
Penghui Liao 2021-01-10 13:59:01 +08:00
parent 21777d3143
commit ef227bf467
13 changed files with 130 additions and 68 deletions

View File

@ -8,3 +8,4 @@
- Fix 4383: ORM Adapter produces panic when using orm.RegisterModelWithPrefix. [4386](https://github.com/beego/beego/pull/4386) - Fix 4383: ORM Adapter produces panic when using orm.RegisterModelWithPrefix. [4386](https://github.com/beego/beego/pull/4386)
- Support 4144: Add new api for order by for supporting multiple way to query [4294](https://github.com/beego/beego/pull/4294) - Support 4144: Add new api for order by for supporting multiple way to query [4294](https://github.com/beego/beego/pull/4294)
- Support session Filter chain. [4404](https://github.com/beego/beego/pull/4404) - Support session Filter chain. [4404](https://github.com/beego/beego/pull/4404)
- Implement context.Context support and deprecate `QueryM2MWithCtx` and `QueryTableWithCtx` [4424](https://github.com/beego/beego/pull/4424)

View File

@ -77,7 +77,6 @@ func RunCommand() {
// sync database struct command interface. // sync database struct command interface.
type commandSyncDb struct { type commandSyncDb struct {
ctx context.Context
al *alias al *alias
force bool force bool
verbose bool verbose bool
@ -143,6 +142,7 @@ func (d *commandSyncDb) Run() error {
fmt.Printf(" %s\n", err.Error()) fmt.Printf(" %s\n", err.Error())
} }
ctx := context.Background()
for i, mi := range modelCache.allOrdered() { for i, mi := range modelCache.allOrdered() {
if !isApplicableTableForDB(mi.addrField, d.al.Name) { if !isApplicableTableForDB(mi.addrField, d.al.Name) {
@ -156,7 +156,7 @@ func (d *commandSyncDb) Run() error {
} }
var fields []*fieldInfo var fields []*fieldInfo
columns, err := d.al.DbBaser.GetColumns(d.ctx, db, mi.table) columns, err := d.al.DbBaser.GetColumns(ctx, db, mi.table)
if err != nil { if err != nil {
if d.rtOnError { if d.rtOnError {
return err return err
@ -190,7 +190,7 @@ func (d *commandSyncDb) Run() error {
} }
for _, idx := range indexes[mi.table] { for _, idx := range indexes[mi.table] {
if !d.al.DbBaser.IndexExists(d.ctx, db, idx.Table, idx.Name) { if !d.al.DbBaser.IndexExists(ctx, db, idx.Table, idx.Name) {
if !d.noInfo { if !d.noInfo {
fmt.Printf("create index `%s` for table `%s`\n", idx.Name, idx.Table) fmt.Printf("create index `%s` for table `%s`\n", idx.Name, idx.Table)
} }
@ -292,7 +292,6 @@ func RunSyncdb(name string, force bool, verbose bool) error {
al := getDbAlias(name) al := getDbAlias(name)
cmd := new(commandSyncDb) cmd := new(commandSyncDb)
cmd.ctx = context.TODO()
cmd.al = al cmd.al = al
cmd.force = force cmd.force = force
cmd.noInfo = !verbose cmd.noInfo = !verbose

View File

@ -66,6 +66,7 @@ func (d *DoNothingOrm) QueryM2M(md interface{}, name string) QueryM2Mer {
return nil return nil
} }
// NOTE: this method is deprecated, context parameter will not take effect.
func (d *DoNothingOrm) QueryM2MWithCtx(ctx context.Context, md interface{}, name string) QueryM2Mer { func (d *DoNothingOrm) QueryM2MWithCtx(ctx context.Context, md interface{}, name string) QueryM2Mer {
return nil return nil
} }
@ -74,6 +75,7 @@ func (d *DoNothingOrm) QueryTable(ptrStructOrTableName interface{}) QuerySeter {
return nil return nil
} }
// NOTE: this method is deprecated, context parameter will not take effect.
func (d *DoNothingOrm) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter { func (d *DoNothingOrm) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter {
return nil return nil
} }

View File

@ -36,7 +36,6 @@ func TestDoNothingOrm(t *testing.T) {
assert.Nil(t, o.Driver()) assert.Nil(t, o.Driver())
assert.Nil(t, o.QueryM2MWithCtx(nil, nil, ""))
assert.Nil(t, o.QueryM2M(nil, "")) assert.Nil(t, o.QueryM2M(nil, ""))
assert.Nil(t, o.ReadWithCtx(nil, nil)) assert.Nil(t, o.ReadWithCtx(nil, nil))
assert.Nil(t, o.Read(nil)) assert.Nil(t, o.Read(nil))
@ -92,7 +91,6 @@ func TestDoNothingOrm(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, int64(0), i) assert.Equal(t, int64(0), i)
assert.Nil(t, o.QueryTableWithCtx(nil, nil))
assert.Nil(t, o.QueryTable(nil)) assert.Nil(t, o.QueryTable(nil))
assert.Nil(t, o.Read(nil)) assert.Nil(t, o.Read(nil))

View File

@ -27,7 +27,7 @@ import (
// this Filter's behavior looks a little bit strange // this Filter's behavior looks a little bit strange
// for example: // for example:
// if we want to trace QuerySetter // if we want to trace QuerySetter
// actually we trace invoking "QueryTable" and "QueryTableWithCtx" // actually we trace invoking "QueryTable"
// the method Begin*, Commit and Rollback are ignored. // the method Begin*, Commit and Rollback are ignored.
// When use using those methods, it means that they want to manager their transaction manually, so we won't handle them. // When use using those methods, it means that they want to manager their transaction manually, so we won't handle them.
type FilterChainBuilder struct { type FilterChainBuilder struct {

View File

@ -31,7 +31,7 @@ import (
// this Filter's behavior looks a little bit strange // this Filter's behavior looks a little bit strange
// for example: // for example:
// if we want to records the metrics of QuerySetter // if we want to records the metrics of QuerySetter
// actually we only records metrics of invoking "QueryTable" and "QueryTableWithCtx" // actually we only records metrics of invoking "QueryTable"
type FilterChainBuilder struct { type FilterChainBuilder struct {
summaryVec prometheus.ObserverVec summaryVec prometheus.ObserverVec
AppName string AppName string

View File

@ -20,6 +20,7 @@ import (
"reflect" "reflect"
"time" "time"
"github.com/beego/beego/v2/core/logs"
"github.com/beego/beego/v2/core/utils" "github.com/beego/beego/v2/core/utils"
) )
@ -161,36 +162,34 @@ func (f *filterOrmDecorator) LoadRelatedWithCtx(ctx context.Context, md interfac
} }
func (f *filterOrmDecorator) QueryM2M(md interface{}, name string) QueryM2Mer { func (f *filterOrmDecorator) QueryM2M(md interface{}, name string) QueryM2Mer {
return f.QueryM2MWithCtx(context.Background(), md, name)
}
func (f *filterOrmDecorator) QueryM2MWithCtx(ctx context.Context, md interface{}, name string) QueryM2Mer {
mi, _ := modelCache.getByMd(md) mi, _ := modelCache.getByMd(md)
inv := &Invocation{ inv := &Invocation{
Method: "QueryM2MWithCtx", Method: "QueryM2M",
Args: []interface{}{md, name}, Args: []interface{}{md, name},
Md: md, Md: md,
mi: mi, mi: mi,
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func(c context.Context) []interface{} { f: func(c context.Context) []interface{} {
res := f.ormer.QueryM2MWithCtx(c, md, name) res := f.ormer.QueryM2M(md, name)
return []interface{}{res} return []interface{}{res}
}, },
} }
res := f.root(ctx, inv) res := f.root(context.Background(), inv)
if res[0] == nil { if res[0] == nil {
return nil return nil
} }
return res[0].(QueryM2Mer) return res[0].(QueryM2Mer)
} }
func (f *filterOrmDecorator) QueryTable(ptrStructOrTableName interface{}) QuerySeter { // NOTE: this method is deprecated, context parameter will not take effect.
return f.QueryTableWithCtx(context.Background(), ptrStructOrTableName) func (f *filterOrmDecorator) QueryM2MWithCtx(_ context.Context, md interface{}, name string) QueryM2Mer {
logs.Warn("QueryM2MWithCtx is DEPRECATED. Use methods with `WithCtx` on QueryM2Mer suffix as replacement.")
return f.QueryM2M(md, name)
} }
func (f *filterOrmDecorator) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter { func (f *filterOrmDecorator) QueryTable(ptrStructOrTableName interface{}) QuerySeter {
var ( var (
name string name string
md interface{} md interface{}
@ -209,18 +208,18 @@ func (f *filterOrmDecorator) QueryTableWithCtx(ctx context.Context, ptrStructOrT
} }
inv := &Invocation{ inv := &Invocation{
Method: "QueryTableWithCtx", Method: "QueryTable",
Args: []interface{}{ptrStructOrTableName}, Args: []interface{}{ptrStructOrTableName},
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
Md: md, Md: md,
mi: mi, mi: mi,
f: func(c context.Context) []interface{} { f: func(c context.Context) []interface{} {
res := f.ormer.QueryTableWithCtx(c, ptrStructOrTableName) res := f.ormer.QueryTable(ptrStructOrTableName)
return []interface{}{res} return []interface{}{res}
}, },
} }
res := f.root(ctx, inv) res := f.root(context.Background(), inv)
if res[0] == nil { if res[0] == nil {
return nil return nil
@ -228,6 +227,12 @@ func (f *filterOrmDecorator) QueryTableWithCtx(ctx context.Context, ptrStructOrT
return res[0].(QuerySeter) return res[0].(QuerySeter)
} }
// NOTE: this method is deprecated, context parameter will not take effect.
func (f *filterOrmDecorator) QueryTableWithCtx(_ context.Context, ptrStructOrTableName interface{}) QuerySeter {
logs.Warn("QueryTableWithCtx is DEPRECATED. Use methods with `WithCtx`on QuerySeter suffix as replacement.")
return f.QueryTable(ptrStructOrTableName)
}
func (f *filterOrmDecorator) DBStats() *sql.DBStats { func (f *filterOrmDecorator) DBStats() *sql.DBStats {
inv := &Invocation{ inv := &Invocation{
Method: "DBStats", Method: "DBStats",

View File

@ -268,7 +268,7 @@ func TestFilterOrmDecorator_QueryM2M(t *testing.T) {
o := &filterMockOrm{} o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter { od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) []interface{} { return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "QueryM2MWithCtx", inv.Method) assert.Equal(t, "QueryM2M", inv.Method)
assert.Equal(t, 2, len(inv.Args)) assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName()) assert.Equal(t, "FILTER_TEST", inv.GetTableName())
assert.False(t, inv.InsideTx) assert.False(t, inv.InsideTx)
@ -284,7 +284,7 @@ func TestFilterOrmDecorator_QueryTable(t *testing.T) {
o := &filterMockOrm{} o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter { od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) []interface{} { return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "QueryTableWithCtx", inv.Method) assert.Equal(t, "QueryTable", inv.Method)
assert.Equal(t, 1, len(inv.Args)) assert.Equal(t, 1, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName()) assert.Equal(t, "FILTER_TEST", inv.GetTableName())
assert.False(t, inv.InsideTx) assert.False(t, inv.InsideTx)

View File

@ -284,9 +284,6 @@ func (o *ormBase) DeleteWithCtx(ctx context.Context, md interface{}, cols ...str
// create a models to models queryer // create a models to models queryer
func (o *ormBase) QueryM2M(md interface{}, name string) QueryM2Mer { func (o *ormBase) QueryM2M(md interface{}, name string) QueryM2Mer {
return o.QueryM2MWithCtx(context.Background(), md, name)
}
func (o *ormBase) QueryM2MWithCtx(ctx context.Context, md interface{}, name string) QueryM2Mer {
mi, ind := o.getMiInd(md, true) mi, ind := o.getMiInd(md, true)
fi := o.getFieldInfo(mi, name) fi := o.getFieldInfo(mi, name)
@ -297,7 +294,13 @@ func (o *ormBase) QueryM2MWithCtx(ctx context.Context, md interface{}, name stri
panic(fmt.Errorf("<Ormer.QueryM2M> model `%s` . name `%s` is not a m2m field", fi.name, mi.fullName)) panic(fmt.Errorf("<Ormer.QueryM2M> model `%s` . name `%s` is not a m2m field", fi.name, mi.fullName))
} }
return newQueryM2M(ctx, md, o, mi, fi, ind) return newQueryM2M(md, o, mi, fi, ind)
}
// NOTE: this method is deprecated, context parameter will not take effect.
func (o *ormBase) QueryM2MWithCtx(_ context.Context, md interface{}, name string) QueryM2Mer {
logs.Warn("QueryM2MWithCtx is DEPRECATED. Use methods with `WithCtx` suffix on QueryM2M as replacement please.")
return o.QueryM2M(md, name)
} }
// load related models to md model. // load related models to md model.
@ -452,9 +455,6 @@ func (o *ormBase) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *queryS
// table name can be string or struct. // table name can be string or struct.
// e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)), // e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)),
func (o *ormBase) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { func (o *ormBase) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) {
return o.QueryTableWithCtx(context.Background(), ptrStructOrTableName)
}
func (o *ormBase) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) (qs QuerySeter) {
var name string var name string
if table, ok := ptrStructOrTableName.(string); ok { if table, ok := ptrStructOrTableName.(string); ok {
name = nameStrategyMap[defaultNameStrategy](table) name = nameStrategyMap[defaultNameStrategy](table)
@ -470,7 +470,13 @@ func (o *ormBase) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName in
if qs == nil { if qs == nil {
panic(fmt.Errorf("<Ormer.QueryTable> table name: `%s` not exists", name)) panic(fmt.Errorf("<Ormer.QueryTable> table name: `%s` not exists", name))
} }
return qs.WithContext(ctx) return qs
}
// NOTE: this method is deprecated, context parameter will not take effect.
func (o *ormBase) QueryTableWithCtx(_ context.Context, ptrStructOrTableName interface{}) (qs QuerySeter) {
logs.Warn("QueryTableWithCtx is DEPRECATED. Use methods with `WithCtx` suffix on QuerySeter as replacement please.")
return o.QueryTable(ptrStructOrTableName)
} }
// return a raw query seter for raw sql string. // return a raw query seter for raw sql string.

View File

@ -21,7 +21,6 @@ import (
// model to model struct // model to model struct
type queryM2M struct { type queryM2M struct {
ctx context.Context
md interface{} md interface{}
mi *modelInfo mi *modelInfo
fi *fieldInfo fi *fieldInfo
@ -37,6 +36,10 @@ type queryM2M struct {
// //
// make sure the relation is defined in post model struct tag. // make sure the relation is defined in post model struct tag.
func (o *queryM2M) Add(mds ...interface{}) (int64, error) { func (o *queryM2M) Add(mds ...interface{}) (int64, error) {
return o.AddWithCtx(context.Background(), mds...)
}
func (o *queryM2M) AddWithCtx(ctx context.Context, mds ...interface{}) (int64, error) {
fi := o.fi fi := o.fi
mi := fi.relThroughModelInfo mi := fi.relThroughModelInfo
mfi := fi.reverseFieldInfo mfi := fi.reverseFieldInfo
@ -100,11 +103,15 @@ func (o *queryM2M) Add(mds ...interface{}) (int64, error) {
} }
names = append(names, otherNames...) names = append(names, otherNames...)
values = append(values, otherValues...) values = append(values, otherValues...)
return dbase.InsertValue(o.ctx, orm.db, mi, true, names, values) return dbase.InsertValue(ctx, orm.db, mi, true, names, values)
} }
// remove models following the origin model relationship // remove models following the origin model relationship
func (o *queryM2M) Remove(mds ...interface{}) (int64, error) { func (o *queryM2M) Remove(mds ...interface{}) (int64, error) {
return o.RemoveWithCtx(context.Background(), mds...)
}
func (o *queryM2M) RemoveWithCtx(ctx context.Context, mds ...interface{}) (int64, error) {
fi := o.fi fi := o.fi
qs := o.qs.Filter(fi.reverseFieldInfo.name, o.md) qs := o.qs.Filter(fi.reverseFieldInfo.name, o.md)
@ -113,33 +120,44 @@ func (o *queryM2M) Remove(mds ...interface{}) (int64, error) {
// check model is existed in relationship of origin model // check model is existed in relationship of origin model
func (o *queryM2M) Exist(md interface{}) bool { func (o *queryM2M) Exist(md interface{}) bool {
return o.ExistWithCtx(context.Background(), md)
}
func (o *queryM2M) ExistWithCtx(ctx context.Context, md interface{}) bool {
fi := o.fi fi := o.fi
return o.qs.Filter(fi.reverseFieldInfo.name, o.md). return o.qs.Filter(fi.reverseFieldInfo.name, o.md).
Filter(fi.reverseFieldInfoTwo.name, md).Exist() Filter(fi.reverseFieldInfoTwo.name, md).ExistWithCtx(ctx)
} }
// clean all models in related of origin model // clean all models in related of origin model
func (o *queryM2M) Clear() (int64, error) { func (o *queryM2M) Clear() (int64, error) {
return o.ClearWithCtx(context.Background())
}
func (o *queryM2M) ClearWithCtx(ctx context.Context) (int64, error) {
fi := o.fi fi := o.fi
return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Delete() return o.qs.Filter(fi.reverseFieldInfo.name, o.md).DeleteWithCtx(ctx)
} }
// count all related models of origin model // count all related models of origin model
func (o *queryM2M) Count() (int64, error) { func (o *queryM2M) Count() (int64, error) {
return o.CountWithCtx(context.Background())
}
func (o *queryM2M) CountWithCtx(ctx context.Context) (int64, error) {
fi := o.fi fi := o.fi
return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Count() return o.qs.Filter(fi.reverseFieldInfo.name, o.md).CountWithCtx(ctx)
} }
var _ QueryM2Mer = new(queryM2M) var _ QueryM2Mer = new(queryM2M)
// create new M2M queryer. // create new M2M queryer.
func newQueryM2M(ctx context.Context, md interface{}, o *ormBase, mi *modelInfo, fi *fieldInfo, ind reflect.Value) QueryM2Mer { func newQueryM2M(md interface{}, o *ormBase, mi *modelInfo, fi *fieldInfo, ind reflect.Value) QueryM2Mer {
qm2m := new(queryM2M) qm2m := new(queryM2M)
qm2m.ctx = ctx
qm2m.md = md qm2m.md = md
qm2m.mi = mi qm2m.mi = mi
qm2m.fi = fi qm2m.fi = fi
qm2m.ind = ind qm2m.ind = ind
qm2m.qs = newQuerySet(o, fi.relThroughModelInfo).WithContext(ctx).(*querySet) qm2m.qs = newQuerySet(o, fi.relThroughModelInfo).(*querySet)
return qm2m return qm2m
} }

View File

@ -78,7 +78,6 @@ type querySet struct {
useIndex int useIndex int
indexes []string indexes []string
orm *ormBase orm *ormBase
ctx context.Context
aggregate string aggregate string
} }
@ -221,35 +220,40 @@ func (o querySet) GetCond() *Condition {
return o.cond return o.cond
} }
func (o querySet) getContext() context.Context {
if o.ctx != nil {
return o.ctx
}
return context.Background()
}
// return QuerySeter execution result number // return QuerySeter execution result number
func (o *querySet) Count() (int64, error) { func (o *querySet) Count() (int64, error) {
ctx := o.getContext() return o.CountWithCtx(context.Background())
}
func (o *querySet) CountWithCtx(ctx context.Context) (int64, error) {
return o.orm.alias.DbBaser.Count(ctx, o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) return o.orm.alias.DbBaser.Count(ctx, o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ)
} }
// check result empty or not after QuerySeter executed // check result empty or not after QuerySeter executed
func (o *querySet) Exist() bool { func (o *querySet) Exist() bool {
ctx := o.getContext() return o.ExistWithCtx(context.Background())
}
func (o *querySet) ExistWithCtx(ctx context.Context) bool {
cnt, _ := o.orm.alias.DbBaser.Count(ctx, o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) cnt, _ := o.orm.alias.DbBaser.Count(ctx, o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ)
return cnt > 0 return cnt > 0
} }
// execute update with parameters // execute update with parameters
func (o *querySet) Update(values Params) (int64, error) { func (o *querySet) Update(values Params) (int64, error) {
ctx := o.getContext() return o.UpdateWithCtx(context.Background(), values)
}
func (o *querySet) UpdateWithCtx(ctx context.Context, values Params) (int64, error) {
return o.orm.alias.DbBaser.UpdateBatch(ctx, o.orm.db, o, o.mi, o.cond, values, o.orm.alias.TZ) return o.orm.alias.DbBaser.UpdateBatch(ctx, o.orm.db, o, o.mi, o.cond, values, o.orm.alias.TZ)
} }
// execute delete // execute delete
func (o *querySet) Delete() (int64, error) { func (o *querySet) Delete() (int64, error) {
ctx := o.getContext() return o.DeleteWithCtx(context.Background())
}
func (o *querySet) DeleteWithCtx(ctx context.Context) (int64, error) {
return o.orm.alias.DbBaser.DeleteBatch(ctx, o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) return o.orm.alias.DbBaser.DeleteBatch(ctx, o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ)
} }
@ -259,21 +263,30 @@ func (o *querySet) Delete() (int64, error) {
// i,err := sq.PrepareInsert() // i,err := sq.PrepareInsert()
// i.Add(&user1{},&user2{}) // i.Add(&user1{},&user2{})
func (o *querySet) PrepareInsert() (Inserter, error) { func (o *querySet) PrepareInsert() (Inserter, error) {
ctx := o.getContext() return o.PrepareInsertWithCtx(context.Background())
}
func (o *querySet) PrepareInsertWithCtx(ctx context.Context) (Inserter, error) {
return newInsertSet(ctx, o.orm, o.mi) return newInsertSet(ctx, o.orm, o.mi)
} }
// query all data and map to containers. // query all data and map to containers.
// cols means the columns when querying. // cols means the columns when querying.
func (o *querySet) All(container interface{}, cols ...string) (int64, error) { func (o *querySet) All(container interface{}, cols ...string) (int64, error) {
ctx := o.getContext() return o.AllWithCtx(context.Background(), container, cols...)
}
func (o *querySet) AllWithCtx(ctx context.Context, container interface{}, cols ...string) (int64, error) {
return o.orm.alias.DbBaser.ReadBatch(ctx, o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols) return o.orm.alias.DbBaser.ReadBatch(ctx, o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols)
} }
// query one row data and map to containers. // query one row data and map to containers.
// cols means the columns when querying. // cols means the columns when querying.
func (o *querySet) One(container interface{}, cols ...string) error { func (o *querySet) One(container interface{}, cols ...string) error {
ctx := o.getContext() return o.OneWithCtx(context.Background(), container, cols...)
}
func (o *querySet) OneWithCtx(ctx context.Context, container interface{}, cols ...string) error {
o.limit = 1 o.limit = 1
num, err := o.orm.alias.DbBaser.ReadBatch(ctx, o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols) num, err := o.orm.alias.DbBaser.ReadBatch(ctx, o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols)
if err != nil { if err != nil {
@ -293,21 +306,30 @@ func (o *querySet) One(container interface{}, cols ...string) error {
// expres means condition expression. // expres means condition expression.
// it converts data to []map[column]value. // it converts data to []map[column]value.
func (o *querySet) Values(results *[]Params, exprs ...string) (int64, error) { func (o *querySet) Values(results *[]Params, exprs ...string) (int64, error) {
ctx := o.getContext() return o.ValuesWithCtx(context.Background(), results, exprs...)
}
func (o *querySet) ValuesWithCtx(ctx context.Context, results *[]Params, exprs ...string) (int64, error) {
return o.orm.alias.DbBaser.ReadValues(ctx, o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ) return o.orm.alias.DbBaser.ReadValues(ctx, o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ)
} }
// query all data and map to [][]interface // query all data and map to [][]interface
// it converts data to [][column_index]value // it converts data to [][column_index]value
func (o *querySet) ValuesList(results *[]ParamsList, exprs ...string) (int64, error) { func (o *querySet) ValuesList(results *[]ParamsList, exprs ...string) (int64, error) {
ctx := o.getContext() return o.ValuesListWithCtx(context.Background(), results, exprs...)
}
func (o *querySet) ValuesListWithCtx(ctx context.Context, results *[]ParamsList, exprs ...string) (int64, error) {
return o.orm.alias.DbBaser.ReadValues(ctx, o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ) return o.orm.alias.DbBaser.ReadValues(ctx, o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ)
} }
// query all data and map to []interface. // query all data and map to []interface.
// it's designed for one row record set, auto change to []value, not [][column]value. // it's designed for one row record set, auto change to []value, not [][column]value.
func (o *querySet) ValuesFlat(result *ParamsList, expr string) (int64, error) { func (o *querySet) ValuesFlat(result *ParamsList, expr string) (int64, error) {
ctx := o.getContext() return o.ValuesFlatWithCtx(context.Background(), result, expr)
}
func (o *querySet) ValuesFlatWithCtx(ctx context.Context, result *ParamsList, expr string) (int64, error) {
return o.orm.alias.DbBaser.ReadValues(ctx, o.orm.db, o, o.mi, o.cond, []string{expr}, result, o.orm.alias.TZ) return o.orm.alias.DbBaser.ReadValues(ctx, o.orm.db, o, o.mi, o.cond, []string{expr}, result, o.orm.alias.TZ)
} }
@ -339,12 +361,6 @@ func (o *querySet) RowsToStruct(ptrStruct interface{}, keyCol, valueCol string)
panic(ErrNotImplement) panic(ErrNotImplement)
} }
// set context to QuerySeter.
func (o querySet) WithContext(ctx context.Context) QuerySeter {
o.ctx = ctx
return &o
}
// create new QuerySeter. // create new QuerySeter.
func newQuerySet(orm *ormBase, mi *modelInfo) QuerySeter { func newQuerySet(orm *ormBase, mi *modelInfo) QuerySeter {
o := new(querySet) o := new(querySet)

View File

@ -2836,7 +2836,7 @@ func TestContextCanceled(t *testing.T) {
ctx, cancel = context.WithCancel(context.Background()) ctx, cancel = context.WithCancel(context.Background())
cancel() cancel()
qs := dORM.QueryTable(user).WithContext(ctx) qs := dORM.QueryTable(user)
_, err = qs.Filter("UserName", "slene").Count() _, err = qs.Filter("UserName", "slene").CountWithCtx(ctx)
throwFail(t, AssertIs(err, context.Canceled)) throwFail(t, AssertIs(err, context.Canceled))
} }

View File

@ -197,12 +197,16 @@ type DQL interface {
// post := Post{Id: 4} // post := Post{Id: 4}
// m2m := Ormer.QueryM2M(&post, "Tags") // m2m := Ormer.QueryM2M(&post, "Tags")
QueryM2M(md interface{}, name string) QueryM2Mer QueryM2M(md interface{}, name string) QueryM2Mer
// NOTE: this method is deprecated, context parameter will not take effect.
// Use context.Context directly on methods with `WithCtx` suffix such as InsertWithCtx/UpdateWithCtx
QueryM2MWithCtx(ctx context.Context, md interface{}, name string) QueryM2Mer QueryM2MWithCtx(ctx context.Context, md interface{}, name string) QueryM2Mer
// return a QuerySeter for table operations. // return a QuerySeter for table operations.
// table name can be string or struct. // table name can be string or struct.
// e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)), // e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)),
QueryTable(ptrStructOrTableName interface{}) QuerySeter QueryTable(ptrStructOrTableName interface{}) QuerySeter
// NOTE: this method is deprecated, context parameter will not take effect.
// Use context.Context directly on methods with `WithCtx` suffix such as InsertWithCtx/UpdateWithCtx
QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter
DBStats() *sql.DBStats DBStats() *sql.DBStats
@ -236,8 +240,6 @@ type Inserter interface {
// QuerySeter query seter // QuerySeter query seter
type QuerySeter interface { type QuerySeter interface {
// add query context for querySeter
WithContext(context.Context) QuerySeter
// add condition expression to QuerySeter. // add condition expression to QuerySeter.
// for example: // for example:
// filter by UserName == 'slene' // filter by UserName == 'slene'
@ -352,9 +354,11 @@ type QuerySeter interface {
// for example: // for example:
// num, err = qs.Filter("profile__age__gt", 28).Count() // num, err = qs.Filter("profile__age__gt", 28).Count()
Count() (int64, error) Count() (int64, error)
CountWithCtx(context.Context) (int64, error)
// check result empty or not after QuerySeter executed // check result empty or not after QuerySeter executed
// the same as QuerySeter.Count > 0 // the same as QuerySeter.Count > 0
Exist() bool Exist() bool
ExistWithCtx(context.Context) bool
// execute update with parameters // execute update with parameters
// for example: // for example:
// num, err = qs.Filter("user_name", "slene").Update(Params{ // num, err = qs.Filter("user_name", "slene").Update(Params{
@ -364,11 +368,13 @@ type QuerySeter interface {
// "user_name": "slene2" // "user_name": "slene2"
// }) // user slene's name will change to slene2 // }) // user slene's name will change to slene2
Update(values Params) (int64, error) Update(values Params) (int64, error)
UpdateWithCtx(ctx context.Context, values Params) (int64, error)
// delete from table // delete from table
// for example: // for example:
// num ,err = qs.Filter("user_name__in", "testing1", "testing2").Delete() // num ,err = qs.Filter("user_name__in", "testing1", "testing2").Delete()
// //delete two user who's name is testing1 or testing2 // //delete two user who's name is testing1 or testing2
Delete() (int64, error) Delete() (int64, error)
DeleteWithCtx(context.Context) (int64, error)
// return a insert queryer. // return a insert queryer.
// it can be used in times. // it can be used in times.
// example: // example:
@ -377,18 +383,21 @@ type QuerySeter interface {
// num, err = i.Insert(&user2) // user table will add one record user2 at once // num, err = i.Insert(&user2) // user table will add one record user2 at once
// err = i.Close() //don't forget call Close // err = i.Close() //don't forget call Close
PrepareInsert() (Inserter, error) PrepareInsert() (Inserter, error)
PrepareInsertWithCtx(context.Context) (Inserter, error)
// query all data and map to containers. // query all data and map to containers.
// cols means the columns when querying. // cols means the columns when querying.
// for example: // for example:
// var users []*User // var users []*User
// qs.All(&users) // users[0],users[1],users[2] ... // qs.All(&users) // users[0],users[1],users[2] ...
All(container interface{}, cols ...string) (int64, error) All(container interface{}, cols ...string) (int64, error)
AllWithCtx(ctx context.Context, container interface{}, cols ...string) (int64, error)
// query one row data and map to containers. // query one row data and map to containers.
// cols means the columns when querying. // cols means the columns when querying.
// for example: // for example:
// var user User // var user User
// qs.One(&user) //user.UserName == "slene" // qs.One(&user) //user.UserName == "slene"
One(container interface{}, cols ...string) error One(container interface{}, cols ...string) error
OneWithCtx(ctx context.Context, container interface{}, cols ...string) error
// query all data and map to []map[string]interface. // query all data and map to []map[string]interface.
// expres means condition expression. // expres means condition expression.
// it converts data to []map[column]value. // it converts data to []map[column]value.
@ -396,18 +405,21 @@ type QuerySeter interface {
// var maps []Params // var maps []Params
// qs.Values(&maps) //maps[0]["UserName"]=="slene" // qs.Values(&maps) //maps[0]["UserName"]=="slene"
Values(results *[]Params, exprs ...string) (int64, error) Values(results *[]Params, exprs ...string) (int64, error)
ValuesWithCtx(ctx context.Context, results *[]Params, exprs ...string) (int64, error)
// query all data and map to [][]interface // query all data and map to [][]interface
// it converts data to [][column_index]value // it converts data to [][column_index]value
// for example: // for example:
// var list []ParamsList // var list []ParamsList
// qs.ValuesList(&list) // list[0][1] == "slene" // qs.ValuesList(&list) // list[0][1] == "slene"
ValuesList(results *[]ParamsList, exprs ...string) (int64, error) ValuesList(results *[]ParamsList, exprs ...string) (int64, error)
ValuesListWithCtx(ctx context.Context, results *[]ParamsList, exprs ...string) (int64, error)
// query all data and map to []interface. // query all data and map to []interface.
// it's designed for one column record set, auto change to []value, not [][column]value. // it's designed for one column record set, auto change to []value, not [][column]value.
// for example: // for example:
// var list ParamsList // var list ParamsList
// qs.ValuesFlat(&list, "UserName") // list[0] == "slene" // qs.ValuesFlat(&list, "UserName") // list[0] == "slene"
ValuesFlat(result *ParamsList, expr string) (int64, error) ValuesFlat(result *ParamsList, expr string) (int64, error)
ValuesFlatWithCtx(ctx context.Context, result *ParamsList, expr string) (int64, error)
// query all rows into map[string]interface with specify key and value column name. // query all rows into map[string]interface with specify key and value column name.
// keyCol = "name", valueCol = "value" // keyCol = "name", valueCol = "value"
// table data // table data
@ -456,18 +468,23 @@ type QueryM2Mer interface {
// insert one or more rows to m2m table // insert one or more rows to m2m table
// make sure the relation is defined in post model struct tag. // make sure the relation is defined in post model struct tag.
Add(...interface{}) (int64, error) Add(...interface{}) (int64, error)
AddWithCtx(context.Context, ...interface{}) (int64, error)
// remove models following the origin model relationship // remove models following the origin model relationship
// only delete rows from m2m table // only delete rows from m2m table
// for example: // for example:
// tag3 := &Tag{Id:5,Name: "TestTag3"} // tag3 := &Tag{Id:5,Name: "TestTag3"}
// num, err = m2m.Remove(tag3) // num, err = m2m.Remove(tag3)
Remove(...interface{}) (int64, error) Remove(...interface{}) (int64, error)
RemoveWithCtx(context.Context, ...interface{}) (int64, error)
// check model is existed in relationship of origin model // check model is existed in relationship of origin model
Exist(interface{}) bool Exist(interface{}) bool
ExistWithCtx(context.Context, interface{}) bool
// clean all models in related of origin model // clean all models in related of origin model
Clear() (int64, error) Clear() (int64, error)
ClearWithCtx(context.Context) (int64, error)
// count all related models of origin model // count all related models of origin model
Count() (int64, error) Count() (int64, error)
CountWithCtx(context.Context) (int64, error)
} }
// RawPreparer raw query statement // RawPreparer raw query statement