Merge pull request #39 from Hadesonly/addInsertIgnore

Add `InsertIgnoreInto`/`ReplaceInto`/etc methods to `Struct`.
This commit is contained in:
Huan Du
2019-11-11 16:29:40 +08:00
committed by GitHub
2 changed files with 124 additions and 43 deletions
+59 -11
View File
@@ -212,7 +212,7 @@ 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.
@@ -220,22 +220,34 @@ 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))
@@ -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))
@@ -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
}
+65 -32
View File
@@ -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,
@@ -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) {
@@ -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,
@@ -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)
}
}
}