mirror of
https://github.com/astaxie/beego.git
synced 2024-11-23 08:20:54 +00:00
130 lines
3.0 KiB
Go
130 lines
3.0 KiB
Go
// Beego (http://beego.me/)
|
|
//
|
|
// @description beego is an open-source, high-performance web framework for the Go programming language.
|
|
//
|
|
// @link http://github.com/astaxie/beego for the canonical source repository
|
|
//
|
|
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
|
//
|
|
// @authors astaxie, slene
|
|
package orm
|
|
|
|
import (
|
|
"reflect"
|
|
)
|
|
|
|
// model to model struct
|
|
type queryM2M struct {
|
|
md interface{}
|
|
mi *modelInfo
|
|
fi *fieldInfo
|
|
qs *querySet
|
|
ind reflect.Value
|
|
}
|
|
|
|
// add models to origin models when creating queryM2M.
|
|
// example:
|
|
// m2m := orm.QueryM2M(post,"Tag")
|
|
// m2m.Add(&Tag1{},&Tag2{})
|
|
// for _,tag := range post.Tags{}
|
|
//
|
|
// make sure the relation is defined in post model struct tag.
|
|
func (o *queryM2M) Add(mds ...interface{}) (int64, error) {
|
|
fi := o.fi
|
|
mi := fi.relThroughModelInfo
|
|
mfi := fi.reverseFieldInfo
|
|
rfi := fi.reverseFieldInfoTwo
|
|
|
|
orm := o.qs.orm
|
|
dbase := orm.alias.DbBaser
|
|
|
|
var models []interface{}
|
|
|
|
for _, md := range mds {
|
|
val := reflect.ValueOf(md)
|
|
if val.Kind() == reflect.Slice || val.Kind() == reflect.Array {
|
|
for i := 0; i < val.Len(); i++ {
|
|
v := val.Index(i)
|
|
if v.CanInterface() {
|
|
models = append(models, v.Interface())
|
|
}
|
|
}
|
|
} else {
|
|
models = append(models, md)
|
|
}
|
|
}
|
|
|
|
_, v1, exist := getExistPk(o.mi, o.ind)
|
|
if exist == false {
|
|
panic(ErrMissPK)
|
|
}
|
|
|
|
names := []string{mfi.column, rfi.column}
|
|
|
|
values := make([]interface{}, 0, len(models)*2)
|
|
|
|
for _, md := range models {
|
|
|
|
ind := reflect.Indirect(reflect.ValueOf(md))
|
|
|
|
var v2 interface{}
|
|
if ind.Kind() != reflect.Struct {
|
|
v2 = ind.Interface()
|
|
} else {
|
|
_, v2, exist = getExistPk(fi.relModelInfo, ind)
|
|
if exist == false {
|
|
panic(ErrMissPK)
|
|
}
|
|
}
|
|
|
|
values = append(values, v1, v2)
|
|
|
|
}
|
|
|
|
return dbase.InsertValue(orm.db, mi, true, names, values)
|
|
}
|
|
|
|
// remove models following the origin model relationship
|
|
func (o *queryM2M) Remove(mds ...interface{}) (int64, error) {
|
|
fi := o.fi
|
|
qs := o.qs.Filter(fi.reverseFieldInfo.name, o.md)
|
|
|
|
nums, err := qs.Filter(fi.reverseFieldInfoTwo.name+ExprSep+"in", mds).Delete()
|
|
if err != nil {
|
|
return nums, err
|
|
}
|
|
return nums, nil
|
|
}
|
|
|
|
// check model is existed in relationship of origin model
|
|
func (o *queryM2M) Exist(md interface{}) bool {
|
|
fi := o.fi
|
|
return o.qs.Filter(fi.reverseFieldInfo.name, o.md).
|
|
Filter(fi.reverseFieldInfoTwo.name, md).Exist()
|
|
}
|
|
|
|
// clean all models in related of origin model
|
|
func (o *queryM2M) Clear() (int64, error) {
|
|
fi := o.fi
|
|
return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Delete()
|
|
}
|
|
|
|
// count all related models of origin model
|
|
func (o *queryM2M) Count() (int64, error) {
|
|
fi := o.fi
|
|
return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Count()
|
|
}
|
|
|
|
var _ QueryM2Mer = new(queryM2M)
|
|
|
|
// create new M2M queryer.
|
|
func newQueryM2M(md interface{}, o *orm, mi *modelInfo, fi *fieldInfo, ind reflect.Value) QueryM2Mer {
|
|
qm2m := new(queryM2M)
|
|
qm2m.md = md
|
|
qm2m.mi = mi
|
|
qm2m.fi = fi
|
|
qm2m.ind = ind
|
|
qm2m.qs = newQuerySet(o, fi.relThroughModelInfo).(*querySet)
|
|
return qm2m
|
|
}
|