github.com/mithrandie/csvq@v1.18.1/lib/query/load_view_test.go (about) 1 package query 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "reflect" 9 "strings" 10 "testing" 11 "time" 12 13 "github.com/mithrandie/csvq/lib/option" 14 "github.com/mithrandie/csvq/lib/parser" 15 "github.com/mithrandie/csvq/lib/value" 16 17 "github.com/mithrandie/go-text" 18 "github.com/mithrandie/go-text/json" 19 ) 20 21 var loadViewTests = []struct { 22 Name string 23 TestCache bool 24 Encoding text.Encoding 25 NoHeader bool 26 From parser.FromClause 27 ForUpdate bool 28 UseInternalId bool 29 Stdin string 30 ImportFormat option.Format 31 Delimiter rune 32 AllowUnevenFields bool 33 DelimiterPositions []int 34 SingleLine bool 35 JsonQuery string 36 WithoutNull bool 37 Scope *ReferenceScope 38 Result *View 39 ResultScope *ReferenceScope 40 Error string 41 }{ 42 { 43 Name: "Dual View", 44 From: parser.FromClause{ 45 Tables: []parser.QueryExpression{ 46 parser.Table{Object: parser.Dual{}}, 47 }, 48 }, 49 Result: &View{ 50 Header: []HeaderField{{}}, 51 RecordSet: []Record{ 52 { 53 NewCell(value.NewNull()), 54 }, 55 }, 56 }, 57 }, 58 { 59 Name: "Dual View With Omitted FromClause", 60 From: parser.FromClause{}, 61 Result: &View{ 62 Header: []HeaderField{{}}, 63 RecordSet: []Record{ 64 { 65 NewCell(value.NewNull()), 66 }, 67 }, 68 }, 69 }, 70 { 71 Name: "LoadView File", 72 From: parser.FromClause{ 73 Tables: []parser.QueryExpression{ 74 parser.Table{ 75 Object: parser.Identifier{Literal: "table1.csv"}, 76 }, 77 }, 78 }, 79 Result: &View{ 80 Header: NewHeader("table1", []string{"column1", "column2"}), 81 RecordSet: []Record{ 82 NewRecord([]value.Primary{ 83 value.NewString("1"), 84 value.NewString("str1"), 85 }), 86 NewRecord([]value.Primary{ 87 value.NewString("2"), 88 value.NewString("str2"), 89 }), 90 NewRecord([]value.Primary{ 91 value.NewString("3"), 92 value.NewString("str3"), 93 }), 94 }, 95 FileInfo: &FileInfo{ 96 Path: "table1.csv", 97 Delimiter: ',', 98 Encoding: text.UTF8, 99 LineBreak: text.LF, 100 }, 101 }, 102 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 103 {scopeNameAliases: { 104 "TABLE1": strings.ToUpper(GetTestFilePath("table1.csv")), 105 }}, 106 }, time.Time{}, nil), 107 }, 108 { 109 Name: "LoadView File ForUpdate", 110 From: parser.FromClause{ 111 Tables: []parser.QueryExpression{ 112 parser.Table{ 113 Object: parser.Identifier{Literal: "table1.csv"}, 114 }, 115 }, 116 }, 117 ForUpdate: true, 118 Result: &View{ 119 Header: NewHeader("table1", []string{"column1", "column2"}), 120 RecordSet: []Record{ 121 NewRecord([]value.Primary{ 122 value.NewString("1"), 123 value.NewString("str1"), 124 }), 125 NewRecord([]value.Primary{ 126 value.NewString("2"), 127 value.NewString("str2"), 128 }), 129 NewRecord([]value.Primary{ 130 value.NewString("3"), 131 value.NewString("str3"), 132 }), 133 }, 134 FileInfo: &FileInfo{ 135 Path: "table1.csv", 136 Delimiter: ',', 137 Encoding: text.UTF8, 138 LineBreak: text.LF, 139 ForUpdate: true, 140 }, 141 }, 142 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{{ 143 scopeNameAliases: { 144 "TABLE1": strings.ToUpper(GetTestFilePath("table1.csv")), 145 }, 146 }}, time.Time{}, nil), 147 }, 148 { 149 Name: "LoadView from Cached View", 150 TestCache: true, 151 From: parser.FromClause{ 152 Tables: []parser.QueryExpression{ 153 parser.Table{ 154 Object: parser.Identifier{Literal: "table1"}, 155 }, 156 }, 157 }, 158 ForUpdate: true, 159 Result: &View{ 160 Header: NewHeader("table1", []string{"column1", "column2"}), 161 RecordSet: []Record{ 162 NewRecord([]value.Primary{ 163 value.NewString("1"), 164 value.NewString("str1"), 165 }), 166 NewRecord([]value.Primary{ 167 value.NewString("2"), 168 value.NewString("str2"), 169 }), 170 NewRecord([]value.Primary{ 171 value.NewString("3"), 172 value.NewString("str3"), 173 }), 174 }, 175 FileInfo: &FileInfo{ 176 Path: "table1.csv", 177 Delimiter: ',', 178 Encoding: text.UTF8, 179 LineBreak: text.LF, 180 ForUpdate: true, 181 }, 182 }, 183 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{{ 184 scopeNameAliases: { 185 "TABLE1": strings.ToUpper(GetTestFilePath("table1.csv")), 186 }, 187 }}, time.Time{}, nil), 188 }, 189 { 190 Name: "LoadView File with UTF-8 BOM", 191 From: parser.FromClause{ 192 Tables: []parser.QueryExpression{ 193 parser.Table{ 194 Object: parser.Identifier{Literal: "table1_bom.csv"}, 195 }, 196 }, 197 }, 198 Result: &View{ 199 Header: NewHeader("table1_bom", []string{"column1", "column2"}), 200 RecordSet: []Record{ 201 NewRecord([]value.Primary{ 202 value.NewString("1"), 203 value.NewString("str1"), 204 }), 205 NewRecord([]value.Primary{ 206 value.NewString("2"), 207 value.NewString("str2"), 208 }), 209 NewRecord([]value.Primary{ 210 value.NewString("3"), 211 value.NewString("str3"), 212 }), 213 }, 214 FileInfo: &FileInfo{ 215 Path: "table1_bom.csv", 216 Delimiter: ',', 217 Encoding: text.UTF8M, 218 LineBreak: text.LF, 219 }, 220 }, 221 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 222 {scopeNameAliases: { 223 "TABLE1_BOM": strings.ToUpper(GetTestFilePath("table1_bom.csv")), 224 }}, 225 }, time.Time{}, nil), 226 }, 227 { 228 Name: "LoadView with Parentheses", 229 From: parser.FromClause{ 230 Tables: []parser.QueryExpression{ 231 parser.Parentheses{ 232 Expr: parser.Table{ 233 Object: parser.Identifier{Literal: "table1.csv"}, 234 }, 235 }, 236 }, 237 }, 238 Result: &View{ 239 Header: NewHeader("table1", []string{"column1", "column2"}), 240 RecordSet: []Record{ 241 NewRecord([]value.Primary{ 242 value.NewString("1"), 243 value.NewString("str1"), 244 }), 245 NewRecord([]value.Primary{ 246 value.NewString("2"), 247 value.NewString("str2"), 248 }), 249 NewRecord([]value.Primary{ 250 value.NewString("3"), 251 value.NewString("str3"), 252 }), 253 }, 254 FileInfo: &FileInfo{ 255 Path: "table1.csv", 256 Delimiter: ',', 257 Encoding: text.UTF8, 258 LineBreak: text.LF, 259 }, 260 }, 261 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 262 {scopeNameAliases: { 263 "TABLE1": strings.ToUpper(GetTestFilePath("table1.csv")), 264 }}, 265 }, time.Time{}, nil), 266 }, 267 { 268 Name: "LoadView From Stdin", 269 From: parser.FromClause{ 270 Tables: []parser.QueryExpression{ 271 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 272 }, 273 }, 274 Stdin: "column1,column2\n1,\"str1\"", 275 Result: &View{ 276 Header: NewHeader("t", []string{"column1", "column2"}), 277 RecordSet: []Record{ 278 NewRecord([]value.Primary{ 279 value.NewString("1"), 280 value.NewString("str1"), 281 }), 282 }, 283 FileInfo: &FileInfo{ 284 Path: "STDIN", 285 Delimiter: ',', 286 Encoding: text.UTF8, 287 LineBreak: text.LF, 288 ViewType: ViewTypeStdin, 289 }, 290 }, 291 ResultScope: GenerateReferenceScope([]map[string]map[string]interface{}{ 292 { 293 scopeNameTempTables: { 294 "STDIN": &View{ 295 FileInfo: &FileInfo{Path: "STDIN"}, 296 }, 297 }, 298 }, 299 }, []map[string]map[string]interface{}{ 300 {scopeNameAliases: { 301 "T": "STDIN", 302 }}, 303 }, time.Time{}, nil), 304 }, 305 { 306 Name: "LoadView From Stdin ForUpdate", 307 From: parser.FromClause{ 308 Tables: []parser.QueryExpression{ 309 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 310 }, 311 }, 312 Stdin: "column1,column2\n1,\"str1\"", 313 ForUpdate: true, 314 Result: &View{ 315 Header: NewHeader("t", []string{"column1", "column2"}), 316 RecordSet: []Record{ 317 NewRecord([]value.Primary{ 318 value.NewString("1"), 319 value.NewString("str1"), 320 }), 321 }, 322 FileInfo: &FileInfo{ 323 Path: "STDIN", 324 Delimiter: ',', 325 Encoding: text.UTF8, 326 LineBreak: text.LF, 327 ViewType: ViewTypeStdin, 328 }, 329 }, 330 ResultScope: GenerateReferenceScope([]map[string]map[string]interface{}{ 331 { 332 scopeNameTempTables: { 333 "STDIN": &View{ 334 FileInfo: &FileInfo{Path: "STDIN"}, 335 }, 336 }, 337 }, 338 }, []map[string]map[string]interface{}{ 339 { 340 scopeNameAliases: { 341 "T": "STDIN", 342 }, 343 }, 344 }, time.Time{}, nil), 345 }, 346 { 347 Name: "LoadView TSV From Stdin", 348 From: parser.FromClause{ 349 Tables: []parser.QueryExpression{ 350 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 351 }, 352 }, 353 Stdin: "column1\tcolumn2\n1\t\"str1\"", 354 ImportFormat: option.TSV, 355 Result: &View{ 356 Header: NewHeader("t", []string{"column1", "column2"}), 357 RecordSet: []Record{ 358 NewRecord([]value.Primary{ 359 value.NewString("1"), 360 value.NewString("str1"), 361 }), 362 }, 363 FileInfo: &FileInfo{ 364 Path: "STDIN", 365 Format: option.TSV, 366 Delimiter: '\t', 367 Encoding: text.UTF8, 368 LineBreak: text.LF, 369 ViewType: ViewTypeStdin, 370 }, 371 }, 372 ResultScope: GenerateReferenceScope([]map[string]map[string]interface{}{ 373 { 374 scopeNameTempTables: { 375 "STDIN": &View{ 376 FileInfo: &FileInfo{Path: "STDIN"}, 377 }, 378 }, 379 }, 380 }, []map[string]map[string]interface{}{ 381 {scopeNameAliases: { 382 "T": "STDIN", 383 }}, 384 }, time.Time{}, nil), 385 }, 386 { 387 Name: "LoadView From Stdin With Internal Id", 388 From: parser.FromClause{ 389 Tables: []parser.QueryExpression{ 390 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 391 }, 392 }, 393 UseInternalId: true, 394 Stdin: "column1,column2\n1,\"str1\"", 395 Result: &View{ 396 Header: NewHeaderWithId("t", []string{"column1", "column2"}), 397 RecordSet: []Record{ 398 NewRecordWithId(0, []value.Primary{ 399 value.NewString("1"), 400 value.NewString("str1"), 401 }), 402 }, 403 FileInfo: &FileInfo{ 404 Path: "STDIN", 405 Delimiter: ',', 406 Encoding: text.UTF8, 407 LineBreak: text.LF, 408 ViewType: ViewTypeStdin, 409 }, 410 }, 411 ResultScope: GenerateReferenceScope([]map[string]map[string]interface{}{ 412 { 413 scopeNameTempTables: { 414 "STDIN": &View{ 415 FileInfo: &FileInfo{Path: "STDIN"}, 416 }, 417 }, 418 }, 419 }, []map[string]map[string]interface{}{ 420 { 421 scopeNameAliases: { 422 "T": "STDIN", 423 }, 424 }, 425 }, time.Time{}, nil), 426 }, 427 { 428 Name: "LoadView Json From Stdin", 429 From: parser.FromClause{ 430 Tables: []parser.QueryExpression{ 431 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 432 }, 433 }, 434 Stdin: "{\"key\":[{\"column1\": 1, \"column2\": \"str1\"}]}", 435 ImportFormat: option.JSON, 436 JsonQuery: "key{}", 437 Result: &View{ 438 Header: NewHeader("t", []string{"column1", "column2"}), 439 RecordSet: []Record{ 440 NewRecord([]value.Primary{ 441 value.NewFloat(1), 442 value.NewString("str1"), 443 }), 444 }, 445 FileInfo: &FileInfo{ 446 Path: "STDIN", 447 Delimiter: ',', 448 JsonQuery: "key{}", 449 Format: option.JSON, 450 Encoding: text.UTF8, 451 LineBreak: text.LF, 452 ViewType: ViewTypeStdin, 453 }, 454 }, 455 ResultScope: GenerateReferenceScope([]map[string]map[string]interface{}{ 456 { 457 scopeNameTempTables: { 458 "STDIN": &View{ 459 FileInfo: &FileInfo{Path: "STDIN"}, 460 }, 461 }, 462 }, 463 }, []map[string]map[string]interface{}{ 464 {scopeNameAliases: { 465 "T": "STDIN", 466 }}, 467 }, time.Time{}, nil), 468 }, 469 { 470 Name: "LoadView Json Lines From Stdin", 471 From: parser.FromClause{ 472 Tables: []parser.QueryExpression{ 473 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 474 }, 475 }, 476 Stdin: "{\"column1\": 1, \"column2\": \"str1\"}\n{\"column1\": 2, \"column2\": \"str2\"}", 477 ImportFormat: option.JSONL, 478 JsonQuery: "", 479 Result: &View{ 480 Header: NewHeader("t", []string{"column1", "column2"}), 481 RecordSet: []Record{ 482 NewRecord([]value.Primary{ 483 value.NewFloat(1), 484 value.NewString("str1"), 485 }), 486 NewRecord([]value.Primary{ 487 value.NewFloat(2), 488 value.NewString("str2"), 489 }), 490 }, 491 FileInfo: &FileInfo{ 492 Path: "STDIN", 493 Delimiter: ',', 494 JsonQuery: "", 495 Format: option.JSONL, 496 Encoding: text.UTF8, 497 LineBreak: text.LF, 498 ViewType: ViewTypeStdin, 499 }, 500 }, 501 ResultScope: GenerateReferenceScope([]map[string]map[string]interface{}{ 502 { 503 scopeNameTempTables: { 504 "STDIN": &View{ 505 FileInfo: &FileInfo{Path: "STDIN"}, 506 }, 507 }, 508 }, 509 }, []map[string]map[string]interface{}{ 510 {scopeNameAliases: { 511 "T": "STDIN", 512 }}, 513 }, time.Time{}, nil), 514 }, 515 { 516 Name: "LoadView Json Lines From Stdin, Json Structure Error", 517 From: parser.FromClause{ 518 Tables: []parser.QueryExpression{ 519 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 520 }, 521 }, 522 Stdin: "{\"column1\": 1, \"column2\": \"str1\"}\n\"str\"", 523 ImportFormat: option.JSONL, 524 JsonQuery: "", 525 Error: "json lines must be an array of objects", 526 }, 527 { 528 Name: "LoadView JsonH From Stdin", 529 From: parser.FromClause{ 530 Tables: []parser.QueryExpression{ 531 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 532 }, 533 }, 534 Stdin: "[{\"item1\": \"value\\u00221\",\"item2\": 1},{\"item1\": \"value2\",\"item2\": 2}]", 535 ImportFormat: option.JSON, 536 JsonQuery: "{}", 537 Result: &View{ 538 Header: NewHeader("t", []string{"item1", "item2"}), 539 RecordSet: []Record{ 540 NewRecord([]value.Primary{ 541 value.NewString("value\"1"), 542 value.NewFloat(1), 543 }), 544 NewRecord([]value.Primary{ 545 value.NewString("value2"), 546 value.NewFloat(2), 547 }), 548 }, 549 FileInfo: &FileInfo{ 550 Path: "STDIN", 551 Delimiter: ',', 552 JsonQuery: "{}", 553 Format: option.JSON, 554 Encoding: text.UTF8, 555 LineBreak: text.LF, 556 JsonEscape: json.HexDigits, 557 ViewType: ViewTypeStdin, 558 }, 559 }, 560 ResultScope: GenerateReferenceScope([]map[string]map[string]interface{}{ 561 { 562 scopeNameTempTables: { 563 "STDIN": &View{ 564 FileInfo: &FileInfo{Path: "STDIN"}, 565 }, 566 }, 567 }, 568 }, []map[string]map[string]interface{}{ 569 { 570 scopeNameAliases: { 571 "T": "STDIN", 572 }, 573 }, 574 }, time.Time{}, nil), 575 }, 576 { 577 Name: "LoadView JsonA From Stdin", 578 From: parser.FromClause{ 579 Tables: []parser.QueryExpression{ 580 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 581 }, 582 }, 583 Stdin: "[{\"item1\": \"\\u0076\\u0061\\u006c\\u0075\\u0065\\u0031\",\"item2\": 1},{\"item1\": \"\\u0076\\u0061\\u006c\\u0075\\u0065\\u0032\",\"item2\": 2}]", 584 ImportFormat: option.JSON, 585 JsonQuery: "{}", 586 Result: &View{ 587 Header: NewHeader("t", []string{"item1", "item2"}), 588 RecordSet: []Record{ 589 NewRecord([]value.Primary{ 590 value.NewString("value1"), 591 value.NewFloat(1), 592 }), 593 NewRecord([]value.Primary{ 594 value.NewString("value2"), 595 value.NewFloat(2), 596 }), 597 }, 598 FileInfo: &FileInfo{ 599 Path: "STDIN", 600 Delimiter: ',', 601 JsonQuery: "{}", 602 Format: option.JSON, 603 Encoding: text.UTF8, 604 LineBreak: text.LF, 605 JsonEscape: json.AllWithHexDigits, 606 ViewType: ViewTypeStdin, 607 }, 608 }, 609 ResultScope: GenerateReferenceScope([]map[string]map[string]interface{}{ 610 { 611 scopeNameTempTables: { 612 "STDIN": &View{ 613 FileInfo: &FileInfo{Path: "STDIN"}, 614 }, 615 }, 616 }, 617 }, []map[string]map[string]interface{}{ 618 { 619 scopeNameAliases: { 620 "T": "STDIN", 621 }, 622 }, 623 }, time.Time{}, nil), 624 }, 625 { 626 Name: "LoadView Json From Stdin Json Query Error", 627 From: parser.FromClause{ 628 Tables: []parser.QueryExpression{ 629 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 630 }, 631 }, 632 Stdin: "{\"key\":[{\"column1\": 1, \"column2\": \"str1\"}]}", 633 ImportFormat: option.JSON, 634 JsonQuery: "key{", 635 Error: "json loading error: column 4: unexpected termination", 636 }, 637 { 638 Name: "LoadView Fixed-Length Text File", 639 ImportFormat: option.FIXED, 640 From: parser.FromClause{ 641 Tables: []parser.QueryExpression{ 642 parser.Table{ 643 Object: parser.Identifier{Literal: "fixed_length.txt"}, 644 }, 645 }, 646 }, 647 Result: &View{ 648 Header: NewHeader("fixed_length", []string{"column1", "__@2__"}), 649 RecordSet: []Record{ 650 NewRecord([]value.Primary{ 651 value.NewString("1"), 652 value.NewString("str1"), 653 }), 654 NewRecord([]value.Primary{ 655 value.NewString("2"), 656 value.NewString("str2"), 657 }), 658 NewRecord([]value.Primary{ 659 value.NewString("3"), 660 value.NewString("str3"), 661 }), 662 }, 663 FileInfo: &FileInfo{ 664 Path: "fixed_length.txt", 665 Delimiter: ',', 666 DelimiterPositions: []int{7, 12}, 667 Format: option.FIXED, 668 NoHeader: false, 669 Encoding: text.UTF8, 670 LineBreak: text.LF, 671 }, 672 }, 673 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 674 {scopeNameAliases: { 675 "FIXED_LENGTH": strings.ToUpper(GetTestFilePath("fixed_length.txt")), 676 }}, 677 }, time.Time{}, nil), 678 }, 679 { 680 Name: "LoadView Fixed-Length Text File NoHeader", 681 NoHeader: true, 682 ImportFormat: option.FIXED, 683 From: parser.FromClause{ 684 Tables: []parser.QueryExpression{ 685 parser.Table{ 686 Object: parser.Identifier{Literal: "fixed_length.txt"}, 687 }, 688 }, 689 }, 690 Result: &View{ 691 Header: NewHeader("fixed_length", []string{"c1", "c2"}), 692 RecordSet: []Record{ 693 NewRecord([]value.Primary{ 694 value.NewString("column1"), 695 value.NewNull(), 696 }), 697 NewRecord([]value.Primary{ 698 value.NewString("1"), 699 value.NewString("str1"), 700 }), 701 NewRecord([]value.Primary{ 702 value.NewString("2"), 703 value.NewString("str2"), 704 }), 705 NewRecord([]value.Primary{ 706 value.NewString("3"), 707 value.NewString("str3"), 708 }), 709 }, 710 FileInfo: &FileInfo{ 711 Path: "fixed_length.txt", 712 Delimiter: ',', 713 DelimiterPositions: []int{7, 12}, 714 Format: option.FIXED, 715 NoHeader: true, 716 Encoding: text.UTF8, 717 LineBreak: text.LF, 718 }, 719 }, 720 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 721 {scopeNameAliases: { 722 "FIXED_LENGTH": strings.ToUpper(GetTestFilePath("fixed_length.txt")), 723 }}, 724 }, time.Time{}, nil), 725 }, 726 { 727 Name: "LoadView Fixed-Length Text File Position Error", 728 ImportFormat: option.FIXED, 729 DelimiterPositions: []int{6, 2}, 730 From: parser.FromClause{ 731 Tables: []parser.QueryExpression{ 732 parser.Table{ 733 Object: parser.Identifier{Literal: "fixed_length.txt"}, 734 }, 735 }, 736 }, 737 Error: fmt.Sprintf("data parse error in %s: invalid delimiter position: [6, 2]", GetTestFilePath("fixed_length.txt")), 738 }, 739 { 740 Name: "LoadView From Stdin With Omitted FromClause", 741 From: parser.FromClause{}, 742 Stdin: "column1,column2\n1,\"str1\"", 743 Result: &View{ 744 Header: NewHeader("STDIN", []string{"column1", "column2"}), 745 RecordSet: []Record{ 746 NewRecord([]value.Primary{ 747 value.NewString("1"), 748 value.NewString("str1"), 749 }), 750 }, 751 FileInfo: &FileInfo{ 752 Path: "STDIN", 753 Delimiter: ',', 754 Encoding: text.UTF8, 755 LineBreak: text.LF, 756 ViewType: ViewTypeStdin, 757 }, 758 }, 759 ResultScope: GenerateReferenceScope([]map[string]map[string]interface{}{ 760 { 761 scopeNameTempTables: { 762 "STDIN": &View{ 763 FileInfo: &FileInfo{Path: "STDIN"}, 764 }, 765 }, 766 }, 767 }, []map[string]map[string]interface{}{ 768 { 769 scopeNameAliases: { 770 "STDIN": "STDIN", 771 }, 772 }, 773 }, time.Time{}, nil), 774 }, 775 { 776 Name: "LoadView From Stdin Broken CSV Error", 777 From: parser.FromClause{ 778 Tables: []parser.QueryExpression{ 779 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 780 }, 781 }, 782 Stdin: "column1,column2\n1\"str1\"", 783 Error: "data parse error in STDIN: line 1, column 8: wrong number of fields in line", 784 }, 785 { 786 Name: "LoadView From Stdin Duplicate Table Name Error", 787 From: parser.FromClause{ 788 Tables: []parser.QueryExpression{ 789 parser.Table{Object: parser.Identifier{Literal: "table1"}, Alias: parser.Identifier{Literal: "t"}}, 790 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 791 }, 792 }, 793 Stdin: "column1,column2\n1,\"str1\"", 794 Error: "table name t is a duplicate", 795 }, 796 { 797 Name: "LoadView From Stdin ForUpdate Duplicate Table Name Error", 798 From: parser.FromClause{ 799 Tables: []parser.QueryExpression{ 800 parser.Table{Object: parser.Identifier{Literal: "table1"}, Alias: parser.Identifier{Literal: "t"}}, 801 parser.Table{Object: parser.Stdin{}, Alias: parser.Identifier{Literal: "t"}}, 802 }, 803 }, 804 ForUpdate: true, 805 Stdin: "column1,column2\n1,\"str1\"", 806 Error: "table name t is a duplicate", 807 }, 808 { 809 Name: "Stdin Empty Error", 810 From: parser.FromClause{ 811 Tables: []parser.QueryExpression{ 812 parser.Table{ 813 Object: parser.Stdin{}, 814 }, 815 }, 816 }, 817 Error: "STDIN is empty", 818 }, 819 { 820 Name: "LoadView FormatSpecifiedFunction From CSV File", 821 From: parser.FromClause{ 822 Tables: []parser.QueryExpression{ 823 parser.Table{ 824 Object: parser.FormatSpecifiedFunction{ 825 Type: parser.Token{Token: parser.CSV, Literal: "csv"}, 826 FormatElement: parser.NewStringValue(","), 827 Path: parser.Identifier{Literal: "table5"}, 828 Args: []parser.QueryExpression{ 829 parser.NewStringValue("SJIS"), 830 parser.NewTernaryValueFromString("true"), 831 parser.NewTernaryValueFromString("true"), 832 }, 833 }, 834 Alias: parser.Identifier{Literal: "t"}, 835 }, 836 }, 837 }, 838 Result: &View{ 839 Header: NewHeader("t", []string{"c1", "c2"}), 840 RecordSet: []Record{ 841 NewRecord([]value.Primary{ 842 value.NewString("1"), 843 value.NewString("str1"), 844 }), 845 NewRecord([]value.Primary{ 846 value.NewString("2"), 847 value.NewString(""), 848 }), 849 NewRecord([]value.Primary{ 850 value.NewString("3"), 851 value.NewString("str3"), 852 }), 853 }, 854 FileInfo: &FileInfo{ 855 Path: "table5.csv", 856 Delimiter: ',', 857 Format: option.CSV, 858 Encoding: text.SJIS, 859 LineBreak: text.LF, 860 NoHeader: true, 861 }, 862 }, 863 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 864 {scopeNameAliases: { 865 "T": strings.ToUpper(GetTestFilePath("table5.csv")), 866 }}, 867 }, time.Time{}, nil), 868 }, 869 { 870 Name: "LoadView FormatSpecifiedFunction From TSV File", 871 From: parser.FromClause{ 872 Tables: []parser.QueryExpression{ 873 parser.Table{ 874 Object: parser.FormatSpecifiedFunction{ 875 Type: parser.Token{Token: parser.CSV, Literal: "csv"}, 876 FormatElement: parser.NewStringValue("\t"), 877 Path: parser.Identifier{Literal: "table3"}, 878 Args: []parser.QueryExpression{ 879 parser.FieldReference{Column: parser.Identifier{Literal: "UTF8"}}, 880 }, 881 }, 882 Alias: parser.Identifier{Literal: "t"}, 883 }, 884 }, 885 }, 886 Result: &View{ 887 Header: NewHeader("t", []string{"column5", "column6"}), 888 RecordSet: []Record{ 889 NewRecord([]value.Primary{ 890 value.NewString("1"), 891 value.NewString("str1"), 892 }), 893 NewRecord([]value.Primary{ 894 value.NewString("2"), 895 value.NewString("str2"), 896 }), 897 }, 898 FileInfo: &FileInfo{ 899 Path: "table3.tsv", 900 Delimiter: '\t', 901 Format: option.TSV, 902 Encoding: text.UTF8, 903 LineBreak: text.LF, 904 }, 905 }, 906 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 907 {scopeNameAliases: { 908 "T": strings.ToUpper(GetTestFilePath("table3.tsv")), 909 }}, 910 }, time.Time{}, nil), 911 }, 912 { 913 Name: "LoadView FormatSpecifiedFunction From CSV File FormatElement Evaluate Error", 914 From: parser.FromClause{ 915 Tables: []parser.QueryExpression{ 916 parser.Table{ 917 Object: parser.FormatSpecifiedFunction{ 918 Type: parser.Token{Token: parser.CSV, Literal: "csv"}, 919 FormatElement: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 920 Path: parser.Identifier{Literal: "table1"}, 921 }, 922 Alias: parser.Identifier{Literal: "t"}, 923 }, 924 }, 925 }, 926 Error: "field notexist does not exist", 927 }, 928 { 929 Name: "LoadView FormatSpecifiedFunction From CSV File FormatElement Is Not Specified", 930 From: parser.FromClause{ 931 Tables: []parser.QueryExpression{ 932 parser.Table{ 933 Object: parser.FormatSpecifiedFunction{ 934 Type: parser.Token{Token: parser.CSV, Literal: "csv"}, 935 Path: parser.Identifier{Literal: "table1"}, 936 }, 937 Alias: parser.Identifier{Literal: "t"}, 938 }, 939 }, 940 }, 941 Error: "invalid argument for csv: delimiter is not specified", 942 }, 943 { 944 Name: "LoadView FormatSpecifiedFunction From CSV File FormatElement is Null", 945 From: parser.FromClause{ 946 Tables: []parser.QueryExpression{ 947 parser.Table{ 948 Object: parser.FormatSpecifiedFunction{ 949 Type: parser.Token{Token: parser.CSV, Literal: "csv"}, 950 FormatElement: parser.NewNullValue(), 951 Path: parser.Identifier{Literal: "table1"}, 952 }, 953 Alias: parser.Identifier{Literal: "t"}, 954 }, 955 }, 956 }, 957 Error: "invalid delimiter: NULL", 958 }, 959 { 960 Name: "LoadView FormatSpecifiedFunction From CSV File FormatElement Invalid Delimiter", 961 From: parser.FromClause{ 962 Tables: []parser.QueryExpression{ 963 parser.Table{ 964 Object: parser.FormatSpecifiedFunction{ 965 Type: parser.Token{Token: parser.CSV, Literal: "csv"}, 966 FormatElement: parser.NewStringValue("invalid"), 967 Path: parser.Identifier{Literal: "table1"}, 968 }, 969 Alias: parser.Identifier{Literal: "t"}, 970 }, 971 }, 972 }, 973 Error: "invalid delimiter: 'invalid'", 974 }, 975 { 976 Name: "LoadView FormatSpecifiedFunction From CSV File Arguments Length Error", 977 From: parser.FromClause{ 978 Tables: []parser.QueryExpression{ 979 parser.Table{ 980 Object: parser.FormatSpecifiedFunction{ 981 Type: parser.Token{Token: parser.CSV, Literal: "csv"}, 982 FormatElement: parser.NewStringValue(","), 983 Path: parser.Identifier{Literal: "table5"}, 984 Args: []parser.QueryExpression{ 985 parser.NewStringValue("SJIS"), 986 parser.NewTernaryValueFromString("true"), 987 parser.NewTernaryValueFromString("true"), 988 parser.NewStringValue("extra"), 989 }, 990 }, 991 Alias: parser.Identifier{Literal: "t"}, 992 }, 993 }, 994 }, 995 Error: "table object csv takes at most 5 arguments", 996 }, 997 { 998 Name: "LoadView FormatSpecifiedFunction From CSV File 3rd Argument Error", 999 From: parser.FromClause{ 1000 Tables: []parser.QueryExpression{ 1001 parser.Table{ 1002 Object: parser.FormatSpecifiedFunction{ 1003 Type: parser.Token{Token: parser.CSV, Literal: "csv"}, 1004 FormatElement: parser.NewStringValue(","), 1005 Path: parser.Identifier{Literal: "table5"}, 1006 Args: []parser.QueryExpression{ 1007 parser.NewTernaryValueFromString("true"), 1008 }, 1009 }, 1010 Alias: parser.Identifier{Literal: "t"}, 1011 }, 1012 }, 1013 }, 1014 Error: "invalid argument for csv: cannot be converted as a encoding value: TRUE", 1015 }, 1016 { 1017 Name: "LoadView FormatSpecifiedFunction From CSV File 4th Argument Error", 1018 From: parser.FromClause{ 1019 Tables: []parser.QueryExpression{ 1020 parser.Table{ 1021 Object: parser.FormatSpecifiedFunction{ 1022 Type: parser.Token{Token: parser.CSV, Literal: "csv"}, 1023 FormatElement: parser.NewStringValue(","), 1024 Path: parser.Identifier{Literal: "table5"}, 1025 Args: []parser.QueryExpression{ 1026 parser.NewStringValue("SJIS"), 1027 parser.NewStringValue("SJIS"), 1028 }, 1029 }, 1030 Alias: parser.Identifier{Literal: "t"}, 1031 }, 1032 }, 1033 }, 1034 Error: "invalid argument for csv: cannot be converted as a no-header value: 'SJIS'", 1035 }, 1036 { 1037 Name: "LoadView FormatSpecifiedFunction From CSV File 5th Argument Error", 1038 From: parser.FromClause{ 1039 Tables: []parser.QueryExpression{ 1040 parser.Table{ 1041 Object: parser.FormatSpecifiedFunction{ 1042 Type: parser.Token{Token: parser.CSV, Literal: "csv"}, 1043 FormatElement: parser.NewStringValue(","), 1044 Path: parser.Identifier{Literal: "table5"}, 1045 Args: []parser.QueryExpression{ 1046 parser.NewStringValue("SJIS"), 1047 parser.NewTernaryValueFromString("true"), 1048 parser.NewStringValue("SJIS"), 1049 }, 1050 }, 1051 Alias: parser.Identifier{Literal: "t"}, 1052 }, 1053 }, 1054 }, 1055 Error: "invalid argument for csv: cannot be converted as a without-null value: 'SJIS'", 1056 }, 1057 { 1058 Name: "LoadView FormatSpecifiedFunction From CSV File Invalid Encoding Type", 1059 From: parser.FromClause{ 1060 Tables: []parser.QueryExpression{ 1061 parser.Table{ 1062 Object: parser.FormatSpecifiedFunction{ 1063 Type: parser.Token{Token: parser.CSV, Literal: "csv"}, 1064 FormatElement: parser.NewStringValue(","), 1065 Path: parser.Identifier{Literal: "table5"}, 1066 Args: []parser.QueryExpression{ 1067 parser.NewStringValue("INVALID"), 1068 }, 1069 }, 1070 Alias: parser.Identifier{Literal: "t"}, 1071 }, 1072 }, 1073 }, 1074 Error: "invalid argument for csv: encoding must be one of AUTO|UTF8|UTF8M|UTF16|UTF16BE|UTF16LE|UTF16BEM|UTF16LEM|SJIS", 1075 }, 1076 { 1077 Name: "LoadView FormatSpecifiedFunction From Fixed-Length File", 1078 From: parser.FromClause{ 1079 Tables: []parser.QueryExpression{ 1080 parser.Table{ 1081 Object: parser.FormatSpecifiedFunction{ 1082 Type: parser.Token{Token: parser.FIXED, Literal: "fixed"}, 1083 FormatElement: parser.NewStringValue("spaces"), 1084 Path: parser.Identifier{Literal: "fixed_length.txt", Quoted: true}, 1085 }, 1086 Alias: parser.Identifier{Literal: "t"}, 1087 }, 1088 }, 1089 }, 1090 Result: &View{ 1091 Header: NewHeader("t", []string{"column1", "__@2__"}), 1092 RecordSet: []Record{ 1093 NewRecord([]value.Primary{ 1094 value.NewString("1"), 1095 value.NewString("str1"), 1096 }), 1097 NewRecord([]value.Primary{ 1098 value.NewString("2"), 1099 value.NewString("str2"), 1100 }), 1101 NewRecord([]value.Primary{ 1102 value.NewString("3"), 1103 value.NewString("str3"), 1104 }), 1105 }, 1106 FileInfo: &FileInfo{ 1107 Path: "fixed_length.txt", 1108 Delimiter: ',', 1109 DelimiterPositions: []int{7, 12}, 1110 Format: option.FIXED, 1111 Encoding: text.UTF8, 1112 LineBreak: text.LF, 1113 }, 1114 }, 1115 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1116 {scopeNameAliases: { 1117 "T": strings.ToUpper(GetTestFilePath("fixed_length.txt")), 1118 }}, 1119 }, time.Time{}, nil), 1120 }, 1121 { 1122 Name: "LoadView FormatSpecifiedFunction From Fixed-Length File with UTF-8 BOM", 1123 From: parser.FromClause{ 1124 Tables: []parser.QueryExpression{ 1125 parser.Table{ 1126 Object: parser.FormatSpecifiedFunction{ 1127 Type: parser.Token{Token: parser.FIXED, Literal: "fixed"}, 1128 FormatElement: parser.NewStringValue("spaces"), 1129 Path: parser.Identifier{Literal: "fixed_length_bom.txt", Quoted: true}, 1130 }, 1131 Alias: parser.Identifier{Literal: "t"}, 1132 }, 1133 }, 1134 }, 1135 Result: &View{ 1136 Header: NewHeader("t", []string{"column1", "__@2__"}), 1137 RecordSet: []Record{ 1138 NewRecord([]value.Primary{ 1139 value.NewString("1"), 1140 value.NewString("str1"), 1141 }), 1142 NewRecord([]value.Primary{ 1143 value.NewString("2"), 1144 value.NewString("str2"), 1145 }), 1146 NewRecord([]value.Primary{ 1147 value.NewString("3"), 1148 value.NewString("str3"), 1149 }), 1150 }, 1151 FileInfo: &FileInfo{ 1152 Path: "fixed_length_bom.txt", 1153 Delimiter: ',', 1154 DelimiterPositions: []int{7, 12}, 1155 Format: option.FIXED, 1156 Encoding: text.UTF8M, 1157 LineBreak: text.LF, 1158 }, 1159 }, 1160 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1161 {scopeNameAliases: { 1162 "T": strings.ToUpper(GetTestFilePath("fixed_length_bom.txt")), 1163 }}, 1164 }, time.Time{}, nil), 1165 }, 1166 { 1167 Name: "LoadView FormatSpecifiedFunction From Single-Line Fixed-Length File", 1168 From: parser.FromClause{ 1169 Tables: []parser.QueryExpression{ 1170 parser.Table{ 1171 Object: parser.FormatSpecifiedFunction{ 1172 Type: parser.Token{Token: parser.FIXED, Literal: "fixed"}, 1173 FormatElement: parser.NewStringValue("s[1,5]"), 1174 Path: parser.Identifier{Literal: "fixed_length_sl.txt", Quoted: true}, 1175 }, 1176 Alias: parser.Identifier{Literal: "t"}, 1177 }, 1178 }, 1179 }, 1180 Result: &View{ 1181 Header: NewHeader("t", []string{"c1", "c2"}), 1182 RecordSet: []Record{ 1183 NewRecord([]value.Primary{ 1184 value.NewString("1"), 1185 value.NewString("str1"), 1186 }), 1187 NewRecord([]value.Primary{ 1188 value.NewString("2"), 1189 value.NewString("str2"), 1190 }), 1191 NewRecord([]value.Primary{ 1192 value.NewString("3"), 1193 value.NewString("str3"), 1194 }), 1195 }, 1196 FileInfo: &FileInfo{ 1197 Path: "fixed_length_sl.txt", 1198 Delimiter: ',', 1199 DelimiterPositions: []int{1, 5}, 1200 Format: option.FIXED, 1201 Encoding: text.UTF8, 1202 LineBreak: text.LF, 1203 SingleLine: true, 1204 }, 1205 }, 1206 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1207 {scopeNameAliases: { 1208 "T": strings.ToUpper(GetTestFilePath("fixed_length_sl.txt")), 1209 }}, 1210 }, time.Time{}, nil), 1211 }, 1212 { 1213 Name: "LoadView FormatSpecifiedFunction From Fixed-Length File FormatElement Is Not Specified", 1214 From: parser.FromClause{ 1215 Tables: []parser.QueryExpression{ 1216 parser.Table{ 1217 Object: parser.FormatSpecifiedFunction{ 1218 Type: parser.Token{Token: parser.FIXED, Literal: "fixed"}, 1219 Path: parser.Identifier{Literal: "fixed_length.txt", Quoted: true}, 1220 }, 1221 Alias: parser.Identifier{Literal: "t"}, 1222 }, 1223 }, 1224 }, 1225 Error: "invalid argument for fixed: delimiter positions are not specified", 1226 }, 1227 { 1228 Name: "LoadView FormatSpecifiedFunction From Fixed-Length File FormatElement is Null", 1229 From: parser.FromClause{ 1230 Tables: []parser.QueryExpression{ 1231 parser.Table{ 1232 Object: parser.FormatSpecifiedFunction{ 1233 Type: parser.Token{Token: parser.FIXED, Literal: "fixed"}, 1234 FormatElement: parser.NewNullValue(), 1235 Path: parser.Identifier{Literal: "fixed_length.txt", Quoted: true}, 1236 }, 1237 Alias: parser.Identifier{Literal: "t"}, 1238 }, 1239 }, 1240 }, 1241 Error: "invalid delimiter positions: NULL", 1242 }, 1243 { 1244 Name: "LoadView FormatSpecifiedFunction From Fixed-Length File Invalid Delimiter Positions", 1245 From: parser.FromClause{ 1246 Tables: []parser.QueryExpression{ 1247 parser.Table{ 1248 Object: parser.FormatSpecifiedFunction{ 1249 Type: parser.Token{Token: parser.FIXED, Literal: "fixed"}, 1250 FormatElement: parser.NewStringValue("invalid"), 1251 Path: parser.Identifier{Literal: "fixed_length.txt", Quoted: true}, 1252 }, 1253 Alias: parser.Identifier{Literal: "t"}, 1254 }, 1255 }, 1256 }, 1257 Error: "invalid delimiter positions: 'invalid'", 1258 }, 1259 { 1260 Name: "LoadView FormatSpecifiedFunction From Fixed-Length File Arguments Length Error", 1261 From: parser.FromClause{ 1262 Tables: []parser.QueryExpression{ 1263 parser.Table{ 1264 Object: parser.FormatSpecifiedFunction{ 1265 Type: parser.Token{Token: parser.FIXED, Literal: "fixed"}, 1266 FormatElement: parser.NewStringValue("spaces"), 1267 Path: parser.Identifier{Literal: "fixed_length.txt", Quoted: true}, 1268 Args: []parser.QueryExpression{ 1269 parser.NewStringValue("SJIS"), 1270 parser.NewTernaryValueFromString("true"), 1271 parser.NewTernaryValueFromString("true"), 1272 parser.NewStringValue("extra"), 1273 }, 1274 }, 1275 Alias: parser.Identifier{Literal: "t"}, 1276 }, 1277 }, 1278 }, 1279 Error: "table object fixed takes at most 5 arguments", 1280 }, 1281 { 1282 Name: "LoadView FormatSpecifiedFunction From Json File", 1283 From: parser.FromClause{ 1284 Tables: []parser.QueryExpression{ 1285 parser.Table{ 1286 Object: parser.FormatSpecifiedFunction{ 1287 Type: parser.Token{Token: parser.JSON, Literal: "json"}, 1288 FormatElement: parser.NewStringValue("{}"), 1289 Path: parser.Identifier{Literal: "table"}, 1290 }, 1291 Alias: parser.Identifier{Literal: "jt"}, 1292 }, 1293 }, 1294 }, 1295 Result: &View{ 1296 Header: NewHeader("jt", []string{"item1", "item2"}), 1297 RecordSet: []Record{ 1298 NewRecord([]value.Primary{ 1299 value.NewString("value1"), 1300 value.NewFloat(1), 1301 }), 1302 NewRecord([]value.Primary{ 1303 value.NewString("value2"), 1304 value.NewFloat(2), 1305 }), 1306 }, 1307 FileInfo: &FileInfo{ 1308 Path: "table.json", 1309 Delimiter: ',', 1310 JsonQuery: "{}", 1311 Format: option.JSON, 1312 Encoding: text.UTF8, 1313 LineBreak: text.LF, 1314 }, 1315 }, 1316 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1317 {scopeNameAliases: { 1318 "JT": strings.ToUpper(GetTestFilePath("table.json")), 1319 }}, 1320 }, time.Time{}, nil), 1321 }, 1322 { 1323 Name: "LoadView FormatSpecifiedFunction From JsonH File", 1324 From: parser.FromClause{ 1325 Tables: []parser.QueryExpression{ 1326 parser.Table{ 1327 Object: parser.FormatSpecifiedFunction{ 1328 Type: parser.Token{Token: parser.JSON, Literal: "json"}, 1329 FormatElement: parser.NewStringValue("{}"), 1330 Path: parser.Identifier{Literal: "table_h"}, 1331 }, 1332 Alias: parser.Identifier{Literal: "jt"}, 1333 }, 1334 }, 1335 }, 1336 Result: &View{ 1337 Header: NewHeader("jt", []string{"item1", "item2"}), 1338 RecordSet: []Record{ 1339 NewRecord([]value.Primary{ 1340 value.NewString("value\"1"), 1341 value.NewFloat(1), 1342 }), 1343 NewRecord([]value.Primary{ 1344 value.NewString("value2"), 1345 value.NewFloat(2), 1346 }), 1347 }, 1348 FileInfo: &FileInfo{ 1349 Path: "table_h.json", 1350 Delimiter: ',', 1351 JsonQuery: "{}", 1352 Format: option.JSON, 1353 Encoding: text.UTF8, 1354 LineBreak: text.LF, 1355 JsonEscape: json.HexDigits, 1356 }, 1357 }, 1358 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1359 {scopeNameAliases: { 1360 "JT": strings.ToUpper(GetTestFilePath("table_h.json")), 1361 }}, 1362 }, time.Time{}, nil), 1363 }, 1364 { 1365 Name: "LoadView FormatSpecifiedFunction From JsonA File", 1366 From: parser.FromClause{ 1367 Tables: []parser.QueryExpression{ 1368 parser.Table{ 1369 Object: parser.FormatSpecifiedFunction{ 1370 Type: parser.Token{Token: parser.JSON, Literal: "json"}, 1371 FormatElement: parser.NewStringValue("{}"), 1372 Path: parser.Identifier{Literal: "table_a"}, 1373 }, 1374 Alias: parser.Identifier{Literal: "jt"}, 1375 }, 1376 }, 1377 }, 1378 Result: &View{ 1379 Header: NewHeader("jt", []string{"item1", "item2"}), 1380 RecordSet: []Record{ 1381 NewRecord([]value.Primary{ 1382 value.NewString("value1"), 1383 value.NewFloat(1), 1384 }), 1385 NewRecord([]value.Primary{ 1386 value.NewString("value2"), 1387 value.NewFloat(2), 1388 }), 1389 }, 1390 FileInfo: &FileInfo{ 1391 Path: "table_a.json", 1392 Delimiter: ',', 1393 JsonQuery: "{}", 1394 Format: option.JSON, 1395 Encoding: text.UTF8, 1396 LineBreak: text.LF, 1397 JsonEscape: json.AllWithHexDigits, 1398 }, 1399 }, 1400 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1401 {scopeNameAliases: { 1402 "JT": strings.ToUpper(GetTestFilePath("table_a.json")), 1403 }}, 1404 }, time.Time{}, nil), 1405 }, 1406 { 1407 Name: "LoadView FormatSpecifiedFunction From Json File FormatElement Is Not Specified", 1408 From: parser.FromClause{ 1409 Tables: []parser.QueryExpression{ 1410 parser.Table{ 1411 Object: parser.FormatSpecifiedFunction{ 1412 Type: parser.Token{Token: parser.JSON, Literal: "json"}, 1413 Path: parser.Identifier{Literal: "table"}, 1414 }, 1415 Alias: parser.Identifier{Literal: "jt"}, 1416 }, 1417 }, 1418 }, 1419 Error: "invalid argument for json: json query is not specified", 1420 }, 1421 { 1422 Name: "LoadView FormatSpecifiedFunction From Json File FormatElement is Null", 1423 From: parser.FromClause{ 1424 Tables: []parser.QueryExpression{ 1425 parser.Table{ 1426 Object: parser.FormatSpecifiedFunction{ 1427 Type: parser.Token{Token: parser.JSON, Literal: "json"}, 1428 FormatElement: parser.NewNullValue(), 1429 Path: parser.Identifier{Literal: "table"}, 1430 }, 1431 Alias: parser.Identifier{Literal: "jt"}, 1432 }, 1433 }, 1434 }, 1435 Error: "invalid json query: NULL", 1436 }, 1437 { 1438 Name: "LoadView Table Object From Json File Path Error", 1439 From: parser.FromClause{ 1440 Tables: []parser.QueryExpression{ 1441 parser.Table{ 1442 Object: parser.FormatSpecifiedFunction{ 1443 Type: parser.Token{Token: parser.JSON, Literal: "json"}, 1444 FormatElement: parser.NewStringValue("{}"), 1445 Path: parser.Identifier{Literal: "notexist"}, 1446 }, 1447 Alias: parser.Identifier{Literal: "jt"}, 1448 }, 1449 }, 1450 }, 1451 Error: "file notexist does not exist", 1452 }, 1453 { 1454 Name: "LoadView FormatSpecifiedFunction From Json Lines File", 1455 From: parser.FromClause{ 1456 Tables: []parser.QueryExpression{ 1457 parser.Table{ 1458 Object: parser.FormatSpecifiedFunction{ 1459 Type: parser.Token{Token: parser.JSONL, Literal: "jsonl"}, 1460 FormatElement: parser.NewStringValue("{}"), 1461 Path: parser.Identifier{Literal: "table7"}, 1462 }, 1463 Alias: parser.Identifier{Literal: "jt"}, 1464 }, 1465 }, 1466 }, 1467 Result: &View{ 1468 Header: NewHeader("jt", []string{"item1", "item2"}), 1469 RecordSet: []Record{ 1470 NewRecord([]value.Primary{ 1471 value.NewString("value1"), 1472 value.NewFloat(1), 1473 }), 1474 NewRecord([]value.Primary{ 1475 value.NewString("value2"), 1476 value.NewFloat(2), 1477 }), 1478 }, 1479 FileInfo: &FileInfo{ 1480 Path: "table7.jsonl", 1481 Delimiter: ',', 1482 JsonQuery: "{}", 1483 Format: option.JSONL, 1484 Encoding: text.UTF8, 1485 LineBreak: text.LF, 1486 }, 1487 }, 1488 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1489 {scopeNameAliases: { 1490 "JT": strings.ToUpper(GetTestFilePath("table7.jsonl")), 1491 }}, 1492 }, time.Time{}, nil), 1493 }, 1494 { 1495 Name: "LoadView FormatSpecifiedFunction From LTSV File", 1496 From: parser.FromClause{ 1497 Tables: []parser.QueryExpression{ 1498 parser.Table{ 1499 Object: parser.FormatSpecifiedFunction{ 1500 Type: parser.Token{Token: parser.LTSV, Literal: "ltsv"}, 1501 Path: parser.Identifier{Literal: "table6"}, 1502 }, 1503 Alias: parser.Identifier{Literal: "t"}, 1504 }, 1505 }, 1506 }, 1507 Result: &View{ 1508 Header: NewHeader("t", []string{"f1", "f2", "f3", "f4"}), 1509 RecordSet: []Record{ 1510 NewRecord([]value.Primary{ 1511 value.NewString("value1"), 1512 value.NewString("value2"), 1513 value.NewString("value3"), 1514 value.NewNull(), 1515 }), 1516 NewRecord([]value.Primary{ 1517 value.NewString("value4"), 1518 value.NewString("value5"), 1519 value.NewNull(), 1520 value.NewString("value6"), 1521 }), 1522 }, 1523 FileInfo: &FileInfo{ 1524 Path: "table6.ltsv", 1525 Delimiter: ',', 1526 Format: option.LTSV, 1527 Encoding: text.UTF8, 1528 LineBreak: text.LF, 1529 }, 1530 }, 1531 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1532 {scopeNameAliases: { 1533 "T": strings.ToUpper(GetTestFilePath("table6.ltsv")), 1534 }}, 1535 }, time.Time{}, nil), 1536 }, 1537 { 1538 Name: "LoadView FormatSpecifiedFunction From LTSV File Without Null", 1539 From: parser.FromClause{ 1540 Tables: []parser.QueryExpression{ 1541 parser.Table{ 1542 Object: parser.FormatSpecifiedFunction{ 1543 Type: parser.Token{Token: parser.LTSV, Literal: "ltsv"}, 1544 Path: parser.Identifier{Literal: "table6"}, 1545 Args: []parser.QueryExpression{ 1546 parser.NewStringValue("UTF8"), 1547 parser.NewTernaryValueFromString("true"), 1548 }, 1549 }, 1550 Alias: parser.Identifier{Literal: "t"}, 1551 }, 1552 }, 1553 }, 1554 Result: &View{ 1555 Header: NewHeader("t", []string{"f1", "f2", "f3", "f4"}), 1556 RecordSet: []Record{ 1557 NewRecord([]value.Primary{ 1558 value.NewString("value1"), 1559 value.NewString("value2"), 1560 value.NewString("value3"), 1561 value.NewString(""), 1562 }), 1563 NewRecord([]value.Primary{ 1564 value.NewString("value4"), 1565 value.NewString("value5"), 1566 value.NewString(""), 1567 value.NewString("value6"), 1568 }), 1569 }, 1570 FileInfo: &FileInfo{ 1571 Path: "table6.ltsv", 1572 Delimiter: ',', 1573 Format: option.LTSV, 1574 Encoding: text.UTF8, 1575 LineBreak: text.LF, 1576 }, 1577 }, 1578 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1579 {scopeNameAliases: { 1580 "T": strings.ToUpper(GetTestFilePath("table6.ltsv")), 1581 }}, 1582 }, time.Time{}, nil), 1583 }, 1584 { 1585 Name: "LoadView FormatSpecifiedFunction From LTSV File with UTF-8 BOM", 1586 From: parser.FromClause{ 1587 Tables: []parser.QueryExpression{ 1588 parser.Table{ 1589 Object: parser.FormatSpecifiedFunction{ 1590 Type: parser.Token{Token: parser.LTSV, Literal: "ltsv"}, 1591 Path: parser.Identifier{Literal: "table6_bom"}, 1592 }, 1593 Alias: parser.Identifier{Literal: "t"}, 1594 }, 1595 }, 1596 }, 1597 Result: &View{ 1598 Header: NewHeader("t", []string{"f1", "f2", "f3", "f4"}), 1599 RecordSet: []Record{ 1600 NewRecord([]value.Primary{ 1601 value.NewString("value1"), 1602 value.NewString("value2"), 1603 value.NewString("value3"), 1604 value.NewNull(), 1605 }), 1606 NewRecord([]value.Primary{ 1607 value.NewString("value4"), 1608 value.NewString("value5"), 1609 value.NewNull(), 1610 value.NewString("value6"), 1611 }), 1612 }, 1613 FileInfo: &FileInfo{ 1614 Path: "table6_bom.ltsv", 1615 Delimiter: ',', 1616 Format: option.LTSV, 1617 Encoding: text.UTF8M, 1618 LineBreak: text.LF, 1619 }, 1620 }, 1621 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1622 {scopeNameAliases: { 1623 "T": strings.ToUpper(GetTestFilePath("table6_bom.ltsv")), 1624 }}, 1625 }, time.Time{}, nil), 1626 }, 1627 { 1628 Name: "LoadView FormatSpecifiedFunction From LTSV File Arguments Length Error", 1629 From: parser.FromClause{ 1630 Tables: []parser.QueryExpression{ 1631 parser.Table{ 1632 Object: parser.FormatSpecifiedFunction{ 1633 Type: parser.Token{Token: parser.LTSV, Literal: "ltsv"}, 1634 Path: parser.Identifier{Literal: "table6"}, 1635 Args: []parser.QueryExpression{ 1636 parser.NewStringValue("UTF8"), 1637 parser.NewTernaryValueFromString("true"), 1638 parser.NewStringValue("extra"), 1639 }, 1640 }, 1641 Alias: parser.Identifier{Literal: "t"}, 1642 }, 1643 }, 1644 }, 1645 Error: "table object ltsv takes exactly 3 arguments", 1646 }, 1647 { 1648 Name: "LoadView FormatSpecifiedFunction Invalid Object Type", 1649 From: parser.FromClause{ 1650 Tables: []parser.QueryExpression{ 1651 parser.Table{ 1652 Object: parser.FormatSpecifiedFunction{ 1653 Type: parser.Token{Token: 0, Literal: "invalid"}, 1654 FormatElement: parser.NewStringValue(","), 1655 Path: parser.Identifier{Literal: "table"}, 1656 }, 1657 Alias: parser.Identifier{Literal: "jt"}, 1658 }, 1659 }, 1660 }, 1661 Error: "invalid table object: invalid", 1662 }, 1663 { 1664 Name: "LoadView FormatSpecifiedFunction From Json File Arguments Length Error", 1665 From: parser.FromClause{ 1666 Tables: []parser.QueryExpression{ 1667 parser.Table{ 1668 Object: parser.FormatSpecifiedFunction{ 1669 Type: parser.Token{Token: parser.JSON, Literal: "json"}, 1670 FormatElement: parser.NewStringValue("{}"), 1671 Path: parser.Identifier{Literal: "table"}, 1672 Args: []parser.QueryExpression{ 1673 parser.NewStringValue("SJIS"), 1674 }, 1675 }, 1676 Alias: parser.Identifier{Literal: "jt"}, 1677 }, 1678 }, 1679 }, 1680 Error: "table object json takes exactly 2 arguments", 1681 }, 1682 { 1683 Name: "LoadView File Error", 1684 From: parser.FromClause{ 1685 Tables: []parser.QueryExpression{ 1686 parser.Table{ 1687 Object: parser.Identifier{Literal: "notexist"}, 1688 }, 1689 }, 1690 }, 1691 Error: "file notexist does not exist", 1692 }, 1693 { 1694 Name: "LoadView From File Duplicate Table Name Error", 1695 From: parser.FromClause{ 1696 Tables: []parser.QueryExpression{ 1697 parser.Table{Object: parser.Identifier{Literal: "table1"}, Alias: parser.Identifier{Literal: "t"}}, 1698 parser.Table{Object: parser.Identifier{Literal: "table2"}, Alias: parser.Identifier{Literal: "t"}}, 1699 }, 1700 }, 1701 Error: "table name t is a duplicate", 1702 }, 1703 { 1704 Name: "LoadView From File ForUpdate Duplicate Table Name Error", 1705 From: parser.FromClause{ 1706 Tables: []parser.QueryExpression{ 1707 parser.Table{Object: parser.Identifier{Literal: "table1"}, Alias: parser.Identifier{Literal: "t"}}, 1708 parser.Table{Object: parser.Identifier{Literal: "table2"}, Alias: parser.Identifier{Literal: "t"}}, 1709 }, 1710 }, 1711 ForUpdate: true, 1712 Error: "table name t is a duplicate", 1713 }, 1714 { 1715 Name: "LoadView From File Inline Table", 1716 From: parser.FromClause{ 1717 Tables: []parser.QueryExpression{ 1718 parser.Table{Object: parser.Identifier{Literal: "it"}, Alias: parser.Identifier{Literal: "t"}}, 1719 }, 1720 }, 1721 Scope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1722 { 1723 scopeNameInlineTables: { 1724 "IT": &View{ 1725 Header: NewHeader("it", []string{"c1", "c2", "num"}), 1726 RecordSet: []Record{ 1727 NewRecord([]value.Primary{ 1728 value.NewString("1"), 1729 value.NewString("str1"), 1730 value.NewInteger(1), 1731 }), 1732 NewRecord([]value.Primary{ 1733 value.NewString("2"), 1734 value.NewString("str2"), 1735 value.NewInteger(1), 1736 }), 1737 NewRecord([]value.Primary{ 1738 value.NewString("3"), 1739 value.NewString("str3"), 1740 value.NewInteger(1), 1741 }), 1742 }, 1743 }, 1744 }, 1745 }, 1746 }, time.Time{}, nil), 1747 Result: &View{ 1748 Header: NewHeader("t", []string{"c1", "c2", "num"}), 1749 RecordSet: []Record{ 1750 NewRecord([]value.Primary{ 1751 value.NewString("1"), 1752 value.NewString("str1"), 1753 value.NewInteger(1), 1754 }), 1755 NewRecord([]value.Primary{ 1756 value.NewString("2"), 1757 value.NewString("str2"), 1758 value.NewInteger(1), 1759 }), 1760 NewRecord([]value.Primary{ 1761 value.NewString("3"), 1762 value.NewString("str3"), 1763 value.NewInteger(1), 1764 }), 1765 }, 1766 }, 1767 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1768 { 1769 scopeNameAliases: { 1770 "T": "", 1771 }, 1772 }, 1773 { 1774 scopeNameInlineTables: { 1775 "IT": &View{ 1776 Header: NewHeader("it", []string{"c1", "c2", "num"}), 1777 RecordSet: []Record{ 1778 NewRecord([]value.Primary{ 1779 value.NewString("1"), 1780 value.NewString("str1"), 1781 value.NewInteger(1), 1782 }), 1783 NewRecord([]value.Primary{ 1784 value.NewString("2"), 1785 value.NewString("str2"), 1786 value.NewInteger(1), 1787 }), 1788 NewRecord([]value.Primary{ 1789 value.NewString("3"), 1790 value.NewString("str3"), 1791 value.NewInteger(1), 1792 }), 1793 }, 1794 }, 1795 }, 1796 }, 1797 }, time.Time{}, nil), 1798 }, 1799 { 1800 Name: "LoadView From File Inline Table Duplicate Table Name Error", 1801 From: parser.FromClause{ 1802 Tables: []parser.QueryExpression{ 1803 parser.Table{Object: parser.Identifier{Literal: "table1"}, Alias: parser.Identifier{Literal: "t"}}, 1804 parser.Table{Object: parser.Identifier{Literal: "it"}, Alias: parser.Identifier{Literal: "t"}}, 1805 }, 1806 }, 1807 Scope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1808 { 1809 scopeNameInlineTables: { 1810 "IT": &View{ 1811 Header: NewHeader("it", []string{"c1", "c2", "num"}), 1812 RecordSet: []Record{ 1813 NewRecord([]value.Primary{ 1814 value.NewString("1"), 1815 value.NewString("str1"), 1816 value.NewInteger(1), 1817 }), 1818 NewRecord([]value.Primary{ 1819 value.NewString("2"), 1820 value.NewString("str2"), 1821 value.NewInteger(1), 1822 }), 1823 NewRecord([]value.Primary{ 1824 value.NewString("3"), 1825 value.NewString("str3"), 1826 value.NewInteger(1), 1827 }), 1828 }, 1829 }, 1830 }, 1831 }, 1832 }, time.Time{}, nil), 1833 Error: "table name t is a duplicate", 1834 }, 1835 { 1836 Name: "LoadView SJIS File", 1837 Encoding: text.SJIS, 1838 From: parser.FromClause{ 1839 Tables: []parser.QueryExpression{ 1840 parser.Table{ 1841 Object: parser.Identifier{Literal: "table_sjis"}, 1842 }, 1843 }, 1844 }, 1845 Result: &View{ 1846 Header: NewHeader("table_sjis", []string{"column1", "column2"}), 1847 RecordSet: []Record{ 1848 NewRecord([]value.Primary{ 1849 value.NewString("1"), 1850 value.NewString("日本語"), 1851 }), 1852 NewRecord([]value.Primary{ 1853 value.NewString("2"), 1854 value.NewString("str"), 1855 }), 1856 }, 1857 }, 1858 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1859 {scopeNameAliases: { 1860 "TABLE_SJIS": strings.ToUpper(GetTestFilePath("table_sjis.csv")), 1861 }}, 1862 }, time.Time{}, nil), 1863 }, 1864 { 1865 Name: "LoadView No Header File", 1866 NoHeader: true, 1867 From: parser.FromClause{ 1868 Tables: []parser.QueryExpression{ 1869 parser.Table{ 1870 Object: parser.Identifier{Literal: "table_noheader"}, 1871 }, 1872 }, 1873 }, 1874 Result: &View{ 1875 Header: NewHeader("table_noheader", []string{"c1", "c2"}), 1876 RecordSet: []Record{ 1877 NewRecord([]value.Primary{ 1878 value.NewString("1"), 1879 value.NewString("str1"), 1880 }), 1881 NewRecord([]value.Primary{ 1882 value.NewString("2"), 1883 value.NewString("str2"), 1884 }), 1885 }, 1886 }, 1887 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1888 {scopeNameAliases: { 1889 "TABLE_NOHEADER": strings.ToUpper(GetTestFilePath("table_noheader.csv")), 1890 }}, 1891 }, time.Time{}, nil), 1892 }, 1893 { 1894 Name: "LoadView Multiple File", 1895 From: parser.FromClause{ 1896 Tables: []parser.QueryExpression{ 1897 parser.Table{ 1898 Object: parser.Identifier{Literal: "table1"}, 1899 }, 1900 parser.Table{ 1901 Object: parser.Identifier{Literal: "table2"}, 1902 }, 1903 }, 1904 }, 1905 Result: &View{ 1906 Header: []HeaderField{ 1907 {View: "table1", Column: "column1", Number: 1, IsFromTable: true}, 1908 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 1909 {View: "table2", Column: "column3", Number: 1, IsFromTable: true}, 1910 {View: "table2", Column: "column4", Number: 2, IsFromTable: true}, 1911 }, 1912 RecordSet: []Record{ 1913 NewRecord([]value.Primary{ 1914 value.NewString("1"), 1915 value.NewString("str1"), 1916 value.NewString("2"), 1917 value.NewString("str22"), 1918 }), 1919 NewRecord([]value.Primary{ 1920 value.NewString("1"), 1921 value.NewString("str1"), 1922 value.NewString("3"), 1923 value.NewString("str33"), 1924 }), 1925 NewRecord([]value.Primary{ 1926 value.NewString("1"), 1927 value.NewString("str1"), 1928 value.NewString("4"), 1929 value.NewString("str44"), 1930 }), 1931 NewRecord([]value.Primary{ 1932 value.NewString("2"), 1933 value.NewString("str2"), 1934 value.NewString("2"), 1935 value.NewString("str22"), 1936 }), 1937 NewRecord([]value.Primary{ 1938 value.NewString("2"), 1939 value.NewString("str2"), 1940 value.NewString("3"), 1941 value.NewString("str33"), 1942 }), 1943 NewRecord([]value.Primary{ 1944 value.NewString("2"), 1945 value.NewString("str2"), 1946 value.NewString("4"), 1947 value.NewString("str44"), 1948 }), 1949 NewRecord([]value.Primary{ 1950 value.NewString("3"), 1951 value.NewString("str3"), 1952 value.NewString("2"), 1953 value.NewString("str22"), 1954 }), 1955 NewRecord([]value.Primary{ 1956 value.NewString("3"), 1957 value.NewString("str3"), 1958 value.NewString("3"), 1959 value.NewString("str33"), 1960 }), 1961 NewRecord([]value.Primary{ 1962 value.NewString("3"), 1963 value.NewString("str3"), 1964 value.NewString("4"), 1965 value.NewString("str44"), 1966 }), 1967 }, 1968 }, 1969 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 1970 {scopeNameAliases: { 1971 "TABLE1": strings.ToUpper(GetTestFilePath("table1.csv")), 1972 "TABLE2": strings.ToUpper(GetTestFilePath("table2.csv")), 1973 }}, 1974 }, time.Time{}, nil), 1975 }, 1976 { 1977 Name: "Cross Join", 1978 From: parser.FromClause{ 1979 Tables: []parser.QueryExpression{ 1980 parser.Table{ 1981 Object: parser.Join{ 1982 Table: parser.Table{ 1983 Object: parser.Identifier{Literal: "table1"}, 1984 }, 1985 JoinTable: parser.Table{ 1986 Object: parser.Identifier{Literal: "table2"}, 1987 }, 1988 JoinType: parser.Token{Token: parser.CROSS, Literal: "cross"}, 1989 }, 1990 }, 1991 }, 1992 }, 1993 Result: &View{ 1994 Header: []HeaderField{ 1995 {View: "table1", Column: "column1", Number: 1, IsFromTable: true}, 1996 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 1997 {View: "table2", Column: "column3", Number: 1, IsFromTable: true}, 1998 {View: "table2", Column: "column4", Number: 2, IsFromTable: true}, 1999 }, 2000 RecordSet: []Record{ 2001 NewRecord([]value.Primary{ 2002 value.NewString("1"), 2003 value.NewString("str1"), 2004 value.NewString("2"), 2005 value.NewString("str22"), 2006 }), 2007 NewRecord([]value.Primary{ 2008 value.NewString("1"), 2009 value.NewString("str1"), 2010 value.NewString("3"), 2011 value.NewString("str33"), 2012 }), 2013 NewRecord([]value.Primary{ 2014 value.NewString("1"), 2015 value.NewString("str1"), 2016 value.NewString("4"), 2017 value.NewString("str44"), 2018 }), 2019 NewRecord([]value.Primary{ 2020 value.NewString("2"), 2021 value.NewString("str2"), 2022 value.NewString("2"), 2023 value.NewString("str22"), 2024 }), 2025 NewRecord([]value.Primary{ 2026 value.NewString("2"), 2027 value.NewString("str2"), 2028 value.NewString("3"), 2029 value.NewString("str33"), 2030 }), 2031 NewRecord([]value.Primary{ 2032 value.NewString("2"), 2033 value.NewString("str2"), 2034 value.NewString("4"), 2035 value.NewString("str44"), 2036 }), 2037 NewRecord([]value.Primary{ 2038 value.NewString("3"), 2039 value.NewString("str3"), 2040 value.NewString("2"), 2041 value.NewString("str22"), 2042 }), 2043 NewRecord([]value.Primary{ 2044 value.NewString("3"), 2045 value.NewString("str3"), 2046 value.NewString("3"), 2047 value.NewString("str33"), 2048 }), 2049 NewRecord([]value.Primary{ 2050 value.NewString("3"), 2051 value.NewString("str3"), 2052 value.NewString("4"), 2053 value.NewString("str44"), 2054 }), 2055 }, 2056 }, 2057 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2058 {scopeNameAliases: { 2059 "TABLE1": strings.ToUpper(GetTestFilePath("table1.csv")), 2060 "TABLE2": strings.ToUpper(GetTestFilePath("table2.csv")), 2061 }}, 2062 }, time.Time{}, nil), 2063 }, 2064 { 2065 Name: "Lateral Cross Join", 2066 From: parser.FromClause{ 2067 Tables: []parser.QueryExpression{ 2068 parser.Table{ 2069 Object: parser.Join{ 2070 Table: parser.Table{ 2071 Object: parser.Identifier{Literal: "table1"}, 2072 }, 2073 JoinTable: parser.Table{ 2074 Lateral: parser.Token{Token: parser.LATERAL}, 2075 Object: parser.Subquery{ 2076 Query: parser.SelectQuery{ 2077 SelectEntity: parser.SelectEntity{ 2078 SelectClause: parser.SelectClause{ 2079 Fields: []parser.QueryExpression{ 2080 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column3"}}}, 2081 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column4"}}}, 2082 }, 2083 }, 2084 FromClause: parser.FromClause{ 2085 Tables: []parser.QueryExpression{ 2086 parser.Table{Object: parser.Identifier{Literal: "table2"}}, 2087 }, 2088 }, 2089 WhereClause: parser.WhereClause{ 2090 Filter: parser.Comparison{ 2091 LHS: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 2092 RHS: parser.FieldReference{Column: parser.Identifier{Literal: "column3"}}, 2093 Operator: parser.Token{Token: '=', Literal: "="}, 2094 }, 2095 }, 2096 }, 2097 }, 2098 }, 2099 Alias: parser.Identifier{ 2100 Literal: "t2", 2101 }, 2102 }, 2103 JoinType: parser.Token{Token: parser.CROSS, Literal: "cross"}, 2104 }, 2105 }, 2106 }, 2107 }, 2108 Result: &View{ 2109 Header: []HeaderField{ 2110 {View: "table1", Column: "column1", Number: 1, IsFromTable: true}, 2111 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 2112 {View: "t2", Column: "column3", Number: 1, IsFromTable: true}, 2113 {View: "t2", Column: "column4", Number: 2, IsFromTable: true}, 2114 }, 2115 RecordSet: []Record{ 2116 NewRecord([]value.Primary{ 2117 value.NewString("2"), 2118 value.NewString("str2"), 2119 value.NewString("2"), 2120 value.NewString("str22"), 2121 }), 2122 NewRecord([]value.Primary{ 2123 value.NewString("3"), 2124 value.NewString("str3"), 2125 value.NewString("3"), 2126 value.NewString("str33"), 2127 }), 2128 }, 2129 }, 2130 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2131 {scopeNameAliases: { 2132 "TABLE1": strings.ToUpper(GetTestFilePath("table1.csv")), 2133 }}, 2134 }, time.Time{}, nil), 2135 }, 2136 { 2137 Name: "Inner Join", 2138 From: parser.FromClause{ 2139 Tables: []parser.QueryExpression{ 2140 parser.Table{ 2141 Object: parser.Join{ 2142 Table: parser.Table{ 2143 Object: parser.Identifier{Literal: "table1"}, 2144 }, 2145 JoinTable: parser.Table{ 2146 Object: parser.Identifier{Literal: "table2"}, 2147 }, 2148 Condition: parser.JoinCondition{ 2149 On: parser.Comparison{ 2150 LHS: parser.FieldReference{View: parser.Identifier{Literal: "table1"}, Column: parser.Identifier{Literal: "column1"}}, 2151 RHS: parser.FieldReference{View: parser.Identifier{Literal: "table2"}, Column: parser.Identifier{Literal: "column3"}}, 2152 Operator: parser.Token{Token: '=', Literal: "="}, 2153 }, 2154 }, 2155 }, 2156 }, 2157 }, 2158 }, 2159 Result: &View{ 2160 Header: []HeaderField{ 2161 {View: "table1", Column: "column1", Number: 1, IsFromTable: true}, 2162 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 2163 {View: "table2", Column: "column3", Number: 1, IsFromTable: true}, 2164 {View: "table2", Column: "column4", Number: 2, IsFromTable: true}, 2165 }, 2166 RecordSet: []Record{ 2167 NewRecord([]value.Primary{ 2168 value.NewString("2"), 2169 value.NewString("str2"), 2170 value.NewString("2"), 2171 value.NewString("str22"), 2172 }), 2173 NewRecord([]value.Primary{ 2174 value.NewString("3"), 2175 value.NewString("str3"), 2176 value.NewString("3"), 2177 value.NewString("str33"), 2178 }), 2179 }, 2180 }, 2181 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2182 {scopeNameAliases: { 2183 "TABLE1": strings.ToUpper(GetTestFilePath("table1.csv")), 2184 "TABLE2": strings.ToUpper(GetTestFilePath("table2.csv")), 2185 }}, 2186 }, time.Time{}, nil), 2187 }, 2188 { 2189 Name: "Inner Join Using Condition", 2190 From: parser.FromClause{ 2191 Tables: []parser.QueryExpression{ 2192 parser.Table{ 2193 Object: parser.Join{ 2194 Table: parser.Table{ 2195 Object: parser.Identifier{Literal: "table1"}, 2196 }, 2197 JoinTable: parser.Table{ 2198 Object: parser.Identifier{Literal: "table1b"}, 2199 }, 2200 Condition: parser.JoinCondition{ 2201 Using: []parser.QueryExpression{ 2202 parser.Identifier{Literal: "column1"}, 2203 }, 2204 }, 2205 }, 2206 }, 2207 }, 2208 }, 2209 Result: &View{ 2210 Header: []HeaderField{ 2211 {Column: "column1", IsFromTable: true, IsJoinColumn: true}, 2212 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 2213 {View: "table1b", Column: "column2b", Number: 2, IsFromTable: true}, 2214 }, 2215 RecordSet: []Record{ 2216 NewRecord([]value.Primary{ 2217 value.NewString("2"), 2218 value.NewString("str2"), 2219 value.NewString("str2b"), 2220 }), 2221 NewRecord([]value.Primary{ 2222 value.NewString("3"), 2223 value.NewString("str3"), 2224 value.NewString("str3b"), 2225 }), 2226 }, 2227 }, 2228 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2229 {scopeNameAliases: { 2230 "TABLE1": strings.ToUpper(GetTestFilePath("table1.csv")), 2231 "TABLE1B": strings.ToUpper(GetTestFilePath("table1b.csv")), 2232 }}, 2233 }, time.Time{}, nil), 2234 }, 2235 { 2236 Name: "Outer Join", 2237 From: parser.FromClause{ 2238 Tables: []parser.QueryExpression{ 2239 parser.Table{ 2240 Object: parser.Join{ 2241 Table: parser.Table{ 2242 Object: parser.Identifier{Literal: "table1"}, 2243 }, 2244 JoinTable: parser.Table{ 2245 Object: parser.Identifier{Literal: "table2"}, 2246 }, 2247 Direction: parser.Token{Token: parser.LEFT, Literal: "left"}, 2248 Condition: parser.JoinCondition{ 2249 On: parser.Comparison{ 2250 LHS: parser.FieldReference{View: parser.Identifier{Literal: "table1"}, Column: parser.Identifier{Literal: "column1"}}, 2251 RHS: parser.FieldReference{View: parser.Identifier{Literal: "table2"}, Column: parser.Identifier{Literal: "column3"}}, 2252 Operator: parser.Token{Token: '=', Literal: "="}, 2253 }, 2254 }, 2255 }, 2256 }, 2257 }, 2258 }, 2259 Result: &View{ 2260 Header: []HeaderField{ 2261 {View: "table1", Column: "column1", Number: 1, IsFromTable: true}, 2262 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 2263 {View: "table2", Column: "column3", Number: 1, IsFromTable: true}, 2264 {View: "table2", Column: "column4", Number: 2, IsFromTable: true}, 2265 }, 2266 RecordSet: []Record{ 2267 NewRecord([]value.Primary{ 2268 value.NewString("1"), 2269 value.NewString("str1"), 2270 value.NewNull(), 2271 value.NewNull(), 2272 }), 2273 NewRecord([]value.Primary{ 2274 value.NewString("2"), 2275 value.NewString("str2"), 2276 value.NewString("2"), 2277 value.NewString("str22"), 2278 }), 2279 NewRecord([]value.Primary{ 2280 value.NewString("3"), 2281 value.NewString("str3"), 2282 value.NewString("3"), 2283 value.NewString("str33"), 2284 }), 2285 }, 2286 }, 2287 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2288 {scopeNameAliases: { 2289 "TABLE1": strings.ToUpper(GetTestFilePath("table1.csv")), 2290 "TABLE2": strings.ToUpper(GetTestFilePath("table2.csv")), 2291 }}, 2292 }, time.Time{}, nil), 2293 }, 2294 { 2295 Name: "Outer Join Natural", 2296 From: parser.FromClause{ 2297 Tables: []parser.QueryExpression{ 2298 parser.Table{ 2299 Object: parser.Join{ 2300 Table: parser.Table{ 2301 Object: parser.Identifier{Literal: "table1"}, 2302 }, 2303 JoinTable: parser.Table{ 2304 Object: parser.Identifier{Literal: "table1b"}, 2305 }, 2306 Direction: parser.Token{Token: parser.RIGHT, Literal: "right"}, 2307 Natural: parser.Token{Token: parser.NATURAL, Literal: "natural"}, 2308 }, 2309 }, 2310 }, 2311 }, 2312 Result: &View{ 2313 Header: []HeaderField{ 2314 {Column: "column1", IsFromTable: true, IsJoinColumn: true}, 2315 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 2316 {View: "table1b", Column: "column2b", Number: 2, IsFromTable: true}, 2317 }, 2318 RecordSet: []Record{ 2319 NewRecord([]value.Primary{ 2320 value.NewString("2"), 2321 value.NewString("str2"), 2322 value.NewString("str2b"), 2323 }), 2324 NewRecord([]value.Primary{ 2325 value.NewString("3"), 2326 value.NewString("str3"), 2327 value.NewString("str3b"), 2328 }), 2329 NewRecord([]value.Primary{ 2330 value.NewString("4"), 2331 value.NewNull(), 2332 value.NewString("str4b"), 2333 }), 2334 }, 2335 }, 2336 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2337 {scopeNameAliases: { 2338 "TABLE1": strings.ToUpper(GetTestFilePath("table1.csv")), 2339 "TABLE1B": strings.ToUpper(GetTestFilePath("table1b.csv")), 2340 }}, 2341 }, time.Time{}, nil), 2342 }, 2343 { 2344 Name: "Full Outer Join Natural", 2345 From: parser.FromClause{ 2346 Tables: []parser.QueryExpression{ 2347 parser.Table{ 2348 Object: parser.Join{ 2349 Table: parser.Table{ 2350 Object: parser.Identifier{Literal: "table1"}, 2351 }, 2352 JoinTable: parser.Table{ 2353 Object: parser.Identifier{Literal: "table1b"}, 2354 }, 2355 Direction: parser.Token{Token: parser.FULL, Literal: "full"}, 2356 Natural: parser.Token{Token: parser.NATURAL, Literal: "natural"}, 2357 }, 2358 }, 2359 }, 2360 }, 2361 Result: &View{ 2362 Header: []HeaderField{ 2363 {Column: "column1", IsFromTable: true, IsJoinColumn: true}, 2364 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 2365 {View: "table1b", Column: "column2b", Number: 2, IsFromTable: true}, 2366 }, 2367 RecordSet: []Record{ 2368 NewRecord([]value.Primary{ 2369 value.NewString("1"), 2370 value.NewString("str1"), 2371 value.NewNull(), 2372 }), 2373 NewRecord([]value.Primary{ 2374 value.NewString("2"), 2375 value.NewString("str2"), 2376 value.NewString("str2b"), 2377 }), 2378 NewRecord([]value.Primary{ 2379 value.NewString("3"), 2380 value.NewString("str3"), 2381 value.NewString("str3b"), 2382 }), 2383 NewRecord([]value.Primary{ 2384 value.NewString("4"), 2385 value.NewNull(), 2386 value.NewString("str4b"), 2387 }), 2388 }, 2389 }, 2390 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2391 {scopeNameAliases: { 2392 "TABLE1": strings.ToUpper(GetTestFilePath("table1.csv")), 2393 "TABLE1B": strings.ToUpper(GetTestFilePath("table1b.csv")), 2394 }}, 2395 }, time.Time{}, nil), 2396 }, 2397 { 2398 Name: "Incorrect LATERAL Usage Error", 2399 From: parser.FromClause{ 2400 Tables: []parser.QueryExpression{ 2401 parser.Table{ 2402 Object: parser.Join{ 2403 Table: parser.Table{ 2404 Object: parser.Identifier{Literal: "table1"}, 2405 }, 2406 JoinTable: parser.Table{ 2407 Lateral: parser.Token{Token: parser.LATERAL}, 2408 Object: parser.Subquery{ 2409 Query: parser.SelectQuery{ 2410 SelectEntity: parser.SelectEntity{ 2411 SelectClause: parser.SelectClause{ 2412 Fields: []parser.QueryExpression{ 2413 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column3"}}}, 2414 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column4"}}}, 2415 }, 2416 }, 2417 FromClause: parser.FromClause{ 2418 Tables: []parser.QueryExpression{ 2419 parser.Table{Object: parser.Identifier{Literal: "table2"}}, 2420 }, 2421 }, 2422 WhereClause: parser.WhereClause{ 2423 Filter: parser.Comparison{ 2424 LHS: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 2425 RHS: parser.FieldReference{Column: parser.Identifier{Literal: "column3"}}, 2426 Operator: parser.Token{Token: '=', Literal: "="}, 2427 }, 2428 }, 2429 }, 2430 }, 2431 }, 2432 }, 2433 Direction: parser.Token{Token: parser.FULL, Literal: "full"}, 2434 Natural: parser.Token{Token: parser.NATURAL, Literal: "natural"}, 2435 }, 2436 }, 2437 }, 2438 }, 2439 Error: "LATERAL cannot to be used in a RIGHT or FULL outer join", 2440 }, 2441 { 2442 Name: "Join Left Side Table File Not Exist Error", 2443 From: parser.FromClause{ 2444 Tables: []parser.QueryExpression{ 2445 parser.Table{ 2446 Object: parser.Join{ 2447 Table: parser.Table{ 2448 Object: parser.Identifier{Literal: "notexist"}, 2449 }, 2450 JoinTable: parser.Table{ 2451 Object: parser.Identifier{Literal: "table2"}, 2452 }, 2453 JoinType: parser.Token{Token: parser.CROSS, Literal: "cross"}, 2454 }, 2455 }, 2456 }, 2457 }, 2458 Error: "file notexist does not exist", 2459 }, 2460 { 2461 Name: "Join Right Side Table File Not Exist Error", 2462 From: parser.FromClause{ 2463 Tables: []parser.QueryExpression{ 2464 parser.Table{ 2465 Object: parser.Join{ 2466 Table: parser.Table{ 2467 Object: parser.Identifier{Literal: "table1"}, 2468 }, 2469 JoinTable: parser.Table{ 2470 Object: parser.Identifier{Literal: "notexist"}, 2471 }, 2472 JoinType: parser.Token{Token: parser.CROSS, Literal: "cross"}, 2473 }, 2474 }, 2475 }, 2476 }, 2477 Error: "file notexist does not exist", 2478 }, 2479 { 2480 Name: "LoadView from DATA table function", 2481 From: parser.FromClause{ 2482 Tables: []parser.QueryExpression{ 2483 parser.Table{ 2484 Object: parser.TableFunction{ 2485 Name: "data", 2486 Args: []parser.QueryExpression{ 2487 parser.NewStringValue("c1,c2\n1,a\n2,b\n"), 2488 }, 2489 }, 2490 Alias: parser.Identifier{Literal: "ci"}, 2491 }, 2492 }, 2493 }, 2494 Result: &View{ 2495 Header: NewHeader("ci", []string{"c1", "c2"}), 2496 RecordSet: []Record{ 2497 NewRecord([]value.Primary{ 2498 value.NewString("1"), 2499 value.NewString("a"), 2500 }), 2501 NewRecord([]value.Primary{ 2502 value.NewString("2"), 2503 value.NewString("b"), 2504 }), 2505 }, 2506 FileInfo: &FileInfo{ 2507 Path: "", 2508 Format: option.CSV, 2509 Delimiter: ',', 2510 JsonQuery: "", 2511 Encoding: text.UTF8, 2512 LineBreak: text.LF, 2513 ViewType: ViewTypeStringObject, 2514 }, 2515 }, 2516 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2517 { 2518 scopeNameAliases: { 2519 "CI": "", 2520 }, 2521 }, 2522 }, time.Time{}, nil), 2523 }, 2524 { //TODO 2525 Name: "LoadView Inline Table as FormatSpecifiedFunction", 2526 From: parser.FromClause{ 2527 Tables: []parser.QueryExpression{ 2528 parser.Table{ 2529 Object: parser.FormatSpecifiedFunction{ 2530 Type: parser.Token{Token: parser.CSV, Literal: "csv"}, 2531 FormatElement: parser.NewStringValue(","), 2532 Path: parser.TableFunction{ 2533 Name: "inline", 2534 Args: []parser.QueryExpression{ 2535 parser.NewStringValue("table5"), 2536 }, 2537 }, 2538 Args: []parser.QueryExpression{ 2539 parser.NewStringValue("SJIS"), 2540 parser.NewTernaryValueFromString("true"), 2541 parser.NewTernaryValueFromString("true"), 2542 }, 2543 }, 2544 Alias: parser.Identifier{Literal: "t"}, 2545 }, 2546 }, 2547 }, 2548 Result: &View{ 2549 Header: NewHeader("t", []string{"c1", "c2"}), 2550 RecordSet: []Record{ 2551 NewRecord([]value.Primary{ 2552 value.NewString("1"), 2553 value.NewString("str1"), 2554 }), 2555 NewRecord([]value.Primary{ 2556 value.NewString("2"), 2557 value.NewString(""), 2558 }), 2559 NewRecord([]value.Primary{ 2560 value.NewString("3"), 2561 value.NewString("str3"), 2562 }), 2563 }, 2564 FileInfo: &FileInfo{ 2565 Path: "", 2566 Delimiter: ',', 2567 Format: option.CSV, 2568 Encoding: text.SJIS, 2569 LineBreak: text.LF, 2570 NoHeader: true, 2571 ViewType: ViewTypeInlineTable, 2572 }, 2573 }, 2574 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2575 {scopeNameAliases: { 2576 "T": "", 2577 }}, 2578 }, time.Time{}, nil), 2579 }, 2580 { 2581 Name: "LoadView from Local File as URL", 2582 From: parser.FromClause{ 2583 Tables: []parser.QueryExpression{ 2584 parser.Table{ 2585 Object: parser.Url{ 2586 Raw: "file:./table.json", 2587 }, 2588 Alias: parser.Identifier{Literal: "jt"}, 2589 }, 2590 }, 2591 }, 2592 Result: &View{ 2593 Header: NewHeader("jt", []string{"item1", "item2"}), 2594 RecordSet: []Record{ 2595 NewRecord([]value.Primary{ 2596 value.NewString("value1"), 2597 value.NewFloat(1), 2598 }), 2599 NewRecord([]value.Primary{ 2600 value.NewString("value2"), 2601 value.NewFloat(2), 2602 }), 2603 }, 2604 FileInfo: &FileInfo{ 2605 Path: "table.json", 2606 Format: option.JSON, 2607 Delimiter: ',', 2608 JsonQuery: "", 2609 Encoding: text.UTF8, 2610 LineBreak: text.LF, 2611 ViewType: ViewTypeFile, 2612 }, 2613 }, 2614 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2615 { 2616 scopeNameAliases: { 2617 "JT": strings.ToUpper(GetTestFilePath("table.json")), 2618 }, 2619 }, 2620 }, time.Time{}, nil), 2621 }, 2622 { 2623 Name: "LoadView Json Inline Table", 2624 From: parser.FromClause{ 2625 Tables: []parser.QueryExpression{ 2626 parser.Table{ 2627 Object: parser.FormatSpecifiedFunction{ 2628 Type: parser.Token{Token: parser.JSON_TABLE, Literal: "json_table"}, 2629 FormatElement: parser.NewStringValue("{column1, column2}"), 2630 Path: parser.NewStringValue("[{\"column1\":1, \"column2\":2},{\"column1\":3, \"column2\":4}]"), 2631 }, 2632 Alias: parser.Identifier{Literal: "jt"}, 2633 }, 2634 }, 2635 }, 2636 Result: &View{ 2637 Header: NewHeader("jt", []string{"column1", "column2"}), 2638 RecordSet: []Record{ 2639 NewRecord([]value.Primary{ 2640 value.NewFloat(1), 2641 value.NewFloat(2), 2642 }), 2643 NewRecord([]value.Primary{ 2644 value.NewFloat(3), 2645 value.NewFloat(4), 2646 }), 2647 }, 2648 FileInfo: &FileInfo{ 2649 Path: "", 2650 Format: option.JSON, 2651 Delimiter: ',', 2652 JsonQuery: "{column1, column2}", 2653 Encoding: text.UTF8, 2654 LineBreak: text.LF, 2655 ViewType: ViewTypeStringObject, 2656 }, 2657 }, 2658 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2659 { 2660 scopeNameAliases: { 2661 "JT": "", 2662 }, 2663 }, 2664 }, time.Time{}, nil), 2665 }, 2666 { 2667 Name: "LoadView Json Inline Table Query Evaluation Error", 2668 From: parser.FromClause{ 2669 Tables: []parser.QueryExpression{ 2670 parser.Table{ 2671 Object: parser.FormatSpecifiedFunction{ 2672 Type: parser.Token{Token: parser.JSON_TABLE, Literal: "json_table"}, 2673 FormatElement: parser.FieldReference{Column: parser.Identifier{Literal: "notexists"}}, 2674 Path: parser.NewStringValue("[{\"column1\":1, \"column2\":2},{\"column1\":3, \"column2\":4}]"), 2675 }, 2676 Alias: parser.Identifier{Literal: "jt"}, 2677 }, 2678 }, 2679 }, 2680 Error: "field notexists does not exist", 2681 }, 2682 { 2683 Name: "LoadView Json Inline Table JsonText Evaluation Error", 2684 From: parser.FromClause{ 2685 Tables: []parser.QueryExpression{ 2686 parser.Table{ 2687 Object: parser.FormatSpecifiedFunction{ 2688 Type: parser.Token{Token: parser.JSON_TABLE, Literal: "json_table"}, 2689 FormatElement: parser.NewStringValue("{column1, column2}"), 2690 Path: parser.FieldReference{Column: parser.Identifier{Literal: "notexists"}}, 2691 }, 2692 Alias: parser.Identifier{Literal: "jt"}, 2693 }, 2694 }, 2695 }, 2696 Error: "field notexists does not exist", 2697 }, 2698 { 2699 Name: "LoadView Json Inline Table Query is Null", 2700 From: parser.FromClause{ 2701 Tables: []parser.QueryExpression{ 2702 parser.Table{ 2703 Object: parser.FormatSpecifiedFunction{ 2704 Type: parser.Token{Token: parser.JSON_TABLE, Literal: "json_table"}, 2705 FormatElement: parser.NewNullValue(), 2706 Path: parser.NewStringValue("[{\"column1\":1, \"column2\":2},{\"column1\":3, \"column2\":4}]"), 2707 }, 2708 Alias: parser.Identifier{Literal: "jt"}, 2709 }, 2710 }, 2711 }, 2712 Error: "invalid json query: NULL", 2713 }, 2714 { 2715 Name: "LoadView Json Inline Table JsonText is Null", 2716 From: parser.FromClause{ 2717 Tables: []parser.QueryExpression{ 2718 parser.Table{ 2719 Object: parser.FormatSpecifiedFunction{ 2720 Type: parser.Token{Token: parser.JSON_TABLE, Literal: "json_table"}, 2721 FormatElement: parser.NewStringValue("{column1, column2}"), 2722 Path: parser.NewNullValue(), 2723 }, 2724 Alias: parser.Identifier{Literal: "jt"}, 2725 }, 2726 }, 2727 }, 2728 Error: "inline table is empty", 2729 }, 2730 { 2731 Name: "LoadView Json Inline Table Loading Error", 2732 From: parser.FromClause{ 2733 Tables: []parser.QueryExpression{ 2734 parser.Table{ 2735 Object: parser.FormatSpecifiedFunction{ 2736 Type: parser.Token{Token: parser.JSON_TABLE, Literal: "json_table"}, 2737 FormatElement: parser.NewStringValue("{column1, column2"), 2738 Path: parser.NewStringValue("[{\"column1\":1, \"column2\":2},{\"column1\":3, \"column2\":4}]"), 2739 }, 2740 Alias: parser.Identifier{Literal: "jt"}, 2741 }, 2742 }, 2743 }, 2744 Error: "json loading error: column 17: unexpected termination", 2745 }, 2746 { 2747 Name: "LoadView Json Inline Table From File", 2748 From: parser.FromClause{ 2749 Tables: []parser.QueryExpression{ 2750 parser.Table{ 2751 Object: parser.FormatSpecifiedFunction{ 2752 Type: parser.Token{Token: parser.JSON_INLINE, Literal: "json_inline"}, 2753 FormatElement: parser.NewStringValue("{}"), 2754 Path: parser.Identifier{Literal: "table"}, 2755 }, 2756 Alias: parser.Identifier{Literal: "jt"}, 2757 }, 2758 }, 2759 }, 2760 Result: &View{ 2761 Header: NewHeader("jt", []string{"item1", "item2"}), 2762 RecordSet: []Record{ 2763 NewRecord([]value.Primary{ 2764 value.NewString("value1"), 2765 value.NewFloat(1), 2766 }), 2767 NewRecord([]value.Primary{ 2768 value.NewString("value2"), 2769 value.NewFloat(2), 2770 }), 2771 }, 2772 FileInfo: &FileInfo{ 2773 Path: "", 2774 Format: option.JSON, 2775 Delimiter: ',', 2776 JsonQuery: "{}", 2777 Encoding: text.UTF8, 2778 LineBreak: text.LF, 2779 ViewType: ViewTypeInlineTable, 2780 }, 2781 }, 2782 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2783 { 2784 scopeNameAliases: { 2785 "JT": "", 2786 }, 2787 }, 2788 }, time.Time{}, nil), 2789 }, 2790 { 2791 Name: "LoadView Json Inline Table From File with No Alias", 2792 From: parser.FromClause{ 2793 Tables: []parser.QueryExpression{ 2794 parser.Table{ 2795 Object: parser.FormatSpecifiedFunction{ 2796 Type: parser.Token{Token: parser.JSON_TABLE, Literal: "json_table"}, 2797 FormatElement: parser.NewStringValue("{}"), 2798 Path: parser.Identifier{Literal: "table"}, 2799 }, 2800 }, 2801 }, 2802 }, 2803 Result: &View{ 2804 Header: NewHeader("table", []string{"item1", "item2"}), 2805 RecordSet: []Record{ 2806 NewRecord([]value.Primary{ 2807 value.NewString("value1"), 2808 value.NewFloat(1), 2809 }), 2810 NewRecord([]value.Primary{ 2811 value.NewString("value2"), 2812 value.NewFloat(2), 2813 }), 2814 }, 2815 FileInfo: &FileInfo{ 2816 Path: "", 2817 Format: option.JSON, 2818 Delimiter: ',', 2819 JsonQuery: "{}", 2820 Encoding: text.UTF8, 2821 LineBreak: text.LF, 2822 ViewType: ViewTypeInlineTable, 2823 }, 2824 }, 2825 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2826 { 2827 scopeNameAliases: { 2828 "TABLE": "", 2829 }, 2830 }, 2831 }, time.Time{}, nil), 2832 }, 2833 { 2834 Name: "LoadView Json Inline Table From File Path Error", 2835 From: parser.FromClause{ 2836 Tables: []parser.QueryExpression{ 2837 parser.Table{ 2838 Object: parser.FormatSpecifiedFunction{ 2839 Type: parser.Token{Token: parser.JSON_TABLE, Literal: "json_table"}, 2840 FormatElement: parser.NewStringValue("{}"), 2841 Path: parser.Identifier{Literal: "notexist"}, 2842 }, 2843 Alias: parser.Identifier{Literal: "jt"}, 2844 }, 2845 }, 2846 }, 2847 Error: "file notexist does not exist", 2848 }, 2849 { 2850 Name: "LoadView CSV Inline Table", 2851 From: parser.FromClause{ 2852 Tables: []parser.QueryExpression{ 2853 parser.Table{ 2854 Object: parser.FormatSpecifiedFunction{ 2855 Type: parser.Token{Token: parser.CSV_INLINE, Literal: "csv_inline"}, 2856 FormatElement: parser.NewStringValue(","), 2857 Path: parser.NewStringValue("c1,c2\n1,a\n2,b\n"), 2858 }, 2859 Alias: parser.Identifier{Literal: "ci"}, 2860 }, 2861 }, 2862 }, 2863 Result: &View{ 2864 Header: NewHeader("ci", []string{"c1", "c2"}), 2865 RecordSet: []Record{ 2866 NewRecord([]value.Primary{ 2867 value.NewString("1"), 2868 value.NewString("a"), 2869 }), 2870 NewRecord([]value.Primary{ 2871 value.NewString("2"), 2872 value.NewString("b"), 2873 }), 2874 }, 2875 FileInfo: &FileInfo{ 2876 Path: "", 2877 Format: option.CSV, 2878 Delimiter: ',', 2879 JsonQuery: "", 2880 Encoding: text.UTF8, 2881 LineBreak: text.LF, 2882 ViewType: ViewTypeStringObject, 2883 }, 2884 }, 2885 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2886 { 2887 scopeNameAliases: { 2888 "CI": "", 2889 }, 2890 }, 2891 }, time.Time{}, nil), 2892 }, 2893 { 2894 Name: "LoadView Subquery", 2895 From: parser.FromClause{ 2896 Tables: []parser.QueryExpression{ 2897 parser.Table{ 2898 Object: parser.Subquery{ 2899 Query: parser.SelectQuery{ 2900 SelectEntity: parser.SelectEntity{ 2901 SelectClause: parser.SelectClause{ 2902 Fields: []parser.QueryExpression{ 2903 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 2904 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 2905 }, 2906 }, 2907 FromClause: parser.FromClause{ 2908 Tables: []parser.QueryExpression{ 2909 parser.Table{Object: parser.Identifier{Literal: "table1"}}, 2910 }, 2911 }, 2912 }, 2913 }, 2914 }, 2915 }, 2916 }, 2917 }, 2918 Result: &View{ 2919 Header: NewHeader("table1", []string{"column1", "column2"}), 2920 RecordSet: []Record{ 2921 NewRecord([]value.Primary{ 2922 value.NewString("1"), 2923 value.NewString("str1"), 2924 }), 2925 NewRecord([]value.Primary{ 2926 value.NewString("2"), 2927 value.NewString("str2"), 2928 }), 2929 NewRecord([]value.Primary{ 2930 value.NewString("3"), 2931 value.NewString("str3"), 2932 }), 2933 }, 2934 }, 2935 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{{}}, time.Time{}, nil), 2936 }, 2937 { 2938 Name: "LoadView Subquery with Table Name Alias", 2939 From: parser.FromClause{ 2940 Tables: []parser.QueryExpression{ 2941 parser.Table{ 2942 Object: parser.Subquery{ 2943 Query: parser.SelectQuery{ 2944 SelectEntity: parser.SelectEntity{ 2945 SelectClause: parser.SelectClause{ 2946 Fields: []parser.QueryExpression{ 2947 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 2948 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 2949 }, 2950 }, 2951 FromClause: parser.FromClause{ 2952 Tables: []parser.QueryExpression{ 2953 parser.Table{Object: parser.Identifier{Literal: "table1"}}, 2954 }, 2955 }, 2956 }, 2957 }, 2958 }, 2959 Alias: parser.Identifier{Literal: "alias"}, 2960 }, 2961 }, 2962 }, 2963 Result: &View{ 2964 Header: NewHeader("alias", []string{"column1", "column2"}), 2965 RecordSet: []Record{ 2966 NewRecord([]value.Primary{ 2967 value.NewString("1"), 2968 value.NewString("str1"), 2969 }), 2970 NewRecord([]value.Primary{ 2971 value.NewString("2"), 2972 value.NewString("str2"), 2973 }), 2974 NewRecord([]value.Primary{ 2975 value.NewString("3"), 2976 value.NewString("str3"), 2977 }), 2978 }, 2979 }, 2980 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 2981 { 2982 scopeNameAliases: { 2983 "ALIAS": "", 2984 }, 2985 }, 2986 }, time.Time{}, nil), 2987 }, 2988 { 2989 Name: "LoadView Subquery Duplicate Table Name Error", 2990 From: parser.FromClause{ 2991 Tables: []parser.QueryExpression{ 2992 parser.Table{Object: parser.Identifier{Literal: "table1"}, Alias: parser.Identifier{Literal: "t"}}, 2993 parser.Table{ 2994 Object: parser.Subquery{ 2995 Query: parser.SelectQuery{ 2996 SelectEntity: parser.SelectEntity{ 2997 SelectClause: parser.SelectClause{ 2998 Fields: []parser.QueryExpression{ 2999 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 3000 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 3001 }, 3002 }, 3003 FromClause: parser.FromClause{ 3004 Tables: []parser.QueryExpression{ 3005 parser.Table{Object: parser.Identifier{Literal: "table1"}}, 3006 }, 3007 }, 3008 }, 3009 }, 3010 }, 3011 Alias: parser.Identifier{Literal: "t"}, 3012 }, 3013 }, 3014 }, 3015 Error: "table name t is a duplicate", 3016 }, 3017 { 3018 Name: "LoadView CSV Parse Error", 3019 From: parser.FromClause{ 3020 Tables: []parser.QueryExpression{ 3021 parser.Table{ 3022 Object: parser.Identifier{Literal: "table_broken.csv"}, 3023 }, 3024 }, 3025 }, 3026 Error: fmt.Sprintf("data parse error in %s: line 3, column 7: wrong number of fields in line", GetTestFilePath("table_broken.csv")), 3027 }, 3028 { 3029 Name: "Allow Uneven Field Length", 3030 From: parser.FromClause{ 3031 Tables: []parser.QueryExpression{ 3032 parser.Table{ 3033 Object: parser.Identifier{Literal: "table_broken.csv"}, 3034 }, 3035 }, 3036 }, 3037 AllowUnevenFields: true, 3038 Result: &View{ 3039 Header: NewHeader("table_broken", []string{"column1", "column2", "__@3__"}), 3040 RecordSet: []Record{ 3041 NewRecord([]value.Primary{ 3042 value.NewString("1"), 3043 value.NewString("str1"), 3044 value.NewNull(), 3045 }), 3046 NewRecord([]value.Primary{ 3047 value.NewString("2"), 3048 value.NewString("str2"), 3049 value.NewString("str2"), 3050 }), 3051 NewRecord([]value.Primary{ 3052 value.NewString("3"), 3053 value.NewString("str3"), 3054 value.NewNull(), 3055 }), 3056 }, 3057 FileInfo: &FileInfo{ 3058 Path: "table_broken.csv", 3059 Delimiter: ',', 3060 Encoding: text.UTF8, 3061 LineBreak: text.LF, 3062 }, 3063 }, 3064 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 3065 {scopeNameAliases: { 3066 "TABLE_BROKEN": strings.ToUpper(GetTestFilePath("table_broken.csv")), 3067 }}, 3068 }, time.Time{}, nil), 3069 }, 3070 { 3071 Name: "Allow Uneven Field Length without Null", 3072 From: parser.FromClause{ 3073 Tables: []parser.QueryExpression{ 3074 parser.Table{ 3075 Object: parser.Identifier{Literal: "table_broken.csv"}, 3076 }, 3077 }, 3078 }, 3079 AllowUnevenFields: true, 3080 WithoutNull: true, 3081 Result: &View{ 3082 Header: NewHeader("table_broken", []string{"column1", "column2", "__@3__"}), 3083 RecordSet: []Record{ 3084 NewRecord([]value.Primary{ 3085 value.NewString("1"), 3086 value.NewString("str1"), 3087 value.NewString(""), 3088 }), 3089 NewRecord([]value.Primary{ 3090 value.NewString("2"), 3091 value.NewString("str2"), 3092 value.NewString("str2"), 3093 }), 3094 NewRecord([]value.Primary{ 3095 value.NewString("3"), 3096 value.NewString("str3"), 3097 value.NewString(""), 3098 }), 3099 }, 3100 FileInfo: &FileInfo{ 3101 Path: "table_broken.csv", 3102 Delimiter: ',', 3103 Encoding: text.UTF8, 3104 LineBreak: text.LF, 3105 }, 3106 }, 3107 ResultScope: GenerateReferenceScope(nil, []map[string]map[string]interface{}{ 3108 {scopeNameAliases: { 3109 "TABLE_BROKEN": strings.ToUpper(GetTestFilePath("table_broken.csv")), 3110 }}, 3111 }, time.Time{}, nil), 3112 }, 3113 { 3114 Name: "Inner Join Join Error", 3115 From: parser.FromClause{ 3116 Tables: []parser.QueryExpression{ 3117 parser.Table{ 3118 Object: parser.Join{ 3119 Table: parser.Table{ 3120 Object: parser.Identifier{Literal: "table1"}, 3121 }, 3122 JoinTable: parser.Table{ 3123 Object: parser.Identifier{Literal: "table2"}, 3124 }, 3125 Condition: parser.JoinCondition{ 3126 On: parser.Comparison{ 3127 LHS: parser.FieldReference{View: parser.Identifier{Literal: "table1"}, Column: parser.Identifier{Literal: "notexist"}}, 3128 RHS: parser.FieldReference{View: parser.Identifier{Literal: "table2"}, Column: parser.Identifier{Literal: "column3"}}, 3129 Operator: parser.Token{Token: '=', Literal: "="}, 3130 }, 3131 }, 3132 }, 3133 }, 3134 }, 3135 }, 3136 Error: "field table1.notexist does not exist", 3137 }, 3138 { 3139 Name: "Outer Join Join Error", 3140 From: parser.FromClause{ 3141 Tables: []parser.QueryExpression{ 3142 parser.Table{ 3143 Object: parser.Join{ 3144 Table: parser.Table{ 3145 Object: parser.Identifier{Literal: "table1"}, 3146 }, 3147 JoinTable: parser.Table{ 3148 Object: parser.Identifier{Literal: "table2"}, 3149 }, 3150 Direction: parser.Token{Token: parser.LEFT, Literal: "left"}, 3151 Condition: parser.JoinCondition{ 3152 On: parser.Comparison{ 3153 LHS: parser.FieldReference{View: parser.Identifier{Literal: "table1"}, Column: parser.Identifier{Literal: "column1"}}, 3154 RHS: parser.FieldReference{View: parser.Identifier{Literal: "table2"}, Column: parser.Identifier{Literal: "notexist"}}, 3155 Operator: parser.Token{Token: '=', Literal: "="}, 3156 }, 3157 }, 3158 }, 3159 }, 3160 }, 3161 }, 3162 Error: "field table2.notexist does not exist", 3163 }, 3164 { 3165 Name: "Inner Join Using Condition Error", 3166 From: parser.FromClause{ 3167 Tables: []parser.QueryExpression{ 3168 parser.Table{ 3169 Object: parser.Join{ 3170 Table: parser.Table{ 3171 Object: parser.Identifier{Literal: "table1"}, 3172 }, 3173 JoinTable: parser.Table{ 3174 Object: parser.Identifier{Literal: "table1b"}, 3175 }, 3176 Condition: parser.JoinCondition{ 3177 Using: []parser.QueryExpression{ 3178 parser.Identifier{Literal: "notexist"}, 3179 }, 3180 }, 3181 }, 3182 }, 3183 }, 3184 }, 3185 Error: "field notexist does not exist", 3186 }, 3187 } 3188 3189 func TestLoadView(t *testing.T) { 3190 defer func() { 3191 _ = TestTx.ReleaseResources() 3192 _ = TestTx.CachedViews.Clean(TestTx.FileContainer) 3193 _ = TestTx.Session.SetStdin(os.Stdin) 3194 initFlag(TestTx.Flags) 3195 }() 3196 3197 TestTx.Flags.Repository = TestDir 3198 ctx := context.Background() 3199 3200 for _, v := range loadViewTests { 3201 TestTx.UnlockStdin() 3202 _ = TestTx.CachedViews.Clean(TestTx.FileContainer) 3203 3204 _ = TestTx.Session.SetStdin(os.Stdin) 3205 TestTx.Flags.ImportOptions.Format = v.ImportFormat 3206 TestTx.Flags.ImportOptions.Delimiter = ',' 3207 if v.Delimiter != 0 { 3208 TestTx.Flags.ImportOptions.Delimiter = v.Delimiter 3209 } 3210 TestTx.Flags.ImportOptions.AllowUnevenFields = v.AllowUnevenFields 3211 TestTx.Flags.ImportOptions.DelimiterPositions = v.DelimiterPositions 3212 TestTx.Flags.ImportOptions.SingleLine = v.SingleLine 3213 TestTx.Flags.ImportOptions.JsonQuery = v.JsonQuery 3214 TestTx.Flags.ImportOptions.NoHeader = v.NoHeader 3215 TestTx.Flags.ImportOptions.WithoutNull = v.WithoutNull 3216 if v.Encoding != text.AUTO { 3217 TestTx.Flags.ImportOptions.Encoding = v.Encoding 3218 } else { 3219 TestTx.Flags.ImportOptions.Encoding = text.UTF8 3220 } 3221 3222 if 0 < len(v.Stdin) { 3223 _ = TestTx.Session.SetStdin(NewInput(strings.NewReader(v.Stdin))) 3224 } else { 3225 _ = TestTx.Session.SetStdin(nil) 3226 } 3227 3228 if v.Scope == nil { 3229 v.Scope = NewReferenceScope(TestTx) 3230 } 3231 3232 queryScope := v.Scope.CreateNode() 3233 view, err := LoadView(ctx, queryScope, v.From.Tables, v.ForUpdate, v.UseInternalId) 3234 if v.TestCache { 3235 queryScope.nodes[len(queryScope.nodes)-1].Clear() 3236 view, err = LoadView(ctx, queryScope, v.From.Tables, v.ForUpdate, v.UseInternalId) 3237 } 3238 3239 if err != nil { 3240 if len(v.Error) < 1 { 3241 t.Errorf("%s: unexpected error %q", v.Name, err) 3242 } else if err.Error() != v.Error { 3243 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 3244 } 3245 continue 3246 } 3247 if 0 < len(v.Error) { 3248 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 3249 continue 3250 } 3251 3252 if v.Result.FileInfo != nil { 3253 if filepath.Base(view.FileInfo.Path) != filepath.Base(v.Result.FileInfo.Path) { 3254 t.Errorf("%s: FileInfo.Path = %q, want %q", v.Name, filepath.Base(view.FileInfo.Path), filepath.Base(v.Result.FileInfo.Path)) 3255 } 3256 if view.FileInfo.Format != v.Result.FileInfo.Format { 3257 t.Errorf("%s: FileInfo.Format = %s, want %s", v.Name, view.FileInfo.Format, v.Result.FileInfo.Format) 3258 } 3259 if view.FileInfo.Delimiter != v.Result.FileInfo.Delimiter { 3260 t.Errorf("%s: FileInfo.Delimiter = %q, want %q", v.Name, view.FileInfo.Delimiter, v.Result.FileInfo.Delimiter) 3261 } 3262 if !reflect.DeepEqual(view.FileInfo.DelimiterPositions, v.Result.FileInfo.DelimiterPositions) { 3263 t.Errorf("%s: FileInfo.DelimiterPositions = %v, want %v", v.Name, view.FileInfo.DelimiterPositions, v.Result.FileInfo.DelimiterPositions) 3264 } 3265 if view.FileInfo.JsonQuery != v.Result.FileInfo.JsonQuery { 3266 t.Errorf("%s: FileInfo.JsonQuery = %q, want %q", v.Name, view.FileInfo.JsonQuery, v.Result.FileInfo.JsonQuery) 3267 } 3268 if view.FileInfo.Encoding != v.Result.FileInfo.Encoding { 3269 t.Errorf("%s: FileInfo.Encoding = %s, want %s", v.Name, view.FileInfo.Encoding, v.Result.FileInfo.Encoding) 3270 } 3271 if view.FileInfo.LineBreak != v.Result.FileInfo.LineBreak { 3272 t.Errorf("%s: FileInfo.LineBreak = %s, want %s", v.Name, view.FileInfo.LineBreak, v.Result.FileInfo.LineBreak) 3273 } 3274 if view.FileInfo.NoHeader != v.Result.FileInfo.NoHeader { 3275 t.Errorf("%s: FileInfo.NoHeader = %t, want %t", v.Name, view.FileInfo.NoHeader, v.Result.FileInfo.NoHeader) 3276 } 3277 if view.FileInfo.PrettyPrint != v.Result.FileInfo.PrettyPrint { 3278 t.Errorf("%s: FileInfo.PrettyPrint = %t, want %t", v.Name, view.FileInfo.PrettyPrint, v.Result.FileInfo.PrettyPrint) 3279 } 3280 if view.FileInfo.ForUpdate != v.Result.FileInfo.ForUpdate { 3281 t.Errorf("%s: FileInfo.ForUpdate = %t, want %t", v.Name, view.FileInfo.ForUpdate, v.Result.FileInfo.ForUpdate) 3282 } 3283 if view.FileInfo.ViewType != v.Result.FileInfo.ViewType { 3284 t.Errorf("%s: FileInfo.ViewType = %d, want %d", v.Name, view.FileInfo.ViewType, v.Result.FileInfo.ViewType) 3285 } 3286 } 3287 if view.FileInfo != nil { 3288 _ = TestTx.FileContainer.Close(view.FileInfo.Handler) 3289 view.FileInfo = nil 3290 } 3291 v.Result.FileInfo = nil 3292 3293 if v.ResultScope == nil { 3294 v.ResultScope = NewReferenceScope(TestTx).CreateNode() 3295 } 3296 3297 if !NodeScopeListEqual(queryScope.nodes, v.ResultScope.nodes) { 3298 t.Errorf("%s: node list = %v, want %v", v.Name, queryScope.nodes, v.ResultScope.nodes) 3299 } 3300 for i := range queryScope.Blocks { 3301 if !reflect.DeepEqual(queryScope.Blocks[i].TemporaryTables.Keys(), v.ResultScope.Blocks[i].TemporaryTables.Keys()) { 3302 t.Errorf("%s: temp view list = %v, want %v", v.Name, queryScope.Blocks[i].TemporaryTables.Keys(), v.ResultScope.Blocks[i].TemporaryTables.Keys()) 3303 } 3304 } 3305 3306 if !reflect.DeepEqual(view, v.Result) { 3307 t.Errorf("%s: \n result = %v,\n expect = %v", v.Name, view, v.Result) 3308 } 3309 } 3310 }