github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/util_test.go (about) 1 // Copyright 2021 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package frontend 16 17 import ( 18 "context" 19 "encoding/binary" 20 "fmt" 21 "math" 22 "sort" 23 "strings" 24 "testing" 25 "time" 26 27 "github.com/matrixorigin/matrixone/pkg/txn/clock" 28 29 "github.com/matrixorigin/matrixone/pkg/defines" 30 "github.com/matrixorigin/matrixone/pkg/vm/engine/memoryengine" 31 32 "github.com/stretchr/testify/assert" 33 34 "github.com/matrixorigin/matrixone/pkg/common/moerr" 35 "github.com/matrixorigin/matrixone/pkg/pb/txn" 36 "github.com/matrixorigin/matrixone/pkg/util/toml" 37 "github.com/matrixorigin/matrixone/pkg/vm/engine" 38 39 "github.com/golang/mock/gomock" 40 cvey "github.com/smartystreets/goconvey/convey" 41 42 "github.com/matrixorigin/matrixone/pkg/common/mpool" 43 "github.com/matrixorigin/matrixone/pkg/config" 44 "github.com/matrixorigin/matrixone/pkg/container/types" 45 "github.com/matrixorigin/matrixone/pkg/container/vector" 46 mock_frontend "github.com/matrixorigin/matrixone/pkg/frontend/test" 47 "github.com/matrixorigin/matrixone/pkg/sql/parsers" 48 "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" 49 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 50 "github.com/matrixorigin/matrixone/pkg/sql/plan" 51 "github.com/matrixorigin/matrixone/pkg/sql/util" 52 "github.com/matrixorigin/matrixone/pkg/testutil" 53 "github.com/matrixorigin/matrixone/pkg/vm/process" 54 55 "github.com/stretchr/testify/require" 56 ) 57 58 func init() { 59 testutil.SetupAutoIncrService() 60 } 61 62 func Test_PathExists(t *testing.T) { 63 cases := [...]struct { 64 path string 65 exist bool 66 isfile bool 67 noerr bool 68 }{ 69 {"test/file", true, true, true}, 70 {"test/file-no", false, false, false}, 71 //{"test/dir",true,false,true}, 72 {"test/dir-no", false, false, false}, 73 {"testx", false, false, false}, 74 } 75 76 for _, c := range cases { 77 exist, isfile, err := PathExists(c.path) 78 require.True(t, (err == nil) == c.noerr) 79 require.True(t, exist == c.exist) 80 require.True(t, isfile == c.isfile) 81 } 82 } 83 84 func Test_MinMax(t *testing.T) { 85 cvey.Convey("min", t, func() { 86 cvey.So(Min(10, 9), cvey.ShouldEqual, 9) 87 cvey.So(Min(9, 10), cvey.ShouldEqual, 9) 88 }) 89 90 cvey.Convey("max", t, func() { 91 cvey.So(Max(10, 9), cvey.ShouldEqual, 10) 92 cvey.So(Max(9, 10), cvey.ShouldEqual, 10) 93 }) 94 } 95 96 func Test_routineid(t *testing.T) { 97 cvey.Convey("rtid", t, func() { 98 x := GetRoutineId() 99 cvey.So(x, cvey.ShouldBeGreaterThanOrEqualTo, 0) 100 }) 101 } 102 103 func Test_timeout(t *testing.T) { 104 cvey.Convey("timeout", t, func() { 105 to := NewTimeout(5*time.Second, true) 106 to.UpdateTime(time.Now()) 107 cvey.So(to.isTimeout(), cvey.ShouldBeFalse) 108 }) 109 } 110 111 func Test_substringFromBegin(t *testing.T) { 112 cvey.Convey("ssfb", t, func() { 113 cvey.So(SubStringFromBegin("abcdef", 3), cvey.ShouldEqual, "abc...") 114 }) 115 } 116 117 func TestWildcardMatch(t *testing.T) { 118 //sort by string 119 120 patterns := []string{ 121 "%", 122 "%%%%%%%%a%%%%%%%%b%%%%%%%%b%%%%%%%%", 123 "%%%%%%%%a%%%%%%%%b%%%%%%%%c%%%%%%%%", 124 "%%%a%b%c%%%", 125 "%.%", 126 "%.zi%", 127 "%.zi_", 128 "%.zip", 129 "%12%12%", 130 "%12%23", 131 "%Abac%", 132 "%SIP%", 133 "%_", 134 "%_%_%", 135 "%_%_%.zip", 136 "%_%_.zip", 137 "%_.zip", 138 "%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%", 139 "%a%b%ba%ca%a%aa%aaa%fa%ga%b%", 140 "%a%b%ba%ca%a%x%aaa%fa%ga%b%", 141 "%a%b%ba%ca%aaaa%fa%ga%ggg%b%", 142 "%a%b%ba%ca%aaaa%fa%ga%gggg%b%", 143 "%aa%", 144 "%aa_", 145 "%aabbaa%a%", 146 "%ab%cd%", 147 "%abac%", 148 "%ccd", 149 "%issip%PI", 150 "%issip%ss%", 151 "%oWn%", 152 "%sip%", 153 "%zi%", 154 "%zi_", 155 "%zip", 156 "._", 157 "XY%Z%XYz", 158 "_", 159 "_%", 160 "_%%_%&_", 161 "_%%_%_", 162 "_%%_c_", 163 "_%%_d_", 164 "_%._%", 165 "_%_", 166 "_%_.zip", 167 "_%b%_%d%_", 168 "_.", 169 "_._", 170 "_.zip", 171 "_LaH", 172 "_Lah", 173 "__", 174 "_a", 175 "_a%__", 176 "_a_", 177 "_aa%", 178 "_b%__", 179 "a%", 180 "a%_%_", 181 "a%_%_%.zip", 182 "a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%", 183 "a%a%a%a%a%a%aa%aaa%a%a%b", 184 "a%aar", 185 "a%b", 186 "a%zz%", 187 "a12b", 188 "a_", 189 "ab%_%xy", 190 "ab%cd%xy", 191 "abc", 192 "abc%abc%abc%abc%abc", 193 "abc%abc%abc%abc%abc%abc%abc%abc%abc%abc%abc%abc%", 194 "abc%abc%abc%abc%abc%abc%abc%abc%abc%abc%abc%abc%abc%abc%abc%abc%abc%", 195 "abc%abc%abc%abc%abc%abc%abc%abc%abc%abc%abcd", 196 "bL_h", 197 "bLaH", 198 "bLa_", 199 "bLah", 200 "mi%Sip%", 201 "mi%sip%", 202 "xxx%zzy%f", 203 "xxxx%zzy%f", 204 "xxxx%zzy%fffff", 205 "xy%xyz", 206 "xy%z%xyz", 207 } 208 209 targets := []string{ 210 "%", 211 "%%%%%%%%a%%%%%%%%b%%%%%%%%c%%%%%%%%", 212 "%abc%", 213 ".a", 214 ".a.", 215 ".a.a", 216 ".a.aa", 217 ".a.b", 218 ".a.bcd", 219 ".aa.", 220 ".ab", 221 ".ab.ab.ab.cd.cd.", 222 ".ab.cd.ab.cd.abcd.", 223 ".axb.cxd.ab.cd.abcd.", 224 ".axb.cxd.ab.cd.abcd.xy", 225 ".axb.cyd.ab.cyd.axbcd.", 226 ".zip", 227 "A12b12", 228 "XYXYXYZYXYz", 229 "a", 230 "a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%", 231 "a%abab", 232 "a%ar", 233 "a%r", 234 "a.", 235 "a.a", 236 "a.a.zip", 237 "a.a.zippo", 238 "a.ab.ab.ab.cd.cd.xy", 239 "a.b", 240 "a.bcd", 241 "a.zip", 242 "a12B12", 243 "a12b12", 244 "aAazz", 245 "aa", 246 "aa.", 247 "aa.a", 248 "aa.ba.ba", 249 "aaa", 250 "aaaa.zip", 251 "aaaaaaaaaaaaaaaa", 252 "aaaaaaaaaaaaaaaaa", 253 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", 254 "aaabbaabbaab", 255 "aaazz", 256 "aannn", 257 "ab", 258 "ab.", 259 "ab.ab.cd.ab.cd.abcdxy.", 260 "ab.axb.cd.xyab.cyd.axbcd.", 261 "ab.axb.cd.xyab.cyd.axbcd.xy", 262 "ab.xy", 263 "abAbac", 264 "abababababababababababababababababababaacacacacacacacadaeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab", 265 "ababac", 266 "abanabnabncd", 267 "abanabnabncdef", 268 "abancda.bnxyabncdefxy", 269 "abancdabnxyabncdef", 270 "abancdabnxyabncdefxy", 271 "abc", 272 "abc%abcd%abcd%abc%abcd", 273 "abc%abcd%abcd%abc%abcd%abcd%abc%abcd%abc%abc%abcd", 274 "abc%abcd%abcde%abcdef%abcdefg%abcdefgh%abcdefghi%abcdefghij%abcdefghijk%abcdefghijkl%abcdefghijklm%abcdefghijklmn", 275 "abcccd", 276 "abcd", 277 "abcde", 278 "abcdx_y", 279 "abxy", 280 "ax", 281 "bLaH", 282 "bLaaa", 283 "bLah", 284 "baa.", 285 "caa.ba.ba", 286 "miSsissippi", 287 "missisSIPpi", 288 "mississipPI", 289 "mississipissippi", 290 "mississippi", 291 "oWn", 292 "xa", 293 "xaab", 294 "xab", 295 "xab_anabnabncd_xy", 296 "xxa", 297 "xxab", 298 "xxxx%zzzzzzzzy%f", 299 "xxxxzzzzzzzzyf", 300 "xyxyxyxyz", 301 "xyxyxyzyxyz", 302 "xyz.bcd", 303 "zip"} 304 305 want := map[int][]int{ 306 0: {0, 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}, 307 1: {11, 12, 13, 14, 15, 21, 28, 38, 44, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 62, 63, 64, 75, 85}, 308 2: {1, 2, 8, 11, 12, 13, 14, 15, 28, 30, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 85}, 309 3: {1, 2, 8, 11, 12, 13, 14, 15, 28, 30, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 85}, 310 4: {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 24, 25, 26, 27, 28, 29, 30, 31, 36, 37, 38, 40, 48, 49, 50, 51, 52, 58, 74, 75, 92}, 311 5: {16, 26, 27, 31, 40}, 312 6: {16, 26, 31, 40}, 313 7: {16, 26, 31, 40}, 314 8: {17, 32, 33}, 315 9: {}, 316 10: {53}, 317 11: {77}, 318 12: {0, 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}, 319 13: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 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}, 320 14: {26, 40}, 321 15: {26, 40}, 322 16: {26, 31, 40}, 323 17: {20, 42, 43, 54}, 324 18: {54}, 325 19: {}, 326 20: {54}, 327 21: {}, 328 22: {6, 9, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 54, 72, 74, 75, 83}, 329 23: {9, 36, 39, 41, 42, 43, 44, 54, 72, 74, 83}, 330 24: {44}, 331 25: {11, 12, 13, 14, 15, 28, 49, 50, 51, 56, 57, 58, 59, 60, 62, 63, 64, 65, 66, 67, 68, 85}, 332 26: {55}, 333 27: {65}, 334 28: {78}, 335 29: {79}, 336 30: {81}, 337 31: {76, 78, 79, 80}, 338 32: {16, 26, 27, 31, 40, 93}, 339 33: {16, 26, 31, 40, 93}, 340 34: {16, 26, 31, 40, 93}, 341 35: {3}, 342 36: {18}, 343 37: {0, 19}, 344 38: {0, 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}, 345 39: {}, 346 40: {1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93}, 347 41: {2, 8, 30, 56, 62, 63, 65, 66, 92}, 348 42: {11, 12, 13, 15, 50, 67}, 349 43: {5, 6, 7, 8, 11, 12, 13, 14, 15, 25, 26, 27, 28, 29, 30, 31, 37, 38, 40, 49, 50, 51, 52, 58, 75, 92}, 350 44: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 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}, 351 45: {26, 40}, 352 46: {11, 12, 13, 14, 15, 28, 49, 50, 51, 54, 57, 58, 59, 60, 62, 63, 64, 67, 68, 85}, 353 47: {24}, 354 48: {25, 29}, 355 49: {31}, 356 50: {71}, 357 51: {73}, 358 52: {3, 24, 35, 47, 70, 82}, 359 53: {3, 35, 82}, 360 54: {2, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 37, 38, 40, 41, 42, 43, 44, 45, 46, 74, 75, 83, 85}, 361 55: {4, 10, 36, 39, 84}, 362 56: {9, 39, 40, 41, 42, 43, 44, 45, 74, 75, 83}, 363 57: {49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 62, 63, 64, 65, 66, 67, 68, 69}, 364 58: {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}, 365 59: {20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69}, 366 60: {26, 40}, 367 61: {20, 42, 43, 54}, 368 62: {43, 54}, 369 63: {}, 370 64: {21, 29, 43, 44, 47, 54}, 371 65: {34, 45}, 372 66: {}, 373 67: {24, 35, 47, 70}, 374 68: {51, 52, 58, 60}, 375 69: {51, 58, 60}, 376 70: {61}, 377 71: {}, 378 72: {64}, 379 73: {}, 380 74: {63}, 381 75: {73}, 382 76: {71}, 383 77: {71, 73}, 384 78: {73}, 385 79: {}, 386 80: {76, 78, 79, 80}, 387 81: {88, 89}, 388 82: {88, 89}, 389 83: {}, 390 84: {90, 91}, 391 85: {91}, 392 } 393 394 cvey.Convey("", t, func() { 395 for i := 0; i < len(patterns); i++ { 396 for j := 0; j < len(targets); j++ { 397 398 //fmt.Println(pat[i], str[j]) 399 ret := WildcardMatch(patterns[i], targets[j]) 400 resArr := want[i] 401 idx := sort.SearchInts(resArr, j) 402 if idx >= len(resArr) || resArr[idx] != j { 403 cvey.So(ret, cvey.ShouldBeFalse) 404 } else { 405 cvey.So(ret, cvey.ShouldBeTrue) 406 } 407 } 408 } 409 }) 410 } 411 412 func TestGetSimpleExprValue(t *testing.T) { 413 ctx := context.TODO() 414 cvey.Convey("", t, func() { 415 type args struct { 416 sql string 417 wantErr bool 418 want interface{} 419 } 420 421 kases := []args{ 422 {"set @@x=1", false, 1}, 423 {"set @@x=-1", false, -1}, 424 {fmt.Sprintf("set @@x=%d", math.MaxInt64), false, math.MaxInt64}, 425 {fmt.Sprintf("set @@x=%d", -math.MaxInt64), false, -math.MaxInt64}, 426 {"set @@x=true", false, true}, 427 {"set @@x=false", false, false}, 428 {"set @@x=on", false, "on"}, 429 {"set @@x=off", false, "off"}, 430 {"set @@x=abc", false, "abc"}, 431 {"set @@x=null", false, nil}, 432 {"set @@x=-null", false, nil}, 433 {"set @@x=-x", true, nil}, 434 } 435 ctrl := gomock.NewController(t) 436 ses := newTestSession(t, ctrl) 437 //ses := NewSession(&FakeProtocol{}, testutil.NewProc().Mp(), config.NewParameterUnit(nil, mock_frontend.NewMockEngine(ctrl), mock_frontend.NewMockTxnClient(ctrl), nil), GSysVariables, false, nil, nil) 438 ec := newTestExecCtx(ctx, ctrl) 439 ec.proc = testutil.NewProc() 440 ec.ses = ses 441 ses.txnCompileCtx.execCtx = ec 442 for _, kase := range kases { 443 stmt, err := parsers.ParseOne(ctx, dialect.MYSQL, kase.sql, 1, 0) 444 cvey.So(err, cvey.ShouldBeNil) 445 446 sv, ok := stmt.(*tree.SetVar) 447 cvey.So(ok, cvey.ShouldBeTrue) 448 value, err := GetSimpleExprValue(ctx, sv.Assignments[0].Value, ses) 449 if kase.wantErr { 450 cvey.So(err, cvey.ShouldNotBeNil) 451 } else { 452 cvey.So(err, cvey.ShouldBeNil) 453 cvey.So(value, cvey.ShouldEqual, kase.want) 454 } 455 } 456 457 }) 458 459 cvey.Convey("", t, func() { 460 type args struct { 461 sql string 462 wantErr bool 463 want interface{} 464 } 465 466 dec1, _, _ := types.Parse64("1.0") 467 dec2, _, _ := types.Parse64("-1.0") 468 dec3, _, _ := types.Parse64("-1.2345670") 469 470 kases := []args{ 471 {"set @@x=1.0", false, fmt.Sprintf("%v", dec1.Format(1))}, 472 {"set @@x=-1.0", false, fmt.Sprintf("%v", dec2.Format(1))}, 473 {"set @@x=-1.2345670", false, fmt.Sprintf("%v", dec3.Format(7))}, 474 } 475 ctrl := gomock.NewController(t) 476 ses := newTestSession(t, ctrl) 477 //ses := NewSession(&FakeProtocol{}, testutil.NewProc().Mp(), config.NewParameterUnit(nil, mock_frontend.NewMockEngine(ctrl), mock_frontend.NewMockTxnClient(ctrl), nil), GSysVariables, false, nil, nil) 478 ec := newTestExecCtx(ctx, ctrl) 479 ec.proc = testutil.NewProc() 480 ec.ses = ses 481 ses.txnCompileCtx.execCtx = ec 482 for _, kase := range kases { 483 stmt, err := parsers.ParseOne(ctx, dialect.MYSQL, kase.sql, 1, 0) 484 cvey.So(err, cvey.ShouldBeNil) 485 486 sv, ok := stmt.(*tree.SetVar) 487 cvey.So(ok, cvey.ShouldBeTrue) 488 value, err := GetSimpleExprValue(ctx, sv.Assignments[0].Value, ses) 489 if kase.wantErr { 490 cvey.So(err, cvey.ShouldNotBeNil) 491 } else { 492 cvey.So(err, cvey.ShouldBeNil) 493 cvey.So(value, cvey.ShouldResemble, kase.want) 494 } 495 } 496 497 }) 498 } 499 500 func TestGetExprValue(t *testing.T) { 501 ctx := defines.AttachAccountId(context.TODO(), sysAccountID) 502 cvey.Convey("", t, func() { 503 type args struct { 504 sql string 505 wantErr bool 506 want interface{} 507 } 508 509 // dec1280, _, err := types.Parse128("-9223372036854775808") 510 // assert.NoError(t, err) 511 512 // dec1281, _, err := types.Parse128("99999999999999999999999999999999999999") 513 // assert.NoError(t, err) 514 515 // dec1282, _, err := types.Parse128("-99999999999999999999999999999999999999") 516 // assert.NoError(t, err) 517 518 // dec1283, _, err := types.Parse128("9223372036854775807") 519 // assert.NoError(t, err) 520 521 kases := []args{ 522 {"set @@x=1", false, 1}, 523 {"set @@x=-1", false, -1}, 524 {fmt.Sprintf("set @@x=%d", math.MaxInt64), false, math.MaxInt64}, 525 {fmt.Sprintf("set @@x=%d", -math.MaxInt64), false, -math.MaxInt64}, 526 {"set @@x=true", false, true}, 527 {"set @@x=false", false, false}, 528 {"set @@x=on", false, "on"}, 529 {"set @@x=off", false, "off"}, 530 {"set @@x=abc", false, "abc"}, 531 {"set @@x=null", false, nil}, 532 {"set @@x=-null", false, nil}, 533 {"set @@x=-x", true, nil}, 534 {"set @@x=(select -t.b from t)", true, nil}, 535 {"set @@x=(select 1)", false, 1}, 536 {"set @@x=(select -1)", false, -1}, 537 {fmt.Sprintf("set @@x=(select %d)", math.MaxInt64), false, math.MaxInt64}, 538 {fmt.Sprintf("set @@x=(select %d)", -math.MaxInt64), false, -math.MaxInt64}, 539 {"set @@x=(select true)", false, true}, 540 {"set @@x=(select false)", false, false}, 541 {"set @@x=(select 'on')", false, "on"}, 542 {"set @@x=(select 'off')", false, "off"}, 543 {"set @@x=(select 'abc')", false, "abc"}, 544 {"set @@x=(select null)", false, nil}, 545 {"set @@x=(select -null)", false, nil}, 546 {"set @@x=(select true != false)", false, true}, 547 {"set @@x=(select true = false)", false, false}, 548 {"set @@x=(" + 549 "select true = (" + 550 " select 1 = (select 0 + (" + 551 " select (select 1 + (select 2 - 0))" + 552 " )" + 553 " )" + 554 " )" + 555 ")", false, false}, 556 {"set @@x=(" + 557 " (select (3 < 4))" + 558 " = " + 559 " (select (1 > 4))" + 560 " )", false, false}, 561 {"set @@x=(select 127)", false, 127}, 562 {"set @@x=(select -128)", false, -128}, 563 {"set @@x=(select -2147483648)", false, -2147483648}, 564 {"set @@x=(select -9223372036854775808)", false, "-9223372036854775808"}, 565 {"set @@x=(select 18446744073709551615)", false, uint64(math.MaxUint64)}, 566 {"set @@x=(select 1.1754943508222875e-38)", false, float32(1.1754943508222875e-38)}, 567 {"set @@x=(select 3.4028234663852886e+38)", false, float32(3.4028234663852886e+38)}, 568 {"set @@x=(select 2.2250738585072014e-308)", false, float64(2.2250738585072014e-308)}, 569 {"set @@x=(select 1.7976931348623157e+308)", false, float64(1.7976931348623157e+308)}, 570 {"set @@x=(select cast(9223372036854775807 as decimal))", false, "9223372036854775807"}, 571 {"set @@x=(select cast(99999999999999999999999999999999999999 as decimal))", false, "99999999999999999999999999999999999999"}, 572 {"set @@x=(select cast(-99999999999999999999999999999999999999 as decimal))", false, "-99999999999999999999999999999999999999"}, 573 {"set @@x=(select cast('{\"a\":1,\"b\":2}' as json))", false, "{\"a\": 1, \"b\": 2}"}, 574 {"set @@x=(select cast('00000000-0000-0000-0000-000000000000' as uuid))", false, "00000000-0000-0000-0000-000000000000"}, 575 {"set @@x=(select cast('00:00:00' as time))", false, "00:00:00"}, 576 {"set @@x=(select cast('1000-01-01 00:00:00' as datetime))", false, "1000-01-01 00:00:00"}, 577 {"set @@x=(select cast('1970-01-01 00:00:00' as timestamp))", false, "1970-01-01 00:00:00"}, 578 {"set @@x=(select 1 into outfile './test.csv')", false, 1}, //!!!NOTE: there is no file './test.csv'. 579 {"set @@x=(((select true = false)))", false, false}, 580 } 581 ctrl := gomock.NewController(t) 582 defer ctrl.Finish() 583 584 eng := mock_frontend.NewMockEngine(ctrl) 585 eng.EXPECT().New(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 586 db := mock_frontend.NewMockDatabase(ctrl) 587 db.EXPECT().Relations(ctx).Return([]string{"t"}, nil).AnyTimes() 588 db.EXPECT().IsSubscription(gomock.Any()).Return(false).AnyTimes() 589 590 table := mock_frontend.NewMockRelation(ctrl) 591 table.EXPECT().GetTableID(gomock.Any()).Return(uint64(0xABC)).AnyTimes() 592 db.EXPECT().Relation(gomock.Any(), "t", nil).Return(table, moerr.NewInternalErrorNoCtx("no such table")).AnyTimes() 593 defs := []engine.TableDef{ 594 &engine.AttributeDef{Attr: engine.Attribute{Name: "a", Type: types.T_char.ToType()}}, 595 &engine.AttributeDef{Attr: engine.Attribute{Name: "b", Type: types.T_int32.ToType()}}, 596 } 597 598 table.EXPECT().TableDefs(gomock.Any()).Return(defs, nil).AnyTimes() 599 table.EXPECT().GetEngineType().Return(engine.Disttae).AnyTimes() 600 601 var ranges memoryengine.ShardIdSlice 602 id := make([]byte, 8) 603 binary.LittleEndian.PutUint64(id, 1) 604 ranges.Append(id) 605 606 table.EXPECT().Ranges(gomock.Any(), gomock.Any()).Return(&ranges, nil).AnyTimes() 607 table.EXPECT().NewReader(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, moerr.NewInvalidInputNoCtx("new reader failed")).AnyTimes() 608 609 eng.EXPECT().Database(gomock.Any(), gomock.Any(), gomock.Any()).Return(db, nil).AnyTimes() 610 eng.EXPECT().Hints().Return(engine.Hints{ 611 CommitOrRollbackTimeout: time.Second, 612 }).AnyTimes() 613 eng.EXPECT().Nodes(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil).AnyTimes() 614 615 ws := mock_frontend.NewMockWorkspace(ctrl) 616 ws.EXPECT().IncrStatementID(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 617 ws.EXPECT().IncrSQLCount().AnyTimes() 618 ws.EXPECT().GetSQLCount().AnyTimes() 619 ws.EXPECT().StartStatement().AnyTimes() 620 ws.EXPECT().EndStatement().AnyTimes() 621 ws.EXPECT().GetSnapshotWriteOffset().Return(0).AnyTimes() 622 ws.EXPECT().UpdateSnapshotWriteOffset().AnyTimes() 623 ws.EXPECT().Adjust(gomock.Any()).AnyTimes() 624 ws.EXPECT().CloneSnapshotWS().AnyTimes() 625 ws.EXPECT().BindTxnOp(gomock.Any()).AnyTimes() 626 627 txnOperator := mock_frontend.NewMockTxnOperator(ctrl) 628 txnOperator.EXPECT().Commit(gomock.Any()).Return(nil).AnyTimes() 629 txnOperator.EXPECT().Rollback(gomock.Any()).Return(nil).AnyTimes() 630 txnOperator.EXPECT().GetWorkspace().Return(ws).AnyTimes() 631 txnOperator.EXPECT().Txn().Return(txn.TxnMeta{}).AnyTimes() 632 txnOperator.EXPECT().ResetRetry(gomock.Any()).AnyTimes() 633 txnOperator.EXPECT().TxnOptions().Return(txn.TxnOptions{}).AnyTimes() 634 txnOperator.EXPECT().NextSequence().Return(uint64(0)).AnyTimes() 635 txnOperator.EXPECT().EnterRunSql().Return().AnyTimes() 636 txnOperator.EXPECT().ExitRunSql().Return().AnyTimes() 637 txnOperator.EXPECT().GetWaitActiveCost().Return(time.Duration(0)).AnyTimes() 638 txnClient := mock_frontend.NewMockTxnClient(ctrl) 639 txnClient.EXPECT().New(gomock.Any(), gomock.Any(), gomock.Any()).Return(txnOperator, nil).AnyTimes() 640 641 sv := &config.FrontendParameters{ 642 SessionTimeout: toml.Duration{Duration: 10 * time.Second}, 643 } 644 645 pu := config.NewParameterUnit(sv, eng, txnClient, nil) 646 setGlobalPu(pu) 647 ses := NewSession(ctx, &FakeProtocol{}, testutil.NewProc().Mp(), GSysVariables, true, nil) 648 ses.SetDatabaseName("db") 649 var c clock.Clock 650 err := ses.GetTxnHandler().CreateTempStorage(c) 651 assert.Nil(t, err) 652 ec := newTestExecCtx(ctx, ctrl) 653 ec.proc = testutil.NewProc() 654 ec.ses = ses 655 ses.txnCompileCtx.execCtx = ec 656 for _, kase := range kases { 657 fmt.Println("++++>", kase.sql) 658 stmt, err := parsers.ParseOne(ctx, dialect.MYSQL, kase.sql, 1, 0) 659 cvey.So(err, cvey.ShouldBeNil) 660 661 sv, ok := stmt.(*tree.SetVar) 662 cvey.So(ok, cvey.ShouldBeTrue) 663 value, err := getExprValue(sv.Assignments[0].Value, ses, ec) 664 if kase.wantErr { 665 cvey.So(err, cvey.ShouldNotBeNil) 666 } else { 667 cvey.So(err, cvey.ShouldBeNil) 668 switch ret := value.(type) { 669 case *plan.Expr: 670 if types.T(ret.GetTyp().Id) == types.T_decimal64 { 671 cvey.So(ret.GetLit().GetDecimal64Val().GetA(), cvey.ShouldEqual, kase.want) 672 } else if types.T(ret.GetTyp().Id) == types.T_decimal128 { 673 temp := kase.want.(types.Decimal128) 674 cvey.So(uint64(ret.GetLit().GetDecimal128Val().GetA()), cvey.ShouldEqual, temp.B0_63) 675 cvey.So(uint64(ret.GetLit().GetDecimal128Val().GetB()), cvey.ShouldEqual, temp.B64_127) 676 } else { 677 panic(fmt.Sprintf("unknown expr type %v", ret.GetTyp())) 678 } 679 default: 680 cvey.So(value, cvey.ShouldEqual, kase.want) 681 } 682 } 683 } 684 685 }) 686 687 cvey.Convey("", t, func() { 688 type args struct { 689 sql string 690 wantErr bool 691 want interface{} 692 } 693 694 // dec1, _, _ := types.Parse64("1.0") 695 // dec2, _, _ := types.Parse64("-1.0") 696 // dec3, _, _ := types.Parse64("-1.2345670") 697 698 kases := []args{ 699 {"set @@x=1.0", false, "1.0"}, 700 {"set @@x=-1.0", false, "-1.0"}, 701 {"set @@x=-1.2345670", false, "-1.2345670"}, 702 } 703 ctrl := gomock.NewController(t) 704 defer ctrl.Finish() 705 706 eng := mock_frontend.NewMockEngine(ctrl) 707 eng.EXPECT().New(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 708 db := mock_frontend.NewMockDatabase(ctrl) 709 db.EXPECT().Relations(ctx).Return([]string{"t"}, nil).AnyTimes() 710 711 table := mock_frontend.NewMockRelation(ctrl) 712 db.EXPECT().Relation(ctx, "t", nil).Return(table, nil).AnyTimes() 713 defs := []engine.TableDef{ 714 &engine.AttributeDef{Attr: engine.Attribute{Name: "a", Type: types.T_char.ToType()}}, 715 &engine.AttributeDef{Attr: engine.Attribute{Name: "b", Type: types.T_int32.ToType()}}, 716 } 717 718 table.EXPECT().TableDefs(ctx).Return(defs, nil).AnyTimes() 719 eng.EXPECT().Database(ctx, gomock.Any(), nil).Return(db, nil).AnyTimes() 720 eng.EXPECT().Hints().Return(engine.Hints{ 721 CommitOrRollbackTimeout: time.Second, 722 }).AnyTimes() 723 eng.EXPECT().Nodes(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil).AnyTimes() 724 725 ws := mock_frontend.NewMockWorkspace(ctrl) 726 ws.EXPECT().IncrStatementID(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 727 ws.EXPECT().StartStatement().AnyTimes() 728 ws.EXPECT().EndStatement().AnyTimes() 729 ws.EXPECT().GetSnapshotWriteOffset().Return(0).AnyTimes() 730 ws.EXPECT().UpdateSnapshotWriteOffset().AnyTimes() 731 ws.EXPECT().Adjust(uint64(0)).AnyTimes() 732 ws.EXPECT().IncrSQLCount().AnyTimes() 733 ws.EXPECT().GetSQLCount().AnyTimes() 734 ws.EXPECT().CloneSnapshotWS().AnyTimes() 735 ws.EXPECT().BindTxnOp(gomock.Any()).AnyTimes() 736 737 txnOperator := mock_frontend.NewMockTxnOperator(ctrl) 738 txnOperator.EXPECT().Commit(gomock.Any()).Return(nil).AnyTimes() 739 txnOperator.EXPECT().Rollback(gomock.Any()).Return(nil).AnyTimes() 740 txnOperator.EXPECT().GetWorkspace().Return(ws).AnyTimes() 741 txnOperator.EXPECT().Txn().Return(txn.TxnMeta{}).AnyTimes() 742 txnOperator.EXPECT().ResetRetry(gomock.Any()).AnyTimes() 743 txnOperator.EXPECT().TxnOptions().Return(txn.TxnOptions{}).AnyTimes() 744 txnOperator.EXPECT().NextSequence().Return(uint64(0)).AnyTimes() 745 txnOperator.EXPECT().EnterRunSql().Return().AnyTimes() 746 txnOperator.EXPECT().ExitRunSql().Return().AnyTimes() 747 txnOperator.EXPECT().GetWaitActiveCost().Return(time.Duration(0)).AnyTimes() 748 txnClient := mock_frontend.NewMockTxnClient(ctrl) 749 txnClient.EXPECT().New(gomock.Any(), gomock.Any(), gomock.Any()).Return(txnOperator, nil).AnyTimes() 750 751 sv := &config.FrontendParameters{ 752 SessionTimeout: toml.Duration{Duration: 5 * time.Minute}, 753 } 754 755 pu := config.NewParameterUnit(sv, eng, txnClient, nil) 756 setGlobalPu(pu) 757 ses := NewSession(ctx, &FakeProtocol{}, testutil.NewProc().Mp(), GSysVariables, true, nil) 758 var c clock.Clock 759 err := ses.GetTxnHandler().CreateTempStorage(c) 760 assert.Nil(t, err) 761 ec := newTestExecCtx(ctx, ctrl) 762 ec.reqCtx = ctx 763 ses.txnCompileCtx.execCtx = ec 764 for _, kase := range kases { 765 stmt, err := parsers.ParseOne(ctx, dialect.MYSQL, kase.sql, 1, 0) 766 cvey.So(err, cvey.ShouldBeNil) 767 768 sv, ok := stmt.(*tree.SetVar) 769 cvey.So(ok, cvey.ShouldBeTrue) 770 value, err := getExprValue(sv.Assignments[0].Value, ses, ec) 771 if kase.wantErr { 772 cvey.So(err, cvey.ShouldNotBeNil) 773 } else { 774 cvey.So(err, cvey.ShouldBeNil) 775 cvey.So(value, cvey.ShouldResemble, kase.want) 776 } 777 } 778 779 }) 780 } 781 782 var _ error = &testError{} 783 784 type testError struct { 785 s string 786 } 787 788 func (t testError) Error() string { 789 return t.s 790 } 791 792 func TestRewriteError(t *testing.T) { 793 type args struct { 794 err error 795 username string 796 } 797 798 tests := []struct { 799 name string 800 args args 801 want uint16 802 want1 string 803 want2 string 804 }{ 805 { 806 name: "t1", 807 args: args{ 808 err: &testError{s: "non moerr"}, 809 }, 810 want: moerr.ER_INTERNAL_ERROR, 811 want1: "HY000", 812 want2: "non moerr", 813 }, 814 { 815 name: "t2", 816 args: args{}, 817 want: moerr.ER_INTERNAL_ERROR, 818 want1: "", 819 want2: "", 820 }, 821 { 822 name: "t3", 823 args: args{ 824 err: moerr.NewInternalErrorNoCtx("check password failed"), 825 username: "abc", 826 }, 827 want: moerr.ER_ACCESS_DENIED_ERROR, 828 want1: "28000", 829 want2: "Access denied for user abc. internal error: check password failed", 830 }, 831 { 832 name: "t4", 833 args: args{ 834 err: moerr.NewInternalErrorNoCtx("suspended"), 835 username: "abc", 836 }, 837 want: moerr.ER_ACCESS_DENIED_ERROR, 838 want1: "28000", 839 want2: "Access denied for user abc. internal error: suspended", 840 }, 841 { 842 name: "t5", 843 args: args{ 844 err: moerr.NewInternalErrorNoCtx("suspended"), 845 username: "abc", 846 }, 847 want: moerr.ER_ACCESS_DENIED_ERROR, 848 want1: "28000", 849 want2: "Access denied for user abc. internal error: suspended", 850 }, 851 { 852 name: "t6", 853 args: args{ 854 err: moerr.NewInternalErrorNoCtx("source address is not authorized"), 855 username: "abc", 856 }, 857 want: moerr.ER_ACCESS_DENIED_ERROR, 858 want1: "28000", 859 want2: "Access denied for user abc. internal error: source address is not authorized", 860 }, 861 { 862 name: "t7", 863 args: args{ 864 err: moerr.NewInternalErrorNoCtx("xxxx"), 865 username: "abc", 866 }, 867 want: moerr.ErrInternal, 868 want1: "HY000", 869 want2: "internal error: xxxx", 870 }, 871 { 872 name: "t8", 873 args: args{ 874 err: moerr.NewBadDBNoCtx("yyy"), 875 username: "abc", 876 }, 877 want: moerr.ER_BAD_DB_ERROR, 878 want1: "HY000", 879 want2: "invalid database yyy", 880 }, 881 } 882 for _, tt := range tests { 883 t.Run(tt.name, func(t *testing.T) { 884 got, got1, got2 := RewriteError(tt.args.err, tt.args.username) 885 assert.Equalf(t, tt.want, got, "RewriteError(%v, %v)", tt.args.err, tt.args.username) 886 assert.Equalf(t, tt.want1, got1, "RewriteError(%v, %v)", tt.args.err, tt.args.username) 887 assert.Equalf(t, tt.want2, got2, "RewriteError(%v, %v)", tt.args.err, tt.args.username) 888 }) 889 } 890 } 891 892 func Test_makeExecuteSql(t *testing.T) { 893 type args struct { 894 ses *Session 895 stmt tree.Statement 896 } 897 898 ctrl := gomock.NewController(t) 899 defer ctrl.Finish() 900 901 eng := mock_frontend.NewMockEngine(ctrl) 902 eng.EXPECT().New(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 903 904 txnClient := mock_frontend.NewMockTxnClient(ctrl) 905 906 sv := &config.FrontendParameters{ 907 SessionTimeout: toml.Duration{Duration: 5 * time.Minute}, 908 } 909 ctx := context.TODO() 910 pu := config.NewParameterUnit(sv, eng, txnClient, nil) 911 setGlobalPu(pu) 912 ses1 := NewSession(ctx, &FakeProtocol{}, testutil.NewProc().Mp(), GSysVariables, true, 913 nil) 914 915 ses1.SetUserDefinedVar("var2", "val2", "set var2 = val2") 916 ses1.SetUserDefinedVar("var3", "val3", "set var3 = val3") 917 ses1.SetPrepareStmt(ctx, "st2", &PrepareStmt{ 918 Name: "st2", 919 Sql: "prepare st2 select * from t where a = ?", 920 }) 921 ses1.SetPrepareStmt(ctx, "st3", &PrepareStmt{ 922 Name: "st3", 923 Sql: "prepare st3 select * from t where a = ? and b = ?", 924 }) 925 926 mp, err := mpool.NewMPool("ut_pool", 0, mpool.NoFixed) 927 if err != nil { 928 assert.NoError(t, err) 929 } 930 defer mpool.DeleteMPool(mp) 931 932 testProc := process.New(context.Background(), mp, nil, nil, nil, nil, nil, nil, nil, nil) 933 934 params1 := testProc.GetVector(types.T_text.ToType()) 935 for i := 0; i < 3; i++ { 936 err = vector.AppendBytes(params1, []byte{}, false, testProc.GetMPool()) 937 assert.NoError(t, err) 938 } 939 940 util.SetAnyToStringVector(testProc, "aVal", params1, 0) 941 util.SetAnyToStringVector(testProc, "NULL", params1, 1) 942 util.SetAnyToStringVector(testProc, "bVal", params1, 2) 943 944 ses1.SetPrepareStmt(ctx, "st4", &PrepareStmt{ 945 Name: "st4", 946 Sql: "prepare st4 select * from t where a = ? and b = ?", 947 params: params1, 948 }) 949 950 ses1.SetPrepareStmt(ctx, "st5", nil) 951 952 tests := []struct { 953 name string 954 args args 955 want string 956 }{ 957 { 958 name: "t1", 959 args: args{}, 960 want: "", 961 }, 962 { 963 name: "t2", 964 args: args{ 965 ses: &Session{}, 966 stmt: &tree.SetVar{}, 967 }, 968 want: "", 969 }, 970 { 971 name: "t3", 972 args: args{ 973 ses: ses1, 974 stmt: &tree.Execute{ 975 Name: "st1", 976 }, 977 }, 978 want: "", 979 }, 980 { 981 name: "t4-no variables - no params", 982 args: args{ 983 ses: ses1, 984 stmt: &tree.Execute{ 985 Name: "st2", 986 }, 987 }, 988 want: "prepare st2 select * from t where a = ? ;", 989 }, 990 { 991 name: "t5 - variables", 992 args: args{ 993 ses: ses1, 994 stmt: &tree.Execute{ 995 Name: "st3", 996 Variables: []*tree.VarExpr{ 997 { 998 Name: "var2", 999 }, 1000 { 1001 Name: "var-none", 1002 }, 1003 { 1004 Name: "var3", 1005 }, 1006 }, 1007 }, 1008 }, 1009 want: "prepare st3 select * from t where a = ? and b = ? ; set var2 = val2 ; ; set var3 = val3", 1010 }, 1011 { 1012 name: "t6 - params", 1013 args: args{ 1014 ses: ses1, 1015 stmt: &tree.Execute{ 1016 Name: "st4", 1017 }, 1018 }, 1019 want: "prepare st4 select * from t where a = ? and b = ? ; aVal ; NULL ; bVal", 1020 }, 1021 { 1022 name: "t7 - params is nil", 1023 args: args{ 1024 ses: ses1, 1025 stmt: &tree.Execute{ 1026 Name: "st5", 1027 }, 1028 }, 1029 want: "", 1030 }, 1031 } 1032 for _, tt := range tests { 1033 t.Run(tt.name, func(t *testing.T) { 1034 if got := makeExecuteSql(ctx, tt.args.ses, tt.args.stmt); strings.TrimSpace(got) != strings.TrimSpace(tt.want) { 1035 t.Errorf("makeExecuteSql() = %v, want %v", got, tt.want) 1036 } 1037 }) 1038 } 1039 } 1040 1041 func Test_getVariableValue(t *testing.T) { 1042 type args struct { 1043 varDefault interface{} 1044 } 1045 tests := []struct { 1046 name string 1047 args args 1048 want string 1049 }{ 1050 {name: "0.1", args: args{varDefault: 0.1}, want: "0.100000"}, 1051 {name: "0.000001", args: args{varDefault: 0.000001}, want: "0.000001"}, 1052 {name: "0.0000009", args: args{varDefault: 0.0000009}, want: "9.000000e-07"}, 1053 {name: "7.43e-14", args: args{varDefault: 7.43e-14}, want: "7.430000e-14"}, 1054 } 1055 for _, tt := range tests { 1056 t.Run(tt.name, func(t *testing.T) { 1057 got := getVariableValue(tt.args.varDefault) 1058 assert.Equalf(t, tt.want, got, "getVariableValue(%v)", tt.args.varDefault) 1059 }) 1060 } 1061 } 1062 1063 var _ error = &testErr{} 1064 1065 type testErr struct { 1066 } 1067 1068 func (t testErr) Error() string { 1069 return "test" 1070 } 1071 1072 func Test_isErrorRollbackWholeTxn(t *testing.T) { 1073 assert.Equal(t, false, isErrorRollbackWholeTxn(nil)) 1074 assert.Equal(t, false, isErrorRollbackWholeTxn(&testError{})) 1075 assert.Equal(t, true, isErrorRollbackWholeTxn(moerr.NewDeadLockDetectedNoCtx())) 1076 assert.Equal(t, true, isErrorRollbackWholeTxn(moerr.NewLockTableBindChangedNoCtx())) 1077 assert.Equal(t, true, isErrorRollbackWholeTxn(moerr.NewLockTableNotFoundNoCtx())) 1078 assert.Equal(t, true, isErrorRollbackWholeTxn(moerr.NewDeadlockCheckBusyNoCtx())) 1079 assert.Equal(t, true, isErrorRollbackWholeTxn(moerr.NewLockConflictNoCtx())) 1080 } 1081 1082 func TestUserInput_getSqlSourceType(t *testing.T) { 1083 type fields struct { 1084 sql string 1085 stmt tree.Statement 1086 sqlSourceType []string 1087 } 1088 type args struct { 1089 i int 1090 } 1091 tests := []struct { 1092 name string 1093 fields fields 1094 args args 1095 want string 1096 }{ 1097 { 1098 name: "t1", 1099 fields: fields{ 1100 sql: "select * from t1", 1101 sqlSourceType: nil, 1102 }, 1103 args: args{ 1104 i: 0, 1105 }, 1106 want: "external_sql", 1107 }, 1108 { 1109 name: "t2", 1110 fields: fields{ 1111 sql: "select * from t1", 1112 sqlSourceType: nil, 1113 }, 1114 args: args{ 1115 i: 1, 1116 }, 1117 want: "external_sql", 1118 }, 1119 { 1120 name: "t3", 1121 fields: fields{ 1122 sql: "select * from t1", 1123 sqlSourceType: []string{ 1124 "a", 1125 "b", 1126 "c", 1127 }, 1128 }, 1129 args: args{ 1130 i: 2, 1131 }, 1132 want: "c", 1133 }, 1134 } 1135 for _, tt := range tests { 1136 t.Run(tt.name, func(t *testing.T) { 1137 ui := &UserInput{ 1138 sql: tt.fields.sql, 1139 stmt: tt.fields.stmt, 1140 sqlSourceType: tt.fields.sqlSourceType, 1141 } 1142 assert.Equalf(t, tt.want, ui.getSqlSourceType(tt.args.i), "getSqlSourceType(%v)", tt.args.i) 1143 }) 1144 } 1145 } 1146 1147 func TestTopsort(t *testing.T) { 1148 cvey.Convey("create graph", t, func() { 1149 g := topsort{next: make(map[string][]string)} 1150 g.addVertex("0") 1151 g.addVertex("1") 1152 g.addVertex("2") 1153 g.addVertex("3") 1154 g.addVertex("4") 1155 g.addVertex("5") 1156 g.addEdge("0", "2") 1157 g.addEdge("1", "2") 1158 g.addEdge("2", "3") 1159 g.addEdge("3", "4") 1160 g.addEdge("3", "5") 1161 1162 ans, ok := g.sort() 1163 cvey.So(ok, cvey.ShouldBeTrue) 1164 1165 sort.StringSlice(ans[:2]).Sort() 1166 cvey.So(ans[:2], cvey.ShouldResemble, []string{"0", "1"}) 1167 cvey.So(ans[2], cvey.ShouldResemble, "2") 1168 cvey.So(ans[3], cvey.ShouldResemble, "3") 1169 sort.StringSlice(ans[4:]).Sort() 1170 cvey.So(ans[4:], cvey.ShouldResemble, []string{"4", "5"}) 1171 }) 1172 1173 cvey.Convey("create graph", t, func() { 1174 g := topsort{next: make(map[string][]string)} 1175 g.addVertex("0") 1176 g.addVertex("1") 1177 g.addVertex("2") 1178 1179 // can be in any order 1180 _, ok := g.sort() 1181 cvey.So(ok, cvey.ShouldBeTrue) 1182 }) 1183 1184 cvey.Convey("create graph", t, func() { 1185 g := topsort{next: make(map[string][]string)} 1186 g.addVertex("0") 1187 g.addVertex("1") 1188 g.addVertex("2") 1189 g.addEdge("0", "1") 1190 g.addEdge("1", "2") 1191 g.addEdge("2", "0") 1192 1193 // has a cycle 1194 _, ok := g.sort() 1195 cvey.So(ok, cvey.ShouldBeFalse) 1196 }) 1197 }