feat:函数增加别名

This commit is contained in:
rulego-team
2025-08-07 19:20:14 +08:00
parent a066a4df1b
commit 790e6c615d
4 changed files with 132 additions and 71 deletions
+78 -58
View File
@@ -1,58 +1,78 @@
package functions
import (
"fmt"
)
// BaseFunction provides basic function implementation with common functionality
type BaseFunction struct {
name string
fnType FunctionType
category string
description string
minArgs int
maxArgs int // -1 means unlimited
}
// NewBaseFunction creates a new base function
func NewBaseFunction(name string, fnType FunctionType, category, description string, minArgs, maxArgs int) *BaseFunction {
return &BaseFunction{
name: name,
fnType: fnType,
category: category,
description: description,
minArgs: minArgs,
maxArgs: maxArgs,
}
}
func (bf *BaseFunction) GetName() string {
return bf.name
}
func (bf *BaseFunction) GetType() FunctionType {
return bf.fnType
}
func (bf *BaseFunction) GetCategory() string {
return bf.category
}
func (bf *BaseFunction) GetDescription() string {
return bf.description
}
// ValidateArgCount validates the number of arguments
func (bf *BaseFunction) ValidateArgCount(args []interface{}) error {
argCount := len(args)
if argCount < bf.minArgs {
return fmt.Errorf("function %s requires at least %d arguments, got %d", bf.name, bf.minArgs, argCount)
}
if bf.maxArgs != -1 && argCount > bf.maxArgs {
return fmt.Errorf("function %s accepts at most %d arguments, got %d", bf.name, bf.maxArgs, argCount)
}
return nil
}
package functions
import (
"fmt"
)
// BaseFunction provides basic function implementation with common functionality
type BaseFunction struct {
name string
fnType FunctionType
category string
description string
minArgs int
maxArgs int // -1 means unlimited
aliases []string // function aliases
}
// NewBaseFunction creates a new base function
func NewBaseFunction(name string, fnType FunctionType, category, description string, minArgs, maxArgs int) *BaseFunction {
return &BaseFunction{
name: name,
fnType: fnType,
category: category,
description: description,
minArgs: minArgs,
maxArgs: maxArgs,
aliases: []string{},
}
}
// NewBaseFunctionWithAliases creates base function with aliases
func NewBaseFunctionWithAliases(name string, fnType FunctionType, category, description string, minArgs, maxArgs int, aliases []string) *BaseFunction {
return &BaseFunction{
name: name,
fnType: fnType,
category: category,
description: description,
minArgs: minArgs,
maxArgs: maxArgs,
aliases: aliases,
}
}
func (bf *BaseFunction) GetName() string {
return bf.name
}
func (bf *BaseFunction) GetType() FunctionType {
return bf.fnType
}
func (bf *BaseFunction) GetCategory() string {
return bf.category
}
func (bf *BaseFunction) GetDescription() string {
return bf.description
}
// GetAliases returns function alias list
func (bf *BaseFunction) GetAliases() []string {
return bf.aliases
}
// ValidateArgCount validates the number of arguments
func (bf *BaseFunction) ValidateArgCount(args []interface{}) error {
argCount := len(args)
if argCount < bf.minArgs {
return fmt.Errorf("function %s requires at least %d arguments, got %d", bf.name, bf.minArgs, argCount)
}
if bf.maxArgs != -1 && argCount > bf.maxArgs {
return fmt.Errorf("function %s accepts at most %d arguments, got %d", bf.name, bf.maxArgs, argCount)
}
return nil
}
+7 -6
View File
@@ -2,10 +2,11 @@ package functions
import (
"fmt"
"github.com/rulego/streamsql/utils/cast"
"math"
"math/rand"
"time"
"github.com/rulego/streamsql/utils/cast"
)
// AbsFunction calculates absolute value
@@ -270,7 +271,7 @@ type CeilingFunction struct {
func NewCeilingFunction() *CeilingFunction {
return &CeilingFunction{
BaseFunction: NewBaseFunction("ceiling", TypeMath, "数学函数", "向上取整", 1, 1),
BaseFunction: NewBaseFunctionWithAliases("ceiling", TypeMath, "数学函数", "向上取整", 1, 1, []string{"ceil"}),
}
}
@@ -404,14 +405,14 @@ func (f *LnFunction) Execute(ctx *FunctionContext, args []interface{}) (interfac
return math.Log(val), nil
}
// LogFunction 自然对数函数 (log的别名)
// LogFunction 以10为底的对数函数 (log的别名)
type LogFunction struct {
*BaseFunction
}
func NewLogFunction() *LogFunction {
return &LogFunction{
BaseFunction: NewBaseFunction("log", TypeMath, "数学函数", "计算自然对数", 1, 1),
BaseFunction: NewBaseFunction("log", TypeMath, "数学函数", "计算以10为底的对数", 1, 1),
}
}
@@ -427,7 +428,7 @@ func (f *LogFunction) Execute(ctx *FunctionContext, args []interface{}) (interfa
if val <= 0 {
return nil, fmt.Errorf("log: value must be positive")
}
return math.Log(val), nil
return math.Log10(val), nil
}
// Log10Function 以10为底的对数函数
@@ -695,7 +696,7 @@ type PowerFunction struct {
func NewPowerFunction() *PowerFunction {
return &PowerFunction{
BaseFunction: NewBaseFunction("power", TypeMath, "数学函数", "计算x的y次幂", 2, 2),
BaseFunction: NewBaseFunctionWithAliases("power", TypeMath, "数学函数", "计算x的y次幂", 2, 2, []string{"pow"}),
}
}
+24 -5
View File
@@ -2,6 +2,7 @@ package functions
import (
"fmt"
"reflect"
"regexp"
"strings"
@@ -42,7 +43,7 @@ type LengthFunction struct {
func NewLengthFunction() *LengthFunction {
return &LengthFunction{
BaseFunction: NewBaseFunction("length", TypeString, "string", "Get string length", 1, 1),
BaseFunction: NewBaseFunctionWithAliases("length", TypeString, "string", "Get length of string or array", 1, 1, []string{"len"}),
}
}
@@ -50,12 +51,30 @@ func (f *LengthFunction) Validate(args []interface{}) error {
return f.ValidateArgCount(args)
}
// Execute calculates the length of a string or array.
// Supports strings, arrays, slices, etc., using Go's standard len() function.
func (f *LengthFunction) Execute(ctx *FunctionContext, args []interface{}) (interface{}, error) {
str, err := cast.ToStringE(args[0])
if err != nil {
return nil, err
arg := args[0]
v := reflect.ValueOf(arg)
var length int
switch v.Kind() {
case reflect.String:
length = len(v.String())
case reflect.Array, reflect.Slice:
length = v.Len()
case reflect.Map:
length = v.Len()
case reflect.Chan:
length = v.Len()
default:
str, err := cast.ToStringE(arg)
if err != nil {
return nil, fmt.Errorf("unsupported type for len function: %T", arg)
}
length = len(str)
}
return int64(len(str)), nil
return length, nil
}
// UpperFunction converts string to uppercase
+23 -2
View File
@@ -53,6 +53,8 @@ type Function interface {
GetType() FunctionType
// GetCategory returns the function category
GetCategory() string
// GetAliases returns the function aliases
GetAliases() []string
// Validate validates the arguments
Validate(args []interface{}) error
// Execute executes the function
@@ -80,6 +82,7 @@ func NewFunctionRegistry() *FunctionRegistry {
}
// Register registers a function
// 注册函数及其别名到注册表中
func (r *FunctionRegistry) Register(fn Function) error {
r.mu.Lock()
defer r.mu.Unlock()
@@ -91,7 +94,18 @@ func (r *FunctionRegistry) Register(fn Function) error {
return fmt.Errorf("function %s already registered", name)
}
// 注册主函数名
r.functions[name] = fn
// 注册所有别名
for _, alias := range fn.GetAliases() {
alias = strings.ToLower(alias)
if _, exists := r.functions[alias]; exists {
return fmt.Errorf("function alias %s already registered", alias)
}
r.functions[alias] = fn
}
r.categories[fn.GetType()] = append(r.categories[fn.GetType()], fn)
// Register aggregator adapter
if fn.GetType() == TypeAggregation {
@@ -132,6 +146,7 @@ func (r *FunctionRegistry) ListAll() map[string]Function {
}
// Unregister removes a function
// 从注册表中移除函数及其所有别名
func (r *FunctionRegistry) Unregister(name string) bool {
r.mu.Lock()
defer r.mu.Unlock()
@@ -142,13 +157,19 @@ func (r *FunctionRegistry) Unregister(name string) bool {
return false
}
delete(r.functions, name)
// 删除主函数名
delete(r.functions, strings.ToLower(fn.GetName()))
// 删除所有别名
for _, alias := range fn.GetAliases() {
delete(r.functions, strings.ToLower(alias))
}
// Remove from categories
fnType := fn.GetType()
if funcs, ok := r.categories[fnType]; ok {
for i, f := range funcs {
if strings.ToLower(f.GetName()) == name {
if strings.ToLower(f.GetName()) == strings.ToLower(fn.GetName()) {
r.categories[fnType] = append(funcs[:i], funcs[i+1:]...)
break
}