@@ -10,27 +10,17 @@ import (
10
10
11
11
const tagName = "gormlike"
12
12
13
- //nolint:gocognit,cyclop // Acceptable
14
- func (d * gormLike ) queryCallback (db * gorm.DB ) {
15
- // If we only want to like queries that are explicitly set to true, we back out early if anything's amiss
16
- settingValue , settingOk := db .Get (tagName )
17
- if d .conditionalSetting && ! settingOk {
18
- return
19
- }
20
-
21
- if settingOk {
22
- if boolValue , _ := settingValue .(bool ); ! boolValue {
23
- return
24
- }
25
- }
26
-
27
- exp , settingOk := db .Statement .Clauses ["WHERE" ].Expression .(clause.Where )
28
- if ! settingOk {
29
- return
30
- }
31
-
32
- for index , cond := range exp .Exprs {
13
+ func (d * gormLike ) replaceExpressions (db * gorm.DB , expressions []clause.Expression ) []clause.Expression {
14
+ for index , cond := range expressions {
33
15
switch cond := cond .(type ) {
16
+ case clause.AndConditions :
17
+ // Recursively go through the expressions of AndConditions
18
+ cond .Exprs = d .replaceExpressions (db , cond .Exprs )
19
+ expressions [index ] = cond
20
+ case clause.OrConditions :
21
+ // Recursively go through the expressions of OrConditions
22
+ cond .Exprs = d .replaceExpressions (db , cond .Exprs )
23
+ expressions [index ] = cond
34
24
case clause.Eq :
35
25
columnName , columnOk := cond .Column .(string )
36
26
if ! columnOk {
@@ -64,13 +54,13 @@ func (d *gormLike) queryCallback(db *gorm.DB) {
64
54
continue
65
55
}
66
56
67
- condition := fmt .Sprintf ("%s LIKE ?" , cond .Column )
57
+ condition := fmt .Sprintf ("CAST(%s as varchar) LIKE ?" , cond .Column )
68
58
69
59
if d .replaceCharacter != "" {
70
60
value = strings .ReplaceAll (value , d .replaceCharacter , "%" )
71
61
}
72
62
73
- exp . Exprs [index ] = db .Session (& gorm.Session {NewDB : true }).Where (condition , value ).Statement .Clauses ["WHERE" ].Expression
63
+ expressions [index ] = db .Session (& gorm.Session {NewDB : true }).Where (condition , value ).Statement .Clauses ["WHERE" ].Expression
74
64
case clause.IN :
75
65
columnName , columnOk := cond .Column .(string )
76
66
if ! columnOk {
@@ -95,7 +85,6 @@ func (d *gormLike) queryCallback(db *gorm.DB) {
95
85
}
96
86
97
87
var likeCounter int
98
- var useOr bool
99
88
100
89
query := db .Session (& gorm.Session {NewDB : true })
101
90
@@ -109,7 +98,7 @@ func (d *gormLike) queryCallback(db *gorm.DB) {
109
98
110
99
// If there are no % AND there aren't ony replaceable characters, just skip it because it's a normal query
111
100
if strings .Contains (value , "%" ) || (d .replaceCharacter != "" && strings .Contains (value , d .replaceCharacter )) {
112
- condition = fmt .Sprintf ("%s LIKE ?" , cond .Column )
101
+ condition = fmt .Sprintf ("CAST(%s as varchar) LIKE ?" , cond .Column )
113
102
114
103
if d .replaceCharacter != "" {
115
104
value = strings .ReplaceAll (value , d .replaceCharacter , "%" )
@@ -118,22 +107,45 @@ func (d *gormLike) queryCallback(db *gorm.DB) {
118
107
likeCounter ++
119
108
}
120
109
121
- if useOr {
122
- query = query .Or (condition , value )
123
-
124
- continue
125
- }
126
-
127
- query = query .Where (condition , value )
128
- useOr = true
110
+ query = query .Or (condition , value )
129
111
}
130
112
131
113
// Don't alter the query if it isn't necessary
132
114
if likeCounter == 0 {
133
115
continue
134
116
}
135
117
136
- exp .Exprs [index ] = db .Session (& gorm.Session {NewDB : true }).Where (query ).Statement .Clauses ["WHERE" ].Expression
118
+ // This feels a bit like a dirty hack
119
+ // but otherwise the generated query would not be correct in case of an AND condition between multiple OR conditions
120
+ // e.g. without this -> x = .. OR x = .. AND y = .. OR y = .. (no brackets around the OR conditions mess up the query)
121
+ // e.g. with this -> (x = .. OR x = ..) AND (y = .. OR y = ..)
122
+ var newExpression clause.OrConditions
123
+ newExpression .Exprs = query .Statement .Clauses ["WHERE" ].Expression .(clause.Where ).Exprs
124
+
125
+ expressions [index ] = newExpression
126
+ }
127
+ }
128
+
129
+ return expressions
130
+ }
131
+
132
+ func (d * gormLike ) queryCallback (db * gorm.DB ) {
133
+ // If we only want to like queries that are explicitly set to true, we back out early if anything's amiss
134
+ settingValue , settingOk := db .Get (tagName )
135
+ if d .conditionalSetting && ! settingOk {
136
+ return
137
+ }
138
+
139
+ if settingOk {
140
+ if boolValue , _ := settingValue .(bool ); ! boolValue {
141
+ return
137
142
}
138
143
}
144
+
145
+ exp , settingOk := db .Statement .Clauses ["WHERE" ].Expression .(clause.Where )
146
+ if ! settingOk {
147
+ return
148
+ }
149
+
150
+ exp .Exprs = d .replaceExpressions (db , exp .Exprs )
139
151
}
0 commit comments