Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use existing nonzero values in autoincr fields instead of overwriting with new autoincr value #29

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 46 additions & 3 deletions modl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,50 @@ func TestColumnProps(t *testing.T) {
}
}

func TestAutoIncrOverride(t *testing.T) {
dbmap := newDbMap()
type T struct {
A string
ID int
B string
}
//dbmap.TraceOn("", log.New(os.Stdout, "modltest: ", log.Lmicroseconds))
dbmap.AddTable(T{}).SetKeys(true, "ID")

err := dbmap.CreateTables()
if err != nil {
panic(err)
}
defer dbmap.Cleanup()

// Insert with a zero pkey.
t0 := &T{ID: 0}
_insert(dbmap, t0)
t1 := T{}
MustGet(dbmap, &t1, t0.ID)
if t1.ID != t0.ID {
t.Errorf("got t1.ID == %d, want %d", t1.ID, t0.ID)
}

// Insert with an overridden nonzero pkey.
t2 := &T{ID: 123}
_insert(dbmap, t2)
t3 := T{}
MustGet(dbmap, &t3, 123)
if t3.ID != 123 {
t.Errorf("got t3.ID == %d, want %d", t3.ID, 123)
}

// Insert with a zero pkey.
t4 := &T{ID: 0}
_insert(dbmap, t4)
t5 := T{}
MustGet(dbmap, &t5, t4.ID)
if t5.ID != t4.ID {
t.Errorf("got t5.ID == %d, want %d", t5.ID, t4.ID)
}
}

func TestRawSelect(t *testing.T) {
dbmap := initDbMap()
defer dbmap.Cleanup()
Expand Down Expand Up @@ -592,9 +636,8 @@ func TestWithStringPk(t *testing.T) {
defer dbmap.Cleanup()

row := &WithStringPk{"1", "foo"}
err = dbmap.Insert(row)
if err == nil {
t.Errorf("Expected error when inserting into table w/non Int PK and autoincr set true")
if err := dbmap.Insert(row); err != nil {
t.Error(err)
}
}

Expand Down
49 changes: 42 additions & 7 deletions tablemap.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ type TableMap struct {
Columns []*ColumnMap
gotype reflect.Type
version *ColumnMap
insertPlan bindPlan
updatePlan bindPlan
deletePlan bindPlan
getPlan bindPlan
Expand All @@ -32,13 +31,17 @@ type TableMap struct {
CanPostUpdate bool
CanPreDelete bool
CanPostDelete bool

insertPlan *bindPlan
insertAutoIncrPlan *bindPlan
}

// ResetSql removes cached insert/update/select/delete SQL strings
// associated with this TableMap. Call this if you've modified
// any column names or the table name itself.
func (t *TableMap) ResetSql() {
t.insertPlan = bindPlan{}
t.insertPlan = nil
t.insertAutoIncrPlan = nil
t.updatePlan = bindPlan{}
t.deletePlan = bindPlan{}
t.getPlan = bindPlan{}
Expand Down Expand Up @@ -234,10 +237,37 @@ func (t *TableMap) bindUpdate(elem reflect.Value) bindInstance {
return plan.createBindInstance(elem)
}

func isZeroVal(v reflect.Value) bool {
return v.Interface() == reflect.Zero(v.Type()).Interface()
}

func (t *TableMap) bindInsert(elem reflect.Value) bindInstance {
plan := t.insertPlan
if plan.query == "" {
plan.autoIncrIdx = -1
// There are 2 possible insert plans: (1) if the autoincr field is
// empty, then use a plan that inserts the AutoIncrBindValue; or
// (2) if the autoincr field is not empty, use a plan that inserts
// the row with the actual field value.

insertsAutoIncrVal := false
for _, col := range t.Keys {
if col.isAutoIncr && isZeroVal(elem.FieldByName(col.fieldName)) {
// This stmt needs to insert an auto-incremented value.
insertsAutoIncrVal = true
break
}
}

var plan *bindPlan
if insertsAutoIncrVal {
plan = t.insertAutoIncrPlan
} else {
plan = t.insertPlan
}

if plan == nil {
plan = &bindPlan{}
if !insertsAutoIncrVal {
plan.autoIncrIdx = -1
}

s := bytes.Buffer{}
s2 := bytes.Buffer{}
Expand All @@ -255,7 +285,7 @@ func (t *TableMap) bindInsert(elem reflect.Value) bindInstance {
}
s.WriteString(t.dbmap.Dialect.QuoteField(col.ColumnName))

if col.isAutoIncr {
if col.isAutoIncr && isZeroVal(elem.FieldByName(col.fieldName)) {
s2.WriteString(t.dbmap.Dialect.AutoIncrBindValue())
plan.autoIncrIdx = y
} else {
Expand All @@ -282,7 +312,12 @@ func (t *TableMap) bindInsert(elem reflect.Value) bindInstance {
s.WriteString(";")

plan.query = s.String()
t.insertPlan = plan

if insertsAutoIncrVal {
t.insertAutoIncrPlan = plan
} else {
t.insertPlan = plan
}
}

return plan.createBindInstance(elem)
Expand Down