@@ -136,62 +136,66 @@ func (c *Conv) WithChildren(children ...sql.Expression) (sql.Expression, error)
136
136
// This conversion truncates nVal as its first subpart that is convertable.
137
137
// nVal is treated as unsigned except nVal is negative.
138
138
func convertFromBase (ctx * sql.Context , nVal string , fromBase interface {}) interface {} {
139
- fromBase , _ , err := types .Int64 .Convert (ctx , fromBase )
140
- if err != nil {
139
+ if len (nVal ) == 0 {
141
140
return nil
142
141
}
143
142
144
- fromVal := int (math .Abs (float64 (fromBase .(int64 ))))
143
+ // Convert and validate fromBase
144
+ baseVal , _ , err := types .Int64 .Convert (ctx , fromBase )
145
+ if err != nil {
146
+ return nil
147
+ }
148
+ fromVal := int (math .Abs (float64 (baseVal .(int64 ))))
145
149
if fromVal < 2 || fromVal > 36 {
146
150
return nil
147
151
}
148
152
153
+ // Handle sign
149
154
negative := false
150
- var upper string
151
- var lower string
152
- if nVal [0 ] == '-' {
155
+ switch {
156
+ case nVal [0 ] == '-' :
157
+ if len (nVal ) == 1 {
158
+ return uint64 (0 )
159
+ }
153
160
negative = true
154
161
nVal = nVal [1 :]
155
- } else if nVal [0 ] == '+' {
162
+ case nVal [0 ] == '+' :
163
+ if len (nVal ) == 1 {
164
+ return uint64 (0 )
165
+ }
156
166
nVal = nVal [1 :]
157
167
}
158
168
159
- // check for upper and lower bound for given fromBase
169
+ // Determine bounds based on sign
170
+ var maxLen int
160
171
if negative {
161
- upper = strconv .FormatInt (math .MaxInt64 , fromVal )
162
- lower = strconv .FormatInt (math .MinInt64 , fromVal )
163
- if len (nVal ) > len (lower ) {
164
- nVal = lower
165
- } else if len (nVal ) > len (upper ) {
166
- nVal = upper
172
+ maxLen = len (strconv .FormatInt (math .MinInt64 , fromVal ))
173
+ if len (nVal ) > maxLen {
174
+ // Use MinInt64 representation in the given base
175
+ nVal = strconv .FormatInt (math .MinInt64 , fromVal )[1 :] // remove minus sign
167
176
}
168
177
} else {
169
- upper = strconv .FormatUint (math .MaxUint64 , fromVal )
170
- lower = "0"
171
- if len (nVal ) < len (lower ) {
172
- nVal = lower
173
- } else if len (nVal ) > len (upper ) {
174
- nVal = upper
178
+ maxLen = len (strconv .FormatUint (math .MaxUint64 , fromVal ))
179
+ if len (nVal ) > maxLen {
180
+ // Use MaxUint64 representation in the given base
181
+ nVal = strconv .FormatUint (math .MaxUint64 , fromVal )
175
182
}
176
183
}
177
184
178
- truncate := false
179
- result := uint64 (0 )
180
- i := 1
181
- for ! truncate && i <= len (nVal ) {
185
+ // Find the longest valid prefix that can be converted
186
+ var result uint64
187
+ for i := 1 ; i <= len (nVal ); i ++ {
182
188
val , err := strconv .ParseUint (nVal [:i ], fromVal , 64 )
183
189
if err != nil {
184
- truncate = true
185
- return result
190
+ break
186
191
}
187
192
result = val
188
- i ++
189
193
}
190
194
191
195
if negative {
196
+ // MySQL returns signed value for negative inputs
192
197
return int64 (result ) * - 1
193
198
}
194
-
195
199
return result
196
200
}
197
201
0 commit comments