From 57365108ae98aefd57a732f0e2e65fa38f865798 Mon Sep 17 00:00:00 2001 From: satorunooshie Date: Mon, 27 Dec 2021 10:11:44 +0800 Subject: [PATCH] Fix insertMultipleStruct to insert null value under certain circumstances (#2077) The behavior of multi insertion of null differs from that of single insertion. On the other hand, behavior between single and bulk insertion of null using pointer of struct field is identical. Please see the example below. ```go s := engineGroup.NewSession() type User struct { ID int `xorm:"not null pk autoincr INT(10)"` Name string `xorm:"not null VARCHAR(191)"` Age int64 `xorm:"null BIGINT(20)"` } list := []*User{ { Name: "John", }, { Name: "Wick", }, } s.Nullable("age") // Single insertion works _, err := s.Insert(list[0]) // [table] `user` INSERT INTO `user` (`name`,`age`) VALUES (?, ?) [John ] s.Nullable("age") // Bulk insertion does not work _, err := s.Insert(list) // [table] `user` INSERT INTO `user` (`name,`age`) VALUES (?, ?),(?, ?) [John, 0, Wick, 0] //--------------------------------- //Using pointer, which is nullable, the generated sql has no difference. //--------------------------------- type User struct { ID int `xorm:"not null pk autoincr INT(10)"` Name string `xorm:"not null VARCHAR(191)"` Age *int64 `xorm:"null BIGINT(20)"` } list := []*User{ { Name: "John", }, { Name: "Wick", }, } s.Nullable("age") // Single insertion works _, err := s.Insert(list[0]) // [table] `user` INSERT INTO `user` (`name`,`age`) VALUES (?, ?) [John ] s.Nullable("age") // Bulk insertion does not work _, err := s.Insert(list) // [table] `user` INSERT INTO `user` (`name,`age`) VALUES (?, ?),(?, ?) [John, , Wick, ] ``` Reviewed-on: https://gitea.com/xorm/xorm/pulls/2077 Co-authored-by: satorunooshie Co-committed-by: satorunooshie --- session_insert.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/session_insert.go b/session_insert.go index 4835eb14..fc025613 100644 --- a/session_insert.go +++ b/session_insert.go @@ -142,6 +142,13 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e if len(session.statement.ColumnMap) > 0 && !session.statement.ColumnMap.Contain(col.Name) { continue } + // !satorunooshie! set fieldValue as nil when column is nullable and zero-value + if _, ok := getFlagForColumn(session.statement.NullableMap, col); ok { + if col.Nullable && utils.IsValueZero(fieldValue) { + var nilValue *int + fieldValue = reflect.ValueOf(nilValue) + } + } if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime { val, t, err := session.engine.nowTime(col) if err != nil {