-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathqapi.go
145 lines (133 loc) · 4.01 KB
/
qapi.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package qorm
import (
"reflect"
"github.com/pkg/errors"
"gorm.io/gorm"
)
// TenantModel is model with the tenant scope
func (qdb *DB) TenantModel(value interface{}) *DB {
qtx := qdb.getInstance()
qtx.DB = qtx.DB.Model(value)
return qtx
}
func (qdb *DB) QOrder(param interface{}) *DB {
if qdb.Err() != nil {
return qdb
}
qtx := qdb.initDB(param)
qtx.TagMeta.Orders = append(qtx.TagMeta.Orders, qtx.paramTagMeta.Orders...)
for _, order := range qtx.TagMeta.Orders {
if relation := getRelation(order.Name); relation != "" {
qtx.QJoins(relation)
}
columnName := qtx.getColumnName(order.Name)
qtx.Order(columnName + " " + order.Flag)
}
return qtx
}
func (qdb *DB) QWhere(param interface{}) *DB {
if qdb.Err() != nil {
return qdb
}
qtx := qdb.initDB(param)
qtx.TagMeta.Wheres = append(qtx.TagMeta.Wheres, qtx.paramTagMeta.Wheres...)
for _, where := range qtx.paramTagMeta.Wheres {
if relation := getRelation(where.Name); relation != "" {
qtx.QJoins(relation)
}
}
return qtx
}
func (qdb *DB) QSelect(param interface{}) *DB {
if qdb.Err() != nil {
return qdb
}
qtx := qdb.initDB(param)
qtx.TagMeta.Selects = append(qtx.TagMeta.Selects, qtx.paramTagMeta.Selects...)
for _, preload := range qtx.TagMeta.Preloads {
isPreloaded := false
for key, _ := range qtx.DB.Statement.Preloads {
if key == preload {
isPreloaded = true
}
}
if !isPreloaded {
qtx.Preload(preload)
}
}
var selects []string
for _, item := range qtx.TagMeta.Selects {
if relation := getRelation(item.Name); relation != "" {
qtx.QJoins(relation)
}
selects = append(selects, qtx.getColumnName(item.Name)+" as "+QuoteTo(qtx.DB, item.Flag))
}
return qtx.Select(selects)
}
// QAssociation 处理关联模型
func (qdb *DB) QAssociation(param interface{}) *DB {
if qdb.Err() != nil {
return qdb
}
qtx := qdb.initDB(param)
printFileWithLineNum(qtx)
qtx.Associations = append(qtx.Associations, qtx.paramTagMeta.Associations...)
if len(qtx.Associations) > 0 {
modelType := reflect.TypeOf(qtx.Statement.Model).Elem()
for _, association := range qtx.Associations {
m := qtx.Statement.Model
// 空数组直接清空关系
if len(association.Value.([]uint)) == 0 {
err := qtx.Session(&gorm.Session{NewDB: true}).Model(m).Association(association.Name).Clear()
if err != nil {
qtx.QErr = errors.Wrap(err, "清空关系失败")
}
continue
} else {
relationField, ok := modelType.FieldByName(association.Name)
if !ok {
qtx.QErr = errors.Errorf("%s 中没有 %s 关联字段", modelType, association.Name)
continue
}
relationModel := reflect.New(relationField.Type).Interface()
if err := qtx.Session(&gorm.Session{NewDB: true, SkipHooks: true, Initialized: true}).DB.Model(relationModel).Find(relationModel, association.Value).Error; err != nil {
qtx.QErr = errors.Wrap(err, "找不到对应id的值")
continue
}
err := qtx.Session(&gorm.Session{FullSaveAssociations: true, NewDB: true, SkipHooks: true, Initialized: true}).Model(m).Association(association.Name).Replace(relationModel)
if err != nil {
qtx.QErr = errors.Wrap(err, "更新关系失败")
}
}
}
}
return qtx
}
// QJoins not only support one to one and many to one, but also support one to many and many to many
//
// db.Joins("Account").Find(&user)
// db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "[email protected]").Find(&user)
func (qdb *DB) QJoins(query string, args ...interface{}) *DB {
qtx := qdb.getInstance()
qtx.TagMeta.Joins = append(qtx.TagMeta.Joins, joinMeta{
Query: query,
Args: args,
})
return qtx
}
// QTable 可以通过传入一个函数的方式动态修改表名
func (qdb *DB) QTable(f func(*gorm.DB) (string, error)) *DB {
qtx := qdb.getInstance()
if tableName, err := f(qtx.DB); err != nil {
qtx.QErr = err
} else {
qtx.Table(tableName)
}
return qtx
}
// QScope 可以通过传入一个函数的方式动态添加语句
func (qdb *DB) QScope(f func(*DB) *DB) *DB {
qtx := qdb.getInstance()
qtx = f(qtx)
return qtx
}