mirror of
https://gitee.com/milvus-io/milvus.git
synced 2025-12-07 01:28:27 +08:00
fix: Add precheck for unsupport datatype cast (#42677)
issue: #42527 --------- Signed-off-by: Cai Zhang <cai.zhang@zilliz.com>
This commit is contained in:
parent
c9bc70f272
commit
4ca1a231ad
@ -265,16 +265,19 @@ func (s *FillExpressionValueSuite) TestBinaryRange() {
|
||||
func (s *FillExpressionValueSuite) TestBinaryArithOpEvalRange() {
|
||||
s.Run("normal case", func() {
|
||||
testcases := []testcase{
|
||||
{`Int64Field + 5.5 == 10.5`, nil},
|
||||
{`Int64Field + 5 == 10`, nil},
|
||||
{`Int64Field - {offset} >= {target}`, map[string]*schemapb.TemplateValue{
|
||||
"offset": generateTemplateValue(schemapb.DataType_Double, 3.5),
|
||||
"target": generateTemplateValue(schemapb.DataType_Double, 11.5),
|
||||
"offset": generateTemplateValue(schemapb.DataType_Int64, int64(3)),
|
||||
"target": generateTemplateValue(schemapb.DataType_Int64, int64(11)),
|
||||
}},
|
||||
{`Int64Field * 3.5 <= {target}`, map[string]*schemapb.TemplateValue{
|
||||
"target": generateTemplateValue(schemapb.DataType_Double, 11.5),
|
||||
{`Int64Field * 3 <= {target}`, map[string]*schemapb.TemplateValue{
|
||||
"target": generateTemplateValue(schemapb.DataType_Int64, int64(11)),
|
||||
}},
|
||||
{`Int64Field / {offset} > 11.5`, map[string]*schemapb.TemplateValue{
|
||||
"offset": generateTemplateValue(schemapb.DataType_Double, 3.5),
|
||||
{`Int64Field / {offset} > 11`, map[string]*schemapb.TemplateValue{
|
||||
"offset": generateTemplateValue(schemapb.DataType_Int64, int64(3)),
|
||||
}},
|
||||
{`FloatField / {offset} > 11.3`, map[string]*schemapb.TemplateValue{
|
||||
"offset": generateTemplateValue(schemapb.DataType_Double, 3.3),
|
||||
}},
|
||||
{`ArrayField[0] % {offset} < 11`, map[string]*schemapb.TemplateValue{
|
||||
"offset": generateTemplateValue(schemapb.DataType_Int64, int64(3)),
|
||||
|
||||
@ -274,8 +274,14 @@ func Power(a, b *planpb.GenericValue) *ExprWithType {
|
||||
} else {
|
||||
// aInt && bInt
|
||||
// 2 ** (-1) = 0.5
|
||||
target := math.Pow(float64(a.GetInt64Val()), float64(b.GetInt64Val()))
|
||||
if b.GetInt64Val() >= 0 && target <= math.MaxInt64 {
|
||||
ret.dataType = schemapb.DataType_Int64
|
||||
ret.expr.GetValueExpr().Value = NewInt(int64(target))
|
||||
} else {
|
||||
ret.dataType = schemapb.DataType_Double
|
||||
ret.expr.GetValueExpr().Value = NewFloat(math.Pow(float64(a.GetInt64Val()), float64(b.GetInt64Val())))
|
||||
ret.expr.GetValueExpr().Value = NewFloat(target)
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
|
||||
@ -215,8 +215,8 @@ func (v *ParserVisitor) VisitAddSub(ctx *parser.AddSubContext) interface{} {
|
||||
} else if rightExpr.expr.GetIsTemplate() {
|
||||
dataType = leftExpr.dataType
|
||||
} else {
|
||||
if !canArithmetic(leftExpr.dataType, getArrayElementType(leftExpr), rightExpr.dataType, getArrayElementType(rightExpr)) {
|
||||
return fmt.Errorf("'%s' can only be used between integer or floating or json field expressions", arithNameMap[ctx.GetOp().GetTokenType()])
|
||||
if err := canArithmetic(leftExpr.dataType, getArrayElementType(leftExpr), rightExpr.dataType, getArrayElementType(rightExpr), reverse); err != nil {
|
||||
return fmt.Errorf("'%s' %s", arithNameMap[ctx.GetOp().GetTokenType()], err.Error())
|
||||
}
|
||||
|
||||
dataType, err = calcDataType(leftExpr, rightExpr, reverse)
|
||||
@ -305,8 +305,8 @@ func (v *ParserVisitor) VisitMulDivMod(ctx *parser.MulDivModContext) interface{}
|
||||
} else if rightExpr.expr.GetIsTemplate() {
|
||||
dataType = leftExpr.dataType
|
||||
} else {
|
||||
if !canArithmetic(leftExpr.dataType, getArrayElementType(leftExpr), rightExpr.dataType, getArrayElementType(rightExpr)) {
|
||||
return fmt.Errorf("'%s' can only be used between integer or floating or json field expressions", arithNameMap[ctx.GetOp().GetTokenType()])
|
||||
if err := canArithmetic(leftExpr.dataType, getArrayElementType(leftExpr), rightExpr.dataType, getArrayElementType(rightExpr), reverse); err != nil {
|
||||
return fmt.Errorf("'%s' %s", arithNameMap[ctx.GetOp().GetTokenType()], err.Error())
|
||||
}
|
||||
|
||||
if err = checkValidModArith(arithExprMap[ctx.GetOp().GetTokenType()], leftExpr.dataType, getArrayElementType(leftExpr), rightExpr.dataType, getArrayElementType(rightExpr)); err != nil {
|
||||
|
||||
@ -422,11 +422,8 @@ func TestExpr_castValue(t *testing.T) {
|
||||
|
||||
exprStr := `Int64Field + 1.1 == 2.1`
|
||||
expr, err := ParseExpr(helper, exprStr, nil)
|
||||
assert.NoError(t, err, exprStr)
|
||||
assert.NotNil(t, expr, exprStr)
|
||||
assert.NotNil(t, expr.GetBinaryArithOpEvalRangeExpr())
|
||||
assert.NotNil(t, expr.GetBinaryArithOpEvalRangeExpr().GetRightOperand().GetFloatVal())
|
||||
assert.NotNil(t, expr.GetBinaryArithOpEvalRangeExpr().GetValue().GetFloatVal())
|
||||
assert.Error(t, err, exprStr)
|
||||
assert.Nil(t, expr, exprStr)
|
||||
|
||||
exprStr = `FloatField +1 == 2`
|
||||
expr, err = ParseExpr(helper, exprStr, nil)
|
||||
@ -458,6 +455,8 @@ func TestExpr_BinaryArith(t *testing.T) {
|
||||
`ArrayField[0] % 19 >= 20`,
|
||||
`JSONField + 15 == 16`,
|
||||
`15 + JSONField == 16`,
|
||||
`Int64Field + (2**3) > 0`,
|
||||
`1 + FloatField > 100`,
|
||||
}
|
||||
for _, exprStr := range exprStrs {
|
||||
assertValidExpr(t, helper, exprStr)
|
||||
@ -467,6 +466,11 @@ func TestExpr_BinaryArith(t *testing.T) {
|
||||
unsupported := []string{
|
||||
`ArrayField + 15 == 16`,
|
||||
`15 + ArrayField == 16`,
|
||||
`Int64Field + 1.1 = 2.1`,
|
||||
`Int64Field == 2.1`,
|
||||
`Int64Field >= 2.1`,
|
||||
`3 > Int64Field >= 2.1`,
|
||||
`Int64Field + (2**-1) > 0`,
|
||||
}
|
||||
for _, exprStr := range unsupported {
|
||||
assertInvalidExpr(t, helper, exprStr)
|
||||
@ -1520,7 +1524,7 @@ func TestRandomSampleWithFilter(t *testing.T) {
|
||||
`VarCharField IS NOT NULL && random_sample(0.01)`,
|
||||
`11.0 < DoubleField < 12.0 && random_sample(0.01)`,
|
||||
`1 < JSONField < 3 && random_sample(0.01)`,
|
||||
`Int64Field + 1.1 == 2.1 && random_sample(0.01)`,
|
||||
`Int64Field + 1 == 2 && random_sample(0.01)`,
|
||||
`Int64Field % 10 != 9 && random_sample(0.01)`,
|
||||
`A * 15 > 16 && random_sample(0.01)`,
|
||||
`(Int16Field - 3 == 4) and (Int32Field * 5 != 6) && random_sample(0.01)`,
|
||||
|
||||
@ -560,8 +560,9 @@ func convertEscapeSingle(literal string) (string, error) {
|
||||
|
||||
func canArithmeticDataType(left, right schemapb.DataType) bool {
|
||||
switch left {
|
||||
case schemapb.DataType_Int8, schemapb.DataType_Int16, schemapb.DataType_Int32, schemapb.DataType_Int64,
|
||||
schemapb.DataType_Float, schemapb.DataType_Double:
|
||||
case schemapb.DataType_Int8, schemapb.DataType_Int16, schemapb.DataType_Int32, schemapb.DataType_Int64:
|
||||
return typeutil.IsIntegerType(right) || typeutil.IsJSONType(right)
|
||||
case schemapb.DataType_Float, schemapb.DataType_Double:
|
||||
return typeutil.IsArithmetic(right) || typeutil.IsJSONType(right)
|
||||
case schemapb.DataType_JSON:
|
||||
return typeutil.IsArithmetic(right)
|
||||
@ -583,17 +584,20 @@ func canArithmeticDataType(left, right schemapb.DataType) bool {
|
||||
// return canArithmeticDataType(left.dataType, getArrayElementType(right))
|
||||
//}
|
||||
|
||||
func canArithmetic(left, leftElement, right, rightElement schemapb.DataType) bool {
|
||||
if !typeutil.IsArrayType(left) && !typeutil.IsArrayType(right) {
|
||||
return canArithmeticDataType(left, right)
|
||||
}
|
||||
if typeutil.IsArrayType(left) && typeutil.IsArrayType(right) {
|
||||
return canArithmeticDataType(leftElement, rightElement)
|
||||
}
|
||||
func canArithmetic(left, leftElement, right, rightElement schemapb.DataType, reverse bool) error {
|
||||
if typeutil.IsArrayType(left) {
|
||||
return canArithmeticDataType(leftElement, right)
|
||||
left = leftElement
|
||||
}
|
||||
return canArithmeticDataType(left, rightElement)
|
||||
if typeutil.IsArrayType(right) {
|
||||
right = rightElement
|
||||
}
|
||||
if reverse {
|
||||
left, right = right, left
|
||||
}
|
||||
if !canArithmeticDataType(left, right) {
|
||||
return fmt.Errorf("cannot perform arithmetic between %s field and %s", left.String(), right.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func canConvertToIntegerType(dataType, elementType schemapb.DataType) bool {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user