github.com/mithrandie/csvq@v1.18.1/lib/query/analytic_function_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 var analyzeTests = []struct { 14 Name string 15 CPU int 16 View *View 17 Scope *ReferenceScope 18 Function parser.AnalyticFunction 19 PartitionIndices []int 20 Result *View 21 Error string 22 }{ 23 { 24 Name: "Analyze AnalyticFunction", 25 CPU: 3, 26 View: &View{ 27 Header: NewHeader("table1", []string{"column1", "column2"}), 28 RecordSet: []Record{ 29 NewRecord([]value.Primary{ 30 value.NewString("a"), 31 value.NewInteger(1), 32 }), 33 NewRecord([]value.Primary{ 34 value.NewString("b"), 35 value.NewInteger(1), 36 }), 37 NewRecord([]value.Primary{ 38 value.NewString("b"), 39 value.NewInteger(1), 40 }), 41 NewRecord([]value.Primary{ 42 value.NewString("b"), 43 value.NewInteger(2), 44 }), 45 NewRecord([]value.Primary{ 46 value.NewString("b"), 47 value.NewInteger(2), 48 }), 49 NewRecord([]value.Primary{ 50 value.NewString("b"), 51 value.NewInteger(3), 52 }), 53 NewRecord([]value.Primary{ 54 value.NewString("a"), 55 value.NewInteger(2), 56 }), 57 }, 58 sortValuesInEachRecord: []SortValues{ 59 {NewSortValue(value.NewInteger(1), TestTx.Flags)}, 60 {NewSortValue(value.NewInteger(1), TestTx.Flags)}, 61 {NewSortValue(value.NewInteger(1), TestTx.Flags)}, 62 {NewSortValue(value.NewInteger(2), TestTx.Flags)}, 63 {NewSortValue(value.NewInteger(2), TestTx.Flags)}, 64 {NewSortValue(value.NewInteger(3), TestTx.Flags)}, 65 {NewSortValue(value.NewInteger(2), TestTx.Flags)}, 66 }, 67 }, 68 Function: parser.AnalyticFunction{ 69 Name: "rank", 70 AnalyticClause: parser.AnalyticClause{ 71 PartitionClause: parser.PartitionClause{ 72 Values: []parser.QueryExpression{ 73 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 74 }, 75 }, 76 OrderByClause: parser.OrderByClause{ 77 Items: []parser.QueryExpression{ 78 parser.OrderItem{ 79 Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 80 }, 81 }, 82 }, 83 }, 84 }, 85 PartitionIndices: []int{0}, 86 Result: &View{ 87 Header: append( 88 NewHeader("table1", []string{"column1", "column2"}), 89 HeaderField{Identifier: "RANK() OVER (PARTITION BY column1 ORDER BY column2)", Column: "RANK() OVER (PARTITION BY column1 ORDER BY column2)"}, 90 ), 91 RecordSet: []Record{ 92 NewRecord([]value.Primary{ 93 value.NewString("a"), 94 value.NewInteger(1), 95 value.NewInteger(1), 96 }), 97 NewRecord([]value.Primary{ 98 value.NewString("b"), 99 value.NewInteger(1), 100 value.NewInteger(1), 101 }), 102 NewRecord([]value.Primary{ 103 value.NewString("b"), 104 value.NewInteger(1), 105 value.NewInteger(1), 106 }), 107 NewRecord([]value.Primary{ 108 value.NewString("b"), 109 value.NewInteger(2), 110 value.NewInteger(3), 111 }), 112 NewRecord([]value.Primary{ 113 value.NewString("b"), 114 value.NewInteger(2), 115 value.NewInteger(3), 116 }), 117 NewRecord([]value.Primary{ 118 value.NewString("b"), 119 value.NewInteger(3), 120 value.NewInteger(5), 121 }), 122 NewRecord([]value.Primary{ 123 value.NewString("a"), 124 value.NewInteger(2), 125 value.NewInteger(2), 126 }), 127 }, 128 sortValuesInEachCell: [][]*SortValue{ 129 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 130 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 131 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 132 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 133 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 134 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 135 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 136 }, 137 sortValuesInEachRecord: []SortValues{ 138 {NewSortValue(value.NewInteger(1), TestTx.Flags)}, 139 {NewSortValue(value.NewInteger(1), TestTx.Flags)}, 140 {NewSortValue(value.NewInteger(1), TestTx.Flags)}, 141 {NewSortValue(value.NewInteger(2), TestTx.Flags)}, 142 {NewSortValue(value.NewInteger(2), TestTx.Flags)}, 143 {NewSortValue(value.NewInteger(3), TestTx.Flags)}, 144 {NewSortValue(value.NewInteger(2), TestTx.Flags)}, 145 }, 146 }, 147 }, 148 { 149 Name: "Analyze AnalyticFunction Empty Record", 150 CPU: 3, 151 View: &View{ 152 Header: NewHeader("table1", []string{"column1", "column2"}), 153 RecordSet: []Record{}, 154 sortValuesInEachRecord: []SortValues{}, 155 }, 156 Function: parser.AnalyticFunction{ 157 Name: "rank", 158 AnalyticClause: parser.AnalyticClause{ 159 PartitionClause: parser.PartitionClause{ 160 Values: []parser.QueryExpression{ 161 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 162 }, 163 }, 164 OrderByClause: parser.OrderByClause{ 165 Items: []parser.QueryExpression{ 166 parser.OrderItem{ 167 Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 168 }, 169 }, 170 }, 171 }, 172 }, 173 PartitionIndices: []int{0}, 174 Result: &View{ 175 Header: append( 176 NewHeader("table1", []string{"column1", "column2"}), 177 HeaderField{Identifier: "RANK() OVER (PARTITION BY column1 ORDER BY column2)", Column: "RANK() OVER (PARTITION BY column1 ORDER BY column2)"}, 178 ), 179 RecordSet: []Record{}, 180 sortValuesInEachCell: [][]*SortValue{}, 181 sortValuesInEachRecord: []SortValues{}, 182 }, 183 }, 184 { 185 Name: "Analyze AnalyticFunction Argument Length Error", 186 View: &View{ 187 Header: NewHeader("table1", []string{"column1", "column2"}), 188 RecordSet: []Record{ 189 NewRecord([]value.Primary{ 190 value.NewString("a"), 191 value.NewInteger(1), 192 }), 193 NewRecord([]value.Primary{ 194 value.NewString("a"), 195 value.NewInteger(2), 196 }), 197 }, 198 }, 199 Function: parser.AnalyticFunction{ 200 Name: "rank", 201 Args: []parser.QueryExpression{ 202 parser.NewIntegerValue(1), 203 }, 204 AnalyticClause: parser.AnalyticClause{ 205 PartitionClause: parser.PartitionClause{ 206 Values: []parser.QueryExpression{ 207 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 208 }, 209 }, 210 OrderByClause: parser.OrderByClause{ 211 Items: []parser.QueryExpression{ 212 parser.OrderItem{ 213 Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 214 }, 215 }, 216 }, 217 }, 218 }, 219 Error: "function rank takes no argument", 220 }, 221 { 222 Name: "Analyze AnalyticFunction Execution Error", 223 View: &View{ 224 Header: NewHeader("table1", []string{"column1", "column2"}), 225 RecordSet: []Record{ 226 NewRecord([]value.Primary{ 227 value.NewString("a"), 228 value.NewInteger(1), 229 }), 230 NewRecord([]value.Primary{ 231 value.NewString("a"), 232 value.NewInteger(2), 233 }), 234 }, 235 }, 236 Function: parser.AnalyticFunction{ 237 Name: "first_value", 238 Args: []parser.QueryExpression{ 239 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 240 }, 241 }, 242 Error: "field notexist does not exist", 243 }, 244 { 245 Name: "Analyze AggregateFunction", 246 View: &View{ 247 Header: NewHeader("table1", []string{"column1", "column2"}), 248 RecordSet: []Record{ 249 NewRecord([]value.Primary{ 250 value.NewString("a"), 251 value.NewInteger(1), 252 }), 253 NewRecord([]value.Primary{ 254 value.NewString("a"), 255 value.NewInteger(2), 256 }), 257 NewRecord([]value.Primary{ 258 value.NewString("b"), 259 value.NewInteger(1), 260 }), 261 NewRecord([]value.Primary{ 262 value.NewString("b"), 263 value.NewNull(), 264 }), 265 NewRecord([]value.Primary{ 266 value.NewString("b"), 267 value.NewInteger(1), 268 }), 269 }, 270 }, 271 Function: parser.AnalyticFunction{ 272 Name: "count", 273 Args: []parser.QueryExpression{ 274 parser.AllColumns{}, 275 }, 276 AnalyticClause: parser.AnalyticClause{ 277 PartitionClause: parser.PartitionClause{ 278 Values: []parser.QueryExpression{ 279 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 280 }, 281 }, 282 }, 283 }, 284 PartitionIndices: []int{0}, 285 Result: &View{ 286 Header: append( 287 NewHeader("table1", []string{"column1", "column2"}), 288 HeaderField{Identifier: "COUNT(*) OVER (PARTITION BY column1)", Column: "COUNT(*) OVER (PARTITION BY column1)"}, 289 ), 290 RecordSet: []Record{ 291 NewRecord([]value.Primary{ 292 value.NewString("a"), 293 value.NewInteger(1), 294 value.NewInteger(2), 295 }), 296 NewRecord([]value.Primary{ 297 value.NewString("a"), 298 value.NewInteger(2), 299 value.NewInteger(2), 300 }), 301 NewRecord([]value.Primary{ 302 value.NewString("b"), 303 value.NewInteger(1), 304 value.NewInteger(3), 305 }), 306 NewRecord([]value.Primary{ 307 value.NewString("b"), 308 value.NewNull(), 309 value.NewInteger(3), 310 }), 311 NewRecord([]value.Primary{ 312 value.NewString("b"), 313 value.NewInteger(1), 314 value.NewInteger(3), 315 }), 316 }, 317 sortValuesInEachCell: [][]*SortValue{ 318 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 319 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 320 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 321 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 322 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 323 }, 324 }, 325 }, 326 { 327 Name: "Analyze AggregateFunction with Windowing Clause", 328 View: &View{ 329 Header: NewHeader("table1", []string{"column1", "column2"}), 330 RecordSet: []Record{ 331 NewRecord([]value.Primary{ 332 value.NewString("a"), 333 value.NewInteger(1), 334 }), 335 NewRecord([]value.Primary{ 336 value.NewString("a"), 337 value.NewInteger(2), 338 }), 339 NewRecord([]value.Primary{ 340 value.NewString("b"), 341 value.NewInteger(1), 342 }), 343 NewRecord([]value.Primary{ 344 value.NewString("b"), 345 value.NewNull(), 346 }), 347 NewRecord([]value.Primary{ 348 value.NewString("b"), 349 value.NewInteger(1), 350 }), 351 }, 352 }, 353 Function: parser.AnalyticFunction{ 354 Name: "sum", 355 Args: []parser.QueryExpression{ 356 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 357 }, 358 AnalyticClause: parser.AnalyticClause{ 359 PartitionClause: parser.PartitionClause{ 360 Values: []parser.QueryExpression{ 361 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 362 }, 363 }, 364 OrderByClause: parser.OrderByClause{ 365 Items: []parser.QueryExpression{ 366 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 367 }, 368 }, 369 WindowingClause: parser.WindowingClause{ 370 FrameLow: parser.WindowFramePosition{ 371 Direction: parser.Token{Token: parser.PRECEDING}, 372 Unbounded: parser.Token{Token: parser.UNBOUNDED}, 373 }, 374 }, 375 }, 376 }, 377 PartitionIndices: []int{0}, 378 Result: &View{ 379 Header: append( 380 NewHeader("table1", []string{"column1", "column2"}), 381 HeaderField{Identifier: "SUM(column2) OVER (PARTITION BY column1 ORDER BY column1 ROWS UNBOUNDED PRECEDING)", Column: "SUM(column2) OVER (PARTITION BY column1 ORDER BY column1 ROWS UNBOUNDED PRECEDING)"}, 382 ), 383 RecordSet: []Record{ 384 NewRecord([]value.Primary{ 385 value.NewString("a"), 386 value.NewInteger(1), 387 value.NewFloat(1), 388 }), 389 NewRecord([]value.Primary{ 390 value.NewString("a"), 391 value.NewInteger(2), 392 value.NewFloat(3), 393 }), 394 NewRecord([]value.Primary{ 395 value.NewString("b"), 396 value.NewInteger(1), 397 value.NewFloat(1), 398 }), 399 NewRecord([]value.Primary{ 400 value.NewString("b"), 401 value.NewNull(), 402 value.NewFloat(1), 403 }), 404 NewRecord([]value.Primary{ 405 value.NewString("b"), 406 value.NewInteger(1), 407 value.NewFloat(2), 408 }), 409 }, 410 sortValuesInEachCell: [][]*SortValue{ 411 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 412 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 413 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 414 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 415 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 416 }, 417 }, 418 }, 419 { 420 Name: "Analyze AggregateFunction With Distinct", 421 View: &View{ 422 Header: NewHeader("table1", []string{"column1", "column2"}), 423 RecordSet: []Record{ 424 NewRecord([]value.Primary{ 425 value.NewString("a"), 426 value.NewInteger(1), 427 }), 428 NewRecord([]value.Primary{ 429 value.NewString("a"), 430 value.NewInteger(2), 431 }), 432 NewRecord([]value.Primary{ 433 value.NewString("b"), 434 value.NewInteger(1), 435 }), 436 NewRecord([]value.Primary{ 437 value.NewString("b"), 438 value.NewNull(), 439 }), 440 NewRecord([]value.Primary{ 441 value.NewString("b"), 442 value.NewInteger(1), 443 }), 444 }, 445 sortValuesInEachCell: [][]*SortValue{ 446 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 447 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 448 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 449 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 450 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 451 }, 452 }, 453 Function: parser.AnalyticFunction{ 454 Name: "count", 455 Distinct: parser.Token{Token: parser.DISTINCT, Literal: "distinct"}, 456 Args: []parser.QueryExpression{ 457 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 458 }, 459 AnalyticClause: parser.AnalyticClause{ 460 PartitionClause: parser.PartitionClause{ 461 Values: []parser.QueryExpression{ 462 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 463 }, 464 }, 465 }, 466 }, 467 PartitionIndices: []int{0}, 468 Result: &View{ 469 Header: append( 470 NewHeader("table1", []string{"column1", "column2"}), 471 HeaderField{Identifier: "COUNT(DISTINCT column2) OVER (PARTITION BY column1)", Column: "COUNT(DISTINCT column2) OVER (PARTITION BY column1)"}, 472 ), 473 RecordSet: []Record{ 474 NewRecord([]value.Primary{ 475 value.NewString("a"), 476 value.NewInteger(1), 477 value.NewInteger(2), 478 }), 479 NewRecord([]value.Primary{ 480 value.NewString("a"), 481 value.NewInteger(2), 482 value.NewInteger(2), 483 }), 484 NewRecord([]value.Primary{ 485 value.NewString("b"), 486 value.NewInteger(1), 487 value.NewInteger(1), 488 }), 489 NewRecord([]value.Primary{ 490 value.NewString("b"), 491 value.NewNull(), 492 value.NewInteger(1), 493 }), 494 NewRecord([]value.Primary{ 495 value.NewString("b"), 496 value.NewInteger(1), 497 value.NewInteger(1), 498 }), 499 }, 500 sortValuesInEachCell: [][]*SortValue{ 501 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 502 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 503 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 504 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 505 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 506 }, 507 }, 508 }, 509 { 510 Name: "Analyze AggregateFunction Argument Length Error", 511 View: &View{ 512 Header: NewHeader("table1", []string{"column1", "column2"}), 513 RecordSet: []Record{ 514 NewRecord([]value.Primary{ 515 value.NewString("a"), 516 value.NewInteger(1), 517 }), 518 NewRecord([]value.Primary{ 519 value.NewString("a"), 520 value.NewInteger(2), 521 }), 522 }, 523 }, 524 Function: parser.AnalyticFunction{ 525 Name: "count", 526 AnalyticClause: parser.AnalyticClause{ 527 PartitionClause: parser.PartitionClause{ 528 Values: []parser.QueryExpression{ 529 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 530 }, 531 }, 532 }, 533 }, 534 Error: "function count takes exactly 1 argument", 535 }, 536 { 537 Name: "Analyze AggregateFunction Aggregate Value Error", 538 View: &View{ 539 Header: NewHeader("table1", []string{"column1", "column2"}), 540 RecordSet: []Record{ 541 NewRecord([]value.Primary{ 542 value.NewString("a"), 543 value.NewInteger(1), 544 }), 545 NewRecord([]value.Primary{ 546 value.NewString("a"), 547 value.NewInteger(2), 548 }), 549 }, 550 }, 551 Function: parser.AnalyticFunction{ 552 Name: "count", 553 Args: []parser.QueryExpression{ 554 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 555 }, 556 AnalyticClause: parser.AnalyticClause{ 557 PartitionClause: parser.PartitionClause{ 558 Values: []parser.QueryExpression{ 559 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 560 }, 561 }, 562 }, 563 }, 564 Error: "field notexist does not exist", 565 }, 566 { 567 Name: "Analyze UserDefinedFunction", 568 View: &View{ 569 Header: NewHeader("table1", []string{"column1", "column2"}), 570 RecordSet: []Record{ 571 NewRecord([]value.Primary{ 572 value.NewString("a"), 573 value.NewInteger(1), 574 }), 575 NewRecord([]value.Primary{ 576 value.NewString("a"), 577 value.NewInteger(2), 578 }), 579 NewRecord([]value.Primary{ 580 value.NewString("b"), 581 value.NewInteger(1), 582 }), 583 NewRecord([]value.Primary{ 584 value.NewString("b"), 585 value.NewNull(), 586 }), 587 NewRecord([]value.Primary{ 588 value.NewString("b"), 589 value.NewInteger(1), 590 }), 591 }, 592 }, 593 Scope: GenerateReferenceScope([]map[string]map[string]interface{}{ 594 { 595 scopeNameFunctions: { 596 "USERAGGFUNC": &UserDefinedFunction{ 597 Name: parser.Identifier{Literal: "useraggfunc"}, 598 IsAggregate: true, 599 Cursor: parser.Identifier{Literal: "list"}, 600 Parameters: []parser.Variable{ 601 {Name: "default"}, 602 }, 603 Statements: []parser.Statement{ 604 parser.VariableDeclaration{ 605 Assignments: []parser.VariableAssignment{ 606 { 607 Variable: parser.Variable{Name: "value"}, 608 }, 609 { 610 Variable: parser.Variable{Name: "fetch"}, 611 }, 612 }, 613 }, 614 parser.WhileInCursor{ 615 Variables: []parser.Variable{ 616 {Name: "fetch"}, 617 }, 618 Cursor: parser.Identifier{Literal: "list"}, 619 Statements: []parser.Statement{ 620 parser.If{ 621 Condition: parser.Is{ 622 LHS: parser.Variable{Name: "fetch"}, 623 RHS: parser.NewNullValue(), 624 }, 625 Statements: []parser.Statement{ 626 parser.FlowControl{Token: parser.CONTINUE}, 627 }, 628 }, 629 parser.If{ 630 Condition: parser.Is{ 631 LHS: parser.Variable{Name: "value"}, 632 RHS: parser.NewNullValue(), 633 }, 634 Statements: []parser.Statement{ 635 parser.VariableSubstitution{ 636 Variable: parser.Variable{Name: "value"}, 637 Value: parser.Variable{Name: "fetch"}, 638 }, 639 parser.FlowControl{Token: parser.CONTINUE}, 640 }, 641 }, 642 parser.VariableSubstitution{ 643 Variable: parser.Variable{Name: "value"}, 644 Value: parser.Arithmetic{ 645 LHS: parser.Variable{Name: "value"}, 646 RHS: parser.Variable{Name: "fetch"}, 647 Operator: parser.Token{Token: '*'}, 648 }, 649 }, 650 }, 651 }, 652 parser.Return{ 653 Value: parser.Variable{Name: "value"}, 654 }, 655 }, 656 }, 657 }, 658 }, 659 }, nil, time.Time{}, nil), 660 Function: parser.AnalyticFunction{ 661 Name: "useraggfunc", 662 Args: []parser.QueryExpression{ 663 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 664 parser.NewIntegerValue(0), 665 }, 666 AnalyticClause: parser.AnalyticClause{ 667 PartitionClause: parser.PartitionClause{ 668 Values: []parser.QueryExpression{ 669 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 670 }, 671 }, 672 }, 673 }, 674 PartitionIndices: []int{0}, 675 Result: &View{ 676 Header: append( 677 NewHeader("table1", []string{"column1", "column2"}), 678 HeaderField{Identifier: "USERAGGFUNC(column2, 0) OVER (PARTITION BY column1)", Column: "USERAGGFUNC(column2, 0) OVER (PARTITION BY column1)"}, 679 ), 680 RecordSet: []Record{ 681 NewRecord([]value.Primary{ 682 value.NewString("a"), 683 value.NewInteger(1), 684 value.NewInteger(2), 685 }), 686 NewRecord([]value.Primary{ 687 value.NewString("a"), 688 value.NewInteger(2), 689 value.NewInteger(2), 690 }), 691 NewRecord([]value.Primary{ 692 value.NewString("b"), 693 value.NewInteger(1), 694 value.NewInteger(1), 695 }), 696 NewRecord([]value.Primary{ 697 value.NewString("b"), 698 value.NewNull(), 699 value.NewInteger(1), 700 }), 701 NewRecord([]value.Primary{ 702 value.NewString("b"), 703 value.NewInteger(1), 704 value.NewInteger(1), 705 }), 706 }, 707 sortValuesInEachCell: [][]*SortValue{ 708 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 709 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 710 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 711 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 712 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 713 }, 714 }, 715 }, 716 { 717 Name: "Analyze UserDefinedFunction with Windowing Clause", 718 View: &View{ 719 Header: NewHeader("table1", []string{"column1", "column2"}), 720 RecordSet: []Record{ 721 NewRecord([]value.Primary{ 722 value.NewString("a"), 723 value.NewInteger(1), 724 }), 725 NewRecord([]value.Primary{ 726 value.NewString("a"), 727 value.NewInteger(2), 728 }), 729 NewRecord([]value.Primary{ 730 value.NewString("b"), 731 value.NewInteger(1), 732 }), 733 NewRecord([]value.Primary{ 734 value.NewString("b"), 735 value.NewNull(), 736 }), 737 NewRecord([]value.Primary{ 738 value.NewString("b"), 739 value.NewInteger(1), 740 }), 741 }, 742 }, 743 Scope: GenerateReferenceScope([]map[string]map[string]interface{}{ 744 { 745 scopeNameFunctions: { 746 "USERAGGFUNC": &UserDefinedFunction{ 747 Name: parser.Identifier{Literal: "useraggfunc"}, 748 IsAggregate: true, 749 Cursor: parser.Identifier{Literal: "list"}, 750 Parameters: []parser.Variable{ 751 {Name: "default"}, 752 }, 753 Statements: []parser.Statement{ 754 parser.VariableDeclaration{ 755 Assignments: []parser.VariableAssignment{ 756 { 757 Variable: parser.Variable{Name: "value"}, 758 }, 759 { 760 Variable: parser.Variable{Name: "fetch"}, 761 }, 762 }, 763 }, 764 parser.WhileInCursor{ 765 Variables: []parser.Variable{ 766 {Name: "fetch"}, 767 }, 768 Cursor: parser.Identifier{Literal: "list"}, 769 Statements: []parser.Statement{ 770 parser.If{ 771 Condition: parser.Is{ 772 LHS: parser.Variable{Name: "fetch"}, 773 RHS: parser.NewNullValue(), 774 }, 775 Statements: []parser.Statement{ 776 parser.FlowControl{Token: parser.CONTINUE}, 777 }, 778 }, 779 parser.If{ 780 Condition: parser.Is{ 781 LHS: parser.Variable{Name: "value"}, 782 RHS: parser.NewNullValue(), 783 }, 784 Statements: []parser.Statement{ 785 parser.VariableSubstitution{ 786 Variable: parser.Variable{Name: "value"}, 787 Value: parser.Variable{Name: "fetch"}, 788 }, 789 parser.FlowControl{Token: parser.CONTINUE}, 790 }, 791 }, 792 parser.VariableSubstitution{ 793 Variable: parser.Variable{Name: "value"}, 794 Value: parser.Arithmetic{ 795 LHS: parser.Variable{Name: "value"}, 796 RHS: parser.Variable{Name: "fetch"}, 797 Operator: parser.Token{Token: '*', Literal: "*"}, 798 }, 799 }, 800 }, 801 }, 802 parser.Return{ 803 Value: parser.Variable{Name: "value"}, 804 }, 805 }, 806 }, 807 }, 808 }, 809 }, nil, time.Time{}, nil), 810 Function: parser.AnalyticFunction{ 811 Name: "useraggfunc", 812 Args: []parser.QueryExpression{ 813 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 814 parser.NewIntegerValue(0), 815 }, 816 AnalyticClause: parser.AnalyticClause{ 817 PartitionClause: parser.PartitionClause{ 818 Values: []parser.QueryExpression{ 819 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 820 }, 821 }, 822 OrderByClause: parser.OrderByClause{ 823 Items: []parser.QueryExpression{ 824 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 825 }, 826 }, 827 WindowingClause: parser.WindowingClause{ 828 FrameLow: parser.WindowFramePosition{ 829 Direction: parser.Token{Token: parser.PRECEDING}, 830 Unbounded: parser.Token{Token: parser.UNBOUNDED}, 831 }, 832 }, 833 }, 834 }, 835 PartitionIndices: []int{0}, 836 Result: &View{ 837 Header: append( 838 NewHeader("table1", []string{"column1", "column2"}), 839 HeaderField{Identifier: "USERAGGFUNC(column2, 0) OVER (PARTITION BY column1 ORDER BY column1 ROWS UNBOUNDED PRECEDING)", Column: "USERAGGFUNC(column2, 0) OVER (PARTITION BY column1 ORDER BY column1 ROWS UNBOUNDED PRECEDING)"}, 840 ), 841 RecordSet: []Record{ 842 NewRecord([]value.Primary{ 843 value.NewString("a"), 844 value.NewInteger(1), 845 value.NewInteger(1), 846 }), 847 NewRecord([]value.Primary{ 848 value.NewString("a"), 849 value.NewInteger(2), 850 value.NewInteger(2), 851 }), 852 NewRecord([]value.Primary{ 853 value.NewString("b"), 854 value.NewInteger(1), 855 value.NewInteger(1), 856 }), 857 NewRecord([]value.Primary{ 858 value.NewString("b"), 859 value.NewNull(), 860 value.NewInteger(1), 861 }), 862 NewRecord([]value.Primary{ 863 value.NewString("b"), 864 value.NewInteger(1), 865 value.NewInteger(1), 866 }), 867 }, 868 sortValuesInEachCell: [][]*SortValue{ 869 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 870 {NewSortValue(value.NewString("a"), TestTx.Flags), nil}, 871 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 872 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 873 {NewSortValue(value.NewString("b"), TestTx.Flags), nil}, 874 }, 875 }, 876 }, 877 { 878 Name: "Analyze UserDefinedFunction Argument Length Error", 879 View: &View{ 880 Header: NewHeader("table1", []string{"column1", "column2"}), 881 RecordSet: []Record{ 882 NewRecord([]value.Primary{ 883 value.NewString("a"), 884 value.NewInteger(1), 885 }), 886 NewRecord([]value.Primary{ 887 value.NewString("a"), 888 value.NewInteger(2), 889 }), 890 }, 891 }, 892 Scope: GenerateReferenceScope([]map[string]map[string]interface{}{ 893 { 894 scopeNameFunctions: { 895 "USERAGGFUNC": &UserDefinedFunction{ 896 Name: parser.Identifier{Literal: "useraggfunc"}, 897 IsAggregate: true, 898 Cursor: parser.Identifier{Literal: "list"}, 899 Parameters: []parser.Variable{ 900 {Name: "default"}, 901 }, 902 Statements: []parser.Statement{ 903 parser.Return{ 904 Value: parser.Variable{Name: "value"}, 905 }, 906 }, 907 }, 908 }, 909 }, 910 }, nil, time.Time{}, nil), 911 Function: parser.AnalyticFunction{ 912 Name: "useraggfunc", 913 AnalyticClause: parser.AnalyticClause{ 914 PartitionClause: parser.PartitionClause{ 915 Values: []parser.QueryExpression{ 916 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 917 }, 918 }, 919 }, 920 }, 921 Error: "function useraggfunc takes exactly 2 arguments", 922 }, 923 { 924 Name: "Analyze UserDefinedFunction Cursor Value Error", 925 View: &View{ 926 Header: NewHeader("table1", []string{"column1", "column2"}), 927 RecordSet: []Record{ 928 NewRecord([]value.Primary{ 929 value.NewString("a"), 930 value.NewInteger(1), 931 }), 932 NewRecord([]value.Primary{ 933 value.NewString("a"), 934 value.NewInteger(2), 935 }), 936 NewRecord([]value.Primary{ 937 value.NewString("b"), 938 value.NewInteger(1), 939 }), 940 NewRecord([]value.Primary{ 941 value.NewString("b"), 942 value.NewNull(), 943 }), 944 NewRecord([]value.Primary{ 945 value.NewString("b"), 946 value.NewInteger(1), 947 }), 948 }, 949 }, 950 Scope: GenerateReferenceScope([]map[string]map[string]interface{}{ 951 { 952 scopeNameFunctions: { 953 "USERAGGFUNC": &UserDefinedFunction{ 954 Name: parser.Identifier{Literal: "useraggfunc"}, 955 IsAggregate: true, 956 Cursor: parser.Identifier{Literal: "list"}, 957 Parameters: []parser.Variable{ 958 {Name: "default"}, 959 }, 960 Statements: []parser.Statement{ 961 parser.Return{ 962 Value: parser.Variable{Name: "value"}, 963 }, 964 }, 965 }, 966 }, 967 }, 968 }, nil, time.Time{}, nil), 969 Function: parser.AnalyticFunction{ 970 Name: "useraggfunc", 971 Args: []parser.QueryExpression{ 972 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 973 parser.NewIntegerValue(0), 974 }, 975 AnalyticClause: parser.AnalyticClause{ 976 PartitionClause: parser.PartitionClause{ 977 Values: []parser.QueryExpression{ 978 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 979 }, 980 }, 981 }, 982 }, 983 PartitionIndices: []int{0}, 984 Error: "field notexist does not exist", 985 }, 986 { 987 Name: "Analyze UserDefinedFunction Argument Value Error", 988 View: &View{ 989 Header: NewHeader("table1", []string{"column1", "column2"}), 990 RecordSet: []Record{ 991 NewRecord([]value.Primary{ 992 value.NewString("a"), 993 value.NewInteger(1), 994 }), 995 NewRecord([]value.Primary{ 996 value.NewString("a"), 997 value.NewInteger(2), 998 }), 999 }, 1000 }, 1001 Scope: GenerateReferenceScope([]map[string]map[string]interface{}{ 1002 { 1003 scopeNameFunctions: { 1004 "USERAGGFUNC": &UserDefinedFunction{ 1005 Name: parser.Identifier{Literal: "useraggfunc"}, 1006 IsAggregate: true, 1007 Cursor: parser.Identifier{Literal: "list"}, 1008 Parameters: []parser.Variable{ 1009 {Name: "default"}, 1010 }, 1011 Statements: []parser.Statement{ 1012 parser.Return{ 1013 Value: parser.Variable{Name: "value"}, 1014 }, 1015 }, 1016 }, 1017 }, 1018 }, 1019 }, nil, time.Time{}, nil), 1020 Function: parser.AnalyticFunction{ 1021 Name: "useraggfunc", 1022 Args: []parser.QueryExpression{ 1023 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1024 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 1025 }, 1026 AnalyticClause: parser.AnalyticClause{ 1027 PartitionClause: parser.PartitionClause{ 1028 Values: []parser.QueryExpression{ 1029 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 1030 }, 1031 }, 1032 }, 1033 }, 1034 Error: "field notexist does not exist", 1035 }, 1036 { 1037 Name: "Analyze UserDefinedFunction Execution Error", 1038 View: &View{ 1039 Header: NewHeader("table1", []string{"column1", "column2"}), 1040 RecordSet: []Record{ 1041 NewRecord([]value.Primary{ 1042 value.NewString("a"), 1043 value.NewInteger(1), 1044 }), 1045 NewRecord([]value.Primary{ 1046 value.NewString("a"), 1047 value.NewInteger(2), 1048 }), 1049 }, 1050 }, 1051 Scope: GenerateReferenceScope([]map[string]map[string]interface{}{ 1052 { 1053 scopeNameFunctions: { 1054 "USERAGGFUNC": &UserDefinedFunction{ 1055 Name: parser.Identifier{Literal: "useraggfunc"}, 1056 IsAggregate: true, 1057 Cursor: parser.Identifier{Literal: "list"}, 1058 Parameters: []parser.Variable{ 1059 {Name: "default"}, 1060 }, 1061 Statements: []parser.Statement{ 1062 parser.Return{ 1063 Value: parser.Variable{Name: "undefined"}, 1064 }, 1065 }, 1066 }, 1067 }, 1068 }, 1069 }, nil, time.Time{}, nil), 1070 Function: parser.AnalyticFunction{ 1071 Name: "useraggfunc", 1072 Args: []parser.QueryExpression{ 1073 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1074 parser.NewIntegerValue(0), 1075 }, 1076 AnalyticClause: parser.AnalyticClause{ 1077 PartitionClause: parser.PartitionClause{ 1078 Values: []parser.QueryExpression{ 1079 parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}, 1080 }, 1081 }, 1082 }, 1083 }, 1084 Error: "variable @undefined is undeclared", 1085 }, 1086 { 1087 Name: "Analyze Not Exist Function Error", 1088 View: &View{ 1089 Header: NewHeader("table1", []string{"column1", "column2"}), 1090 RecordSet: []Record{ 1091 NewRecord([]value.Primary{ 1092 value.NewString("a"), 1093 value.NewInteger(1), 1094 }), 1095 NewRecord([]value.Primary{ 1096 value.NewString("a"), 1097 value.NewInteger(2), 1098 }), 1099 }, 1100 }, 1101 Function: parser.AnalyticFunction{ 1102 Name: "notexist", 1103 }, 1104 Error: "function notexist does not exist", 1105 }, 1106 } 1107 1108 func TestAnalyze(t *testing.T) { 1109 defer initFlag(TestTx.Flags) 1110 1111 for _, v := range analyzeTests { 1112 if 0 < v.CPU { 1113 TestTx.Flags.CPU = v.CPU 1114 } else { 1115 TestTx.Flags.CPU = 1 1116 } 1117 1118 ctx := context.Background() 1119 if v.Scope == nil { 1120 v.Scope = NewReferenceScope(TestTx) 1121 } 1122 1123 err := Analyze(ctx, v.Scope, v.View, v.Function, v.PartitionIndices) 1124 if err != nil { 1125 if len(v.Error) < 1 { 1126 t.Errorf("%s: unexpected error %q", v.Name, err) 1127 } else if err.Error() != v.Error { 1128 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 1129 } 1130 continue 1131 } 1132 if 0 < len(v.Error) { 1133 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 1134 continue 1135 } 1136 1137 if !reflect.DeepEqual(v.View, v.Result) { 1138 t.Errorf("%s: result = %v, want %v", v.Name, v.View, v.Result) 1139 } 1140 } 1141 } 1142 1143 type analyticFunctionCheckArgsLenTests struct { 1144 Name string 1145 Function parser.AnalyticFunction 1146 Error string 1147 } 1148 1149 func testAnalyticFunctionCheckArgsLenTests(t *testing.T, fn AnalyticFunction, tests []analyticFunctionCheckArgsLenTests) { 1150 for _, v := range tests { 1151 err := fn.CheckArgsLen(v.Function) 1152 if err != nil { 1153 if len(v.Error) < 1 { 1154 t.Errorf("%s: unexpected error %q", v.Name, err) 1155 } else if err.Error() != v.Error { 1156 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 1157 } 1158 continue 1159 } 1160 if 0 < len(v.Error) { 1161 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 1162 continue 1163 } 1164 } 1165 } 1166 1167 type analyticFunctionExecuteTests struct { 1168 Name string 1169 Items Partition 1170 SortValues map[int]SortValues 1171 Function parser.AnalyticFunction 1172 Result map[int]value.Primary 1173 Error string 1174 } 1175 1176 var analyticFunctionTestScope = GenerateReferenceScope(nil, nil, time.Time{}, []ReferenceRecord{ 1177 { 1178 view: &View{ 1179 Header: NewHeader("table1", []string{"column1", "column2"}), 1180 RecordSet: []Record{ 1181 NewRecord([]value.Primary{ 1182 value.NewString("a"), 1183 value.NewInteger(100), 1184 }), 1185 NewRecord([]value.Primary{ 1186 value.NewString("a"), 1187 value.NewInteger(200), 1188 }), 1189 NewRecord([]value.Primary{ 1190 value.NewString("b"), 1191 value.NewNull(), 1192 }), 1193 NewRecord([]value.Primary{ 1194 value.NewString("b"), 1195 value.NewInteger(200), 1196 }), 1197 NewRecord([]value.Primary{ 1198 value.NewString("b"), 1199 value.NewInteger(300), 1200 }), 1201 NewRecord([]value.Primary{ 1202 value.NewString("b"), 1203 value.NewInteger(500), 1204 }), 1205 NewRecord([]value.Primary{ 1206 value.NewString("b"), 1207 value.NewInteger(800), 1208 }), 1209 NewRecord([]value.Primary{ 1210 value.NewString("b"), 1211 value.NewNull(), 1212 }), 1213 }, 1214 }, 1215 recordIndex: 0, 1216 cache: NewFieldIndexCache(10, LimitToUseFieldIndexSliceChache), 1217 }, 1218 }) 1219 1220 func testAnalyticFunctionExecute(t *testing.T, fn AnalyticFunction, tests []analyticFunctionExecuteTests) { 1221 for _, v := range tests { 1222 if v.SortValues != nil { 1223 list := make([]SortValues, analyticFunctionTestScope.Records[0].view.RecordLen()) 1224 for i, v := range v.SortValues { 1225 list[i] = v 1226 } 1227 analyticFunctionTestScope.Records[0].view.sortValuesInEachRecord = list 1228 } else { 1229 analyticFunctionTestScope.Records[0].view.sortValuesInEachRecord = nil 1230 } 1231 1232 result, err := fn.Execute(context.Background(), analyticFunctionTestScope, v.Items, v.Function) 1233 if err != nil { 1234 if len(v.Error) < 1 { 1235 t.Errorf("%s: unexpected error %q", v.Name, err) 1236 } else if err.Error() != v.Error { 1237 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 1238 } 1239 continue 1240 } 1241 if 0 < len(v.Error) { 1242 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 1243 continue 1244 } 1245 if !reflect.DeepEqual(result, v.Result) { 1246 t.Errorf("%s: result = %q, want %q", v.Name, result, v.Result) 1247 } 1248 } 1249 } 1250 1251 var rowNumberCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 1252 { 1253 Name: "RowNumber CheckArgsLen", 1254 Function: parser.AnalyticFunction{ 1255 Name: "row_number", 1256 Args: nil, 1257 }, 1258 }, 1259 { 1260 Name: "RowNumber CheckArgsLen Error", 1261 Function: parser.AnalyticFunction{ 1262 Name: "row_number", 1263 Args: []parser.QueryExpression{ 1264 parser.NewIntegerValue(1), 1265 }, 1266 }, 1267 Error: "function row_number takes no argument", 1268 }, 1269 } 1270 1271 func TestRowNumber_CheckArgsLen(t *testing.T) { 1272 testAnalyticFunctionCheckArgsLenTests(t, RowNumber{}, rowNumberCheckArgsLenTests) 1273 } 1274 1275 var rowNumberExecuteTests = []analyticFunctionExecuteTests{ 1276 { 1277 Name: "RowNumber Execute", 1278 Items: Partition{2, 4, 1, 3, 5}, 1279 Function: parser.AnalyticFunction{ 1280 Name: "row_number", 1281 }, 1282 Result: map[int]value.Primary{ 1283 2: value.NewInteger(1), 1284 4: value.NewInteger(2), 1285 1: value.NewInteger(3), 1286 3: value.NewInteger(4), 1287 5: value.NewInteger(5), 1288 }, 1289 }, 1290 } 1291 1292 func TestRowNumber_Execute(t *testing.T) { 1293 testAnalyticFunctionExecute(t, RowNumber{}, rowNumberExecuteTests) 1294 } 1295 1296 var rankCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 1297 { 1298 Name: "Rank CheckArgsLen Error", 1299 Function: parser.AnalyticFunction{ 1300 Name: "rank", 1301 Args: []parser.QueryExpression{ 1302 parser.NewIntegerValue(1), 1303 }, 1304 }, 1305 Error: "function rank takes no argument", 1306 }, 1307 } 1308 1309 func TestRank_CheckArgsLen(t *testing.T) { 1310 testAnalyticFunctionCheckArgsLenTests(t, Rank{}, rankCheckArgsLenTests) 1311 } 1312 1313 var rankExecuteTests = []analyticFunctionExecuteTests{ 1314 { 1315 Name: "Rank Execute", 1316 Items: Partition{2, 4, 1, 3, 5}, 1317 SortValues: map[int]SortValues{ 1318 2: {NewSortValue(value.NewString("1"), TestTx.Flags)}, 1319 4: {NewSortValue(value.NewString("1"), TestTx.Flags)}, 1320 1: {NewSortValue(value.NewString("2"), TestTx.Flags)}, 1321 3: {NewSortValue(value.NewString("2"), TestTx.Flags)}, 1322 5: {NewSortValue(value.NewString("3"), TestTx.Flags)}, 1323 }, 1324 Function: parser.AnalyticFunction{ 1325 Name: "rank", 1326 }, 1327 Result: map[int]value.Primary{ 1328 2: value.NewInteger(1), 1329 4: value.NewInteger(1), 1330 1: value.NewInteger(3), 1331 3: value.NewInteger(3), 1332 5: value.NewInteger(5), 1333 }, 1334 }, 1335 } 1336 1337 func TestRank_Execute(t *testing.T) { 1338 testAnalyticFunctionExecute(t, Rank{}, rankExecuteTests) 1339 } 1340 1341 var denseRankCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 1342 { 1343 Name: "DenseRank CheckArgsLen Error", 1344 Function: parser.AnalyticFunction{ 1345 Name: "dense_rank", 1346 Args: []parser.QueryExpression{ 1347 parser.NewIntegerValue(1), 1348 }, 1349 }, 1350 Error: "function dense_rank takes no argument", 1351 }, 1352 } 1353 1354 func TestDenseRank_CheckArgsLen(t *testing.T) { 1355 testAnalyticFunctionCheckArgsLenTests(t, DenseRank{}, denseRankCheckArgsLenTests) 1356 } 1357 1358 var denseRankExecuteTests = []analyticFunctionExecuteTests{ 1359 { 1360 Name: "DenseRank Execute", 1361 Items: Partition{2, 4, 1, 3, 5}, 1362 SortValues: map[int]SortValues{ 1363 2: {NewSortValue(value.NewString("1"), TestTx.Flags)}, 1364 4: {NewSortValue(value.NewString("1"), TestTx.Flags)}, 1365 1: {NewSortValue(value.NewString("2"), TestTx.Flags)}, 1366 3: {NewSortValue(value.NewString("2"), TestTx.Flags)}, 1367 5: {NewSortValue(value.NewString("3"), TestTx.Flags)}, 1368 }, 1369 Function: parser.AnalyticFunction{ 1370 Name: "dense_rank", 1371 }, 1372 Result: map[int]value.Primary{ 1373 2: value.NewInteger(1), 1374 4: value.NewInteger(1), 1375 1: value.NewInteger(2), 1376 3: value.NewInteger(2), 1377 5: value.NewInteger(3), 1378 }, 1379 }, 1380 } 1381 1382 func TestDenseRank_Execute(t *testing.T) { 1383 testAnalyticFunctionExecute(t, DenseRank{}, denseRankExecuteTests) 1384 } 1385 1386 var cumeDistCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 1387 { 1388 Name: "CumeDist CheckArgsLen Error", 1389 Function: parser.AnalyticFunction{ 1390 Name: "cume_dist", 1391 Args: []parser.QueryExpression{ 1392 parser.NewIntegerValue(1), 1393 }, 1394 }, 1395 Error: "function cume_dist takes no argument", 1396 }, 1397 } 1398 1399 func TestCumeDist_CheckArgsLen(t *testing.T) { 1400 testAnalyticFunctionCheckArgsLenTests(t, CumeDist{}, cumeDistCheckArgsLenTests) 1401 } 1402 1403 var cumeDistExecuteTests = []analyticFunctionExecuteTests{ 1404 { 1405 Name: "CumeDist Execute", 1406 Items: Partition{2, 4, 1, 3}, 1407 SortValues: map[int]SortValues{ 1408 2: {NewSortValue(value.NewString("1"), TestTx.Flags)}, 1409 4: {NewSortValue(value.NewString("2"), TestTx.Flags)}, 1410 1: {NewSortValue(value.NewString("2"), TestTx.Flags)}, 1411 3: {NewSortValue(value.NewString("3"), TestTx.Flags)}, 1412 }, 1413 Function: parser.AnalyticFunction{ 1414 Name: "cume_dist", 1415 }, 1416 Result: map[int]value.Primary{ 1417 2: value.NewFloat(0.25), 1418 4: value.NewFloat(0.75), 1419 1: value.NewFloat(0.75), 1420 3: value.NewFloat(1), 1421 }, 1422 }, 1423 } 1424 1425 func TestCumeDist_Execute(t *testing.T) { 1426 testAnalyticFunctionExecute(t, CumeDist{}, cumeDistExecuteTests) 1427 } 1428 1429 var percentRankCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 1430 { 1431 Name: "PercentRank CheckArgsLen Error", 1432 Function: parser.AnalyticFunction{ 1433 Name: "percent_rank", 1434 Args: []parser.QueryExpression{ 1435 parser.NewIntegerValue(1), 1436 }, 1437 }, 1438 Error: "function percent_rank takes no argument", 1439 }, 1440 } 1441 1442 func TestPercentRank_CheckArgsLen(t *testing.T) { 1443 testAnalyticFunctionCheckArgsLenTests(t, PercentRank{}, percentRankCheckArgsLenTests) 1444 } 1445 1446 var percentRankExecuteTests = []analyticFunctionExecuteTests{ 1447 { 1448 Name: "PercentRank Execute", 1449 Items: Partition{2, 4, 1, 3, 5}, 1450 SortValues: map[int]SortValues{ 1451 2: {NewSortValue(value.NewString("1"), TestTx.Flags)}, 1452 4: {NewSortValue(value.NewString("2"), TestTx.Flags)}, 1453 1: {NewSortValue(value.NewString("2"), TestTx.Flags)}, 1454 3: {NewSortValue(value.NewString("3"), TestTx.Flags)}, 1455 5: {NewSortValue(value.NewString("4"), TestTx.Flags)}, 1456 }, 1457 Function: parser.AnalyticFunction{ 1458 Name: "percent_rank", 1459 }, 1460 Result: map[int]value.Primary{ 1461 2: value.NewFloat(0), 1462 4: value.NewFloat(0.25), 1463 1: value.NewFloat(0.25), 1464 3: value.NewFloat(0.75), 1465 5: value.NewFloat(1), 1466 }, 1467 }, 1468 } 1469 1470 func TestPercentRank_Execute(t *testing.T) { 1471 testAnalyticFunctionExecute(t, PercentRank{}, percentRankExecuteTests) 1472 } 1473 1474 var nTileCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 1475 { 1476 Name: "NTile CheckArgsLen Error", 1477 Function: parser.AnalyticFunction{ 1478 Name: "ntile", 1479 }, 1480 Error: "function ntile takes exactly 1 argument", 1481 }, 1482 } 1483 1484 func TestNTile_CheckArgsLen(t *testing.T) { 1485 testAnalyticFunctionCheckArgsLenTests(t, NTile{}, nTileCheckArgsLenTests) 1486 } 1487 1488 var ntileValueExecuteTests = []analyticFunctionExecuteTests{ 1489 { 1490 Name: "NTile Execute", 1491 Items: Partition{1, 2, 3, 4, 5, 6, 7}, 1492 Function: parser.AnalyticFunction{ 1493 Name: "ntile", 1494 Args: []parser.QueryExpression{ 1495 parser.NewIntegerValue(3), 1496 }, 1497 }, 1498 Result: map[int]value.Primary{ 1499 1: value.NewInteger(1), 1500 2: value.NewInteger(1), 1501 3: value.NewInteger(1), 1502 4: value.NewInteger(2), 1503 5: value.NewInteger(2), 1504 6: value.NewInteger(3), 1505 7: value.NewInteger(3), 1506 }, 1507 }, 1508 { 1509 Name: "NTile Execute Greater Tile Number", 1510 Items: Partition{1, 2}, 1511 Function: parser.AnalyticFunction{ 1512 Name: "ntile", 1513 Args: []parser.QueryExpression{ 1514 parser.NewIntegerValue(3), 1515 }, 1516 }, 1517 Result: map[int]value.Primary{ 1518 1: value.NewInteger(1), 1519 2: value.NewInteger(2), 1520 }, 1521 }, 1522 { 1523 Name: "NTile Execute Argument Evaluation Error", 1524 Items: Partition{1, 2, 3, 4, 5, 6, 7}, 1525 Function: parser.AnalyticFunction{ 1526 Name: "ntile", 1527 Args: []parser.QueryExpression{ 1528 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 1529 }, 1530 }, 1531 Error: "the first argument must be an integer for function ntile", 1532 }, 1533 { 1534 Name: "NTile Execute Argument Type Error", 1535 Items: Partition{1, 2, 3, 4, 5, 6, 7}, 1536 Function: parser.AnalyticFunction{ 1537 Name: "ntile", 1538 Args: []parser.QueryExpression{ 1539 parser.NewNullValue(), 1540 }, 1541 }, 1542 Error: "the first argument must be an integer for function ntile", 1543 }, 1544 { 1545 Name: "NTile Execute Argument Value Error", 1546 Items: Partition{1, 2, 3, 4, 5, 6, 7}, 1547 Function: parser.AnalyticFunction{ 1548 Name: "ntile", 1549 Args: []parser.QueryExpression{ 1550 parser.NewIntegerValue(0), 1551 }, 1552 }, 1553 Error: "the first argument must be greater than 0 for function ntile", 1554 }, 1555 } 1556 1557 func TestNTile_Execute(t *testing.T) { 1558 testAnalyticFunctionExecute(t, NTile{}, ntileValueExecuteTests) 1559 } 1560 1561 var firstValueCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 1562 { 1563 Name: "FirstValue CheckArgsLen Error", 1564 Function: parser.AnalyticFunction{ 1565 Name: "first_value", 1566 }, 1567 Error: "function first_value takes exactly 1 argument", 1568 }, 1569 } 1570 1571 func TestFirstValue_CheckArgsLen(t *testing.T) { 1572 testAnalyticFunctionCheckArgsLenTests(t, FirstValue{}, firstValueCheckArgsLenTests) 1573 } 1574 1575 var firstValueExecuteTests = []analyticFunctionExecuteTests{ 1576 { 1577 Name: "FirstValue Execute", 1578 Items: Partition{2, 3, 4, 5, 6, 7}, 1579 Function: parser.AnalyticFunction{ 1580 Name: "first_value", 1581 Args: []parser.QueryExpression{ 1582 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1583 }, 1584 }, 1585 Result: map[int]value.Primary{ 1586 2: value.NewNull(), 1587 3: value.NewNull(), 1588 4: value.NewNull(), 1589 5: value.NewNull(), 1590 6: value.NewNull(), 1591 7: value.NewNull(), 1592 }, 1593 }, 1594 { 1595 Name: "FirstValue Execute IgnoreNulls", 1596 Items: Partition{2, 3, 4, 5, 6, 7}, 1597 Function: parser.AnalyticFunction{ 1598 Name: "first_value", 1599 Args: []parser.QueryExpression{ 1600 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1601 }, 1602 IgnoreType: parser.Token{Token: parser.NULLS, Literal: "nulls"}, 1603 }, 1604 Result: map[int]value.Primary{ 1605 2: value.NewInteger(200), 1606 3: value.NewInteger(200), 1607 4: value.NewInteger(200), 1608 5: value.NewInteger(200), 1609 6: value.NewInteger(200), 1610 7: value.NewInteger(200), 1611 }, 1612 }, 1613 { 1614 Name: "FirstValue Execute Argument Value Error", 1615 Items: Partition{2, 3}, 1616 Function: parser.AnalyticFunction{ 1617 Name: "first_value", 1618 Args: []parser.QueryExpression{ 1619 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 1620 }, 1621 }, 1622 Error: "field notexist does not exist", 1623 }, 1624 } 1625 1626 func TestFirstValue_Execute(t *testing.T) { 1627 testAnalyticFunctionExecute(t, FirstValue{}, firstValueExecuteTests) 1628 } 1629 1630 var lastValueCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 1631 { 1632 Name: "LastValue CheckArgsLen Error", 1633 Function: parser.AnalyticFunction{ 1634 Name: "last_value", 1635 }, 1636 Error: "function last_value takes exactly 1 argument", 1637 }, 1638 } 1639 1640 func TestLastValue_CheckArgsLen(t *testing.T) { 1641 testAnalyticFunctionCheckArgsLenTests(t, LastValue{}, lastValueCheckArgsLenTests) 1642 } 1643 1644 var lastValueExecuteTests = []analyticFunctionExecuteTests{ 1645 { 1646 Name: "LastValue Execute", 1647 Items: Partition{2, 3, 4, 5, 6, 7}, 1648 Function: parser.AnalyticFunction{ 1649 Name: "last_value", 1650 Args: []parser.QueryExpression{ 1651 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1652 }, 1653 }, 1654 Result: map[int]value.Primary{ 1655 2: value.NewNull(), 1656 3: value.NewNull(), 1657 4: value.NewNull(), 1658 5: value.NewNull(), 1659 6: value.NewNull(), 1660 7: value.NewNull(), 1661 }, 1662 }, 1663 { 1664 Name: "LastValue Execute IgnoreNulls", 1665 Items: Partition{2, 3, 4, 5, 6, 7}, 1666 Function: parser.AnalyticFunction{ 1667 Name: "last_value", 1668 Args: []parser.QueryExpression{ 1669 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1670 }, 1671 IgnoreType: parser.Token{Token: parser.NULLS, Literal: "nulls"}, 1672 }, 1673 Result: map[int]value.Primary{ 1674 2: value.NewInteger(800), 1675 3: value.NewInteger(800), 1676 4: value.NewInteger(800), 1677 5: value.NewInteger(800), 1678 6: value.NewInteger(800), 1679 7: value.NewInteger(800), 1680 }, 1681 }, 1682 } 1683 1684 func TestLastValue_Execute(t *testing.T) { 1685 testAnalyticFunctionExecute(t, LastValue{}, lastValueExecuteTests) 1686 } 1687 1688 var nthValueCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 1689 { 1690 Name: "NthValue CheckArgsLen Error", 1691 Function: parser.AnalyticFunction{ 1692 Name: "nth_value", 1693 }, 1694 Error: "function nth_value takes exactly 2 arguments", 1695 }, 1696 } 1697 1698 func TestNthValue_CheckArgsLen(t *testing.T) { 1699 testAnalyticFunctionCheckArgsLenTests(t, NthValue{}, nthValueCheckArgsLenTests) 1700 } 1701 1702 var nthValueExecuteTests = []analyticFunctionExecuteTests{ 1703 { 1704 Name: "NthValue Execute", 1705 Items: Partition{2, 3, 4, 5, 6, 7}, 1706 Function: parser.AnalyticFunction{ 1707 Name: "nth_value", 1708 Args: []parser.QueryExpression{ 1709 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1710 parser.NewIntegerValue(2), 1711 }, 1712 }, 1713 Result: map[int]value.Primary{ 1714 2: value.NewInteger(200), 1715 3: value.NewInteger(200), 1716 4: value.NewInteger(200), 1717 5: value.NewInteger(200), 1718 6: value.NewInteger(200), 1719 7: value.NewInteger(200), 1720 }, 1721 }, 1722 { 1723 Name: "NthValue with Start Specified Windowing Clause Execute", 1724 Items: Partition{2, 3, 4, 5, 6, 7}, 1725 Function: parser.AnalyticFunction{ 1726 Name: "nth_value", 1727 Args: []parser.QueryExpression{ 1728 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1729 parser.NewIntegerValue(2), 1730 }, 1731 AnalyticClause: parser.AnalyticClause{ 1732 OrderByClause: parser.OrderByClause{ 1733 Items: []parser.QueryExpression{ 1734 parser.OrderItem{Value: parser.Identifier{Literal: "column2"}}, 1735 }, 1736 }, 1737 WindowingClause: parser.WindowingClause{ 1738 FrameLow: parser.WindowFramePosition{ 1739 Direction: parser.Token{Token: parser.PRECEDING}, 1740 Offset: 2, 1741 }, 1742 }, 1743 }, 1744 }, 1745 Result: map[int]value.Primary{ 1746 2: value.NewNull(), 1747 3: value.NewInteger(200), 1748 4: value.NewInteger(200), 1749 5: value.NewInteger(300), 1750 6: value.NewInteger(500), 1751 7: value.NewInteger(800), 1752 }, 1753 }, 1754 { 1755 Name: "NthValue with Rows Specified Windowing Clause Execute", 1756 Items: Partition{2, 3, 4, 5, 6, 7}, 1757 Function: parser.AnalyticFunction{ 1758 Name: "nth_value", 1759 Args: []parser.QueryExpression{ 1760 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1761 parser.NewIntegerValue(2), 1762 }, 1763 AnalyticClause: parser.AnalyticClause{ 1764 OrderByClause: parser.OrderByClause{ 1765 Items: []parser.QueryExpression{ 1766 parser.OrderItem{Value: parser.Identifier{Literal: "column2"}}, 1767 }, 1768 }, 1769 WindowingClause: parser.WindowingClause{ 1770 FrameLow: parser.WindowFramePosition{ 1771 Direction: parser.Token{Token: parser.CURRENT}, 1772 }, 1773 FrameHigh: parser.WindowFramePosition{ 1774 Direction: parser.Token{Token: parser.FOLLOWING}, 1775 Unbounded: parser.Token{Token: parser.UNBOUNDED}, 1776 }, 1777 }, 1778 }, 1779 }, 1780 Result: map[int]value.Primary{ 1781 2: value.NewInteger(200), 1782 3: value.NewInteger(300), 1783 4: value.NewInteger(500), 1784 5: value.NewInteger(800), 1785 6: value.NewNull(), 1786 7: value.NewNull(), 1787 }, 1788 }, 1789 { 1790 Name: "NthValue with Rows Specified Windowing Clause Execute 2", 1791 Items: Partition{2, 3, 4, 5, 6, 7}, 1792 Function: parser.AnalyticFunction{ 1793 Name: "nth_value", 1794 Args: []parser.QueryExpression{ 1795 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1796 parser.NewIntegerValue(2), 1797 }, 1798 AnalyticClause: parser.AnalyticClause{ 1799 OrderByClause: parser.OrderByClause{ 1800 Items: []parser.QueryExpression{ 1801 parser.OrderItem{Value: parser.Identifier{Literal: "column2"}}, 1802 }, 1803 }, 1804 WindowingClause: parser.WindowingClause{ 1805 FrameLow: parser.WindowFramePosition{ 1806 Direction: parser.Token{Token: parser.PRECEDING}, 1807 Unbounded: parser.Token{Token: parser.UNBOUNDED}, 1808 }, 1809 FrameHigh: parser.WindowFramePosition{ 1810 Direction: parser.Token{Token: parser.FOLLOWING}, 1811 Offset: 2, 1812 }, 1813 }, 1814 }, 1815 }, 1816 Result: map[int]value.Primary{ 1817 2: value.NewInteger(200), 1818 3: value.NewInteger(200), 1819 4: value.NewInteger(200), 1820 5: value.NewInteger(200), 1821 6: value.NewInteger(200), 1822 7: value.NewInteger(200), 1823 }, 1824 }, 1825 { 1826 Name: "NthValue with Rows Specified Windowing Clause Execute 3", 1827 Items: Partition{2, 3, 4, 5, 6, 7}, 1828 Function: parser.AnalyticFunction{ 1829 Name: "nth_value", 1830 Args: []parser.QueryExpression{ 1831 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1832 parser.NewIntegerValue(2), 1833 }, 1834 AnalyticClause: parser.AnalyticClause{ 1835 OrderByClause: parser.OrderByClause{ 1836 Items: []parser.QueryExpression{ 1837 parser.OrderItem{Value: parser.Identifier{Literal: "column2"}}, 1838 }, 1839 }, 1840 WindowingClause: parser.WindowingClause{ 1841 FrameLow: parser.WindowFramePosition{ 1842 Direction: parser.Token{Token: parser.PRECEDING}, 1843 Unbounded: parser.Token{Token: parser.UNBOUNDED}, 1844 }, 1845 FrameHigh: parser.WindowFramePosition{ 1846 Direction: parser.Token{Token: parser.FOLLOWING}, 1847 Unbounded: parser.Token{Token: parser.UNBOUNDED}, 1848 }, 1849 }, 1850 }, 1851 }, 1852 Result: map[int]value.Primary{ 1853 2: value.NewInteger(200), 1854 3: value.NewInteger(200), 1855 4: value.NewInteger(200), 1856 5: value.NewInteger(200), 1857 6: value.NewInteger(200), 1858 7: value.NewInteger(200), 1859 }, 1860 }, 1861 { 1862 Name: "NthValue with Default Windowing Clause Execute", 1863 Items: Partition{2, 3, 4, 5, 6, 7}, 1864 Function: parser.AnalyticFunction{ 1865 Name: "nth_value", 1866 Args: []parser.QueryExpression{ 1867 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1868 parser.NewIntegerValue(2), 1869 }, 1870 AnalyticClause: parser.AnalyticClause{ 1871 OrderByClause: parser.OrderByClause{ 1872 Items: []parser.QueryExpression{ 1873 parser.OrderItem{Value: parser.Identifier{Literal: "column2"}}, 1874 }, 1875 }, 1876 }, 1877 }, 1878 Result: map[int]value.Primary{ 1879 2: value.NewNull(), 1880 3: value.NewInteger(200), 1881 4: value.NewInteger(200), 1882 5: value.NewInteger(200), 1883 6: value.NewInteger(200), 1884 7: value.NewInteger(200), 1885 }, 1886 }, 1887 { 1888 Name: "NthValue Execute Second Argument Evaluation Error", 1889 Items: Partition{2, 3, 4, 5, 6, 7}, 1890 Function: parser.AnalyticFunction{ 1891 Name: "nth_value", 1892 Args: []parser.QueryExpression{ 1893 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1894 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 1895 }, 1896 }, 1897 Error: "the second argument must be an integer for function nth_value", 1898 }, 1899 { 1900 Name: "NthValue Execute Second Argument Type Error", 1901 Items: Partition{2, 3, 4, 5, 6, 7}, 1902 Function: parser.AnalyticFunction{ 1903 Name: "nth_value", 1904 Args: []parser.QueryExpression{ 1905 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1906 parser.NewNullValue(), 1907 }, 1908 }, 1909 Error: "the second argument must be an integer for function nth_value", 1910 }, 1911 { 1912 Name: "NthValue Execute Second Argument Value Error", 1913 Items: Partition{2, 3, 4, 5, 6, 7}, 1914 Function: parser.AnalyticFunction{ 1915 Name: "nth_value", 1916 Args: []parser.QueryExpression{ 1917 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1918 parser.NewIntegerValue(0), 1919 }, 1920 }, 1921 Error: "the second argument must be greater than 0 for function nth_value", 1922 }, 1923 } 1924 1925 func TestNthValue_Execute(t *testing.T) { 1926 testAnalyticFunctionExecute(t, NthValue{}, nthValueExecuteTests) 1927 } 1928 1929 var lagCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 1930 { 1931 Name: "Lag CheckArgsLen Too Little Error", 1932 Function: parser.AnalyticFunction{ 1933 Name: "lag", 1934 }, 1935 Error: "function lag takes at least 1 argument", 1936 }, 1937 { 1938 Name: "Lag CheckArgsLen Too Many Error", 1939 Function: parser.AnalyticFunction{ 1940 Name: "lag", 1941 Args: []parser.QueryExpression{ 1942 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1943 parser.NewIntegerValue(2), 1944 parser.NewIntegerValue(0), 1945 parser.NewIntegerValue(0), 1946 }, 1947 }, 1948 Error: "function lag takes at most 3 arguments", 1949 }, 1950 } 1951 1952 func TestLag_CheckArgsLen(t *testing.T) { 1953 testAnalyticFunctionCheckArgsLenTests(t, Lag{}, lagCheckArgsLenTests) 1954 } 1955 1956 var lagExecuteTests = []analyticFunctionExecuteTests{ 1957 { 1958 Name: "Lag Execute", 1959 Items: Partition{2, 3, 4, 5, 6, 7}, 1960 Function: parser.AnalyticFunction{ 1961 Name: "lag", 1962 Args: []parser.QueryExpression{ 1963 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1964 parser.NewIntegerValue(2), 1965 parser.NewIntegerValue(0), 1966 }, 1967 }, 1968 Result: map[int]value.Primary{ 1969 2: value.NewInteger(0), 1970 3: value.NewInteger(0), 1971 4: value.NewNull(), 1972 5: value.NewInteger(200), 1973 6: value.NewInteger(300), 1974 7: value.NewInteger(500), 1975 }, 1976 }, 1977 { 1978 Name: "Lag Execute With Default Value", 1979 Items: Partition{2, 3, 4, 5, 6, 7}, 1980 Function: parser.AnalyticFunction{ 1981 Name: "lag", 1982 Args: []parser.QueryExpression{ 1983 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 1984 }, 1985 }, 1986 Result: map[int]value.Primary{ 1987 2: value.NewNull(), 1988 3: value.NewNull(), 1989 4: value.NewInteger(200), 1990 5: value.NewInteger(300), 1991 6: value.NewInteger(500), 1992 7: value.NewInteger(800), 1993 }, 1994 }, 1995 { 1996 Name: "Lag Execute With IgnoreNulls", 1997 Items: Partition{2, 3, 4, 5, 6, 7}, 1998 Function: parser.AnalyticFunction{ 1999 Name: "lag", 2000 Args: []parser.QueryExpression{ 2001 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2002 parser.NewIntegerValue(2), 2003 parser.NewIntegerValue(0), 2004 }, 2005 IgnoreType: parser.Token{Token: parser.NULLS, Literal: "nulls"}, 2006 }, 2007 Result: map[int]value.Primary{ 2008 2: value.NewInteger(0), 2009 3: value.NewInteger(0), 2010 4: value.NewInteger(0), 2011 5: value.NewInteger(200), 2012 6: value.NewInteger(300), 2013 7: value.NewInteger(500), 2014 }, 2015 }, 2016 { 2017 Name: "Lag Execute First Argument Evaluation Error", 2018 Items: Partition{2, 3, 4, 5, 6, 7}, 2019 Function: parser.AnalyticFunction{ 2020 Name: "lag", 2021 Args: []parser.QueryExpression{ 2022 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 2023 parser.NewIntegerValue(2), 2024 parser.NewIntegerValue(0), 2025 }, 2026 }, 2027 Error: "field notexist does not exist", 2028 }, 2029 { 2030 Name: "Lag Execute Second Argument Evaluation Error", 2031 Items: Partition{2, 3, 4, 5, 6, 7}, 2032 Function: parser.AnalyticFunction{ 2033 Name: "lag", 2034 Args: []parser.QueryExpression{ 2035 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2036 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 2037 parser.NewIntegerValue(0), 2038 }, 2039 }, 2040 Error: "the second argument must be an integer for function lag", 2041 }, 2042 { 2043 Name: "Lag Execute Second Argument Type Error", 2044 Items: Partition{2, 3, 4, 5, 6, 7}, 2045 Function: parser.AnalyticFunction{ 2046 Name: "lag", 2047 Args: []parser.QueryExpression{ 2048 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2049 parser.NewNullValue(), 2050 parser.NewIntegerValue(0), 2051 }, 2052 }, 2053 Error: "the second argument must be an integer for function lag", 2054 }, 2055 { 2056 Name: "Lag Execute Third Argument Evaluation Error", 2057 Items: Partition{2, 3, 4, 5, 6, 7}, 2058 Function: parser.AnalyticFunction{ 2059 Name: "lag", 2060 Args: []parser.QueryExpression{ 2061 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2062 parser.NewIntegerValue(2), 2063 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 2064 }, 2065 }, 2066 Error: "field notexist does not exist", 2067 }, 2068 } 2069 2070 func TestLag_Execute(t *testing.T) { 2071 testAnalyticFunctionExecute(t, Lag{}, lagExecuteTests) 2072 } 2073 2074 var leadCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 2075 { 2076 Name: "Lead CheckArgsLen Too Little Error", 2077 Function: parser.AnalyticFunction{ 2078 Name: "lead", 2079 }, 2080 Error: "function lead takes at least 1 argument", 2081 }, 2082 } 2083 2084 func TestLead_CheckArgsLen(t *testing.T) { 2085 testAnalyticFunctionCheckArgsLenTests(t, Lead{}, leadCheckArgsLenTests) 2086 } 2087 2088 var leadExecuteTests = []analyticFunctionExecuteTests{ 2089 { 2090 Name: "Lead Execute With Default Value", 2091 Items: Partition{2, 3, 4, 5, 6, 7}, 2092 Function: parser.AnalyticFunction{ 2093 Name: "lead", 2094 Args: []parser.QueryExpression{ 2095 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2096 }, 2097 }, 2098 Result: map[int]value.Primary{ 2099 2: value.NewInteger(200), 2100 3: value.NewInteger(300), 2101 4: value.NewInteger(500), 2102 5: value.NewInteger(800), 2103 6: value.NewNull(), 2104 7: value.NewNull(), 2105 }, 2106 }, 2107 } 2108 2109 func TestLead_Execute(t *testing.T) { 2110 testAnalyticFunctionExecute(t, Lead{}, leadExecuteTests) 2111 } 2112 2113 var analyticListAggCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 2114 { 2115 Name: "ListAgg CheckArgsLen Too Little Error", 2116 Function: parser.AnalyticFunction{ 2117 Name: "listagg", 2118 }, 2119 Error: "function listagg takes at least 1 argument", 2120 }, 2121 } 2122 2123 func TestAnalyticListAgg_CheckArgsLen(t *testing.T) { 2124 testAnalyticFunctionCheckArgsLenTests(t, AnalyticListAgg{}, analyticListAggCheckArgsLenTests) 2125 } 2126 2127 var analyticListAggExecuteTests = []analyticFunctionExecuteTests{ 2128 { 2129 Name: "AnalyticListAgg Execute", 2130 Items: Partition{0, 1, 2, 3, 4}, 2131 Function: parser.AnalyticFunction{ 2132 Name: "listagg", 2133 Args: []parser.QueryExpression{ 2134 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2135 parser.NewStringValue(","), 2136 }, 2137 }, 2138 Result: map[int]value.Primary{ 2139 0: value.NewString("100,200,200,300"), 2140 1: value.NewString("100,200,200,300"), 2141 2: value.NewString("100,200,200,300"), 2142 3: value.NewString("100,200,200,300"), 2143 4: value.NewString("100,200,200,300"), 2144 }, 2145 }, 2146 { 2147 Name: "AnalyticListAgg Execute With Default Value", 2148 Items: Partition{0, 1, 2, 3, 4}, 2149 Function: parser.AnalyticFunction{ 2150 Name: "listagg", 2151 Args: []parser.QueryExpression{ 2152 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2153 }, 2154 }, 2155 Result: map[int]value.Primary{ 2156 0: value.NewString("100200200300"), 2157 1: value.NewString("100200200300"), 2158 2: value.NewString("100200200300"), 2159 3: value.NewString("100200200300"), 2160 4: value.NewString("100200200300"), 2161 }, 2162 }, 2163 { 2164 Name: "AnalyticListAgg Execute With Distinct", 2165 Items: Partition{0, 1, 2, 3, 4}, 2166 Function: parser.AnalyticFunction{ 2167 Name: "listagg", 2168 Distinct: parser.Token{Token: parser.DISTINCT, Literal: "distinct"}, 2169 Args: []parser.QueryExpression{ 2170 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2171 parser.NewStringValue(","), 2172 }, 2173 }, 2174 Result: map[int]value.Primary{ 2175 0: value.NewString("100,200,300"), 2176 1: value.NewString("100,200,300"), 2177 2: value.NewString("100,200,300"), 2178 3: value.NewString("100,200,300"), 2179 4: value.NewString("100,200,300"), 2180 }, 2181 }, 2182 { 2183 Name: "AnalyticListAgg Execute First Argument Evaluation Error", 2184 Items: Partition{0, 1, 2, 3, 4}, 2185 Function: parser.AnalyticFunction{ 2186 Name: "listagg", 2187 Args: []parser.QueryExpression{ 2188 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 2189 parser.NewStringValue(","), 2190 }, 2191 }, 2192 Error: "field notexist does not exist", 2193 }, 2194 { 2195 Name: "AnalyticListAgg Execute Second Argument Evaluation Error", 2196 Items: Partition{0, 1, 2, 3, 4}, 2197 Function: parser.AnalyticFunction{ 2198 Name: "listagg", 2199 Args: []parser.QueryExpression{ 2200 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2201 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 2202 }, 2203 }, 2204 Error: "the second argument must be a string for function listagg", 2205 }, 2206 { 2207 Name: "AnalyticListAgg Execute Second Argument Type Error", 2208 Items: Partition{0, 1, 2, 3, 4}, 2209 Function: parser.AnalyticFunction{ 2210 Name: "listagg", 2211 Args: []parser.QueryExpression{ 2212 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2213 parser.NewNullValue(), 2214 }, 2215 }, 2216 Error: "the second argument must be a string for function listagg", 2217 }, 2218 } 2219 2220 func TestAnalyticListAgg_Execute(t *testing.T) { 2221 testAnalyticFunctionExecute(t, AnalyticListAgg{}, analyticListAggExecuteTests) 2222 } 2223 2224 var analyticJsonAggCheckArgsLenTests = []analyticFunctionCheckArgsLenTests{ 2225 { 2226 Name: "JsonAgg CheckArgsLen Too Little Error", 2227 Function: parser.AnalyticFunction{ 2228 Name: "json_agg", 2229 }, 2230 Error: "function json_agg takes exactly 1 argument", 2231 }, 2232 } 2233 2234 func TestAnalyticJsonAgg_CheckArgsLen(t *testing.T) { 2235 testAnalyticFunctionCheckArgsLenTests(t, AnalyticJsonAgg{}, analyticJsonAggCheckArgsLenTests) 2236 } 2237 2238 var analyticJsonAggExecuteTests = []analyticFunctionExecuteTests{ 2239 { 2240 Name: "AnalyticJsonAgg Execute", 2241 Items: Partition{0, 1, 2, 3, 4}, 2242 Function: parser.AnalyticFunction{ 2243 Name: "json_agg", 2244 Args: []parser.QueryExpression{ 2245 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2246 }, 2247 }, 2248 Result: map[int]value.Primary{ 2249 0: value.NewString("[100,200,null,200,300]"), 2250 1: value.NewString("[100,200,null,200,300]"), 2251 2: value.NewString("[100,200,null,200,300]"), 2252 3: value.NewString("[100,200,null,200,300]"), 2253 4: value.NewString("[100,200,null,200,300]"), 2254 }, 2255 }, 2256 { 2257 Name: "AnalyticJsonAgg Execute With Distinct", 2258 Items: Partition{0, 1, 2, 3, 4}, 2259 Function: parser.AnalyticFunction{ 2260 Name: "json_agg", 2261 Distinct: parser.Token{Token: parser.DISTINCT, Literal: "distinct"}, 2262 Args: []parser.QueryExpression{ 2263 parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, 2264 }, 2265 }, 2266 Result: map[int]value.Primary{ 2267 0: value.NewString("[100,200,null,300]"), 2268 1: value.NewString("[100,200,null,300]"), 2269 2: value.NewString("[100,200,null,300]"), 2270 3: value.NewString("[100,200,null,300]"), 2271 4: value.NewString("[100,200,null,300]"), 2272 }, 2273 }, 2274 { 2275 Name: "AnalyticJsonAgg Execute First Argument Evaluation Error", 2276 Items: Partition{0, 1, 2, 3, 4}, 2277 Function: parser.AnalyticFunction{ 2278 Name: "json_agg", 2279 Args: []parser.QueryExpression{ 2280 parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}, 2281 }, 2282 }, 2283 Error: "field notexist does not exist", 2284 }, 2285 } 2286 2287 func TestAnalyticJsonAgg_Execute(t *testing.T) { 2288 testAnalyticFunctionExecute(t, AnalyticJsonAgg{}, analyticJsonAggExecuteTests) 2289 }