Files
streamsql/functions/functions_multirow.go
T
2025-06-11 18:45:39 +08:00

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
}