mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-10-18 08:43:36 +00:00
FB-2041 Added tests for typeIsTimeQuantum and typeIsSet and made them pass. Added tests for DataTypeTuple cases in typesAreAssignmentCompatible. Timestamp conversion checking is handled before it gets to that point but I left those branches in as a backstop. Checking to see if DataType[String,ID]SetQuantum can be assigned to themselves doesn't appear to be reachable currently but left those branches in, because something may use them in future. Added one test to the DAX skip list since it's the IDSetQ version of a StringSetQ test that was already on there, changed skip list to refer to both tests by name instead of by number.
208 lines
4.8 KiB
Go
208 lines
4.8 KiB
Go
package planner
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/featurebasedb/featurebase/v3/sql3"
|
|
"github.com/featurebasedb/featurebase/v3/sql3/parser"
|
|
)
|
|
|
|
func (n *callPlanExpression) EvaluateSetContains(currentRow []interface{}) (interface{}, error) {
|
|
targetSetEval, err := n.args[0].Evaluate(currentRow)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
testValueEval, err := n.args[1].Evaluate(currentRow)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
//if either term is null, then null
|
|
if testValueEval == nil || targetSetEval == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
if targetSetEval != nil {
|
|
switch typ := n.args[0].Type().(type) {
|
|
case *parser.DataTypeStringSet, *parser.DataTypeStringSetQuantum:
|
|
targetSet, ok := targetSetEval.([]string)
|
|
if !ok {
|
|
return nil, sql3.NewErrInternalf("unable to convert value")
|
|
}
|
|
|
|
testValue, ok := testValueEval.(string)
|
|
if !ok {
|
|
return nil, sql3.NewErrInternalf("unable to convert value")
|
|
}
|
|
|
|
return stringSetContains(targetSet, testValue), nil
|
|
|
|
case *parser.DataTypeIDSet, *parser.DataTypeIDSetQuantum:
|
|
targetSet, ok := targetSetEval.([]int64)
|
|
if !ok {
|
|
return nil, sql3.NewErrInternalf("unable to convert value")
|
|
}
|
|
|
|
testValue, ok := testValueEval.(int64)
|
|
if !ok {
|
|
return nil, sql3.NewErrInternalf("unable to convert value")
|
|
}
|
|
|
|
return intSetContains(targetSet, testValue), nil
|
|
|
|
default:
|
|
return nil, sql3.NewErrInternalf("unexpected data type '%T'", typ)
|
|
}
|
|
}
|
|
return nil, sql3.NewErrInternalf("unable to to find column '%s' in currentColumns", n.name)
|
|
}
|
|
|
|
func (n *callPlanExpression) EvaluateSetContainsAny(currentRow []interface{}) (interface{}, error) {
|
|
targetSetEval, err := n.args[0].Evaluate(currentRow)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
testSetEval, err := n.args[1].Evaluate(currentRow)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if targetSetEval != nil {
|
|
switch typ := n.args[0].Type().(type) {
|
|
case *parser.DataTypeStringSet:
|
|
targetSet, ok := targetSetEval.([]string)
|
|
if !ok {
|
|
return nil, sql3.NewErrInternalf("unable to convert value")
|
|
}
|
|
|
|
testSet, ok := testSetEval.([]string)
|
|
if !ok {
|
|
return nil, sql3.NewErrInternalf("unable to convert value")
|
|
}
|
|
|
|
return stringSetContainsAny(targetSet, testSet), nil
|
|
|
|
case *parser.DataTypeIDSet:
|
|
targetSet, ok := targetSetEval.([]int64)
|
|
if !ok {
|
|
return nil, sql3.NewErrInternalf("unable to convert value")
|
|
}
|
|
|
|
testSet, ok := testSetEval.([]int64)
|
|
if !ok {
|
|
return nil, sql3.NewErrInternalf("unable to convert value")
|
|
}
|
|
|
|
return intSetContainsAny(targetSet, testSet), nil
|
|
|
|
default:
|
|
return nil, sql3.NewErrInternalf("unexpected data type '%T'", typ)
|
|
}
|
|
|
|
}
|
|
return nil, sql3.NewErrInternalf("unable to to find column '%s' in currentColumns", n.name)
|
|
}
|
|
|
|
func (n *callPlanExpression) EvaluateSetContainsAll(currentRow []interface{}) (interface{}, error) {
|
|
targetSetEval, err := n.args[0].Evaluate(currentRow)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
testSetEval, err := n.args[1].Evaluate(currentRow)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if targetSetEval != nil {
|
|
switch typ := n.args[0].Type().(type) {
|
|
case *parser.DataTypeStringSet:
|
|
targetSet, ok := targetSetEval.([]string)
|
|
if !ok {
|
|
return nil, sql3.NewErrInternalf("unable to convert value")
|
|
}
|
|
|
|
testSet, ok := testSetEval.([]string)
|
|
if !ok {
|
|
return nil, sql3.NewErrInternalf("unable to convert value")
|
|
}
|
|
|
|
return stringSetContainsAll(targetSet, testSet), nil
|
|
|
|
case *parser.DataTypeIDSet:
|
|
targetSet, ok := targetSetEval.([]int64)
|
|
if !ok {
|
|
return nil, sql3.NewErrInternalf("unable to convert value")
|
|
}
|
|
|
|
testSet, ok := testSetEval.([]int64)
|
|
if !ok {
|
|
return nil, sql3.NewErrInternalf("unable to convert value")
|
|
}
|
|
|
|
return intSetContainsAll(targetSet, testSet), nil
|
|
|
|
default:
|
|
return nil, sql3.NewErrInternalf("unexpected data type '%T'", typ)
|
|
}
|
|
|
|
}
|
|
|
|
return nil, sql3.NewErrInternalf("unable to to find column '%s' in currentColumns", n.name)
|
|
}
|
|
|
|
func stringSetContains(set []string, val string) bool {
|
|
for _, v := range set {
|
|
if strings.EqualFold(v, val) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func stringSetContainsAny(targetSet []string, testSet []string) bool {
|
|
for _, test := range testSet {
|
|
if stringSetContains(targetSet, test) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func stringSetContainsAll(targetSet []string, testSet []string) bool {
|
|
for _, test := range testSet {
|
|
if !stringSetContains(targetSet, test) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func intSetContains(set []int64, val int64) bool {
|
|
for _, v := range set {
|
|
if v == val {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func intSetContainsAny(targetSet []int64, testSet []int64) bool {
|
|
for _, test := range testSet {
|
|
if intSetContains(targetSet, test) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func intSetContainsAll(targetSet []int64, testSet []int64) bool {
|
|
for _, test := range testSet {
|
|
if !intSetContains(targetSet, test) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|