github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/schema_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 dbs
    15  
    16  import (
    17  	"context"
    18  	"time"
    19  
    20  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    21  	"github.com/whtcorpsinc/BerolinaSQL/terror"
    22  	. "github.com/whtcorpsinc/check"
    23  	"github.com/whtcorpsinc/errors"
    24  	"github.com/whtcorpsinc/milevadb/ekv"
    25  	"github.com/whtcorpsinc/milevadb/schemareplicant"
    26  	"github.com/whtcorpsinc/milevadb/spacetime"
    27  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    28  	"github.com/whtcorpsinc/milevadb/types"
    29  )
    30  
    31  var _ = Suite(&testSchemaSuite{})
    32  
    33  type testSchemaSuite struct{}
    34  
    35  func (s *testSchemaSuite) SetUpSuite(c *C) {
    36  }
    37  
    38  func (s *testSchemaSuite) TearDownSuite(c *C) {
    39  }
    40  
    41  func testSchemaInfo(c *C, d *dbs, name string) *perceptron.DBInfo {
    42  	dbInfo := &perceptron.DBInfo{
    43  		Name: perceptron.NewCIStr(name),
    44  	}
    45  	genIDs, err := d.genGlobalIDs(1)
    46  	c.Assert(err, IsNil)
    47  	dbInfo.ID = genIDs[0]
    48  	return dbInfo
    49  }
    50  
    51  func testCreateSchema(c *C, ctx stochastikctx.Context, d *dbs, dbInfo *perceptron.DBInfo) *perceptron.Job {
    52  	job := &perceptron.Job{
    53  		SchemaID:   dbInfo.ID,
    54  		Type:       perceptron.CausetActionCreateSchema,
    55  		BinlogInfo: &perceptron.HistoryInfo{},
    56  		Args:       []interface{}{dbInfo},
    57  	}
    58  	err := d.doDBSJob(ctx, job)
    59  	c.Assert(err, IsNil)
    60  
    61  	v := getSchemaVer(c, ctx)
    62  	dbInfo.State = perceptron.StatePublic
    63  	checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, EDB: dbInfo})
    64  	dbInfo.State = perceptron.StateNone
    65  	return job
    66  }
    67  
    68  func buildDropSchemaJob(dbInfo *perceptron.DBInfo) *perceptron.Job {
    69  	return &perceptron.Job{
    70  		SchemaID:   dbInfo.ID,
    71  		Type:       perceptron.CausetActionDropSchema,
    72  		BinlogInfo: &perceptron.HistoryInfo{},
    73  	}
    74  }
    75  
    76  func testDropSchema(c *C, ctx stochastikctx.Context, d *dbs, dbInfo *perceptron.DBInfo) (*perceptron.Job, int64) {
    77  	job := buildDropSchemaJob(dbInfo)
    78  	err := d.doDBSJob(ctx, job)
    79  	c.Assert(err, IsNil)
    80  	ver := getSchemaVer(c, ctx)
    81  	return job, ver
    82  }
    83  
    84  func isDBSJobDone(c *C, t *spacetime.Meta) bool {
    85  	job, err := t.GetDBSJobByIdx(0)
    86  	c.Assert(err, IsNil)
    87  	if job == nil {
    88  		return true
    89  	}
    90  
    91  	time.Sleep(testLease)
    92  	return false
    93  }
    94  
    95  func testCheckSchemaState(c *C, d *dbs, dbInfo *perceptron.DBInfo, state perceptron.SchemaState) {
    96  	isDropped := true
    97  
    98  	for {
    99  		ekv.RunInNewTxn(d.causetstore, false, func(txn ekv.Transaction) error {
   100  			t := spacetime.NewMeta(txn)
   101  			info, err := t.GetDatabase(dbInfo.ID)
   102  			c.Assert(err, IsNil)
   103  
   104  			if state == perceptron.StateNone {
   105  				isDropped = isDBSJobDone(c, t)
   106  				if !isDropped {
   107  					return nil
   108  				}
   109  				c.Assert(info, IsNil)
   110  				return nil
   111  			}
   112  
   113  			c.Assert(info.Name, DeepEquals, dbInfo.Name)
   114  			c.Assert(info.State, Equals, state)
   115  			return nil
   116  		})
   117  
   118  		if isDropped {
   119  			break
   120  		}
   121  	}
   122  }
   123  
   124  func (s *testSchemaSuite) TestSchema(c *C) {
   125  	causetstore := testCreateStore(c, "test_schema")
   126  	defer causetstore.Close()
   127  	d := testNewDBSAndStart(
   128  		context.Background(),
   129  		c,
   130  		WithStore(causetstore),
   131  		WithLease(testLease),
   132  	)
   133  	defer d.Stop()
   134  	ctx := testNewContext(d)
   135  	dbInfo := testSchemaInfo(c, d, "test")
   136  
   137  	// create a database.
   138  	job := testCreateSchema(c, ctx, d, dbInfo)
   139  	testCheckSchemaState(c, d, dbInfo, perceptron.StatePublic)
   140  	testCheckJobDone(c, d, job, true)
   141  
   142  	/*** to drop the schemaReplicant with two blocks. ***/
   143  	// create causet t with 100 records.
   144  	tblInfo1 := testBlockInfo(c, d, "t", 3)
   145  	tJob1 := testCreateBlock(c, ctx, d, dbInfo, tblInfo1)
   146  	testCheckBlockState(c, d, dbInfo, tblInfo1, perceptron.StatePublic)
   147  	testCheckJobDone(c, d, tJob1, true)
   148  	tbl1 := testGetBlock(c, d, dbInfo.ID, tblInfo1.ID)
   149  	for i := 1; i <= 100; i++ {
   150  		_, err := tbl1.AddRecord(ctx, types.MakeCausets(i, i, i))
   151  		c.Assert(err, IsNil)
   152  	}
   153  	// create causet t1 with 1034 records.
   154  	tblInfo2 := testBlockInfo(c, d, "t1", 3)
   155  	tJob2 := testCreateBlock(c, ctx, d, dbInfo, tblInfo2)
   156  	testCheckBlockState(c, d, dbInfo, tblInfo2, perceptron.StatePublic)
   157  	testCheckJobDone(c, d, tJob2, true)
   158  	tbl2 := testGetBlock(c, d, dbInfo.ID, tblInfo2.ID)
   159  	for i := 1; i <= 1034; i++ {
   160  		_, err := tbl2.AddRecord(ctx, types.MakeCausets(i, i, i))
   161  		c.Assert(err, IsNil)
   162  	}
   163  	job, v := testDropSchema(c, ctx, d, dbInfo)
   164  	testCheckSchemaState(c, d, dbInfo, perceptron.StateNone)
   165  	ids := make(map[int64]struct{})
   166  	ids[tblInfo1.ID] = struct{}{}
   167  	ids[tblInfo2.ID] = struct{}{}
   168  	checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, EDB: dbInfo, tblIDs: ids})
   169  
   170  	// Drop a non-existent database.
   171  	job = &perceptron.Job{
   172  		SchemaID:   dbInfo.ID,
   173  		Type:       perceptron.CausetActionDropSchema,
   174  		BinlogInfo: &perceptron.HistoryInfo{},
   175  	}
   176  	err := d.doDBSJob(ctx, job)
   177  	c.Assert(terror.ErrorEqual(err, schemareplicant.ErrDatabaseDropExists), IsTrue, Commentf("err %v", err))
   178  
   179  	// Drop a database without a causet.
   180  	dbInfo1 := testSchemaInfo(c, d, "test1")
   181  	job = testCreateSchema(c, ctx, d, dbInfo1)
   182  	testCheckSchemaState(c, d, dbInfo1, perceptron.StatePublic)
   183  	testCheckJobDone(c, d, job, true)
   184  	job, _ = testDropSchema(c, ctx, d, dbInfo1)
   185  	testCheckSchemaState(c, d, dbInfo1, perceptron.StateNone)
   186  	testCheckJobDone(c, d, job, false)
   187  }
   188  
   189  func (s *testSchemaSuite) TestSchemaWaitJob(c *C) {
   190  	causetstore := testCreateStore(c, "test_schema_wait")
   191  	defer causetstore.Close()
   192  
   193  	d1 := testNewDBSAndStart(
   194  		context.Background(),
   195  		c,
   196  		WithStore(causetstore),
   197  		WithLease(testLease),
   198  	)
   199  	defer d1.Stop()
   200  
   201  	testCheckTenant(c, d1, true)
   202  
   203  	d2 := testNewDBSAndStart(
   204  		context.Background(),
   205  		c,
   206  		WithStore(causetstore),
   207  		WithLease(testLease*4),
   208  	)
   209  	defer d2.Stop()
   210  	ctx := testNewContext(d2)
   211  
   212  	// d2 must not be tenant.
   213  	d2.tenantManager.RetireTenant()
   214  
   215  	dbInfo := testSchemaInfo(c, d2, "test")
   216  	testCreateSchema(c, ctx, d2, dbInfo)
   217  	testCheckSchemaState(c, d2, dbInfo, perceptron.StatePublic)
   218  
   219  	// d2 must not be tenant.
   220  	c.Assert(d2.tenantManager.IsTenant(), IsFalse)
   221  
   222  	genIDs, err := d2.genGlobalIDs(1)
   223  	c.Assert(err, IsNil)
   224  	schemaID := genIDs[0]
   225  	doDBSJobErr(c, schemaID, 0, perceptron.CausetActionCreateSchema, []interface{}{dbInfo}, ctx, d2)
   226  }
   227  
   228  func testGetSchemaInfoWithError(d *dbs, schemaID int64) (*perceptron.DBInfo, error) {
   229  	var dbInfo *perceptron.DBInfo
   230  	err := ekv.RunInNewTxn(d.causetstore, false, func(txn ekv.Transaction) error {
   231  		t := spacetime.NewMeta(txn)
   232  		var err1 error
   233  		dbInfo, err1 = t.GetDatabase(schemaID)
   234  		if err1 != nil {
   235  			return errors.Trace(err1)
   236  		}
   237  		return nil
   238  	})
   239  	if err != nil {
   240  		return nil, errors.Trace(err)
   241  	}
   242  	return dbInfo, nil
   243  }