github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/sqle/expreval/literal_helpers_test.go (about) 1 // Copyright 2019-2020 Dolthub, Inc. 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 expreval 16 17 import ( 18 "testing" 19 "time" 20 21 "github.com/dolthub/go-mysql-server/sql" 22 "github.com/dolthub/go-mysql-server/sql/expression" 23 "github.com/stretchr/testify/assert" 24 25 "github.com/dolthub/dolt/go/store/types" 26 ) 27 28 func TestLiteralAsInt64(t *testing.T) { 29 tests := []struct { 30 name string 31 l *expression.Literal 32 expected int64 33 expectErr bool 34 }{ 35 { 36 "int8 literal", 37 expression.NewLiteral(int8(5), sql.Int8), 38 5, 39 false, 40 }, 41 { 42 "int16 literal", 43 expression.NewLiteral(int16(5), sql.Int16), 44 5, 45 false, 46 }, 47 { 48 "int32 literal", 49 expression.NewLiteral(int32(5), sql.Int32), 50 5, 51 false, 52 }, 53 { 54 "int literal", 55 expression.NewLiteral(int(5), sql.Int32), 56 5, 57 false, 58 }, 59 { 60 "int64 literal", 61 expression.NewLiteral(int64(5), sql.Int64), 62 5, 63 false, 64 }, 65 66 { 67 "uint8 literal", 68 expression.NewLiteral(uint8(5), sql.Uint8), 69 5, 70 false, 71 }, 72 { 73 "uint16 literal", 74 expression.NewLiteral(uint16(5), sql.Uint16), 75 5, 76 false, 77 }, 78 { 79 "uint32 literal", 80 expression.NewLiteral(uint32(5), sql.Uint32), 81 5, 82 false, 83 }, 84 { 85 "uint literal", 86 expression.NewLiteral(uint(5), sql.Uint32), 87 5, 88 false, 89 }, 90 { 91 "uint64 literal", 92 expression.NewLiteral(uint64(5), sql.Uint64), 93 5, 94 false, 95 }, 96 { 97 "true literal", 98 expression.NewLiteral(true, sql.Boolean), 99 1, 100 false, 101 }, 102 { 103 "false literal", 104 expression.NewLiteral(false, sql.Boolean), 105 0, 106 false, 107 }, 108 { 109 "float32 literal", 110 expression.NewLiteral(float32(32.0), sql.Float32), 111 32, 112 false, 113 }, 114 { 115 "float64 literal", 116 expression.NewLiteral(float64(32.0), sql.Float64), 117 32, 118 false, 119 }, 120 { 121 "string literal", 122 expression.NewLiteral("54321", sql.Text), 123 54321, 124 false, 125 }, 126 { 127 "uint literal too big", 128 expression.NewLiteral(uint64(0xFFFFFFFFFFFFFFFF), sql.Uint32), 129 0, 130 true, 131 }, 132 { 133 "float64 with fractional portion", 134 expression.NewLiteral(float64(5.0005), sql.Float64), 135 0, 136 true, 137 }, 138 { 139 "float32 with fractional portion", 140 expression.NewLiteral(float32(5.0005), sql.Float32), 141 0, 142 true, 143 }, 144 { 145 "string not a number", 146 expression.NewLiteral("not a number", sql.Text), 147 0, 148 true, 149 }, 150 } 151 152 for _, test := range tests { 153 t.Run(test.name, func(t *testing.T) { 154 res, err := literalAsInt64(test.l) 155 assertOnUnexpectedErr(t, test.expectErr, err) 156 157 if err == nil { 158 assert.Equal(t, test.expected, res) 159 } 160 }) 161 } 162 } 163 164 func TestLiteralAsUint64(t *testing.T) { 165 tests := []struct { 166 name string 167 l *expression.Literal 168 expected uint64 169 expectErr bool 170 }{ 171 { 172 "int8 literal", 173 expression.NewLiteral(int8(5), sql.Int8), 174 5, 175 false, 176 }, 177 { 178 "int16 literal", 179 expression.NewLiteral(int16(5), sql.Int16), 180 5, 181 false, 182 }, 183 { 184 "int32 literal", 185 expression.NewLiteral(int32(5), sql.Int32), 186 5, 187 false, 188 }, 189 { 190 "int literal", 191 expression.NewLiteral(int(5), sql.Int32), 192 5, 193 false, 194 }, 195 { 196 "int64 literal", 197 expression.NewLiteral(int64(5), sql.Int64), 198 5, 199 false, 200 }, 201 { 202 "uint8 literal", 203 expression.NewLiteral(uint8(5), sql.Uint8), 204 5, 205 false, 206 }, 207 { 208 "uint16 literal", 209 expression.NewLiteral(uint16(5), sql.Uint16), 210 5, 211 false, 212 }, 213 { 214 "uint32 literal", 215 expression.NewLiteral(uint32(5), sql.Uint32), 216 5, 217 false, 218 }, 219 { 220 "uint literal", 221 expression.NewLiteral(uint(5), sql.Uint32), 222 5, 223 false, 224 }, 225 { 226 "uint64 literal", 227 expression.NewLiteral(uint64(5), sql.Uint64), 228 5, 229 false, 230 }, 231 { 232 "true literal", 233 expression.NewLiteral(true, sql.Boolean), 234 1, 235 false, 236 }, 237 { 238 "false literal", 239 expression.NewLiteral(false, sql.Boolean), 240 0, 241 false, 242 }, 243 { 244 "float32 literal", 245 expression.NewLiteral(float32(32.0), sql.Float32), 246 32, 247 false, 248 }, 249 { 250 "float64 literal", 251 expression.NewLiteral(float64(32.0), sql.Float64), 252 32, 253 false, 254 }, 255 { 256 "string literal", 257 expression.NewLiteral("54321", sql.Text), 258 54321, 259 false, 260 }, 261 { 262 "negative int8 literal", 263 expression.NewLiteral(int8(-1), sql.Int8), 264 0, 265 true, 266 }, 267 { 268 "negative int16 literal", 269 expression.NewLiteral(int16(-1), sql.Int16), 270 0, 271 true, 272 }, 273 { 274 "negative int32 literal", 275 expression.NewLiteral(int32(-1), sql.Int32), 276 0, 277 true, 278 }, 279 { 280 "negative int literal", 281 expression.NewLiteral(int(-1), sql.Int32), 282 0, 283 true, 284 }, 285 { 286 "negative int64 literal", 287 expression.NewLiteral(int64(-1), sql.Int64), 288 0, 289 true, 290 }, 291 { 292 "float32 with fractional portion", 293 expression.NewLiteral(float32(5.0005), sql.Float32), 294 0, 295 true, 296 }, 297 { 298 "float64 with fractional portion", 299 expression.NewLiteral(float64(5.0005), sql.Float64), 300 0, 301 true, 302 }, 303 { 304 "string not a number", 305 expression.NewLiteral("not a number", sql.Text), 306 0, 307 true, 308 }, 309 } 310 311 for _, test := range tests { 312 t.Run(test.name, func(t *testing.T) { 313 res, err := literalAsUint64(test.l) 314 assertOnUnexpectedErr(t, test.expectErr, err) 315 316 if err == nil { 317 assert.Equal(t, test.expected, res) 318 } 319 }) 320 } 321 } 322 323 func TestLiteralAsFloat64(t *testing.T) { 324 tests := []struct { 325 name string 326 l *expression.Literal 327 expected float64 328 expectErr bool 329 }{ 330 { 331 "int8 literal", 332 expression.NewLiteral(int8(-5), sql.Int8), 333 -5.0, 334 false, 335 }, 336 { 337 "int16 literal", 338 expression.NewLiteral(int16(-5), sql.Int16), 339 -5.0, 340 false, 341 }, 342 { 343 "int32 literal", 344 expression.NewLiteral(int32(-5), sql.Int32), 345 -5.0, 346 false, 347 }, 348 { 349 "int literal", 350 expression.NewLiteral(int(-5), sql.Int32), 351 -5.0, 352 false, 353 }, 354 { 355 "int64 literal", 356 expression.NewLiteral(int64(-5), sql.Int64), 357 -5.0, 358 false, 359 }, 360 { 361 "uint8 literal", 362 expression.NewLiteral(uint8(5), sql.Uint8), 363 5.0, 364 false, 365 }, 366 { 367 "uint16 literal", 368 expression.NewLiteral(uint16(5), sql.Uint16), 369 5.0, 370 false, 371 }, 372 { 373 "uint32 literal", 374 expression.NewLiteral(uint32(5), sql.Uint32), 375 5.0, 376 false, 377 }, 378 { 379 "uint literal", 380 expression.NewLiteral(uint(5), sql.Uint32), 381 5.0, 382 false, 383 }, 384 { 385 "uint64 literal", 386 expression.NewLiteral(uint64(5), sql.Uint64), 387 5.0, 388 false, 389 }, 390 { 391 "bool literal", 392 expression.NewLiteral(true, sql.Boolean), 393 0.0, 394 true, 395 }, 396 { 397 "float32 literal", 398 expression.NewLiteral(float32(32.0), sql.Float32), 399 32.0, 400 false, 401 }, 402 { 403 "float64 literal", 404 expression.NewLiteral(float64(32.0), sql.Float64), 405 32.0, 406 false, 407 }, 408 { 409 "string literal", 410 expression.NewLiteral("-54.321", sql.Text), 411 -54.321, 412 false, 413 }, 414 { 415 "non numeric string", 416 expression.NewLiteral("test", sql.Text), 417 0, 418 true, 419 }, 420 } 421 422 for _, test := range tests { 423 t.Run(test.name, func(t *testing.T) { 424 res, err := literalAsFloat64(test.l) 425 assertOnUnexpectedErr(t, test.expectErr, err) 426 427 if err == nil { 428 assert.Equal(t, test.expected, res) 429 } 430 }) 431 } 432 } 433 434 func TestLiteralAsBool(t *testing.T) { 435 tests := []struct { 436 name string 437 l *expression.Literal 438 expected bool 439 expectErr bool 440 }{ 441 { 442 "int8 literal", 443 expression.NewLiteral(int8(0), sql.Int8), 444 false, 445 false, 446 }, 447 { 448 "int16 literal", 449 expression.NewLiteral(int16(1), sql.Int16), 450 true, 451 false, 452 }, 453 { 454 "int32 literal", 455 expression.NewLiteral(int32(0), sql.Int32), 456 false, 457 false, 458 }, 459 { 460 "int literal", 461 expression.NewLiteral(int(1), sql.Int32), 462 true, 463 false, 464 }, 465 { 466 "int64 literal", 467 expression.NewLiteral(int64(0), sql.Int64), 468 false, 469 false, 470 }, 471 472 { 473 "uint8 literal", 474 expression.NewLiteral(uint8(1), sql.Uint8), 475 true, 476 false, 477 }, 478 { 479 "uint16 literal", 480 expression.NewLiteral(uint16(0), sql.Uint16), 481 false, 482 false, 483 }, 484 { 485 "uint32 literal", 486 expression.NewLiteral(uint32(1), sql.Uint32), 487 true, 488 false, 489 }, 490 { 491 "uint literal", 492 expression.NewLiteral(uint(0), sql.Uint32), 493 false, 494 false, 495 }, 496 { 497 "uint64 literal", 498 expression.NewLiteral(uint64(1), sql.Uint64), 499 true, 500 false, 501 }, 502 { 503 "bool literal", 504 expression.NewLiteral(true, sql.Boolean), 505 true, 506 false, 507 }, 508 { 509 "float literal not supported", 510 expression.NewLiteral(float32(32.0), sql.Float32), 511 false, 512 true, 513 }, 514 { 515 "string literal false", 516 expression.NewLiteral("false", sql.Text), 517 false, 518 false, 519 }, 520 { 521 "string literal 1", 522 expression.NewLiteral("1", sql.Text), 523 true, 524 false, 525 }, 526 { 527 "non numeric non bool string", 528 expression.NewLiteral("test", sql.Text), 529 false, 530 true, 531 }, 532 } 533 534 for _, test := range tests { 535 t.Run(test.name, func(t *testing.T) { 536 res, err := literalAsBool(test.l) 537 assertOnUnexpectedErr(t, test.expectErr, err) 538 539 if err == nil { 540 assert.Equal(t, test.expected, res) 541 } 542 }) 543 } 544 } 545 546 func TestLiteralAsString(t *testing.T) { 547 tests := []struct { 548 name string 549 l *expression.Literal 550 expected string 551 expectErr bool 552 }{ 553 { 554 "int literal", 555 expression.NewLiteral(5, sql.Int16), 556 "5", 557 false, 558 }, 559 { 560 "uint literal", 561 expression.NewLiteral(uint32(5), sql.Uint32), 562 "5", 563 false, 564 }, 565 { 566 "bool literal", 567 expression.NewLiteral(true, sql.Boolean), 568 "true", 569 false, 570 }, 571 { 572 "float literal", 573 expression.NewLiteral(float32(-2.5), sql.Float32), 574 "-2.5", 575 false, 576 }, 577 { 578 "string literal", 579 expression.NewLiteral("test", sql.Text), 580 "test", 581 false, 582 }, 583 } 584 585 for _, test := range tests { 586 t.Run(test.name, func(t *testing.T) { 587 res, err := literalAsString(test.l) 588 assertOnUnexpectedErr(t, test.expectErr, err) 589 590 if err == nil { 591 assert.Equal(t, test.expected, res) 592 } 593 }) 594 } 595 } 596 597 func TestParseDate(t *testing.T) { 598 tests := []struct { 599 name string 600 str string 601 expected time.Time 602 expectErr bool 603 }{ 604 { 605 "YYYY-MM-DD", 606 "2006-01-02", 607 time.Date(2006, 1, 2, 0, 0, 0, 0, time.UTC), 608 false, 609 }, 610 { 611 "YYYY-MM-DD HH:MM:SS", 612 "2006-01-02 15:04:05", 613 time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC), 614 false, 615 }, 616 { 617 "Invalid format", 618 "not a date", 619 time.Time{}, 620 true, 621 }, 622 } 623 624 for _, test := range tests { 625 t.Run(test.name, func(t *testing.T) { 626 res, err := parseDate(test.str) 627 assertOnUnexpectedErr(t, test.expectErr, err) 628 629 if err == nil { 630 assert.Equal(t, test.expected, res) 631 } 632 }) 633 } 634 } 635 636 func TestLiteralAsTimestamp(t *testing.T) { 637 tests := []struct { 638 name string 639 l *expression.Literal 640 expected time.Time 641 expectErr bool 642 }{ 643 { 644 "YYYY-MM-DD", 645 expression.NewLiteral("2006-01-02", sql.Text), 646 time.Date(2006, 1, 2, 0, 0, 0, 0, time.UTC), 647 false, 648 }, 649 { 650 "YYYY-MM-DD HH:MM:SS", 651 expression.NewLiteral("2006-01-02 15:04:05", sql.Text), 652 time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC), 653 false, 654 }, 655 { 656 "Invalid format", 657 expression.NewLiteral("not a date", sql.Text), 658 time.Time{}, 659 true, 660 }, 661 { 662 "int literal", 663 expression.NewLiteral(5, sql.Int8), 664 time.Time{}, 665 true, 666 }, 667 } 668 669 for _, test := range tests { 670 t.Run(test.name, func(t *testing.T) { 671 res, err := literalAsTimestamp(test.l) 672 assertOnUnexpectedErr(t, test.expectErr, err) 673 674 if err == nil { 675 assert.Equal(t, test.expected, res) 676 } 677 }) 678 } 679 } 680 681 func TestLiteralToNomsValue(t *testing.T) { 682 tests := []struct { 683 name string 684 l *expression.Literal 685 expected types.Value 686 expectErr bool 687 }{ 688 {"int", expression.NewLiteral(-1, sql.Int32), types.Int(-1), false}, 689 {"int err", expression.NewLiteral(uint64(0xFFFFFFFFFFFFFFFF), sql.Uint64), types.Int(0), true}, 690 {"uint", expression.NewLiteral(1, sql.Uint32), types.Uint(1), false}, 691 {"uint err", expression.NewLiteral(-1, sql.Int16), types.Uint(1), true}, 692 {"float", expression.NewLiteral(1.5, sql.Float32), types.Float(1.5), false}, 693 {"float err", expression.NewLiteral("not a valid float", sql.Text), types.Float(1.5), true}, 694 {"bool", expression.NewLiteral(true, sql.Boolean), types.Bool(true), false}, 695 {"bool err", expression.NewLiteral("not a valid bool", sql.Text), types.Bool(true), true}, 696 {"string", expression.NewLiteral("this is a test", sql.Text), types.String("this is a test"), false}, 697 { 698 "date", 699 expression.NewLiteral("1900-01-01", sql.Text), 700 types.Timestamp(time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC)), 701 false, 702 }, 703 { 704 "date err", 705 expression.NewLiteral("not a valid date", sql.Text), 706 types.Timestamp(time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC)), 707 true, 708 }, 709 } 710 711 for _, test := range tests { 712 t.Run(test.name, func(t *testing.T) { 713 res, err := LiteralToNomsValue(test.expected.Kind(), test.l) 714 assertOnUnexpectedErr(t, test.expectErr, err) 715 716 if err == nil { 717 assert.Equal(t, test.expected, res) 718 } 719 }) 720 } 721 }