Skip to content

Commit d2aadb4

Browse files
committed
fix #65 Struct#InsertInto* methods are aware of omitempty options now
1 parent 02da50f commit d2aadb4

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed

struct.go

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ func (s *Struct) UpdateForTag(table string, tag string, value interface{}) *Upda
182182
} else {
183183
val = dereferencedValue(val)
184184
}
185+
185186
data := val.Interface()
186187
assignments = append(assignments, ub.Assign(quoted[i], data))
187188
}
@@ -252,23 +253,60 @@ func (s *Struct) buildColsAndValuesForTag(ib *InsertBuilder, tag string, value .
252253
if len(vs) == 0 {
253254
return
254255
}
256+
255257
cols := make([]string, 0, len(fields))
256258
values := make([][]interface{}, len(vs))
259+
nilCols := make([]int, len(fields))
257260

258-
for _, f := range fields {
261+
for idx, f := range fields {
259262
cols = append(cols, f)
260263
name := sf.fieldAlias[f]
264+
shouldOmitempty := false
265+
266+
if omitEmptyTagMap, ok := sf.omitEmptyFields[f]; ok {
267+
if omitEmptyTagMap.containsAny("", tag) {
268+
shouldOmitempty = true
269+
}
270+
}
261271

262272
for i, v := range vs {
263-
data := v.FieldByName(name).Interface()
264-
values[i] = append(values[i], data)
273+
val := v.FieldByName(name)
274+
275+
if isEmptyValue(val) && shouldOmitempty {
276+
nilCols[idx]++
277+
}
278+
279+
val = dereferencedValue(val)
280+
281+
if val.IsValid() {
282+
values[i] = append(values[i], val.Interface())
283+
} else {
284+
values[i] = append(values[i], nil)
285+
}
286+
}
287+
}
288+
289+
// Try to filter out nil values if possible.
290+
filteredCols := make([]string, 0, len(cols))
291+
filteredValues := make([][]interface{}, len(values))
292+
293+
for i, cnt := range nilCols {
294+
// If all values are nil in a column, ignore the column completedly.
295+
if cnt == len(values) {
296+
continue
297+
}
298+
299+
filteredCols = append(filteredCols, cols[i])
300+
301+
for n, value := range values {
302+
filteredValues[n] = append(filteredValues[n], value[i])
265303
}
266304
}
267305

268-
cols = s.quoteFields(sf, cols)
269-
ib.Cols(cols...)
306+
filteredCols = s.quoteFields(sf, filteredCols)
307+
ib.Cols(filteredCols...)
270308

271-
for _, value := range values {
309+
for _, value := range filteredValues {
272310
ib.Values(value...)
273311
}
274312
}

struct_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ func TestStructOmitEmptyForMultipleTags(t *testing.T) {
623623

624624
i := 123
625625
b := "bbbb"
626+
c := uint16(2)
626627
e := true
627628
sql2, args2 := st.UpdateForTag("foo", "patch2", &structOmitEmptyForMultipleTags{
628629
A: i,
@@ -634,6 +635,24 @@ func TestStructOmitEmptyForMultipleTags(t *testing.T) {
634635

635636
a.Equal(sql2, "UPDATE foo SET `aa` = ?")
636637
a.Equal(args2, []interface{}{i})
638+
639+
value1 := &structOmitEmptyForMultipleTags{
640+
A: i,
641+
B: &b,
642+
C: 0,
643+
D: nil,
644+
E: false, // should be false value.
645+
}
646+
value2 := &structOmitEmptyForMultipleTags{
647+
A: i,
648+
B: &b,
649+
C: c, // should not be omitted as C in value1 is not empty.
650+
D: nil,
651+
E: true,
652+
}
653+
sql3, args3 := st.InsertIntoForTag("foo", "patch2", value1, value2).Build()
654+
a.Equal(sql3, "INSERT INTO foo (`aa`, cc) VALUES (?, ?), (?, ?)")
655+
a.Equal(args3, []interface{}{i, uint16(0), i, c})
637656
}
638657

639658
type structWithPointers struct {

0 commit comments

Comments
 (0)