select: add MISSING operator support (#14406)

Probably not full support, but for regular checks it should work.

Fixes #14358
This commit is contained in:
Klaus Post
2022-02-25 12:31:19 -08:00
committed by GitHub
parent e43cc316ff
commit 88fd1cba71
8 changed files with 153 additions and 29 deletions

View File

@@ -49,6 +49,9 @@ type Value struct {
value interface{}
}
// Missing is used to indicate a non-existing value.
type Missing struct{}
// MarshalJSON provides json marshaling of values.
func (v Value) MarshalJSON() ([]byte, error) {
if b, ok := v.ToBytes(); ok {
@@ -76,6 +79,8 @@ func (v Value) GetTypeString() string {
return "BYTES"
case []Value:
return "ARRAY"
case Missing:
return "MISSING"
}
return "--"
}
@@ -104,6 +109,8 @@ func (v Value) Repr() string {
}
s.WriteString("]:ARRAY")
return s.String()
case Missing:
return ":MISSING"
default:
return fmt.Sprintf("%v:INVALID", v.value)
}
@@ -139,6 +146,11 @@ func FromNull() *Value {
return &Value{value: nil}
}
// FromMissing creates a Value with Missing value
func FromMissing() *Value {
return &Value{value: Missing{}}
}
// FromBytes creates a Value from a []byte
func FromBytes(b []byte) *Value {
return &Value{value: b}
@@ -239,6 +251,12 @@ func (v Value) IsNull() bool {
return false
}
// IsMissing - checks if value is missing.
func (v Value) IsMissing() bool {
_, ok := v.value.(Missing)
return ok
}
// IsArray returns whether the value is an array.
func (v Value) IsArray() (ok bool) {
_, ok = v.value.([]Value)
@@ -283,7 +301,7 @@ func (v Value) String() string {
// CSVString - convert to string for CSV serialization
func (v Value) CSVString() string {
switch x := v.value.(type) {
case nil:
case nil, Missing:
return ""
case bool:
if x {
@@ -390,13 +408,21 @@ func (v *Value) compareOp(op string, a *Value) (res bool, err error) {
switch op {
case opIs:
if a.IsNull() {
return v.IsNull(), nil
// Missing is null
return v.IsNull() || v.IsMissing(), nil
}
if a.IsMissing() {
return v.IsMissing(), nil
}
// Forward to Equal
op = opEq
case opIsNot:
if a.IsNull() {
return !v.IsNull(), nil
// Missing is not null
return !v.IsNull() && !v.IsMissing(), nil
}
if a.IsMissing() {
return !v.IsMissing(), nil
}
// Forward to not equal.
op = opIneq
@@ -416,6 +442,11 @@ func (v *Value) compareOp(op string, a *Value) (res bool, err error) {
return boolCompare(op, v.IsNull(), a.IsNull())
}
if a.IsMissing() || v.IsMissing() {
// If one is, both must be.
return boolCompare(op, v.IsMissing(), a.IsMissing())
}
// Check array values
aArr, aOK := a.ToArray()
vArr, vOK := v.ToArray()