github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/aggregation/common.go (about) 1 // Copyright 2020-2021 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 "fmt" 19 20 "gopkg.in/src-d/go-errors.v1" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 "github.com/dolthub/go-mysql-server/sql/expression" 24 ) 25 26 var ErrEvalUnsupportedOnAggregation = errors.NewKind("Unimplemented %s.Eval(). The code should have used AggregationBuffer.Eval(ctx).") 27 28 // unaryAggBase is the generic embedded class optgen 29 // uses to codegen single expression aggregate functions. 30 type unaryAggBase struct { 31 expression.UnaryExpression 32 window *sql.WindowDefinition 33 functionName string 34 description string 35 typ sql.Type 36 id sql.ColumnId 37 } 38 39 var _ sql.Aggregation = (*unaryAggBase)(nil) 40 var _ sql.CollationCoercible = (*unaryAggBase)(nil) 41 42 func (a *unaryAggBase) NewWindowFunction() (sql.WindowFunction, error) { 43 panic("unaryAggBase is a base type, type must implement NewWindowFunction") 44 } 45 46 func (a *unaryAggBase) NewBuffer() (sql.AggregationBuffer, error) { 47 panic("unaryAggBase is a base type, type must implement NewWindowFunction") 48 } 49 50 // WithWindow returns a new unaryAggBase to be embedded in wrapping type 51 func (a *unaryAggBase) WithWindow(window *sql.WindowDefinition) sql.WindowAdaptableExpression { 52 na := *a 53 na.window = window 54 return &na 55 } 56 57 func (a *unaryAggBase) Window() *sql.WindowDefinition { 58 return a.window 59 } 60 61 func (a *unaryAggBase) String() string { 62 return fmt.Sprintf("%s(%s)", a.functionName, a.Child) 63 } 64 65 func (a *unaryAggBase) Type() sql.Type { 66 return a.typ 67 } 68 69 // Id implements the Aggregation interface 70 func (a *unaryAggBase) Id() sql.ColumnId { 71 return a.id 72 } 73 74 // WithId implements the Aggregation interface 75 func (a *unaryAggBase) WithId(id sql.ColumnId) sql.IdExpression { 76 ret := *a 77 ret.id = id 78 return &ret 79 } 80 81 // CollationCoercibility implements the interface sql.CollationCoercible. 82 func (a *unaryAggBase) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 83 return sql.GetCoercibility(ctx, a.Child) 84 } 85 86 func (a *unaryAggBase) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 87 return nil, ErrEvalUnsupportedOnAggregation.New(a.FunctionName()) 88 } 89 90 func (a *unaryAggBase) Children() []sql.Expression { 91 children := []sql.Expression{a.Child} 92 if a.window != nil { 93 children = append(children, a.window.ToExpressions()...) 94 } 95 return children 96 } 97 98 func (a *unaryAggBase) Resolved() bool { 99 if _, ok := a.Child.(*expression.Star); ok { 100 return true 101 } else if !a.Child.Resolved() { 102 return false 103 } 104 if a.window == nil { 105 return true 106 } 107 return windowResolved(a.window) 108 } 109 110 // WithChildren returns a new unaryAggBase to be embedded in wrapping type 111 func (a *unaryAggBase) WithChildren(children ...sql.Expression) (sql.Expression, error) { 112 if len(children) < 1 { 113 return nil, sql.ErrInvalidChildrenNumber.New(a, len(children), 1) 114 } 115 116 na := *a 117 na.UnaryExpression = expression.UnaryExpression{Child: children[0]} 118 if len(children) > 1 && a.window != nil { 119 w, err := a.window.FromExpressions(children[1:]) 120 if err != nil { 121 return nil, err 122 } 123 return na.WithWindow(w), nil 124 } 125 return &na, nil 126 } 127 128 func (a unaryAggBase) FunctionName() string { 129 return a.functionName 130 } 131 132 func (a unaryAggBase) Description() string { 133 return a.description 134 } 135 136 func windowResolved(w *sql.WindowDefinition) bool { 137 return expression.ExpressionsResolved(append(w.OrderBy.ToExpressions(), w.PartitionBy...)...) 138 }