fix #65 Struct#InsertInto* methods are aware of omitempty options now

This commit is contained in:
Huan Du
2021-07-25 15:34:47 +08:00
parent c4c083ed73
commit 1bb5856684
2 changed files with 63 additions and 6 deletions
+44 -6
View File
@@ -182,6 +182,7 @@ func (s *Struct) UpdateForTag(table string, tag string, value interface{}) *Upda
} else {
val = dereferencedValue(val)
}
data := val.Interface()
assignments = append(assignments, ub.Assign(quoted[i], data))
}
@@ -252,23 +253,60 @@ func (s *Struct) buildColsAndValuesForTag(ib *InsertBuilder, tag string, value .
if len(vs) == 0 {
return
}
cols := make([]string, 0, len(fields))
values := make([][]interface{}, len(vs))
nilCols := make([]int, len(fields))
for _, f := range fields {
for idx, f := range fields {
cols = append(cols, f)
name := sf.fieldAlias[f]
shouldOmitempty := false
if omitEmptyTagMap, ok := sf.omitEmptyFields[f]; ok {
if omitEmptyTagMap.containsAny("", tag) {
shouldOmitempty = true
}
}
for i, v := range vs {
data := v.FieldByName(name).Interface()
values[i] = append(values[i], data)
val := v.FieldByName(name)
if isEmptyValue(val) && shouldOmitempty {
nilCols[idx]++
}
val = dereferencedValue(val)
if val.IsValid() {
values[i] = append(values[i], val.Interface())
} else {
values[i] = append(values[i], nil)
}
}
}
cols = s.quoteFields(sf, cols)
ib.Cols(cols...)
// Try to filter out nil values if possible.
filteredCols := make([]string, 0, len(cols))
filteredValues := make([][]interface{}, len(values))
for _, value := range values {
for i, cnt := range nilCols {
// If all values are nil in a column, ignore the column completedly.
if cnt == len(values) {
continue
}
filteredCols = append(filteredCols, cols[i])
for n, value := range values {
filteredValues[n] = append(filteredValues[n], value[i])
}
}
filteredCols = s.quoteFields(sf, filteredCols)
ib.Cols(filteredCols...)
for _, value := range filteredValues {
ib.Values(value...)
}
}
+19
View File
@@ -623,6 +623,7 @@ func TestStructOmitEmptyForMultipleTags(t *testing.T) {
i := 123
b := "bbbb"
c := uint16(2)
e := true
sql2, args2 := st.UpdateForTag("foo", "patch2", &structOmitEmptyForMultipleTags{
A: i,
@@ -634,6 +635,24 @@ func TestStructOmitEmptyForMultipleTags(t *testing.T) {
a.Equal(sql2, "UPDATE foo SET `aa` = ?")
a.Equal(args2, []interface{}{i})
value1 := &structOmitEmptyForMultipleTags{
A: i,
B: &b,
C: 0,
D: nil,
E: false, // should be false value.
}
value2 := &structOmitEmptyForMultipleTags{
A: i,
B: &b,
C: c, // should not be omitted as C in value1 is not empty.
D: nil,
E: true,
}
sql3, args3 := st.InsertIntoForTag("foo", "patch2", value1, value2).Build()
a.Equal(sql3, "INSERT INTO foo (`aa`, cc) VALUES (?, ?), (?, ?)")
a.Equal(args3, []interface{}{i, uint16(0), i, c})
}
type structWithPointers struct {