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 }