2014-08-18 08:41:43 +00:00
|
|
|
// Copyright 2014 beego Author. All Rights Reserved.
|
2014-07-03 15:40:21 +00:00
|
|
|
//
|
2014-08-18 08:41:43 +00:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
2014-07-03 15:40:21 +00:00
|
|
|
//
|
2014-08-18 08:41:43 +00:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2014-07-03 15:40:21 +00:00
|
|
|
//
|
2014-08-18 08:41:43 +00:00
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2013-10-14 14:31:35 +00:00
|
|
|
package orm
|
|
|
|
|
2016-01-14 15:49:28 +00:00
|
|
|
import "reflect"
|
2013-10-14 14:31:35 +00:00
|
|
|
|
2014-01-17 15:28:54 +00:00
|
|
|
// model to model struct
|
2013-10-14 14:31:35 +00:00
|
|
|
type queryM2M struct {
|
|
|
|
md interface{}
|
|
|
|
mi *modelInfo
|
|
|
|
fi *fieldInfo
|
|
|
|
qs *querySet
|
|
|
|
ind reflect.Value
|
|
|
|
}
|
|
|
|
|
2014-01-17 15:28:54 +00:00
|
|
|
// 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.
|
2013-10-14 14:31:35 +00:00
|
|
|
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{}
|
2016-01-17 16:18:21 +00:00
|
|
|
var otherValues []interface{}
|
|
|
|
var otherNames []string
|
2015-11-19 14:46:14 +00:00
|
|
|
|
|
|
|
for _, colname := range mi.fields.dbcols {
|
2016-01-14 15:49:28 +00:00
|
|
|
if colname != mfi.column && colname != rfi.column && colname != fi.mi.fields.pk.column &&
|
|
|
|
mi.fields.columns[colname] != mi.fields.pk {
|
2016-01-17 16:18:21 +00:00
|
|
|
otherNames = append(otherNames, colname)
|
2015-11-19 14:46:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for i, md := range mds {
|
|
|
|
if reflect.Indirect(reflect.ValueOf(md)).Kind() != reflect.Struct && i > 0 {
|
2016-01-17 16:18:21 +00:00
|
|
|
otherValues = append(otherValues, md)
|
2015-12-02 08:35:36 +00:00
|
|
|
mds = append(mds[:i], mds[i+1:]...)
|
2015-11-19 14:46:14 +00:00
|
|
|
}
|
2015-11-19 12:30:14 +00:00
|
|
|
}
|
2013-10-14 14:31:35 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2015-11-19 14:46:14 +00:00
|
|
|
names := []string{mfi.column, rfi.column}
|
2014-01-06 03:07:03 +00:00
|
|
|
|
2015-11-19 14:46:14 +00:00
|
|
|
values := make([]interface{}, 0, len(models)*2)
|
2013-10-14 14:31:35 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
2015-11-19 14:46:14 +00:00
|
|
|
values = append(values, v1, v2)
|
2013-10-14 14:31:35 +00:00
|
|
|
|
|
|
|
}
|
2016-01-17 16:18:21 +00:00
|
|
|
names = append(names, otherNames...)
|
|
|
|
values = append(values, otherValues...)
|
2014-01-06 03:07:03 +00:00
|
|
|
return dbase.InsertValue(orm.db, mi, true, names, values)
|
2013-10-14 14:31:35 +00:00
|
|
|
}
|
|
|
|
|
2014-01-17 15:28:54 +00:00
|
|
|
// remove models following the origin model relationship
|
2013-10-14 14:31:35 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2014-01-17 15:28:54 +00:00
|
|
|
// check model is existed in relationship of origin model
|
2013-10-14 14:31:35 +00:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2014-01-17 15:28:54 +00:00
|
|
|
// clean all models in related of origin model
|
2013-10-14 14:31:35 +00:00
|
|
|
func (o *queryM2M) Clear() (int64, error) {
|
|
|
|
fi := o.fi
|
|
|
|
return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Delete()
|
|
|
|
}
|
|
|
|
|
2014-01-17 15:28:54 +00:00
|
|
|
// count all related models of origin model
|
2013-10-14 14:31:35 +00:00
|
|
|
func (o *queryM2M) Count() (int64, error) {
|
|
|
|
fi := o.fi
|
|
|
|
return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Count()
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ QueryM2Mer = new(queryM2M)
|
|
|
|
|
2014-01-17 15:28:54 +00:00
|
|
|
// create new M2M queryer.
|
2013-10-14 14:31:35 +00:00
|
|
|
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
|
|
|
|
}
|