github.com/dolthub/go-mysql-server@v0.18.0/sql/aggregates.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 sql
    16  
    17  import "fmt"
    18  
    19  // Aggregation implements an aggregation expression, where an
    20  // aggregation buffer is created for each grouping (NewBuffer). Rows for the
    21  // grouping should be fed to the buffer with |Update| and the buffer should be
    22  // eval'd with |Eval|. Calling |Eval| directly on an Aggregation expression is
    23  // typically an error.
    24  type Aggregation interface {
    25  	WindowAdaptableExpression
    26  	// NewBuffer creates a new aggregation buffer and returns it as a Row.
    27  	NewBuffer() (AggregationBuffer, error)
    28  }
    29  
    30  // WindowBuffer is a type alias for a window materialization
    31  type WindowBuffer []Row
    32  
    33  // WindowInterval is a WindowBuffer index range, where [Start] is inclusive, and [End] is exclusive
    34  type WindowInterval struct {
    35  	Start, End int
    36  }
    37  
    38  // WindowFunction performs aggregations on buffer intervals, optionally maintaining internal state
    39  // for performance optimizations
    40  type WindowFunction interface {
    41  	Disposable
    42  
    43  	// StartPartition discards any previous state and initializes the aggregation for a new partition
    44  	StartPartition(*Context, WindowInterval, WindowBuffer) error
    45  	// DefaultFramer returns a new instance of the default WindowFramer for a particular aggregation
    46  	DefaultFramer() WindowFramer
    47  	// NewSlidingFrameInterval is updates the function's internal aggregation state for the next
    48  	// Compute call using three WindowInterval: added, dropped, and current.
    49  	// TODO: implement sliding window interface in aggregation functions and windowBlockIter
    50  	// NewSlidingFrameInterval(added, dropped WindowInterval)
    51  	// Compute returns an aggregation result for a given interval and buffer
    52  	Compute(*Context, WindowInterval, WindowBuffer) interface{}
    53  }
    54  
    55  // WindowAdaptableExpression is an Expression that can be executed as a window aggregation
    56  type WindowAdaptableExpression interface {
    57  	Expression
    58  	IdExpression
    59  
    60  	// NewEvalable constructs an executable aggregation WindowFunction
    61  	NewWindowFunction() (WindowFunction, error)
    62  	// WithWindow returns a version of this aggregation with the WindowDefinition given
    63  	WithWindow(window *WindowDefinition) WindowAdaptableExpression
    64  	// Window returns this expression's window
    65  	Window() *WindowDefinition
    66  }
    67  
    68  type IdExpression interface {
    69  	Expression
    70  	Id() ColumnId
    71  	WithId(ColumnId) IdExpression
    72  }
    73  
    74  // WindowFramer is responsible for tracking window frame indices for partition rows.
    75  // WindowFramer is aware of the framing strategy (offsets, ranges, etc),
    76  // and is responsible for returning a WindowInterval for each partition row.
    77  type WindowFramer interface {
    78  	// NewFramer is a prototype constructor that create a new Framer with pass-through
    79  	// parent arguments
    80  	NewFramer(WindowInterval) (WindowFramer, error)
    81  	// Next returns the next WindowInterval frame, or an io.EOF error after the last row
    82  	Next(*Context, WindowBuffer) (WindowInterval, error)
    83  	// FirstIdx returns the current frame start index
    84  	FirstIdx() int
    85  	// LastIdx returns the last valid index in the current frame
    86  	LastIdx() int
    87  	// Interval returns the current frame as a WindowInterval
    88  	Interval() (WindowInterval, error)
    89  	// SlidingInterval returns three WindowIntervals: the current frame, dropped range since the
    90  	// last frame, and added range since the last frame.
    91  	// TODO: implement sliding window interface in framers, windowBlockIter, and aggregation functions
    92  	// SlidingInterval(ctx Context) (WindowInterval, WindowInterval, WindowInterval)
    93  }
    94  
    95  // WindowFrame describe input bounds for an aggregation function
    96  // execution. A frame will only have two non-null fields for the start
    97  // and end bounds. A WindowFrame plan node is associated
    98  // with an exec WindowFramer.
    99  type WindowFrame interface {
   100  	fmt.Stringer
   101  
   102  	// NewFramer constructs an executable WindowFramer
   103  	NewFramer(*WindowDefinition) (WindowFramer, error)
   104  	// UnboundedFollowing returns whether a frame end is unbounded
   105  	UnboundedFollowing() bool
   106  	// UnboundedPreceding returns whether a frame start is unbounded
   107  	UnboundedPreceding() bool
   108  	// StartCurrentRow returns whether a frame start is CURRENT ROW
   109  	StartCurrentRow() bool
   110  	// EndCurrentRow returns whether a frame end is CURRENT ROW
   111  	EndCurrentRow() bool
   112  	// StartNFollowing returns a frame's start preceding Expression or nil
   113  	StartNPreceding() Expression
   114  	// StartNFollowing returns a frame's start following Expression or nil
   115  	StartNFollowing() Expression
   116  	// EndNPreceding returns whether a frame end preceding Expression or nil
   117  	EndNPreceding() Expression
   118  	// EndNPreceding returns whether a frame end following Expression or nil
   119  	EndNFollowing() Expression
   120  }
   121  
   122  type AggregationBuffer interface {
   123  	Disposable
   124  
   125  	// Eval the given buffer.
   126  	Eval(*Context) (interface{}, error)
   127  	// Update the given buffer with the given row.
   128  	Update(ctx *Context, row Row) error
   129  }
   130  
   131  // WindowAggregation implements a window aggregation expression. A WindowAggregation is similar to an Aggregation,
   132  // except that it returns a result row for every input row, as opposed to as single for the entire result set. A
   133  // WindowAggregation is expected to track its input rows in the order received, and to return the value for the row
   134  // index given on demand.
   135  type WindowAggregation interface {
   136  	WindowAdaptableExpression
   137  }