github.com/ecodeclub/eorm@v0.0.2-0.20231001112437-dae71da914d0/internal/datasource/transaction/delay_transaction_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 15 package transaction_test 16 17 import ( 18 "context" 19 "database/sql" 20 "errors" 21 "regexp" 22 "strings" 23 "testing" 24 25 "github.com/ecodeclub/eorm/internal/datasource" 26 "github.com/ecodeclub/eorm/internal/datasource/cluster" 27 "github.com/ecodeclub/eorm/internal/datasource/shardingsource" 28 "github.com/ecodeclub/eorm/internal/errs" 29 "github.com/ecodeclub/eorm/internal/model" 30 "go.uber.org/multierr" 31 32 "github.com/DATA-DOG/go-sqlmock" 33 "github.com/ecodeclub/eorm" 34 "github.com/ecodeclub/eorm/internal/datasource/masterslave" 35 "github.com/ecodeclub/eorm/internal/datasource/transaction" 36 "github.com/ecodeclub/eorm/internal/test" 37 "github.com/stretchr/testify/assert" 38 "github.com/stretchr/testify/require" 39 "github.com/stretchr/testify/suite" 40 ) 41 42 type TestDelayTxTestSuite struct { 43 ShardingTransactionSuite 44 } 45 46 func (s *TestDelayTxTestSuite) TestExecute_Commit_Or_Rollback() { 47 t := s.T() 48 testCases := []struct { 49 name string 50 wantAffected int64 51 wantErr error 52 values []*test.OrderDetail 53 querySet []*test.OrderDetail 54 txFunc func() (*eorm.Tx, error) 55 mockOrder func(mock1, mock2 sqlmock.Sqlmock) 56 afterFunc func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) 57 }{ 58 { 59 name: "begin err", 60 wantErr: errors.New("begin err"), 61 querySet: []*test.OrderDetail{ 62 {OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"}, 63 {OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"}, 64 {OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"}, 65 {OrderId: 253, ItemId: 8, UsingCol1: "Stephen", UsingCol2: "Curry"}, 66 {OrderId: 181, ItemId: 11, UsingCol1: "Kawhi", UsingCol2: "Leonard"}, 67 }, 68 mockOrder: func(mock1, mock2 sqlmock.Sqlmock) { 69 mock2.ExpectBegin().WillReturnError(errors.New("begin err")) 70 mock1.ExpectBegin().WillReturnError(errors.New("begin err")) 71 }, 72 txFunc: func() (*eorm.Tx, error) { 73 return s.shardingDB.BeginTx(transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{}) 74 }, 75 afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) {}, 76 }, 77 { 78 name: "not find data source err", 79 wantErr: errs.NewErrNotFoundTargetDataSource("0.db.cluster.company.com:3306"), 80 mockOrder: func(mock1, mock2 sqlmock.Sqlmock) {}, 81 afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) {}, 82 txFunc: func() (*eorm.Tx, error) { 83 ds := shardingsource.NewShardingDataSource(map[string]datasource.DataSource{ 84 "1.db.cluster.company.com:3306": s.clusterDB, 85 }) 86 r := model.NewMetaRegistry() 87 _, err := r.Register(&test.OrderDetail{}, 88 model.WithTableShardingAlgorithm(s.algorithm)) 89 require.NoError(t, err) 90 db, err := eorm.OpenDS("mysql", ds, eorm.DBWithMetaRegistry(r)) 91 require.NoError(t, err) 92 return db.BeginTx(transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{}) 93 }, 94 }, 95 { 96 name: "not complete Finder err", 97 wantErr: errs.NewErrNotCompleteFinder("0.db.cluster.company.com:3306"), 98 mockOrder: func(mock1, mock2 sqlmock.Sqlmock) {}, 99 afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) {}, 100 txFunc: func() (*eorm.Tx, error) { 101 ds := shardingsource.NewShardingDataSource(map[string]datasource.DataSource{ 102 "0.db.cluster.company.com:3306": masterslave.NewMasterSlavesDB(s.mockMaster1DB, masterslave.MasterSlavesWithSlaves( 103 newSlaves(t, s.mockSlave1DB, s.mockSlave2DB, s.mockSlave3DB))), 104 }) 105 r := model.NewMetaRegistry() 106 _, err := r.Register(&test.OrderDetail{}, 107 model.WithTableShardingAlgorithm(s.algorithm)) 108 require.NoError(t, err) 109 db, err := eorm.OpenDS("mysql", ds, eorm.DBWithMetaRegistry(r)) 110 require.NoError(t, err) 111 return db.BeginTx(transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{}) 112 }, 113 }, 114 { 115 name: "not find target db err", 116 wantErr: errs.NewErrNotFoundTargetDB("order_detail_db_1"), 117 mockOrder: func(mock1, mock2 sqlmock.Sqlmock) { 118 mock1.ExpectBegin() 119 }, 120 afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) {}, 121 txFunc: func() (*eorm.Tx, error) { 122 clusterDB := cluster.NewClusterDB(map[string]*masterslave.MasterSlavesDB{ 123 "order_detail_db_0": masterslave.NewMasterSlavesDB(s.mockMaster1DB, masterslave.MasterSlavesWithSlaves( 124 newSlaves(t, s.mockSlave1DB, s.mockSlave2DB, s.mockSlave3DB))), 125 }) 126 ds := shardingsource.NewShardingDataSource(map[string]datasource.DataSource{ 127 "0.db.cluster.company.com:3306": clusterDB, 128 }) 129 r := model.NewMetaRegistry() 130 _, err := r.Register(&test.OrderDetail{}, 131 model.WithTableShardingAlgorithm(s.algorithm)) 132 require.NoError(t, err) 133 db, err := eorm.OpenDS("mysql", ds, eorm.DBWithMetaRegistry(r)) 134 require.NoError(t, err) 135 return db.BeginTx(transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{}) 136 }, 137 }, 138 { 139 name: "select insert all commit err", 140 wantAffected: 2, 141 values: []*test.OrderDetail{ 142 {OrderId: 288, ItemId: 101, UsingCol1: "Jimmy", UsingCol2: "Butler"}, 143 {OrderId: 33, ItemId: 100, UsingCol1: "Nikolai", UsingCol2: "Jokic"}, 144 }, 145 querySet: []*test.OrderDetail{ 146 {OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"}, 147 {OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"}, 148 {OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"}, 149 {OrderId: 253, ItemId: 8, UsingCol1: "Stephen", UsingCol2: "Curry"}, 150 {OrderId: 181, ItemId: 11, UsingCol1: "Kawhi", UsingCol2: "Leonard"}, 151 }, 152 mockOrder: func(mock1, mock2 sqlmock.Sqlmock) { 153 mock1.MatchExpectationsInOrder(false) 154 mock2.MatchExpectationsInOrder(false) 155 mock1.ExpectBegin() 156 mock2.ExpectBegin() 157 158 mock1.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_0` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_1` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_2` WHERE `order_id`!=?;")). 159 WithArgs(123, 123, 123). 160 WillReturnRows(mock1.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(234, 12, "Kevin", "Durant").AddRow(8, 6, "Kobe", "Bryant")) 161 162 mock2.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_0` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_1` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_2` WHERE `order_id`!=?;")). 163 WithArgs(123, 123, 123). 164 WillReturnRows(mock2.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(253, 8, "Stephen", "Curry").AddRow(181, 11, "Kawhi", "Leonard").AddRow(11, 8, "James", "Harden")) 165 166 mock1.ExpectExec(regexp.QuoteMeta("INSERT INTO `order_detail_db_0`.`order_detail_tab_0`(`order_id`,`item_id`,`using_col1`,`using_col2`) VALUES(?,?,?,?);")). 167 WithArgs(288, 101, "Jimmy", "Butler").WillReturnResult(sqlmock.NewResult(1, 1)) 168 mock2.ExpectExec(regexp.QuoteMeta("INSERT INTO `order_detail_db_1`.`order_detail_tab_0`(`order_id`,`item_id`,`using_col1`,`using_col2`) VALUES(?,?,?,?);")). 169 WithArgs(33, 100, "Nikolai", "Jokic").WillReturnResult(sqlmock.NewResult(1, 1)) 170 171 commitErr := errors.New("commit fail") 172 mock1.ExpectCommit().WillReturnError(commitErr) 173 mock2.ExpectCommit().WillReturnError(commitErr) 174 }, 175 txFunc: func() (*eorm.Tx, error) { 176 return s.shardingDB.BeginTx(transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{}) 177 }, 178 afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) { 179 err := tx.Commit() 180 newErr := errors.New("commit fail") 181 errSlice := strings.Split(err.Error(), "; ") 182 wantErrSlice := []string{ 183 newMockCommitErr("order_detail_db_0", newErr).Error(), 184 newMockCommitErr("order_detail_db_1", newErr).Error()} 185 assert.ElementsMatch(t, wantErrSlice, errSlice) 186 187 s.mockMaster.MatchExpectationsInOrder(false) 188 s.mockMaster2.MatchExpectationsInOrder(false) 189 rows := s.mockMaster.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}) 190 s.mockMaster.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_0` WHERE (`order_id`=?) OR (`order_id`=?);")). 191 WithArgs(288, 33).WillReturnRows(rows) 192 193 s.mockMaster2.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_0` WHERE (`order_id`=?) OR (`order_id`=?);")). 194 WithArgs(288, 33).WillReturnRows(rows) 195 196 queryVal := s.findTgt(t, values) 197 var wantOds []*test.OrderDetail 198 assert.ElementsMatch(t, wantOds, queryVal) 199 }, 200 }, 201 { 202 name: "select insert part commit err", 203 wantAffected: 2, 204 values: []*test.OrderDetail{ 205 {OrderId: 288, ItemId: 101, UsingCol1: "Jimmy", UsingCol2: "Butler"}, 206 {OrderId: 33, ItemId: 100, UsingCol1: "Nikolai", UsingCol2: "Jokic"}, 207 }, 208 querySet: []*test.OrderDetail{ 209 {OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"}, 210 {OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"}, 211 {OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"}, 212 {OrderId: 253, ItemId: 8, UsingCol1: "Stephen", UsingCol2: "Curry"}, 213 {OrderId: 181, ItemId: 11, UsingCol1: "Kawhi", UsingCol2: "Leonard"}, 214 }, 215 mockOrder: func(mock1, mock2 sqlmock.Sqlmock) { 216 mock1.MatchExpectationsInOrder(false) 217 mock2.MatchExpectationsInOrder(false) 218 mock1.ExpectBegin() 219 mock2.ExpectBegin() 220 221 mock1.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_0` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_1` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_2` WHERE `order_id`!=?;")). 222 WithArgs(123, 123, 123). 223 WillReturnRows(mock1.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(234, 12, "Kevin", "Durant").AddRow(8, 6, "Kobe", "Bryant")) 224 225 mock2.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_0` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_1` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_2` WHERE `order_id`!=?;")). 226 WithArgs(123, 123, 123). 227 WillReturnRows(mock1.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(253, 8, "Stephen", "Curry").AddRow(181, 11, "Kawhi", "Leonard").AddRow(11, 8, "James", "Harden")) 228 229 mock1.ExpectExec(regexp.QuoteMeta("INSERT INTO `order_detail_db_0`.`order_detail_tab_0`(`order_id`,`item_id`,`using_col1`,`using_col2`) VALUES(?,?,?,?);")). 230 WithArgs(288, 101, "Jimmy", "Butler").WillReturnResult(sqlmock.NewResult(1, 1)) 231 mock2.ExpectExec(regexp.QuoteMeta("INSERT INTO `order_detail_db_1`.`order_detail_tab_0`(`order_id`,`item_id`,`using_col1`,`using_col2`) VALUES(?,?,?,?);")). 232 WithArgs(33, 100, "Nikolai", "Jokic").WillReturnResult(sqlmock.NewResult(1, 1)) 233 234 mock1.ExpectCommit() 235 mock2.ExpectCommit().WillReturnError(errors.New("commit fail")) 236 }, 237 txFunc: func() (*eorm.Tx, error) { 238 return s.shardingDB.BeginTx(transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{}) 239 }, 240 afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) { 241 err := tx.Commit() 242 wantErr := multierr.Combine(newMockCommitErr("order_detail_db_1", errors.New("commit fail"))) 243 assert.Equal(t, wantErr, err) 244 245 s.mockMaster.MatchExpectationsInOrder(false) 246 s.mockMaster2.MatchExpectationsInOrder(false) 247 248 rows := s.mockMaster.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}) 249 s.mockMaster.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_0` WHERE (`order_id`=?) OR (`order_id`=?);")). 250 WithArgs(288, 33).WillReturnRows(rows) 251 252 s.mockMaster2.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_0` WHERE (`order_id`=?) OR (`order_id`=?);")). 253 WithArgs(288, 33).WillReturnRows(rows) 254 255 queryVal := s.findTgt(t, values) 256 var wantVal []*test.OrderDetail 257 assert.ElementsMatch(t, wantVal, queryVal) 258 }, 259 }, 260 { 261 name: "select insert all rollback err", 262 wantAffected: 2, 263 values: []*test.OrderDetail{ 264 {OrderId: 288, ItemId: 101, UsingCol1: "Jimmy", UsingCol2: "Butler"}, 265 {OrderId: 33, ItemId: 100, UsingCol1: "Nikolai", UsingCol2: "Jokic"}, 266 }, 267 querySet: []*test.OrderDetail{ 268 {OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"}, 269 {OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"}, 270 {OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"}, 271 {OrderId: 253, ItemId: 8, UsingCol1: "Stephen", UsingCol2: "Curry"}, 272 {OrderId: 181, ItemId: 11, UsingCol1: "Kawhi", UsingCol2: "Leonard"}, 273 }, 274 mockOrder: func(mock1, mock2 sqlmock.Sqlmock) { 275 mock1.MatchExpectationsInOrder(false) 276 mock2.MatchExpectationsInOrder(false) 277 mock1.ExpectBegin() 278 mock2.ExpectBegin() 279 280 mock1.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_0` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_1` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_2` WHERE `order_id`!=?;")). 281 WithArgs(123, 123, 123). 282 WillReturnRows(mock1.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(234, 12, "Kevin", "Durant").AddRow(8, 6, "Kobe", "Bryant")) 283 284 mock2.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_0` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_1` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_2` WHERE `order_id`!=?;")). 285 WithArgs(123, 123, 123). 286 WillReturnRows(mock1.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(253, 8, "Stephen", "Curry").AddRow(181, 11, "Kawhi", "Leonard").AddRow(11, 8, "James", "Harden")) 287 288 mock1.ExpectExec(regexp.QuoteMeta("INSERT INTO `order_detail_db_0`.`order_detail_tab_0`(`order_id`,`item_id`,`using_col1`,`using_col2`) VALUES(?,?,?,?);")). 289 WithArgs(288, 101, "Jimmy", "Butler").WillReturnResult(sqlmock.NewResult(1, 1)) 290 mock2.ExpectExec(regexp.QuoteMeta("INSERT INTO `order_detail_db_1`.`order_detail_tab_0`(`order_id`,`item_id`,`using_col1`,`using_col2`) VALUES(?,?,?,?);")). 291 WithArgs(33, 100, "Nikolai", "Jokic").WillReturnResult(sqlmock.NewResult(1, 1)) 292 293 rollbackErr := errors.New("rollback fail") 294 mock1.ExpectRollback().WillReturnError(rollbackErr) 295 mock2.ExpectRollback().WillReturnError(rollbackErr) 296 }, 297 txFunc: func() (*eorm.Tx, error) { 298 return s.shardingDB.BeginTx(transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{}) 299 }, 300 afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) { 301 err := tx.Rollback() 302 newErr := errors.New("rollback fail") 303 errSlice := strings.Split(err.Error(), "; ") 304 wantErrSlice := []string{ 305 newMockRollbackErr("order_detail_db_0", newErr).Error(), 306 newMockRollbackErr("order_detail_db_1", newErr).Error()} 307 assert.ElementsMatch(t, wantErrSlice, errSlice) 308 309 s.mockMaster.MatchExpectationsInOrder(false) 310 s.mockMaster2.MatchExpectationsInOrder(false) 311 312 rows := s.mockMaster.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}) 313 s.mockMaster.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_0` WHERE (`order_id`=?) OR (`order_id`=?);")). 314 WithArgs(288, 33).WillReturnRows(rows) 315 316 s.mockMaster2.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_0` WHERE (`order_id`=?) OR (`order_id`=?);")). 317 WithArgs(288, 33).WillReturnRows(rows) 318 319 queryVal := s.findTgt(t, values) 320 var wantOds []*test.OrderDetail 321 assert.ElementsMatch(t, wantOds, queryVal) 322 }, 323 }, 324 { 325 name: "select insert part rollback err", 326 wantAffected: 2, 327 values: []*test.OrderDetail{ 328 {OrderId: 288, ItemId: 101, UsingCol1: "Jimmy", UsingCol2: "Butler"}, 329 {OrderId: 33, ItemId: 100, UsingCol1: "Nikolai", UsingCol2: "Jokic"}, 330 }, 331 querySet: []*test.OrderDetail{ 332 {OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"}, 333 {OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"}, 334 {OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"}, 335 {OrderId: 253, ItemId: 8, UsingCol1: "Stephen", UsingCol2: "Curry"}, 336 {OrderId: 181, ItemId: 11, UsingCol1: "Kawhi", UsingCol2: "Leonard"}, 337 }, 338 mockOrder: func(mock1, mock2 sqlmock.Sqlmock) { 339 mock1.MatchExpectationsInOrder(false) 340 mock2.MatchExpectationsInOrder(false) 341 mock1.ExpectBegin() 342 mock2.ExpectBegin() 343 344 mock1.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_0` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_1` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_2` WHERE `order_id`!=?;")). 345 WithArgs(123, 123, 123). 346 WillReturnRows(mock1.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(234, 12, "Kevin", "Durant").AddRow(8, 6, "Kobe", "Bryant")) 347 348 mock2.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_0` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_1` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_2` WHERE `order_id`!=?;")). 349 WithArgs(123, 123, 123). 350 WillReturnRows(mock1.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(253, 8, "Stephen", "Curry").AddRow(181, 11, "Kawhi", "Leonard").AddRow(11, 8, "James", "Harden")) 351 352 mock1.ExpectExec(regexp.QuoteMeta("INSERT INTO `order_detail_db_0`.`order_detail_tab_0`(`order_id`,`item_id`,`using_col1`,`using_col2`) VALUES(?,?,?,?);")). 353 WithArgs(288, 101, "Jimmy", "Butler").WillReturnResult(sqlmock.NewResult(1, 1)) 354 mock2.ExpectExec(regexp.QuoteMeta("INSERT INTO `order_detail_db_1`.`order_detail_tab_0`(`order_id`,`item_id`,`using_col1`,`using_col2`) VALUES(?,?,?,?);")). 355 WithArgs(33, 100, "Nikolai", "Jokic").WillReturnResult(sqlmock.NewResult(1, 1)) 356 357 mock1.ExpectRollback().WillReturnError(errors.New("rollback fail")) 358 mock2.ExpectRollback() 359 }, 360 txFunc: func() (*eorm.Tx, error) { 361 return s.shardingDB.BeginTx(transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{}) 362 }, 363 afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) { 364 err := tx.Rollback() 365 wantErr := multierr.Combine(newMockRollbackErr("order_detail_db_0", errors.New("rollback fail"))) 366 assert.Equal(t, wantErr, err) 367 368 s.mockMaster.MatchExpectationsInOrder(false) 369 s.mockMaster2.MatchExpectationsInOrder(false) 370 371 rows := s.mockMaster.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}) 372 s.mockMaster.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_0` WHERE (`order_id`=?) OR (`order_id`=?);")). 373 WithArgs(288, 33).WillReturnRows(rows) 374 375 s.mockMaster2.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_0` WHERE (`order_id`=?) OR (`order_id`=?);")). 376 WithArgs(288, 33).WillReturnRows(rows) 377 378 queryVal := s.findTgt(t, values) 379 var wantOds []*test.OrderDetail 380 assert.ElementsMatch(t, wantOds, queryVal) 381 }, 382 }, 383 { 384 name: "select insert commit", 385 wantAffected: 2, 386 values: []*test.OrderDetail{ 387 {OrderId: 288, ItemId: 101, UsingCol1: "Jimmy", UsingCol2: "Butler"}, 388 {OrderId: 33, ItemId: 100, UsingCol1: "Nikolai", UsingCol2: "Jokic"}, 389 }, 390 querySet: []*test.OrderDetail{ 391 {OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"}, 392 {OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"}, 393 {OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"}, 394 {OrderId: 253, ItemId: 8, UsingCol1: "Stephen", UsingCol2: "Curry"}, 395 {OrderId: 181, ItemId: 11, UsingCol1: "Kawhi", UsingCol2: "Leonard"}, 396 }, 397 mockOrder: func(mock1, mock2 sqlmock.Sqlmock) { 398 mock1.MatchExpectationsInOrder(false) 399 mock2.MatchExpectationsInOrder(false) 400 mock1.ExpectBegin() 401 mock2.ExpectBegin() 402 403 mock1.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_0` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_1` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_2` WHERE `order_id`!=?;")). 404 WithArgs(123, 123, 123). 405 WillReturnRows(mock1.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(234, 12, "Kevin", "Durant").AddRow(8, 6, "Kobe", "Bryant")) 406 407 mock2.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_0` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_1` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_2` WHERE `order_id`!=?;")). 408 WithArgs(123, 123, 123). 409 WillReturnRows(mock1.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(253, 8, "Stephen", "Curry").AddRow(181, 11, "Kawhi", "Leonard").AddRow(11, 8, "James", "Harden")) 410 411 mock1.ExpectExec(regexp.QuoteMeta("INSERT INTO `order_detail_db_0`.`order_detail_tab_0`(`order_id`,`item_id`,`using_col1`,`using_col2`) VALUES(?,?,?,?);")). 412 WithArgs(288, 101, "Jimmy", "Butler").WillReturnResult(sqlmock.NewResult(1, 1)) 413 mock2.ExpectExec(regexp.QuoteMeta("INSERT INTO `order_detail_db_1`.`order_detail_tab_0`(`order_id`,`item_id`,`using_col1`,`using_col2`) VALUES(?,?,?,?);")). 414 WithArgs(33, 100, "Nikolai", "Jokic").WillReturnResult(sqlmock.NewResult(1, 1)) 415 416 mock1.ExpectCommit() 417 mock2.ExpectCommit() 418 }, 419 txFunc: func() (*eorm.Tx, error) { 420 return s.shardingDB.BeginTx(transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{}) 421 }, 422 afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) { 423 err := tx.Commit() 424 require.NoError(t, err) 425 426 s.mockMaster.MatchExpectationsInOrder(false) 427 s.mockMaster2.MatchExpectationsInOrder(false) 428 429 s.mockMaster.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_0` WHERE (`order_id`=?) OR (`order_id`=?);")). 430 WithArgs(288, 33).WillReturnRows(s.mockMaster.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(288, 101, "Jimmy", "Butler")) 431 432 s.mockMaster2.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_0` WHERE (`order_id`=?) OR (`order_id`=?);")). 433 WithArgs(288, 33).WillReturnRows(s.mockMaster.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(33, 100, "Nikolai", "Jokic")) 434 435 queryVal := s.findTgt(t, values) 436 assert.ElementsMatch(t, values, queryVal) 437 }, 438 }, 439 { 440 name: "select insert rollback", 441 wantAffected: 2, 442 values: []*test.OrderDetail{ 443 {OrderId: 199, ItemId: 100, UsingCol1: "Jason", UsingCol2: "Tatum"}, 444 {OrderId: 299, ItemId: 101, UsingCol1: "Paul", UsingCol2: "George"}, 445 }, 446 querySet: []*test.OrderDetail{ 447 {OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"}, 448 {OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"}, 449 {OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"}, 450 {OrderId: 253, ItemId: 8, UsingCol1: "Stephen", UsingCol2: "Curry"}, 451 {OrderId: 181, ItemId: 11, UsingCol1: "Kawhi", UsingCol2: "Leonard"}, 452 }, 453 mockOrder: func(mock1, mock2 sqlmock.Sqlmock) { 454 mock1.MatchExpectationsInOrder(false) 455 mock2.MatchExpectationsInOrder(false) 456 mock1.ExpectBegin() 457 mock2.ExpectBegin() 458 459 mock1.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_0` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_1` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_0`.`order_detail_tab_2` WHERE `order_id`!=?;")). 460 WithArgs(123, 123, 123). 461 WillReturnRows(mock1.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(234, 12, "Kevin", "Durant").AddRow(8, 6, "Kobe", "Bryant")) 462 463 mock2.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_0` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_1` WHERE `order_id`!=?;SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_2` WHERE `order_id`!=?;")). 464 WithArgs(123, 123, 123). 465 WillReturnRows(mock1.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}).AddRow(253, 8, "Stephen", "Curry").AddRow(181, 11, "Kawhi", "Leonard").AddRow(11, 8, "James", "Harden")) 466 467 mock2.ExpectExec(regexp.QuoteMeta("INSERT INTO `order_detail_db_1`.`order_detail_tab_1`(`order_id`,`item_id`,`using_col1`,`using_col2`) VALUES(?,?,?,?);")). 468 WithArgs(199, 100, "Jason", "Tatum").WillReturnResult(sqlmock.NewResult(1, 1)) 469 mock2.ExpectExec(regexp.QuoteMeta("INSERT INTO `order_detail_db_1`.`order_detail_tab_2`(`order_id`,`item_id`,`using_col1`,`using_col2`) VALUES(?,?,?,?);")). 470 WithArgs(299, 101, "Paul", "George").WillReturnResult(sqlmock.NewResult(1, 1)) 471 472 mock1.ExpectRollback() 473 mock2.ExpectRollback() 474 }, 475 txFunc: func() (*eorm.Tx, error) { 476 return s.shardingDB.BeginTx(transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{}) 477 }, 478 afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) { 479 err := tx.Rollback() 480 require.NoError(t, err) 481 s.mockMaster2.MatchExpectationsInOrder(false) 482 483 rows := s.mockMaster2.NewRows([]string{"order_id", "item_id", "using_col1", "using_col2"}) 484 s.mockMaster2.ExpectQuery(regexp.QuoteMeta("SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_2` WHERE (`order_id`=?) OR (`order_id`=?);SELECT `order_id`,`item_id`,`using_col1`,`using_col2` FROM `order_detail_db_1`.`order_detail_tab_1` WHERE (`order_id`=?) OR (`order_id`=?);")). 485 WithArgs(199, 299, 199, 299).WillReturnRows(rows) 486 }, 487 }, 488 } 489 for _, tc := range testCases { 490 t.Run(tc.name, func(t *testing.T) { 491 tc.mockOrder(s.mockMaster, s.mockMaster2) 492 tx, err := tc.txFunc() 493 require.NoError(t, err) 494 495 querySet, err := eorm.NewShardingSelector[test.OrderDetail](tx). 496 Where(eorm.C("OrderId").NEQ(123)). 497 GetMulti(masterslave.UseMaster(context.Background())) 498 assert.Equal(t, tc.wantErr, err) 499 if err != nil { 500 return 501 } 502 assert.ElementsMatch(t, tc.querySet, querySet) 503 504 values := tc.values 505 res := eorm.NewShardingInsert[test.OrderDetail](tx). 506 Values(values).Exec(context.Background()) 507 affected, err := res.RowsAffected() 508 require.NoError(t, err) 509 assert.Equal(t, tc.wantAffected, affected) 510 tc.afterFunc(t, tx, values) 511 }) 512 } 513 } 514 515 func TestDelayTransactionSuite(t *testing.T) { 516 suite.Run(t, &TestDelayTxTestSuite{ 517 ShardingTransactionSuite: newShardingTransactionSuite(), 518 }) 519 }