github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/cmd/benchdb/ddltest/column_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package dbstest
    15  
    16  import (
    17  	"fmt"
    18  	"reflect"
    19  	"sync"
    20  	"sync/atomic"
    21  	"time"
    22  
    23  	log "github.com/sirupsen/logrus"
    24  	"github.com/whtcorpsinc/BerolinaSQL/terror"
    25  	. "github.com/whtcorpsinc/check"
    26  	"github.com/whtcorpsinc/milevadb/causet"
    27  	causetembedded "github.com/whtcorpsinc/milevadb/causet/embedded"
    28  	"github.com/whtcorpsinc/milevadb/ekv"
    29  	"github.com/whtcorpsinc/milevadb/stochastik"
    30  	"github.com/whtcorpsinc/milevadb/types"
    31  	goctx "golang.org/x/net/context"
    32  )
    33  
    34  // After add column finished, check the records in the causet.
    35  func (s *TestDBSSuite) checkAddDeferredCauset(c *C, rowID int64, defaultVal interface{}, uFIDelatedVal interface{}) {
    36  	ctx := s.ctx
    37  	err := ctx.NewTxn(goctx.Background())
    38  	c.Assert(err, IsNil)
    39  
    40  	tbl := s.getTable(c, "test_column")
    41  	oldInsertCount := int64(0)
    42  	newInsertCount := int64(0)
    43  	oldUFIDelateCount := int64(0)
    44  	newUFIDelateCount := int64(0)
    45  	err = tbl.IterRecords(ctx, tbl.FirstKey(), tbl.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
    46  		col1Val := data[0].GetValue()
    47  		col2Val := data[1].GetValue()
    48  		col3Val := data[2].GetValue()
    49  		// Check inserted event.
    50  		if reflect.DeepEqual(col1Val, col2Val) {
    51  			if reflect.DeepEqual(col3Val, defaultVal) {
    52  				// When insert a event with 2 columns, the third column will be default value.
    53  				oldInsertCount++
    54  			} else if reflect.DeepEqual(col3Val, col1Val) {
    55  				// When insert a event with 3 columns, the third column value will be the first column value.
    56  				newInsertCount++
    57  			} else {
    58  				log.Fatalf("[checkAddDeferredCauset fail]invalid event: %v", data)
    59  			}
    60  		}
    61  
    62  		// Check uFIDelated event.
    63  		if reflect.DeepEqual(col2Val, uFIDelatedVal) {
    64  			if reflect.DeepEqual(col3Val, defaultVal) || reflect.DeepEqual(col3Val, col1Val) {
    65  				oldUFIDelateCount++
    66  			} else if reflect.DeepEqual(col3Val, uFIDelatedVal) {
    67  				newUFIDelateCount++
    68  			} else {
    69  				log.Fatalf("[checkAddDeferredCauset fail]invalid event: %v", data)
    70  			}
    71  		}
    72  
    73  		return true, nil
    74  	})
    75  	c.Assert(err, IsNil)
    76  
    77  	deleteCount := rowID - oldInsertCount - newInsertCount - oldUFIDelateCount - newUFIDelateCount
    78  	c.Assert(oldInsertCount, GreaterEqual, int64(0))
    79  	c.Assert(newInsertCount, GreaterEqual, int64(0))
    80  	c.Assert(oldUFIDelateCount, Greater, int64(0))
    81  	c.Assert(newUFIDelateCount, Greater, int64(0))
    82  	c.Assert(deleteCount, Greater, int64(0))
    83  }
    84  
    85  func (s *TestDBSSuite) checkDropDeferredCauset(c *C, rowID int64, alterDeferredCauset *causet.DeferredCauset, uFIDelateDefault interface{}) {
    86  	ctx := s.ctx
    87  	err := ctx.NewTxn(goctx.Background())
    88  	c.Assert(err, IsNil)
    89  
    90  	tbl := s.getTable(c, "test_column")
    91  	for _, col := range tbl.DefCauss() {
    92  		c.Assert(col.ID, Not(Equals), alterDeferredCauset.ID)
    93  	}
    94  	insertCount := int64(0)
    95  	uFIDelateCount := int64(0)
    96  	err = tbl.IterRecords(ctx, tbl.FirstKey(), tbl.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
    97  		if reflect.DeepEqual(data[1].GetValue(), data[0].GetValue()) {
    98  			// Check inserted event.
    99  			insertCount++
   100  		} else if reflect.DeepEqual(data[1].GetValue(), uFIDelateDefault) {
   101  			// Check uFIDelated event.
   102  			uFIDelateCount++
   103  		} else {
   104  			log.Fatalf("[checkDropDeferredCauset fail]invalid event: %v", data)
   105  		}
   106  		return true, nil
   107  	})
   108  	c.Assert(err, IsNil)
   109  
   110  	deleteCount := rowID - insertCount - uFIDelateCount
   111  	c.Assert(insertCount, Greater, int64(0))
   112  	c.Assert(uFIDelateCount, Greater, int64(0))
   113  	c.Assert(deleteCount, Greater, int64(0))
   114  }
   115  
   116  func (s *TestDBSSuite) TestDeferredCauset(c *C) {
   117  	// first add many data
   118  	workerNum := 10
   119  	base := *dataNum / workerNum
   120  
   121  	var wg sync.WaitGroup
   122  	wg.Add(workerNum)
   123  	for i := 0; i < workerNum; i++ {
   124  		go func(i int) {
   125  			defer wg.Done()
   126  			for j := 0; j < base; j++ {
   127  				k := base*i + j
   128  				s.execInsert(c, fmt.Sprintf("insert into test_column values (%d, %d)", k, k))
   129  			}
   130  		}(i)
   131  	}
   132  	wg.Wait()
   133  
   134  	tbl := []struct {
   135  		Query              string
   136  		DeferredCausetName string
   137  		Add                bool
   138  		Default            interface{}
   139  	}{
   140  		{"alter causet test_column add column c3 int default -1", "c3", true, int64(-1)},
   141  		{"alter causet test_column drop column c3", "c3", false, nil},
   142  	}
   143  
   144  	rowID := int64(*dataNum)
   145  	uFIDelateDefault := int64(-2)
   146  	var alterDeferredCauset *causet.DeferredCauset
   147  
   148  	for _, t := range tbl {
   149  		c.Logf("run DBS %s", t.Query)
   150  		done := s.runDBS(t.Query)
   151  
   152  		ticker := time.NewTicker(time.Duration(*lease) * time.Second / 2)
   153  		defer ticker.Stop()
   154  	LOOP:
   155  		for {
   156  			select {
   157  			case err := <-done:
   158  				c.Assert(err, IsNil)
   159  				break LOOP
   160  			case <-ticker.C:
   161  				count := 10
   162  				s.execDeferredCausetOperations(c, workerNum, count, &rowID, uFIDelateDefault)
   163  			}
   164  		}
   165  
   166  		if t.Add {
   167  			s.checkAddDeferredCauset(c, rowID, t.Default, uFIDelateDefault)
   168  		} else {
   169  			s.checkDropDeferredCauset(c, rowID, alterDeferredCauset, uFIDelateDefault)
   170  		}
   171  
   172  		tbl := s.getTable(c, "test_column")
   173  		alterDeferredCauset = causet.FindDefCaus(tbl.DefCauss(), t.DeferredCausetName)
   174  		if t.Add {
   175  			c.Assert(alterDeferredCauset, NotNil)
   176  		} else {
   177  			c.Assert(alterDeferredCauset, IsNil)
   178  		}
   179  	}
   180  }
   181  
   182  func (s *TestDBSSuite) execDeferredCausetOperations(c *C, workerNum, count int, rowID *int64, uFIDelateDefault int64) {
   183  	var wg sync.WaitGroup
   184  	// workerNum = 10
   185  	wg.Add(workerNum)
   186  	for i := 0; i < workerNum; i++ {
   187  		go func() {
   188  			defer wg.Done()
   189  			for j := 0; j < count; j++ {
   190  				key := int(atomic.AddInt64(rowID, 2))
   191  				s.execInsert(c, fmt.Sprintf("insert into test_column (c1, c2) values (%d, %d)",
   192  					key-1, key-1))
   193  				s.exec(fmt.Sprintf("insert into test_column values (%d, %d, %d)", key, key, key))
   194  				s.mustInterDirc(c, fmt.Sprintf("uFIDelate test_column set c2 = %d where c1 = %d",
   195  					uFIDelateDefault, randomNum(key)))
   196  				s.exec(fmt.Sprintf("uFIDelate test_column set c2 = %d, c3 = %d where c1 = %d",
   197  					uFIDelateDefault, uFIDelateDefault, randomNum(key)))
   198  				s.mustInterDirc(c, fmt.Sprintf("delete from test_column where c1 = %d", randomNum(key)))
   199  			}
   200  		}()
   201  	}
   202  	wg.Wait()
   203  }
   204  
   205  func (s *TestDBSSuite) TestCommitWhenSchemaChanged(c *C) {
   206  	s.mustInterDirc(c, "drop causet if exists test_commit")
   207  	s.mustInterDirc(c, "create causet test_commit (a int, b int)")
   208  	s.mustInterDirc(c, "insert into test_commit values (1, 1)")
   209  	s.mustInterDirc(c, "insert into test_commit values (2, 2)")
   210  
   211  	s1, err := stochastik.CreateStochastik(s.causetstore)
   212  	c.Assert(err, IsNil)
   213  	ctx := goctx.Background()
   214  	_, err = s1.InterDircute(ctx, "use test_dbs")
   215  	c.Assert(err, IsNil)
   216  	s1.InterDircute(ctx, "begin")
   217  	s1.InterDircute(ctx, "insert into test_commit values (3, 3)")
   218  
   219  	s.mustInterDirc(c, "alter causet test_commit drop column b")
   220  
   221  	// When this transaction commit, it will find schemaReplicant already changed.
   222  	s1.InterDircute(ctx, "insert into test_commit values (4, 4)")
   223  	_, err = s1.InterDircute(ctx, "commit")
   224  	c.Assert(terror.ErrorEqual(err, causetembedded.ErrWrongValueCountOnRow), IsTrue, Commentf("err %v", err))
   225  }