mirror of
https://github.com/chaisql/chai.git
synced 2025-10-26 17:10:25 +08:00
fn: add objects.fields
This commit is contained in:
@@ -3,9 +3,10 @@ package doc
|
|||||||
type functionDocs map[string]string
|
type functionDocs map[string]string
|
||||||
|
|
||||||
var packageDocs = map[string]functionDocs{
|
var packageDocs = map[string]functionDocs{
|
||||||
"strings": stringsDocs,
|
|
||||||
"math": mathDocs,
|
|
||||||
"": builtinDocs,
|
"": builtinDocs,
|
||||||
|
"math": mathDocs,
|
||||||
|
"strings": stringsDocs,
|
||||||
|
"objects": objectsDocs,
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtinDocs = functionDocs{
|
var builtinDocs = functionDocs{
|
||||||
@@ -39,3 +40,7 @@ var stringsDocs = functionDocs{
|
|||||||
"ltrim": "The ltrim function returns arg1 with leading characters removed. space by default or arg2",
|
"ltrim": "The ltrim function returns arg1 with leading characters removed. space by default or arg2",
|
||||||
"rtrim": "The rtrim function returns arg1 with trailing characters removed. space by default or arg2",
|
"rtrim": "The rtrim function returns arg1 with trailing characters removed. space by default or arg2",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var objectsDocs = functionDocs{
|
||||||
|
"fields": "The fields function returns the top-level fields of arg1 if arg1 evals to object, otherwise it returns null. It returns an array of TEXT.",
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ func DefaultPackages() Packages {
|
|||||||
"": BuiltinDefinitions(),
|
"": BuiltinDefinitions(),
|
||||||
"math": MathFunctions(),
|
"math": MathFunctions(),
|
||||||
"strings": StringsDefinitions(),
|
"strings": StringsDefinitions(),
|
||||||
|
"objects": ObjectsDefinitions(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
73
internal/expr/functions/object.go
Normal file
73
internal/expr/functions/object.go
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
package functions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/chaisql/chai/internal/environment"
|
||||||
|
"github.com/chaisql/chai/internal/expr"
|
||||||
|
"github.com/chaisql/chai/internal/object"
|
||||||
|
"github.com/chaisql/chai/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var objectsFunctions = Definitions{
|
||||||
|
"fields": &definition{
|
||||||
|
name: "fields",
|
||||||
|
arity: 1,
|
||||||
|
constructorFn: func(args ...expr.Expr) (expr.Function, error) {
|
||||||
|
return &ObjectFields{Expr: args[0]}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func ObjectsDefinitions() Definitions {
|
||||||
|
return objectsFunctions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectFields implements the objects.fields function
|
||||||
|
// which returns the list of top-level fields of an object.
|
||||||
|
// If the argument is not an object, it returns null.
|
||||||
|
type ObjectFields struct {
|
||||||
|
Expr expr.Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ObjectFields) Eval(env *environment.Environment) (types.Value, error) {
|
||||||
|
val, err := s.Expr.Eval(env)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if val.Type() != types.ObjectValue {
|
||||||
|
return types.NewNullValue(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
obj := types.As[types.Object](val)
|
||||||
|
var fields []string
|
||||||
|
err = obj.Iterate(func(k string, _ types.Value) error {
|
||||||
|
fields = append(fields, k)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.NewArrayValue(object.NewArrayFromSlice(fields)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ObjectFields) IsEqual(other expr.Expr) bool {
|
||||||
|
if other == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
o, ok := other.(*ObjectFields)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return expr.Equal(s.Expr, o.Expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ObjectFields) Params() []expr.Expr { return []expr.Expr{s.Expr} }
|
||||||
|
|
||||||
|
func (s *ObjectFields) String() string {
|
||||||
|
return fmt.Sprintf("objects.fields(%v)", s.Expr)
|
||||||
|
}
|
||||||
78
internal/sqltests/SELECT/objects/fields.sql
Normal file
78
internal/sqltests/SELECT/objects/fields.sql
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
-- setup:
|
||||||
|
CREATE TABLE test(
|
||||||
|
a TEXT,
|
||||||
|
b INT,
|
||||||
|
c BOOL,
|
||||||
|
d DOUBLE,
|
||||||
|
e ARRAY,
|
||||||
|
f OBJECT
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO test (a, b, c, d, e, f) VALUES (
|
||||||
|
"FOO",
|
||||||
|
42,
|
||||||
|
true,
|
||||||
|
42.42,
|
||||||
|
["A", "b", "C", "d", "E"],
|
||||||
|
{
|
||||||
|
a: "HELLO",
|
||||||
|
b: "WorlD"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
-- test: TEXT value
|
||||||
|
SELECT objects.fields(a) FROM test;
|
||||||
|
/* result:
|
||||||
|
{
|
||||||
|
"objects.fields(a)": NULL
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
-- test: INT value
|
||||||
|
SELECT objects.fields(b) FROM test;
|
||||||
|
/* result:
|
||||||
|
{
|
||||||
|
"objects.fields(b)": NULL
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
-- test: BOOL value
|
||||||
|
SELECT objects.fields(c) FROM test;
|
||||||
|
/* result:
|
||||||
|
{
|
||||||
|
"objects.fields(c)": NULL
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
-- test: DOUBLE value
|
||||||
|
SELECT objects.fields(d) FROM test;
|
||||||
|
/* result:
|
||||||
|
{
|
||||||
|
"objects.fields(d)": NULL
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
-- test: ARRAY value
|
||||||
|
SELECT objects.fields(e) FROM test;
|
||||||
|
/* result:
|
||||||
|
{
|
||||||
|
"objects.fields(e)": NULL
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
-- test: OBJECT value
|
||||||
|
SELECT objects.fields(f) FROM test;
|
||||||
|
/* result:
|
||||||
|
{
|
||||||
|
"objects.fields(f)": ["a", "b"]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
-- test: wildcard
|
||||||
|
SELECT objects.fields(*) FROM test;
|
||||||
|
/* result:
|
||||||
|
{
|
||||||
|
"objects.fields(*)": ["a", "b", "c", "d", "e", "f"]
|
||||||
|
}
|
||||||
|
*/
|
||||||
35
internal/sqltests/expr/objects.sql
Normal file
35
internal/sqltests/expr/objects.sql
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
-- test: objects.fields
|
||||||
|
> objects.fields({})
|
||||||
|
[]
|
||||||
|
|
||||||
|
> objects.fields({a: 1})
|
||||||
|
['a']
|
||||||
|
|
||||||
|
> objects.fields({a: 1, b: {c: 2}})
|
||||||
|
['a', 'b']
|
||||||
|
|
||||||
|
|
||||||
|
> objects.fields(NULL)
|
||||||
|
NULL
|
||||||
|
|
||||||
|
> objects.fields(true)
|
||||||
|
NULL
|
||||||
|
|
||||||
|
> objects.fields(false)
|
||||||
|
NULL
|
||||||
|
|
||||||
|
> objects.fields(1)
|
||||||
|
NULL
|
||||||
|
|
||||||
|
> objects.fields(1.0)
|
||||||
|
NULL
|
||||||
|
|
||||||
|
> objects.fields('hello')
|
||||||
|
NULL
|
||||||
|
|
||||||
|
> objects.fields('\xAA')
|
||||||
|
NULL
|
||||||
|
|
||||||
|
> objects.fields([])
|
||||||
|
NULL
|
||||||
|
|
||||||
Reference in New Issue
Block a user