forked from go-gorm/gorm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcallback_query.go
141 lines (122 loc) · 3.57 KB
/
callback_query.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
package gorm
import (
"errors"
"fmt"
"reflect"
"crypto/md5"
"encoding/json"
"strings"
"regexp"
)
// Define callbacks for querying
func init() {
DefaultCallback.Query().Register("gorm:query", queryCallback)
DefaultCallback.Query().Register("gorm:preload", preloadCallback)
DefaultCallback.Query().Register("gorm:after_query", afterQueryCallback)
}
type SubObject struct {
isCache bool
Id string
}
// queryCallback used to query data from database
func queryCallback(scope *Scope) {
defer scope.trace(NowFunc())
var (
isSlice, isPtr bool
resultType reflect.Type
results = scope.IndirectValue()
)
if orderBy, ok := scope.Get("gorm:order_by_primary_key"); ok {
if primaryField := scope.PrimaryField(); primaryField != nil {
scope.Search.Order(fmt.Sprintf("%v.%v %v", scope.QuotedTableName(), scope.Quote(primaryField.DBName), orderBy))
}
}
if value, ok := scope.Get("gorm:query_destination"); ok {
results = indirect(reflect.ValueOf(value))
}
if kind := results.Kind(); kind == reflect.Slice {
isSlice = true
resultType = results.Type().Elem()
results.Set(reflect.MakeSlice(results.Type(), 0, 0))
if resultType.Kind() == reflect.Ptr {
isPtr = true
resultType = resultType.Elem()
}
} else if kind != reflect.Struct {
scope.Err(errors.New("unsupported destination, should be slice or struct"))
return
}
scope.prepareQuerySQL()
if !scope.HasError() {
scope.db.RowsAffected = 0
if str, ok := scope.Get("gorm:query_option"); ok {
scope.SQL += addExtraSpaceIfExist(fmt.Sprint(str))
}
var sqlvarsstr string
if(scope.TableName()==""){
sqlvarsstr = fmt.Sprint(*scope.db.QueryExpr())
}else{
vars := fmt.Sprint(scope.SQLVars)
sqlvarsstr = scope.SQL+vars
}
fmt.Println(sqlvarsstr)
iscache :=strings.Contains(scope.SQL,"true=true")
haskey := md5.Sum([]byte(sqlvarsstr))
haskeystr := fmt.Sprintf("%x", haskey) //将[]byte转成16进制
fmt.Println("query:",haskeystr)
//iscache存在且其值为真,则调用redis缓存逻辑
var firstTableName string
if (iscache) {
//get tables name
reg := regexp.MustCompile("(?i)\\s+(from|join)\\s+`*(\\w+)`*\\s+")
tableNames := reg.FindAllStringSubmatch(scope.SQL,-1)
if len(tableNames)>0 {
firstTableName = tableNames[0][2]
//is value exist? /
if (Rds.HExists(firstTableName, haskeystr).Val()) {
//get values from redis
redisValue, _ := Rds.HGet(firstTableName, haskeystr).Bytes()
fmt.Println(redisValue,haskeystr)
json.Unmarshal(redisValue, scope.Value)
return
}
}
}
if rows, err := scope.SQLDB().Query(scope.SQL, scope.SQLVars...); scope.Err(err) == nil {
defer rows.Close()
fmt.Println("queryend")
columns, _ := rows.Columns()
for rows.Next() {
scope.db.RowsAffected++
elem := results
if isSlice {
elem = reflect.New(resultType).Elem()
}
scope.scan(rows, columns, scope.New(elem.Addr().Interface()).Fields())
if isSlice {
if isPtr {
results.Set(reflect.Append(results, elem.Addr()))
} else {
results.Set(reflect.Append(results, elem))
}
}
}
if (iscache && len(firstTableName)>0 && scope.Value!=nil) {
//set redis value
jsonValue, _ := json.Marshal(scope.Value)
Rds.HSet(firstTableName, haskeystr, jsonValue)
if err := rows.Err(); err != nil {
scope.Err(err)
} else if scope.db.RowsAffected == 0 && !isSlice {
scope.Err(ErrRecordNotFound)
}
}
}
}
}
// afterQueryCallback will invoke `AfterFind` method after querying
func afterQueryCallback(scope *Scope) {
if !scope.HasError() {
scope.CallMethod("AfterFind")
}
}