From 2def92d41f65857009c641ef993e0addf3b61153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toma=C5=BE=20Jerman?= Date: Fri, 1 Oct 2021 12:39:20 +0200 Subject: [PATCH] Tweak expr record value selection and bool casting * properly handle casting of false values (empty string) * add support for record.values.xyz expressions where values is not set --- automation/service/workflow.go | 2 +- compose/automation/expr_types.go | 16 +++++++++------- compose/types/record_value.go | 3 ++- pkg/expr/func_generic.go | 10 ++++++++++ 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/automation/service/workflow.go b/automation/service/workflow.go index 772df7111..7d09e2b90 100644 --- a/automation/service/workflow.go +++ b/automation/service/workflow.go @@ -84,7 +84,7 @@ const ( func Workflow(log *zap.Logger, corredorOpt options.CorredorOpt, opt options.WorkflowOpt) *workflow { return &workflow{ log: log, - opt: opt, + opt: opt, actionlog: DefaultActionlog, store: DefaultStore, ac: DefaultAccessControl, diff --git a/compose/automation/expr_types.go b/compose/automation/expr_types.go index 7312a84ec..026294f26 100644 --- a/compose/automation/expr_types.go +++ b/compose/automation/expr_types.go @@ -75,9 +75,6 @@ func CastToComposeRecord(val interface{}) (out *types.Record, err error) { val = &types.Record{} } - if val.Values == nil { - val.Values = types.RecordValueSet{} - } return val, nil case map[string]interface{}: out = &types.Record{} @@ -127,10 +124,6 @@ func (t *ComposeRecord) SelectGVal(_ context.Context, k string) (interface{}, er t.value.Values = types.RecordValueSet{} } - if t.value.Values.Len() == 0 { - return nil, nil - } - return &ComposeRecordValues{t.value}, nil } @@ -254,6 +247,15 @@ func (t *ComposeRecordValues) SelectGVal(_ context.Context, k string) (interface return composeRecordValuesGValSelector(t.value, k) } +// IsEmpty implements pkg/expr.empty requirements to be able to determine if +// the value is empty. +// +// This is needed cor cases when we are working with empty records, but are trying +// to access their values. +func (t *ComposeRecordValues) IsEmpty() bool { + return t == nil || t.value == nil || len(t.value.Values) == 0 +} + // Select is field accessor for *types.Record // // Similar to SelectGVal but returns typed values diff --git a/compose/types/record_value.go b/compose/types/record_value.go index 35b56aece..e03e0f62f 100644 --- a/compose/types/record_value.go +++ b/compose/types/record_value.go @@ -7,6 +7,7 @@ import ( "strconv" "time" + "github.com/cortezaproject/corteza-server/pkg/expr" "github.com/cortezaproject/corteza-server/pkg/filter" "github.com/pkg/errors" "github.com/spf13/cast" @@ -73,7 +74,7 @@ func (v RecordValue) Cast(f *ModuleField) (interface{}, error) { return cast.ToTimeE(v.Value) case f.IsBoolean(): - return cast.ToBoolE(v.Value) + return expr.CastToBoolean(v.Value) case f.IsNumeric(): if f.Options.Precision() == 0 { diff --git a/pkg/expr/func_generic.go b/pkg/expr/func_generic.go index 280cdc341..dd963994b 100644 --- a/pkg/expr/func_generic.go +++ b/pkg/expr/func_generic.go @@ -7,6 +7,12 @@ import ( "github.com/PaesslerAG/gval" ) +type ( + empty interface { + IsEmpty() bool + } +) + func GenericFunctions() []gval.Language { return []gval.Language{ gval.Function("coalesce", coalesce), @@ -57,6 +63,10 @@ func isEmpty(i interface{}) bool { return true } + if c, ok := i.(empty); ok { + return c.IsEmpty() + } + switch reflect.TypeOf(i).Kind() { case reflect.Slice, reflect.Array, reflect.Map: return reflect.ValueOf(i).Len() == 0