select: Add IS (NOT) operators (#13906)

Add `IS` and `IS NOT` as comparison operators.

This may be a bit wider than the S3 spec, but we can rather 
easily remove the forwarding.
This commit is contained in:
Klaus Post
2021-12-14 09:54:50 -08:00
committed by GitHub
parent 44a9339c0a
commit a8d4042853
3 changed files with 74 additions and 16 deletions

View File

@@ -184,7 +184,7 @@ type ConditionRHS struct {
// Compare represents the RHS of a comparison expression
type Compare struct {
Operator string `parser:"@( \"<>\" | \"<=\" | \">=\" | \"=\" | \"<\" | \">\" | \"!=\" )"`
Operator string `parser:"@( \"<>\" | \"<=\" | \">=\" | \"=\" | \"<\" | \">\" | \"!=\" | \"IS\" \"NOT\" | \"IS\")"`
Operand *Operand `parser:" @@"`
}

View File

@@ -326,12 +326,14 @@ func (v *Value) negate() {
// Supported comparison operators
const (
opLt = "<"
opLte = "<="
opGt = ">"
opGte = ">="
opEq = "="
opIneq = "!="
opLt = "<"
opLte = "<="
opGt = ">"
opGte = ">="
opEq = "="
opIneq = "!="
opIs = "IS"
opIsNot = "ISNOT"
)
// InferBytesType will attempt to infer the data type of bytes.
@@ -385,6 +387,21 @@ func (v *Value) compareOp(op string, a *Value) (res bool, err error) {
if !isValidComparisonOperator(op) {
return false, errArithInvalidOperator
}
switch op {
case opIs:
if a.IsNull() {
return v.IsNull(), nil
}
// Forward to Equal
op = opEq
case opIsNot:
if a.IsNull() {
return !v.IsNull(), nil
}
// Forward to not equal.
op = opIneq
default:
}
// Check if type conversion/inference is needed - it is needed
// if the Value is a byte-slice.
@@ -747,12 +764,7 @@ func inferTypeAsString(v *Value) {
func isValidComparisonOperator(op string) bool {
switch op {
case opLt:
case opLte:
case opGt:
case opGte:
case opEq:
case opIneq:
case opLt, opLte, opGt, opGte, opEq, opIneq, opIs, opIsNot:
default:
return false
}