Null values on datetime fields

This commit is contained in:
Peter Grlica
2024-06-12 12:38:06 +02:00
parent 813bd67359
commit fd7b018456
8 changed files with 266 additions and 14 deletions
+19 -3
View File
@@ -503,11 +503,14 @@ func CastToDuration(val interface{}) (out time.Duration, err error) {
func CastToDateTime(val interface{}) (out *time.Time, err error) {
val = UntypedValue(val)
switch casted := val.(type) {
case *time.Time:
return casted, nil
case time.Time:
return &casted, nil
case nil:
return nil, nil
default:
var c time.Time
if c, err = cast.ToTimeE(casted); err != nil {
@@ -959,6 +962,10 @@ func (v *Any) Clone() (out TypedValue, err error) {
return aux, err
}
func (t *Array) IsEmpty() bool {
return len(t.GetValue()) == 0
}
func (v *Array) Clone() (out TypedValue, err error) {
if len(v.value) > cloneParallelItemThreshold {
return v.cloneParallel(cloneParallelItemThreshold)
@@ -1024,6 +1031,10 @@ func (v *Boolean) Clone() (out TypedValue, err error) {
return aux, err
}
func (t *Bytes) IsEmpty() bool {
return len(t.GetValue()) == 0
}
func (v *Bytes) Clone() (out TypedValue, err error) {
cpy := make([]byte, len(v.value))
copy(cpy, v.value)
@@ -1033,10 +1044,11 @@ func (v *Bytes) Clone() (out TypedValue, err error) {
}
func (v *DateTime) Clone() (out TypedValue, err error) {
t := *v.GetValue()
if v.value == nil {
return NewDateTime(nil)
}
aux, err := NewDateTime(&t)
return aux, err
return NewDateTime(*v.value)
}
func (v *Duration) Clone() (out TypedValue, err error) {
@@ -1128,3 +1140,7 @@ func (v *UnsignedInteger) Clone() (out TypedValue, err error) {
func (v Unresolved) Clone() (out TypedValue, err error) {
return nil, fmt.Errorf("cannot unref unresolved type")
}
func (v DateTime) IsEmpty() bool {
return v.GetValue() == nil
}
+9 -2
View File
@@ -47,6 +47,15 @@ func length(i interface{}) int {
}
func isNil(i interface{}) bool {
_, isTyped := i.(TypedValue)
if isTyped {
switch i.(type) {
case *Duration, *DateTime, *Bytes, *Array, *Integer:
i = i.(TypedValue).Get()
}
}
return gvalfnc.IsNil(i)
}
@@ -115,8 +124,6 @@ func isMap(v interface{}) bool {
// toArray removes expr types (if wrapped) and checks if the variable is slice
// internal only
//
//
func toSlice(vv interface{}) (interface{}, error) {
vv = UntypedValue(vv)
+204 -2
View File
@@ -2,11 +2,12 @@ package expr
import (
"testing"
"time"
"github.com/stretchr/testify/require"
)
func Test_empty(t *testing.T) {
func Test_isEmpty(t *testing.T) {
var (
req = require.New(t)
unsetSliceString []string
@@ -16,75 +17,276 @@ func Test_empty(t *testing.T) {
unsetString string
unsetInt64 int64
unsetDateTime *time.Time
unsetDuration time.Duration
tcc = []struct {
value interface{}
expect interface{}
sc string
}{
{
value: []string{},
expect: true,
sc: "empty string slice",
},
{
value: map[string]string{},
expect: true,
sc: "empty map of strings",
},
{
value: unsetSliceString,
expect: true,
sc: "undefined string slice",
},
{
value: []int{},
expect: true,
sc: "empty int slice",
},
{
value: []int{1},
expect: false,
sc: "1-elem int slice",
},
{
value: unsetSliceInt,
expect: true,
sc: "undefined int slice",
},
{
value: unsetSliceBool,
expect: true,
sc: "undefined slice bool",
},
{
value: int(1),
expect: false,
sc: "defined int",
},
{
value: int(0),
expect: true,
sc: "defined int 0",
},
{
value: "",
expect: true,
sc: "emty string",
},
{
value: unsetString,
expect: true,
sc: "undefined string",
},
{
value: unsetSliceFloat,
expect: true,
sc: "undefined slice float",
},
{
value: unsetInt64,
expect: true,
sc: "undefined slice int64",
},
{
value: []float32{11.1},
expect: false,
sc: "non-empty slice float32",
},
{
value: []float32{},
expect: true,
sc: "empty slice float32",
},
{
value: unsetDateTime,
expect: true,
sc: "undefined datetime",
},
{
value: Must(NewInteger(nil)),
expect: false,
sc: "undefined Integer expr",
},
{
value: Must(NewDateTime(nil)),
expect: true,
sc: "undefined DateTime expr",
},
{
value: Must(NewDateTime(unsetDateTime)),
expect: true,
sc: "undefined DateTime expr",
},
{
value: Must(NewArray([]string{"A"})),
expect: false,
sc: "non empty Array expr",
},
{
value: Must(NewBoolean(nil)),
expect: false,
sc: "undefined Boolean expr",
},
{
value: Must(NewBytes(nil)),
expect: true,
sc: "undefined Bytes expr",
},
{
value: Must(NewDuration(unsetDuration)),
expect: false,
sc: "undefined Duration expr",
},
}
)
for _, tst := range tcc {
req.Equal(tst.expect, isEmpty(tst.value))
req.Equal(tst.expect, isEmpty(tst.value), "Failed isEmpty test: %s", tst.sc)
}
}
func Test_isNil(t *testing.T) {
var (
req = require.New(t)
unsetSliceString []string
unsetSliceInt []int8
unsetSliceBool []bool
unsetSliceFloat []float32
unsetString string
unsetInt64 int64
unsetDateTime *time.Time
unsetDuration time.Duration
tcc = []struct {
value interface{}
expect interface{}
sc string
}{
{
value: []string{},
expect: false,
sc: "empty string slice",
},
{
value: map[string]string{},
expect: false,
sc: "empty map of strings",
},
{
// @todo
value: unsetSliceString,
expect: false,
sc: "undefined string slice",
},
{
value: []int{},
expect: false,
sc: "empty int slice",
},
{
value: []int{1},
expect: false,
sc: "1-elem int slice",
},
{
// @todo
value: unsetSliceInt,
expect: false,
sc: "undefined int slice",
},
{
value: unsetSliceBool,
expect: false,
sc: "undefined slice bool",
},
{
value: int(1),
expect: false,
sc: "defined int",
},
{
value: int(0),
expect: false,
sc: "defined int 0",
},
{
value: "",
expect: false,
sc: "emty string",
},
{
value: unsetString,
expect: false,
sc: "undefined string",
},
{
value: unsetSliceFloat,
expect: false,
sc: "undefined slice float",
},
{
value: unsetInt64,
expect: false,
sc: "undefined slice int64",
},
{
value: []float32{11.1},
expect: false,
sc: "non-empty slice float32",
},
{
value: []float32{},
expect: false,
sc: "empty slice float32",
},
{
value: unsetDateTime,
expect: true,
sc: "undefined datetime",
},
{
value: Must(NewInteger(nil)),
expect: false,
sc: "undefined Integer expr",
},
{
value: Must(NewDateTime(nil)),
expect: true,
sc: "nil DateTime expr",
},
{
value: Must(NewDateTime(unsetDateTime)),
expect: true,
sc: "undefined DateTime expr",
},
{
value: Must(NewArray([]string{"A"})),
expect: false,
sc: "non empty Array expr",
},
{
value: Must(NewBoolean(nil)),
expect: false,
sc: "undefined Boolean expr",
},
{
value: Must(NewBytes(nil)),
expect: false,
sc: "undefined Bytes expr",
},
{
value: Must(NewDuration(unsetDuration)),
expect: false,
sc: "undefined Duration expr",
},
}
)
for _, tst := range tcc {
req.Equal(tst.expect, isNil(tst.value), "Failed isNil test: %s", tst.sc)
}
}