fix: check allow_insert_auto_id flag in RESTful v2 insert API (#46822)

Related to #46818

When a collection has autoID enabled and `allow_insert_auto_id` property
set to true, the RESTful v2 insert API was incorrectly rejecting
requests that included the primary key field. This fix adds proper
checking of the `allow_insert_auto_id` flag in the `anyToColumns`
function.

Changes:
- Read `allow_insert_auto_id` property from collection schema
- Skip PK field only when autoID is enabled AND allow_insert_auto_id is
false
- Allow PK field in insert request when allow_insert_auto_id is true
- Filter out empty PK column when autoID is enabled and user didn't
provide PK

Signed-off-by: Congqi Xia <congqi.xia@zilliz.com>
This commit is contained in:
congqixia 2026-01-07 10:13:25 +08:00 committed by GitHub
parent fbd8a766c5
commit bc8d4c175c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 3 deletions

View File

@ -750,13 +750,22 @@ func anyToColumns(rows []map[string]interface{}, validDataMap map[string][]bool,
}
isDynamic := sch.EnableDynamicField
allowInsertAutoID, _ := common.IsAllowInsertAutoID(sch.GetProperties()...)
isAutoIDPK := false
pkFieldName := ""
nameColumns := make(map[string]interface{})
nameDims := make(map[string]int64)
fieldData := make(map[string]*schemapb.FieldData)
for _, field := range sch.Fields {
if (field.IsPrimaryKey && field.AutoID && inInsert) || field.IsDynamic {
if field.IsPrimaryKey {
pkFieldName = field.Name
if field.AutoID {
isAutoIDPK = true
}
}
if (field.IsPrimaryKey && field.AutoID && inInsert && !allowInsertAutoID) || field.IsDynamic {
continue
}
// skip function output field
@ -845,10 +854,12 @@ func anyToColumns(rows []map[string]interface{}, validDataMap map[string][]bool,
}
candi, ok := set[field.Name]
if field.IsPrimaryKey && field.AutoID && inInsert {
if ok {
if !ok {
continue
}
if !allowInsertAutoID {
return nil, merr.WrapErrParameterInvalidMsg(fmt.Sprintf("no need to pass pk field(%s) when autoid==true in insert", field.Name))
}
continue
}
if (field.Nullable || field.DefaultValue != nil) && !ok {
continue
@ -947,6 +958,9 @@ func anyToColumns(rows []map[string]interface{}, validDataMap map[string][]bool,
}
columns := make([]*schemapb.FieldData, 0, len(nameColumns))
for name, column := range nameColumns {
if fieldLen[name] == 0 && name == pkFieldName && isAutoIDPK {
continue
}
if fieldLen[name] == 0 && partialUpdate {
// for partial update, skip update for nullable field
// cause we cannot distinguish between missing fields and fields explicitly set to null

View File

@ -649,6 +649,25 @@ func TestAnyToColumns(t *testing.T) {
assert.Equal(t, true, strings.HasPrefix(err.Error(), "no need to pass pk field"))
})
t.Run("insert,autoid==true,allow_insert_auto_id=true", func(t *testing.T) {
body := []byte("{\"data\": {\"id\": 0, \"book_id\": 1, \"book_intro\": [0.1, 0.2], \"word_count\": 2, \"classified\": false, \"databaseID\": null}}")
req := InsertReq{}
coll := generateCollectionSchema(schemapb.DataType_Int64, true, true)
coll.Properties = append(coll.Properties, &commonpb.KeyValuePair{
Key: common.AllowInsertAutoIDKey,
Value: "true",
})
var err error
err, req.Data, _ = checkAndSetData(body, coll, false)
assert.Equal(t, nil, err)
assert.Equal(t, int64(0), req.Data[0]["id"])
assert.Equal(t, int64(1), req.Data[0]["book_id"])
assert.Equal(t, int64(2), req.Data[0]["word_count"])
t.Log(req.Data)
_, err = anyToColumns(req.Data, nil, coll, true, false)
assert.NoError(t, err)
})
t.Run("pass more field", func(t *testing.T) {
body := []byte("{\"data\": {\"id\": 0, \"book_id\": 1, \"book_intro\": [0.1, 0.2], \"word_count\": 2, \"classified\": false, \"databaseID\": null}}")
coll := generateCollectionSchema(schemapb.DataType_Int64, true, false)