github.com/ecodeclub/eorm@v0.0.2-0.20231001112437-dae71da914d0/insert_test.go (about)

     1  // Copyright 2021 ecodeclub
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  package eorm
    15  
    16  import (
    17  	"context"
    18  	"errors"
    19  	"fmt"
    20  	"testing"
    21  
    22  	"github.com/stretchr/testify/assert"
    23  )
    24  
    25  func TestInserter_Values(t *testing.T) {
    26  	type User struct {
    27  		Id        int64 `eorm:"auto_increment,primary_key"`
    28  		FirstName string
    29  		Ctime     uint64
    30  	}
    31  	n := uint64(1000)
    32  	u := &User{
    33  		Id:        12,
    34  		FirstName: "Tom",
    35  		Ctime:     n,
    36  	}
    37  	u1 := &User{
    38  		Id:        13,
    39  		FirstName: "Jerry",
    40  		Ctime:     n,
    41  	}
    42  	db := memoryDB()
    43  	testCases := []CommonTestCase{
    44  		{
    45  			name:    "no examples of values",
    46  			builder: NewInserter[User](db).Values(),
    47  			wantErr: errors.New("插入0行"),
    48  		},
    49  		{
    50  			name:     "single example of values",
    51  			builder:  NewInserter[User](db).Values(u),
    52  			wantSql:  "INSERT INTO `user`(`id`,`first_name`,`ctime`) VALUES(?,?,?);",
    53  			wantArgs: []interface{}{int64(12), "Tom", n},
    54  		},
    55  
    56  		{
    57  			name:     "multiple values of same type",
    58  			builder:  NewInserter[User](db).Values(u, u1),
    59  			wantSql:  "INSERT INTO `user`(`id`,`first_name`,`ctime`) VALUES(?,?,?),(?,?,?);",
    60  			wantArgs: []interface{}{int64(12), "Tom", n, int64(13), "Jerry", n},
    61  		},
    62  
    63  		{
    64  			name:     "no example of a whole columns",
    65  			builder:  NewInserter[User](db).Columns("Id", "FirstName").Values(u),
    66  			wantSql:  "INSERT INTO `user`(`id`,`first_name`) VALUES(?,?);",
    67  			wantArgs: []interface{}{int64(12), "Tom"},
    68  		},
    69  		{
    70  			name:    "an example with invalid columns",
    71  			builder: NewInserter[User](db).Columns("id", "FirstName").Values(u),
    72  			wantErr: errors.New("eorm: 未知字段 id"),
    73  		},
    74  		{
    75  			name:     "no whole columns and multiple values of same type",
    76  			builder:  NewInserter[User](db).Columns("Id", "FirstName").Values(u, u1),
    77  			wantSql:  "INSERT INTO `user`(`id`,`first_name`) VALUES(?,?),(?,?);",
    78  			wantArgs: []interface{}{int64(12), "Tom", int64(13), "Jerry"},
    79  		},
    80  		{
    81  			name:     "ignore pk default",
    82  			builder:  NewInserter[User](db).SkipPK().Values(u),
    83  			wantSql:  "INSERT INTO `user`(`first_name`,`ctime`) VALUES(?,?);",
    84  			wantArgs: []interface{}{"Tom", uint64(1000)},
    85  		},
    86  		{
    87  			name:     "ignore pk",
    88  			builder:  NewInserter[User](db).SkipPK().Columns("Id", "FirstName").Values(u),
    89  			wantSql:  "INSERT INTO `user`(`id`,`first_name`) VALUES(?,?);",
    90  			wantArgs: []interface{}{int64(12), "Tom"},
    91  		},
    92  		{
    93  			name:     "ignore pk multi default",
    94  			builder:  NewInserter[User](db).SkipPK().Values(u, u1),
    95  			wantSql:  "INSERT INTO `user`(`first_name`,`ctime`) VALUES(?,?),(?,?);",
    96  			wantArgs: []interface{}{"Tom", uint64(1000), "Jerry", uint64(1000)},
    97  		},
    98  		{
    99  			name:     "ignore pk multi",
   100  			builder:  NewInserter[User](db).SkipPK().Columns("Id", "FirstName", "Ctime").Values(u, u1),
   101  			wantSql:  "INSERT INTO `user`(`id`,`first_name`,`ctime`) VALUES(?,?,?),(?,?,?);",
   102  			wantArgs: []interface{}{int64(12), "Tom", uint64(1000), int64(13), "Jerry", uint64(1000)},
   103  		},
   104  	}
   105  
   106  	for _, tc := range testCases {
   107  		c := tc
   108  		t.Run(tc.name, func(t *testing.T) {
   109  			q, err := c.builder.Build()
   110  			assert.Equal(t, c.wantErr, err)
   111  			if err != nil {
   112  				return
   113  			}
   114  			assert.Equal(t, c.wantSql, q.SQL)
   115  			assert.EqualValues(t, c.wantArgs, q.Args)
   116  		})
   117  	}
   118  }
   119  
   120  func TestInserter_ValuesForCombination(t *testing.T) {
   121  	type BaseEntity struct {
   122  		Id         int64 `eorm:"auto_increment,primary_key"`
   123  		CreateTime uint64
   124  	}
   125  	type User struct {
   126  		BaseEntity
   127  		FirstName string
   128  	}
   129  	type Profile struct {
   130  		BaseEntity
   131  		IdCard    int64 `eorm:"auto_increment,primary_key"`
   132  		FirstName string
   133  	}
   134  	n := uint64(1000)
   135  	idCard := int64(123456)
   136  	p := &Profile{
   137  		FirstName: "Tom",
   138  		BaseEntity: BaseEntity{
   139  			Id:         12,
   140  			CreateTime: n,
   141  		},
   142  		IdCard: idCard,
   143  	}
   144  	p1 := &Profile{
   145  		FirstName: "Jerry",
   146  		BaseEntity: BaseEntity{
   147  			Id:         13,
   148  			CreateTime: n,
   149  		},
   150  		IdCard: idCard,
   151  	}
   152  	u := &User{
   153  		FirstName: "Tom",
   154  		BaseEntity: BaseEntity{
   155  			Id:         12,
   156  			CreateTime: n,
   157  		},
   158  	}
   159  	u1 := &User{
   160  		FirstName: "Jerry",
   161  		BaseEntity: BaseEntity{
   162  			Id:         13,
   163  			CreateTime: n,
   164  		},
   165  	}
   166  	db := memoryDB()
   167  	testCases := []CommonTestCase{
   168  		{
   169  			name:    "no examples of values",
   170  			builder: NewInserter[User](db).Values(),
   171  			wantErr: errors.New("插入0行"),
   172  		},
   173  		{
   174  			name:     "single example of values",
   175  			builder:  NewInserter[User](db).Values(u),
   176  			wantSql:  "INSERT INTO `user`(`id`,`create_time`,`first_name`) VALUES(?,?,?);",
   177  			wantArgs: []interface{}{int64(12), n, "Tom"},
   178  		},
   179  
   180  		{
   181  			name:     "multiple values of same type",
   182  			builder:  NewInserter[User](db).Values(u, u1),
   183  			wantSql:  "INSERT INTO `user`(`id`,`create_time`,`first_name`) VALUES(?,?,?),(?,?,?);",
   184  			wantArgs: []interface{}{int64(12), n, "Tom", int64(13), n, "Jerry"},
   185  		},
   186  
   187  		{
   188  			name:     "no example of a whole columns",
   189  			builder:  NewInserter[User](db).Columns("Id", "FirstName").Values(u),
   190  			wantSql:  "INSERT INTO `user`(`id`,`first_name`) VALUES(?,?);",
   191  			wantArgs: []interface{}{int64(12), "Tom"},
   192  		},
   193  
   194  		{
   195  			name:     "no example of a whole columns2",
   196  			builder:  NewInserter[User](db).Columns("FirstName", "Id").Values(u),
   197  			wantSql:  "INSERT INTO `user`(`first_name`,`id`) VALUES(?,?);",
   198  			wantArgs: []interface{}{"Tom", int64(12)},
   199  		},
   200  		{
   201  			name:    "an example with invalid columns",
   202  			builder: NewInserter[User](db).Columns("id", "FirstName").Values(u),
   203  			wantErr: errors.New("eorm: 未知字段 id"),
   204  		},
   205  		{
   206  			name:     "no whole columns and multiple values of same type",
   207  			builder:  NewInserter[User](db).Columns("Id", "FirstName").Values(u, u1),
   208  			wantSql:  "INSERT INTO `user`(`id`,`first_name`) VALUES(?,?),(?,?);",
   209  			wantArgs: []interface{}{int64(12), "Tom", int64(13), "Jerry"},
   210  		},
   211  		{
   212  			name:     "ignore pk default",
   213  			builder:  NewInserter[User](db).SkipPK().Values(u),
   214  			wantSql:  "INSERT INTO `user`(`create_time`,`first_name`) VALUES(?,?);",
   215  			wantArgs: []interface{}{uint64(1000), "Tom"},
   216  		},
   217  		{
   218  			name:     "ignore pk",
   219  			builder:  NewInserter[User](db).SkipPK().Columns("Id", "CreateTime", "FirstName").Values(u),
   220  			wantSql:  "INSERT INTO `user`(`id`,`create_time`,`first_name`) VALUES(?,?,?);",
   221  			wantArgs: []interface{}{int64(12), uint64(1000), "Tom"},
   222  		},
   223  		{
   224  			name:     "ignore pk multi default",
   225  			builder:  NewInserter[User](db).SkipPK().Values(u, u1),
   226  			wantSql:  "INSERT INTO `user`(`create_time`,`first_name`) VALUES(?,?),(?,?);",
   227  			wantArgs: []interface{}{uint64(1000), "Tom", uint64(1000), "Jerry"},
   228  		},
   229  		{
   230  			name:     "ignore pk multi",
   231  			builder:  NewInserter[User](db).SkipPK().Columns("Id", "CreateTime", "FirstName").Values(u, u1),
   232  			wantSql:  "INSERT INTO `user`(`id`,`create_time`,`first_name`) VALUES(?,?,?),(?,?,?);",
   233  			wantArgs: []interface{}{int64(12), uint64(1000), "Tom", int64(13), uint64(1000), "Jerry"},
   234  		},
   235  
   236  		{
   237  			name:     "ignore multi pk default",
   238  			builder:  NewInserter[Profile](db).SkipPK().Values(p),
   239  			wantSql:  "INSERT INTO `profile`(`create_time`,`first_name`) VALUES(?,?);",
   240  			wantArgs: []interface{}{uint64(1000), "Tom"},
   241  		},
   242  		{
   243  			name:     "ignore multi pk multi data default",
   244  			builder:  NewInserter[Profile](db).SkipPK().Values(p, p1),
   245  			wantSql:  "INSERT INTO `profile`(`create_time`,`first_name`) VALUES(?,?),(?,?);",
   246  			wantArgs: []interface{}{uint64(1000), "Tom", uint64(1000), "Jerry"},
   247  		},
   248  
   249  		{
   250  			name:     "ignore multi pk",
   251  			builder:  NewInserter[Profile](db).SkipPK().Columns("Id", "CreateTime", "FirstName", "IdCard").Values(p),
   252  			wantSql:  "INSERT INTO `profile`(`id`,`create_time`,`first_name`,`id_card`) VALUES(?,?,?,?);",
   253  			wantArgs: []interface{}{int64(12), uint64(1000), "Tom", int64(123456)},
   254  		},
   255  		{
   256  			name:     "ignore multi pk multi data",
   257  			builder:  NewInserter[Profile](db).SkipPK().Columns("Id", "CreateTime", "FirstName", "IdCard").Values(p, p1),
   258  			wantSql:  "INSERT INTO `profile`(`id`,`create_time`,`first_name`,`id_card`) VALUES(?,?,?,?),(?,?,?,?);",
   259  			wantArgs: []interface{}{int64(12), uint64(1000), "Tom", int64(123456), int64(13), uint64(1000), "Jerry", int64(123456)},
   260  		},
   261  	}
   262  
   263  	for _, tc := range testCases {
   264  		c := tc
   265  		t.Run(tc.name, func(t *testing.T) {
   266  			q, err := c.builder.Build()
   267  			assert.Equal(t, c.wantErr, err)
   268  			if err != nil {
   269  				return
   270  			}
   271  			assert.Equal(t, c.wantSql, q.SQL)
   272  			assert.Equal(t, c.wantArgs, q.Args)
   273  		})
   274  	}
   275  }
   276  
   277  func TestInserter_Exec(t *testing.T) {
   278  	orm := memoryDB()
   279  	testCases := []struct {
   280  		name         string
   281  		i            *Inserter[TestModel]
   282  		wantErr      string
   283  		wantAffected int64
   284  	}{
   285  		{
   286  			name:    "invalid query",
   287  			i:       NewInserter[TestModel](orm).Values(),
   288  			wantErr: "插入0行",
   289  		},
   290  		{
   291  			// 表没创建
   292  			name:    "table not exist",
   293  			i:       NewInserter[TestModel](orm).Values(&TestModel{}),
   294  			wantErr: "no such table: test_model",
   295  		},
   296  	}
   297  
   298  	for _, tc := range testCases {
   299  		t.Run(tc.name, func(t *testing.T) {
   300  			res := tc.i.Exec(context.Background())
   301  			if res.Err() != nil {
   302  				assert.EqualError(t, res.Err(), tc.wantErr)
   303  				return
   304  			}
   305  			assert.Nil(t, tc.wantErr)
   306  			affected, err := res.RowsAffected()
   307  			if err != nil {
   308  				t.Fatal(err)
   309  			}
   310  			assert.Equal(t, tc.wantAffected, affected)
   311  		})
   312  	}
   313  }
   314  
   315  func ExampleInserter_Build() {
   316  	db := memoryDB()
   317  	query, _ := NewInserter[TestModel](db).Values(&TestModel{
   318  		Id:  1,
   319  		Age: 18,
   320  	}).Build()
   321  	fmt.Printf("case1\n%s", query.String())
   322  
   323  	query, _ = NewInserter[TestModel](db).Values(&TestModel{}).Build()
   324  	fmt.Printf("case2\n%s", query.String())
   325  
   326  	// Output:
   327  	// case1
   328  	// SQL: INSERT INTO `test_model`(`id`,`first_name`,`age`,`last_name`) VALUES(?,?,?,?);
   329  	// Args: []interface {}{1, "", 18, (*sql.NullString)(nil)}
   330  	// case2
   331  	// SQL: INSERT INTO `test_model`(`id`,`first_name`,`age`,`last_name`) VALUES(?,?,?,?);
   332  	// Args: []interface {}{0, "", 0, (*sql.NullString)(nil)}
   333  }
   334  
   335  func ExampleInserter_Columns() {
   336  	db := memoryDB()
   337  	query, _ := NewInserter[TestModel](db).Values(&TestModel{
   338  		Id:  1,
   339  		Age: 18,
   340  	}).Columns("Id", "Age").Build()
   341  	fmt.Printf("case1\n%s", query.String())
   342  
   343  	query, _ = NewInserter[TestModel](db).Values(&TestModel{
   344  		Id:  1,
   345  		Age: 18,
   346  	}, &TestModel{}, &TestModel{FirstName: "Tom"}).Columns("Id", "Age").Build()
   347  	fmt.Printf("case2\n%s", query.String())
   348  
   349  	// Output:
   350  	// case1
   351  	// SQL: INSERT INTO `test_model`(`id`,`age`) VALUES(?,?);
   352  	// Args: []interface {}{1, 18}
   353  	// case2
   354  	// SQL: INSERT INTO `test_model`(`id`,`age`) VALUES(?,?),(?,?),(?,?);
   355  	// Args: []interface {}{1, 18, 0, 0, 0, 0}
   356  
   357  }
   358  
   359  func ExampleInserter_Values() {
   360  	db := memoryDB()
   361  	query, _ := NewInserter[TestModel](db).Values(&TestModel{
   362  		Id:  1,
   363  		Age: 18,
   364  	}, &TestModel{}).Build()
   365  	fmt.Println(query.String())
   366  	// Output:
   367  	// SQL: INSERT INTO `test_model`(`id`,`first_name`,`age`,`last_name`) VALUES(?,?,?,?),(?,?,?,?);
   368  	// Args: []interface {}{1, "", 18, (*sql.NullString)(nil), 0, "", 0, (*sql.NullString)(nil)}
   369  }
   370  
   371  func ExampleNewInserter() {
   372  	db := memoryDB()
   373  	tm := &TestModel{}
   374  	query, _ := NewInserter[TestModel](db).Values(tm).Build()
   375  	fmt.Printf("SQL: %s", query.SQL)
   376  	// Output:
   377  	// SQL: INSERT INTO `test_model`(`id`,`first_name`,`age`,`last_name`) VALUES(?,?,?,?);
   378  }