Skip to content

Commit 9e3ad92

Browse files
author
José Carlos
authoredOct 20, 2016
Merge pull request #277 from upper/issue-276
Add test for Where() before Set() on update
2 parents 69048c2 + f0f283b commit 9e3ad92

File tree

6 files changed

+107
-24
lines changed

6 files changed

+107
-24
lines changed
 

‎lib/sqlbuilder/builder.go

+16
Original file line numberDiff line numberDiff line change
@@ -530,3 +530,19 @@ var (
530530
_ = Builder(&sqlBuilder{})
531531
_ = exprDB(&exprProxy{})
532532
)
533+
534+
func joinArguments(args ...[]interface{}) []interface{} {
535+
total := 0
536+
for i := range args {
537+
total += len(args[i])
538+
}
539+
if total == 0 {
540+
return nil
541+
}
542+
543+
flatten := make([]interface{}, 0, total)
544+
for i := range args {
545+
flatten = append(flatten, args[i]...)
546+
}
547+
return flatten
548+
}

‎lib/sqlbuilder/builder_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,45 @@ func TestUpdate(t *testing.T) {
654654
b.Update("artist").Set("name", "Artist").String(),
655655
)
656656

657+
{
658+
idSlice := []int64{8, 7, 6}
659+
q := b.Update("artist").Set(db.Cond{"some_column": 10}).Where(db.Cond{"id": 1}, db.Cond{"another_val": idSlice})
660+
assert.Equal(
661+
`UPDATE "artist" SET "some_column" = $1 WHERE ("id" = $2 AND "another_val" IN ($3, $4, $5))`,
662+
q.String(),
663+
)
664+
assert.Equal(
665+
[]interface{}{10, 1, int64(8), int64(7), int64(6)},
666+
q.Arguments(),
667+
)
668+
}
669+
670+
{
671+
idSlice := []int64{}
672+
q := b.Update("artist").Set(db.Cond{"some_column": 10}).Where(db.Cond{"id": 1}, db.Cond{"another_val": idSlice})
673+
assert.Equal(
674+
`UPDATE "artist" SET "some_column" = $1 WHERE ("id" = $2 AND "another_val" IS NULL)`,
675+
q.String(),
676+
)
677+
assert.Equal(
678+
[]interface{}{10, 1},
679+
q.Arguments(),
680+
)
681+
}
682+
683+
{
684+
idSlice := []int64{}
685+
q := b.Update("artist").Where(db.Cond{"id": 1}, db.Cond{"another_val": idSlice}).Set(db.Cond{"some_column": 10})
686+
assert.Equal(
687+
`UPDATE "artist" SET "some_column" = $1 WHERE ("id" = $2 AND "another_val" IS NULL)`,
688+
q.String(),
689+
)
690+
assert.Equal(
691+
[]interface{}{10, 1},
692+
q.Arguments(),
693+
)
694+
}
695+
657696
assert.Equal(
658697
`UPDATE "artist" SET "name" = $1 WHERE ("id" < $2)`,
659698
b.Update("artist").Set("name = ?", "Artist").Where("id <", 5).String(),
@@ -671,6 +710,13 @@ func TestUpdate(t *testing.T) {
671710
}{"Artist"}).Where(db.Cond{"id <": 5}).String(),
672711
)
673712

713+
assert.Equal(
714+
`UPDATE "artist" SET "name" = $1 WHERE ("id" < $2)`,
715+
b.Update("artist").Where(db.Cond{"id <": 5}).Set(struct {
716+
Nombre string `db:"name"`
717+
}{"Artist"}).String(),
718+
)
719+
674720
assert.Equal(
675721
`UPDATE "artist" SET "name" = $1, "last_name" = $2 WHERE ("id" < $3)`,
676722
b.Update("artist").Set(struct {

‎lib/sqlbuilder/delete.go

+4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ func (qd *deleter) Limit(limit int) Deleter {
2727
return qd
2828
}
2929

30+
func (qd *deleter) Arguments() []interface{} {
31+
return qd.arguments
32+
}
33+
3034
func (qd *deleter) Exec() (sql.Result, error) {
3135
return qd.builder.sess.StatementExec(qd.statement(), qd.arguments...)
3236
}

‎lib/sqlbuilder/interfaces.go

+6
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,9 @@ type Deleter interface {
365365
// fmt.Stringer provides `String() string`, you can use `String()` to compile
366366
// the `Inserter` into a string.
367367
fmt.Stringer
368+
369+
// Arguments returns the arguments that are prepared for this query.
370+
Arguments() []interface{}
368371
}
369372

370373
// Updater represents an UPDATE statement.
@@ -388,6 +391,9 @@ type Updater interface {
388391
// fmt.Stringer provides `String() string`, you can use `String()` to compile
389392
// the `Inserter` into a string.
390393
fmt.Stringer
394+
395+
// Arguments returns the arguments that are prepared for this query.
396+
Arguments() []interface{}
391397
}
392398

393399
// Execer provides methods for executing statements that do not return results.

‎lib/sqlbuilder/select.go

+8-12
Original file line numberDiff line numberDiff line change
@@ -121,18 +121,14 @@ func (qs *selector) Arguments() []interface{} {
121121
qs.mu.Lock()
122122
defer qs.mu.Unlock()
123123

124-
total := len(qs.tableArgs) + len(qs.columnsArgs) + len(qs.whereArgs) + len(qs.joinsArgs) + len(qs.groupByArgs) + len(qs.orderByArgs)
125-
if total == 0 {
126-
return nil
127-
}
128-
args := make([]interface{}, 0, total)
129-
args = append(args, qs.tableArgs...)
130-
args = append(args, qs.columnsArgs...)
131-
args = append(args, qs.joinsArgs...)
132-
args = append(args, qs.whereArgs...)
133-
args = append(args, qs.groupByArgs...)
134-
args = append(args, qs.orderByArgs...)
135-
return args
124+
return joinArguments(
125+
qs.tableArgs,
126+
qs.columnsArgs,
127+
qs.joinsArgs,
128+
qs.whereArgs,
129+
qs.groupByArgs,
130+
qs.orderByArgs,
131+
)
136132
}
137133

138134
func (qs *selector) GroupBy(columns ...interface{}) Selector {

‎lib/sqlbuilder/update.go

+27-12
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,25 @@ package sqlbuilder
22

33
import (
44
"database/sql"
5+
"sync"
56

67
"upper.io/db.v2/internal/sqladapter/exql"
78
)
89

910
type updater struct {
1011
*stringer
11-
builder *sqlBuilder
12-
table string
13-
columnValues *exql.ColumnValues
14-
limit int
15-
where *exql.Where
16-
arguments []interface{}
12+
builder *sqlBuilder
13+
table string
14+
15+
columnValues *exql.ColumnValues
16+
columnValuesArgs []interface{}
17+
18+
limit int
19+
20+
where *exql.Where
21+
whereArgs []interface{}
22+
23+
mu sync.Mutex
1724
}
1825

1926
func (qu *updater) Set(terms ...interface{}) Updater {
@@ -36,28 +43,36 @@ func (qu *updater) Set(terms ...interface{}) Updater {
3643
cvs = append(cvs, cv)
3744
}
3845

39-
args = append(args, qu.arguments...)
40-
4146
qu.columnValues.Insert(cvs...)
42-
qu.arguments = append(qu.arguments, args...)
47+
qu.columnValuesArgs = append(qu.columnValuesArgs, args...)
4348
} else if len(terms) > 1 {
4449
cv, arguments := qu.builder.t.ToColumnValues(terms)
4550
qu.columnValues.Insert(cv.ColumnValues...)
46-
qu.arguments = append(qu.arguments, arguments...)
51+
qu.columnValuesArgs = append(qu.columnValuesArgs, arguments...)
4752
}
4853

4954
return qu
5055
}
5156

57+
func (qu *updater) Arguments() []interface{} {
58+
qu.mu.Lock()
59+
defer qu.mu.Unlock()
60+
61+
return joinArguments(
62+
qu.columnValuesArgs,
63+
qu.whereArgs,
64+
)
65+
}
66+
5267
func (qu *updater) Where(terms ...interface{}) Updater {
5368
where, arguments := qu.builder.t.ToWhereWithArguments(terms)
5469
qu.where = &where
55-
qu.arguments = append(qu.arguments, arguments...)
70+
qu.whereArgs = append(qu.whereArgs, arguments...)
5671
return qu
5772
}
5873

5974
func (qu *updater) Exec() (sql.Result, error) {
60-
return qu.builder.sess.StatementExec(qu.statement(), qu.arguments...)
75+
return qu.builder.sess.StatementExec(qu.statement(), qu.Arguments()...)
6176
}
6277

6378
func (qu *updater) Limit(limit int) Updater {

0 commit comments

Comments
 (0)