diff --git a/internal/proxy/task_insert_test.go b/internal/proxy/task_insert_test.go index 4ff99989bf..9fb2a5f962 100644 --- a/internal/proxy/task_insert_test.go +++ b/internal/proxy/task_insert_test.go @@ -31,7 +31,7 @@ func TestInsertTask_CheckAligned(t *testing.T) { err = case1.insertMsg.CheckAligned() assert.NoError(t, err) - // checkLengthOfFieldsData was already checked by TestInsertTask_checkLengthOfFieldsData + // fillFieldsDataBySchema was already checked by TestInsertTask_fillFieldsDataBySchema boolFieldSchema := &schemapb.FieldSchema{DataType: schemapb.DataType_Bool} int8FieldSchema := &schemapb.FieldSchema{DataType: schemapb.DataType_Int8} diff --git a/internal/proxy/task_upsert.go b/internal/proxy/task_upsert.go index b35b7f769b..6deca4f7f7 100644 --- a/internal/proxy/task_upsert.go +++ b/internal/proxy/task_upsert.go @@ -147,6 +147,7 @@ func (it *upsertTask) insertPreExecute(ctx context.Context) error { log.Error("valid partition name failed", zap.String("partition name", partitionTag), zap.Error(err)) return err } + rowNums := uint32(it.upsertMsg.InsertMsg.NRows()) // set upsertTask.insertRequest.rowIDs tr := timerecord.NewTimeRecorder("applyPK") diff --git a/internal/proxy/task_upsert_test.go b/internal/proxy/task_upsert_test.go index cd24ed662b..bf8909160a 100644 --- a/internal/proxy/task_upsert_test.go +++ b/internal/proxy/task_upsert_test.go @@ -59,7 +59,7 @@ func TestUpsertTask_CheckAligned(t *testing.T) { err = case1.upsertMsg.InsertMsg.CheckAligned() assert.NoError(t, err) - // checkLengthOfFieldsData was already checked by TestUpsertTask_checkLengthOfFieldsData + // fillFieldsDataBySchema was already checked by TestUpsertTask_fillFieldsDataBySchema boolFieldSchema := &schemapb.FieldSchema{DataType: schemapb.DataType_Bool} int8FieldSchema := &schemapb.FieldSchema{DataType: schemapb.DataType_Int8} diff --git a/internal/proxy/util.go b/internal/proxy/util.go index f31870ae38..336f741a64 100644 --- a/internal/proxy/util.go +++ b/internal/proxy/util.go @@ -892,16 +892,56 @@ func isPartitionLoaded(ctx context.Context, qc types.QueryCoord, collID int64, p return false, nil } -func checkLengthOfFieldsData(schema *schemapb.CollectionSchema, insertMsg *msgstream.InsertMsg) error { +func fillFieldsDataBySchema(schema *schemapb.CollectionSchema, insertMsg *msgstream.InsertMsg) error { neededFieldsNum := 0 - for _, field := range schema.Fields { - if !field.AutoID { + isPrimaryKeyNum := 0 + + var dataNameSet = typeutil.NewSet[string]() + + for _, data := range insertMsg.FieldsData { + dataNameSet.Insert(data.GetFieldName()) + } + + for _, fieldSchema := range schema.Fields { + if fieldSchema.AutoID && !fieldSchema.IsPrimaryKey { + log.Error("not primary key field, but set autoID true", zap.String("fieldSchemaName", fieldSchema.GetName())) + return merr.WrapErrParameterInvalid("only primary key field can set autoID true", "") + } + if fieldSchema.GetDefaultValue() != nil && fieldSchema.IsPrimaryKey { + return merr.WrapErrParameterInvalid("no default data", "", "pk field schema can not set default value") + } + if !fieldSchema.AutoID { neededFieldsNum++ } + // if has no field pass in, consider use default value + // so complete it with field schema + if _, ok := dataNameSet[fieldSchema.GetName()]; !ok { + // primary key can not use default value + if fieldSchema.IsPrimaryKey { + isPrimaryKeyNum++ + continue + } + dataToAppend := &schemapb.FieldData{ + Type: fieldSchema.GetDataType(), + FieldName: fieldSchema.GetName(), + } + insertMsg.FieldsData = append(insertMsg.FieldsData, dataToAppend) + } } - if len(insertMsg.FieldsData) < neededFieldsNum { - return merr.WrapErrParameterInvalid(neededFieldsNum, len(insertMsg.FieldsData), "the length of passed fields is less than needed") + if isPrimaryKeyNum > 1 { + log.Error("the number of passed primary key fields is more than 1", + zap.Int64("primaryKeyNum", int64(isPrimaryKeyNum)), + zap.String("CollectionSchemaName", schema.GetName())) + return merr.WrapErrParameterInvalid("0 or 1", fmt.Sprint(isPrimaryKeyNum), "the number of passed primary key fields is more than 1") + } + + if len(insertMsg.FieldsData) != neededFieldsNum { + log.Error("the length of passed fields is not equal to needed", + zap.Int("expectFieldNumber", neededFieldsNum), + zap.Int("passFieldNumber", len(insertMsg.FieldsData)), + zap.String("CollectionSchemaName", schema.GetName())) + return merr.WrapErrParameterInvalid(neededFieldsNum, len(insertMsg.FieldsData), "the length of passed fields is equal to needed") } return nil @@ -914,7 +954,7 @@ func checkPrimaryFieldData(schema *schemapb.CollectionSchema, result *milvuspb.M return nil, merr.WrapErrParameterInvalid("invalid num_rows", fmt.Sprint(rowNums), "num_rows should be greater than 0") } - if err := checkLengthOfFieldsData(schema, insertMsg); err != nil { + if err := fillFieldsDataBySchema(schema, insertMsg); err != nil { return nil, err } @@ -1084,3 +1124,12 @@ func getPartitionProgress( return } + +func memsetLoop[T any](v T, numRows int) []T { + ret := make([]T, 0, numRows) + for i := 0; i < numRows; i++ { + ret = append(ret, v) + } + + return ret +} diff --git a/internal/proxy/util_test.go b/internal/proxy/util_test.go index 7f92099b94..e06d4f4497 100644 --- a/internal/proxy/util_test.go +++ b/internal/proxy/util_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/cockroachdb/errors" + "github.com/milvus-io/milvus/pkg/util/merr" "github.com/milvus-io/milvus/pkg/util/tsoutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -1002,14 +1003,14 @@ func Test_isPartitionIsLoaded(t *testing.T) { }) } -func Test_InsertTaskCheckLengthOfFieldsData(t *testing.T) { +func Test_InsertTaskfillFieldsDataBySchema(t *testing.T) { var err error // schema is empty, though won't happen in system case1 := insertTask{ schema: &schemapb.CollectionSchema{ - Name: "TestInsertTask_checkLengthOfFieldsData", - Description: "TestInsertTask_checkLengthOfFieldsData", + Name: "TestInsertTask_fillFieldsDataBySchema", + Description: "TestInsertTask_fillFieldsDataBySchema", AutoID: false, Fields: []*schemapb.FieldSchema{}, }, @@ -1018,28 +1019,30 @@ func Test_InsertTaskCheckLengthOfFieldsData(t *testing.T) { Base: &commonpb.MsgBase{ MsgType: commonpb.MsgType_Insert, }, - DbName: "TestInsertTask_checkLengthOfFieldsData", - CollectionName: "TestInsertTask_checkLengthOfFieldsData", - PartitionName: "TestInsertTask_checkLengthOfFieldsData", + DbName: "TestInsertTask_fillFieldsDataBySchema", + CollectionName: "TestInsertTask_fillFieldsDataBySchema", + PartitionName: "TestInsertTask_fillFieldsDataBySchema", }, }, } - err = checkLengthOfFieldsData(case1.schema, case1.insertMsg) + err = fillFieldsDataBySchema(case1.schema, case1.insertMsg) assert.Equal(t, nil, err) - // schema has two fields, neither of them are autoID + // schema has two fields, msg has no field. fields will be filled in case2 := insertTask{ schema: &schemapb.CollectionSchema{ - Name: "TestInsertTask_checkLengthOfFieldsData", - Description: "TestInsertTask_checkLengthOfFieldsData", + Name: "TestInsertTask_fillFieldsDataBySchema", + Description: "TestInsertTask_fillFieldsDataBySchema", AutoID: false, Fields: []*schemapb.FieldSchema{ { + Name: "a", AutoID: false, DataType: schemapb.DataType_Int64, }, { + Name: "b", AutoID: false, DataType: schemapb.DataType_Int64, }, @@ -1053,50 +1056,26 @@ func Test_InsertTaskCheckLengthOfFieldsData(t *testing.T) { }, }, } - // passed fields is empty - // case2.BaseInsertTask = BaseInsertTask{ - // InsertRequest: msgpb.InsertRequest{ - // Base: &commonpb.MsgBase{ - // MsgType: commonpb.MsgType_Insert, - // MsgID: 0, - // SourceID: paramtable.GetNodeID(), - // }, - // }, - // } - err = checkLengthOfFieldsData(case2.schema, case2.insertMsg) - assert.NotEqual(t, nil, err) - // the num of passed fields is less than needed - case2.insertMsg.FieldsData = []*schemapb.FieldData{ - { - Type: schemapb.DataType_Int64, - }, - } - err = checkLengthOfFieldsData(case2.schema, case2.insertMsg) - assert.NotEqual(t, nil, err) - // satisfied - case2.insertMsg.FieldsData = []*schemapb.FieldData{ - { - Type: schemapb.DataType_Int64, - }, - { - Type: schemapb.DataType_Int64, - }, - } - err = checkLengthOfFieldsData(case2.schema, case2.insertMsg) - assert.Equal(t, nil, err) - // schema has two field, one of them are autoID + err = fillFieldsDataBySchema(case2.schema, case2.insertMsg) + assert.Equal(t, nil, err) + assert.Equal(t, len(case2.insertMsg.FieldsData), 2) + + // schema has a pk can't fill in, and another can. case3 := insertTask{ schema: &schemapb.CollectionSchema{ - Name: "TestInsertTask_checkLengthOfFieldsData", - Description: "TestInsertTask_checkLengthOfFieldsData", + Name: "TestInsertTask_fillFieldsDataBySchema", + Description: "TestInsertTask_fillFieldsDataBySchema", AutoID: false, Fields: []*schemapb.FieldSchema{ { - AutoID: true, - DataType: schemapb.DataType_Int64, + Name: "a", + AutoID: true, + IsPrimaryKey: true, + DataType: schemapb.DataType_Int64, }, { + Name: "b", AutoID: false, DataType: schemapb.DataType_Int64, }, @@ -1110,28 +1089,28 @@ func Test_InsertTaskCheckLengthOfFieldsData(t *testing.T) { }, }, } - // passed fields is empty - // case3.req = &milvuspb.InsertRequest{} - err = checkLengthOfFieldsData(case3.schema, case3.insertMsg) - assert.NotEqual(t, nil, err) - // satisfied - case3.insertMsg.FieldsData = []*schemapb.FieldData{ - { - Type: schemapb.DataType_Int64, - }, - } - err = checkLengthOfFieldsData(case3.schema, case3.insertMsg) - assert.Equal(t, nil, err) - // schema has one field which is autoID + err = fillFieldsDataBySchema(case3.schema, case3.insertMsg) + assert.Equal(t, nil, err) + assert.Equal(t, len(case3.insertMsg.FieldsData), 1) + + // schema has a pk can't fill in, and another can, but pk autoid == false + // means that data pass less case4 := insertTask{ schema: &schemapb.CollectionSchema{ - Name: "TestInsertTask_checkLengthOfFieldsData", - Description: "TestInsertTask_checkLengthOfFieldsData", + Name: "TestInsertTask_fillFieldsDataBySchema", + Description: "TestInsertTask_fillFieldsDataBySchema", AutoID: false, Fields: []*schemapb.FieldSchema{ { - AutoID: true, + Name: "a", + AutoID: false, + IsPrimaryKey: true, + DataType: schemapb.DataType_Int64, + }, + { + Name: "b", + AutoID: false, DataType: schemapb.DataType_Int64, }, }, @@ -1144,11 +1123,150 @@ func Test_InsertTaskCheckLengthOfFieldsData(t *testing.T) { }, }, } - // passed fields is empty - // satisfied - // case4.req = &milvuspb.InsertRequest{} - err = checkLengthOfFieldsData(case4.schema, case4.insertMsg) - assert.Equal(t, nil, err) + + err = fillFieldsDataBySchema(case4.schema, case4.insertMsg) + assert.ErrorIs(t, merr.ErrParameterInvalid, err) + assert.Equal(t, len(case4.insertMsg.FieldsData), 1) + + // pass more data field + case5 := insertTask{ + schema: &schemapb.CollectionSchema{ + Name: "TestInsertTask_fillFieldsDataBySchema", + Description: "TestInsertTask_fillFieldsDataBySchema", + AutoID: false, + Fields: []*schemapb.FieldSchema{ + { + Name: "a", + AutoID: false, + IsPrimaryKey: false, + DataType: schemapb.DataType_Int64, + }, + { + Name: "b", + AutoID: false, + DataType: schemapb.DataType_Int64, + }, + }, + }, + insertMsg: &BaseInsertTask{ + InsertRequest: msgpb.InsertRequest{ + Base: &commonpb.MsgBase{ + MsgType: commonpb.MsgType_Insert, + }, + FieldsData: []*schemapb.FieldData{ + { + FieldName: "c", + Type: schemapb.DataType_Int64, + }, + }, + }, + }, + } + + err = fillFieldsDataBySchema(case5.schema, case5.insertMsg) + assert.ErrorIs(t, merr.ErrParameterInvalid, err) + assert.Equal(t, len(case5.insertMsg.FieldsData), 3) + + // not pk, but autoid == true + case6 := insertTask{ + schema: &schemapb.CollectionSchema{ + Name: "TestInsertTask_fillFieldsDataBySchema", + Description: "TestInsertTask_fillFieldsDataBySchema", + AutoID: false, + Fields: []*schemapb.FieldSchema{ + { + Name: "a", + AutoID: false, + IsPrimaryKey: true, + DataType: schemapb.DataType_Int64, + }, + { + Name: "b", + AutoID: true, + IsPrimaryKey: false, + DataType: schemapb.DataType_Int64, + }, + }, + }, + insertMsg: &BaseInsertTask{ + InsertRequest: msgpb.InsertRequest{ + Base: &commonpb.MsgBase{ + MsgType: commonpb.MsgType_Insert, + }, + }, + }, + } + + err = fillFieldsDataBySchema(case6.schema, case6.insertMsg) + assert.ErrorIs(t, merr.ErrParameterInvalid, err) + assert.Equal(t, len(case6.insertMsg.FieldsData), 0) + + // more than one pk + case7 := insertTask{ + schema: &schemapb.CollectionSchema{ + Name: "TestInsertTask_fillFieldsDataBySchema", + Description: "TestInsertTask_fillFieldsDataBySchema", + AutoID: false, + Fields: []*schemapb.FieldSchema{ + { + Name: "a", + AutoID: false, + IsPrimaryKey: true, + DataType: schemapb.DataType_Int64, + }, + { + Name: "b", + AutoID: false, + IsPrimaryKey: true, + DataType: schemapb.DataType_Int64, + }, + }, + }, + insertMsg: &BaseInsertTask{ + InsertRequest: msgpb.InsertRequest{ + Base: &commonpb.MsgBase{ + MsgType: commonpb.MsgType_Insert, + }, + }, + }, + } + + err = fillFieldsDataBySchema(case7.schema, case7.insertMsg) + assert.ErrorIs(t, merr.ErrParameterInvalid, err) + assert.Equal(t, len(case7.insertMsg.FieldsData), 0) + + // pk can not set default value + case8 := insertTask{ + schema: &schemapb.CollectionSchema{ + Name: "TestInsertTask_fillFieldsDataBySchema", + Description: "TestInsertTask_fillFieldsDataBySchema", + AutoID: false, + Fields: []*schemapb.FieldSchema{ + { + Name: "a", + AutoID: false, + IsPrimaryKey: true, + DataType: schemapb.DataType_Int64, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_LongData{ + LongData: 1, + }, + }, + }, + }, + }, + insertMsg: &BaseInsertTask{ + InsertRequest: msgpb.InsertRequest{ + Base: &commonpb.MsgBase{ + MsgType: commonpb.MsgType_Insert, + }, + }, + }, + } + + err = fillFieldsDataBySchema(case8.schema, case8.insertMsg) + assert.ErrorIs(t, merr.ErrParameterInvalid, err) + assert.Equal(t, len(case8.insertMsg.FieldsData), 0) } func Test_InsertTaskCheckPrimaryFieldData(t *testing.T) { @@ -1470,8 +1588,8 @@ func Test_UpsertTaskCheckPrimaryFieldData(t *testing.T) { }, FieldsData: []*schemapb.FieldData{ { - Type: schemapb.DataType_Int64, - FieldName: "int64Field", + Type: schemapb.DataType_Float, + FieldName: "floatField", }, }, }, diff --git a/internal/proxy/validate_util.go b/internal/proxy/validate_util.go index 6ba3995257..9a197b94a3 100644 --- a/internal/proxy/validate_util.go +++ b/internal/proxy/validate_util.go @@ -4,10 +4,12 @@ import ( "fmt" "github.com/milvus-io/milvus-proto/go-api/schemapb" + "github.com/milvus-io/milvus/pkg/log" "github.com/milvus-io/milvus/pkg/util/funcutil" "github.com/milvus-io/milvus/pkg/util/merr" "github.com/milvus-io/milvus/pkg/util/paramtable" "github.com/milvus-io/milvus/pkg/util/typeutil" + "go.uber.org/zap" ) type validateUtil struct { @@ -41,6 +43,11 @@ func (v *validateUtil) Validate(data []*schemapb.FieldData, schema *schemapb.Col return err } + err = v.fillWithDefaultValue(data, helper, numRows) + if err != nil { + return err + } + if err := v.checkAligned(data, helper, numRows); err != nil { return err } @@ -139,6 +146,82 @@ func (v *validateUtil) checkAligned(data []*schemapb.FieldData, schema *typeutil return nil } +func (v *validateUtil) fillWithDefaultValue(data []*schemapb.FieldData, schema *typeutil.SchemaHelper, numRows uint64) error { + for _, field := range data { + fieldSchema, err := schema.GetFieldFromName(field.GetFieldName()) + if err != nil { + return err + } + + // if default value is not set, continue + // compatible with 2.2.x + if fieldSchema.GetDefaultValue() == nil { + continue + } + + switch field.Field.(type) { + case *schemapb.FieldData_Scalars: + switch sd := field.GetScalars().GetData().(type) { + case *schemapb.ScalarField_BoolData: + if len(sd.BoolData.Data) == 0 { + defaultValue := fieldSchema.GetDefaultValue().GetBoolData() + sd.BoolData.Data = memsetLoop(defaultValue, int(numRows)) + } + + case *schemapb.ScalarField_IntData: + if len(sd.IntData.Data) == 0 { + defaultValue := fieldSchema.GetDefaultValue().GetIntData() + sd.IntData.Data = memsetLoop(defaultValue, int(numRows)) + } + + case *schemapb.ScalarField_LongData: + if len(sd.LongData.Data) == 0 { + defaultValue := fieldSchema.GetDefaultValue().GetLongData() + sd.LongData.Data = memsetLoop(defaultValue, int(numRows)) + } + + case *schemapb.ScalarField_FloatData: + if len(sd.FloatData.Data) == 0 { + defaultValue := fieldSchema.GetDefaultValue().GetFloatData() + sd.FloatData.Data = memsetLoop(defaultValue, int(numRows)) + } + + case *schemapb.ScalarField_DoubleData: + if len(sd.DoubleData.Data) == 0 { + defaultValue := fieldSchema.GetDefaultValue().GetDoubleData() + sd.DoubleData.Data = memsetLoop(defaultValue, int(numRows)) + } + + case *schemapb.ScalarField_StringData: + if len(sd.StringData.Data) == 0 { + defaultValue := fieldSchema.GetDefaultValue().GetStringData() + sd.StringData.Data = memsetLoop(defaultValue, int(numRows)) + } + + case *schemapb.ScalarField_ArrayData: + log.Error("array type not support default value", zap.String("fieldSchemaName", field.GetFieldName())) + return merr.WrapErrParameterInvalid("not set default value", "", "array type not support default value") + + case *schemapb.ScalarField_JsonData: + log.Error("json type not support default value", zap.String("fieldSchemaName", field.GetFieldName())) + return merr.WrapErrParameterInvalid("not set default value", "", "json type not support default value") + + default: + panic("undefined data type " + field.Type.String()) + } + + case *schemapb.FieldData_Vectors: + log.Error("vectors not support default value", zap.String("fieldSchemaName", field.GetFieldName())) + return merr.WrapErrParameterInvalid("not set default value", "", "json type not support default value") + + default: + panic("undefined data type " + field.Type.String()) + } + } + + return nil +} + func (v *validateUtil) checkFloatVectorFieldData(field *schemapb.FieldData, fieldSchema *schemapb.FieldSchema) error { floatArray := field.GetVectors().GetFloatVector().GetData() if floatArray == nil { diff --git a/internal/proxy/validate_util_test.go b/internal/proxy/validate_util_test.go index 6dc666caa9..8b3c19cea8 100644 --- a/internal/proxy/validate_util_test.go +++ b/internal/proxy/validate_util_test.go @@ -956,3 +956,881 @@ func Test_validateUtil_Validate(t *testing.T) { assert.NoError(t, err) }) } + +func checkFillWithDefaultValueData[T comparable](values []T, v T, length int) bool { + if len(values) != length { + return false + } + for i := 0; i < length; i++ { + if values[i] != v { + return false + } + } + + return true +} + +func Test_validateUtil_fillWithDefaultValue(t *testing.T) { + t.Run("bool scalars schema not found", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Bool, + }, + } + + schema := &schemapb.CollectionSchema{} + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 1) + + assert.Error(t, err) + }) + + t.Run("bool scalars has no data, and schema default value is legal", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Bool, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_BoolData{ + BoolData: &schemapb.BoolArray{ + Data: []bool{}, + }, + }, + }, + }, + }, + } + + var key bool + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_BinaryVector, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_BoolData{ + BoolData: key, + }, + }, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetBoolData().Data, schema.Fields[0].GetDefaultValue().GetBoolData(), 10) + assert.True(t, flag) + }) + + t.Run("bool scalars has data, and schema default value is not set", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Bool, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_BoolData{ + BoolData: &schemapb.BoolArray{ + Data: []bool{true}, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_BinaryVector, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + }) + + t.Run("bool scalars has data, and schema default value is legal", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Bool, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_BoolData{ + BoolData: &schemapb.BoolArray{ + Data: []bool{true}, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_BinaryVector, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_BoolData{ + BoolData: false, + }, + }, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetBoolData().Data, true, 1) + assert.True(t, flag) + }) + + //////////////////////////////////////////////////////////////////// + + t.Run("int scalars schema not found", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Int32, + }, + } + + schema := &schemapb.CollectionSchema{} + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 1) + + assert.Error(t, err) + }) + + t.Run("int scalars has no data, and schema default value is legal", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Int32, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_IntData{ + IntData: &schemapb.IntArray{ + Data: []int32{}, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_Int32, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_IntData{ + IntData: 1, + }, + }, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetIntData().Data, schema.Fields[0].GetDefaultValue().GetIntData(), 10) + assert.True(t, flag) + }) + + t.Run("int scalars has data, and schema default value is not set", func(t *testing.T) { + intData := []int32{1} + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Int32, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_IntData{ + IntData: &schemapb.IntArray{ + Data: intData, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_Int32, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + }) + + t.Run("int scalars has data, and schema default value is legal", func(t *testing.T) { + intData := []int32{1} + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Int32, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_IntData{ + IntData: &schemapb.IntArray{ + Data: intData, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_Int32, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_IntData{ + IntData: 2, + }, + }, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetIntData().Data, intData[0], 1) + assert.True(t, flag) + }) + //////////////////////////////////////////////////////////////////// + + t.Run("long scalars schema not found", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Int64, + }, + } + + schema := &schemapb.CollectionSchema{} + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 1) + + assert.Error(t, err) + }) + + t.Run("long scalars has no data, and schema default value is legal", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Int64, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_LongData{ + LongData: &schemapb.LongArray{ + Data: []int64{}, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_Int32, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_LongData{ + LongData: 1, + }, + }, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetLongData().Data, schema.Fields[0].GetDefaultValue().GetLongData(), 10) + assert.True(t, flag) + }) + + t.Run("long scalars has data, and schema default value is not set", func(t *testing.T) { + longData := []int64{1} + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Int64, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_LongData{ + LongData: &schemapb.LongArray{ + Data: longData, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_Int64, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + }) + + t.Run("long scalars has data, and schema default value is legal", func(t *testing.T) { + longData := []int64{1} + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Int64, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_LongData{ + LongData: &schemapb.LongArray{ + Data: longData, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_Int64, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_LongData{ + LongData: 2, + }, + }, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetLongData().Data, longData[0], 1) + assert.True(t, flag) + }) + + //////////////////////////////////////////////////////////////////// + + t.Run("float scalars schema not found", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Float, + }, + } + + schema := &schemapb.CollectionSchema{} + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 1) + + assert.Error(t, err) + }) + + t.Run("float scalars has no data, and schema default value is legal", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Float, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_FloatData{ + FloatData: &schemapb.FloatArray{ + Data: []float32{}, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_Float, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_FloatData{ + FloatData: 1, + }, + }, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetFloatData().Data, schema.Fields[0].GetDefaultValue().GetFloatData(), 10) + assert.True(t, flag) + }) + + t.Run("float scalars has data, and schema default value is not set", func(t *testing.T) { + floatData := []float32{1} + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Float, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_FloatData{ + FloatData: &schemapb.FloatArray{ + Data: floatData, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_Float, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + }) + + t.Run("float scalars has data, and schema default value is legal", func(t *testing.T) { + floatData := []float32{1} + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Float, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_FloatData{ + FloatData: &schemapb.FloatArray{ + Data: floatData, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_Float, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_FloatData{ + FloatData: 2, + }, + }, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetFloatData().Data, floatData[0], 1) + assert.True(t, flag) + }) + + //////////////////////////////////////////////////////////////////// + + t.Run("double scalars schema not found", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Double, + }, + } + + schema := &schemapb.CollectionSchema{} + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 1) + + assert.Error(t, err) + }) + + t.Run("double scalars has no data, and schema default value is legal", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Double, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_DoubleData{ + DoubleData: &schemapb.DoubleArray{ + Data: []float64{}, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_Double, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_DoubleData{ + DoubleData: 1, + }, + }, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetDoubleData().Data, schema.Fields[0].GetDefaultValue().GetDoubleData(), 10) + assert.True(t, flag) + }) + + t.Run("double scalars has data, and schema default value is not set", func(t *testing.T) { + doubleData := []float64{1} + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Double, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_DoubleData{ + DoubleData: &schemapb.DoubleArray{ + Data: doubleData, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_Double, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + }) + + t.Run("double scalars has data, and schema default value is legal", func(t *testing.T) { + doubleData := []float64{1} + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_Double, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_DoubleData{ + DoubleData: &schemapb.DoubleArray{ + Data: doubleData, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_Double, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_DoubleData{ + DoubleData: 2, + }, + }, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetDoubleData().Data, doubleData[0], 1) + assert.True(t, flag) + }) + + ////////////////////////////////////////////////////////////////// + + t.Run("string scalars schema not found", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_VarChar, + }, + } + + schema := &schemapb.CollectionSchema{} + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 1) + + assert.Error(t, err) + }) + + t.Run("string scalars has no data, and schema default value is legal", func(t *testing.T) { + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_VarChar, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_StringData{ + StringData: &schemapb.StringArray{ + Data: []string{}, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_VarChar, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_StringData{ + StringData: "b", + }, + }, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetStringData().Data, schema.Fields[0].GetDefaultValue().GetStringData(), 10) + assert.True(t, flag) + }) + + t.Run("string scalars has data, and schema default value is legal", func(t *testing.T) { + stringData := []string{"a"} + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_VarChar, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_StringData{ + StringData: &schemapb.StringArray{ + Data: stringData, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_VarChar, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_StringData{ + StringData: "b", + }, + }, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetStringData().Data, stringData[0], 1) + assert.True(t, flag) + }) + + t.Run("string scalars has data, and schema default value is not set", func(t *testing.T) { + stringData := []string{"a"} + data := []*schemapb.FieldData{ + { + FieldName: "test", + Type: schemapb.DataType_VarChar, + Field: &schemapb.FieldData_Scalars{ + Scalars: &schemapb.ScalarField{ + Data: &schemapb.ScalarField_StringData{ + StringData: &schemapb.StringArray{ + Data: stringData, + }, + }, + }, + }, + }, + } + + schema := &schemapb.CollectionSchema{ + Fields: []*schemapb.FieldSchema{ + { + Name: "test", + DataType: schemapb.DataType_VarChar, + }, + }, + } + h, err := typeutil.CreateSchemaHelper(schema) + assert.NoError(t, err) + + v := newValidateUtil() + + err = v.fillWithDefaultValue(data, h, 10) + + assert.NoError(t, err) + + flag := checkFillWithDefaultValueData(data[0].GetScalars().GetStringData().Data, stringData[0], 1) + assert.True(t, flag) + }) + +} diff --git a/internal/rootcoord/create_collection_task.go b/internal/rootcoord/create_collection_task.go index 9ef9679861..e5f5603531 100644 --- a/internal/rootcoord/create_collection_task.go +++ b/internal/rootcoord/create_collection_task.go @@ -19,6 +19,7 @@ package rootcoord import ( "context" "fmt" + "math" "github.com/cockroachdb/errors" "github.com/golang/protobuf/proto" @@ -77,6 +78,56 @@ func (t *createCollectionTask) validate() error { return nil } +func defaultValueTypeMatch(schema *schemapb.CollectionSchema) error { + for _, fieldSchema := range schema.Fields { + if fieldSchema.GetDefaultValue() != nil { + switch fieldSchema.GetDefaultValue().Data.(type) { + case *schemapb.ValueField_BoolData: + if fieldSchema.GetDataType() != schemapb.DataType_Bool { + return merr.WrapErrParameterInvalid("DataType_Bool", "not match", "default value type mismatches field schema type") + } + case *schemapb.ValueField_IntData: + if fieldSchema.GetDataType() != schemapb.DataType_Int32 && + fieldSchema.GetDataType() != schemapb.DataType_Int16 && + fieldSchema.GetDataType() != schemapb.DataType_Int8 { + return merr.WrapErrParameterInvalid("DataType_Int", "not match", "default value type mismatches field schema type") + } + defaultValue := fieldSchema.GetDefaultValue().GetIntData() + if fieldSchema.GetDataType() == schemapb.DataType_Int16 { + if defaultValue > math.MaxInt16 || defaultValue < math.MinInt16 { + return merr.WrapErrParameterInvalidRange(math.MinInt16, math.MaxInt16, defaultValue, "default value out of range") + } + } + if fieldSchema.GetDataType() == schemapb.DataType_Int8 { + if defaultValue > math.MaxInt8 || defaultValue < math.MinInt8 { + return merr.WrapErrParameterInvalidRange(math.MinInt8, math.MaxInt8, defaultValue, "default value out of range") + } + } + case *schemapb.ValueField_LongData: + if fieldSchema.GetDataType() != schemapb.DataType_Int64 { + return merr.WrapErrParameterInvalid("DataType_Int64", "not match", "default value type mismatches field schema type") + } + case *schemapb.ValueField_FloatData: + if fieldSchema.GetDataType() != schemapb.DataType_Float { + return merr.WrapErrParameterInvalid("DataType_Float", "not match", "default value type mismatches field schema type") + } + case *schemapb.ValueField_DoubleData: + if fieldSchema.GetDataType() != schemapb.DataType_Double { + return merr.WrapErrParameterInvalid("DataType_Double", "not match", "default value type mismatches field schema type") + } + case *schemapb.ValueField_StringData: + if fieldSchema.GetDataType() != schemapb.DataType_VarChar { + return merr.WrapErrParameterInvalid("DataType_VarChar", "not match", "default value type mismatches field schema type") + } + default: + panic("default value unsupport data type") + } + } + } + + return nil +} + func hasSystemFields(schema *schemapb.CollectionSchema, systemFields []string) bool { for _, f := range schema.GetFields() { if funcutil.SliceContain(systemFields, f.GetName()) { @@ -87,11 +138,23 @@ func hasSystemFields(schema *schemapb.CollectionSchema, systemFields []string) b } func (t *createCollectionTask) validateSchema(schema *schemapb.CollectionSchema) error { + log.With(zap.String("CollectionName", t.Req.CollectionName)) if t.Req.GetCollectionName() != schema.GetName() { - return fmt.Errorf("collection name = %s, schema.Name=%s", t.Req.GetCollectionName(), schema.Name) + log.Error("collection name not matches schema name", zap.String("SchemaName", schema.Name)) + msg := fmt.Sprintf("collection name = %s, schema.Name=%s", t.Req.GetCollectionName(), schema.Name) + return merr.WrapErrParameterInvalid("collection name matches schema name", "don't match", msg) } + + err := defaultValueTypeMatch(schema) + if err != nil { + log.Error("default value type mismatch field schema type") + return err + } + if hasSystemFields(schema, []string{RowIDFieldName, TimeStampFieldName}) { - return fmt.Errorf("schema contains system field: %s, %s", RowIDFieldName, TimeStampFieldName) + log.Error("schema contains system field", zap.String("RowIDFieldName", RowIDFieldName), zap.String("TimeStampFieldName", TimeStampFieldName)) + msg := fmt.Sprintf("schema contains system field: %s, %s", RowIDFieldName, TimeStampFieldName) + return merr.WrapErrParameterInvalid("schema don't contains system field", "contains", msg) } return nil } diff --git a/internal/rootcoord/create_collection_task_test.go b/internal/rootcoord/create_collection_task_test.go index a79b3e760d..fc02158d62 100644 --- a/internal/rootcoord/create_collection_task_test.go +++ b/internal/rootcoord/create_collection_task_test.go @@ -18,6 +18,7 @@ package rootcoord import ( "context" + "math" "testing" "time" @@ -128,6 +129,143 @@ func Test_createCollectionTask_validateSchema(t *testing.T) { assert.Error(t, err) }) + t.Run("default value type mismatch", func(t *testing.T) { + collectionName := funcutil.GenRandomStr() + task := createCollectionTask{ + Req: &milvuspb.CreateCollectionRequest{ + Base: &commonpb.MsgBase{MsgType: commonpb.MsgType_CreateCollection}, + CollectionName: collectionName, + }, + } + schema1 := &schemapb.CollectionSchema{ + Name: collectionName, + Fields: []*schemapb.FieldSchema{ + { + DataType: schemapb.DataType_BinaryVector, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_BoolData{ + BoolData: false, + }, + }, + }, + }, + } + err1 := task.validateSchema(schema1) + assert.ErrorIs(t, err1, merr.ErrParameterInvalid) + + schema2 := &schemapb.CollectionSchema{ + Name: collectionName, + Fields: []*schemapb.FieldSchema{ + { + DataType: schemapb.DataType_BinaryVector, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_IntData{ + IntData: 1, + }, + }, + }, + }, + } + err2 := task.validateSchema(schema2) + assert.ErrorIs(t, err2, merr.ErrParameterInvalid) + + schema3 := &schemapb.CollectionSchema{ + Name: collectionName, + Fields: []*schemapb.FieldSchema{ + { + DataType: schemapb.DataType_BinaryVector, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_LongData{ + LongData: 1, + }, + }, + }, + }, + } + err3 := task.validateSchema(schema3) + assert.ErrorIs(t, err3, merr.ErrParameterInvalid) + + schema4 := &schemapb.CollectionSchema{ + Name: collectionName, + Fields: []*schemapb.FieldSchema{ + { + DataType: schemapb.DataType_BinaryVector, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_FloatData{ + FloatData: 1, + }, + }, + }, + }, + } + err4 := task.validateSchema(schema4) + assert.ErrorIs(t, err4, merr.ErrParameterInvalid) + + schema5 := &schemapb.CollectionSchema{ + Name: collectionName, + Fields: []*schemapb.FieldSchema{ + { + DataType: schemapb.DataType_BinaryVector, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_DoubleData{ + DoubleData: 1, + }, + }, + }, + }, + } + err5 := task.validateSchema(schema5) + assert.ErrorIs(t, err5, merr.ErrParameterInvalid) + + schema6 := &schemapb.CollectionSchema{ + Name: collectionName, + Fields: []*schemapb.FieldSchema{ + { + DataType: schemapb.DataType_BinaryVector, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_StringData{ + StringData: "a", + }, + }, + }, + }, + } + err6 := task.validateSchema(schema6) + assert.ErrorIs(t, err6, merr.ErrParameterInvalid) + + schema7 := &schemapb.CollectionSchema{ + Name: collectionName, + Fields: []*schemapb.FieldSchema{ + { + DataType: schemapb.DataType_Int16, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_IntData{ + IntData: math.MaxInt32, + }, + }, + }, + }, + } + err7 := task.validateSchema(schema7) + assert.ErrorIs(t, err7, merr.ErrParameterInvalid) + + schema8 := &schemapb.CollectionSchema{ + Name: collectionName, + Fields: []*schemapb.FieldSchema{ + { + DataType: schemapb.DataType_Int8, + DefaultValue: &schemapb.ValueField{ + Data: &schemapb.ValueField_IntData{ + IntData: math.MaxInt32, + }, + }, + }, + }, + } + err8 := task.validateSchema(schema8) + assert.ErrorIs(t, err8, merr.ErrParameterInvalid) + }) + t.Run("normal case", func(t *testing.T) { collectionName := funcutil.GenRandomStr() task := createCollectionTask{