github.com/ecodeclub/eorm@v0.0.2-0.20231001112437-dae71da914d0/internal/integration/sharding_single_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 ShardingSingleTxTestSuite struct {
    35  	ShardingSelectUpdateInsertSuite
    36  }
    37  
    38  func (s *ShardingSingleTxTestSuite) TestDoubleShardingSelect() {
    39  	t := s.T()
    40  	testCases := []struct {
    41  		name     string
    42  		querySet []*test.OrderDetail
    43  		txFunc   func(t *testing.T) *eorm.Tx
    44  	}{
    45  		{
    46  			name: "double select",
    47  			querySet: []*test.OrderDetail{
    48  				{OrderId: 123, ItemId: 10, UsingCol1: "LeBron", UsingCol2: "James"},
    49  			},
    50  			txFunc: func(t *testing.T) *eorm.Tx {
    51  				tx, er := s.shardingDB.BeginTx(
    52  					transaction.UsingTxType(context.Background(), transaction.Single), &sql.TxOptions{})
    53  				require.NoError(t, er)
    54  				return tx
    55  			},
    56  		},
    57  	}
    58  	for _, tc := range testCases {
    59  		t.Run(tc.name, func(t *testing.T) {
    60  			tx := tc.txFunc(t)
    61  			defer tx.Commit()
    62  			querySet, err := eorm.NewShardingSelector[test.OrderDetail](tx).
    63  				Where(eorm.C("OrderId").EQ(123)).
    64  				GetMulti(masterslave.UseMaster(context.Background()))
    65  			require.NoError(t, err)
    66  			assert.ElementsMatch(t, tc.querySet, querySet)
    67  
    68  			querySet, err = eorm.NewShardingSelector[test.OrderDetail](tx).
    69  				Where(eorm.C("OrderId").EQ(123)).
    70  				GetMulti(masterslave.UseMaster(context.Background()))
    71  			require.NoError(t, err)
    72  			assert.ElementsMatch(t, tc.querySet, querySet)
    73  		})
    74  	}
    75  }
    76  
    77  func (s *ShardingSingleTxTestSuite) TestShardingSelectInsert_Commit_Or_Rollback() {
    78  	t := s.T()
    79  	testCases := []struct {
    80  		name         string
    81  		wantAffected int64
    82  		values       []*test.OrderDetail
    83  		querySet     []*test.OrderDetail
    84  		txFunc       func(t *testing.T) *eorm.Tx
    85  		afterFunc    func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail)
    86  	}{
    87  		{
    88  			name:         "select insert commit",
    89  			wantAffected: 1,
    90  			values: []*test.OrderDetail{
    91  				{OrderId: 33, ItemId: 100, UsingCol1: "Nikolai", UsingCol2: "Jokic"},
    92  			},
    93  			querySet: []*test.OrderDetail{
    94  				{OrderId: 123, ItemId: 10, UsingCol1: "LeBron", UsingCol2: "James"},
    95  			},
    96  			txFunc: func(t *testing.T) *eorm.Tx {
    97  				tx, er := s.shardingDB.BeginTx(
    98  					transaction.UsingTxType(context.Background(), transaction.Single), &sql.TxOptions{})
    99  				require.NoError(t, er)
   100  				return tx
   101  			},
   102  			afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) {
   103  				err := tx.Commit()
   104  				require.NoError(t, err)
   105  
   106  				queryVal := s.findTgt(t, values)
   107  				assert.ElementsMatch(t, values, queryVal)
   108  			},
   109  		},
   110  		{
   111  			name:         "select insert rollback",
   112  			wantAffected: 1,
   113  			values: []*test.OrderDetail{
   114  				{OrderId: 199, ItemId: 100, UsingCol1: "Jason", UsingCol2: "Tatum"},
   115  			},
   116  			querySet: []*test.OrderDetail{
   117  				{OrderId: 123, ItemId: 10, UsingCol1: "LeBron", UsingCol2: "James"},
   118  			},
   119  			txFunc: func(t *testing.T) *eorm.Tx {
   120  				tx, er := s.shardingDB.BeginTx(
   121  					transaction.UsingTxType(context.Background(), transaction.Single), &sql.TxOptions{})
   122  				require.NoError(t, er)
   123  				return tx
   124  			},
   125  			afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) {
   126  				var wantOds []*test.OrderDetail
   127  				err := tx.Rollback()
   128  				require.NoError(t, err)
   129  
   130  				queryVal := s.findTgt(t, values)
   131  				assert.ElementsMatch(t, wantOds, queryVal)
   132  			},
   133  		},
   134  	}
   135  	for _, tc := range testCases {
   136  		t.Run(tc.name, func(t *testing.T) {
   137  			tx := tc.txFunc(t)
   138  			querySet, err := eorm.NewShardingSelector[test.OrderDetail](tx).
   139  				Where(eorm.C("OrderId").EQ(123)).
   140  				GetMulti(masterslave.UseMaster(context.Background()))
   141  			require.NoError(t, err)
   142  			assert.ElementsMatch(t, tc.querySet, querySet)
   143  			res := eorm.NewShardingInsert[test.OrderDetail](tx).
   144  				Values(tc.values).Exec(context.Background())
   145  			affected, err := res.RowsAffected()
   146  			require.NoError(t, err)
   147  			assert.Equal(t, tc.wantAffected, affected)
   148  			tc.afterFunc(t, tx, tc.values)
   149  		})
   150  	}
   151  }
   152  
   153  func (s *ShardingSingleTxTestSuite) TestShardingSelectUpdate_Commit_Or_Rollback() {
   154  	t := s.T()
   155  	testCases := []struct {
   156  		name         string
   157  		wantAffected int64
   158  		target       *test.OrderDetail
   159  		upPre        eorm.Predicate
   160  		querySet     []*test.OrderDetail
   161  		upQuerySet   []*test.OrderDetail
   162  		txFunc       func(t *testing.T) *eorm.Tx
   163  		afterFunc    func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail)
   164  	}{
   165  		{
   166  			name:         "select update where eq commit",
   167  			upPre:        eorm.C("OrderId").EQ(11),
   168  			wantAffected: 1,
   169  			target:       &test.OrderDetail{UsingCol1: "ben"},
   170  			querySet: []*test.OrderDetail{
   171  				{OrderId: 123, ItemId: 10, UsingCol1: "LeBron", UsingCol2: "James"},
   172  			},
   173  			upQuerySet: []*test.OrderDetail{
   174  				{OrderId: 11, ItemId: 8, UsingCol1: "ben", UsingCol2: "Harden"},
   175  				{OrderId: 123, ItemId: 10, UsingCol1: "LeBron", UsingCol2: "James"},
   176  			},
   177  			txFunc: func(t *testing.T) *eorm.Tx {
   178  				tx, er := s.shardingDB.BeginTx(
   179  					transaction.UsingTxType(context.Background(), transaction.Single), &sql.TxOptions{})
   180  				require.NoError(t, er)
   181  				return tx
   182  			},
   183  			afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) {
   184  				err := tx.Commit()
   185  				require.NoError(t, err)
   186  
   187  				queryVal := s.findTgt(t, values)
   188  				assert.ElementsMatch(t, values, queryVal)
   189  			},
   190  		},
   191  		{
   192  			name:         "select update rollback",
   193  			upPre:        eorm.C("OrderId").EQ(181),
   194  			wantAffected: 1,
   195  			target:       &test.OrderDetail{UsingCol1: "Jordan"},
   196  			querySet: []*test.OrderDetail{
   197  				{OrderId: 123, ItemId: 10, UsingCol1: "LeBron", UsingCol2: "James"},
   198  			},
   199  			upQuerySet: []*test.OrderDetail{
   200  				{OrderId: 181, ItemId: 11, UsingCol1: "Kawhi", UsingCol2: "Leonard"},
   201  				{OrderId: 123, ItemId: 10, UsingCol1: "LeBron", UsingCol2: "James"},
   202  			},
   203  			txFunc: func(t *testing.T) *eorm.Tx {
   204  				tx, er := s.shardingDB.BeginTx(
   205  					transaction.UsingTxType(context.Background(), transaction.Single), &sql.TxOptions{})
   206  				require.NoError(t, er)
   207  				return tx
   208  			},
   209  			afterFunc: func(t *testing.T, tx *eorm.Tx, values []*test.OrderDetail) {
   210  				err := tx.Rollback()
   211  				require.NoError(t, err)
   212  
   213  				queryVal := s.findTgt(t, values)
   214  				assert.ElementsMatch(t, values, queryVal)
   215  			},
   216  		},
   217  	}
   218  	for _, tc := range testCases {
   219  		t.Run(tc.name, func(t *testing.T) {
   220  			tx := tc.txFunc(t)
   221  			querySet, err := eorm.NewShardingSelector[test.OrderDetail](tx).
   222  				Where(eorm.C("OrderId").EQ(123)).
   223  				GetMulti(masterslave.UseMaster(context.Background()))
   224  			require.NoError(t, err)
   225  			assert.ElementsMatch(t, tc.querySet, querySet)
   226  			res := eorm.NewShardingUpdater[test.OrderDetail](tx).Update(tc.target).
   227  				Set(eorm.C("UsingCol1")).Where(tc.upPre).Exec(context.Background())
   228  			affected, err := res.RowsAffected()
   229  			require.NoError(t, err)
   230  			assert.Equal(t, tc.wantAffected, affected)
   231  			tc.afterFunc(t, tx, tc.upQuerySet)
   232  		})
   233  	}
   234  }
   235  
   236  func TestMySQL8ShardingSingleTxTestSuite(t *testing.T) {
   237  	suite.Run(t, &ShardingSingleTxTestSuite{
   238  		ShardingSelectUpdateInsertSuite: newShardingSelectUpdateInsertSuite(),
   239  	})
   240  }