Skip to content

Commit fb26041

Browse files
Closes go-xorm#10 iterate Neq and Eq in predictable order
Also, uncomment an older test that is now passing reliably! And change error from "to be update" to "to be insert" in builder_insert.
1 parent a9b7ffc commit fb26041

File tree

5 files changed

+52
-13
lines changed

5 files changed

+52
-13
lines changed

builder_insert.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func (b *Builder) insertWriteTo(w Writer) error {
1515
return errors.New("no table indicated")
1616
}
1717
if len(b.inserts) <= 0 {
18-
return errors.New("no column to be update")
18+
return errors.New("no column to be insert")
1919
}
2020

2121
if _, err := fmt.Fprintf(w, "INSERT INTO %s (", b.tableName); err != nil {
@@ -26,7 +26,9 @@ func (b *Builder) insertWriteTo(w Writer) error {
2626
var bs []byte
2727
var valBuffer = bytes.NewBuffer(bs)
2828
var i = 0
29-
for col, value := range b.inserts {
29+
30+
for _, col := range b.inserts.sortedKeys() {
31+
value := b.inserts[col]
3032
fmt.Fprint(w, col)
3133
if e, ok := value.(expr); ok {
3234
fmt.Fprint(valBuffer, e.sql)

builder_test.go

+5-6
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,11 @@ func TestBuilderCond(t *testing.T) {
110110
"0=0",
111111
[]interface{}{},
112112
},
113-
// FIXME: since map will not guarantee the sequence, this may be failed random
114-
/*{
113+
{
115114
Or(Eq{"a": 1, "b": 2}, Eq{"c": 3, "d": 4}),
116115
"(a=? AND b=?) OR (c=? AND d=?)",
117116
[]interface{}{1, 2, 3, 4},
118-
},*/
117+
},
119118
}
120119

121120
for _, k := range cases {
@@ -208,14 +207,14 @@ func TestSubquery(t *testing.T) {
208207
subb := Select("id").From("table_b").Where(Eq{"b": "a"})
209208
b := Select("a, b").From("table_a").Where(
210209
Eq{
211-
"id": 23,
212210
"b_id": subb,
211+
"id": 23,
213212
},
214213
)
215214
sql, args, err := b.ToSQL()
216215
assert.NoError(t, err)
217-
assert.EqualValues(t, "SELECT a, b FROM table_a WHERE id=? AND b_id=(SELECT id FROM table_b WHERE b=?)", sql)
218-
assert.EqualValues(t, []interface{}{23, "a"}, args)
216+
assert.EqualValues(t, "SELECT a, b FROM table_a WHERE b_id=(SELECT id FROM table_b WHERE b=?) AND id=?", sql)
217+
assert.EqualValues(t, []interface{}{"a", 23}, args)
219218
}
220219

221220
// https://github.com/go-xorm/xorm/issues/820

cond_compare.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ import "fmt"
1010
func WriteMap(w Writer, data map[string]interface{}, op string) error {
1111
var args = make([]interface{}, 0, len(data))
1212
var i = 0
13-
for k, v := range data {
13+
keys := make([]string, 0, len(data))
14+
for k := range data {
15+
keys = append(keys, k)
16+
}
17+
18+
for _, k := range keys {
19+
v := data[k]
1420
switch v.(type) {
1521
case expr:
1622
if _, err := fmt.Fprintf(w, "%s%s(", k, op); err != nil {

cond_eq.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
package builder
66

7-
import "fmt"
7+
import (
8+
"fmt"
9+
"sort"
10+
)
811

912
// Incr implements a type used by Eq
1013
type Incr int
@@ -19,7 +22,8 @@ var _ Cond = Eq{}
1922

2023
func (eq Eq) opWriteTo(op string, w Writer) error {
2124
var i = 0
22-
for k, v := range eq {
25+
for _, k := range eq.sortedKeys() {
26+
v := eq[k]
2327
switch v.(type) {
2428
case []int, []int64, []string, []int32, []int16, []int8, []uint, []uint64, []uint32, []uint16, []interface{}:
2529
if err := In(k, v).WriteTo(w); err != nil {
@@ -94,3 +98,15 @@ func (eq Eq) Or(conds ...Cond) Cond {
9498
func (eq Eq) IsValid() bool {
9599
return len(eq) > 0
96100
}
101+
102+
// sortedKeys returns all keys of this Eq sorted with sort.Strings.
103+
// It is used internally for consistent ordering when generating
104+
// SQL, see https://github.com/go-xorm/builder/issues/10
105+
func (eq Eq) sortedKeys() []string {
106+
keys := make([]string, 0, len(eq))
107+
for key := range eq {
108+
keys = append(keys, key)
109+
}
110+
sort.Strings(keys)
111+
return keys
112+
}

cond_neq.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
package builder
66

7-
import "fmt"
7+
import (
8+
"fmt"
9+
"sort"
10+
)
811

912
// Neq defines not equal conditions
1013
type Neq map[string]interface{}
@@ -15,7 +18,8 @@ var _ Cond = Neq{}
1518
func (neq Neq) WriteTo(w Writer) error {
1619
var args = make([]interface{}, 0, len(neq))
1720
var i = 0
18-
for k, v := range neq {
21+
for _, k := range neq.sortedKeys() {
22+
v := neq[k]
1923
switch v.(type) {
2024
case []int, []int64, []string, []int32, []int16, []int8:
2125
if err := NotIn(k, v).WriteTo(w); err != nil {
@@ -76,3 +80,15 @@ func (neq Neq) Or(conds ...Cond) Cond {
7680
func (neq Neq) IsValid() bool {
7781
return len(neq) > 0
7882
}
83+
84+
// sortedKeys returns all keys of this Neq sorted with sort.Strings.
85+
// It is used internally for consistent ordering when generating
86+
// SQL, see https://github.com/go-xorm/builder/issues/10
87+
func (neq Neq) sortedKeys() []string {
88+
keys := make([]string, 0, len(neq))
89+
for key := range neq {
90+
keys = append(keys, key)
91+
}
92+
sort.Strings(keys)
93+
return keys
94+
}

0 commit comments

Comments
 (0)