github.com/ecodeclub/eorm@v0.0.2-0.20231001112437-dae71da914d0/internal/integration/sharding_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  //go:build e2e
    16  
    17  package integration
    18  
    19  import (
    20  	"context"
    21  	"database/sql"
    22  	"testing"
    23  
    24  	"github.com/ecodeclub/eorm/internal/datasource/masterslave"
    25  	"github.com/ecodeclub/eorm/internal/datasource/transaction"
    26  
    27  	"github.com/ecodeclub/eorm"
    28  	"github.com/ecodeclub/eorm/internal/test"
    29  	"github.com/stretchr/testify/assert"
    30  	"github.com/stretchr/testify/require"
    31  	"github.com/stretchr/testify/suite"
    32  )
    33  
    34  type ShardingDelayTxTestSuite struct {
    35  	ShardingSelectUpdateInsertSuite
    36  }
    37  
    38  func (s *ShardingDelayTxTestSuite) TestDoubleShardingSelect() {
    39  	t := s.T()
    40  	testCases := []struct {
    41  		name     string
    42  		wantErr  error
    43  		querySet []*test.OrderDetail
    44  		txFunc   func(t *testing.T) *eorm.Tx
    45  	}{
    46  		{
    47  			name: "double select",
    48  			querySet: []*test.OrderDetail{
    49  				{OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"},
    50  				{OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"},
    51  				{OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"},
    52  				{OrderId: 253, ItemId: 8, UsingCol1: "Stephen", UsingCol2: "Curry"},
    53  				{OrderId: 181, ItemId: 11, UsingCol1: "Kawhi", UsingCol2: "Leonard"},
    54  			},
    55  			txFunc: func(t *testing.T) *eorm.Tx {
    56  				tx, er := s.shardingDB.BeginTx(
    57  					transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{})
    58  				require.NoError(t, er)
    59  				return tx
    60  			},
    61  		},
    62  	}
    63  	for _, tc := range testCases {
    64  		t.Run(tc.name, func(t *testing.T) {
    65  			tx := tc.txFunc(t)
    66  			defer tx.Commit()
    67  			querySet, err := eorm.NewShardingSelector[test.OrderDetail](tx).
    68  				Where(eorm.C("OrderId").NEQ(123)).
    69  				GetMulti(masterslave.UseMaster(context.Background()))
    70  			require.NoError(t, err)
    71  			assert.ElementsMatch(t, tc.querySet, querySet)
    72  
    73  			querySet, err = eorm.NewShardingSelector[test.OrderDetail](tx).
    74  				Where(eorm.C("OrderId").NEQ(123)).
    75  				GetMulti(masterslave.UseMaster(context.Background()))
    76  			require.NoError(t, err)
    77  			assert.ElementsMatch(t, tc.querySet, querySet)
    78  		})
    79  	}
    80  }
    81  
    82  func (s *ShardingDelayTxTestSuite) TestShardingSelectUpdateInsert_Commit_Or_Rollback() {
    83  	t := s.T()
    84  	testCases := []struct {
    85  		name           string
    86  		updateAffected int64
    87  		insertAffected int64
    88  		target         *test.OrderDetail
    89  		upPre          eorm.Predicate
    90  		insertValues   []*test.OrderDetail
    91  		querySet       []*test.OrderDetail
    92  		upQuerySet     []*test.OrderDetail
    93  		txFunc         func(t *testing.T) *eorm.Tx
    94  		afterFunc      func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail)
    95  	}{
    96  		{
    97  			name:           "select insert update commit",
    98  			upPre:          eorm.C("OrderId").EQ(181),
    99  			updateAffected: 1,
   100  			insertAffected: 2,
   101  			target:         &test.OrderDetail{UsingCol1: "Jordan"},
   102  			insertValues: []*test.OrderDetail{
   103  				{OrderId: 33, ItemId: 100, UsingCol1: "Nikolai", UsingCol2: "Jokic"},
   104  				{OrderId: 288, ItemId: 101, UsingCol1: "Jimmy", UsingCol2: "Butler"},
   105  			},
   106  			querySet: []*test.OrderDetail{
   107  				{OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"},
   108  				{OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"},
   109  				{OrderId: 181, ItemId: 11, UsingCol1: "Kawhi", UsingCol2: "Leonard"},
   110  				{OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"},
   111  				{OrderId: 253, ItemId: 8, UsingCol1: "Stephen", UsingCol2: "Curry"},
   112  			},
   113  			upQuerySet: []*test.OrderDetail{
   114  				{OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"},
   115  				{OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"},
   116  				{OrderId: 33, ItemId: 100, UsingCol1: "Nikolai", UsingCol2: "Jokic"},
   117  				{OrderId: 181, ItemId: 11, UsingCol1: "Jordan", UsingCol2: "Leonard"},
   118  				{OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"},
   119  				{OrderId: 253, ItemId: 8, UsingCol1: "Stephen", UsingCol2: "Curry"},
   120  				{OrderId: 288, ItemId: 101, UsingCol1: "Jimmy", UsingCol2: "Butler"},
   121  			},
   122  			txFunc: func(t *testing.T) *eorm.Tx {
   123  				tx, er := s.shardingDB.BeginTx(
   124  					transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{})
   125  				require.NoError(t, er)
   126  				return tx
   127  			},
   128  			afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) {
   129  				err := tx.Commit()
   130  				require.NoError(t, err)
   131  
   132  				queryVal := s.findTgt(t, values)
   133  				assert.ElementsMatch(t, values, queryVal)
   134  			},
   135  		},
   136  		{
   137  			name:           "select insert update broadcast commit",
   138  			upPre:          eorm.C("OrderId").GTEQ(253),
   139  			updateAffected: 2,
   140  			insertAffected: 2,
   141  			target:         &test.OrderDetail{UsingCol1: "Jordan"},
   142  			insertValues: []*test.OrderDetail{
   143  				{OrderId: 199, ItemId: 100, UsingCol1: "Jason", UsingCol2: "Tatum"},
   144  				{OrderId: 299, ItemId: 101, UsingCol1: "Paul", UsingCol2: "George"},
   145  			},
   146  			querySet: []*test.OrderDetail{
   147  				{OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"},
   148  				{OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"},
   149  				{OrderId: 33, ItemId: 100, UsingCol1: "Nikolai", UsingCol2: "Jokic"},
   150  				{OrderId: 181, ItemId: 11, UsingCol1: "Jordan", UsingCol2: "Leonard"},
   151  				{OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"},
   152  				{OrderId: 253, ItemId: 8, UsingCol1: "Stephen", UsingCol2: "Curry"},
   153  				{OrderId: 288, ItemId: 101, UsingCol1: "Jimmy", UsingCol2: "Butler"},
   154  			},
   155  			upQuerySet: []*test.OrderDetail{
   156  				{OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"},
   157  				{OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"},
   158  				{OrderId: 33, ItemId: 100, UsingCol1: "Nikolai", UsingCol2: "Jokic"},
   159  				{OrderId: 181, ItemId: 11, UsingCol1: "Jordan", UsingCol2: "Leonard"},
   160  				{OrderId: 199, ItemId: 100, UsingCol1: "Jason", UsingCol2: "Tatum"},
   161  				{OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"},
   162  				{OrderId: 253, ItemId: 8, UsingCol1: "Jordan", UsingCol2: "Curry"},
   163  				{OrderId: 288, ItemId: 101, UsingCol1: "Jordan", UsingCol2: "Butler"},
   164  				{OrderId: 299, ItemId: 101, UsingCol1: "Paul", UsingCol2: "George"},
   165  			},
   166  			txFunc: func(t *testing.T) *eorm.Tx {
   167  				tx, er := s.shardingDB.BeginTx(
   168  					transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{})
   169  				require.NoError(t, er)
   170  				return tx
   171  			},
   172  			afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) {
   173  				err := tx.Commit()
   174  				require.NoError(t, err)
   175  
   176  				queryVal := s.findTgt(t, values)
   177  				assert.ElementsMatch(t, values, queryVal)
   178  			},
   179  		},
   180  		{
   181  			name:           "select insert update rollback",
   182  			upPre:          eorm.C("OrderId").EQ(299),
   183  			updateAffected: 1,
   184  			insertAffected: 1,
   185  			target:         &test.OrderDetail{UsingCol1: "Jordan"},
   186  			insertValues: []*test.OrderDetail{
   187  				{OrderId: 48, ItemId: 100},
   188  			},
   189  			querySet: []*test.OrderDetail{
   190  				{OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"},
   191  				{OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"},
   192  				{OrderId: 33, ItemId: 100, UsingCol1: "Nikolai", UsingCol2: "Jokic"},
   193  				{OrderId: 181, ItemId: 11, UsingCol1: "Jordan", UsingCol2: "Leonard"},
   194  				{OrderId: 199, ItemId: 100, UsingCol1: "Jason", UsingCol2: "Tatum"},
   195  				{OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"},
   196  				{OrderId: 253, ItemId: 8, UsingCol1: "Jordan", UsingCol2: "Curry"},
   197  				{OrderId: 288, ItemId: 101, UsingCol1: "Jordan", UsingCol2: "Butler"},
   198  				{OrderId: 299, ItemId: 101, UsingCol1: "Paul", UsingCol2: "George"},
   199  			},
   200  			upQuerySet: []*test.OrderDetail{
   201  				{OrderId: 8, ItemId: 6, UsingCol1: "Kobe", UsingCol2: "Bryant"},
   202  				{OrderId: 11, ItemId: 8, UsingCol1: "James", UsingCol2: "Harden"},
   203  				{OrderId: 33, ItemId: 100, UsingCol1: "Nikolai", UsingCol2: "Jokic"},
   204  				{OrderId: 181, ItemId: 11, UsingCol1: "Jordan", UsingCol2: "Leonard"},
   205  				{OrderId: 199, ItemId: 100, UsingCol1: "Jason", UsingCol2: "Tatum"},
   206  				{OrderId: 234, ItemId: 12, UsingCol1: "Kevin", UsingCol2: "Durant"},
   207  				{OrderId: 253, ItemId: 8, UsingCol1: "Jordan", UsingCol2: "Curry"},
   208  				{OrderId: 288, ItemId: 101, UsingCol1: "Jordan", UsingCol2: "Butler"},
   209  				{OrderId: 299, ItemId: 101, UsingCol1: "Paul", UsingCol2: "George"},
   210  			},
   211  			txFunc: func(t *testing.T) *eorm.Tx {
   212  				tx, er := s.shardingDB.BeginTx(
   213  					transaction.UsingTxType(context.Background(), transaction.Delay), &sql.TxOptions{})
   214  				require.NoError(t, er)
   215  				return tx
   216  			},
   217  			afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) {
   218  				err := tx.Rollback()
   219  				require.NoError(t, err)
   220  
   221  				queryVal := s.findTgt(t, values)
   222  				assert.ElementsMatch(t, values, queryVal)
   223  			},
   224  		},
   225  	}
   226  	for _, tc := range testCases {
   227  		t.Run(tc.name, func(t *testing.T) {
   228  			tx := tc.txFunc(t)
   229  			querySet, err := eorm.NewShardingSelector[test.OrderDetail](tx).
   230  				Where(eorm.C("OrderId").NEQ(123)).
   231  				GetMulti(masterslave.UseMaster(context.Background()))
   232  			require.NoError(t, err)
   233  			assert.ElementsMatch(t, tc.querySet, querySet)
   234  
   235  			res := eorm.NewShardingUpdater[test.OrderDetail](tx).Update(tc.target).
   236  				Set(eorm.C("UsingCol1")).Where(tc.upPre).Exec(context.Background())
   237  			affected, err := res.RowsAffected()
   238  			require.NoError(t, err)
   239  			assert.Equal(t, tc.updateAffected, affected)
   240  
   241  			res = eorm.NewShardingInsert[test.OrderDetail](tx).
   242  				Values(tc.insertValues).Exec(context.Background())
   243  			affected, err = res.RowsAffected()
   244  			require.NoError(t, err)
   245  			assert.Equal(t, tc.insertAffected, affected)
   246  
   247  			tc.afterFunc(t, tx, tc.upQuerySet)
   248  		})
   249  	}
   250  }
   251  
   252  func TestMySQL8ShardingDelayTxTestSuite(t *testing.T) {
   253  	suite.Run(t, &ShardingDelayTxTestSuite{
   254  		ShardingSelectUpdateInsertSuite: newShardingSelectUpdateInsertSuite(),
   255  	})
   256  }