fixed all the stuff that adding the vector data type broke

This commit is contained in:
pokeeffe-molecula 2023-04-10 10:51:45 -05:00
parent 082b6e661c
commit 7d2a3293ec
10 changed files with 213 additions and 42 deletions

View file

@ -234,10 +234,10 @@ func NewErrCacheKeyNotFound(key uint64) error {
)
}
func NewErrTypeAssignmentIncompatible(line, col int, type1, type2 string) error {
func NewErrTypeAssignmentIncompatible(line, col int, sourceType, targetType string) error {
return errors.New(
ErrTypeAssignmentIncompatible,
fmt.Sprintf("[%d:%d] an expression of type '%s' cannot be assigned to type '%s'", line, col, type1, type2),
fmt.Sprintf("[%d:%d] an expression of type '%s' cannot be assigned to type '%s'", line, col, sourceType, targetType),
)
}

View file

@ -165,7 +165,7 @@ func (p *ExecutionPlanner) analyzeModelOptionExpr(ctx context.Context, optName s
if !e.IsLiteral() {
return nil, sql3.NewErrInternalf("string array literal expected")
}
ok, baseType := typeIsSet(e.DataType())
ok, baseType := typeIsAssignmentCompatibleWithSet(e.DataType())
if !ok {
return nil, sql3.NewErrInternalf("array expression expected")
}

View file

@ -2455,6 +2455,25 @@ func (n *exprArrayLiteralPlanExpression) Evaluate(currentRow []interface{}) (int
}
switch typ := arrayType.SubscriptType.(type) {
case *parser.DataTypeInt:
result := []int64{}
for _, e := range n.members {
er, err := e.Evaluate(currentRow)
if err != nil {
return nil, err
}
coercedEr, err := coerceValue(e.Type(), &parser.DataTypeInt{}, er, parser.Pos{Line: 0, Column: 0})
if err != nil {
return nil, err
}
eri, ok := coercedEr.(int64)
if !ok {
return nil, sql3.NewErrInternalf("unable to convert element result")
}
result = append(result, eri)
}
return result, nil
case *parser.DataTypeID:
result := []int64{}
for _, e := range n.members {

View file

@ -220,14 +220,17 @@ func (p *ExecutionPlanner) analyzeCallExpression(ctx context.Context, call *pars
return nil, sql3.NewErrCallParameterCountMismatch(call.Rparen.Line, call.Rparen.Column, call.Name.Name, 2, len(call.Args))
}
ok, baseType := typeIsSet(call.Args[0].DataType())
// first arg should be assignment compatible with any set type
ok, baseType := typeIsAssignmentCompatibleWithSet(call.Args[0].DataType())
if !ok {
return nil, sql3.NewErrSetExpressionExpected(call.Args[0].Pos().Line, call.Args[0].Pos().Column)
}
if !typesAreComparable(baseType, call.Args[1].DataType()) {
return nil, sql3.NewErrTypesAreNotEquatable(call.Args[1].Pos().Line, call.Args[1].Pos().Column, call.Args[0].DataType().TypeDescription(), call.Args[1].DataType().TypeDescription())
// second argument should be assignment compatible with the base type
if !typesAreAssignmentCompatible(baseType, call.Args[1].DataType()) {
return nil, sql3.NewErrTypeAssignmentIncompatible(call.Args[1].Pos().Line, call.Args[1].Pos().Column, call.Args[1].DataType().TypeDescription(), baseType.TypeDescription())
}
call.ResultDataType = parser.NewDataTypeBool()
case "SETCONTAINSALL":
@ -236,14 +239,14 @@ func (p *ExecutionPlanner) analyzeCallExpression(ctx context.Context, call *pars
return nil, sql3.NewErrCallParameterCountMismatch(call.Rparen.Line, call.Rparen.Column, call.Name.Name, 2, len(call.Args))
}
// first arg should be set
ok, baseType1 := typeIsSet(call.Args[0].DataType())
// first arg should be assignment compatible with any set type
ok, baseType1 := typeIsAssignmentCompatibleWithSet(call.Args[0].DataType())
if !ok {
return nil, sql3.NewErrSetExpressionExpected(call.Args[0].Pos().Line, call.Args[0].Pos().Column)
}
// second arg should be set
ok, baseType2 := typeIsSet(call.Args[1].DataType())
// second arg should be assignment compatible with any set type
ok, baseType2 := typeIsAssignmentCompatibleWithSet(call.Args[1].DataType())
if !ok {
return nil, sql3.NewErrSetExpressionExpected(call.Args[0].Pos().Line, call.Args[0].Pos().Column)
}
@ -261,13 +264,13 @@ func (p *ExecutionPlanner) analyzeCallExpression(ctx context.Context, call *pars
}
// first arg should be set
ok, baseType1 := typeIsSet(call.Args[0].DataType())
ok, baseType1 := typeIsAssignmentCompatibleWithSet(call.Args[0].DataType())
if !ok {
return nil, sql3.NewErrSetExpressionExpected(call.Args[0].Pos().Line, call.Args[0].Pos().Column)
}
// second arg should be set
ok, baseType2 := typeIsSet(call.Args[1].DataType())
ok, baseType2 := typeIsAssignmentCompatibleWithSet(call.Args[1].DataType())
if !ok {
return nil, sql3.NewErrSetExpressionExpected(call.Args[0].Pos().Line, call.Args[0].Pos().Column)
}

View file

@ -290,65 +290,105 @@ func typesAreAssignmentCompatible(targetType parser.ExprDataType, sourceType par
return false
}
case *parser.DataTypeStringSet:
switch sourceType.(type) {
switch source := sourceType.(type) {
case *parser.DataTypeStringSet:
return true
case *parser.DataTypeArray:
switch source.SubscriptType.(type) {
case *parser.DataTypeString:
return true
default:
return false
}
default:
return false
}
case *parser.DataTypeStringSetQuantum:
switch source := sourceType.(type) {
case *parser.DataTypeStringSetQuantum:
return true
case *parser.DataTypeStringSet:
return true
case *parser.DataTypeArray:
switch source.SubscriptType.(type) {
case *parser.DataTypeString:
return true
default:
return false
}
case *parser.DataTypeTuple:
// if we are assigning to a time quantum, a tuple is allowed, but members
// have to be a timestamp (or coercable to a timestamp) and and stringset
// (or coercable to a string set)
if len(source.Members) != 2 {
return false
}
if !typesAreAssignmentCompatible(parser.NewDataTypeTimestamp(), source.Members[0]) {
return false
}
_, ok = source.Members[1].(*parser.DataTypeStringSet)
ok, baseType := typeIsAssignmentCompatibleWithSet(source.Members[1])
if !ok {
return false
}
if !typesAreAssignmentCompatible(parser.NewDataTypeString(), baseType) {
return false
}
return true
default:
return false
}
case *parser.DataTypeIDSet:
switch sourceType.(type) {
switch st := sourceType.(type) {
case *parser.DataTypeIDSet:
return true
case *parser.DataTypeArray:
switch st.SubscriptType.(type) {
case *parser.DataTypeInt, *parser.DataTypeID:
return true
default:
return false
}
default:
return false
}
case *parser.DataTypeIDSetQuantum:
switch source := sourceType.(type) {
case *parser.DataTypeIDSetQuantum:
return true
case *parser.DataTypeIDSet:
return true
case *parser.DataTypeArray:
switch source.SubscriptType.(type) {
case *parser.DataTypeInt, *parser.DataTypeID:
return true
default:
return false
}
case *parser.DataTypeTuple:
// if we are assigning to a time quantum, a tuple is allowed, but members
// have to be a timestamp (or coercable to a timestamp) and and idset
// have to be a timestamp (or coercable to a timestamp) and and idset (or coercable to)
if len(source.Members) != 2 {
return false
}
if !typesAreAssignmentCompatible(parser.NewDataTypeTimestamp(), source.Members[0]) {
return false
}
_, ok = source.Members[1].(*parser.DataTypeIDSet)
ok, baseType := typeIsAssignmentCompatibleWithSet(source.Members[1])
if !ok {
return false
}
// make sure the base type matches
if !typesAreAssignmentCompatible(parser.NewDataTypeID(), baseType) {
return false
}
return true
default:
return false
}
case *parser.DataTypeDecimal:
switch rhs := sourceType.(type) {
case *parser.DataTypeDecimal:
@ -480,9 +520,9 @@ func typeIsRange(testType parser.ExprDataType) bool {
}
}
// returns true if the type is a set type
func typeIsSet(testType parser.ExprDataType) (bool, parser.ExprDataType) {
switch testType.(type) {
// returns true if the type is assignment compatible with a set, and the subscript type
func typeIsAssignmentCompatibleWithSet(testType parser.ExprDataType) (bool, parser.ExprDataType) {
switch tt := testType.(type) {
case *parser.DataTypeIDSet:
return true, parser.NewDataTypeID()
case *parser.DataTypeStringSet:
@ -491,6 +531,13 @@ func typeIsSet(testType parser.ExprDataType) (bool, parser.ExprDataType) {
return true, parser.NewDataTypeID()
case *parser.DataTypeStringSetQuantum:
return true, parser.NewDataTypeString()
case *parser.DataTypeArray:
switch bt := tt.SubscriptType.(type) {
case *parser.DataTypeID, *parser.DataTypeInt, *parser.DataTypeString:
return true, bt
default:
return false, nil
}
default:
return false, nil
}
@ -635,10 +682,14 @@ func typesAreComparable(testTypeL parser.ExprDataType, testTypeR parser.ExprData
}
case *parser.DataTypeIDSet:
switch testTypeR.(type) {
switch rhs := testTypeR.(type) {
case *parser.DataTypeIDSet:
return true
case *parser.DataTypeArray:
switch rhs.SubscriptType.(type) {
case *parser.DataTypeID, *parser.DataTypeInt:
return true
}
}
case *parser.DataTypeString:
@ -649,10 +700,14 @@ func typesAreComparable(testTypeL parser.ExprDataType, testTypeR parser.ExprData
}
case *parser.DataTypeStringSet:
switch testTypeR.(type) {
switch rhs := testTypeR.(type) {
case *parser.DataTypeStringSet:
return true
case *parser.DataTypeArray:
switch rhs.SubscriptType.(type) {
case *parser.DataTypeString:
return true
}
}
}

View file

@ -25,6 +25,35 @@ func (n *callPlanExpression) EvaluateSetContains(currentRow []interface{}) (inte
if targetSetEval != nil {
switch typ := n.args[0].Type().(type) {
case *parser.DataTypeArray:
switch typ.SubscriptType.(type) {
case *parser.DataTypeString:
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.DataTypeID, *parser.DataTypeInt:
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
}
case *parser.DataTypeStringSet, *parser.DataTypeStringSetQuantum:
targetSet, ok := targetSetEval.([]string)
if !ok {
@ -76,6 +105,35 @@ func (n *callPlanExpression) EvaluateSetContainsAny(currentRow []interface{}) (i
if targetSetEval != nil {
switch typ := n.args[0].Type().(type) {
case *parser.DataTypeArray:
switch typ.SubscriptType.(type) {
case *parser.DataTypeString:
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.DataTypeID, *parser.DataTypeInt:
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
}
case *parser.DataTypeStringSet:
targetSet, ok := targetSetEval.([]string)
if !ok {
@ -128,6 +186,35 @@ func (n *callPlanExpression) EvaluateSetContainsAll(currentRow []interface{}) (i
if targetSetEval != nil {
switch typ := n.args[0].Type().(type) {
case *parser.DataTypeArray:
switch typ.SubscriptType.(type) {
case *parser.DataTypeString:
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.DataTypeID, *parser.DataTypeInt:
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
}
case *parser.DataTypeStringSet:
targetSet, ok := targetSetEval.([]string)
if !ok {

View file

@ -90,7 +90,7 @@ var betweenTests = TableTest{
SQLs: sqls(
"select ids1 between [100, 102] and [456, 789] from between_all_types",
),
ExpErr: "type 'idset' cannot be used as a range subscript",
ExpErr: "type 'array(int)' cannot be used as a range subscript",
},
{
SQLs: sqls(
@ -102,7 +102,7 @@ var betweenTests = TableTest{
SQLs: sqls(
"select ss1 between ['a', 'b'] and ['c', 'd'] from between_all_types",
),
ExpErr: "type 'stringset' cannot be used as a range subscript",
ExpErr: "type 'array(string)' cannot be used as a range subscript",
},
{
SQLs: sqls(
@ -209,7 +209,7 @@ var notBetweenTests = TableTest{
SQLs: sqls(
"select ids1 not between [100, 102] and [456, 789] from not_between_all_types",
),
ExpErr: "type 'idset' cannot be used as a range subscript",
ExpErr: "type 'array(int)' cannot be used as a range subscript",
},
{
SQLs: sqls(
@ -221,7 +221,7 @@ var notBetweenTests = TableTest{
SQLs: sqls(
"select ss1 not between ['a', 'b'] and ['c', 'd'] from not_between_all_types",
),
ExpErr: "type 'stringset' cannot be used as a range subscript",
ExpErr: "type 'array(string)' cannot be used as a range subscript",
},
{
SQLs: sqls(

View file

@ -115,14 +115,14 @@ var insertTest = TableTest{
SQLs: sqls(
"insert into testinsert (_id, a, event) values (4, 40, [101, 150])",
),
ExpErr: "an expression of type 'idset' cannot be assigned to type 'stringset'",
ExpErr: "an expression of type 'array(int)' cannot be assigned to type 'stringset'",
},
{
// InsertSetsTypeError2
SQLs: sqls(
"insert into testinsert (_id, a, ievent) values (4, 40, ['POST', 'GET'])",
),
ExpErr: "an expression of type 'stringset' cannot be assigned to type 'idset'",
ExpErr: "an expression of type 'array(string)' cannot be assigned to type 'idset'",
},
{
name: "min constraint",

View file

@ -296,7 +296,7 @@ var setFunctionTests = TableTest{
SQLs: sqls(
"select * from selectwithset where setcontains(event, 1)",
),
ExpErr: "types 'stringset' and 'int' are not equatable",
ExpErr: "an expression of type 'int' cannot be assigned to type 'string'",
},
{
// SetContainsWrongTypeInt
@ -304,7 +304,7 @@ var setFunctionTests = TableTest{
SQLs: sqls(
"select * from selectwithset where setcontains(ievent, 'foo')",
),
ExpErr: "types 'idset' and 'string' are not equatable",
ExpErr: "an expression of type 'string' cannot be assigned to type 'id'",
},
{
// SetContainsWrongTypeSet
@ -312,7 +312,7 @@ var setFunctionTests = TableTest{
SQLs: sqls(
"select * from selectwithset where setcontains(event, ['foo'])",
),
ExpErr: "types 'stringset' and 'stringset' are not equatable",
ExpErr: "an expression of type 'array(string)' cannot be assigned to type 'string'",
},
{
// SetContainsWrongTypeSet
@ -328,7 +328,14 @@ var setFunctionTests = TableTest{
SQLs: sqls(
"select * from selectwithset where setcontains(event, null)",
),
ExpErr: "types 'stringset' and 'void' are not equatable",
ExpHdrs: hdrs(
hdr("_id", fldTypeID),
hdr("a", fldTypeInt),
hdr("b", fldTypeInt),
hdr("event", fldTypeStringSet),
hdr("ievent", fldTypeIDSet),
),
ExpRows: rows(),
},
{
// SetContainsWrongTypeSet
@ -376,13 +383,13 @@ var setParameterTests = TableTest{
SQLs: sqls(
"select setcontains(['POST', 'GET'], 1)",
),
ExpErr: "types 'stringset' and 'int' are not equatable",
ExpErr: "an expression of type 'int' cannot be assigned to type 'string'",
},
{
SQLs: sqls(
"select setcontains([1, 2], '1')",
),
ExpErr: "types 'idset' and 'string' are not equatable",
ExpErr: "an expression of type 'string' cannot be assigned to type 'int'",
},
{
@ -404,14 +411,14 @@ var setParameterTests = TableTest{
"select setcontainsall(['POST', 'GET'], [1, 2])",
"select setcontainsany(['POST', 'GET'], [1, 2])",
),
ExpErr: "types 'string' and 'id' are not equatable",
ExpErr: "types 'string' and 'int' are not equatable",
},
{
SQLs: sqls(
"select setcontainsall([1, 2], ['1', '2'])",
"select setcontainsany([1, 2], ['1', '2'])",
),
ExpErr: "types 'id' and 'string' are not equatable",
ExpErr: "types 'int' and 'string' are not equatable",
},
},
}

View file

@ -24,13 +24,13 @@ var timeQuantumTest = TableTest{
SQLs: sqls(
"insert into time_quantum_insert (_id, i1, ss1, ids1) values (1, 1, {['1']}, {[1]})",
),
ExpErr: "an expression of type 'tuple(stringset)' cannot be assigned to type 'stringsetq'",
ExpErr: "an expression of type 'tuple(array(string))' cannot be assigned to type 'stringsetq'",
},
{
SQLs: sqls(
"insert into time_quantum_insert (_id, i1, ss1, ids1) values (1, 1, ['1'], {[1]})",
),
ExpErr: "an expression of type 'tuple(idset)' cannot be assigned to type 'idsetq'",
ExpErr: "an expression of type 'tuple(array(int))' cannot be assigned to type 'idsetq'",
},
{
SQLs: sqls(
@ -48,13 +48,13 @@ var timeQuantumTest = TableTest{
SQLs: sqls(
"insert into time_quantum_insert (_id, i1, ss1, ids1) values (1, 1, {'2022-01-01T00:00:00Z', [1]}, {[1]})",
),
ExpErr: "an expression of type 'tuple(string, idset)' cannot be assigned to type 'stringsetq'",
ExpErr: "an expression of type 'tuple(string, array(int))' cannot be assigned to type 'stringsetq'",
},
{
SQLs: sqls(
"insert into time_quantum_insert (_id, i1, ss1, ids1) values (1, 1, ['1'], {'2022-01-01T00:00:00Z', ['1']})",
),
ExpErr: "an expression of type 'tuple(string, stringset)' cannot be assigned to type 'idsetq'",
ExpErr: "an expression of type 'tuple(string, array(string))' cannot be assigned to type 'idsetq'",
},
{
SQLs: sqls(