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() {
|
func (s *FillExpressionValueSuite) TestBinaryArithOpEvalRange() {
|
||||||
s.Run("normal case", func() {
|
s.Run("normal case", func() {
|
||||||
testcases := []testcase{
|
testcases := []testcase{
|
||||||
{`Int64Field + 5.5 == 10.5`, nil},
|
{`Int64Field + 5 == 10`, nil},
|
||||||
{`Int64Field - {offset} >= {target}`, map[string]*schemapb.TemplateValue{
|
{`Int64Field - {offset} >= {target}`, map[string]*schemapb.TemplateValue{
|
||||||
"offset": generateTemplateValue(schemapb.DataType_Double, 3.5),
|
"offset": generateTemplateValue(schemapb.DataType_Int64, int64(3)),
|
||||||
"target": generateTemplateValue(schemapb.DataType_Double, 11.5),
|
"target": generateTemplateValue(schemapb.DataType_Int64, int64(11)),
|
||||||
}},
|
}},
|
||||||
{`Int64Field * 3.5 <= {target}`, map[string]*schemapb.TemplateValue{
|
{`Int64Field * 3 <= {target}`, map[string]*schemapb.TemplateValue{
|
||||||
"target": generateTemplateValue(schemapb.DataType_Double, 11.5),
|
"target": generateTemplateValue(schemapb.DataType_Int64, int64(11)),
|
||||||
}},
|
}},
|
||||||
{`Int64Field / {offset} > 11.5`, map[string]*schemapb.TemplateValue{
|
{`Int64Field / {offset} > 11`, map[string]*schemapb.TemplateValue{
|
||||||
"offset": generateTemplateValue(schemapb.DataType_Double, 3.5),
|
"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{
|
{`ArrayField[0] % {offset} < 11`, map[string]*schemapb.TemplateValue{
|
||||||
"offset": generateTemplateValue(schemapb.DataType_Int64, int64(3)),
|
"offset": generateTemplateValue(schemapb.DataType_Int64, int64(3)),
|
||||||
|
|||||||
@ -274,8 +274,14 @@ func Power(a, b *planpb.GenericValue) *ExprWithType {
|
|||||||
} else {
|
} else {
|
||||||
// aInt && bInt
|
// aInt && bInt
|
||||||
// 2 ** (-1) = 0.5
|
// 2 ** (-1) = 0.5
|
||||||
ret.dataType = schemapb.DataType_Double
|
target := math.Pow(float64(a.GetInt64Val()), float64(b.GetInt64Val()))
|
||||||
ret.expr.GetValueExpr().Value = NewFloat(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(target)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|||||||
@ -215,8 +215,8 @@ func (v *ParserVisitor) VisitAddSub(ctx *parser.AddSubContext) interface{} {
|
|||||||
} else if rightExpr.expr.GetIsTemplate() {
|
} else if rightExpr.expr.GetIsTemplate() {
|
||||||
dataType = leftExpr.dataType
|
dataType = leftExpr.dataType
|
||||||
} else {
|
} else {
|
||||||
if !canArithmetic(leftExpr.dataType, getArrayElementType(leftExpr), rightExpr.dataType, getArrayElementType(rightExpr)) {
|
if err := canArithmetic(leftExpr.dataType, getArrayElementType(leftExpr), rightExpr.dataType, getArrayElementType(rightExpr), reverse); err != nil {
|
||||||
return fmt.Errorf("'%s' can only be used between integer or floating or json field expressions", arithNameMap[ctx.GetOp().GetTokenType()])
|
return fmt.Errorf("'%s' %s", arithNameMap[ctx.GetOp().GetTokenType()], err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
dataType, err = calcDataType(leftExpr, rightExpr, reverse)
|
dataType, err = calcDataType(leftExpr, rightExpr, reverse)
|
||||||
@ -305,8 +305,8 @@ func (v *ParserVisitor) VisitMulDivMod(ctx *parser.MulDivModContext) interface{}
|
|||||||
} else if rightExpr.expr.GetIsTemplate() {
|
} else if rightExpr.expr.GetIsTemplate() {
|
||||||
dataType = leftExpr.dataType
|
dataType = leftExpr.dataType
|
||||||
} else {
|
} else {
|
||||||
if !canArithmetic(leftExpr.dataType, getArrayElementType(leftExpr), rightExpr.dataType, getArrayElementType(rightExpr)) {
|
if err := canArithmetic(leftExpr.dataType, getArrayElementType(leftExpr), rightExpr.dataType, getArrayElementType(rightExpr), reverse); err != nil {
|
||||||
return fmt.Errorf("'%s' can only be used between integer or floating or json field expressions", arithNameMap[ctx.GetOp().GetTokenType()])
|
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 {
|
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`
|
exprStr := `Int64Field + 1.1 == 2.1`
|
||||||
expr, err := ParseExpr(helper, exprStr, nil)
|
expr, err := ParseExpr(helper, exprStr, nil)
|
||||||
assert.NoError(t, err, exprStr)
|
assert.Error(t, err, exprStr)
|
||||||
assert.NotNil(t, expr, exprStr)
|
assert.Nil(t, expr, exprStr)
|
||||||
assert.NotNil(t, expr.GetBinaryArithOpEvalRangeExpr())
|
|
||||||
assert.NotNil(t, expr.GetBinaryArithOpEvalRangeExpr().GetRightOperand().GetFloatVal())
|
|
||||||
assert.NotNil(t, expr.GetBinaryArithOpEvalRangeExpr().GetValue().GetFloatVal())
|
|
||||||
|
|
||||||
exprStr = `FloatField +1 == 2`
|
exprStr = `FloatField +1 == 2`
|
||||||
expr, err = ParseExpr(helper, exprStr, nil)
|
expr, err = ParseExpr(helper, exprStr, nil)
|
||||||
@ -458,6 +455,8 @@ func TestExpr_BinaryArith(t *testing.T) {
|
|||||||
`ArrayField[0] % 19 >= 20`,
|
`ArrayField[0] % 19 >= 20`,
|
||||||
`JSONField + 15 == 16`,
|
`JSONField + 15 == 16`,
|
||||||
`15 + JSONField == 16`,
|
`15 + JSONField == 16`,
|
||||||
|
`Int64Field + (2**3) > 0`,
|
||||||
|
`1 + FloatField > 100`,
|
||||||
}
|
}
|
||||||
for _, exprStr := range exprStrs {
|
for _, exprStr := range exprStrs {
|
||||||
assertValidExpr(t, helper, exprStr)
|
assertValidExpr(t, helper, exprStr)
|
||||||
@ -467,6 +466,11 @@ func TestExpr_BinaryArith(t *testing.T) {
|
|||||||
unsupported := []string{
|
unsupported := []string{
|
||||||
`ArrayField + 15 == 16`,
|
`ArrayField + 15 == 16`,
|
||||||
`15 + ArrayField == 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 {
|
for _, exprStr := range unsupported {
|
||||||
assertInvalidExpr(t, helper, exprStr)
|
assertInvalidExpr(t, helper, exprStr)
|
||||||
@ -1520,7 +1524,7 @@ func TestRandomSampleWithFilter(t *testing.T) {
|
|||||||
`VarCharField IS NOT NULL && random_sample(0.01)`,
|
`VarCharField IS NOT NULL && random_sample(0.01)`,
|
||||||
`11.0 < DoubleField < 12.0 && random_sample(0.01)`,
|
`11.0 < DoubleField < 12.0 && random_sample(0.01)`,
|
||||||
`1 < JSONField < 3 && 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)`,
|
`Int64Field % 10 != 9 && random_sample(0.01)`,
|
||||||
`A * 15 > 16 && random_sample(0.01)`,
|
`A * 15 > 16 && random_sample(0.01)`,
|
||||||
`(Int16Field - 3 == 4) and (Int32Field * 5 != 6) && 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 {
|
func canArithmeticDataType(left, right schemapb.DataType) bool {
|
||||||
switch left {
|
switch left {
|
||||||
case schemapb.DataType_Int8, schemapb.DataType_Int16, schemapb.DataType_Int32, schemapb.DataType_Int64,
|
case schemapb.DataType_Int8, schemapb.DataType_Int16, schemapb.DataType_Int32, schemapb.DataType_Int64:
|
||||||
schemapb.DataType_Float, schemapb.DataType_Double:
|
return typeutil.IsIntegerType(right) || typeutil.IsJSONType(right)
|
||||||
|
case schemapb.DataType_Float, schemapb.DataType_Double:
|
||||||
return typeutil.IsArithmetic(right) || typeutil.IsJSONType(right)
|
return typeutil.IsArithmetic(right) || typeutil.IsJSONType(right)
|
||||||
case schemapb.DataType_JSON:
|
case schemapb.DataType_JSON:
|
||||||
return typeutil.IsArithmetic(right)
|
return typeutil.IsArithmetic(right)
|
||||||
@ -583,17 +584,20 @@ func canArithmeticDataType(left, right schemapb.DataType) bool {
|
|||||||
// return canArithmeticDataType(left.dataType, getArrayElementType(right))
|
// return canArithmeticDataType(left.dataType, getArrayElementType(right))
|
||||||
//}
|
//}
|
||||||
|
|
||||||
func canArithmetic(left, leftElement, right, rightElement schemapb.DataType) bool {
|
func canArithmetic(left, leftElement, right, rightElement schemapb.DataType, reverse bool) error {
|
||||||
if !typeutil.IsArrayType(left) && !typeutil.IsArrayType(right) {
|
|
||||||
return canArithmeticDataType(left, right)
|
|
||||||
}
|
|
||||||
if typeutil.IsArrayType(left) && typeutil.IsArrayType(right) {
|
|
||||||
return canArithmeticDataType(leftElement, rightElement)
|
|
||||||
}
|
|
||||||
if typeutil.IsArrayType(left) {
|
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 {
|
func canConvertToIntegerType(dataType, elementType schemapb.DataType) bool {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user