Null values on datetime fields
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user