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 <nil>]

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 <nil>]

s.Nullable("age")
// Bulk insertion does not work
_, err := s.Insert(list) // [table] `user` INSERT INTO `user` (`name,`age`) VALUES (?, ?),(?, ?) [John, <nil>, Wick, <nil>]
```

Reviewed-on: https://gitea.com/xorm/xorm/pulls/2077
Co-authored-by: satorunooshie <satorunooshie@noreply.gitea.io>
Co-committed-by: satorunooshie <satorunooshie@noreply.gitea.io>
This commit is contained in:
satorunooshie 2021-12-27 10:11:44 +08:00 committed by Lunny Xiao
parent a2d3669edf
commit 57365108ae
1 changed files with 7 additions and 0 deletions

View File

@ -142,6 +142,13 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e
if len(session.statement.ColumnMap) > 0 && !session.statement.ColumnMap.Contain(col.Name) { if len(session.statement.ColumnMap) > 0 && !session.statement.ColumnMap.Contain(col.Name) {
continue 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 { if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime {
val, t, err := session.engine.nowTime(col) val, t, err := session.engine.nowTime(col)
if err != nil { if err != nil {