mirror of
https://gitee.com/rulego/streamsql.git
synced 2026-04-08 05:22:51 +00:00
109 lines
2.6 KiB
Go
109 lines
2.6 KiB
Go
package functions
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
// UnnestFunction 将数组展开为多行
|
|
type UnnestFunction struct {
|
|
*BaseFunction
|
|
}
|
|
|
|
func NewUnnestFunction() *UnnestFunction {
|
|
return &UnnestFunction{
|
|
BaseFunction: NewBaseFunction("unnest", TypeString, "多行函数", "将数组展开为多行", 1, 1),
|
|
}
|
|
}
|
|
|
|
func (f *UnnestFunction) Validate(args []interface{}) error {
|
|
return f.ValidateArgCount(args)
|
|
}
|
|
|
|
func (f *UnnestFunction) Execute(ctx *FunctionContext, args []interface{}) (interface{}, error) {
|
|
if err := f.Validate(args); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
array := args[0]
|
|
if array == nil {
|
|
return []interface{}{}, nil
|
|
}
|
|
|
|
// 使用反射检查是否为数组或切片
|
|
v := reflect.ValueOf(array)
|
|
if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
|
|
return nil, fmt.Errorf("unnest requires an array or slice, got %T", array)
|
|
}
|
|
|
|
// 转换为 []interface{}
|
|
result := make([]interface{}, v.Len())
|
|
for i := 0; i < v.Len(); i++ {
|
|
elem := v.Index(i).Interface()
|
|
|
|
// 如果数组元素是对象(map),则展开为列
|
|
if elemMap, ok := elem.(map[string]interface{}); ok {
|
|
// 对于对象,我们返回一个特殊的结构来表示需要展开为列
|
|
result[i] = map[string]interface{}{
|
|
"__unnest_object__": true,
|
|
"__data__": elemMap,
|
|
}
|
|
} else {
|
|
result[i] = elem
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// UnnestResult 表示 unnest 函数的结果
|
|
type UnnestResult struct {
|
|
Rows []map[string]interface{}
|
|
}
|
|
|
|
// IsUnnestResult 检查是否为 unnest 结果
|
|
func IsUnnestResult(value interface{}) bool {
|
|
if slice, ok := value.([]interface{}); ok {
|
|
for _, item := range slice {
|
|
if itemMap, ok := item.(map[string]interface{}); ok {
|
|
if unnest, exists := itemMap["__unnest_object__"]; exists {
|
|
if unnestBool, ok := unnest.(bool); ok && unnestBool {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// ProcessUnnestResult 处理 unnest 结果,将其转换为多行
|
|
func ProcessUnnestResult(value interface{}) []map[string]interface{} {
|
|
slice, ok := value.([]interface{})
|
|
if !ok {
|
|
return nil
|
|
}
|
|
|
|
var rows []map[string]interface{}
|
|
for _, item := range slice {
|
|
if itemMap, ok := item.(map[string]interface{}); ok {
|
|
if unnest, exists := itemMap["__unnest_object__"]; exists {
|
|
if unnestBool, ok := unnest.(bool); ok && unnestBool {
|
|
if data, exists := itemMap["__data__"]; exists {
|
|
if dataMap, ok := data.(map[string]interface{}); ok {
|
|
rows = append(rows, dataMap)
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
// 对于非对象元素,创建一个包含单个值的行
|
|
row := map[string]interface{}{
|
|
"value": item,
|
|
}
|
|
rows = append(rows, row)
|
|
}
|
|
|
|
return rows
|
|
} |