github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/schemareplicant/infoschema_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 schemareplicant_test
    15  
    16  import (
    17  	"sync"
    18  	"testing"
    19  
    20  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    21  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    22  	. "github.com/whtcorpsinc/check"
    23  	"github.com/whtcorpsinc/errors"
    24  	"github.com/whtcorpsinc/milevadb/causetstore/mockstore"
    25  	"github.com/whtcorpsinc/milevadb/ekv"
    26  	"github.com/whtcorpsinc/milevadb/schemareplicant"
    27  	"github.com/whtcorpsinc/milevadb/soliton"
    28  	"github.com/whtcorpsinc/milevadb/soliton/solitonutil"
    29  	"github.com/whtcorpsinc/milevadb/soliton/testleak"
    30  	"github.com/whtcorpsinc/milevadb/spacetime"
    31  	"github.com/whtcorpsinc/milevadb/stochastik"
    32  	"github.com/whtcorpsinc/milevadb/types"
    33  )
    34  
    35  func TestT(t *testing.T) {
    36  	CustomVerboseFlag = true
    37  	TestingT(t)
    38  }
    39  
    40  var _ = Suite(&testSuite{})
    41  
    42  type testSuite struct {
    43  }
    44  
    45  func (*testSuite) TestT(c *C) {
    46  	defer testleak.AfterTest(c)()
    47  	causetstore, err := mockstore.NewMockStore()
    48  	c.Assert(err, IsNil)
    49  	defer causetstore.Close()
    50  	// Make sure it calls perfschema.Init().
    51  	dom, err := stochastik.BootstrapStochastik(causetstore)
    52  	c.Assert(err, IsNil)
    53  	defer dom.Close()
    54  
    55  	handle := schemareplicant.NewHandle(causetstore)
    56  	dbName := perceptron.NewCIStr("Test")
    57  	tbName := perceptron.NewCIStr("T")
    58  	defCausName := perceptron.NewCIStr("A")
    59  	idxName := perceptron.NewCIStr("idx")
    60  	noexist := perceptron.NewCIStr("noexist")
    61  
    62  	defCausID, err := genGlobalID(causetstore)
    63  	c.Assert(err, IsNil)
    64  	defCausInfo := &perceptron.DeferredCausetInfo{
    65  		ID:        defCausID,
    66  		Name:      defCausName,
    67  		Offset:    0,
    68  		FieldType: *types.NewFieldType(allegrosql.TypeLonglong),
    69  		State:     perceptron.StatePublic,
    70  	}
    71  
    72  	idxInfo := &perceptron.IndexInfo{
    73  		Name:  idxName,
    74  		Block: tbName,
    75  		DeferredCausets: []*perceptron.IndexDeferredCauset{
    76  			{
    77  				Name:   defCausName,
    78  				Offset: 0,
    79  				Length: 10,
    80  			},
    81  		},
    82  		Unique:  true,
    83  		Primary: true,
    84  		State:   perceptron.StatePublic,
    85  	}
    86  
    87  	tbID, err := genGlobalID(causetstore)
    88  	c.Assert(err, IsNil)
    89  	tblInfo := &perceptron.BlockInfo{
    90  		ID:              tbID,
    91  		Name:            tbName,
    92  		DeferredCausets: []*perceptron.DeferredCausetInfo{defCausInfo},
    93  		Indices:         []*perceptron.IndexInfo{idxInfo},
    94  		State:           perceptron.StatePublic,
    95  	}
    96  
    97  	dbID, err := genGlobalID(causetstore)
    98  	c.Assert(err, IsNil)
    99  	dbInfo := &perceptron.DBInfo{
   100  		ID:     dbID,
   101  		Name:   dbName,
   102  		Blocks: []*perceptron.BlockInfo{tblInfo},
   103  		State:  perceptron.StatePublic,
   104  	}
   105  
   106  	dbInfos := []*perceptron.DBInfo{dbInfo}
   107  	err = ekv.RunInNewTxn(causetstore, true, func(txn ekv.Transaction) error {
   108  		spacetime.NewMeta(txn).CreateDatabase(dbInfo)
   109  		return errors.Trace(err)
   110  	})
   111  	c.Assert(err, IsNil)
   112  
   113  	builder, err := schemareplicant.NewBuilder(handle).InitWithDBInfos(dbInfos, 1)
   114  	c.Assert(err, IsNil)
   115  
   116  	txn, err := causetstore.Begin()
   117  	c.Assert(err, IsNil)
   118  	checkApplyCreateNonExistsSchemaDoesNotPanic(c, txn, builder)
   119  	checkApplyCreateNonExistsBlockDoesNotPanic(c, txn, builder, dbID)
   120  	txn.Rollback()
   121  
   122  	builder.Build()
   123  	is := handle.Get()
   124  
   125  	schemaNames := is.AllSchemaNames()
   126  	c.Assert(schemaNames, HasLen, 4)
   127  	c.Assert(solitonutil.CompareUnorderedStringSlice(schemaNames, []string{soliton.InformationSchemaName.O, soliton.MetricSchemaName.O, soliton.PerformanceSchemaName.O, "Test"}), IsTrue)
   128  
   129  	schemas := is.AllSchemas()
   130  	c.Assert(schemas, HasLen, 4)
   131  	schemas = is.Clone()
   132  	c.Assert(schemas, HasLen, 4)
   133  
   134  	c.Assert(is.SchemaExists(dbName), IsTrue)
   135  	c.Assert(is.SchemaExists(noexist), IsFalse)
   136  
   137  	schemaReplicant, ok := is.SchemaByID(dbID)
   138  	c.Assert(ok, IsTrue)
   139  	c.Assert(schemaReplicant, NotNil)
   140  
   141  	schemaReplicant, ok = is.SchemaByID(tbID)
   142  	c.Assert(ok, IsFalse)
   143  	c.Assert(schemaReplicant, IsNil)
   144  
   145  	schemaReplicant, ok = is.SchemaByName(dbName)
   146  	c.Assert(ok, IsTrue)
   147  	c.Assert(schemaReplicant, NotNil)
   148  
   149  	schemaReplicant, ok = is.SchemaByName(noexist)
   150  	c.Assert(ok, IsFalse)
   151  	c.Assert(schemaReplicant, IsNil)
   152  
   153  	schemaReplicant, ok = is.SchemaByBlock(tblInfo)
   154  	c.Assert(ok, IsTrue)
   155  	c.Assert(schemaReplicant, NotNil)
   156  
   157  	noexistTblInfo := &perceptron.BlockInfo{ID: 12345, Name: tblInfo.Name}
   158  	schemaReplicant, ok = is.SchemaByBlock(noexistTblInfo)
   159  	c.Assert(ok, IsFalse)
   160  	c.Assert(schemaReplicant, IsNil)
   161  
   162  	c.Assert(is.BlockExists(dbName, tbName), IsTrue)
   163  	c.Assert(is.BlockExists(dbName, noexist), IsFalse)
   164  	c.Assert(is.BlockIsView(dbName, tbName), IsFalse)
   165  	c.Assert(is.BlockIsSequence(dbName, tbName), IsFalse)
   166  
   167  	tb, ok := is.BlockByID(tbID)
   168  	c.Assert(ok, IsTrue)
   169  	c.Assert(tb, NotNil)
   170  
   171  	tb, ok = is.BlockByID(dbID)
   172  	c.Assert(ok, IsFalse)
   173  	c.Assert(tb, IsNil)
   174  
   175  	alloc, ok := is.AllocByID(tbID)
   176  	c.Assert(ok, IsTrue)
   177  	c.Assert(alloc, NotNil)
   178  
   179  	tb, err = is.BlockByName(dbName, tbName)
   180  	c.Assert(err, IsNil)
   181  	c.Assert(tb, NotNil)
   182  
   183  	_, err = is.BlockByName(dbName, noexist)
   184  	c.Assert(err, NotNil)
   185  
   186  	tbs := is.SchemaBlocks(dbName)
   187  	c.Assert(tbs, HasLen, 1)
   188  
   189  	tbs = is.SchemaBlocks(noexist)
   190  	c.Assert(tbs, HasLen, 0)
   191  
   192  	// Make sure partitions causet exists
   193  	tb, err = is.BlockByName(perceptron.NewCIStr("information_schema"), perceptron.NewCIStr("partitions"))
   194  	c.Assert(err, IsNil)
   195  	c.Assert(tb, NotNil)
   196  
   197  	err = ekv.RunInNewTxn(causetstore, true, func(txn ekv.Transaction) error {
   198  		spacetime.NewMeta(txn).CreateBlockOrView(dbID, tblInfo)
   199  		return errors.Trace(err)
   200  	})
   201  	c.Assert(err, IsNil)
   202  	txn, err = causetstore.Begin()
   203  	c.Assert(err, IsNil)
   204  	_, err = builder.ApplyDiff(spacetime.NewMeta(txn), &perceptron.SchemaDiff{Type: perceptron.CausetActionRenameBlock, SchemaID: dbID, BlockID: tbID, OldSchemaID: dbID})
   205  	c.Assert(err, IsNil)
   206  	txn.Rollback()
   207  	builder.Build()
   208  	is = handle.Get()
   209  	schemaReplicant, ok = is.SchemaByID(dbID)
   210  	c.Assert(ok, IsTrue)
   211  	c.Assert(len(schemaReplicant.Blocks), Equals, 1)
   212  
   213  	emptyHandle := handle.EmptyClone()
   214  	c.Assert(emptyHandle.Get(), IsNil)
   215  }
   216  
   217  func (testSuite) TestMockSchemaReplicant(c *C) {
   218  	tblID := int64(1234)
   219  	tblName := perceptron.NewCIStr("tbl_m")
   220  	blockInfo := &perceptron.BlockInfo{
   221  		ID:    tblID,
   222  		Name:  tblName,
   223  		State: perceptron.StatePublic,
   224  	}
   225  	defCausInfo := &perceptron.DeferredCausetInfo{
   226  		State:     perceptron.StatePublic,
   227  		Offset:    0,
   228  		Name:      perceptron.NewCIStr("h"),
   229  		FieldType: *types.NewFieldType(allegrosql.TypeLong),
   230  		ID:        1,
   231  	}
   232  	blockInfo.DeferredCausets = []*perceptron.DeferredCausetInfo{defCausInfo}
   233  	is := schemareplicant.MockSchemaReplicant([]*perceptron.BlockInfo{blockInfo})
   234  	tbl, ok := is.BlockByID(tblID)
   235  	c.Assert(ok, IsTrue)
   236  	c.Assert(tbl.Meta().Name, Equals, tblName)
   237  	c.Assert(tbl.DefCauss()[0].DeferredCausetInfo, Equals, defCausInfo)
   238  }
   239  
   240  func checkApplyCreateNonExistsSchemaDoesNotPanic(c *C, txn ekv.Transaction, builder *schemareplicant.Builder) {
   241  	m := spacetime.NewMeta(txn)
   242  	_, err := builder.ApplyDiff(m, &perceptron.SchemaDiff{Type: perceptron.CausetActionCreateSchema, SchemaID: 999})
   243  	c.Assert(schemareplicant.ErrDatabaseNotExists.Equal(err), IsTrue)
   244  }
   245  
   246  func checkApplyCreateNonExistsBlockDoesNotPanic(c *C, txn ekv.Transaction, builder *schemareplicant.Builder, dbID int64) {
   247  	m := spacetime.NewMeta(txn)
   248  	_, err := builder.ApplyDiff(m, &perceptron.SchemaDiff{Type: perceptron.CausetActionCreateBlock, SchemaID: dbID, BlockID: 999})
   249  	c.Assert(schemareplicant.ErrBlockNotExists.Equal(err), IsTrue)
   250  }
   251  
   252  // TestConcurrent makes sure it is safe to concurrently create handle on multiple stores.
   253  func (testSuite) TestConcurrent(c *C) {
   254  	defer testleak.AfterTest(c)()
   255  	storeCount := 5
   256  	stores := make([]ekv.CausetStorage, storeCount)
   257  	for i := 0; i < storeCount; i++ {
   258  		causetstore, err := mockstore.NewMockStore()
   259  		c.Assert(err, IsNil)
   260  		stores[i] = causetstore
   261  	}
   262  	defer func() {
   263  		for _, causetstore := range stores {
   264  			causetstore.Close()
   265  		}
   266  	}()
   267  	var wg sync.WaitGroup
   268  	wg.Add(storeCount)
   269  	for _, causetstore := range stores {
   270  		go func(s ekv.CausetStorage) {
   271  			defer wg.Done()
   272  			_ = schemareplicant.NewHandle(s)
   273  		}(causetstore)
   274  	}
   275  	wg.Wait()
   276  }
   277  
   278  // TestInfoBlocks makes sure that all blocks of information_schema could be found in schemareplicant handle.
   279  func (*testSuite) TestInfoBlocks(c *C) {
   280  	defer testleak.AfterTest(c)()
   281  	causetstore, err := mockstore.NewMockStore()
   282  	c.Assert(err, IsNil)
   283  	defer causetstore.Close()
   284  	handle := schemareplicant.NewHandle(causetstore)
   285  	builder, err := schemareplicant.NewBuilder(handle).InitWithDBInfos(nil, 0)
   286  	c.Assert(err, IsNil)
   287  	builder.Build()
   288  	is := handle.Get()
   289  	c.Assert(is, NotNil)
   290  
   291  	infoBlocks := []string{
   292  		"SCHEMATA",
   293  		"TABLES",
   294  		"COLUMNS",
   295  		"STATISTICS",
   296  		"CHARACTER_SETS",
   297  		"COLLATIONS",
   298  		"FILES",
   299  		"PROFILING",
   300  		"PARTITIONS",
   301  		"KEY_COLUMN_USAGE",
   302  		"REFERENTIAL_CONSTRAINTS",
   303  		"SESSION_VARIABLES",
   304  		"PLUGINS",
   305  		"TABLE_CONSTRAINTS",
   306  		"TRIGGERS",
   307  		"USER_PRIVILEGES",
   308  		"ENGINES",
   309  		"VIEWS",
   310  		"ROUTINES",
   311  		"SCHEMA_PRIVILEGES",
   312  		"COLUMN_PRIVILEGES",
   313  		"TABLE_PRIVILEGES",
   314  		"PARAMETERS",
   315  		"EVENTS",
   316  		"GLOBAL_STATUS",
   317  		"GLOBAL_VARIABLES",
   318  		"SESSION_STATUS",
   319  		"OPTIMIZER_TRACE",
   320  		"TABLESPACES",
   321  		"COLLATION_CHARACTER_SET_APPLICABILITY",
   322  		"PROCESSLIST",
   323  	}
   324  	for _, t := range infoBlocks {
   325  		tb, err1 := is.BlockByName(soliton.InformationSchemaName, perceptron.NewCIStr(t))
   326  		c.Assert(err1, IsNil)
   327  		c.Assert(tb, NotNil)
   328  	}
   329  }
   330  
   331  func genGlobalID(causetstore ekv.CausetStorage) (int64, error) {
   332  	var globalID int64
   333  	err := ekv.RunInNewTxn(causetstore, true, func(txn ekv.Transaction) error {
   334  		var err error
   335  		globalID, err = spacetime.NewMeta(txn).GenGlobalID()
   336  		return errors.Trace(err)
   337  	})
   338  	return globalID, errors.Trace(err)
   339  }