github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/aggregation/window_functions.go (about) 1 // Copyright 2022 DoltHub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package aggregation 16 17 import ( 18 "sort" 19 "strings" 20 21 "github.com/dolthub/go-mysql-server/sql" 22 "github.com/dolthub/go-mysql-server/sql/expression" 23 "github.com/dolthub/go-mysql-server/sql/types" 24 ) 25 26 var _ sql.WindowFunction = (*SumAgg)(nil) 27 var _ sql.WindowFunction = (*MaxAgg)(nil) 28 var _ sql.WindowFunction = (*MinAgg)(nil) 29 var _ sql.WindowFunction = (*AvgAgg)(nil) 30 var _ sql.WindowFunction = (*LastAgg)(nil) 31 var _ sql.WindowFunction = (*FirstAgg)(nil) 32 var _ sql.WindowFunction = (*CountAgg)(nil) 33 var _ sql.WindowFunction = (*GroupConcatAgg)(nil) 34 var _ sql.WindowFunction = (*WindowedJSONArrayAgg)(nil) 35 var _ sql.WindowFunction = (*WindowedJSONObjectAgg)(nil) 36 37 var _ sql.WindowFunction = (*PercentRank)(nil) 38 var _ sql.WindowFunction = (*RowNumber)(nil) 39 var _ sql.WindowFunction = (*Lag)(nil) 40 var _ sql.WindowFunction = (*Lead)(nil) 41 42 type AnyValueAgg struct { 43 expr sql.Expression 44 framer sql.WindowFramer 45 } 46 47 func NewAnyValueAgg(e sql.Expression) *AnyValueAgg { 48 return &AnyValueAgg{ 49 expr: e, 50 } 51 } 52 53 func (a *AnyValueAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 54 na := *a 55 if w.Frame != nil { 56 framer, err := w.Frame.NewFramer(w) 57 if err != nil { 58 return nil, err 59 } 60 na.framer = framer 61 } 62 return &na, nil 63 } 64 65 func (a *AnyValueAgg) Dispose() { 66 expression.Dispose(a.expr) 67 } 68 69 // DefaultFramer returns a NewUnboundedPrecedingToCurrentRowFramer 70 func (a *AnyValueAgg) DefaultFramer() sql.WindowFramer { 71 if a.framer != nil { 72 return a.framer 73 } 74 return NewUnboundedPrecedingToCurrentRowFramer() 75 } 76 77 func (a *AnyValueAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) error { 78 a.Dispose() 79 return nil 80 } 81 82 func (a *AnyValueAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 83 for i := interval.Start; i < interval.End; i++ { 84 row := buf[i] 85 v, err := a.expr.Eval(ctx, row) 86 if err != nil { 87 return err 88 } 89 return v 90 } 91 return nil 92 } 93 94 type SumAgg struct { 95 partitionStart, partitionEnd int 96 expr sql.Expression 97 framer sql.WindowFramer 98 99 // use prefix sums to quickly calculate arbitrary frame sum within partition 100 prefixSum []float64 101 } 102 103 func NewSumAgg(e sql.Expression) *SumAgg { 104 return &SumAgg{ 105 partitionStart: -1, 106 partitionEnd: -1, 107 expr: e, 108 } 109 } 110 111 func (a *SumAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 112 na := *a 113 if w.Frame != nil { 114 framer, err := w.Frame.NewFramer(w) 115 if err != nil { 116 return nil, err 117 } 118 na.framer = framer 119 } 120 return &na, nil 121 } 122 123 func (a *SumAgg) Dispose() { 124 expression.Dispose(a.expr) 125 } 126 127 // DefaultFramer returns a NewUnboundedPrecedingToCurrentRowFramer 128 func (a *SumAgg) DefaultFramer() sql.WindowFramer { 129 if a.framer != nil { 130 return a.framer 131 } 132 return NewUnboundedPrecedingToCurrentRowFramer() 133 } 134 135 func (a *SumAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) error { 136 a.partitionStart, a.partitionEnd = interval.Start, interval.End 137 a.Dispose() 138 var err error 139 a.prefixSum, _, err = floatPrefixSum(ctx, interval, buf, a.expr) 140 return err 141 } 142 143 func (a *SumAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 144 panic("sliding window interface not implemented yet") 145 } 146 147 func (a *SumAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 148 if interval.End-interval.Start < 1 { 149 return nil 150 } 151 return computePrefixSum(interval, a.partitionStart, a.prefixSum) 152 } 153 154 func floatPrefixSum(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer, e sql.Expression) ([]float64, []int, error) { 155 intervalLen := interval.End - interval.Start 156 sums := make([]float64, intervalLen) 157 nulls := make([]int, intervalLen) 158 var last float64 159 var nullCnt int 160 for i := 0; i < intervalLen; i++ { 161 v, err := e.Eval(ctx, buf[interval.Start+i]) 162 if err != nil { 163 continue 164 } 165 val, _, err := types.Float64.Convert(v) 166 if err != nil || val == nil { 167 val = float64(0) 168 nullCnt += 1 169 } 170 last += val.(float64) 171 sums[i] = last 172 nulls[i] = nullCnt 173 } 174 return sums, nulls, nil 175 } 176 177 func computePrefixSum(interval sql.WindowInterval, partitionStart int, prefixSum []float64) float64 { 178 startIdx := interval.Start - partitionStart - 1 179 endIdx := interval.End - partitionStart - 1 180 181 var sum float64 182 if endIdx >= 0 { 183 sum = prefixSum[endIdx] 184 } 185 if startIdx >= 0 { 186 sum -= prefixSum[startIdx] 187 } 188 return sum 189 } 190 191 type AvgAgg struct { 192 partitionStart int 193 partitionEnd int 194 expr sql.Expression 195 framer sql.WindowFramer 196 197 // use prefix sums to quickly calculate arbitrary frame sum within partition 198 prefixSum []float64 199 // exclude nulls in average denominator 200 nullCnt []int 201 } 202 203 func NewAvgAgg(e sql.Expression) *AvgAgg { 204 return &AvgAgg{ 205 expr: e, 206 } 207 } 208 209 func (a *AvgAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 210 na := *a 211 if w.Frame != nil { 212 framer, err := w.Frame.NewFramer(w) 213 if err != nil { 214 return nil, err 215 } 216 na.framer = framer 217 } 218 return &na, nil 219 } 220 221 func (a *AvgAgg) Dispose() { 222 expression.Dispose(a.expr) 223 } 224 225 // DefaultFramer returns a NewUnboundedPrecedingToCurrentRowFramer 226 func (a *AvgAgg) DefaultFramer() sql.WindowFramer { 227 if a.framer != nil { 228 return a.framer 229 } 230 return NewUnboundedPrecedingToCurrentRowFramer() 231 } 232 233 func (a *AvgAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) error { 234 a.Dispose() 235 a.partitionStart = interval.Start 236 a.partitionEnd = interval.End 237 var err error 238 a.prefixSum, a.nullCnt, err = floatPrefixSum(ctx, interval, buf, a.expr) 239 return err 240 } 241 242 func (a *AvgAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 243 panic("sliding window interface not implemented yet") 244 } 245 246 func (a *AvgAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 247 startIdx := interval.Start - a.partitionStart - 1 248 endIdx := interval.End - a.partitionStart - 1 249 250 var nonNullCnt int 251 if endIdx >= 0 { 252 nonNullCnt += endIdx + 1 253 nonNullCnt -= a.nullCnt[endIdx] 254 } 255 if startIdx >= 0 { 256 nonNullCnt -= startIdx + 1 257 nonNullCnt += a.nullCnt[startIdx] 258 } 259 return computePrefixSum(interval, a.partitionStart, a.prefixSum) / float64(nonNullCnt) 260 } 261 262 type BitAndAgg struct { 263 expr sql.Expression 264 framer sql.WindowFramer 265 } 266 267 func NewBitAndAgg(e sql.Expression) *BitAndAgg { 268 return &BitAndAgg{ 269 expr: e, 270 } 271 } 272 273 func (b *BitAndAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 274 na := *b 275 if w.Frame != nil { 276 framer, err := w.Frame.NewFramer(w) 277 if err != nil { 278 return nil, err 279 } 280 na.framer = framer 281 } 282 return &na, nil 283 } 284 285 func (b *BitAndAgg) Dispose() { 286 expression.Dispose(b.expr) 287 } 288 289 // DefaultFramer returns a NewUnboundedPrecedingToCurrentRowFramer 290 func (b *BitAndAgg) DefaultFramer() sql.WindowFramer { 291 if b.framer != nil { 292 return b.framer 293 } 294 return NewPartitionFramer() 295 } 296 297 func (b *BitAndAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) error { 298 b.Dispose() 299 return nil 300 } 301 302 func (b *BitAndAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 303 panic("sliding window interface not implemented yet") 304 } 305 306 func (b *BitAndAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 307 res := ^uint64(0) // bitwise not xor, so 0xffff... 308 for i := interval.Start; i < interval.End; i++ { 309 row := buf[i] 310 v, err := b.expr.Eval(ctx, row) 311 if err != nil { 312 return err 313 } 314 315 if v == nil { 316 continue 317 } 318 319 val, _, err := types.Uint64.Convert(v) 320 if err != nil { 321 return 0 322 } 323 324 res &= val.(uint64) 325 } 326 return res 327 } 328 329 type BitOrAgg struct { 330 expr sql.Expression 331 framer sql.WindowFramer 332 } 333 334 func NewBitOrAgg(e sql.Expression) *BitOrAgg { 335 return &BitOrAgg{ 336 expr: e, 337 } 338 } 339 340 func (b *BitOrAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 341 na := *b 342 if w.Frame != nil { 343 framer, err := w.Frame.NewFramer(w) 344 if err != nil { 345 return nil, err 346 } 347 na.framer = framer 348 } 349 return &na, nil 350 } 351 352 func (b *BitOrAgg) Dispose() { 353 expression.Dispose(b.expr) 354 } 355 356 // DefaultFramer returns a NewUnboundedPrecedingToCurrentRowFramer 357 func (b *BitOrAgg) DefaultFramer() sql.WindowFramer { 358 if b.framer != nil { 359 return b.framer 360 } 361 return NewPartitionFramer() 362 } 363 364 func (b *BitOrAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) error { 365 b.Dispose() 366 return nil 367 } 368 369 func (b *BitOrAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 370 panic("sliding window interface not implemented yet") 371 } 372 373 func (b *BitOrAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 374 var res uint64 375 for i := interval.Start; i < interval.End; i++ { 376 row := buf[i] 377 v, err := b.expr.Eval(ctx, row) 378 if err != nil { 379 return err 380 } 381 382 if v == nil { 383 continue 384 } 385 386 val, _, err := types.Uint64.Convert(v) 387 if err != nil { 388 return 0 389 } 390 391 res |= val.(uint64) 392 } 393 return res 394 } 395 396 type BitXorAgg struct { 397 expr sql.Expression 398 framer sql.WindowFramer 399 } 400 401 func NewBitXorAgg(e sql.Expression) *BitXorAgg { 402 return &BitXorAgg{ 403 expr: e, 404 } 405 } 406 407 func (b *BitXorAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 408 na := *b 409 if w.Frame != nil { 410 framer, err := w.Frame.NewFramer(w) 411 if err != nil { 412 return nil, err 413 } 414 na.framer = framer 415 } 416 return &na, nil 417 } 418 419 func (b *BitXorAgg) Dispose() { 420 expression.Dispose(b.expr) 421 } 422 423 // DefaultFramer returns a NewUnboundedPrecedingToCurrentRowFramer 424 func (b *BitXorAgg) DefaultFramer() sql.WindowFramer { 425 if b.framer != nil { 426 return b.framer 427 } 428 return NewPartitionFramer() 429 } 430 431 func (b *BitXorAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) error { 432 b.Dispose() 433 return nil 434 } 435 436 func (b *BitXorAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 437 panic("sliding window interface not implemented yet") 438 } 439 440 func (b *BitXorAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 441 var res uint64 442 for i := interval.Start; i < interval.End; i++ { 443 row := buf[i] 444 v, err := b.expr.Eval(ctx, row) 445 if err != nil { 446 return err 447 } 448 449 if v == nil { 450 continue 451 } 452 453 // TODO: handle strings 454 val, _, err := types.Uint64.Convert(v) 455 if err != nil { 456 return 0 457 } 458 459 res ^= val.(uint64) 460 } 461 return res 462 } 463 464 type MaxAgg struct { 465 expr sql.Expression 466 framer sql.WindowFramer 467 } 468 469 func NewMaxAgg(e sql.Expression) *MaxAgg { 470 return &MaxAgg{ 471 expr: e, 472 } 473 } 474 475 func (a *MaxAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 476 na := *a 477 if w.Frame != nil { 478 framer, err := w.Frame.NewFramer(w) 479 if err != nil { 480 return nil, err 481 } 482 na.framer = framer 483 } 484 return &na, nil 485 } 486 487 func (a *MaxAgg) Dispose() { 488 expression.Dispose(a.expr) 489 } 490 491 // DefaultFramer returns a NewPartitionFramer 492 func (a *MaxAgg) DefaultFramer() sql.WindowFramer { 493 if a.framer != nil { 494 return a.framer 495 } 496 return NewPartitionFramer() 497 } 498 499 func (a *MaxAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buffer sql.WindowBuffer) error { 500 a.Dispose() 501 return nil 502 } 503 504 func (a *MaxAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 505 panic("sliding window interface not implemented yet") 506 } 507 508 func (a *MaxAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buffer sql.WindowBuffer) interface{} { 509 var max interface{} 510 for i := interval.Start; i < interval.End; i++ { 511 row := buffer[i] 512 v, err := a.expr.Eval(ctx, row) 513 if err != nil { 514 return err 515 } 516 517 if v == nil { 518 continue 519 } 520 521 if max == nil { 522 max = v 523 } 524 525 cmp, err := a.expr.Type().Compare(v, max) 526 if err != nil { 527 return err 528 } 529 if cmp == 1 { 530 max = v 531 } 532 } 533 return max 534 } 535 536 type MinAgg struct { 537 expr sql.Expression 538 framer sql.WindowFramer 539 } 540 541 func NewMinAgg(e sql.Expression) *MinAgg { 542 return &MinAgg{ 543 expr: e, 544 } 545 } 546 547 func (a *MinAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 548 na := *a 549 if w.Frame != nil { 550 framer, err := w.Frame.NewFramer(w) 551 if err != nil { 552 return nil, err 553 } 554 na.framer = framer 555 } 556 return &na, nil 557 } 558 559 func (a *MinAgg) Dispose() { 560 expression.Dispose(a.expr) 561 } 562 563 // DefaultFramer returns a NewUnboundedPrecedingToCurrentRowFramer 564 func (a *MinAgg) DefaultFramer() sql.WindowFramer { 565 if a.framer != nil { 566 return a.framer 567 } 568 return NewUnboundedPrecedingToCurrentRowFramer() 569 } 570 571 func (a *MinAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buffer sql.WindowBuffer) error { 572 a.Dispose() 573 return nil 574 } 575 576 func (a *MinAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 577 panic("sliding window interface not implemented yet") 578 } 579 580 func (a *MinAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 581 var min interface{} 582 for _, row := range buf[interval.Start:interval.End] { 583 v, err := a.expr.Eval(ctx, row) 584 if err != nil { 585 return err 586 } 587 588 if v == nil { 589 continue 590 } 591 592 if min == nil { 593 min = v 594 continue 595 } 596 597 cmp, err := a.expr.Type().Compare(v, min) 598 if err != nil { 599 return err 600 } 601 if cmp == -1 { 602 min = v 603 } 604 } 605 return min 606 } 607 608 type LastAgg struct { 609 expr sql.Expression 610 framer sql.WindowFramer 611 } 612 613 func NewLastAgg(e sql.Expression) *LastAgg { 614 return &LastAgg{ 615 expr: e, 616 } 617 } 618 619 func (a *LastAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 620 na := *a 621 if w != nil && w.Frame != nil { 622 framer, err := w.Frame.NewFramer(w) 623 if err != nil { 624 return nil, err 625 } 626 na.framer = framer 627 } 628 return &na, nil 629 } 630 631 func (a *LastAgg) Dispose() { 632 expression.Dispose(a.expr) 633 } 634 635 // DefaultFramer returns a NewUnboundedPrecedingToCurrentRowFramer 636 func (a *LastAgg) DefaultFramer() sql.WindowFramer { 637 if a.framer != nil { 638 return a.framer 639 } 640 return NewUnboundedPrecedingToCurrentRowFramer() 641 } 642 643 func (a *LastAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buffer sql.WindowBuffer) error { 644 a.Dispose() 645 return nil 646 } 647 648 func (a *LastAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 649 panic("sliding window interface not implemented yet") 650 } 651 652 func (a *LastAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buffer sql.WindowBuffer) interface{} { 653 if interval.End-interval.Start < 1 { 654 return nil 655 } 656 row := buffer[interval.End-1] 657 v, err := a.expr.Eval(ctx, row) 658 if err != nil { 659 return err 660 } 661 return v 662 } 663 664 type FirstAgg struct { 665 partitionStart, partitionEnd int 666 expr sql.Expression 667 framer sql.WindowFramer 668 } 669 670 func NewFirstAgg(e sql.Expression) *FirstAgg { 671 return &FirstAgg{ 672 expr: e, 673 } 674 } 675 676 func (a *FirstAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 677 na := *a 678 if w.Frame != nil { 679 framer, err := w.Frame.NewFramer(w) 680 if err != nil { 681 return nil, err 682 } 683 na.framer = framer 684 } 685 return &na, nil 686 } 687 688 func (a *FirstAgg) Dispose() { 689 expression.Dispose(a.expr) 690 } 691 692 // DefaultFramer returns a NewUnboundedPrecedingToCurrentRowFramer 693 func (a *FirstAgg) DefaultFramer() sql.WindowFramer { 694 if a.framer != nil { 695 return a.framer 696 } 697 return NewUnboundedPrecedingToCurrentRowFramer() 698 } 699 700 func (a *FirstAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buffer sql.WindowBuffer) error { 701 a.Dispose() 702 a.partitionStart, a.partitionEnd = interval.Start, interval.End 703 return nil 704 } 705 706 func (a *FirstAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 707 panic("sliding window interface not implemented yet") 708 } 709 710 func (a *FirstAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buffer sql.WindowBuffer) interface{} { 711 if interval.End-interval.Start < 1 { 712 return nil 713 } 714 row := buffer[interval.Start] 715 v, err := a.expr.Eval(ctx, row) 716 if err != nil { 717 return err 718 } 719 return v 720 } 721 722 type CountAgg struct { 723 partitionStart int 724 partitionEnd int 725 expr sql.Expression 726 framer sql.WindowFramer 727 728 // use prefix sums to quickly calculate arbitrary a frame's row cnt within partition 729 prefixSum []float64 730 // orderBy tracks peer group increments 731 orderBy []sql.Expression 732 // pos increments every iteration 733 pos int 734 // peerGroup tracks value increments 735 peerGroup sql.WindowInterval 736 } 737 738 func NewCountAgg(e sql.Expression) *CountAgg { 739 return &CountAgg{ 740 partitionStart: -1, 741 partitionEnd: -1, 742 expr: e, 743 } 744 } 745 746 func NewCountDistinctAgg(e sql.Expression) *CountAgg { 747 e = expression.NewDistinctExpression(e) 748 return &CountAgg{ 749 partitionStart: -1, 750 partitionEnd: -1, 751 expr: e, 752 } 753 } 754 755 func (a *CountAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 756 na := *a 757 if w.Frame != nil { 758 framer, err := w.Frame.NewFramer(w) 759 if err != nil { 760 return nil, err 761 } 762 na.framer = framer 763 return &na, nil 764 } 765 if w.OrderBy != nil { 766 na.orderBy = w.OrderBy.ToExpressions() 767 } 768 return &na, nil 769 } 770 771 func (a *CountAgg) Dispose() { 772 expression.Dispose(a.expr) 773 } 774 775 // DefaultFramer returns a NewPartitionFramer 776 func (a *CountAgg) DefaultFramer() sql.WindowFramer { 777 if a.framer != nil { 778 return a.framer 779 } 780 781 if a.orderBy == nil || len(a.orderBy) < 1 { 782 return NewPartitionFramer() 783 } 784 785 return &RangeUnboundedPrecedingToCurrentRowFramer{ 786 rangeFramerBase{ 787 orderBy: a.orderBy[0], 788 unboundedPreceding: true, 789 endCurrentRow: true, 790 }, 791 } 792 } 793 794 func (a *CountAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) error { 795 a.Dispose() 796 a.partitionStart, a.partitionEnd = interval.Start, interval.End 797 a.pos = a.partitionStart 798 a.peerGroup = sql.WindowInterval{} 799 var err error 800 a.prefixSum, err = countPrefixSum(ctx, interval, buf, a.expr) 801 if err != nil { 802 return err 803 } 804 return nil 805 } 806 807 func (a *CountAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 808 panic("sliding window interface not implemented yet") 809 } 810 811 func (a *CountAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 812 a.pos++ 813 return int64(computePrefixSum(sql.WindowInterval{Start: interval.Start, End: interval.End}, a.partitionStart, a.prefixSum)) 814 } 815 816 func countPrefixSum(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer, expr sql.Expression) ([]float64, error) { 817 intervalLen := interval.End - interval.Start 818 sums := make([]float64, intervalLen) 819 var last float64 820 for i := 0; i < intervalLen; i++ { 821 row := buf[interval.Start+i] 822 var inc bool 823 if _, ok := expr.(*expression.Star); ok { 824 inc = true 825 } else { 826 v, err := expr.Eval(ctx, row) 827 if v != nil { 828 inc = true 829 } 830 831 if err != nil { 832 return nil, err 833 } 834 } 835 836 if inc { 837 last += 1 838 } 839 sums[i] = last 840 } 841 return sums, nil 842 } 843 844 type GroupConcatAgg struct { 845 gc *GroupConcat 846 framer sql.WindowFramer 847 // hash map to deduplicate values 848 // TODO make this more efficient, ideally with sliding window and hashes 849 distinct map[string]struct{} 850 // original row order used for optional result sorting 851 rows []sql.Row 852 } 853 854 func NewGroupConcatAgg(gc *GroupConcat) *GroupConcatAgg { 855 return &GroupConcatAgg{ 856 gc: gc, 857 } 858 } 859 860 func (a *GroupConcatAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 861 na := *a 862 if w.Frame != nil { 863 framer, err := w.Frame.NewFramer(w) 864 if err != nil { 865 return nil, err 866 } 867 na.framer = framer 868 } 869 return &na, nil 870 } 871 872 func (a *GroupConcatAgg) Dispose() { 873 expression.Dispose(a.gc) 874 } 875 876 // DefaultFramer returns a NewUnboundedPrecedingToCurrentRowFramer 877 func (a *GroupConcatAgg) DefaultFramer() sql.WindowFramer { 878 if a.framer != nil { 879 return a.framer 880 } 881 return NewUnboundedPrecedingToCurrentRowFramer() 882 } 883 884 func (a *GroupConcatAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) error { 885 a.Dispose() 886 var err error 887 a.rows, a.distinct, err = a.filterToDistinct(ctx, buf[interval.Start:interval.End]) 888 return err 889 } 890 891 func (a *GroupConcatAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 892 panic("sliding window interface not implemented yet") 893 } 894 895 func (a *GroupConcatAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 896 rows := a.rows 897 898 if len(rows) == 0 { 899 return nil 900 } 901 902 // Execute the order operation if it exists. 903 if a.gc.sf != nil { 904 sorter := &expression.Sorter{ 905 SortFields: a.gc.sf, 906 Rows: rows, 907 Ctx: ctx, 908 } 909 910 sort.Stable(sorter) 911 if sorter.LastError != nil { 912 return nil 913 } 914 } 915 916 sb := strings.Builder{} 917 for i, row := range rows { 918 lastIdx := len(row) - 1 919 if i == 0 { 920 sb.WriteString(row[lastIdx].(string)) 921 } else { 922 sb.WriteString(a.gc.separator) 923 sb.WriteString(row[lastIdx].(string)) 924 } 925 926 // Don't allow the string to cross maxlen 927 if sb.Len() >= a.gc.maxLen { 928 break 929 } 930 } 931 932 ret := sb.String() 933 934 // There might be a couple of character differences even if we broke early in the loop 935 if len(ret) > a.gc.maxLen { 936 ret = ret[:a.gc.maxLen] 937 } 938 939 // Add this to handle any one off errors. 940 return ret 941 } 942 943 func (a *GroupConcatAgg) filterToDistinct(ctx *sql.Context, buf sql.WindowBuffer) ([]sql.Row, map[string]struct{}, error) { 944 rows := make([]sql.Row, 0) 945 distinct := make(map[string]struct{}, 0) 946 for _, row := range buf { 947 evalRow, retType, err := evalExprs(ctx, a.gc.selectExprs, row) 948 if err != nil { 949 return nil, nil, err 950 } 951 952 a.gc.returnType = retType 953 954 // Skip if this is a null row 955 if evalRow == nil { 956 continue 957 } 958 959 var v interface{} 960 if retType == types.Blob { 961 v, _, err = types.Blob.Convert(evalRow[0]) 962 } else { 963 v, _, err = types.LongText.Convert(evalRow[0]) 964 } 965 966 if err != nil { 967 return nil, nil, err 968 } 969 970 if v == nil { 971 continue 972 } 973 974 vs := v.(string) 975 976 // Get the current array of rows and the map 977 // Check if distinct is active if so look at and update our map 978 if a.gc.distinct != "" { 979 // If this value exists go ahead and return nil 980 if _, ok := distinct[vs]; ok { 981 continue 982 } else { 983 distinct[vs] = struct{}{} 984 } 985 } 986 987 // Append the current value to the end of the row. We want to preserve the row's original structure for 988 // for sort ordering in the final step. 989 rows = append(rows, append(row, nil, vs)) 990 } 991 return rows, distinct, nil 992 } 993 994 type WindowedJSONArrayAgg struct { 995 expr sql.Expression 996 framer sql.WindowFramer 997 } 998 999 func NewJsonArrayAgg(expr sql.Expression) *WindowedJSONArrayAgg { 1000 return &WindowedJSONArrayAgg{ 1001 expr: expr, 1002 } 1003 } 1004 1005 func (a *WindowedJSONArrayAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 1006 na := *a 1007 if w.Frame != nil { 1008 framer, err := w.Frame.NewFramer(w) 1009 if err != nil { 1010 return nil, err 1011 } 1012 na.framer = framer 1013 } 1014 return &na, nil 1015 } 1016 1017 func (a *WindowedJSONArrayAgg) Dispose() { 1018 expression.Dispose(a.expr) 1019 } 1020 1021 // DefaultFramer returns a NewUnboundedPrecedingToCurrentRowFramer 1022 func (a *WindowedJSONArrayAgg) DefaultFramer() sql.WindowFramer { 1023 return NewUnboundedPrecedingToCurrentRowFramer() 1024 } 1025 1026 func (a *WindowedJSONArrayAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) error { 1027 a.Dispose() 1028 return nil 1029 } 1030 1031 func (a *WindowedJSONArrayAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 1032 panic("sliding window interface not implemented yet") 1033 } 1034 1035 func (a *WindowedJSONArrayAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 1036 res, err := a.aggregateVals(ctx, interval, buf) 1037 if err != nil { 1038 return nil 1039 } 1040 return types.JSONDocument{Val: res} 1041 } 1042 1043 func (a *WindowedJSONArrayAgg) aggregateVals(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) ([]interface{}, error) { 1044 vals := make([]interface{}, 0, interval.End-interval.Start) 1045 for _, row := range buf[interval.Start:interval.End] { 1046 v, err := a.expr.Eval(ctx, row) 1047 if err != nil { 1048 return nil, err 1049 } 1050 1051 // unwrap JSON values 1052 if js, ok := v.(sql.JSONWrapper); ok { 1053 v = js.ToInterface() 1054 } 1055 1056 vals = append(vals, v) 1057 } 1058 1059 return vals, nil 1060 } 1061 1062 type WindowedJSONObjectAgg struct { 1063 j *JSONObjectAgg 1064 framer sql.WindowFramer 1065 // we need to eval the partition before Compute to return nil key errors 1066 vals map[string]interface{} 1067 } 1068 1069 func NewWindowedJSONObjectAgg(j *JSONObjectAgg) *WindowedJSONObjectAgg { 1070 return &WindowedJSONObjectAgg{ 1071 j: j, 1072 } 1073 } 1074 1075 func (a *WindowedJSONObjectAgg) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 1076 na := *a 1077 if w.Frame != nil { 1078 framer, err := w.Frame.NewFramer(w) 1079 if err != nil { 1080 return nil, err 1081 } 1082 na.framer = framer 1083 } 1084 return &na, nil 1085 } 1086 1087 func (a *WindowedJSONObjectAgg) Dispose() { 1088 expression.Dispose(a.j) 1089 } 1090 1091 // DefaultFramer returns a NewUnboundedPrecedingToCurrentRowFramer 1092 func (a *WindowedJSONObjectAgg) DefaultFramer() sql.WindowFramer { 1093 if a.framer != nil { 1094 return a.framer 1095 } 1096 return NewUnboundedPrecedingToCurrentRowFramer() 1097 } 1098 1099 func (a *WindowedJSONObjectAgg) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) error { 1100 a.Dispose() 1101 var err error 1102 a.vals, err = a.aggregateVals(ctx, interval, buf) 1103 return err 1104 } 1105 1106 func (a *WindowedJSONObjectAgg) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 1107 panic("sliding window interface not implemented yet") 1108 } 1109 1110 func (a *WindowedJSONObjectAgg) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 1111 if len(a.vals) == 0 { 1112 return nil 1113 } 1114 return types.JSONDocument{Val: a.vals} 1115 } 1116 1117 func (a *WindowedJSONObjectAgg) aggregateVals(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) (map[string]interface{}, error) { 1118 vals := make(map[string]interface{}, 0) 1119 for _, row := range buf[interval.Start:interval.End] { 1120 key, err := a.j.key.Eval(ctx, row) 1121 if err != nil { 1122 return nil, err 1123 } 1124 1125 // An error occurs if any key name is NULL 1126 if key == nil { 1127 return nil, sql.ErrJSONObjectAggNullKey.New() 1128 } 1129 1130 val, err := a.j.value.Eval(ctx, row) 1131 if err != nil { 1132 return nil, err 1133 } 1134 1135 // unwrap JSON values 1136 if js, ok := val.(sql.JSONWrapper); ok { 1137 val = js.ToInterface() 1138 } 1139 1140 // Update the map. 1141 keyAsString, _, err := types.LongText.Convert(key) 1142 if err != nil { 1143 continue 1144 } 1145 vals[keyAsString.(string)] = val 1146 1147 } 1148 1149 return vals, nil 1150 } 1151 1152 type RowNumber struct { 1153 pos int 1154 } 1155 1156 func NewRowNumber() *RowNumber { 1157 return &RowNumber{ 1158 pos: -1, 1159 } 1160 } 1161 1162 func (a *RowNumber) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 1163 return a, nil 1164 } 1165 1166 func (a *RowNumber) Dispose() { 1167 return 1168 } 1169 1170 // DefaultFramer returns a NewPartitionFramer 1171 func (a *RowNumber) DefaultFramer() sql.WindowFramer { 1172 return NewPartitionFramer() 1173 } 1174 1175 func (a *RowNumber) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buffer sql.WindowBuffer) error { 1176 a.Dispose() 1177 a.pos = 1 1178 return nil 1179 } 1180 1181 func (a *RowNumber) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 1182 panic("implement me") 1183 } 1184 1185 func (a *RowNumber) Compute(ctx *sql.Context, interval sql.WindowInterval, buffer sql.WindowBuffer) interface{} { 1186 if interval.End-interval.Start < 1 { 1187 return nil 1188 } 1189 defer func() { a.pos++ }() 1190 return a.pos 1191 } 1192 1193 type rankBase struct { 1194 partitionStart, partitionEnd int 1195 1196 // orderBy tracks peer group increments 1197 orderBy []sql.Expression 1198 // pos increments every iteration 1199 pos int 1200 // peerGroup tracks value increments 1201 peerGroup sql.WindowInterval 1202 } 1203 1204 func (a *rankBase) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 1205 na := *a 1206 na.orderBy = w.OrderBy.ToExpressions() 1207 return &na, nil 1208 } 1209 1210 func (a *rankBase) Dispose() { 1211 return 1212 } 1213 1214 func (a *rankBase) DefaultFramer() sql.WindowFramer { 1215 return NewPeerGroupFramer(a.orderBy) 1216 } 1217 1218 func (a *rankBase) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buffer sql.WindowBuffer) error { 1219 a.Dispose() 1220 a.partitionStart, a.partitionEnd = interval.Start, interval.End 1221 a.pos = a.partitionStart 1222 a.peerGroup = sql.WindowInterval{} 1223 return nil 1224 } 1225 1226 func (a *rankBase) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 1227 panic("implement me") 1228 } 1229 1230 // Compute returns the number of elements before the current peer group (rank) + 1. 1231 // ex: [1, 2, 2, 2, 3, 3, 3, 4, 5, 5, 6] => every 3 returns uint64(5) because 1232 // there are 4 values less than 3 1233 func (a *rankBase) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 1234 if interval.End-interval.Start < 1 { 1235 return nil 1236 } 1237 defer func() { a.pos++ }() 1238 switch { 1239 case a.pos == 0: 1240 return uint64(1) 1241 case a.partitionEnd-a.partitionStart == 1: 1242 return uint64(1) 1243 default: 1244 return uint64(interval.Start-a.partitionStart) + 1 1245 } 1246 } 1247 1248 type Rank struct { 1249 *rankBase 1250 } 1251 1252 func NewRank(orderBy []sql.Expression) *Rank { 1253 return &Rank{ 1254 &rankBase{ 1255 partitionStart: -1, 1256 partitionEnd: -1, 1257 pos: -1, 1258 orderBy: orderBy, 1259 }, 1260 } 1261 } 1262 1263 type PercentRank struct { 1264 *rankBase 1265 } 1266 1267 func NewPercentRank(orderBy []sql.Expression) *PercentRank { 1268 return &PercentRank{ 1269 &rankBase{ 1270 partitionStart: -1, 1271 partitionEnd: -1, 1272 pos: -1, 1273 orderBy: orderBy, 1274 }, 1275 } 1276 } 1277 1278 // Compute returns the number of elements before the current peer group (rank), 1279 // and returns (rank - 1)/(rows - 1). 1280 // ex: [1, 2, 2, 2, 3, 3, 3, 4, 5, 5, 6] => every 3 returns float64(4) / float64(9), because 1281 // there are 4 values less than 3, and there are (10 - 1) total rows in the list. 1282 func (a *PercentRank) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 1283 rank := a.rankBase.Compute(ctx, interval, buf) 1284 if rank == nil { 1285 return nil 1286 } 1287 if a.partitionEnd-a.partitionStart == 1 { 1288 return float64(0) 1289 } 1290 return float64(rank.(uint64)-1) / float64(a.partitionEnd-a.partitionStart-1) 1291 } 1292 1293 type DenseRank struct { 1294 *rankBase 1295 // prevRank tracks what the previous non-dense rank was 1296 prevRank uint64 1297 // denseRank tracks what the previous dense rank is 1298 denseRank uint64 1299 } 1300 1301 func NewDenseRank(orderBy []sql.Expression) *DenseRank { 1302 return &DenseRank{ 1303 rankBase: &rankBase{ 1304 partitionStart: -1, 1305 partitionEnd: -1, 1306 pos: -1, 1307 orderBy: orderBy, 1308 }, 1309 } 1310 } 1311 1312 // Compute returns the number of unique elements before the current peer group (rank) + 1. 1313 // ex: [1, 2, 2, 2, 3, 3, 3, 4, 5, 5, 6] => every 3 returns uint64(3) because 1314 // there are 2 unique values less than 3 1315 func (a *DenseRank) Compute(ctx *sql.Context, interval sql.WindowInterval, buf sql.WindowBuffer) interface{} { 1316 rank := a.rankBase.Compute(ctx, interval, buf) 1317 if rank == nil { 1318 return nil 1319 } 1320 1321 if rank.(uint64) == 1 { 1322 a.prevRank = 1 1323 a.denseRank = 1 1324 } else if rank != a.prevRank { 1325 a.prevRank = rank.(uint64) 1326 a.denseRank += 1 1327 } 1328 return a.denseRank 1329 } 1330 1331 type Lag struct { 1332 leadLagBase 1333 } 1334 1335 func NewLag(expr, def sql.Expression, offset int) *Lag { 1336 return &Lag{ 1337 leadLagBase: leadLagBase{ 1338 expr: expr, 1339 def: def, 1340 offset: offset, 1341 }, 1342 } 1343 } 1344 1345 type Lead struct { 1346 leadLagBase 1347 } 1348 1349 func NewLead(expr, def sql.Expression, offset int) *Lead { 1350 return &Lead{ 1351 leadLagBase: leadLagBase{ 1352 expr: expr, 1353 def: def, 1354 offset: -offset, 1355 }, 1356 } 1357 } 1358 1359 type leadLagBase struct { 1360 expr sql.Expression 1361 def sql.Expression 1362 offset int 1363 pos int 1364 } 1365 1366 func (a *leadLagBase) WithWindow(w *sql.WindowDefinition) (sql.WindowFunction, error) { 1367 return a, nil 1368 } 1369 1370 func (a *leadLagBase) Dispose() { 1371 return 1372 } 1373 1374 // DefaultFramer returns a NewPartitionFramer 1375 func (a *leadLagBase) DefaultFramer() sql.WindowFramer { 1376 return NewPartitionFramer() 1377 } 1378 1379 func (a *leadLagBase) StartPartition(ctx *sql.Context, interval sql.WindowInterval, buffer sql.WindowBuffer) error { 1380 a.Dispose() 1381 return nil 1382 } 1383 1384 func (a *leadLagBase) NewSlidingFrameInterval(added, dropped sql.WindowInterval) { 1385 panic("implement me") 1386 } 1387 1388 func (a *leadLagBase) Compute(ctx *sql.Context, interval sql.WindowInterval, buffer sql.WindowBuffer) interface{} { 1389 var res interface{} 1390 var err error 1391 idx := a.pos - a.offset 1392 switch { 1393 case interval.Start > interval.End: 1394 case idx >= interval.Start && idx < interval.End: 1395 res, err = a.expr.Eval(ctx, buffer[idx]) 1396 case a.def != nil: 1397 res, err = a.def.Eval(ctx, buffer[a.pos]) 1398 } 1399 if err != nil { 1400 return nil 1401 } 1402 a.pos++ 1403 return res 1404 }