github.com/mithrandie/csvq@v1.18.1/lib/query/view_test.go (about) 1 package query 2 3 import ( 4 "context" 5 "reflect" 6 "testing" 7 "time" 8 9 "github.com/mithrandie/csvq/lib/parser" 10 "github.com/mithrandie/csvq/lib/value" 11 ) 12 13 func TestNewViewFromGroupedRecord(t *testing.T) { 14 fr := ReferenceRecord{ 15 view: &View{ 16 Header: NewHeaderWithId("table1", []string{"column1", "column2"}), 17 RecordSet: []Record{ 18 { 19 NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(2), value.NewInteger(3)}), 20 NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(2), value.NewInteger(3)}), 21 NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str2"), value.NewString("str3")}), 22 }, 23 }, 24 }, 25 recordIndex: 0, 26 cache: NewFieldIndexCache(10, LimitToUseFieldIndexSliceChache), 27 } 28 expect := &View{ 29 Header: NewHeaderWithId("table1", []string{"column1", "column2"}), 30 RecordSet: []Record{ 31 {NewCell(value.NewInteger(1)), NewCell(value.NewInteger(1)), NewCell(value.NewString("str1"))}, 32 {NewCell(value.NewInteger(2)), NewCell(value.NewInteger(2)), NewCell(value.NewString("str2"))}, 33 {NewCell(value.NewInteger(3)), NewCell(value.NewInteger(3)), NewCell(value.NewString("str3"))}, 34 }, 35 } 36 37 result, _ := NewViewFromGroupedRecord(context.Background(), TestTx.Flags, fr) 38 if !reflect.DeepEqual(result, expect) { 39 t.Errorf("result = %v, want %v", result, expect) 40 } 41 } 42 43 var viewWhereTests = []struct { 44 Name string 45 CPU int 46 View *View 47 Where parser.WhereClause 48 Result RecordSet 49 Error string 50 }{ 51 { 52 Name: "Where", 53 View: &View{ 54 Header: NewHeaderWithId("table1", []string{"column1", "column2"}), 55 RecordSet: RecordSet{ 56 NewRecordWithId(1, []value.Primary{ 57 value.NewString("1"), 58 value.NewString("str1"), 59 }), 60 NewRecordWithId(2, []value.Primary{ 61 value.NewString("2"), 62 value.NewString("str2"), 63 }), 64 NewRecordWithId(3, []value.Primary{ 65 value.NewString("3"), 66 value.NewString("str3"), 67 }), 68 }, 69 }, 70 Where: parser.WhereClause{ 71 Filter: parser.Comparison{ 72 LHS: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 73 RHS: parser.NewIntegerValueFromString("2"), 74 Operator: parser.Token{Token: '=', Literal: "="}, 75 }, 76 }, 77 Result: RecordSet{ 78 NewRecordWithId(2, []value.Primary{ 79 value.NewString("2"), 80 value.NewString("str2"), 81 }), 82 }, 83 }, 84 { 85 Name: "Where in Multi Threading", 86 CPU: 3, 87 View: &View{ 88 Header: NewHeaderWithId("table1", []string{"column1", "column2"}), 89 RecordSet: RecordSet{ 90 NewRecordWithId(1, []value.Primary{ 91 value.NewString("1"), 92 value.NewString("str1"), 93 }), 94 NewRecordWithId(2, []value.Primary{ 95 value.NewString("2"), 96 value.NewString("str2"), 97 }), 98 NewRecordWithId(3, []value.Primary{ 99 value.NewString("3"), 100 value.NewString("str3"), 101 }), 102 }, 103 }, 104 Where: parser.WhereClause{ 105 Filter: parser.Comparison{ 106 LHS: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 107 RHS: parser.NewIntegerValueFromString("2"), 108 Operator: parser.Token{Token: '=', Literal: "="}, 109 }, 110 }, 111 Result: RecordSet{ 112 NewRecordWithId(2, []value.Primary{ 113 value.NewString("2"), 114 value.NewString("str2"), 115 }), 116 }, 117 }, 118 { 119 Name: "Where Filter Error", 120 View: &View{ 121 Header: NewHeaderWithId("table1", []string{"column1", "column2"}), 122 RecordSet: []Record{ 123 NewRecordWithId(1, []value.Primary{ 124 value.NewString("1"), 125 value.NewString("str1"), 126 }), 127 NewRecordWithId(2, []value.Primary{ 128 value.NewString("2"), 129 value.NewString("str2"), 130 }), 131 NewRecordWithId(3, []value.Primary{ 132 value.NewString("3"), 133 value.NewString("str3"), 134 }), 135 }, 136 }, 137 Where: parser.WhereClause{ 138 Filter: parser.Comparison{ 139 LHS: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 140 RHS: parser.NewIntegerValueFromString("2"), 141 Operator: parser.Token{Token: '=', Literal: "="}, 142 }, 143 }, 144 Error: "field notexist does not exist", 145 }, 146 } 147 148 func TestView_Where(t *testing.T) { 149 defer initFlag(TestTx.Flags) 150 151 scope := NewReferenceScope(TestTx) 152 ctx := context.Background() 153 for _, v := range viewWhereTests { 154 TestTx.Flags.CPU = 1 155 if v.CPU != 0 { 156 TestTx.Flags.CPU = v.CPU 157 } 158 159 err := v.View.Where(ctx, scope, v.Where) 160 if err != nil { 161 if len(v.Error) < 1 { 162 t.Errorf("%s: unexpected error %q", v.Name, err) 163 } else if err.Error() != v.Error { 164 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 165 } 166 continue 167 } 168 if 0 < len(v.Error) { 169 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 170 continue 171 } 172 if !reflect.DeepEqual(v.View.RecordSet, v.Result) { 173 t.Errorf("%s: result = %s, want %s", v.Name, v.View.RecordSet, v.Result) 174 } 175 } 176 } 177 178 var viewGroupByTests = []struct { 179 Name string 180 View *View 181 GroupBy parser.GroupByClause 182 Result *View 183 IsGrouped bool 184 GroupItems []string 185 Error string 186 }{ 187 { 188 Name: "Group By", 189 View: &View{ 190 Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}), 191 RecordSet: []Record{ 192 NewRecordWithId(1, []value.Primary{ 193 value.NewString("1"), 194 value.NewString("str1"), 195 value.NewString("group1"), 196 }), 197 NewRecordWithId(2, []value.Primary{ 198 value.NewString("2"), 199 value.NewString("str2"), 200 value.NewString("group2"), 201 }), 202 NewRecordWithId(3, []value.Primary{ 203 value.NewString("3"), 204 value.NewString("str3"), 205 value.NewString("group1"), 206 }), 207 NewRecordWithId(4, []value.Primary{ 208 value.NewString("4"), 209 value.NewString("str4"), 210 value.NewString("group2"), 211 }), 212 }, 213 }, 214 GroupBy: parser.GroupByClause{ 215 Items: []parser.QueryExpression{ 216 parser.FieldReference{Column: parser.Identifier{Literal: "column3"}}, 217 }, 218 }, 219 Result: &View{ 220 Header: []HeaderField{ 221 { 222 View: "table1", 223 Column: InternalIdColumn, 224 }, 225 { 226 View: "table1", 227 Column: "column1", 228 Number: 1, 229 IsFromTable: true, 230 }, 231 { 232 View: "table1", 233 Column: "column2", 234 Number: 2, 235 IsFromTable: true, 236 }, 237 { 238 View: "table1", 239 Column: "column3", 240 Number: 3, 241 IsFromTable: true, 242 IsGroupKey: true, 243 }, 244 }, 245 RecordSet: []Record{ 246 { 247 NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(3)}), 248 NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("3")}), 249 NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str3")}), 250 NewGroupCell([]value.Primary{value.NewString("group1"), value.NewString("group1")}), 251 }, 252 { 253 NewGroupCell([]value.Primary{value.NewInteger(2), value.NewInteger(4)}), 254 NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}), 255 NewGroupCell([]value.Primary{value.NewString("str2"), value.NewString("str4")}), 256 NewGroupCell([]value.Primary{value.NewString("group2"), value.NewString("group2")}), 257 }, 258 }, 259 isGrouped: true, 260 }, 261 }, 262 { 263 Name: "Group By With ColumnNumber", 264 View: &View{ 265 Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}), 266 RecordSet: []Record{ 267 NewRecordWithId(1, []value.Primary{ 268 value.NewString("1"), 269 value.NewString("str1"), 270 value.NewString("group1"), 271 }), 272 NewRecordWithId(2, []value.Primary{ 273 value.NewString("2"), 274 value.NewString("str2"), 275 value.NewString("group2"), 276 }), 277 NewRecordWithId(3, []value.Primary{ 278 value.NewString("3"), 279 value.NewString("str3"), 280 value.NewString("group1"), 281 }), 282 NewRecordWithId(4, []value.Primary{ 283 value.NewString("4"), 284 value.NewString("str4"), 285 value.NewString("group2"), 286 }), 287 }, 288 }, 289 GroupBy: parser.GroupByClause{ 290 Items: []parser.QueryExpression{ 291 parser.ColumnNumber{View: parser.Identifier{Literal: "table1"}, Number: value.NewInteger(3)}, 292 }, 293 }, 294 Result: &View{ 295 Header: []HeaderField{ 296 { 297 View: "table1", 298 Column: InternalIdColumn, 299 }, 300 { 301 View: "table1", 302 Column: "column1", 303 Number: 1, 304 IsFromTable: true, 305 }, 306 { 307 View: "table1", 308 Column: "column2", 309 Number: 2, 310 IsFromTable: true, 311 }, 312 { 313 View: "table1", 314 Column: "column3", 315 Number: 3, 316 IsFromTable: true, 317 IsGroupKey: true, 318 }, 319 }, 320 RecordSet: []Record{ 321 { 322 NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(3)}), 323 NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("3")}), 324 NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str3")}), 325 NewGroupCell([]value.Primary{value.NewString("group1"), value.NewString("group1")}), 326 }, 327 { 328 NewGroupCell([]value.Primary{value.NewInteger(2), value.NewInteger(4)}), 329 NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}), 330 NewGroupCell([]value.Primary{value.NewString("str2"), value.NewString("str4")}), 331 NewGroupCell([]value.Primary{value.NewString("group2"), value.NewString("group2")}), 332 }, 333 }, 334 isGrouped: true, 335 }, 336 }, 337 { 338 Name: "Group By Evaluation Error", 339 View: &View{ 340 Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}), 341 RecordSet: []Record{ 342 NewRecordWithId(1, []value.Primary{ 343 value.NewString("1"), 344 value.NewString("str1"), 345 value.NewString("group1"), 346 }), 347 NewRecordWithId(2, []value.Primary{ 348 value.NewString("2"), 349 value.NewString("str2"), 350 value.NewString("group2"), 351 }), 352 NewRecordWithId(3, []value.Primary{ 353 value.NewString("3"), 354 value.NewString("str3"), 355 value.NewString("group1"), 356 }), 357 NewRecordWithId(4, []value.Primary{ 358 value.NewString("4"), 359 value.NewString("str4"), 360 value.NewString("group2"), 361 }), 362 }, 363 }, 364 GroupBy: parser.GroupByClause{ 365 Items: []parser.QueryExpression{ 366 parser.ColumnNumber{View: parser.Identifier{Literal: "table1"}, Number: value.NewInteger(0)}, 367 }, 368 }, 369 Error: "field table1.0 does not exist", 370 }, 371 { 372 Name: "Group By Empty Record", 373 View: &View{ 374 Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}), 375 RecordSet: []Record{}, 376 }, 377 GroupBy: parser.GroupByClause{ 378 Items: []parser.QueryExpression{ 379 parser.FieldReference{Column: parser.Identifier{Literal: "column3"}}, 380 }, 381 }, 382 Result: &View{ 383 Header: []HeaderField{ 384 { 385 View: "table1", 386 Column: InternalIdColumn, 387 }, 388 { 389 View: "table1", 390 Column: "column1", 391 Number: 1, 392 IsFromTable: true, 393 }, 394 { 395 View: "table1", 396 Column: "column2", 397 Number: 2, 398 IsFromTable: true, 399 }, 400 { 401 View: "table1", 402 Column: "column3", 403 Number: 3, 404 IsFromTable: true, 405 IsGroupKey: true, 406 }, 407 }, 408 RecordSet: []Record{}, 409 isGrouped: true, 410 }, 411 }, 412 { 413 Name: "Group By Empty Record with No Condition", 414 View: &View{ 415 Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}), 416 RecordSet: []Record{}, 417 }, 418 GroupBy: parser.GroupByClause{ 419 Items: nil, 420 }, 421 Result: &View{ 422 Header: []HeaderField{ 423 { 424 View: "table1", 425 Column: InternalIdColumn, 426 }, 427 { 428 View: "table1", 429 Column: "column1", 430 Number: 1, 431 IsFromTable: true, 432 }, 433 { 434 View: "table1", 435 Column: "column2", 436 Number: 2, 437 IsFromTable: true, 438 }, 439 { 440 View: "table1", 441 Column: "column3", 442 Number: 3, 443 IsFromTable: true, 444 }, 445 }, 446 RecordSet: []Record{}, 447 isGrouped: true, 448 }, 449 }, 450 } 451 452 func TestView_GroupBy(t *testing.T) { 453 scope := NewReferenceScope(TestTx) 454 ctx := context.Background() 455 for _, v := range viewGroupByTests { 456 err := v.View.GroupBy(ctx, scope, v.GroupBy) 457 if err != nil { 458 if len(v.Error) < 1 { 459 t.Errorf("%s: unexpected error %q", v.Name, err) 460 } else if err.Error() != v.Error { 461 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 462 } 463 continue 464 } 465 if 0 < len(v.Error) { 466 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 467 continue 468 } 469 if !reflect.DeepEqual(v.View, v.Result) { 470 t.Errorf("%s: result = %v, want %v", v.Name, v.View, v.Result) 471 } 472 } 473 } 474 475 var viewHavingTests = []struct { 476 Name string 477 View *View 478 Having parser.HavingClause 479 Result RecordSet 480 Error string 481 }{ 482 { 483 Name: "Having", 484 View: &View{ 485 Header: []HeaderField{ 486 { 487 View: "table1", 488 Column: InternalIdColumn, 489 }, 490 { 491 View: "table1", 492 Column: "column1", 493 IsFromTable: true, 494 }, 495 { 496 View: "table1", 497 Column: "column2", 498 IsFromTable: true, 499 }, 500 { 501 View: "table1", 502 Column: "column3", 503 IsFromTable: true, 504 IsGroupKey: true, 505 }, 506 }, 507 isGrouped: true, 508 RecordSet: RecordSet{ 509 { 510 NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("3")}), 511 NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("3")}), 512 NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str3")}), 513 NewGroupCell([]value.Primary{value.NewString("group1"), value.NewString("group1")}), 514 }, 515 { 516 NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}), 517 NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}), 518 NewGroupCell([]value.Primary{value.NewString("str2"), value.NewString("str4")}), 519 NewGroupCell([]value.Primary{value.NewString("group2"), value.NewString("group2")}), 520 }, 521 }, 522 }, 523 Having: parser.HavingClause{ 524 Filter: parser.Comparison{ 525 LHS: parser.AggregateFunction{ 526 Name: "sum", 527 Distinct: parser.Token{}, 528 Args: []parser.QueryExpression{ 529 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 530 }, 531 }, 532 RHS: parser.NewIntegerValueFromString("5"), 533 Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: ">"}, 534 }, 535 }, 536 Result: RecordSet{ 537 { 538 NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}), 539 NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}), 540 NewGroupCell([]value.Primary{value.NewString("str2"), value.NewString("str4")}), 541 NewGroupCell([]value.Primary{value.NewString("group2"), value.NewString("group2")}), 542 }, 543 }, 544 }, 545 { 546 Name: "Having Filter Error", 547 View: &View{ 548 Header: []HeaderField{ 549 { 550 View: "table1", 551 Column: InternalIdColumn, 552 }, 553 { 554 View: "table1", 555 Column: "column1", 556 IsFromTable: true, 557 }, 558 { 559 View: "table1", 560 Column: "column2", 561 IsFromTable: true, 562 }, 563 { 564 View: "table1", 565 Column: "column3", 566 IsFromTable: true, 567 IsGroupKey: true, 568 }, 569 }, 570 isGrouped: true, 571 RecordSet: RecordSet{ 572 { 573 NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("3")}), 574 NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("3")}), 575 NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str3")}), 576 NewGroupCell([]value.Primary{value.NewString("group1"), value.NewString("group1")}), 577 }, 578 { 579 NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}), 580 NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}), 581 NewGroupCell([]value.Primary{value.NewString("str2"), value.NewString("str4")}), 582 NewGroupCell([]value.Primary{value.NewString("group2"), value.NewString("group2")}), 583 }, 584 }, 585 }, 586 Having: parser.HavingClause{ 587 Filter: parser.Comparison{ 588 LHS: parser.AggregateFunction{ 589 Name: "sum", 590 Distinct: parser.Token{}, 591 Args: []parser.QueryExpression{ 592 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 593 }, 594 }, 595 RHS: parser.NewIntegerValueFromString("5"), 596 Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: ">"}, 597 }, 598 }, 599 Error: "field notexist does not exist", 600 }, 601 { 602 Name: "Having Not Grouped", 603 View: &View{ 604 Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}), 605 RecordSet: RecordSet{ 606 NewRecordWithId(1, []value.Primary{ 607 value.NewString("2"), 608 value.NewString("str2"), 609 value.NewString("group2"), 610 }), 611 NewRecordWithId(2, []value.Primary{ 612 value.NewString("4"), 613 value.NewString("str4"), 614 value.NewString("group2"), 615 }), 616 }, 617 }, 618 Having: parser.HavingClause{ 619 Filter: parser.Comparison{ 620 LHS: parser.AggregateFunction{ 621 Name: "sum", 622 Distinct: parser.Token{}, 623 Args: []parser.QueryExpression{ 624 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 625 }, 626 }, 627 RHS: parser.NewIntegerValueFromString("5"), 628 Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: ">"}, 629 }, 630 }, 631 Result: RecordSet{ 632 { 633 NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(2)}), 634 NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}), 635 NewGroupCell([]value.Primary{value.NewString("str2"), value.NewString("str4")}), 636 NewGroupCell([]value.Primary{value.NewString("group2"), value.NewString("group2")}), 637 }, 638 }, 639 }, 640 { 641 Name: "Having All RecordSet Filter Error", 642 View: &View{ 643 Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}), 644 RecordSet: RecordSet{ 645 NewRecordWithId(1, []value.Primary{ 646 value.NewString("2"), 647 value.NewString("str2"), 648 value.NewString("group2"), 649 }), 650 NewRecordWithId(2, []value.Primary{ 651 value.NewString("4"), 652 value.NewString("str4"), 653 value.NewString("group2"), 654 }), 655 }, 656 }, 657 Having: parser.HavingClause{ 658 Filter: parser.Comparison{ 659 LHS: parser.AggregateFunction{ 660 Name: "sum", 661 Distinct: parser.Token{}, 662 Args: []parser.QueryExpression{ 663 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 664 }, 665 }, 666 RHS: parser.NewIntegerValueFromString("5"), 667 Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: ">"}, 668 }, 669 }, 670 Error: "field notexist does not exist", 671 }, 672 } 673 674 func TestView_Having(t *testing.T) { 675 scope := NewReferenceScope(TestTx) 676 ctx := context.Background() 677 for _, v := range viewHavingTests { 678 err := v.View.Having(ctx, scope, v.Having) 679 if err != nil { 680 if len(v.Error) < 1 { 681 t.Errorf("%s: unexpected error %q", v.Name, err) 682 } else if err.Error() != v.Error { 683 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 684 } 685 continue 686 } 687 if 0 < len(v.Error) { 688 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 689 continue 690 } 691 if !reflect.DeepEqual(v.View.RecordSet, v.Result) { 692 t.Errorf("%s: result = %s, want %s", v.Name, v.View.RecordSet, v.Result) 693 } 694 } 695 } 696 697 var viewSelectTests = []struct { 698 Name string 699 View *View 700 Scope *ReferenceScope 701 Select parser.SelectClause 702 Result *View 703 Error string 704 }{ 705 { 706 Name: "Select", 707 View: &View{ 708 Header: []HeaderField{ 709 {View: "table1", Column: InternalIdColumn}, 710 {View: "table1", Column: "column1", Number: 1, IsFromTable: true}, 711 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 712 {View: "table2", Column: InternalIdColumn}, 713 {View: "table2", Column: "column3", Number: 1, IsFromTable: true}, 714 {View: "table2", Column: "column4", Number: 2, IsFromTable: true}, 715 }, 716 RecordSet: []Record{ 717 NewRecord([]value.Primary{ 718 value.NewInteger(1), 719 value.NewString("1"), 720 value.NewString("str1"), 721 value.NewInteger(1), 722 value.NewString("2"), 723 value.NewString("str22"), 724 }), 725 NewRecord([]value.Primary{ 726 value.NewInteger(1), 727 value.NewString("1"), 728 value.NewString("str1"), 729 value.NewInteger(2), 730 value.NewString("3"), 731 value.NewString("str33"), 732 }), 733 NewRecord([]value.Primary{ 734 value.NewInteger(1), 735 value.NewString("1"), 736 value.NewString("str1"), 737 value.NewInteger(3), 738 value.NewString("1"), 739 value.NewString("str44"), 740 }), 741 NewRecord([]value.Primary{ 742 value.NewInteger(2), 743 value.NewString("2"), 744 value.NewString("str2"), 745 value.NewInteger(1), 746 value.NewString("2"), 747 value.NewString("str22"), 748 }), 749 }, 750 }, 751 Select: parser.SelectClause{ 752 Fields: []parser.QueryExpression{ 753 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, Alias: parser.Identifier{Literal: "c2"}}, 754 parser.Field{Object: parser.AllColumns{}}, 755 parser.Field{Object: parser.NewIntegerValueFromString("1"), Alias: parser.Identifier{Literal: "a"}}, 756 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, Alias: parser.Identifier{Literal: "c2a"}}, 757 parser.Field{Object: parser.ColumnNumber{View: parser.Identifier{Literal: "table2"}, Number: value.NewInteger(1)}, Alias: parser.Identifier{Literal: "t21"}}, 758 parser.Field{Object: parser.ColumnNumber{View: parser.Identifier{Literal: "table2"}, Number: value.NewInteger(1)}, Alias: parser.Identifier{Literal: "t21a"}}, 759 parser.Field{Object: parser.PrimitiveType{ 760 Literal: "2012-01-01", 761 Value: value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())), 762 }}, 763 }, 764 }, 765 Result: &View{ 766 Header: []HeaderField{ 767 {View: "table1", Column: InternalIdColumn}, 768 {View: "table1", Column: "column1", Number: 1, IsFromTable: true}, 769 {View: "table1", Column: "column2", Aliases: []string{"c2", "c2a"}, Number: 2, IsFromTable: true}, 770 {View: "table2", Column: InternalIdColumn}, 771 {View: "table2", Column: "column3", Aliases: []string{"t21", "t21a"}, Number: 1, IsFromTable: true}, 772 {View: "table2", Column: "column4", Number: 2, IsFromTable: true}, 773 {Identifier: "@__PT:I:1", Column: "1", Aliases: []string{"a"}}, 774 {Identifier: "@__PT:D:2012-01-01T00:00:00Z", Column: "2012-01-01T00:00:00Z"}, 775 }, 776 RecordSet: []Record{ 777 NewRecord([]value.Primary{ 778 value.NewInteger(1), 779 value.NewString("1"), 780 value.NewString("str1"), 781 value.NewInteger(1), 782 value.NewString("2"), 783 value.NewString("str22"), 784 value.NewInteger(1), 785 value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())), 786 }), 787 NewRecord([]value.Primary{ 788 value.NewInteger(1), 789 value.NewString("1"), 790 value.NewString("str1"), 791 value.NewInteger(2), 792 value.NewString("3"), 793 value.NewString("str33"), 794 value.NewInteger(1), 795 value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())), 796 }), 797 NewRecord([]value.Primary{ 798 value.NewInteger(1), 799 value.NewString("1"), 800 value.NewString("str1"), 801 value.NewInteger(3), 802 value.NewString("1"), 803 value.NewString("str44"), 804 value.NewInteger(1), 805 value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())), 806 }), 807 NewRecord([]value.Primary{ 808 value.NewInteger(2), 809 value.NewString("2"), 810 value.NewString("str2"), 811 value.NewInteger(1), 812 value.NewString("2"), 813 value.NewString("str22"), 814 value.NewInteger(1), 815 value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())), 816 }), 817 }, 818 selectFields: []int{2, 1, 2, 4, 5, 6, 2, 4, 4, 7}, 819 }, 820 }, 821 { 822 Name: "Select using Table Wildcard", 823 View: &View{ 824 Header: []HeaderField{ 825 {View: "table1", Column: InternalIdColumn}, 826 {View: "table1", Column: "column1", Number: 1, IsFromTable: true}, 827 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 828 {View: "table2", Column: InternalIdColumn}, 829 {View: "table2", Column: "column3", Number: 1, IsFromTable: true}, 830 {View: "table2", Column: "column4", Number: 2, IsFromTable: true}, 831 }, 832 RecordSet: []Record{ 833 NewRecord([]value.Primary{ 834 value.NewInteger(1), 835 value.NewString("1"), 836 value.NewString("str1"), 837 value.NewInteger(1), 838 value.NewString("2"), 839 value.NewString("str22"), 840 }), 841 NewRecord([]value.Primary{ 842 value.NewInteger(1), 843 value.NewString("1"), 844 value.NewString("str1"), 845 value.NewInteger(2), 846 value.NewString("3"), 847 value.NewString("str33"), 848 }), 849 NewRecord([]value.Primary{ 850 value.NewInteger(1), 851 value.NewString("1"), 852 value.NewString("str1"), 853 value.NewInteger(3), 854 value.NewString("1"), 855 value.NewString("str44"), 856 }), 857 NewRecord([]value.Primary{ 858 value.NewInteger(2), 859 value.NewString("2"), 860 value.NewString("str2"), 861 value.NewInteger(1), 862 value.NewString("2"), 863 value.NewString("str22"), 864 }), 865 }, 866 }, 867 Select: parser.SelectClause{ 868 Fields: []parser.QueryExpression{ 869 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, Alias: parser.Identifier{Literal: "c2"}}, 870 parser.Field{Object: parser.FieldReference{View: parser.Identifier{Literal: "table2"}, Column: parser.AllColumns{}}}, 871 parser.Field{Object: parser.NewIntegerValueFromString("1"), Alias: parser.Identifier{Literal: "a"}}, 872 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, Alias: parser.Identifier{Literal: "c2a"}}, 873 parser.Field{Object: parser.ColumnNumber{View: parser.Identifier{Literal: "table2"}, Number: value.NewInteger(1)}, Alias: parser.Identifier{Literal: "t21"}}, 874 parser.Field{Object: parser.ColumnNumber{View: parser.Identifier{Literal: "table2"}, Number: value.NewInteger(1)}, Alias: parser.Identifier{Literal: "t21a"}}, 875 parser.Field{Object: parser.PrimitiveType{ 876 Literal: "2012-01-01", 877 Value: value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())), 878 }}, 879 }, 880 }, 881 Result: &View{ 882 Header: []HeaderField{ 883 {View: "table1", Column: InternalIdColumn}, 884 {View: "table1", Column: "column1", Number: 1, IsFromTable: true}, 885 {View: "table1", Column: "column2", Aliases: []string{"c2", "c2a"}, Number: 2, IsFromTable: true}, 886 {View: "table2", Column: InternalIdColumn}, 887 {View: "table2", Column: "column3", Aliases: []string{"t21", "t21a"}, Number: 1, IsFromTable: true}, 888 {View: "table2", Column: "column4", Number: 2, IsFromTable: true}, 889 {Identifier: "@__PT:I:1", Column: "1", Aliases: []string{"a"}}, 890 {Identifier: "@__PT:D:2012-01-01T00:00:00Z", Column: "2012-01-01T00:00:00Z"}, 891 }, 892 RecordSet: []Record{ 893 NewRecord([]value.Primary{ 894 value.NewInteger(1), 895 value.NewString("1"), 896 value.NewString("str1"), 897 value.NewInteger(1), 898 value.NewString("2"), 899 value.NewString("str22"), 900 value.NewInteger(1), 901 value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())), 902 }), 903 NewRecord([]value.Primary{ 904 value.NewInteger(1), 905 value.NewString("1"), 906 value.NewString("str1"), 907 value.NewInteger(2), 908 value.NewString("3"), 909 value.NewString("str33"), 910 value.NewInteger(1), 911 value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())), 912 }), 913 NewRecord([]value.Primary{ 914 value.NewInteger(1), 915 value.NewString("1"), 916 value.NewString("str1"), 917 value.NewInteger(3), 918 value.NewString("1"), 919 value.NewString("str44"), 920 value.NewInteger(1), 921 value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())), 922 }), 923 NewRecord([]value.Primary{ 924 value.NewInteger(2), 925 value.NewString("2"), 926 value.NewString("str2"), 927 value.NewInteger(1), 928 value.NewString("2"), 929 value.NewString("str22"), 930 value.NewInteger(1), 931 value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())), 932 }), 933 }, 934 selectFields: []int{2, 4, 5, 6, 2, 4, 4, 7}, 935 }, 936 }, 937 { 938 Name: "Select Distinct", 939 View: &View{ 940 Header: []HeaderField{ 941 {View: "table1", Column: InternalIdColumn}, 942 {View: "table1", Column: "column1", IsFromTable: true}, 943 {View: "table1", Column: "column2", IsFromTable: true}, 944 {View: "table2", Column: InternalIdColumn}, 945 {View: "table2", Column: "column3", IsFromTable: true}, 946 {View: "table2", Column: "column4", IsFromTable: true}, 947 }, 948 RecordSet: []Record{ 949 NewRecord([]value.Primary{ 950 value.NewInteger(1), 951 value.NewString("1"), 952 value.NewString("str1"), 953 value.NewInteger(1), 954 value.NewString("2"), 955 value.NewString("str22"), 956 }), 957 NewRecord([]value.Primary{ 958 value.NewInteger(1), 959 value.NewString("1"), 960 value.NewString("str1"), 961 value.NewInteger(2), 962 value.NewString("3"), 963 value.NewString("str33"), 964 }), 965 NewRecord([]value.Primary{ 966 value.NewInteger(1), 967 value.NewString("1"), 968 value.NewString("str1"), 969 value.NewInteger(3), 970 value.NewString("4"), 971 value.NewString("str44"), 972 }), 973 NewRecord([]value.Primary{ 974 value.NewInteger(2), 975 value.NewString("2"), 976 value.NewString("str2"), 977 value.NewInteger(1), 978 value.NewString("2"), 979 value.NewString("str22"), 980 }), 981 }, 982 }, 983 Select: parser.SelectClause{ 984 Distinct: parser.Token{Token: parser.DISTINCT, Literal: "distinct"}, 985 Fields: []parser.QueryExpression{ 986 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 987 parser.Field{Object: parser.NewIntegerValueFromString("1"), Alias: parser.Identifier{Literal: "a"}}, 988 }, 989 }, 990 Result: &View{ 991 Header: []HeaderField{ 992 {View: "table1", Column: "column1", IsFromTable: true}, 993 {Identifier: "@__PT:I:1", Column: "1", Aliases: []string{"a"}}, 994 }, 995 RecordSet: []Record{ 996 NewRecord([]value.Primary{ 997 value.NewString("1"), 998 value.NewInteger(1), 999 }), 1000 NewRecord([]value.Primary{ 1001 value.NewString("2"), 1002 value.NewInteger(1), 1003 }), 1004 }, 1005 selectFields: []int{0, 1}, 1006 }, 1007 }, 1008 { 1009 Name: "Select Aggregate Function", 1010 View: &View{ 1011 Header: []HeaderField{ 1012 {View: "table1", Column: InternalIdColumn}, 1013 {View: "table1", Column: "column1", IsFromTable: true}, 1014 {View: "table1", Column: "column2", IsFromTable: true}, 1015 }, 1016 RecordSet: []Record{ 1017 NewRecordWithId(1, []value.Primary{ 1018 value.NewString("1"), 1019 value.NewString("str1"), 1020 }), 1021 NewRecordWithId(2, []value.Primary{ 1022 value.NewString("2"), 1023 value.NewString("str2"), 1024 }), 1025 }, 1026 }, 1027 Select: parser.SelectClause{ 1028 Fields: []parser.QueryExpression{ 1029 parser.Field{ 1030 Object: parser.AggregateFunction{ 1031 Name: "sum", 1032 Distinct: parser.Token{}, 1033 Args: []parser.QueryExpression{ 1034 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 1035 }, 1036 }, 1037 }, 1038 }, 1039 }, 1040 Result: &View{ 1041 Header: []HeaderField{ 1042 {View: "table1", Column: InternalIdColumn}, 1043 {View: "table1", Column: "column1", IsFromTable: true}, 1044 {View: "table1", Column: "column2", IsFromTable: true}, 1045 {Identifier: "SUM(column1)", Column: "SUM(column1)"}, 1046 }, 1047 RecordSet: []Record{ 1048 { 1049 NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(2)}), 1050 NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("2")}), 1051 NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str2")}), 1052 NewCell(value.NewFloat(3)), 1053 }, 1054 }, 1055 selectFields: []int{3}, 1056 }, 1057 }, 1058 { 1059 Name: "Select Aggregate Function Not Group Key Error", 1060 View: &View{ 1061 Header: []HeaderField{ 1062 {View: "table1", Column: InternalIdColumn}, 1063 {View: "table1", Column: "column1", IsFromTable: true}, 1064 {View: "table1", Column: "column2", IsFromTable: true}, 1065 }, 1066 RecordSet: []Record{ 1067 NewRecordWithId(1, []value.Primary{ 1068 value.NewString("1"), 1069 value.NewString("str1"), 1070 }), 1071 NewRecordWithId(2, []value.Primary{ 1072 value.NewString("2"), 1073 value.NewString("str2"), 1074 }), 1075 }, 1076 }, 1077 Select: parser.SelectClause{ 1078 Fields: []parser.QueryExpression{ 1079 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 1080 parser.Field{ 1081 Object: parser.AggregateFunction{ 1082 Name: "sum", 1083 Distinct: parser.Token{}, 1084 Args: []parser.QueryExpression{ 1085 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 1086 }, 1087 }, 1088 }, 1089 }, 1090 }, 1091 Error: "field column2 is not a group key", 1092 }, 1093 { 1094 Name: "Select Aggregate Function All RecordSet Lazy Evaluation", 1095 View: &View{ 1096 Header: []HeaderField{ 1097 {View: "table1", Column: InternalIdColumn}, 1098 {View: "table1", Column: "column1", IsFromTable: true}, 1099 {View: "table1", Column: "column2", IsFromTable: true}, 1100 }, 1101 RecordSet: []Record{ 1102 NewRecordWithId(1, []value.Primary{ 1103 value.NewString("1"), 1104 value.NewString("str1"), 1105 }), 1106 NewRecordWithId(2, []value.Primary{ 1107 value.NewString("2"), 1108 value.NewString("str2"), 1109 }), 1110 }, 1111 }, 1112 Select: parser.SelectClause{ 1113 Fields: []parser.QueryExpression{ 1114 parser.Field{Object: parser.NewIntegerValueFromString("1")}, 1115 parser.Field{ 1116 Object: parser.Arithmetic{ 1117 LHS: parser.AggregateFunction{ 1118 Name: "sum", 1119 Distinct: parser.Token{}, 1120 Args: []parser.QueryExpression{ 1121 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 1122 }, 1123 }, 1124 RHS: parser.NewIntegerValueFromString("1"), 1125 Operator: parser.Token{Token: '+', Literal: "+"}, 1126 }, 1127 }, 1128 }, 1129 }, 1130 Result: &View{ 1131 Header: []HeaderField{ 1132 {View: "table1", Column: InternalIdColumn}, 1133 {View: "table1", Column: "column1", IsFromTable: true}, 1134 {View: "table1", Column: "column2", IsFromTable: true}, 1135 {Identifier: "@__PT:I:1", Column: "1"}, 1136 {Identifier: "SUM(column1) + 1", Column: "SUM(column1) + 1"}, 1137 }, 1138 RecordSet: []Record{ 1139 { 1140 NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(2)}), 1141 NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("2")}), 1142 NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str2")}), 1143 NewCell(value.NewInteger(1)), 1144 NewCell(value.NewFloat(4)), 1145 }, 1146 }, 1147 selectFields: []int{3, 4}, 1148 }, 1149 }, 1150 { 1151 Name: "Select Analytic Function", 1152 View: &View{ 1153 Header: NewHeader("table1", []string{"column1", "column2"}), 1154 RecordSet: []Record{ 1155 NewRecord([]value.Primary{ 1156 value.NewString("a"), 1157 value.NewInteger(2), 1158 }), 1159 NewRecord([]value.Primary{ 1160 value.NewString("b"), 1161 value.NewInteger(3), 1162 }), 1163 NewRecord([]value.Primary{ 1164 value.NewString("b"), 1165 value.NewInteger(5), 1166 }), 1167 NewRecord([]value.Primary{ 1168 value.NewString("a"), 1169 value.NewInteger(1), 1170 }), 1171 NewRecord([]value.Primary{ 1172 value.NewString("b"), 1173 value.NewInteger(4), 1174 }), 1175 }, 1176 }, 1177 Select: parser.SelectClause{ 1178 Fields: []parser.QueryExpression{ 1179 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 1180 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 1181 parser.Field{ 1182 Object: parser.AnalyticFunction{ 1183 Name: "row_number", 1184 AnalyticClause: parser.AnalyticClause{ 1185 PartitionClause: parser.PartitionClause{ 1186 Values: []parser.QueryExpression{ 1187 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 1188 }, 1189 }, 1190 OrderByClause: parser.OrderByClause{ 1191 Items: []parser.QueryExpression{ 1192 parser.OrderItem{ 1193 Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1194 }, 1195 }, 1196 }, 1197 }, 1198 }, 1199 Alias: parser.Identifier{Literal: "rownum"}, 1200 }, 1201 }, 1202 }, 1203 Result: &View{ 1204 Header: []HeaderField{ 1205 {View: "table1", Column: "column1", Number: 1, IsFromTable: true}, 1206 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 1207 {Identifier: "ROW_NUMBER() OVER (PARTITION BY column1 ORDER BY column2)", Column: "ROW_NUMBER() OVER (PARTITION BY column1 ORDER BY column2)", Aliases: []string{"rownum"}}, 1208 }, 1209 RecordSet: []Record{ 1210 NewRecord([]value.Primary{ 1211 value.NewString("a"), 1212 value.NewInteger(1), 1213 value.NewInteger(1), 1214 }), 1215 NewRecord([]value.Primary{ 1216 value.NewString("a"), 1217 value.NewInteger(2), 1218 value.NewInteger(2), 1219 }), 1220 NewRecord([]value.Primary{ 1221 value.NewString("b"), 1222 value.NewInteger(3), 1223 value.NewInteger(1), 1224 }), 1225 NewRecord([]value.Primary{ 1226 value.NewString("b"), 1227 value.NewInteger(4), 1228 value.NewInteger(2), 1229 }), 1230 NewRecord([]value.Primary{ 1231 value.NewString("b"), 1232 value.NewInteger(5), 1233 value.NewInteger(3), 1234 }), 1235 }, 1236 selectFields: []int{0, 1, 2}, 1237 }, 1238 }, 1239 { 1240 Name: "Select Analytic Function Not Exist Error", 1241 View: &View{ 1242 Header: NewHeader("table1", []string{"column1", "column2"}), 1243 RecordSet: []Record{ 1244 NewRecord([]value.Primary{ 1245 value.NewString("a"), 1246 value.NewInteger(2), 1247 }), 1248 NewRecord([]value.Primary{ 1249 value.NewString("b"), 1250 value.NewInteger(3), 1251 }), 1252 NewRecord([]value.Primary{ 1253 value.NewString("b"), 1254 value.NewInteger(5), 1255 }), 1256 NewRecord([]value.Primary{ 1257 value.NewString("a"), 1258 value.NewInteger(1), 1259 }), 1260 NewRecord([]value.Primary{ 1261 value.NewString("b"), 1262 value.NewInteger(4), 1263 }), 1264 }, 1265 }, 1266 Select: parser.SelectClause{ 1267 Fields: []parser.QueryExpression{ 1268 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 1269 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 1270 parser.Field{ 1271 Object: parser.AnalyticFunction{ 1272 Name: "notexist", 1273 AnalyticClause: parser.AnalyticClause{ 1274 PartitionClause: parser.PartitionClause{ 1275 Values: []parser.QueryExpression{ 1276 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 1277 }, 1278 }, 1279 OrderByClause: parser.OrderByClause{ 1280 Items: []parser.QueryExpression{ 1281 parser.OrderItem{ 1282 Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1283 }, 1284 }, 1285 }, 1286 }, 1287 }, 1288 Alias: parser.Identifier{Literal: "rownum"}, 1289 }, 1290 }, 1291 }, 1292 Error: "function notexist does not exist", 1293 }, 1294 { 1295 Name: "Select Analytic Function Partition Error", 1296 View: &View{ 1297 Header: NewHeader("table1", []string{"column1", "column2"}), 1298 RecordSet: []Record{ 1299 NewRecord([]value.Primary{ 1300 value.NewString("a"), 1301 value.NewInteger(2), 1302 }), 1303 NewRecord([]value.Primary{ 1304 value.NewString("b"), 1305 value.NewInteger(3), 1306 }), 1307 NewRecord([]value.Primary{ 1308 value.NewString("b"), 1309 value.NewInteger(5), 1310 }), 1311 NewRecord([]value.Primary{ 1312 value.NewString("a"), 1313 value.NewInteger(1), 1314 }), 1315 NewRecord([]value.Primary{ 1316 value.NewString("b"), 1317 value.NewInteger(4), 1318 }), 1319 }, 1320 }, 1321 Select: parser.SelectClause{ 1322 Fields: []parser.QueryExpression{ 1323 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 1324 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 1325 parser.Field{ 1326 Object: parser.AnalyticFunction{ 1327 Name: "row_number", 1328 AnalyticClause: parser.AnalyticClause{ 1329 PartitionClause: parser.PartitionClause{ 1330 Values: []parser.QueryExpression{ 1331 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 1332 }, 1333 }, 1334 OrderByClause: parser.OrderByClause{ 1335 Items: []parser.QueryExpression{ 1336 parser.OrderItem{ 1337 Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1338 }, 1339 }, 1340 }, 1341 }, 1342 }, 1343 Alias: parser.Identifier{Literal: "rownum"}, 1344 }, 1345 }, 1346 }, 1347 Error: "field notexist does not exist", 1348 }, 1349 { 1350 Name: "Select Analytic Function Order Error", 1351 View: &View{ 1352 Header: NewHeader("table1", []string{"column1", "column2"}), 1353 RecordSet: []Record{ 1354 NewRecord([]value.Primary{ 1355 value.NewString("a"), 1356 value.NewInteger(2), 1357 }), 1358 NewRecord([]value.Primary{ 1359 value.NewString("b"), 1360 value.NewInteger(3), 1361 }), 1362 NewRecord([]value.Primary{ 1363 value.NewString("b"), 1364 value.NewInteger(5), 1365 }), 1366 NewRecord([]value.Primary{ 1367 value.NewString("a"), 1368 value.NewInteger(1), 1369 }), 1370 NewRecord([]value.Primary{ 1371 value.NewString("b"), 1372 value.NewInteger(4), 1373 }), 1374 }, 1375 }, 1376 Select: parser.SelectClause{ 1377 Fields: []parser.QueryExpression{ 1378 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 1379 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 1380 parser.Field{ 1381 Object: parser.AnalyticFunction{ 1382 Name: "row_number", 1383 AnalyticClause: parser.AnalyticClause{ 1384 PartitionClause: parser.PartitionClause{ 1385 Values: []parser.QueryExpression{ 1386 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 1387 }, 1388 }, 1389 OrderByClause: parser.OrderByClause{ 1390 Items: []parser.QueryExpression{ 1391 parser.OrderItem{ 1392 Value: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 1393 }, 1394 }, 1395 }, 1396 }, 1397 }, 1398 Alias: parser.Identifier{Literal: "rownum"}, 1399 }, 1400 }, 1401 }, 1402 Error: "field notexist does not exist", 1403 }, 1404 { 1405 Name: "Select User Defined Analytic Function", 1406 View: &View{ 1407 Header: NewHeader("table1", []string{"column1", "column2"}), 1408 RecordSet: []Record{ 1409 NewRecord([]value.Primary{ 1410 value.NewString("a"), 1411 value.NewInteger(2), 1412 }), 1413 NewRecord([]value.Primary{ 1414 value.NewString("b"), 1415 value.NewInteger(3), 1416 }), 1417 NewRecord([]value.Primary{ 1418 value.NewString("b"), 1419 value.NewInteger(5), 1420 }), 1421 NewRecord([]value.Primary{ 1422 value.NewString("a"), 1423 value.NewInteger(1), 1424 }), 1425 NewRecord([]value.Primary{ 1426 value.NewString("b"), 1427 value.NewInteger(4), 1428 }), 1429 }, 1430 }, 1431 Scope: GenerateReferenceScope([]map[string]map[string]interface{}{ 1432 { 1433 scopeNameFunctions: { 1434 "USERAGGFUNC": &UserDefinedFunction{ 1435 Name: parser.Identifier{Literal: "useraggfunc"}, 1436 IsAggregate: true, 1437 Cursor: parser.Identifier{Literal: "list"}, 1438 RequiredArgs: 0, 1439 Statements: []parser.Statement{ 1440 parser.VariableDeclaration{ 1441 Assignments: []parser.VariableAssignment{ 1442 { 1443 Variable: parser.Variable{Name: "value"}, 1444 }, 1445 { 1446 Variable: parser.Variable{Name: "fetch"}, 1447 }, 1448 }, 1449 }, 1450 parser.WhileInCursor{ 1451 Variables: []parser.Variable{ 1452 {Name: "fetch"}, 1453 }, 1454 Cursor: parser.Identifier{Literal: "list"}, 1455 Statements: []parser.Statement{ 1456 parser.If{ 1457 Condition: parser.Is{ 1458 LHS: parser.Variable{Name: "value"}, 1459 RHS: parser.NewNullValue(), 1460 }, 1461 Statements: []parser.Statement{ 1462 parser.VariableSubstitution{ 1463 Variable: parser.Variable{Name: "value"}, 1464 Value: parser.Variable{Name: "fetch"}, 1465 }, 1466 parser.FlowControl{Token: parser.CONTINUE}, 1467 }, 1468 }, 1469 parser.VariableSubstitution{ 1470 Variable: parser.Variable{Name: "value"}, 1471 Value: parser.Arithmetic{ 1472 LHS: parser.Variable{Name: "value"}, 1473 RHS: parser.Variable{Name: "fetch"}, 1474 Operator: parser.Token{Token: '+', Literal: "+"}, 1475 }, 1476 }, 1477 }, 1478 }, 1479 1480 parser.Return{ 1481 Value: parser.Variable{Name: "value"}, 1482 }, 1483 }, 1484 }, 1485 }, 1486 }, 1487 }, nil, time.Time{}, nil), 1488 Select: parser.SelectClause{ 1489 Fields: []parser.QueryExpression{ 1490 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}, 1491 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}}, 1492 parser.Field{ 1493 Object: parser.AnalyticFunction{ 1494 Name: "useraggfunc", 1495 Args: []parser.QueryExpression{ 1496 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1497 }, 1498 AnalyticClause: parser.AnalyticClause{}, 1499 }, 1500 }, 1501 }, 1502 }, 1503 Result: &View{ 1504 Header: []HeaderField{ 1505 {View: "table1", Column: "column1", Number: 1, IsFromTable: true}, 1506 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 1507 {Identifier: "USERAGGFUNC(column2) OVER ()", Column: "USERAGGFUNC(column2) OVER ()"}, 1508 }, 1509 RecordSet: []Record{ 1510 NewRecord([]value.Primary{ 1511 value.NewString("a"), 1512 value.NewInteger(2), 1513 value.NewInteger(15), 1514 }), 1515 NewRecord([]value.Primary{ 1516 value.NewString("b"), 1517 value.NewInteger(3), 1518 value.NewInteger(15), 1519 }), 1520 NewRecord([]value.Primary{ 1521 value.NewString("b"), 1522 value.NewInteger(5), 1523 value.NewInteger(15), 1524 }), 1525 NewRecord([]value.Primary{ 1526 value.NewString("a"), 1527 value.NewInteger(1), 1528 value.NewInteger(15), 1529 }), 1530 NewRecord([]value.Primary{ 1531 value.NewString("b"), 1532 value.NewInteger(4), 1533 value.NewInteger(15), 1534 }), 1535 }, 1536 selectFields: []int{0, 1, 2}, 1537 }, 1538 }, 1539 { 1540 Name: "Select Aggregate Empty Rows", 1541 View: &View{ 1542 Header: []HeaderField{ 1543 {View: "table1", Column: "column1", IsFromTable: true}, 1544 {View: "table1", Column: "column2", IsFromTable: true}, 1545 }, 1546 RecordSet: []Record{}, 1547 }, 1548 Select: parser.SelectClause{ 1549 Fields: []parser.QueryExpression{ 1550 parser.Field{Object: parser.NewIntegerValue(1)}, 1551 parser.Field{Object: parser.AggregateFunction{Name: "count", Args: []parser.QueryExpression{parser.AllColumns{}}}}, 1552 parser.Field{Object: parser.AggregateFunction{Name: "sum", Args: []parser.QueryExpression{parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}}}, 1553 }, 1554 }, 1555 Result: &View{ 1556 Header: []HeaderField{ 1557 {View: "table1", Column: "column1", IsFromTable: true}, 1558 {View: "table1", Column: "column2", IsFromTable: true}, 1559 {Identifier: "@__PT:I:1", Column: "1"}, 1560 {Identifier: "COUNT(*)", Column: "COUNT(*)"}, 1561 {Identifier: "SUM(column1)", Column: "SUM(column1)"}, 1562 }, 1563 RecordSet: []Record{ 1564 NewRecord([]value.Primary{ 1565 nil, 1566 nil, 1567 value.NewInteger(1), 1568 value.NewInteger(0), 1569 value.NewNull(), 1570 }), 1571 }, 1572 selectFields: []int{2, 3, 4}, 1573 }, 1574 }, 1575 { 1576 Name: "Select Compound Function with Aggregate Empty Rows", 1577 View: &View{ 1578 Header: []HeaderField{ 1579 {View: "table1", Column: "column1", IsFromTable: true}, 1580 {View: "table1", Column: "column2", IsFromTable: true}, 1581 }, 1582 RecordSet: []Record{}, 1583 }, 1584 Select: parser.SelectClause{ 1585 Fields: []parser.QueryExpression{ 1586 parser.Field{ 1587 Object: parser.Function{Name: "coalesce", 1588 Args: []parser.QueryExpression{ 1589 parser.AggregateFunction{Name: "sum", Args: []parser.QueryExpression{parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}}, 1590 parser.NewIntegerValue(0), 1591 }, 1592 }, 1593 }, 1594 }, 1595 }, 1596 Result: &View{ 1597 Header: []HeaderField{ 1598 {View: "table1", Column: "column1", IsFromTable: true}, 1599 {View: "table1", Column: "column2", IsFromTable: true}, 1600 {Identifier: "COALESCE(SUM(column1), 0)", Column: "COALESCE(SUM(column1), 0)"}, 1601 }, 1602 RecordSet: []Record{ 1603 NewRecord([]value.Primary{ 1604 nil, 1605 nil, 1606 value.NewInteger(0), 1607 }), 1608 }, 1609 selectFields: []int{2}, 1610 }, 1611 }, 1612 } 1613 1614 func TestView_Select(t *testing.T) { 1615 ctx := context.Background() 1616 for _, v := range viewSelectTests { 1617 if v.Scope == nil { 1618 v.Scope = NewReferenceScope(TestTx) 1619 } 1620 err := v.View.Select(ctx, v.Scope, v.Select) 1621 if err != nil { 1622 if len(v.Error) < 1 { 1623 t.Errorf("%s: unexpected error %q", v.Name, err) 1624 } else if err.Error() != v.Error { 1625 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 1626 } 1627 continue 1628 } 1629 if 0 < len(v.Error) { 1630 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 1631 continue 1632 } 1633 if !reflect.DeepEqual(v.View.Header, v.Result.Header) { 1634 t.Errorf("%s: header = %v, want %v", v.Name, v.View.Header, v.Result.Header) 1635 } 1636 if !reflect.DeepEqual(v.View.RecordSet, v.Result.RecordSet) { 1637 t.Errorf("%s: records = %s, want %s", v.Name, v.View.RecordSet, v.Result.RecordSet) 1638 } 1639 if !reflect.DeepEqual(v.View.selectFields, v.Result.selectFields) { 1640 t.Errorf("%s: select indices = %v, want %v", v.Name, v.View.selectFields, v.Result.selectFields) 1641 } 1642 } 1643 } 1644 1645 var viewOrderByTests = []struct { 1646 Name string 1647 View *View 1648 OrderBy parser.OrderByClause 1649 Result *View 1650 Error string 1651 }{ 1652 { 1653 Name: "Order By", 1654 View: &View{ 1655 Header: []HeaderField{ 1656 {View: "table1", Column: InternalIdColumn}, 1657 {View: "table1", Column: "column1", IsFromTable: true}, 1658 {View: "table1", Column: "column2", IsFromTable: true}, 1659 {View: "table1", Column: "column3", IsFromTable: true}, 1660 }, 1661 RecordSet: []Record{ 1662 NewRecordWithId(1, []value.Primary{ 1663 value.NewString("1"), 1664 value.NewString("3"), 1665 value.NewString("2"), 1666 }), 1667 NewRecordWithId(2, []value.Primary{ 1668 value.NewString("1"), 1669 value.NewString("4"), 1670 value.NewString("3"), 1671 }), 1672 NewRecordWithId(3, []value.Primary{ 1673 value.NewString("1"), 1674 value.NewString("4"), 1675 value.NewString("3"), 1676 }), 1677 NewRecordWithId(4, []value.Primary{ 1678 value.NewString("1"), 1679 value.NewString("3"), 1680 value.NewNull(), 1681 }), 1682 NewRecordWithId(5, []value.Primary{ 1683 value.NewNull(), 1684 value.NewString("2"), 1685 value.NewString("4"), 1686 }), 1687 }, 1688 }, 1689 OrderBy: parser.OrderByClause{ 1690 Items: []parser.QueryExpression{ 1691 parser.OrderItem{ 1692 Value: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 1693 }, 1694 parser.OrderItem{ 1695 Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1696 Direction: parser.Token{Token: parser.DESC, Literal: "desc"}, 1697 }, 1698 parser.OrderItem{ 1699 Value: parser.FieldReference{Column: parser.Identifier{Literal: "column3"}}, 1700 }, 1701 parser.OrderItem{ 1702 Value: parser.NewIntegerValueFromString("1"), 1703 }, 1704 }, 1705 }, 1706 Result: &View{ 1707 Header: []HeaderField{ 1708 {View: "table1", Column: InternalIdColumn}, 1709 {View: "table1", Column: "column1", IsFromTable: true}, 1710 {View: "table1", Column: "column2", IsFromTable: true}, 1711 {View: "table1", Column: "column3", IsFromTable: true}, 1712 {Identifier: "@__PT:I:1", Column: "1"}, 1713 }, 1714 RecordSet: []Record{ 1715 NewRecordWithId(5, []value.Primary{ 1716 value.NewNull(), 1717 value.NewString("2"), 1718 value.NewString("4"), 1719 value.NewInteger(1), 1720 }), 1721 NewRecordWithId(2, []value.Primary{ 1722 value.NewString("1"), 1723 value.NewString("4"), 1724 value.NewString("3"), 1725 value.NewInteger(1), 1726 }), 1727 NewRecordWithId(3, []value.Primary{ 1728 value.NewString("1"), 1729 value.NewString("4"), 1730 value.NewString("3"), 1731 value.NewInteger(1), 1732 }), 1733 NewRecordWithId(4, []value.Primary{ 1734 value.NewString("1"), 1735 value.NewString("3"), 1736 value.NewNull(), 1737 value.NewInteger(1), 1738 }), 1739 NewRecordWithId(1, []value.Primary{ 1740 value.NewString("1"), 1741 value.NewString("3"), 1742 value.NewString("2"), 1743 value.NewInteger(1), 1744 }), 1745 }, 1746 }, 1747 }, 1748 { 1749 Name: "Order By with Cached SortValues", 1750 View: &View{ 1751 Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}), 1752 RecordSet: []Record{ 1753 NewRecordWithId(1, []value.Primary{ 1754 value.NewString("1"), 1755 value.NewString("3"), 1756 value.NewString("2"), 1757 }), 1758 NewRecordWithId(2, []value.Primary{ 1759 value.NewString("1"), 1760 value.NewString("4"), 1761 value.NewString("3"), 1762 }), 1763 NewRecordWithId(3, []value.Primary{ 1764 value.NewString("1"), 1765 value.NewString("4"), 1766 value.NewString("3"), 1767 }), 1768 NewRecordWithId(4, []value.Primary{ 1769 value.NewString("1"), 1770 value.NewString("3"), 1771 value.NewNull(), 1772 }), 1773 NewRecordWithId(5, []value.Primary{ 1774 value.NewNull(), 1775 value.NewString("2"), 1776 value.NewString("4"), 1777 }), 1778 }, 1779 sortValuesInEachCell: [][]*SortValue{ 1780 {nil, nil, NewSortValue(value.NewString("3"), TestTx.Flags), nil}, 1781 {nil, nil, NewSortValue(value.NewString("4"), TestTx.Flags), nil}, 1782 {nil, nil, NewSortValue(value.NewString("4"), TestTx.Flags), nil}, 1783 {nil, nil, NewSortValue(value.NewString("3"), TestTx.Flags), nil}, 1784 {nil, nil, NewSortValue(value.NewString("2"), TestTx.Flags), nil}, 1785 }, 1786 }, 1787 OrderBy: parser.OrderByClause{ 1788 Items: []parser.QueryExpression{ 1789 parser.OrderItem{ 1790 Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1791 }, 1792 }, 1793 }, 1794 Result: &View{ 1795 Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}), 1796 RecordSet: []Record{ 1797 NewRecordWithId(5, []value.Primary{ 1798 value.NewNull(), 1799 value.NewString("2"), 1800 value.NewString("4"), 1801 }), 1802 NewRecordWithId(1, []value.Primary{ 1803 value.NewString("1"), 1804 value.NewString("3"), 1805 value.NewString("2"), 1806 }), 1807 NewRecordWithId(4, []value.Primary{ 1808 value.NewString("1"), 1809 value.NewString("3"), 1810 value.NewNull(), 1811 }), 1812 NewRecordWithId(2, []value.Primary{ 1813 value.NewString("1"), 1814 value.NewString("4"), 1815 value.NewString("3"), 1816 }), 1817 NewRecordWithId(3, []value.Primary{ 1818 value.NewString("1"), 1819 value.NewString("4"), 1820 value.NewString("3"), 1821 }), 1822 }, 1823 sortValuesInEachCell: [][]*SortValue{ 1824 {nil, nil, NewSortValue(value.NewString("2"), TestTx.Flags), nil}, 1825 {nil, nil, NewSortValue(value.NewString("3"), TestTx.Flags), nil}, 1826 {nil, nil, NewSortValue(value.NewString("3"), TestTx.Flags), nil}, 1827 {nil, nil, NewSortValue(value.NewString("4"), TestTx.Flags), nil}, 1828 {nil, nil, NewSortValue(value.NewString("4"), TestTx.Flags), nil}, 1829 }, 1830 }, 1831 }, 1832 { 1833 Name: "Order By With Null Positions", 1834 View: &View{ 1835 Header: []HeaderField{ 1836 {View: "table1", Column: InternalIdColumn}, 1837 {View: "table1", Column: "column1", IsFromTable: true}, 1838 {View: "table1", Column: "column2", IsFromTable: true}, 1839 }, 1840 RecordSet: []Record{ 1841 NewRecordWithId(1, []value.Primary{ 1842 value.NewString("1"), 1843 value.NewNull(), 1844 }), 1845 NewRecordWithId(2, []value.Primary{ 1846 value.NewString("1"), 1847 value.NewString("2"), 1848 }), 1849 NewRecordWithId(3, []value.Primary{ 1850 value.NewNull(), 1851 value.NewString("2"), 1852 }), 1853 NewRecordWithId(4, []value.Primary{ 1854 value.NewString("1"), 1855 value.NewNull(), 1856 }), 1857 NewRecordWithId(5, []value.Primary{ 1858 value.NewString("1"), 1859 value.NewString("2"), 1860 }), 1861 }, 1862 }, 1863 OrderBy: parser.OrderByClause{ 1864 Items: []parser.QueryExpression{ 1865 parser.OrderItem{ 1866 Value: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 1867 NullsPosition: parser.Token{Token: parser.LAST, Literal: "last"}, 1868 }, 1869 parser.OrderItem{ 1870 Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1871 NullsPosition: parser.Token{Token: parser.FIRST, Literal: "first"}, 1872 }, 1873 }, 1874 }, 1875 Result: &View{ 1876 Header: []HeaderField{ 1877 {View: "table1", Column: InternalIdColumn}, 1878 {View: "table1", Column: "column1", IsFromTable: true}, 1879 {View: "table1", Column: "column2", IsFromTable: true}, 1880 }, 1881 RecordSet: []Record{ 1882 NewRecordWithId(1, []value.Primary{ 1883 value.NewString("1"), 1884 value.NewNull(), 1885 }), 1886 NewRecordWithId(4, []value.Primary{ 1887 value.NewString("1"), 1888 value.NewNull(), 1889 }), 1890 NewRecordWithId(2, []value.Primary{ 1891 value.NewString("1"), 1892 value.NewString("2"), 1893 }), 1894 NewRecordWithId(5, []value.Primary{ 1895 value.NewString("1"), 1896 value.NewString("2"), 1897 }), 1898 NewRecordWithId(3, []value.Primary{ 1899 value.NewNull(), 1900 value.NewString("2"), 1901 }), 1902 }, 1903 }, 1904 }, 1905 { 1906 Name: "Order By Record Extend Error", 1907 View: &View{ 1908 Header: []HeaderField{ 1909 {View: "table1", Column: InternalIdColumn}, 1910 {View: "table1", Column: "column1", IsFromTable: true}, 1911 {View: "table1", Column: "column2", IsFromTable: true}, 1912 }, 1913 RecordSet: []Record{ 1914 NewRecordWithId(1, []value.Primary{ 1915 value.NewString("1"), 1916 value.NewNull(), 1917 }), 1918 NewRecordWithId(2, []value.Primary{ 1919 value.NewString("1"), 1920 value.NewString("2"), 1921 }), 1922 }, 1923 }, 1924 OrderBy: parser.OrderByClause{ 1925 Items: []parser.QueryExpression{ 1926 parser.OrderItem{ 1927 Value: parser.AggregateFunction{ 1928 Name: "sum", 1929 Distinct: parser.Token{}, 1930 Args: []parser.QueryExpression{ 1931 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 1932 }, 1933 }, 1934 }, 1935 }, 1936 }, 1937 Error: "function sum cannot aggregate not grouping records", 1938 }, 1939 } 1940 1941 func TestView_OrderBy(t *testing.T) { 1942 scope := NewReferenceScope(TestTx) 1943 ctx := context.Background() 1944 for _, v := range viewOrderByTests { 1945 err := v.View.OrderBy(ctx, scope, v.OrderBy) 1946 if err != nil { 1947 if len(v.Error) < 1 { 1948 t.Errorf("%s: unexpected error %q", v.Name, err) 1949 } else if err.Error() != v.Error { 1950 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 1951 } 1952 continue 1953 } 1954 if 0 < len(v.Error) { 1955 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 1956 continue 1957 } 1958 if !reflect.DeepEqual(v.View.Header, v.Result.Header) { 1959 t.Errorf("%s: header = %v, want %v", v.Name, v.View.Header, v.Result.Header) 1960 } 1961 if !reflect.DeepEqual(v.View.RecordSet, v.Result.RecordSet) { 1962 t.Errorf("%s: records = %s, want %s", v.Name, v.View.RecordSet, v.Result.RecordSet) 1963 } 1964 } 1965 } 1966 1967 var viewExtendRecordCapacityTests = []struct { 1968 Name string 1969 View *View 1970 Scope *ReferenceScope 1971 Exprs []parser.QueryExpression 1972 Result int 1973 Error string 1974 }{ 1975 { 1976 Name: "ExtendRecordCapacity", 1977 View: &View{ 1978 Header: NewHeader("table1", []string{"column1", "column2"}), 1979 RecordSet: RecordSet{ 1980 NewRecord([]value.Primary{ 1981 value.NewInteger(1), 1982 value.NewInteger(2), 1983 }), 1984 }, 1985 isGrouped: true, 1986 }, 1987 Scope: GenerateReferenceScope([]map[string]map[string]interface{}{ 1988 { 1989 scopeNameFunctions: { 1990 "USERFUNC": &UserDefinedFunction{ 1991 Name: parser.Identifier{Literal: "userfunc"}, 1992 Parameters: []parser.Variable{ 1993 {Name: "arg1"}, 1994 }, 1995 RequiredArgs: 1, 1996 Statements: []parser.Statement{ 1997 parser.Return{Value: parser.Variable{Name: "arg1"}}, 1998 }, 1999 IsAggregate: true, 2000 }, 2001 }, 2002 }, 2003 }, nil, time.Time{}, nil), 2004 Exprs: []parser.QueryExpression{ 2005 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 2006 parser.ColumnNumber{View: parser.Identifier{Literal: "table1"}, Number: value.NewInteger(2)}, 2007 parser.Function{ 2008 Name: "userfunc", 2009 Args: []parser.QueryExpression{ 2010 parser.NewIntegerValueFromString("1"), 2011 }, 2012 }, 2013 parser.AggregateFunction{ 2014 Name: "avg", 2015 Distinct: parser.Token{}, 2016 Args: []parser.QueryExpression{ 2017 parser.AggregateFunction{ 2018 Name: "avg", 2019 Args: []parser.QueryExpression{ 2020 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 2021 }, 2022 }, 2023 }, 2024 }, 2025 parser.AnalyticFunction{ 2026 Name: "rank", 2027 AnalyticClause: parser.AnalyticClause{ 2028 PartitionClause: parser.PartitionClause{ 2029 Values: []parser.QueryExpression{ 2030 parser.Arithmetic{ 2031 LHS: parser.NewIntegerValueFromString("1"), 2032 RHS: parser.NewIntegerValueFromString("2"), 2033 Operator: parser.Token{Token: '+', Literal: "+"}, 2034 }, 2035 }, 2036 }, 2037 OrderByClause: parser.OrderByClause{ 2038 Items: []parser.QueryExpression{ 2039 parser.OrderItem{ 2040 Value: parser.Arithmetic{ 2041 LHS: parser.NewIntegerValueFromString("3"), 2042 RHS: parser.NewIntegerValueFromString("4"), 2043 Operator: parser.Token{Token: '+', Literal: "+"}, 2044 }, 2045 }, 2046 }, 2047 }, 2048 }, 2049 }, 2050 parser.Arithmetic{ 2051 LHS: parser.NewIntegerValueFromString("5"), 2052 RHS: parser.NewIntegerValueFromString("6"), 2053 Operator: parser.Token{Token: '+', Literal: "+"}, 2054 }, 2055 }, 2056 Result: 8, 2057 }, 2058 } 2059 2060 func TestView_ExtendRecordCapacity(t *testing.T) { 2061 ctx := context.Background() 2062 for _, v := range viewExtendRecordCapacityTests { 2063 if v.Scope == nil { 2064 v.Scope = NewReferenceScope(TestTx) 2065 } 2066 2067 err := v.View.ExtendRecordCapacity(ctx, v.Scope, v.Exprs, nil) 2068 if err != nil { 2069 if len(v.Error) < 1 { 2070 t.Errorf("%s: unexpected error %q", v.Name, err) 2071 } else if err.Error() != v.Error { 2072 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 2073 } 2074 continue 2075 } 2076 if 0 < len(v.Error) { 2077 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 2078 continue 2079 } 2080 if cap(v.View.RecordSet[0]) != v.Result { 2081 t.Errorf("%s: record capacity = %d, want %d", v.Name, cap(v.View.RecordSet[0]), v.Result) 2082 } 2083 } 2084 } 2085 2086 var viewLimitTests = []struct { 2087 Name string 2088 View *View 2089 Limit parser.LimitClause 2090 Result *View 2091 Error string 2092 }{ 2093 { 2094 Name: "Limit", 2095 View: &View{ 2096 Header: []HeaderField{ 2097 {View: "table1", Column: InternalIdColumn}, 2098 {View: "table1", Column: "column1", IsFromTable: true}, 2099 {View: "table1", Column: "column2", IsFromTable: true}, 2100 }, 2101 RecordSet: []Record{ 2102 NewRecordWithId(1, []value.Primary{ 2103 value.NewString("1"), 2104 value.NewString("str1"), 2105 }), 2106 NewRecordWithId(2, []value.Primary{ 2107 value.NewString("1"), 2108 value.NewString("str1"), 2109 }), 2110 NewRecordWithId(3, []value.Primary{ 2111 value.NewString("1"), 2112 value.NewString("str1"), 2113 }), 2114 NewRecordWithId(4, []value.Primary{ 2115 value.NewString("2"), 2116 value.NewString("str2"), 2117 }), 2118 NewRecordWithId(4, []value.Primary{ 2119 value.NewString("3"), 2120 value.NewString("str3"), 2121 }), 2122 }, 2123 }, 2124 Limit: parser.LimitClause{Value: parser.NewIntegerValueFromString("2")}, 2125 Result: &View{ 2126 Header: []HeaderField{ 2127 {View: "table1", Column: InternalIdColumn}, 2128 {View: "table1", Column: "column1", IsFromTable: true}, 2129 {View: "table1", Column: "column2", IsFromTable: true}, 2130 }, 2131 RecordSet: []Record{ 2132 NewRecordWithId(1, []value.Primary{ 2133 value.NewString("1"), 2134 value.NewString("str1"), 2135 }), 2136 NewRecordWithId(2, []value.Primary{ 2137 value.NewString("1"), 2138 value.NewString("str1"), 2139 }), 2140 }, 2141 }, 2142 }, 2143 { 2144 Name: "Limit With Ties", 2145 View: &View{ 2146 Header: []HeaderField{ 2147 {View: "table1", Column: InternalIdColumn}, 2148 {View: "table1", Column: "column1", IsFromTable: true}, 2149 {View: "table1", Column: "column2", IsFromTable: true}, 2150 }, 2151 RecordSet: []Record{ 2152 NewRecordWithId(1, []value.Primary{ 2153 value.NewString("1"), 2154 value.NewString("str1"), 2155 }), 2156 NewRecordWithId(2, []value.Primary{ 2157 value.NewString("1"), 2158 value.NewString("str1"), 2159 }), 2160 NewRecordWithId(3, []value.Primary{ 2161 value.NewString("1"), 2162 value.NewString("str1"), 2163 }), 2164 NewRecordWithId(4, []value.Primary{ 2165 value.NewString("2"), 2166 value.NewString("str2"), 2167 }), 2168 NewRecordWithId(4, []value.Primary{ 2169 value.NewString("3"), 2170 value.NewString("str3"), 2171 }), 2172 }, 2173 sortValuesInEachRecord: []SortValues{ 2174 { 2175 &SortValue{Type: IntegerType, Integer: 1}, 2176 &SortValue{Type: StringType, String: "str1"}, 2177 }, 2178 { 2179 &SortValue{Type: IntegerType, Integer: 1}, 2180 &SortValue{Type: StringType, String: "str1"}, 2181 }, 2182 { 2183 &SortValue{Type: IntegerType, Integer: 1}, 2184 &SortValue{Type: StringType, String: "str1"}, 2185 }, 2186 { 2187 &SortValue{Type: IntegerType, Integer: 2}, 2188 &SortValue{Type: StringType, String: "str2"}, 2189 }, 2190 { 2191 &SortValue{Type: IntegerType, Integer: 3}, 2192 &SortValue{Type: StringType, String: "str3"}, 2193 }, 2194 }, 2195 }, 2196 Limit: parser.LimitClause{Value: parser.NewIntegerValueFromString("2"), Restriction: parser.Token{Token: parser.TIES}}, 2197 Result: &View{ 2198 Header: []HeaderField{ 2199 {View: "table1", Column: InternalIdColumn}, 2200 {View: "table1", Column: "column1", IsFromTable: true}, 2201 {View: "table1", Column: "column2", IsFromTable: true}, 2202 }, 2203 RecordSet: []Record{ 2204 NewRecordWithId(1, []value.Primary{ 2205 value.NewString("1"), 2206 value.NewString("str1"), 2207 }), 2208 NewRecordWithId(2, []value.Primary{ 2209 value.NewString("1"), 2210 value.NewString("str1"), 2211 }), 2212 NewRecordWithId(3, []value.Primary{ 2213 value.NewString("1"), 2214 value.NewString("str1"), 2215 }), 2216 }, 2217 sortValuesInEachRecord: []SortValues{ 2218 { 2219 &SortValue{Type: IntegerType, Integer: 1}, 2220 &SortValue{Type: StringType, String: "str1"}, 2221 }, 2222 { 2223 &SortValue{Type: IntegerType, Integer: 1}, 2224 &SortValue{Type: StringType, String: "str1"}, 2225 }, 2226 { 2227 &SortValue{Type: IntegerType, Integer: 1}, 2228 &SortValue{Type: StringType, String: "str1"}, 2229 }, 2230 { 2231 &SortValue{Type: IntegerType, Integer: 2}, 2232 &SortValue{Type: StringType, String: "str2"}, 2233 }, 2234 { 2235 &SortValue{Type: IntegerType, Integer: 3}, 2236 &SortValue{Type: StringType, String: "str3"}, 2237 }, 2238 }, 2239 }, 2240 }, 2241 { 2242 Name: "Limit By Percentage", 2243 View: &View{ 2244 Header: []HeaderField{ 2245 {View: "table1", Column: InternalIdColumn}, 2246 {View: "table1", Column: "column1", IsFromTable: true}, 2247 {View: "table1", Column: "column2", IsFromTable: true}, 2248 }, 2249 RecordSet: []Record{ 2250 NewRecordWithId(2, []value.Primary{ 2251 value.NewString("1"), 2252 value.NewString("str1"), 2253 }), 2254 NewRecordWithId(3, []value.Primary{ 2255 value.NewString("1"), 2256 value.NewString("str1"), 2257 }), 2258 NewRecordWithId(4, []value.Primary{ 2259 value.NewString("2"), 2260 value.NewString("str2"), 2261 }), 2262 NewRecordWithId(4, []value.Primary{ 2263 value.NewString("3"), 2264 value.NewString("str3"), 2265 }), 2266 }, 2267 offset: 1, 2268 }, 2269 Limit: parser.LimitClause{Value: parser.NewFloatValue(50.5), Unit: parser.Token{Token: parser.PERCENT}}, 2270 Result: &View{ 2271 Header: []HeaderField{ 2272 {View: "table1", Column: InternalIdColumn}, 2273 {View: "table1", Column: "column1", IsFromTable: true}, 2274 {View: "table1", Column: "column2", IsFromTable: true}, 2275 }, 2276 RecordSet: []Record{ 2277 NewRecordWithId(2, []value.Primary{ 2278 value.NewString("1"), 2279 value.NewString("str1"), 2280 }), 2281 NewRecordWithId(3, []value.Primary{ 2282 value.NewString("1"), 2283 value.NewString("str1"), 2284 }), 2285 NewRecordWithId(4, []value.Primary{ 2286 value.NewString("2"), 2287 value.NewString("str2"), 2288 }), 2289 }, 2290 offset: 1, 2291 }, 2292 }, 2293 { 2294 Name: "Limit By Over 100 Percentage", 2295 View: &View{ 2296 Header: []HeaderField{ 2297 {View: "table1", Column: InternalIdColumn}, 2298 {View: "table1", Column: "column1", IsFromTable: true}, 2299 {View: "table1", Column: "column2", IsFromTable: true}, 2300 }, 2301 RecordSet: []Record{ 2302 NewRecordWithId(1, []value.Primary{ 2303 value.NewString("1"), 2304 value.NewString("str1"), 2305 }), 2306 NewRecordWithId(2, []value.Primary{ 2307 value.NewString("1"), 2308 value.NewString("str1"), 2309 }), 2310 NewRecordWithId(3, []value.Primary{ 2311 value.NewString("1"), 2312 value.NewString("str1"), 2313 }), 2314 NewRecordWithId(4, []value.Primary{ 2315 value.NewString("2"), 2316 value.NewString("str2"), 2317 }), 2318 NewRecordWithId(4, []value.Primary{ 2319 value.NewString("3"), 2320 value.NewString("str3"), 2321 }), 2322 }, 2323 }, 2324 Limit: parser.LimitClause{Value: parser.NewFloatValue(150), Unit: parser.Token{Token: parser.PERCENT}}, 2325 Result: &View{ 2326 Header: []HeaderField{ 2327 {View: "table1", Column: InternalIdColumn}, 2328 {View: "table1", Column: "column1", IsFromTable: true}, 2329 {View: "table1", Column: "column2", IsFromTable: true}, 2330 }, 2331 RecordSet: []Record{ 2332 NewRecordWithId(1, []value.Primary{ 2333 value.NewString("1"), 2334 value.NewString("str1"), 2335 }), 2336 NewRecordWithId(2, []value.Primary{ 2337 value.NewString("1"), 2338 value.NewString("str1"), 2339 }), 2340 NewRecordWithId(3, []value.Primary{ 2341 value.NewString("1"), 2342 value.NewString("str1"), 2343 }), 2344 NewRecordWithId(4, []value.Primary{ 2345 value.NewString("2"), 2346 value.NewString("str2"), 2347 }), 2348 NewRecordWithId(4, []value.Primary{ 2349 value.NewString("3"), 2350 value.NewString("str3"), 2351 }), 2352 }, 2353 }, 2354 }, 2355 { 2356 Name: "Limit By Negative Percentage", 2357 View: &View{ 2358 Header: []HeaderField{ 2359 {View: "table1", Column: InternalIdColumn}, 2360 {View: "table1", Column: "column1", IsFromTable: true}, 2361 {View: "table1", Column: "column2", IsFromTable: true}, 2362 }, 2363 RecordSet: []Record{ 2364 NewRecordWithId(1, []value.Primary{ 2365 value.NewString("1"), 2366 value.NewString("str1"), 2367 }), 2368 NewRecordWithId(2, []value.Primary{ 2369 value.NewString("1"), 2370 value.NewString("str1"), 2371 }), 2372 NewRecordWithId(3, []value.Primary{ 2373 value.NewString("1"), 2374 value.NewString("str1"), 2375 }), 2376 NewRecordWithId(4, []value.Primary{ 2377 value.NewString("2"), 2378 value.NewString("str2"), 2379 }), 2380 NewRecordWithId(4, []value.Primary{ 2381 value.NewString("3"), 2382 value.NewString("str3"), 2383 }), 2384 }, 2385 }, 2386 Limit: parser.LimitClause{Value: parser.NewFloatValue(-10), Unit: parser.Token{Token: parser.PERCENT}}, 2387 Result: &View{ 2388 Header: []HeaderField{ 2389 {View: "table1", Column: InternalIdColumn}, 2390 {View: "table1", Column: "column1", IsFromTable: true}, 2391 {View: "table1", Column: "column2", IsFromTable: true}, 2392 }, 2393 RecordSet: []Record{}, 2394 }, 2395 }, 2396 { 2397 Name: "Limit Greater Than RecordSet", 2398 View: &View{ 2399 Header: []HeaderField{ 2400 {View: "table1", Column: InternalIdColumn}, 2401 {View: "table1", Column: "column1", IsFromTable: true}, 2402 {View: "table1", Column: "column2", IsFromTable: true}, 2403 }, 2404 RecordSet: []Record{ 2405 NewRecordWithId(1, []value.Primary{ 2406 value.NewString("1"), 2407 value.NewString("str1"), 2408 }), 2409 NewRecordWithId(2, []value.Primary{ 2410 value.NewString("1"), 2411 value.NewString("str1"), 2412 }), 2413 }, 2414 }, 2415 Limit: parser.LimitClause{Value: parser.NewIntegerValueFromString("5")}, 2416 Result: &View{ 2417 Header: []HeaderField{ 2418 {View: "table1", Column: InternalIdColumn}, 2419 {View: "table1", Column: "column1", IsFromTable: true}, 2420 {View: "table1", Column: "column2", IsFromTable: true}, 2421 }, 2422 RecordSet: []Record{ 2423 NewRecordWithId(1, []value.Primary{ 2424 value.NewString("1"), 2425 value.NewString("str1"), 2426 }), 2427 NewRecordWithId(2, []value.Primary{ 2428 value.NewString("1"), 2429 value.NewString("str1"), 2430 }), 2431 }, 2432 }, 2433 }, 2434 { 2435 Name: "Limit Evaluate Error", 2436 View: &View{ 2437 Header: []HeaderField{ 2438 {View: "table1", Column: InternalIdColumn}, 2439 {View: "table1", Column: "column1", IsFromTable: true}, 2440 {View: "table1", Column: "column2", IsFromTable: true}, 2441 }, 2442 RecordSet: []Record{ 2443 NewRecordWithId(1, []value.Primary{ 2444 value.NewString("1"), 2445 value.NewString("str1"), 2446 }), 2447 NewRecordWithId(2, []value.Primary{ 2448 value.NewString("1"), 2449 value.NewString("str1"), 2450 }), 2451 }, 2452 }, 2453 Limit: parser.LimitClause{Value: parser.Variable{Name: "notexist"}}, 2454 Error: "variable @notexist is undeclared", 2455 }, 2456 { 2457 Name: "Limit Value Error", 2458 View: &View{ 2459 Header: []HeaderField{ 2460 {View: "table1", Column: InternalIdColumn}, 2461 {View: "table1", Column: "column1", IsFromTable: true}, 2462 {View: "table1", Column: "column2", IsFromTable: true}, 2463 }, 2464 RecordSet: []Record{ 2465 NewRecordWithId(1, []value.Primary{ 2466 value.NewString("1"), 2467 value.NewString("str1"), 2468 }), 2469 NewRecordWithId(2, []value.Primary{ 2470 value.NewString("1"), 2471 value.NewString("str1"), 2472 }), 2473 }, 2474 }, 2475 Limit: parser.LimitClause{Value: parser.NewStringValue("str")}, 2476 Error: "limit number of records 'str' is not an integer value", 2477 }, 2478 { 2479 Name: "Limit Negative Value", 2480 View: &View{ 2481 Header: []HeaderField{ 2482 {View: "table1", Column: InternalIdColumn}, 2483 {View: "table1", Column: "column1", IsFromTable: true}, 2484 {View: "table1", Column: "column2", IsFromTable: true}, 2485 }, 2486 RecordSet: []Record{ 2487 NewRecordWithId(1, []value.Primary{ 2488 value.NewString("1"), 2489 value.NewString("str1"), 2490 }), 2491 NewRecordWithId(2, []value.Primary{ 2492 value.NewString("1"), 2493 value.NewString("str1"), 2494 }), 2495 }, 2496 }, 2497 Limit: parser.LimitClause{Value: parser.NewIntegerValue(-1)}, 2498 Result: &View{ 2499 Header: []HeaderField{ 2500 {View: "table1", Column: InternalIdColumn}, 2501 {View: "table1", Column: "column1", IsFromTable: true}, 2502 {View: "table1", Column: "column2", IsFromTable: true}, 2503 }, 2504 RecordSet: []Record{}, 2505 }, 2506 }, 2507 { 2508 Name: "Limit By Percentage Value Error", 2509 View: &View{ 2510 Header: []HeaderField{ 2511 {View: "table1", Column: InternalIdColumn}, 2512 {View: "table1", Column: "column1", IsFromTable: true}, 2513 {View: "table1", Column: "column2", IsFromTable: true}, 2514 }, 2515 RecordSet: []Record{ 2516 NewRecordWithId(1, []value.Primary{ 2517 value.NewString("1"), 2518 value.NewString("str1"), 2519 }), 2520 NewRecordWithId(2, []value.Primary{ 2521 value.NewString("1"), 2522 value.NewString("str1"), 2523 }), 2524 }, 2525 }, 2526 Limit: parser.LimitClause{Value: parser.NewStringValue("str"), Unit: parser.Token{Token: parser.PERCENT}}, 2527 Error: "limit percentage 'str' is not a float value", 2528 }, 2529 } 2530 2531 func TestView_Limit(t *testing.T) { 2532 scope := NewReferenceScope(TestTx) 2533 ctx := context.Background() 2534 for _, v := range viewLimitTests { 2535 err := v.View.Limit(ctx, scope, v.Limit) 2536 if err != nil { 2537 if len(v.Error) < 1 { 2538 t.Errorf("%s: unexpected error %q", v.Name, err) 2539 } else if err.Error() != v.Error { 2540 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 2541 } 2542 continue 2543 } 2544 if 0 < len(v.Error) { 2545 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 2546 continue 2547 } 2548 if !reflect.DeepEqual(v.View, v.Result) { 2549 t.Errorf("%s: view = %v, want %v", v.Name, v.View, v.Result) 2550 } 2551 } 2552 } 2553 2554 var viewOffsetTests = []struct { 2555 Name string 2556 View *View 2557 Offset parser.OffsetClause 2558 Result *View 2559 Error string 2560 }{ 2561 { 2562 Name: "Offset", 2563 View: &View{ 2564 Header: []HeaderField{ 2565 {View: "table1", Column: InternalIdColumn}, 2566 {View: "table1", Column: "column1", IsFromTable: true}, 2567 {View: "table1", Column: "column2", IsFromTable: true}, 2568 }, 2569 RecordSet: []Record{ 2570 NewRecordWithId(1, []value.Primary{ 2571 value.NewString("1"), 2572 value.NewString("str1"), 2573 }), 2574 NewRecordWithId(2, []value.Primary{ 2575 value.NewString("1"), 2576 value.NewString("str1"), 2577 }), 2578 NewRecordWithId(3, []value.Primary{ 2579 value.NewString("1"), 2580 value.NewString("str1"), 2581 }), 2582 NewRecordWithId(4, []value.Primary{ 2583 value.NewString("2"), 2584 value.NewString("str2"), 2585 }), 2586 }, 2587 }, 2588 Offset: parser.OffsetClause{Value: parser.NewIntegerValueFromString("3")}, 2589 Result: &View{ 2590 Header: []HeaderField{ 2591 {View: "table1", Column: InternalIdColumn}, 2592 {View: "table1", Column: "column1", IsFromTable: true}, 2593 {View: "table1", Column: "column2", IsFromTable: true}, 2594 }, 2595 RecordSet: []Record{ 2596 NewRecordWithId(4, []value.Primary{ 2597 value.NewString("2"), 2598 value.NewString("str2"), 2599 }), 2600 }, 2601 offset: 3, 2602 }, 2603 }, 2604 { 2605 Name: "Offset Equal To Record Length", 2606 View: &View{ 2607 Header: []HeaderField{ 2608 {View: "table1", Column: InternalIdColumn}, 2609 {View: "table1", Column: "column1", IsFromTable: true}, 2610 {View: "table1", Column: "column2", IsFromTable: true}, 2611 }, 2612 RecordSet: []Record{ 2613 NewRecordWithId(1, []value.Primary{ 2614 value.NewString("1"), 2615 value.NewString("str1"), 2616 }), 2617 NewRecordWithId(2, []value.Primary{ 2618 value.NewString("1"), 2619 value.NewString("str1"), 2620 }), 2621 NewRecordWithId(3, []value.Primary{ 2622 value.NewString("1"), 2623 value.NewString("str1"), 2624 }), 2625 NewRecordWithId(4, []value.Primary{ 2626 value.NewString("2"), 2627 value.NewString("str2"), 2628 }), 2629 }, 2630 }, 2631 Offset: parser.OffsetClause{Value: parser.NewIntegerValueFromString("4")}, 2632 Result: &View{ 2633 Header: []HeaderField{ 2634 {View: "table1", Column: InternalIdColumn}, 2635 {View: "table1", Column: "column1", IsFromTable: true}, 2636 {View: "table1", Column: "column2", IsFromTable: true}, 2637 }, 2638 RecordSet: []Record{}, 2639 offset: 4, 2640 }, 2641 }, 2642 { 2643 Name: "Offset Evaluate Error", 2644 View: &View{ 2645 Header: []HeaderField{ 2646 {View: "table1", Column: InternalIdColumn}, 2647 {View: "table1", Column: "column1", IsFromTable: true}, 2648 {View: "table1", Column: "column2", IsFromTable: true}, 2649 }, 2650 RecordSet: []Record{ 2651 NewRecordWithId(1, []value.Primary{ 2652 value.NewString("1"), 2653 value.NewString("str1"), 2654 }), 2655 NewRecordWithId(2, []value.Primary{ 2656 value.NewString("1"), 2657 value.NewString("str1"), 2658 }), 2659 NewRecordWithId(3, []value.Primary{ 2660 value.NewString("1"), 2661 value.NewString("str1"), 2662 }), 2663 NewRecordWithId(4, []value.Primary{ 2664 value.NewString("2"), 2665 value.NewString("str2"), 2666 }), 2667 }, 2668 }, 2669 Offset: parser.OffsetClause{Value: parser.Variable{Name: "notexist"}}, 2670 Error: "variable @notexist is undeclared", 2671 }, 2672 { 2673 Name: "Offset Value Error", 2674 View: &View{ 2675 Header: []HeaderField{ 2676 {View: "table1", Column: InternalIdColumn}, 2677 {View: "table1", Column: "column1", IsFromTable: true}, 2678 {View: "table1", Column: "column2", IsFromTable: true}, 2679 }, 2680 RecordSet: []Record{ 2681 NewRecordWithId(1, []value.Primary{ 2682 value.NewString("1"), 2683 value.NewString("str1"), 2684 }), 2685 NewRecordWithId(2, []value.Primary{ 2686 value.NewString("1"), 2687 value.NewString("str1"), 2688 }), 2689 NewRecordWithId(3, []value.Primary{ 2690 value.NewString("1"), 2691 value.NewString("str1"), 2692 }), 2693 NewRecordWithId(4, []value.Primary{ 2694 value.NewString("2"), 2695 value.NewString("str2"), 2696 }), 2697 }, 2698 }, 2699 Offset: parser.OffsetClause{Value: parser.NewStringValue("str")}, 2700 Error: "offset number 'str' is not an integer value", 2701 }, 2702 { 2703 Name: "Offset Negative Number", 2704 View: &View{ 2705 Header: []HeaderField{ 2706 {View: "table1", Column: InternalIdColumn}, 2707 {View: "table1", Column: "column1", IsFromTable: true}, 2708 {View: "table1", Column: "column2", IsFromTable: true}, 2709 }, 2710 RecordSet: []Record{ 2711 NewRecordWithId(1, []value.Primary{ 2712 value.NewString("1"), 2713 value.NewString("str1"), 2714 }), 2715 NewRecordWithId(2, []value.Primary{ 2716 value.NewString("1"), 2717 value.NewString("str1"), 2718 }), 2719 }, 2720 }, 2721 Offset: parser.OffsetClause{Value: parser.NewIntegerValue(-3)}, 2722 Result: &View{ 2723 Header: []HeaderField{ 2724 {View: "table1", Column: InternalIdColumn}, 2725 {View: "table1", Column: "column1", IsFromTable: true}, 2726 {View: "table1", Column: "column2", IsFromTable: true}, 2727 }, 2728 RecordSet: []Record{ 2729 NewRecordWithId(1, []value.Primary{ 2730 value.NewString("1"), 2731 value.NewString("str1"), 2732 }), 2733 NewRecordWithId(2, []value.Primary{ 2734 value.NewString("1"), 2735 value.NewString("str1"), 2736 }), 2737 }, 2738 offset: 0, 2739 }, 2740 }, 2741 } 2742 2743 func TestView_Offset(t *testing.T) { 2744 scope := NewReferenceScope(TestTx) 2745 ctx := context.Background() 2746 for _, v := range viewOffsetTests { 2747 err := v.View.Offset(ctx, scope, v.Offset) 2748 if err != nil { 2749 if len(v.Error) < 1 { 2750 t.Errorf("%s: unexpected error %q", v.Name, err) 2751 } else if err.Error() != v.Error { 2752 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 2753 } 2754 continue 2755 } 2756 if 0 < len(v.Error) { 2757 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 2758 continue 2759 } 2760 if !reflect.DeepEqual(v.View, v.Result) { 2761 t.Errorf("%s: view = %v, want %v", v.Name, v.View, v.Result) 2762 } 2763 } 2764 } 2765 2766 var viewInsertValuesTests = []struct { 2767 Name string 2768 Fields []parser.QueryExpression 2769 ValuesList []parser.QueryExpression 2770 Result *View 2771 UpdateCount int 2772 Error string 2773 }{ 2774 { 2775 Name: "InsertValues", 2776 Fields: []parser.QueryExpression{ 2777 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 2778 }, 2779 ValuesList: []parser.QueryExpression{ 2780 parser.RowValue{ 2781 Value: parser.ValueList{ 2782 Values: []parser.QueryExpression{ 2783 parser.NewIntegerValueFromString("3"), 2784 }, 2785 }, 2786 }, 2787 parser.RowValue{ 2788 Value: parser.ValueList{ 2789 Values: []parser.QueryExpression{ 2790 parser.NewIntegerValueFromString("4"), 2791 }, 2792 }, 2793 }, 2794 }, 2795 Result: &View{ 2796 Header: NewHeaderWithId("table1", []string{"column1", "column2"}), 2797 RecordSet: []Record{ 2798 NewRecord([]value.Primary{ 2799 value.NewInteger(1), 2800 value.NewString("1"), 2801 value.NewString("str1"), 2802 }), 2803 NewRecord([]value.Primary{ 2804 value.NewInteger(2), 2805 value.NewString("2"), 2806 value.NewString("str2"), 2807 }), 2808 NewRecord([]value.Primary{ 2809 value.NewNull(), 2810 value.NewInteger(3), 2811 value.NewNull(), 2812 }), 2813 NewRecord([]value.Primary{ 2814 value.NewNull(), 2815 value.NewInteger(4), 2816 value.NewNull(), 2817 }), 2818 }, 2819 }, 2820 UpdateCount: 2, 2821 }, 2822 { 2823 Name: "InsertValues Field Length Does Not Match Error", 2824 Fields: []parser.QueryExpression{ 2825 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 2826 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2827 }, 2828 ValuesList: []parser.QueryExpression{ 2829 parser.RowValue{ 2830 Value: parser.ValueList{ 2831 Values: []parser.QueryExpression{ 2832 parser.NewIntegerValueFromString("3"), 2833 }, 2834 }, 2835 }, 2836 }, 2837 Error: "row value should contain exactly 2 values", 2838 }, 2839 { 2840 Name: "InsertValues Value Evaluation Error", 2841 Fields: []parser.QueryExpression{ 2842 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 2843 }, 2844 ValuesList: []parser.QueryExpression{ 2845 parser.RowValue{ 2846 Value: parser.ValueList{ 2847 Values: []parser.QueryExpression{ 2848 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 2849 }, 2850 }, 2851 }, 2852 }, 2853 Error: "field notexist does not exist", 2854 }, 2855 { 2856 Name: "InsertValues Field Does Not Exist Error", 2857 Fields: []parser.QueryExpression{ 2858 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 2859 }, 2860 ValuesList: []parser.QueryExpression{ 2861 parser.RowValue{ 2862 Value: parser.ValueList{ 2863 Values: []parser.QueryExpression{ 2864 parser.NewIntegerValueFromString("3"), 2865 }, 2866 }, 2867 }, 2868 }, 2869 Error: "field notexist does not exist", 2870 }, 2871 } 2872 2873 func TestView_InsertValues(t *testing.T) { 2874 view := &View{ 2875 Header: NewHeaderWithId("table1", []string{"column1", "column2"}), 2876 RecordSet: []Record{ 2877 NewRecordWithId(1, []value.Primary{ 2878 value.NewString("1"), 2879 value.NewString("str1"), 2880 }), 2881 NewRecordWithId(2, []value.Primary{ 2882 value.NewString("2"), 2883 value.NewString("str2"), 2884 }), 2885 }, 2886 } 2887 2888 scope := NewReferenceScope(TestTx) 2889 ctx := context.Background() 2890 for _, v := range viewInsertValuesTests { 2891 cnt, err := view.InsertValues(ctx, scope, v.Fields, v.ValuesList) 2892 if err != nil { 2893 if len(v.Error) < 1 { 2894 t.Errorf("%s: unexpected error %q", v.Name, err) 2895 } else if err.Error() != v.Error { 2896 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 2897 } 2898 continue 2899 } 2900 if 0 < len(v.Error) { 2901 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 2902 continue 2903 } 2904 if !reflect.DeepEqual(view, v.Result) { 2905 t.Errorf("%s: result = %v, want %v", v.Name, view, v.Result) 2906 } 2907 if cnt != v.UpdateCount { 2908 t.Errorf("%s: update count = %d, want %d", v.Name, cnt, v.UpdateCount) 2909 } 2910 2911 } 2912 } 2913 2914 var viewInsertFromQueryTests = []struct { 2915 Name string 2916 Fields []parser.QueryExpression 2917 Query parser.SelectQuery 2918 Result *View 2919 UpdateCount int 2920 Error string 2921 }{ 2922 { 2923 Name: "InsertFromQuery", 2924 Fields: []parser.QueryExpression{ 2925 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 2926 }, 2927 Query: parser.SelectQuery{ 2928 SelectEntity: parser.SelectEntity{ 2929 SelectClause: parser.SelectClause{ 2930 Fields: []parser.QueryExpression{ 2931 parser.Field{Object: parser.NewIntegerValueFromString("3")}, 2932 }, 2933 }, 2934 }, 2935 }, 2936 Result: &View{ 2937 Header: NewHeaderWithId("table1", []string{"column1", "column2"}), 2938 RecordSet: []Record{ 2939 NewRecord([]value.Primary{ 2940 value.NewInteger(1), 2941 value.NewString("1"), 2942 value.NewString("str1"), 2943 }), 2944 NewRecord([]value.Primary{ 2945 value.NewInteger(2), 2946 value.NewString("2"), 2947 value.NewString("str2"), 2948 }), 2949 NewRecord([]value.Primary{ 2950 value.NewNull(), 2951 value.NewInteger(3), 2952 value.NewNull(), 2953 }), 2954 }, 2955 }, 2956 UpdateCount: 1, 2957 }, 2958 { 2959 Name: "InsertFromQuery Field Lenght Does Not Match Error", 2960 Fields: []parser.QueryExpression{ 2961 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 2962 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2963 }, 2964 Query: parser.SelectQuery{ 2965 SelectEntity: parser.SelectEntity{ 2966 SelectClause: parser.SelectClause{ 2967 Fields: []parser.QueryExpression{ 2968 parser.Field{Object: parser.NewIntegerValueFromString("3")}, 2969 }, 2970 }, 2971 }, 2972 }, 2973 Error: "select query should return exactly 2 fields", 2974 }, 2975 { 2976 Name: "InsertFromQuery Exuecution Error", 2977 Fields: []parser.QueryExpression{ 2978 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 2979 }, 2980 Query: parser.SelectQuery{ 2981 SelectEntity: parser.SelectEntity{ 2982 SelectClause: parser.SelectClause{ 2983 Fields: []parser.QueryExpression{ 2984 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}}, 2985 }, 2986 }, 2987 }, 2988 }, 2989 Error: "field notexist does not exist", 2990 }, 2991 } 2992 2993 func TestView_InsertFromQuery(t *testing.T) { 2994 view := &View{ 2995 Header: NewHeaderWithId("table1", []string{"column1", "column2"}), 2996 RecordSet: []Record{ 2997 NewRecordWithId(1, []value.Primary{ 2998 value.NewString("1"), 2999 value.NewString("str1"), 3000 }), 3001 NewRecordWithId(2, []value.Primary{ 3002 value.NewString("2"), 3003 value.NewString("str2"), 3004 }), 3005 }, 3006 } 3007 3008 scope := NewReferenceScope(TestTx) 3009 ctx := context.Background() 3010 for _, v := range viewInsertFromQueryTests { 3011 cnt, err := view.InsertFromQuery(ctx, scope, v.Fields, v.Query) 3012 if err != nil { 3013 if len(v.Error) < 1 { 3014 t.Errorf("%s: unexpected error %q", v.Name, err) 3015 } else if err.Error() != v.Error { 3016 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 3017 } 3018 continue 3019 } 3020 if 0 < len(v.Error) { 3021 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 3022 continue 3023 } 3024 if !reflect.DeepEqual(view, v.Result) { 3025 t.Errorf("%s: result = %v, want %v", v.Name, view, v.Result) 3026 } 3027 if cnt != v.UpdateCount { 3028 t.Errorf("%s: update count = %d, want %d", v.Name, cnt, v.UpdateCount) 3029 } 3030 } 3031 } 3032 3033 var viewReplaceValuesTests = []struct { 3034 Name string 3035 Fields []parser.QueryExpression 3036 Keys []parser.QueryExpression 3037 ValuesList []parser.QueryExpression 3038 Result *View 3039 UpdateCount int 3040 Error string 3041 }{ 3042 { 3043 Name: "ReplaceValues", 3044 Fields: []parser.QueryExpression{ 3045 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3046 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 3047 }, 3048 Keys: []parser.QueryExpression{ 3049 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3050 }, 3051 ValuesList: []parser.QueryExpression{ 3052 parser.RowValue{ 3053 Value: parser.ValueList{ 3054 Values: []parser.QueryExpression{ 3055 parser.NewIntegerValueFromString("1"), 3056 parser.NewStringValue("str3"), 3057 }, 3058 }, 3059 }, 3060 parser.RowValue{ 3061 Value: parser.ValueList{ 3062 Values: []parser.QueryExpression{ 3063 parser.NewIntegerValueFromString("4"), 3064 parser.NewStringValue("str4"), 3065 }, 3066 }, 3067 }, 3068 }, 3069 Result: &View{ 3070 Header: NewHeader("table1", []string{"column1", "column2"}), 3071 RecordSet: []Record{ 3072 NewRecord([]value.Primary{ 3073 value.NewString("1"), 3074 value.NewString("str3"), 3075 }), 3076 NewRecord([]value.Primary{ 3077 value.NewString("2"), 3078 value.NewString("str2"), 3079 }), 3080 NewRecord([]value.Primary{ 3081 value.NewInteger(4), 3082 value.NewString("str4"), 3083 }), 3084 }, 3085 }, 3086 UpdateCount: 2, 3087 }, 3088 { 3089 Name: "ReplaceValues Field Length Does Not Match Error", 3090 Fields: []parser.QueryExpression{ 3091 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3092 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 3093 }, 3094 Keys: []parser.QueryExpression{ 3095 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3096 }, 3097 ValuesList: []parser.QueryExpression{ 3098 parser.RowValue{ 3099 Value: parser.ValueList{ 3100 Values: []parser.QueryExpression{ 3101 parser.NewIntegerValueFromString("3"), 3102 }, 3103 }, 3104 }, 3105 }, 3106 Error: "row value should contain exactly 2 values", 3107 }, 3108 { 3109 Name: "ReplaceValues Value Evaluation Error", 3110 Fields: []parser.QueryExpression{ 3111 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3112 }, 3113 Keys: []parser.QueryExpression{ 3114 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3115 }, 3116 ValuesList: []parser.QueryExpression{ 3117 parser.RowValue{ 3118 Value: parser.ValueList{ 3119 Values: []parser.QueryExpression{ 3120 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 3121 }, 3122 }, 3123 }, 3124 }, 3125 Error: "field notexist does not exist", 3126 }, 3127 { 3128 Name: "ReplaceValues Field Does Not Exist Error", 3129 Fields: []parser.QueryExpression{ 3130 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 3131 }, 3132 Keys: []parser.QueryExpression{ 3133 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3134 }, 3135 ValuesList: []parser.QueryExpression{ 3136 parser.RowValue{ 3137 Value: parser.ValueList{ 3138 Values: []parser.QueryExpression{ 3139 parser.NewIntegerValueFromString("3"), 3140 }, 3141 }, 3142 }, 3143 }, 3144 Error: "field notexist does not exist", 3145 }, 3146 { 3147 Name: "ReplaceValues Key Does Not Exist Error", 3148 Fields: []parser.QueryExpression{ 3149 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3150 }, 3151 Keys: []parser.QueryExpression{ 3152 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 3153 }, 3154 ValuesList: []parser.QueryExpression{ 3155 parser.RowValue{ 3156 Value: parser.ValueList{ 3157 Values: []parser.QueryExpression{ 3158 parser.NewIntegerValueFromString("3"), 3159 }, 3160 }, 3161 }, 3162 }, 3163 Error: "field notexist does not exist", 3164 }, 3165 { 3166 Name: "ReplaceValues Key Not Set Error", 3167 Fields: []parser.QueryExpression{ 3168 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3169 }, 3170 Keys: []parser.QueryExpression{ 3171 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 3172 }, 3173 ValuesList: []parser.QueryExpression{ 3174 parser.RowValue{ 3175 Value: parser.ValueList{ 3176 Values: []parser.QueryExpression{ 3177 parser.NewIntegerValueFromString("3"), 3178 }, 3179 }, 3180 }, 3181 }, 3182 Error: "replace Key column2 is not set", 3183 }, 3184 } 3185 3186 func TestView_ReplaceValues(t *testing.T) { 3187 view := &View{ 3188 Header: NewHeader("table1", []string{"column1", "column2"}), 3189 RecordSet: []Record{ 3190 NewRecord([]value.Primary{ 3191 value.NewString("1"), 3192 value.NewString("str1"), 3193 }), 3194 NewRecord([]value.Primary{ 3195 value.NewString("2"), 3196 value.NewString("str2"), 3197 }), 3198 }, 3199 } 3200 3201 scope := NewReferenceScope(TestTx) 3202 ctx := context.Background() 3203 for _, v := range viewReplaceValuesTests { 3204 cnt, err := view.ReplaceValues(ctx, scope, v.Fields, v.ValuesList, v.Keys) 3205 if err != nil { 3206 if len(v.Error) < 1 { 3207 t.Errorf("%s: unexpected error %q", v.Name, err) 3208 } else if err.Error() != v.Error { 3209 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 3210 } 3211 continue 3212 } 3213 if 0 < len(v.Error) { 3214 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 3215 continue 3216 } 3217 if !reflect.DeepEqual(view, v.Result) { 3218 t.Errorf("%s: result = %v, want %v", v.Name, view, v.Result) 3219 } 3220 if cnt != v.UpdateCount { 3221 t.Errorf("%s: update count = %d, want %d", v.Name, cnt, v.UpdateCount) 3222 } 3223 3224 } 3225 } 3226 3227 var viewReplaceFromQueryTests = []struct { 3228 Name string 3229 Fields []parser.QueryExpression 3230 Keys []parser.QueryExpression 3231 Query parser.SelectQuery 3232 Result *View 3233 UpdateCount int 3234 Error string 3235 }{ 3236 { 3237 Name: "ReplaceFromQuery", 3238 Fields: []parser.QueryExpression{ 3239 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3240 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 3241 }, 3242 Keys: []parser.QueryExpression{ 3243 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3244 }, 3245 Query: parser.SelectQuery{ 3246 SelectEntity: parser.SelectEntity{ 3247 SelectClause: parser.SelectClause{ 3248 Fields: []parser.QueryExpression{ 3249 parser.Field{Object: parser.NewIntegerValueFromString("1")}, 3250 parser.Field{Object: parser.NewStringValue("str3")}, 3251 }, 3252 }, 3253 }, 3254 }, 3255 Result: &View{ 3256 Header: NewHeader("table1", []string{"column1", "column2"}), 3257 RecordSet: []Record{ 3258 NewRecord([]value.Primary{ 3259 value.NewString("1"), 3260 value.NewString("str3"), 3261 }), 3262 NewRecord([]value.Primary{ 3263 value.NewString("2"), 3264 value.NewString("str2"), 3265 }), 3266 }, 3267 }, 3268 UpdateCount: 1, 3269 }, 3270 { 3271 Name: "ReplaceFromQuery Field Lenght Does Not Match Error", 3272 Fields: []parser.QueryExpression{ 3273 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3274 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 3275 }, 3276 Query: parser.SelectQuery{ 3277 SelectEntity: parser.SelectEntity{ 3278 SelectClause: parser.SelectClause{ 3279 Fields: []parser.QueryExpression{ 3280 parser.Field{Object: parser.NewIntegerValueFromString("3")}, 3281 }, 3282 }, 3283 }, 3284 }, 3285 Error: "select query should return exactly 2 fields", 3286 }, 3287 } 3288 3289 func TestView_ReplaceFromQuery(t *testing.T) { 3290 view := &View{ 3291 Header: NewHeader("table1", []string{"column1", "column2"}), 3292 RecordSet: []Record{ 3293 NewRecord([]value.Primary{ 3294 value.NewString("1"), 3295 value.NewString("str1"), 3296 }), 3297 NewRecord([]value.Primary{ 3298 value.NewString("2"), 3299 value.NewString("str2"), 3300 }), 3301 }, 3302 } 3303 3304 scope := NewReferenceScope(TestTx) 3305 ctx := context.Background() 3306 for _, v := range viewReplaceFromQueryTests { 3307 cnt, err := view.ReplaceFromQuery(ctx, scope, v.Fields, v.Query, v.Keys) 3308 if err != nil { 3309 if len(v.Error) < 1 { 3310 t.Errorf("%s: unexpected error %q", v.Name, err) 3311 } else if err.Error() != v.Error { 3312 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 3313 } 3314 continue 3315 } 3316 if 0 < len(v.Error) { 3317 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 3318 continue 3319 } 3320 if !reflect.DeepEqual(view, v.Result) { 3321 t.Errorf("%s: result = %v, want %v", v.Name, view, v.Result) 3322 } 3323 if cnt != v.UpdateCount { 3324 t.Errorf("%s: update count = %d, want %d", v.Name, cnt, v.UpdateCount) 3325 } 3326 } 3327 } 3328 3329 func TestView_Fix(t *testing.T) { 3330 view := &View{ 3331 Header: []HeaderField{ 3332 {View: "table1", Column: InternalIdColumn}, 3333 {View: "table1", Column: "column1", IsFromTable: true}, 3334 {View: "table1", Column: "column2", IsFromTable: true}, 3335 }, 3336 RecordSet: []Record{ 3337 NewRecordWithId(1, []value.Primary{ 3338 value.NewString("1"), 3339 value.NewString("str1"), 3340 }), 3341 NewRecordWithId(2, []value.Primary{ 3342 value.NewString("1"), 3343 value.NewString("str1"), 3344 }), 3345 }, 3346 selectFields: []int{2}, 3347 } 3348 expect := &View{ 3349 Header: NewHeader("table1", []string{"column2"}), 3350 RecordSet: []Record{ 3351 NewRecord([]value.Primary{ 3352 value.NewString("str1"), 3353 }), 3354 NewRecord([]value.Primary{ 3355 value.NewString("str1"), 3356 }), 3357 }, 3358 selectFields: []int(nil), 3359 } 3360 3361 _ = view.Fix(context.Background(), TestTx.Flags) 3362 if !reflect.DeepEqual(view, expect) { 3363 t.Errorf("fix: view = %v, want %v", view, expect) 3364 } 3365 3366 view = &View{ 3367 Header: []HeaderField{ 3368 {View: "table1", Column: InternalIdColumn}, 3369 {View: "table1", Column: "column1", IsFromTable: true}, 3370 {View: "table1", Column: "column2", IsFromTable: true}, 3371 }, 3372 RecordSet: []Record{ 3373 NewRecordWithId(1, []value.Primary{ 3374 value.NewString("1"), 3375 value.NewString("str1"), 3376 }), 3377 NewRecordWithId(2, []value.Primary{ 3378 value.NewString("1"), 3379 value.NewString("str1"), 3380 }), 3381 }, 3382 selectFields: []int{2, 2, 2, 2}, 3383 } 3384 expect = &View{ 3385 Header: NewHeader("table1", []string{"column2", "column2", "column2", "column2"}), 3386 RecordSet: []Record{ 3387 NewRecord([]value.Primary{ 3388 value.NewString("str1"), 3389 value.NewString("str1"), 3390 value.NewString("str1"), 3391 value.NewString("str1"), 3392 }), 3393 NewRecord([]value.Primary{ 3394 value.NewString("str1"), 3395 value.NewString("str1"), 3396 value.NewString("str1"), 3397 value.NewString("str1"), 3398 }), 3399 }, 3400 selectFields: []int(nil), 3401 } 3402 3403 _ = view.Fix(context.Background(), TestTx.Flags) 3404 if !reflect.DeepEqual(view, expect) { 3405 t.Errorf("fix: view = %v, want %v", view, expect) 3406 } 3407 } 3408 3409 func TestView_Union(t *testing.T) { 3410 view := &View{ 3411 Header: []HeaderField{ 3412 {View: "table1", Column: "column1", IsFromTable: true}, 3413 {View: "table1", Column: "column2", IsFromTable: true}, 3414 }, 3415 RecordSet: RecordSet{ 3416 NewRecord([]value.Primary{ 3417 value.NewString("1"), 3418 value.NewString("str1"), 3419 }), 3420 NewRecord([]value.Primary{ 3421 value.NewString("1"), 3422 value.NewString("str1"), 3423 }), 3424 NewRecord([]value.Primary{ 3425 value.NewString("2"), 3426 value.NewString("str2"), 3427 }), 3428 NewRecord([]value.Primary{ 3429 value.NewString("2"), 3430 value.NewString("str2"), 3431 }), 3432 }, 3433 } 3434 3435 calcView := &View{ 3436 Header: []HeaderField{ 3437 {View: "table2", Column: "column3", IsFromTable: true}, 3438 {View: "table2", Column: "column4", IsFromTable: true}, 3439 }, 3440 RecordSet: RecordSet{ 3441 NewRecord([]value.Primary{ 3442 value.NewString("2"), 3443 value.NewString("str2"), 3444 }), 3445 NewRecord([]value.Primary{ 3446 value.NewString("3"), 3447 value.NewString("str3"), 3448 }), 3449 }, 3450 } 3451 3452 expect := &View{ 3453 Header: []HeaderField{ 3454 {View: "table1", Column: "column1", IsFromTable: true}, 3455 {View: "table1", Column: "column2", IsFromTable: true}, 3456 }, 3457 RecordSet: RecordSet{ 3458 NewRecord([]value.Primary{ 3459 value.NewString("1"), 3460 value.NewString("str1"), 3461 }), 3462 NewRecord([]value.Primary{ 3463 value.NewString("2"), 3464 value.NewString("str2"), 3465 }), 3466 NewRecord([]value.Primary{ 3467 value.NewString("3"), 3468 value.NewString("str3"), 3469 }), 3470 }, 3471 } 3472 3473 ctx := context.Background() 3474 err := view.Union(ctx, TestTx.Flags, calcView, false) 3475 if err != nil { 3476 t.Errorf("unexpected error %q", err) 3477 } 3478 if !reflect.DeepEqual(view, expect) { 3479 t.Errorf("union: view = %v, want %v", view, expect) 3480 } 3481 3482 view = &View{ 3483 Header: []HeaderField{ 3484 {View: "table1", Column: "column1", IsFromTable: true}, 3485 {View: "table1", Column: "column2", IsFromTable: true}, 3486 }, 3487 RecordSet: RecordSet{ 3488 NewRecord([]value.Primary{ 3489 value.NewString("1"), 3490 value.NewString("str1"), 3491 }), 3492 NewRecord([]value.Primary{ 3493 value.NewString("1"), 3494 value.NewString("str1"), 3495 }), 3496 NewRecord([]value.Primary{ 3497 value.NewString("2"), 3498 value.NewString("str2"), 3499 }), 3500 NewRecord([]value.Primary{ 3501 value.NewString("2"), 3502 value.NewString("str2"), 3503 }), 3504 }, 3505 } 3506 3507 expect = &View{ 3508 Header: []HeaderField{ 3509 {View: "table1", Column: "column1", IsFromTable: true}, 3510 {View: "table1", Column: "column2", IsFromTable: true}, 3511 }, 3512 RecordSet: RecordSet{ 3513 NewRecord([]value.Primary{ 3514 value.NewString("1"), 3515 value.NewString("str1"), 3516 }), 3517 NewRecord([]value.Primary{ 3518 value.NewString("1"), 3519 value.NewString("str1"), 3520 }), 3521 NewRecord([]value.Primary{ 3522 value.NewString("2"), 3523 value.NewString("str2"), 3524 }), 3525 NewRecord([]value.Primary{ 3526 value.NewString("2"), 3527 value.NewString("str2"), 3528 }), 3529 NewRecord([]value.Primary{ 3530 value.NewString("2"), 3531 value.NewString("str2"), 3532 }), 3533 NewRecord([]value.Primary{ 3534 value.NewString("3"), 3535 value.NewString("str3"), 3536 }), 3537 }, 3538 } 3539 3540 err = view.Union(ctx, TestTx.Flags, calcView, true) 3541 if err != nil { 3542 t.Errorf("unexpected error %q", err) 3543 } 3544 if !reflect.DeepEqual(view, expect) { 3545 t.Errorf("union all: view = %v, want %v", view, expect) 3546 } 3547 } 3548 3549 func TestView_Except(t *testing.T) { 3550 view := &View{ 3551 Header: []HeaderField{ 3552 {View: "table1", Column: "column1", IsFromTable: true}, 3553 {View: "table1", Column: "column2", IsFromTable: true}, 3554 }, 3555 RecordSet: RecordSet{ 3556 NewRecord([]value.Primary{ 3557 value.NewString("1"), 3558 value.NewString("str1"), 3559 }), 3560 NewRecord([]value.Primary{ 3561 value.NewString("1"), 3562 value.NewString("str1"), 3563 }), 3564 NewRecord([]value.Primary{ 3565 value.NewString("2"), 3566 value.NewString("str2"), 3567 }), 3568 NewRecord([]value.Primary{ 3569 value.NewString("2"), 3570 value.NewString("str2"), 3571 }), 3572 }, 3573 } 3574 3575 calcView := &View{ 3576 Header: []HeaderField{ 3577 {View: "table2", Column: "column3", IsFromTable: true}, 3578 {View: "table2", Column: "column4", IsFromTable: true}, 3579 }, 3580 RecordSet: RecordSet{ 3581 NewRecord([]value.Primary{ 3582 value.NewString("2"), 3583 value.NewString("str2"), 3584 }), 3585 NewRecord([]value.Primary{ 3586 value.NewString("3"), 3587 value.NewString("str3"), 3588 }), 3589 }, 3590 } 3591 3592 expect := &View{ 3593 Header: []HeaderField{ 3594 {View: "table1", Column: "column1", IsFromTable: true}, 3595 {View: "table1", Column: "column2", IsFromTable: true}, 3596 }, 3597 RecordSet: RecordSet{ 3598 NewRecord([]value.Primary{ 3599 value.NewString("1"), 3600 value.NewString("str1"), 3601 }), 3602 }, 3603 } 3604 3605 ctx := context.Background() 3606 err := view.Except(ctx, TestTx.Flags, calcView, false) 3607 if err != nil { 3608 t.Errorf("unexpected error %q", err) 3609 } 3610 if !reflect.DeepEqual(view, expect) { 3611 t.Errorf("except: view = %v, want %v", view, expect) 3612 } 3613 3614 view = &View{ 3615 Header: []HeaderField{ 3616 {View: "table1", Column: "column1", IsFromTable: true}, 3617 {View: "table1", Column: "column2", IsFromTable: true}, 3618 }, 3619 RecordSet: RecordSet{ 3620 NewRecord([]value.Primary{ 3621 value.NewString("1"), 3622 value.NewString("str1"), 3623 }), 3624 NewRecord([]value.Primary{ 3625 value.NewString("1"), 3626 value.NewString("str1"), 3627 }), 3628 NewRecord([]value.Primary{ 3629 value.NewString("2"), 3630 value.NewString("str2"), 3631 }), 3632 NewRecord([]value.Primary{ 3633 value.NewString("2"), 3634 value.NewString("str2"), 3635 }), 3636 }, 3637 } 3638 3639 expect = &View{ 3640 Header: []HeaderField{ 3641 {View: "table1", Column: "column1", IsFromTable: true}, 3642 {View: "table1", Column: "column2", IsFromTable: true}, 3643 }, 3644 RecordSet: RecordSet{ 3645 NewRecord([]value.Primary{ 3646 value.NewString("1"), 3647 value.NewString("str1"), 3648 }), 3649 NewRecord([]value.Primary{ 3650 value.NewString("1"), 3651 value.NewString("str1"), 3652 }), 3653 }, 3654 } 3655 3656 err = view.Except(ctx, TestTx.Flags, calcView, true) 3657 if err != nil { 3658 t.Errorf("unexpected error %q", err) 3659 } 3660 if !reflect.DeepEqual(view, expect) { 3661 t.Errorf("except all: view = %v, want %v", view, expect) 3662 } 3663 } 3664 3665 func TestView_Intersect(t *testing.T) { 3666 view := &View{ 3667 Header: []HeaderField{ 3668 {View: "table1", Column: "column1", IsFromTable: true}, 3669 {View: "table1", Column: "column2", IsFromTable: true}, 3670 }, 3671 RecordSet: RecordSet{ 3672 NewRecord([]value.Primary{ 3673 value.NewString("1"), 3674 value.NewString("str1"), 3675 }), 3676 NewRecord([]value.Primary{ 3677 value.NewString("1"), 3678 value.NewString("str1"), 3679 }), 3680 NewRecord([]value.Primary{ 3681 value.NewString("2"), 3682 value.NewString("str2"), 3683 }), 3684 NewRecord([]value.Primary{ 3685 value.NewString("2"), 3686 value.NewString("str2"), 3687 }), 3688 }, 3689 } 3690 3691 calcView := &View{ 3692 Header: []HeaderField{ 3693 {View: "table2", Column: "column3", IsFromTable: true}, 3694 {View: "table2", Column: "column4", IsFromTable: true}, 3695 }, 3696 RecordSet: RecordSet{ 3697 NewRecord([]value.Primary{ 3698 value.NewString("2"), 3699 value.NewString("str2"), 3700 }), 3701 NewRecord([]value.Primary{ 3702 value.NewString("3"), 3703 value.NewString("str3"), 3704 }), 3705 }, 3706 } 3707 3708 expect := &View{ 3709 Header: []HeaderField{ 3710 {View: "table1", Column: "column1", IsFromTable: true}, 3711 {View: "table1", Column: "column2", IsFromTable: true}, 3712 }, 3713 RecordSet: RecordSet{ 3714 NewRecord([]value.Primary{ 3715 value.NewString("2"), 3716 value.NewString("str2"), 3717 }), 3718 }, 3719 } 3720 3721 ctx := context.Background() 3722 err := view.Intersect(ctx, TestTx.Flags, calcView, false) 3723 if err != nil { 3724 t.Errorf("unexpected error %q", err) 3725 } 3726 if !reflect.DeepEqual(view, expect) { 3727 t.Errorf("intersect: view = %v, want %v", view, expect) 3728 } 3729 3730 view = &View{ 3731 Header: []HeaderField{ 3732 {View: "table1", Column: "column1", IsFromTable: true}, 3733 {View: "table1", Column: "column2", IsFromTable: true}, 3734 }, 3735 RecordSet: RecordSet{ 3736 NewRecord([]value.Primary{ 3737 value.NewString("1"), 3738 value.NewString("str1"), 3739 }), 3740 NewRecord([]value.Primary{ 3741 value.NewString("1"), 3742 value.NewString("str1"), 3743 }), 3744 NewRecord([]value.Primary{ 3745 value.NewString("2"), 3746 value.NewString("str2"), 3747 }), 3748 NewRecord([]value.Primary{ 3749 value.NewString("2"), 3750 value.NewString("str2"), 3751 }), 3752 }, 3753 } 3754 3755 expect = &View{ 3756 Header: []HeaderField{ 3757 {View: "table1", Column: "column1", IsFromTable: true}, 3758 {View: "table1", Column: "column2", IsFromTable: true}, 3759 }, 3760 RecordSet: RecordSet{ 3761 NewRecord([]value.Primary{ 3762 value.NewString("2"), 3763 value.NewString("str2"), 3764 }), 3765 NewRecord([]value.Primary{ 3766 value.NewString("2"), 3767 value.NewString("str2"), 3768 }), 3769 }, 3770 } 3771 3772 err = view.Intersect(ctx, TestTx.Flags, calcView, true) 3773 if err != nil { 3774 t.Errorf("unexpected error %q", err) 3775 } 3776 if !reflect.DeepEqual(view, expect) { 3777 t.Errorf("intersect all: view = %v, want %v", view, expect) 3778 } 3779 } 3780 3781 func TestView_FieldIndex(t *testing.T) { 3782 view := &View{ 3783 Header: []HeaderField{ 3784 {View: "table1", Column: "column1", Number: 1, IsFromTable: true}, 3785 {View: "table1", Column: "column2", Number: 2, IsFromTable: true}, 3786 }, 3787 } 3788 fieldRef := parser.FieldReference{ 3789 Column: parser.Identifier{Literal: "column1"}, 3790 } 3791 expect := 0 3792 3793 idx, _ := view.FieldIndex(fieldRef) 3794 if idx != expect { 3795 t.Errorf("field index = %d, want %d", idx, expect) 3796 } 3797 3798 columnNum := parser.ColumnNumber{ 3799 View: parser.Identifier{Literal: "table1"}, 3800 Number: value.NewInteger(2), 3801 } 3802 expect = 1 3803 3804 idx, _ = view.FieldIndex(columnNum) 3805 if idx != expect { 3806 t.Errorf("field index = %d, want %d", idx, expect) 3807 } 3808 } 3809 3810 func TestView_FieldIndices(t *testing.T) { 3811 view := &View{ 3812 Header: []HeaderField{ 3813 {View: "table1", Column: "column1", IsFromTable: true}, 3814 {View: "table1", Column: "column2", IsFromTable: true}, 3815 }, 3816 } 3817 fields := []parser.QueryExpression{ 3818 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 3819 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 3820 } 3821 expect := []int{1, 0} 3822 3823 indices, _ := view.FieldIndices(fields) 3824 if !reflect.DeepEqual(indices, expect) { 3825 t.Errorf("field indices = %v, want %v", indices, expect) 3826 } 3827 3828 fields = []parser.QueryExpression{ 3829 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 3830 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 3831 } 3832 expectErr := "field notexist does not exist" 3833 _, err := view.FieldIndices(fields) 3834 if err == nil { 3835 t.Errorf("no error, want error %s", expectErr) 3836 } else if err.Error() != expectErr { 3837 t.Errorf("error = %s, want %s", err, expectErr) 3838 } 3839 } 3840 3841 func TestView_FieldViewName(t *testing.T) { 3842 view := &View{ 3843 Header: []HeaderField{ 3844 {View: "table1", Column: "column1", IsFromTable: true}, 3845 {View: "table2", Column: "column2", IsFromTable: true}, 3846 }, 3847 } 3848 fieldRef := parser.FieldReference{ 3849 Column: parser.Identifier{Literal: "column1"}, 3850 } 3851 expect := "table1" 3852 3853 ref, _ := view.FieldViewName(fieldRef) 3854 if ref != expect { 3855 t.Errorf("field reference = %s, want %s", ref, expect) 3856 } 3857 3858 fieldRef = parser.FieldReference{ 3859 Column: parser.Identifier{Literal: "notexist"}, 3860 } 3861 expectErr := "field notexist does not exist" 3862 _, err := view.FieldViewName(fieldRef) 3863 if err == nil { 3864 t.Errorf("no error, want error %s", expectErr) 3865 } else if err.Error() != expectErr { 3866 t.Errorf("error = %s, want %s", err, expectErr) 3867 } 3868 } 3869 3870 func TestView_InternalRecordId(t *testing.T) { 3871 view := &View{ 3872 Header: NewHeaderWithId("table1", []string{"column1", "column2"}), 3873 RecordSet: []Record{ 3874 NewRecordWithId(0, []value.Primary{value.NewInteger(1), value.NewString("str1")}), 3875 NewRecordWithId(1, []value.Primary{value.NewInteger(2), value.NewString("str2")}), 3876 NewRecordWithId(2, []value.Primary{value.NewInteger(3), value.NewString("str3")}), 3877 }, 3878 } 3879 ref := "table1" 3880 recordIndex := 1 3881 expect := 1 3882 3883 id, _ := view.InternalRecordId(ref, recordIndex) 3884 if id != expect { 3885 t.Errorf("field internal id = %d, want %d", id, expect) 3886 } 3887 3888 view.RecordSet[1][0] = NewCell(value.NewNull()) 3889 expectErr := "internal record id is empty" 3890 _, err := view.InternalRecordId(ref, recordIndex) 3891 if err == nil { 3892 t.Errorf("no error, want error %s", expectErr) 3893 } else if err.Error() != expectErr { 3894 t.Errorf("error = %s, want %s", err, expectErr) 3895 } 3896 3897 view = &View{ 3898 Header: []HeaderField{ 3899 {View: "table1", Column: "column1", IsFromTable: true}, 3900 {View: "table2", Column: "column2", IsFromTable: true}, 3901 }, 3902 } 3903 expectErr = "internal record id does not exist" 3904 _, err = view.InternalRecordId(ref, recordIndex) 3905 if err == nil { 3906 t.Errorf("no error, want error %s", expectErr) 3907 } else if err.Error() != expectErr { 3908 t.Errorf("error = %s, want %s", err, expectErr) 3909 } 3910 } 3911 3912 func BenchmarkView_GroupBy(b *testing.B) { 3913 view := &View{ 3914 Header: NewHeader("t", []string{"c1", "c2", "c3"}), 3915 RecordSet: make(RecordSet, 10000), 3916 } 3917 for i := int64(0); i < 10000; i++ { 3918 view.RecordSet[i] = NewRecord([]value.Primary{ 3919 value.NewInteger(i), 3920 value.NewString(randomStr(1)), 3921 value.NewString(randomStr(1)), 3922 }) 3923 } 3924 3925 ctx := context.Background() 3926 scope := NewReferenceScope(TestTx) 3927 clause := parser.GroupByClause{ 3928 Items: []parser.QueryExpression{ 3929 parser.FieldReference{Column: parser.Identifier{Literal: "c2"}}, 3930 parser.FieldReference{Column: parser.Identifier{Literal: "c3"}}, 3931 }, 3932 } 3933 3934 b.ResetTimer() 3935 for i := 0; i < b.N; i++ { 3936 v := &View{ 3937 Header: view.Header.Copy(), 3938 RecordSet: view.RecordSet.Copy(), 3939 } 3940 _ = v.GroupBy(ctx, scope, clause) 3941 } 3942 } 3943 3944 func BenchmarkView_SelectDistinct(b *testing.B) { 3945 view := &View{ 3946 Header: NewHeader("t", []string{"c1", "c2", "c3"}), 3947 RecordSet: make(RecordSet, 10000), 3948 } 3949 for i := int64(0); i < 10000; i++ { 3950 view.RecordSet[i] = NewRecord([]value.Primary{ 3951 value.NewInteger(i), 3952 value.NewString(randomStr(1)), 3953 value.NewString(randomStr(1)), 3954 }) 3955 } 3956 3957 ctx := context.Background() 3958 scope := NewReferenceScope(TestTx) 3959 clause := parser.SelectClause{ 3960 Distinct: parser.Token{Token: parser.DISTINCT}, 3961 Fields: []parser.QueryExpression{ 3962 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "c1"}}}, 3963 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "c2"}}}, 3964 parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "c3"}}}, 3965 }, 3966 } 3967 3968 b.ResetTimer() 3969 for i := 0; i < b.N; i++ { 3970 v := &View{ 3971 Header: view.Header.Copy(), 3972 RecordSet: view.RecordSet.Copy(), 3973 } 3974 _ = v.Select(ctx, scope, clause) 3975 } 3976 }