Files
2026-07-13 12:32:25 +08:00

134 lines
4.9 KiB
Go

// Copyright 2024 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package framework
import (
"strings"
cerrors "github.com/cockroachdb/errors"
"github.com/dolthub/go-mysql-server/sql"
"github.com/dolthub/go-mysql-server/sql/expression"
)
// AggregateFunction is an expression that represents CompiledAggregateFunction
type AggregateFunction interface {
sql.FunctionExpression
sql.Aggregation
specificFuncImpl()
}
type NewBufferFn func([]sql.Expression) (sql.AggregationBuffer, error)
// CompiledAggregateFunction is an expression that represents a fully-analyzed PostgreSQL aggregate function.
type CompiledAggregateFunction struct {
*CompiledFunction
aggId sql.ColumnId
newBuffer NewBufferFn
}
var _ AggregateFunction = (*CompiledAggregateFunction)(nil)
// NewCompiledAggregateFunction returns a newly compiled function.
// TODO: newBuffer probably needs to be parameterized in the overloads
func NewCompiledAggregateFunction(ctx *sql.Context, name string, args []sql.Expression, functions *Overloads, newBuffer NewBufferFn) *CompiledAggregateFunction {
return newCompiledAggregateFunctionInternal(ctx, name, args, functions, functions.overloadsForParams(len(args)), newBuffer)
}
// newCompiledAggregateFunctionInternal is called internally, which skips steps that may have already been processed.
func newCompiledAggregateFunctionInternal(ctx *sql.Context, name string, args []sql.Expression, overloads *Overloads, fnOverloads []Overload, newBuffer NewBufferFn) *CompiledAggregateFunction {
cf := newCompiledFunctionInternal(ctx, name, args, overloads, fnOverloads, false, nil)
c := &CompiledAggregateFunction{
CompiledFunction: cf,
newBuffer: newBuffer,
}
return c
}
// Eval implements the interface sql.Expression.
func (c *CompiledAggregateFunction) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
return nil, cerrors.New("Eval should not be called on CompiledAggregateFunction")
}
// WithChildren implements the interface sql.Expression.
func (c *CompiledAggregateFunction) WithChildren(ctx *sql.Context, children ...sql.Expression) (sql.Expression, error) {
if len(children) != len(c.Arguments) {
return nil, sql.ErrInvalidChildrenNumber.New(len(children), len(c.Arguments))
}
// We have to re-resolve here, since the change in children may require it (e.g. we have more type info than we did)
return newCompiledAggregateFunctionInternal(ctx, c.Name, children, c.overloads, c.fnOverloads, c.newBuffer), nil
}
// SetStatementRunner implements the interface analyzer.Interpreter.
func (c *CompiledAggregateFunction) SetStatementRunner(ctx *sql.Context, runner sql.StatementRunner) sql.Expression {
nc := *c
nc.runner = runner
return &nc
}
// specificFuncImpl implements the interface sql.Expression.
func (*CompiledAggregateFunction) specificFuncImpl() {}
func (c *CompiledAggregateFunction) DebugString(ctx *sql.Context) string {
sb := strings.Builder{}
sb.WriteString("CompiledAggregateFunction:")
sb.WriteString(c.Name + "(")
for i, param := range c.Arguments {
// Aliases will output the string "x as x", which is an artifact of how we build the AST, so we'll bypass it
if alias, ok := param.(*expression.Alias); ok {
param = alias.Child
}
if i > 0 {
sb.WriteString(", ")
}
sb.WriteString(sql.DebugString(ctx, param))
}
sb.WriteString(")")
return sb.String()
}
// NewBuffer implements the interface sql.Aggregation.
func (c *CompiledAggregateFunction) NewBuffer(ctx *sql.Context) (sql.AggregationBuffer, error) {
return c.newBuffer(c.Arguments)
}
// Id implements the interface sql.Aggregation.
func (c *CompiledAggregateFunction) Id() sql.ColumnId {
return c.aggId
}
// WithId implements the interface sql.Aggregation.
func (c *CompiledAggregateFunction) WithId(id sql.ColumnId) sql.IdExpression {
nc := *c
nc.aggId = id
return &nc
}
// NewWindowFunction implements the interface sql.WindowAdaptableExpression.
func (c *CompiledAggregateFunction) NewWindowFunction(ctx *sql.Context) (sql.WindowFunction, error) {
panic("windows are not implemented yet")
}
// WithWindow implements the interface sql.WindowAdaptableExpression.
func (c *CompiledAggregateFunction) WithWindow(ctx *sql.Context, window *sql.WindowDefinition) sql.WindowAdaptableExpression {
panic("windows are not implemented yet")
}
// Window implements the interface sql.WindowAdaptableExpression.
func (c *CompiledAggregateFunction) Window() *sql.WindowDefinition {
panic("windows are not implemented yet")
}