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  }