mirror of
https://github.com/chaisql/chai.git
synced 2025-09-27 03:55:59 +08:00
96 lines
2.9 KiB
Go
96 lines
2.9 KiB
Go
package functions
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/chaisql/chai/internal/environment"
|
|
"github.com/chaisql/chai/internal/expr"
|
|
"github.com/chaisql/chai/internal/types"
|
|
)
|
|
|
|
// A ScalarDefinition is the definition type for functions which operates on scalar values in contrast to other SQL functions
|
|
// such as the SUM aggregator which operates on expressions instead.
|
|
//
|
|
// This difference allows to simply define them with a CallFn function that takes multiple object.Value and
|
|
// return another types.Value, rather than having to manually evaluate expressions (see Definition).
|
|
type ScalarDefinition struct {
|
|
name string
|
|
arity int
|
|
callFn func(...types.Value) (types.Value, error)
|
|
}
|
|
|
|
func NewScalarDefinition(name string, arity int, callFn func(...types.Value) (types.Value, error)) *ScalarDefinition {
|
|
return &ScalarDefinition{name: name, arity: arity, callFn: callFn}
|
|
}
|
|
|
|
// Name returns the defined function named (as an ident, so no parentheses).
|
|
func (fd *ScalarDefinition) Name() string {
|
|
return fd.name
|
|
}
|
|
|
|
// String returns the defined function name and its arguments.
|
|
func (fd *ScalarDefinition) String() string {
|
|
args := make([]string, 0, fd.arity)
|
|
for i := 0; i < fd.arity; i++ {
|
|
args = append(args, fmt.Sprintf("arg%d", i+1))
|
|
}
|
|
return fmt.Sprintf("%s(%s)", fd.name, strings.Join(args, ", "))
|
|
}
|
|
|
|
// Function returns a Function expr node.
|
|
func (fd *ScalarDefinition) Function(args ...expr.Expr) (expr.Function, error) {
|
|
if len(args) != fd.arity {
|
|
return nil, fmt.Errorf("%s takes %d argument(s), not %d", fd.String(), fd.arity, len(args))
|
|
}
|
|
return &ScalarFunction{
|
|
params: args,
|
|
def: fd,
|
|
}, nil
|
|
}
|
|
|
|
// Arity returns the arity of the defined function.
|
|
func (fd *ScalarDefinition) Arity() int {
|
|
return fd.arity
|
|
}
|
|
|
|
// A ScalarFunction is a function which operates on scalar values in contrast to other SQL functions
|
|
// such as the SUM aggregator wich operates on expressions instead.
|
|
type ScalarFunction struct {
|
|
def *ScalarDefinition
|
|
params []expr.Expr
|
|
}
|
|
|
|
// Eval returns a object.Value based on the given environment and the underlying function
|
|
// definition.
|
|
func (sf *ScalarFunction) Eval(env *environment.Environment) (types.Value, error) {
|
|
args, err := sf.evalParams(env)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return sf.def.callFn(args...)
|
|
}
|
|
|
|
// evalParams evaluate all arguments given to the function in the context of the given environmment.
|
|
func (sf *ScalarFunction) evalParams(env *environment.Environment) ([]types.Value, error) {
|
|
values := make([]types.Value, 0, len(sf.params))
|
|
for _, param := range sf.params {
|
|
v, err := param.Eval(env)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
values = append(values, v)
|
|
}
|
|
return values, nil
|
|
}
|
|
|
|
// String returns a string represention of the function expression and its arguments.
|
|
func (sf *ScalarFunction) String() string {
|
|
return fmt.Sprintf("%s(%v)", sf.def.name, sf.params)
|
|
}
|
|
|
|
// Params return the function arguments.
|
|
func (sf *ScalarFunction) Params() []expr.Expr {
|
|
return sf.params
|
|
}
|