mirror of
https://github.com/minio/minio.git
synced 2025-11-20 18:06:10 -05:00
S3 Select: Add parser support for lists. (#8329)
This commit is contained in:
committed by
Harshavardhana
parent
e85df07518
commit
002ac82631
@@ -17,6 +17,7 @@
|
||||
package sql
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
@@ -46,6 +47,14 @@ type Value struct {
|
||||
value interface{}
|
||||
}
|
||||
|
||||
// MarshalJSON provides json marshaling of values.
|
||||
func (v Value) MarshalJSON() ([]byte, error) {
|
||||
if b, ok := v.ToBytes(); ok {
|
||||
return b, nil
|
||||
}
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
// GetTypeString returns a string representation for vType
|
||||
func (v Value) GetTypeString() string {
|
||||
switch v.value.(type) {
|
||||
@@ -63,6 +72,8 @@ func (v Value) GetTypeString() string {
|
||||
return "TIMESTAMP"
|
||||
case []byte:
|
||||
return "BYTES"
|
||||
case []Value:
|
||||
return "ARRAY"
|
||||
}
|
||||
return "--"
|
||||
}
|
||||
@@ -80,6 +91,17 @@ func (v Value) Repr() string {
|
||||
return fmt.Sprintf("\"%s\":%s", x, v.GetTypeString())
|
||||
case []byte:
|
||||
return fmt.Sprintf("\"%s\":BYTES", string(x))
|
||||
case []Value:
|
||||
var s strings.Builder
|
||||
s.WriteByte('[')
|
||||
for i, v := range x {
|
||||
s.WriteString(v.Repr())
|
||||
if i < len(x)-1 {
|
||||
s.WriteByte(',')
|
||||
}
|
||||
}
|
||||
s.WriteString("]:ARRAY")
|
||||
return s.String()
|
||||
default:
|
||||
return fmt.Sprintf("%v:INVALID", v.value)
|
||||
}
|
||||
@@ -120,6 +142,11 @@ func FromBytes(b []byte) *Value {
|
||||
return &Value{value: b}
|
||||
}
|
||||
|
||||
// FromArray creates a Value from an array of values.
|
||||
func FromArray(a []Value) *Value {
|
||||
return &Value{value: a}
|
||||
}
|
||||
|
||||
// ToFloat works for int and float values
|
||||
func (v Value) ToFloat() (val float64, ok bool) {
|
||||
switch x := v.value.(type) {
|
||||
@@ -167,6 +194,8 @@ func (v Value) SameTypeAs(b Value) (ok bool) {
|
||||
_, ok = b.value.(time.Time)
|
||||
case []byte:
|
||||
_, ok = b.value.([]byte)
|
||||
case []Value:
|
||||
_, ok = b.value.([]Value)
|
||||
default:
|
||||
ok = reflect.TypeOf(v.value) == reflect.TypeOf(b.value)
|
||||
}
|
||||
@@ -192,6 +221,12 @@ func (v Value) ToBytes() (val []byte, ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// ToArray returns the value if it is a slice of values.
|
||||
func (v Value) ToArray() (val []Value, ok bool) {
|
||||
val, ok = v.value.([]Value)
|
||||
return
|
||||
}
|
||||
|
||||
// IsNull - checks if value is missing.
|
||||
func (v Value) IsNull() bool {
|
||||
switch v.value.(type) {
|
||||
@@ -201,6 +236,12 @@ func (v Value) IsNull() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsArray returns whether the value is an array.
|
||||
func (v Value) IsArray() (ok bool) {
|
||||
_, ok = v.value.([]Value)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (v Value) isNumeric() bool {
|
||||
switch v.value.(type) {
|
||||
case int64, float64:
|
||||
@@ -255,6 +296,10 @@ func (v Value) CSVString() string {
|
||||
return FormatSQLTimestamp(x)
|
||||
case []byte:
|
||||
return string(x)
|
||||
case []Value:
|
||||
b, _ := json.Marshal(x)
|
||||
return string(b)
|
||||
|
||||
default:
|
||||
return "CSV serialization not implemented for this type"
|
||||
}
|
||||
@@ -311,6 +356,19 @@ func (v *Value) compareOp(op string, a *Value) (res bool, err error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Check if either is nil
|
||||
if v.IsNull() || a.IsNull() {
|
||||
// If one is, both must be.
|
||||
return boolCompare(op, v.IsNull(), a.IsNull())
|
||||
}
|
||||
|
||||
// Check array values
|
||||
aArr, aOK := a.ToArray()
|
||||
vArr, vOK := v.ToArray()
|
||||
if aOK && vOK {
|
||||
return arrayCompare(op, aArr, vArr)
|
||||
}
|
||||
|
||||
isNumeric := v.isNumeric() && a.isNumeric()
|
||||
if isNumeric {
|
||||
intV, ok1i := v.ToInt()
|
||||
@@ -725,6 +783,32 @@ func boolCompare(op string, left, right bool) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func arrayCompare(op string, left, right []Value) (bool, error) {
|
||||
switch op {
|
||||
case opEq:
|
||||
if len(left) != len(right) {
|
||||
return false, nil
|
||||
}
|
||||
for i, l := range left {
|
||||
eq, err := l.compareOp(op, &right[i])
|
||||
if !eq || err != nil {
|
||||
return eq, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case opIneq:
|
||||
for i, l := range left {
|
||||
eq, err := l.compareOp(op, &right[i])
|
||||
if eq || err != nil {
|
||||
return eq, err
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
default:
|
||||
return false, errCmpInvalidBoolOperator
|
||||
}
|
||||
}
|
||||
|
||||
func timestampCompare(op string, left, right time.Time) bool {
|
||||
switch op {
|
||||
case opLt:
|
||||
|
||||
Reference in New Issue
Block a user