Skip to content

Commit 90f139a

Browse files
authored
[fix] full table scan when with duplicated record (jinzhu#15)
1 parent 466b344 commit 90f139a

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

callback_create.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,19 @@ func createCallback(scope *Scope) {
176176
// forceReloadAfterCreateCallback will reload columns that having default value, and set it back to current object
177177
func forceReloadAfterCreateCallback(scope *Scope) {
178178
if blankColumnsWithDefaultValue, ok := scope.InstanceGet("gorm:blank_columns_with_default_value"); ok {
179+
var shouldScan bool
179180
db := scope.DB().New().Table(scope.TableName()).Select(blankColumnsWithDefaultValue.([]string))
180181
for _, field := range scope.Fields() {
181182
if field.IsPrimaryKey && !field.IsBlank {
182183
db = db.Where(fmt.Sprintf("%v = ?", field.DBName), field.Field.Interface())
184+
shouldScan = true
183185
}
184186
}
187+
188+
if !shouldScan {
189+
return
190+
}
191+
185192
db.Scan(scope.Value)
186193
}
187194
}

create_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ package gorm_test
33
import (
44
"os"
55
"reflect"
6+
"strings"
67
"testing"
78
"time"
89

910
"github.com/jinzhu/now"
11+
12+
"github.com/jinzhu/gorm"
1013
)
1114

1215
func TestCreate(t *testing.T) {
@@ -286,3 +289,25 @@ func TestCreateIgnore(t *testing.T) {
286289
t.Error("Should ignore duplicate user insert by insert modifier:IGNORE ")
287290
}
288291
}
292+
293+
func TestFixFullTableScanWhenInsertIgnore(t *testing.T) {
294+
pandaYuanYuan := Panda{Number: 200408301001}
295+
296+
if !DB.NewRecord(pandaYuanYuan) || !DB.NewRecord(&pandaYuanYuan) {
297+
t.Error("Panda should be new record before create")
298+
}
299+
300+
if count := DB.Create(&pandaYuanYuan).RowsAffected; count != 1 {
301+
t.Error("There should be one record be affected when create record")
302+
}
303+
304+
DB.Callback().Query().Register("gorm:fix_full_table_scan", func(scope *gorm.Scope) {
305+
if strings.Contains(scope.SQL, "SELECT") && strings.Contains(scope.SQL, "pandas") && len(scope.SQLVars) == 0 {
306+
t.Error("Should skip force reload when ignore duplicate panda insert")
307+
}
308+
})
309+
310+
if DB.Dialect().GetName() == "mysql" && DB.Set("gorm:insert_modifier", "IGNORE").Create(&pandaYuanYuan).Error != nil {
311+
t.Error("Should ignore duplicate panda insert by insert modifier:IGNORE ")
312+
}
313+
}

migration_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,11 @@ func getPreparedUser(name string, role string) *User {
283283
}
284284
}
285285

286+
type Panda struct {
287+
Number int64 `gorm:"unique_index:number"`
288+
Name string `gorm:"column:name;type:varchar(255);default:null"`
289+
}
290+
286291
func runMigration() {
287292
if err := DB.DropTableIfExists(&User{}).Error; err != nil {
288293
fmt.Printf("Got error when try to delete table users, %+v\n", err)
@@ -292,7 +297,7 @@ func runMigration() {
292297
DB.Exec(fmt.Sprintf("drop table %v;", table))
293298
}
294299

295-
values := []interface{}{&Short{}, &ReallyLongThingThatReferencesShort{}, &ReallyLongTableNameToTestMySQLNameLengthLimit{}, &NotSoLongTableName{}, &Product{}, &Email{}, &Address{}, &CreditCard{}, &Company{}, &Role{}, &Language{}, &HNPost{}, &EngadgetPost{}, &Animal{}, &User{}, &JoinTable{}, &Post{}, &Category{}, &Comment{}, &Cat{}, &Dog{}, &Hamster{}, &Toy{}, &ElementWithIgnoredField{}, &Place{}}
300+
values := []interface{}{&Short{}, &ReallyLongThingThatReferencesShort{}, &ReallyLongTableNameToTestMySQLNameLengthLimit{}, &NotSoLongTableName{}, &Product{}, &Email{}, &Address{}, &CreditCard{}, &Company{}, &Role{}, &Language{}, &HNPost{}, &EngadgetPost{}, &Animal{}, &User{}, &JoinTable{}, &Post{}, &Category{}, &Comment{}, &Cat{}, &Dog{}, &Hamster{}, &Toy{}, &ElementWithIgnoredField{}, &Place{}, &Panda{}}
296301
for _, value := range values {
297302
DB.DropTable(value)
298303
}

0 commit comments

Comments
 (0)