github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/aggregation/unary_agg_buffers.go (about) 1 package aggregation 2 3 import ( 4 "fmt" 5 "reflect" 6 7 "github.com/cespare/xxhash/v2" 8 "github.com/shopspring/decimal" 9 10 "github.com/dolthub/go-mysql-server/sql" 11 "github.com/dolthub/go-mysql-server/sql/expression" 12 "github.com/dolthub/go-mysql-server/sql/types" 13 ) 14 15 type anyValueBuffer struct { 16 res interface{} 17 expr sql.Expression 18 } 19 20 func NewAnyValueBuffer(child sql.Expression) *anyValueBuffer { 21 return &anyValueBuffer{nil, child} 22 } 23 24 // Update implements the AggregationBuffer interface. 25 func (a *anyValueBuffer) Update(ctx *sql.Context, row sql.Row) error { 26 if a.res != nil { 27 return nil 28 } 29 30 v, err := a.expr.Eval(ctx, row) 31 if err != nil { 32 return err 33 } 34 if v == nil { 35 return nil 36 } 37 38 a.res = v 39 40 return nil 41 } 42 43 // Eval implements the AggregationBuffer interface. 44 func (a *anyValueBuffer) Eval(ctx *sql.Context) (interface{}, error) { 45 return a.res, nil 46 } 47 48 // Dispose implements the Disposable interface. 49 func (a *anyValueBuffer) Dispose() { 50 expression.Dispose(a.expr) 51 } 52 53 type sumBuffer struct { 54 isnil bool 55 sum interface{} // sum is either decimal.Decimal or float64 56 expr sql.Expression 57 } 58 59 func NewSumBuffer(child sql.Expression) *sumBuffer { 60 return &sumBuffer{true, float64(0), child} 61 } 62 63 // Update implements the AggregationBuffer interface. 64 func (m *sumBuffer) Update(ctx *sql.Context, row sql.Row) error { 65 v, err := m.expr.Eval(ctx, row) 66 if err != nil { 67 return err 68 } 69 70 if v == nil { 71 return nil 72 } 73 74 m.PerformSum(v) 75 76 return nil 77 } 78 79 func (m *sumBuffer) PerformSum(v interface{}) { 80 // decimal.Decimal values are evaluated to string value even though the Literal expr type is Decimal type, 81 // so convert it to appropriate Decimal type 82 if s, isStr := v.(string); isStr && types.IsDecimal(m.expr.Type()) { 83 val, _, err := m.expr.Type().Convert(s) 84 if err == nil { 85 v = val 86 } 87 } 88 89 switch n := v.(type) { 90 case decimal.Decimal: 91 if m.isnil { 92 m.sum = decimal.NewFromInt(0) 93 m.isnil = false 94 } 95 if sum, ok := m.sum.(decimal.Decimal); ok { 96 m.sum = sum.Add(n) 97 } else { 98 m.sum = decimal.NewFromFloat(m.sum.(float64)).Add(n) 99 } 100 default: 101 val, _, err := types.Float64.Convert(n) 102 if err != nil { 103 val = float64(0) 104 } 105 if m.isnil { 106 m.sum = float64(0) 107 m.isnil = false 108 } 109 sum, _, err := types.Float64.Convert(m.sum) 110 if err != nil { 111 sum = float64(0) 112 } 113 m.sum = sum.(float64) + val.(float64) 114 } 115 } 116 117 // Eval implements the AggregationBuffer interface. 118 func (m *sumBuffer) Eval(ctx *sql.Context) (interface{}, error) { 119 if m.isnil { 120 return nil, nil 121 } 122 return m.sum, nil 123 } 124 125 // Dispose implements the Disposable interface. 126 func (m *sumBuffer) Dispose() { 127 expression.Dispose(m.expr) 128 } 129 130 type lastBuffer struct { 131 val interface{} 132 expr sql.Expression 133 } 134 135 func NewLastBuffer(child sql.Expression) *lastBuffer { 136 const ( 137 sum = float64(0) 138 rows = int64(0) 139 ) 140 141 return &lastBuffer{nil, child} 142 } 143 144 // Update implements the AggregationBuffer interface. 145 func (l *lastBuffer) Update(ctx *sql.Context, row sql.Row) error { 146 v, err := l.expr.Eval(ctx, row) 147 if err != nil { 148 return err 149 } 150 151 if v == nil { 152 return nil 153 } 154 155 l.val = v 156 157 return nil 158 } 159 160 // Eval implements the AggregationBuffer interface. 161 func (l *lastBuffer) Eval(ctx *sql.Context) (interface{}, error) { 162 return l.val, nil 163 } 164 165 // Dispose implements the Disposable interface. 166 func (l *lastBuffer) Dispose() { 167 expression.Dispose(l.expr) 168 } 169 170 type avgBuffer struct { 171 sum *sumBuffer // sum is either decimal.Decimal or float64 172 rows int64 173 expr sql.Expression 174 } 175 176 func NewAvgBuffer(child sql.Expression) *avgBuffer { 177 const ( 178 rows = int64(0) 179 ) 180 181 return &avgBuffer{NewSumBuffer(child), rows, child} 182 } 183 184 // Update implements the AggregationBuffer interface. 185 func (a *avgBuffer) Update(ctx *sql.Context, row sql.Row) error { 186 v, err := a.expr.Eval(ctx, row) 187 if err != nil { 188 return err 189 } 190 191 if v == nil { 192 return nil 193 } 194 195 a.sum.PerformSum(v) 196 a.rows += 1 197 198 return nil 199 } 200 201 // Eval implements the AggregationBuffer interface. 202 func (a *avgBuffer) Eval(ctx *sql.Context) (interface{}, error) { 203 sum, err := a.sum.Eval(ctx) 204 if err != nil { 205 return nil, err 206 } 207 // This case is triggered when no rows exist. 208 switch s := sum.(type) { 209 case float64: 210 if s == 0 && a.rows == 0 { 211 return nil, nil 212 } 213 214 if a.rows == 0 { 215 return float64(0), nil 216 } 217 218 return s / float64(a.rows), nil 219 case decimal.Decimal: 220 if s.IsZero() && a.rows == 0 { 221 return nil, nil 222 } 223 if a.rows == 0 { 224 return decimal.NewFromInt(0), nil 225 } 226 scale := (s.Exponent() * -1) + 4 227 return s.DivRound(decimal.NewFromInt(a.rows), scale), nil 228 } 229 return nil, nil 230 } 231 232 // Dispose implements the Disposable interface. 233 func (a *avgBuffer) Dispose() { 234 expression.Dispose(a.expr) 235 } 236 237 type bitAndBuffer struct { 238 res uint64 239 rows uint64 240 expr sql.Expression 241 } 242 243 func NewBitAndBuffer(child sql.Expression) *bitAndBuffer { 244 const ( 245 res = ^uint64(0) // bitwise not xor, so 0xffff... 246 rows = uint64(0) 247 ) 248 249 return &bitAndBuffer{res, rows, child} 250 } 251 252 // Update implements the AggregationBuffer interface. 253 func (b *bitAndBuffer) Update(ctx *sql.Context, row sql.Row) error { 254 v, err := b.expr.Eval(ctx, row) 255 if err != nil { 256 return err 257 } 258 259 if v == nil { 260 return nil 261 } 262 263 v, _, err = types.Uint64.Convert(v) 264 if err != nil { 265 v = uint64(0) 266 } 267 268 b.res &= v.(uint64) 269 b.rows += 1 270 271 return nil 272 } 273 274 // Eval implements the AggregationBuffer interface. 275 func (b *bitAndBuffer) Eval(ctx *sql.Context) (interface{}, error) { 276 return b.res, nil 277 } 278 279 // Dispose implements the Disposable interface. 280 func (b *bitAndBuffer) Dispose() { 281 expression.Dispose(b.expr) 282 } 283 284 type bitOrBuffer struct { 285 res uint64 286 rows uint64 287 expr sql.Expression 288 } 289 290 func NewBitOrBuffer(child sql.Expression) *bitOrBuffer { 291 const ( 292 res = uint64(0) 293 rows = uint64(0) 294 ) 295 296 return &bitOrBuffer{res, rows, child} 297 } 298 299 // Update implements the AggregationBuffer interface. 300 func (b *bitOrBuffer) Update(ctx *sql.Context, row sql.Row) error { 301 v, err := b.expr.Eval(ctx, row) 302 if err != nil { 303 return err 304 } 305 306 if v == nil { 307 return nil 308 } 309 310 v, _, err = types.Uint64.Convert(v) 311 if err != nil { 312 v = uint64(0) 313 } 314 315 b.res |= v.(uint64) 316 b.rows += 1 317 318 return nil 319 } 320 321 // Eval implements the AggregationBuffer interface. 322 func (b *bitOrBuffer) Eval(ctx *sql.Context) (interface{}, error) { 323 return b.res, nil 324 } 325 326 // Dispose implements the Disposable interface. 327 func (b *bitOrBuffer) Dispose() { 328 expression.Dispose(b.expr) 329 } 330 331 type bitXorBuffer struct { 332 res uint64 333 rows uint64 334 expr sql.Expression 335 } 336 337 func NewBitXorBuffer(child sql.Expression) *bitXorBuffer { 338 const ( 339 res = uint64(0) 340 rows = uint64(0) 341 ) 342 343 return &bitXorBuffer{res, rows, child} 344 } 345 346 // Update implements the AggregationBuffer interface. 347 func (b *bitXorBuffer) Update(ctx *sql.Context, row sql.Row) error { 348 v, err := b.expr.Eval(ctx, row) 349 if err != nil { 350 return err 351 } 352 353 if v == nil { 354 return nil 355 } 356 357 v, _, err = types.Uint64.Convert(v) 358 if err != nil { 359 v = uint64(0) 360 } 361 362 b.res ^= v.(uint64) 363 b.rows += 1 364 365 return nil 366 } 367 368 // Eval implements the AggregationBuffer interface. 369 func (b *bitXorBuffer) Eval(ctx *sql.Context) (interface{}, error) { 370 // This case is triggered when no rows exist. 371 if b.res == 0 && b.rows == 0 { 372 return uint64(0), nil 373 } 374 375 if b.rows == 0 { 376 return uint64(0), nil 377 } 378 379 return b.res, nil 380 } 381 382 // Dispose implements the Disposable interface. 383 func (b *bitXorBuffer) Dispose() { 384 expression.Dispose(b.expr) 385 } 386 387 type countDistinctBuffer struct { 388 seen map[uint64]struct{} 389 exprs []sql.Expression 390 } 391 392 func NewCountDistinctBuffer(children []sql.Expression) *countDistinctBuffer { 393 return &countDistinctBuffer{make(map[uint64]struct{}), children} 394 } 395 396 // Update implements the AggregationBuffer interface. 397 func (c *countDistinctBuffer) Update(ctx *sql.Context, row sql.Row) error { 398 var value interface{} 399 if len(c.exprs) == 0 { 400 return fmt.Errorf("no expressions") 401 } 402 if _, ok := c.exprs[0].(*expression.Star); ok { 403 value = row 404 } else { 405 val := make(sql.Row, len(c.exprs)) 406 for i, expr := range c.exprs { 407 v, err := expr.Eval(ctx, row) 408 if err != nil { 409 return err 410 } 411 // skip nil values 412 if v == nil { 413 return nil 414 } 415 val[i] = v 416 } 417 value = val 418 } 419 420 var str string 421 for _, val := range value.(sql.Row) { 422 // skip nil values 423 if val == nil { 424 return nil 425 } 426 v, _, err := types.Text.Convert(val) 427 if err != nil { 428 return err 429 } 430 vv, ok := v.(string) 431 if !ok { 432 return fmt.Errorf("count distinct unable to hash value: %s", err) 433 } 434 str += vv + "," 435 } 436 437 hash := xxhash.New() 438 _, err := hash.WriteString(str) 439 if err != nil { 440 return err 441 } 442 h := hash.Sum64() 443 c.seen[h] = struct{}{} 444 445 return nil 446 } 447 448 // Eval implements the AggregationBuffer interface. 449 func (c *countDistinctBuffer) Eval(ctx *sql.Context) (interface{}, error) { 450 return int64(len(c.seen)), nil 451 } 452 453 func (c *countDistinctBuffer) Dispose() { 454 for _, e := range c.exprs { 455 expression.Dispose(e) 456 } 457 } 458 459 type countBuffer struct { 460 cnt int64 461 expr sql.Expression 462 } 463 464 func NewCountBuffer(child sql.Expression) *countBuffer { 465 return &countBuffer{0, child} 466 } 467 468 // Update implements the AggregationBuffer interface. 469 func (c *countBuffer) Update(ctx *sql.Context, row sql.Row) error { 470 var inc bool 471 if _, ok := c.expr.(*expression.Star); ok { 472 inc = true 473 } else { 474 v, err := c.expr.Eval(ctx, row) 475 if v != nil { 476 inc = true 477 } 478 479 if err != nil { 480 return err 481 } 482 } 483 484 if inc { 485 c.cnt += 1 486 } 487 488 return nil 489 } 490 491 // Eval implements the AggregationBuffer interface. 492 func (c *countBuffer) Eval(ctx *sql.Context) (interface{}, error) { 493 return c.cnt, nil 494 } 495 496 // Dispose implements the Disposable interface. 497 func (c *countBuffer) Dispose() { 498 expression.Dispose(c.expr) 499 } 500 501 type firstBuffer struct { 502 val interface{} 503 expr sql.Expression 504 } 505 506 func NewFirstBuffer(child sql.Expression) *firstBuffer { 507 return &firstBuffer{nil, child} 508 } 509 510 // Update implements the AggregationBuffer interface. 511 func (f *firstBuffer) Update(ctx *sql.Context, row sql.Row) error { 512 if f.val != nil { 513 return nil 514 } 515 516 v, err := f.expr.Eval(ctx, row) 517 if err != nil { 518 return err 519 } 520 521 if v == nil { 522 return nil 523 } 524 525 f.val = v 526 527 return nil 528 } 529 530 // Eval implements the AggregationBuffer interface. 531 func (f *firstBuffer) Eval(ctx *sql.Context) (interface{}, error) { 532 return f.val, nil 533 } 534 535 // Dispose implements the Disposable interface. 536 func (f *firstBuffer) Dispose() { 537 expression.Dispose(f.expr) 538 } 539 540 type maxBuffer struct { 541 val interface{} 542 expr sql.Expression 543 } 544 545 func NewMaxBuffer(child sql.Expression) *maxBuffer { 546 return &maxBuffer{nil, child} 547 } 548 549 // Update implements the AggregationBuffer interface. 550 func (m *maxBuffer) Update(ctx *sql.Context, row sql.Row) error { 551 v, err := m.expr.Eval(ctx, row) 552 if err != nil { 553 return err 554 } 555 556 if reflect.TypeOf(v) == nil { 557 return nil 558 } 559 560 if m.val == nil { 561 m.val = v 562 return nil 563 } 564 565 cmp, err := m.expr.Type().Compare(v, m.val) 566 if err != nil { 567 return err 568 } 569 if cmp == 1 { 570 m.val = v 571 } 572 573 return nil 574 } 575 576 // Eval implements the AggregationBuffer interface. 577 func (m *maxBuffer) Eval(ctx *sql.Context) (interface{}, error) { 578 return m.val, nil 579 } 580 581 // Dispose implements the Disposable interface. 582 func (m *maxBuffer) Dispose() { 583 expression.Dispose(m.expr) 584 } 585 586 type minBuffer struct { 587 val interface{} 588 expr sql.Expression 589 } 590 591 func NewMinBuffer(child sql.Expression) *minBuffer { 592 return &minBuffer{nil, child} 593 } 594 595 // Update implements the AggregationBuffer interface. 596 func (m *minBuffer) Update(ctx *sql.Context, row sql.Row) error { 597 v, err := m.expr.Eval(ctx, row) 598 if err != nil { 599 return err 600 } 601 602 if reflect.TypeOf(v) == nil { 603 return nil 604 } 605 606 if m.val == nil { 607 m.val = v 608 return nil 609 } 610 611 cmp, err := m.expr.Type().Compare(v, m.val) 612 if err != nil { 613 return err 614 } 615 if cmp == -1 { 616 m.val = v 617 } 618 619 return nil 620 } 621 622 // Eval implements the AggregationBuffer interface. 623 func (m *minBuffer) Eval(ctx *sql.Context) (interface{}, error) { 624 return m.val, nil 625 } 626 627 // Dispose implements the Disposable interface. 628 func (m *minBuffer) Dispose() { 629 expression.Dispose(m.expr) 630 } 631 632 type jsonArrayBuffer struct { 633 vals []interface{} 634 expr sql.Expression 635 } 636 637 func NewJsonArrayBuffer(child sql.Expression) *jsonArrayBuffer { 638 return &jsonArrayBuffer{nil, child} 639 } 640 641 // Update implements the AggregationBuffer interface. 642 func (j *jsonArrayBuffer) Update(ctx *sql.Context, row sql.Row) error { 643 v, err := j.expr.Eval(ctx, row) 644 if err != nil { 645 return err 646 } 647 648 // unwrap JSON values 649 if js, ok := v.(sql.JSONWrapper); ok { 650 v = js.ToInterface() 651 } 652 653 j.vals = append(j.vals, v) 654 655 return nil 656 } 657 658 // Eval implements the AggregationBuffer interface. 659 func (j *jsonArrayBuffer) Eval(ctx *sql.Context) (interface{}, error) { 660 return types.JSONDocument{Val: j.vals}, nil 661 } 662 663 // Dispose implements the Disposable interface. 664 func (j *jsonArrayBuffer) Dispose() { 665 }