mirror of
https://gitee.com/rulego/streamsql.git
synced 2026-04-10 14:27:10 +00:00
feat:函数增加别名
This commit is contained in:
+78
-58
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user