Skip to content

Commit 7eb0ba7

Browse files
author
Mateusz Czapliński
committed
fix data race
Using sync/atomic.Value, wrap lazy building of cached buildPlan values to make them concurrency-friendly.
1 parent 2bb75da commit 7eb0ba7

File tree

1 file changed

+26
-21
lines changed

1 file changed

+26
-21
lines changed

gorp.go

+26-21
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"reflect"
2121
"regexp"
2222
"strings"
23+
"sync/atomic"
2324
"time"
2425
)
2526

@@ -172,21 +173,21 @@ type TableMap struct {
172173
keys []*ColumnMap
173174
uniqueTogether [][]string
174175
version *ColumnMap
175-
insertPlan bindPlan
176-
updatePlan bindPlan
177-
deletePlan bindPlan
178-
getPlan bindPlan
176+
insertPlan atomic.Value
177+
updatePlan atomic.Value
178+
deletePlan atomic.Value
179+
getPlan atomic.Value
179180
dbmap *DbMap
180181
}
181182

182183
// ResetSql removes cached insert/update/select/delete SQL strings
183184
// associated with this TableMap. Call this if you've modified
184185
// any column names or the table name itself.
185186
func (t *TableMap) ResetSql() {
186-
t.insertPlan = bindPlan{}
187-
t.updatePlan = bindPlan{}
188-
t.deletePlan = bindPlan{}
189-
t.getPlan = bindPlan{}
187+
t.insertPlan.Store((*bindPlan)(nil))
188+
t.updatePlan.Store((*bindPlan)(nil))
189+
t.deletePlan.Store((*bindPlan)(nil))
190+
t.getPlan.Store((*bindPlan)(nil))
190191
}
191192

192193
// SetKeys lets you specify the fields on a struct that map to primary
@@ -337,8 +338,9 @@ type bindInstance struct {
337338
}
338339

339340
func (t *TableMap) bindInsert(elem reflect.Value) (bindInstance, error) {
340-
plan := t.insertPlan
341-
if plan.query == "" {
341+
plan := t.insertPlan.Load().(*bindPlan)
342+
if plan == nil {
343+
plan = &bindPlan{}
342344
plan.autoIncrIdx = -1
343345

344346
s := bytes.Buffer{}
@@ -388,15 +390,16 @@ func (t *TableMap) bindInsert(elem reflect.Value) (bindInstance, error) {
388390
s.WriteString(t.dbmap.Dialect.QuerySuffix())
389391

390392
plan.query = s.String()
391-
t.insertPlan = plan
393+
t.insertPlan.Store(plan)
392394
}
393395

394396
return plan.createBindInstance(elem, t.dbmap.TypeConverter)
395397
}
396398

397399
func (t *TableMap) bindUpdate(elem reflect.Value) (bindInstance, error) {
398-
plan := t.updatePlan
399-
if plan.query == "" {
400+
plan := t.updatePlan.Load().(*bindPlan)
401+
if plan == nil {
402+
plan = &bindPlan{}
400403

401404
s := bytes.Buffer{}
402405
s.WriteString(fmt.Sprintf("update %s set ", t.dbmap.Dialect.QuotedTableForQuery(t.SchemaName, t.TableName)))
@@ -446,15 +449,16 @@ func (t *TableMap) bindUpdate(elem reflect.Value) (bindInstance, error) {
446449
s.WriteString(t.dbmap.Dialect.QuerySuffix())
447450

448451
plan.query = s.String()
449-
t.updatePlan = plan
452+
t.updatePlan.Store(plan)
450453
}
451454

452455
return plan.createBindInstance(elem, t.dbmap.TypeConverter)
453456
}
454457

455458
func (t *TableMap) bindDelete(elem reflect.Value) (bindInstance, error) {
456-
plan := t.deletePlan
457-
if plan.query == "" {
459+
plan := t.deletePlan.Load().(*bindPlan)
460+
if plan == nil {
461+
plan = &bindPlan{}
458462

459463
s := bytes.Buffer{}
460464
s.WriteString(fmt.Sprintf("delete from %s", t.dbmap.Dialect.QuotedTableForQuery(t.SchemaName, t.TableName)))
@@ -492,15 +496,16 @@ func (t *TableMap) bindDelete(elem reflect.Value) (bindInstance, error) {
492496
s.WriteString(t.dbmap.Dialect.QuerySuffix())
493497

494498
plan.query = s.String()
495-
t.deletePlan = plan
499+
t.deletePlan.Store(plan)
496500
}
497501

498502
return plan.createBindInstance(elem, t.dbmap.TypeConverter)
499503
}
500504

501505
func (t *TableMap) bindGet() bindPlan {
502-
plan := t.getPlan
503-
if plan.query == "" {
506+
plan := t.getPlan.Load().(*bindPlan)
507+
if plan == nil {
508+
plan = &bindPlan{}
504509

505510
s := bytes.Buffer{}
506511
s.WriteString("select ")
@@ -533,10 +538,10 @@ func (t *TableMap) bindGet() bindPlan {
533538
s.WriteString(t.dbmap.Dialect.QuerySuffix())
534539

535540
plan.query = s.String()
536-
t.getPlan = plan
541+
t.getPlan.Store(plan)
537542
}
538543

539-
return plan
544+
return *plan
540545
}
541546

542547
// ColumnMap represents a mapping between a Go struct field and a single

0 commit comments

Comments
 (0)