Repository: milvus-io/milvus
File: internal/proxy/task_upsert.go (Go)

Code before:
	sliceIndex := make([]uint32, rowNums)
	for i := uint32(0); i < rowNums; i++ {
		sliceIndex[i] = i
	}
	it.result.SuccIndex = sliceIndex

	if it.schema.EnableDynamicField {
		if it.req.GetPartialUpdate() {
			// For partial update, ensure $meta field exists but skip static field
			// name validation. Merged data from queryPreExecute may contain $meta
			// keys matching static field names due to schema evolution — this is
			// legitimate historical data that should be preserved.
			hasDynamic := false
			for _, data := range it.upsertMsg.InsertMsg.FieldsData {
				if data.IsDynamic {
					data.FieldName = common.MetaFieldName
					hasDynamic = true
					break
				}
			}
			if !hasDynamic {
				defaultData := make([][]byte, it.upsertMsg.InsertMsg.NRows())
				for i := range defaultData {
					defaultData[i] = []byte("{}")
				}
				dynamicData := autoGenDynamicFieldData(defaultData)
				it.upsertMsg.InsertMsg.FieldsData = append(it.upsertMsg.InsertMsg.FieldsData, dynamicData)
			}
		} else {
			err := checkDynamicFieldData(it.schema.CollectionSchema, it.upsertMsg.InsertMsg)
			if err != nil {
				return err
			}
		}
	}

	if Params.CommonCfg.EnableNamespace.GetAsBool() {
		err := addNamespaceData(it.schema.CollectionSchema, it.upsertMsg.InsertMsg)
		if err != nil {
			return err
		}
	}

	if err := checkAndFlattenStructFieldData(it.schema.CollectionSchema, it.upsertMsg.InsertMsg); err != nil {
		return err
	}

	allFields := typeutil.GetAllFieldSchemas(it.schema.CollectionSchema)

	// use the passed pk as new pk when autoID == false
	// automatic generate pk as new pk wehen autoID == true

Review comment (suggestion):
if $meta field include 3 field `dfA, dfB, dfC`, and we also have a static field dfA, the above logic will override the whole $meta field vlaue, but the expected behavior should be just remove dfA's value from $meta

Code after:
	sliceIndex := make([]uint32, rowNums)
	for i := uint32(0); i < rowNums; i++ {
		sliceIndex[i] = i
	}
	it.result.SuccIndex = sliceIndex

	if it.schema.EnableDynamicField {
		var err error
		if it.req.GetPartialUpdate() {
			err = checkDynamicFieldDataForPartialUpdate(it.schema.CollectionSchema, it.upsertMsg.InsertMsg)
		} else {
			err = checkDynamicFieldData(it.schema.CollectionSchema, it.upsertMsg.InsertMsg)
		}
		if err != nil {
			return err
		}
	}

	if Params.CommonCfg.EnableNamespace.GetAsBool() {
		err := addNamespaceData(it.schema.CollectionSchema, it.upsertMsg.InsertMsg)
		if err != nil {
			return err
		}
	}

	if err := checkAndFlattenStructFieldData(it.schema.CollectionSchema, it.upsertMsg.InsertMsg); err != nil {
		return err
	}

	allFields := typeutil.GetAllFieldSchemas(it.schema.CollectionSchema)

	// use the passed pk as new pk when autoID == false
	// automatic generate pk as new pk wehen autoID == true
	var err error
	it.result.IDs, it.oldIDs, err = checkUpsertPrimaryFieldData(allFields, it.schema.CollectionSchema, it.upsertMsg.InsertMsg)
	log := log.Ctx(ctx).With(zap.String("collectionName", it.upsertMsg.InsertMsg.CollectionName))
	if err != nil {
		log.Warn("check primary field data and hash primary key failed when upsert",
			zap.Error(err))
		return merr.WrapErrAsInputErrorWhen(err, merr.ErrParameterInvalid)
	}

	// check varchar/text with analyzer was utf-8 format
	err = checkInputUtf8Compatiable(allFields, it.upsertMsg.InsertMsg)
	if err != nil {
		log.Warn("check varchar/text format failed", zap.Error(err))
		return err
	}

	// Validate and set field ID to insert field data
	err = validateFieldDataColumns(it.upsertMsg.InsertMsg.GetFieldsData(), it.schema)