Skip to content

Commit

Permalink
Merge pull request #39 from Hadesonly/addInsertIgnore
Browse files Browse the repository at this point in the history
Add `InsertIgnoreInto`/`ReplaceInto`/etc methods to `Struct`.
  • Loading branch information
huandu authored Nov 11, 2019
2 parents 24b0824 + b65aad7 commit a88ee9b
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 43 deletions.
70 changes: 59 additions & 11 deletions struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,30 +212,42 @@ func (s *Struct) UpdateForTag(table string, tag string, value interface{}) *Upda
return ub
}

// InsertInto creates a new `InsertBuilder` with table name.
// InsertInto creates a new `InsertBuilder` with table name using verb INSERT INTO.
// By default, all exported fields of the s is inserted in INSERT with the field values from value.
// Bulk insert is supported. Item in value that is not the same as that of s will be skipped.
// If no item in value is valid, InsertInto returns a dummy `InsertBuilder` with table name.
func (s *Struct) InsertInto(table string, value ...interface{}) *InsertBuilder {
return s.InsertIntoForTag(table, "", value...)
}

// InsertIntoForTag creates a new `InsertBuilder` with table name.
// By default, all fields of the s tagged with tag is inserted in INSERT with the field values from value.
// InsertIgnoreInto creates a new `InsertBuilder` with table name using verb INSERT IGNORE INTO.
// By default, all exported fields of the s is inserted in INSERT IGNORE with the field values from value.
// Bulk insert is supported. Item in value that is not the same as that of s will be skipped.
// If no item in value is valid, InsertIntoForTag returns a dummy `InsertBuilder` with table name.
func (s *Struct) InsertIntoForTag(table string, tag string, value ...interface{}) *InsertBuilder {
ib := s.Flavor.NewInsertBuilder()
ib.InsertInto(table)
// If no item in value is valid, InsertIgnoreInto returns a dummy `InsertBuilder` with table name.
func (s *Struct) InsertIgnoreInto(table string, value ...interface{}) *InsertBuilder {
return s.InsertIgnoreIntoForTag(table, "", value...)
}

// ReplaceInto creates a new `InsertBuilder` with table name using verb REPLACE INTO.
// By default, all exported fields of the s is inserted in REPLACE with the field values from value.
// Bulk insert is supported. Item in value that is not the same as that of s will be skipped.
// If no item in value is valid, ReplaceInto returns a dummy `InsertBuilder` with table name.
func (s *Struct) ReplaceInto(table string, value ...interface{}) *InsertBuilder {
return s.ReplaceIntoForTag(table, "", value...)
}

// buildColsAndValuesForTag add columns and values into an existing `InsertBuilder`.
// By default, all exported fields of the s is inserted in INSERT with the field values from value.
// If no item in value is valid, buildColsAndValuesForTag returns original `InsertBuilder`.
func (s *Struct) buildColsAndValuesForTag(ib *InsertBuilder, tag string, value ...interface{}) {
if s.taggedFields == nil {
return ib
return
}

fields, ok := s.taggedFields[tag]

if !ok {
return ib
return
}

vs := make([]reflect.Value, 0, len(value))
Expand All @@ -250,9 +262,8 @@ func (s *Struct) InsertIntoForTag(table string, tag string, value ...interface{}
}

if len(vs) == 0 {
return ib
return
}

cols := make([]string, 0, len(fields))
values := make([][]interface{}, len(vs))

Expand All @@ -272,6 +283,43 @@ func (s *Struct) InsertIntoForTag(table string, tag string, value ...interface{}
for _, value := range values {
ib.Values(value...)
}
}

// InsertIntoForTag creates a new `InsertBuilder` with table name using verb INSERT INTO.
// By default, all fields of the s tagged with tag is inserted in INSERT with the field values from value.
// Bulk insert is supported. Item in value that is not the same as that of s will be skipped.
// If no item in value is valid, InsertIntoForTag returns a dummy `InsertBuilder` with table name.
func (s *Struct) InsertIntoForTag(table string, tag string, value ...interface{}) *InsertBuilder {
ib := s.Flavor.NewInsertBuilder()
ib.InsertInto(table)

s.buildColsAndValuesForTag(ib, tag, value...)

return ib
}

// InsertIgnoreIntoForTag creates a new `InsertBuilder` with table name using verb INSERT IGNORE INTO.
// By default, all fields of the s tagged with tag is inserted in INSERT IGNORE with the field values from value.
// Bulk insert is supported. Item in value that is not the same as that of s will be skipped.
// If no item in value is valid, InsertIgnoreIntoForTag returns a dummy `InsertBuilder` with table name.
func (s *Struct) InsertIgnoreIntoForTag(table string, tag string, value ...interface{}) *InsertBuilder {
ib := s.Flavor.NewInsertBuilder()
ib.InsertIgnoreInto(table)

s.buildColsAndValuesForTag(ib, tag, value...)

return ib
}

// InsertIgnoreIntoForTag creates a new `InsertBuilder` with table name using verb REPLACE INTO.
// By default, all fields of the s tagged with tag is inserted in REPLACE with the field values from value.
// Bulk insert is supported. Item in value that is not the same as that of s will be skipped.
// If no item in value is valid, ReplaceIntoForTag returns a dummy `InsertBuilder` with table name.
func (s *Struct) ReplaceIntoForTag(table string, tag string, value ...interface{}) *InsertBuilder {
ib := s.Flavor.NewInsertBuilder()
ib.ReplaceInto(table)

s.buildColsAndValuesForTag(ib, tag, value...)

return ib
}
Expand Down
97 changes: 65 additions & 32 deletions struct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,6 @@ func TestStructInsertInto(t *testing.T) {
Status: 2,
CreatedAt: 1234567890,
}
ib := userForTest.InsertInto("user", user)
sql, args := ib.Build()

if expected := "INSERT INTO user (id, Name, status, created_at) VALUES (?, ?, ?, ?)"; expected != sql {
t.Fatalf("invalid SQL. [expected:%v] [actual:%v]", expected, sql)
}

if expected := []interface{}{123, "Huan Du", 2, 1234567890}; !reflect.DeepEqual(expected, args) {
t.Fatalf("invalid args. [expected:%v] [actual:%v]", expected, args)
}

user2 := &structUserForTest{
ID: 456,
Expand All @@ -113,16 +103,43 @@ func TestStructInsertInto(t *testing.T) {
}{789}

users := []interface{}{user, user2, &fakeUser}
ib = userForTest.InsertInto("user", users...)
sql, args = ib.Build()

if expected := "INSERT INTO user (id, Name, status, created_at) VALUES (?, ?, ?, ?), (?, ?, ?, ?)"; expected != sql {
t.Fatalf("invalid SQL. [expected:%v] [actual:%v]", expected, sql)
testInsert := map[*InsertBuilder]string{
userForTest.InsertInto("user", user): "INSERT ",
userForTest.InsertIgnoreInto("user", user): "INSERT IGNORE ",
userForTest.ReplaceInto("user", user): "REPLACE ",
}

if expected := []interface{}{123, "Huan Du", 2, 1234567890, 456, "Du Huan", 2, 1234567890}; !reflect.DeepEqual(expected, args) {
t.Fatalf("invalid args. [expected:%v] [actual:%v]", expected, args)
testMulitInsert := map[*InsertBuilder]string{
userForTest.InsertInto("user", users...): "INSERT ",
userForTest.InsertIgnoreInto("user", users...): "INSERT IGNORE ",
userForTest.ReplaceInto("user", users...): "REPLACE ",
}

for ib, exceptedVerb := range testInsert{
sql, args := ib.Build()

if expected := exceptedVerb + "INTO user (id, Name, status, created_at) VALUES (?, ?, ?, ?)"; expected != sql {
t.Fatalf("invalid SQL. [expected:%v] [actual:%v]", expected, sql)
}

if expected := []interface{}{123, "Huan Du", 2, 1234567890}; !reflect.DeepEqual(expected, args) {
t.Fatalf("invalid args. [expected:%v] [actual:%v]", expected, args)
}
}

for ib, exceptedVerb := range testMulitInsert{
sql, args := ib.Build()

if expected := exceptedVerb + "INTO user (id, Name, status, created_at) VALUES (?, ?, ?, ?), (?, ?, ?, ?)"; expected != sql {
t.Fatalf("invalid SQL. [expected:%v] [actual:%v]", expected, sql)
}

if expected := []interface{}{123, "Huan Du", 2, 1234567890, 456, "Du Huan", 2, 1234567890}; !reflect.DeepEqual(expected, args) {
t.Fatalf("invalid args. [expected:%v] [actual:%v]", expected, args)
}
}

}

func TestStructInsertIntoForTag(t *testing.T) {
Expand All @@ -132,16 +149,6 @@ func TestStructInsertIntoForTag(t *testing.T) {
Status: 2,
CreatedAt: 1234567890,
}
ib := userForTest.InsertIntoForTag("user", "important", user)
sql, args := ib.Build()

if expected := "INSERT INTO user (id, Name, status) VALUES (?, ?, ?)"; expected != sql {
t.Fatalf("invalid SQL. [expected:%v] [actual:%v]", expected, sql)
}

if expected := []interface{}{123, "Huan Du", 2}; !reflect.DeepEqual(expected, args) {
t.Fatalf("invalid args. [expected:%v] [actual:%v]", expected, args)
}

user2 := &structUserForTest{
ID: 456,
Expand All @@ -155,15 +162,41 @@ func TestStructInsertIntoForTag(t *testing.T) {
}{789}

users := []interface{}{user, user2, &fakeUser}
ib = userForTest.InsertIntoForTag("user", "important", users...)
sql, args = ib.Build()

if expected := "INSERT INTO user (id, Name, status) VALUES (?, ?, ?), (?, ?, ?)"; expected != sql {
t.Fatalf("invalid SQL. [expected:%v] [actual:%v]", expected, sql)
testInsertForTag := map[*InsertBuilder]string{
userForTest.InsertIntoForTag("user","important", user): "INSERT ",
userForTest.InsertIgnoreIntoForTag("user","important", user): "INSERT IGNORE ",
userForTest.ReplaceIntoForTag("user","important", user): "REPLACE ",
}

if expected := []interface{}{123, "Huan Du", 2, 456, "Du Huan", 2}; !reflect.DeepEqual(expected, args) {
t.Fatalf("invalid args. [expected:%v] [actual:%v]", expected, args)
testMulitInsertForTag := map[*InsertBuilder]string{
userForTest.InsertIntoForTag("user","important", users...): "INSERT ",
userForTest.InsertIgnoreIntoForTag("user","important", users...): "INSERT IGNORE ",
userForTest.ReplaceIntoForTag("user","important", users...): "REPLACE ",
}

for ib, exceptedVerb := range testInsertForTag{
sql, args := ib.Build()

if expected := exceptedVerb + "INTO user (id, Name, status) VALUES (?, ?, ?)"; expected != sql {
t.Fatalf("invalid SQL. [expected:%v] [actual:%v]", expected, sql)
}

if expected := []interface{}{123, "Huan Du", 2}; !reflect.DeepEqual(expected, args) {
t.Fatalf("invalid args. [expected:%v] [actual:%v]", expected, args)
}
}

for ib, exceptedVerb := range testMulitInsertForTag{
sql, args := ib.Build()

if expected := exceptedVerb + "INTO user (id, Name, status) VALUES (?, ?, ?), (?, ?, ?)"; expected != sql {
t.Fatalf("invalid SQL. [expected:%v] [actual:%v]", expected, sql)
}

if expected := []interface{}{123, "Huan Du", 2, 456, "Du Huan", 2}; !reflect.DeepEqual(expected, args) {
t.Fatalf("invalid args. [expected:%v] [actual:%v]", expected, args)
}
}

}
Expand Down

0 comments on commit a88ee9b

Please sign in to comment.