github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/catalog/catalog_test.go (about) 1 // Copyright 2021 Matrix Origin 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 package catalog 16 17 import ( 18 "context" 19 "fmt" 20 "sync" 21 "testing" 22 "time" 23 24 "github.com/matrixorigin/matrixone/pkg/common/moerr" 25 "github.com/matrixorigin/matrixone/pkg/container/types" 26 "github.com/matrixorigin/matrixone/pkg/pb/api" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 28 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 29 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/testutils" 30 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 31 "github.com/stretchr/testify/assert" 32 "github.com/stretchr/testify/require" 33 ) 34 35 const ( 36 ModuleName = "TAECATALOG" 37 ) 38 39 func TestCreateDB1(t *testing.T) { 40 defer testutils.AfterTest(t)() 41 catalog := MockCatalog() 42 defer catalog.Close() 43 44 txnMgr := txnbase.NewTxnManager(MockTxnStoreFactory(catalog), MockTxnFactory(catalog), types.NewMockHLCClock(1)) 45 txnMgr.Start(context.Background()) 46 defer txnMgr.Stop() 47 48 txn1, _ := txnMgr.StartTxn(nil) 49 50 name := fmt.Sprintf("%s-%d", t.Name(), 1) 51 db1, err := txn1.CreateDatabase(name, "", "") 52 assert.Nil(t, err) 53 t.Log(db1.String()) 54 55 assert.Equal(t, 2, len(catalog.entries)) 56 cnt := 0 57 catalog.link.Loop(func(n *common.GenericDLNode[*DBEntry]) bool { 58 t.Log(n.GetPayload().ID) 59 cnt++ 60 return true 61 }, true) 62 assert.Equal(t, 2, cnt) 63 64 _, err = txn1.CreateDatabase(name, "", "") 65 assert.True(t, moerr.IsMoErrCode(err, moerr.OkExpectedDup)) 66 67 txn2, _ := txnMgr.StartTxn(nil) 68 69 _, err = txn2.CreateDatabase(name, "", "") 70 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrTxnWWConflict)) 71 72 _, err = txn1.GetDatabase(name) 73 assert.Nil(t, err) 74 75 err = txn1.Commit(context.Background()) 76 assert.Nil(t, err) 77 78 assert.Nil(t, err) 79 // assert.False(t, db1.(*mcokDBHandle).entry.IsCommitting()) 80 81 _, err = txn2.CreateDatabase(name, "", "") 82 assert.NotNil(t, err) 83 84 _, err = txn2.DropDatabase(name) 85 assert.True(t, moerr.IsMoErrCode(err, moerr.OkExpectedEOB)) 86 87 txn3, _ := txnMgr.StartTxn(nil) 88 _, err = txn3.DropDatabase(name) 89 assert.Nil(t, err) 90 // assert.True(t, db1.(*mcokDBHandle).entry.IsDroppedUncommitted()) 91 92 _, err = txn3.CreateDatabase(name, "", "") 93 assert.Nil(t, err) 94 95 cnt = 0 96 catalog.link.Loop(func(n *common.GenericDLNode[*DBEntry]) bool { 97 // t.Log(n.payload.(*DBEntry).String()) 98 cnt++ 99 return true 100 }, true) 101 assert.Equal(t, 3, cnt) 102 103 txn4, _ := txnMgr.StartTxn(nil) 104 105 h, err := txn4.GetDatabase(name) 106 assert.Nil(t, err) 107 assert.NotNil(t, h) 108 // assert.Equal(t, db1.(*mcokDBHandle).entry, h.(*mcokDBHandle).entry) 109 } 110 111 // TXN1-S TXN2-S TXN1-C TXN3-S TXN4-S TXN3-C TXN5-S 112 // 113 // | | | | | | | Time 114 // 115 // -+-+---+---+--+--+----+---+--+---+-+----+-+-----+------+-+------------------------------------> 116 // 117 // | | | | | | | | | 118 // | | | | | | | | [TXN5]: GET TBL [NOTFOUND] 119 // | | | | | | | [TXN4]: GET TBL [OK] | DROP DB1-TB1 [W-W] 120 // | | | | | | [TXN3]: GET TBL [OK] | DROP DB1-TB1 [OK] | GET TBL [NOT FOUND] 121 // | | | | | [TXN2]: DROP DB [NOTFOUND] 122 // | | | | [TXN2]: DROP DB [NOTFOUND] 123 // | | | [TXN2]: GET DB [NOTFOUND] | CREATE DB [W-W] 124 // | | [TXN1]: CREATE DB1-TB1 [DUP] 125 // | [TXN1]: CREATE DB1-TB1 [OK] | GET TBL [OK] 126 // [TXN1]: CREATE DB1 [OK] | GET DB [OK] 127 func TestTableEntry1(t *testing.T) { 128 defer testutils.AfterTest(t)() 129 catalog := MockCatalog() 130 defer catalog.Close() 131 132 txnMgr := txnbase.NewTxnManager(MockTxnStoreFactory(catalog), MockTxnFactory(catalog), types.NewMockHLCClock(1)) 133 txnMgr.Start(context.Background()) 134 defer txnMgr.Stop() 135 136 txn1, _ := txnMgr.StartTxn(nil) 137 name := "db1" 138 db1, err := txn1.CreateDatabase(name, "", "") 139 assert.Nil(t, err) 140 t.Log(db1.String()) 141 142 schema := MockSchema(2, 0) 143 schema.Name = "tb1" 144 tb1, err := db1.CreateRelation(schema) 145 assert.Nil(t, err) 146 t.Log(tb1.String()) 147 148 _, err = db1.GetRelationByName(schema.Name) 149 assert.Nil(t, err) 150 151 _, err = db1.CreateRelation(schema) 152 assert.True(t, moerr.IsMoErrCode(err, moerr.OkExpectedDup)) 153 154 txn2, _ := txnMgr.StartTxn(nil) 155 _, err = txn2.GetDatabase(schema.Name) 156 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrBadDB)) 157 158 _, err = txn2.CreateDatabase(name, "", "") 159 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrTxnWWConflict)) 160 161 _, err = txn2.DropDatabase(name) 162 assert.True(t, moerr.IsMoErrCode(err, moerr.OkExpectedEOB)) 163 164 err = txn1.Commit(context.Background()) 165 assert.Nil(t, err) 166 167 _, err = txn2.DropDatabase(name) 168 assert.True(t, moerr.IsMoErrCode(err, moerr.OkExpectedEOB)) 169 170 txn3, _ := txnMgr.StartTxn(nil) 171 db, err := txn3.GetDatabase(name) 172 assert.Nil(t, err) 173 174 _, err = db.DropRelationByName(schema.Name) 175 assert.Nil(t, err) 176 t.Log(tb1.String()) 177 178 _, err = db.GetRelationByName(schema.Name) 179 assert.True(t, moerr.IsMoErrCode(err, moerr.OkExpectedEOB)) 180 181 txn4, _ := txnMgr.StartTxn(nil) 182 db, err = txn4.GetDatabase(name) 183 assert.Nil(t, err) 184 _, err = db.GetRelationByName(schema.Name) 185 assert.Nil(t, err) 186 187 _, err = db.DropRelationByName(schema.Name) 188 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrTxnWWConflict)) 189 190 err = txn3.Commit(context.Background()) 191 assert.Nil(t, err) 192 193 t.Log(tb1.String()) 194 195 txn5, _ := txnMgr.StartTxn(nil) 196 db, err = txn5.GetDatabase(name) 197 assert.Nil(t, err) 198 _, err = db.GetRelationByName(schema.Name) 199 assert.True(t, moerr.IsMoErrCode(err, moerr.OkExpectedEOB)) 200 } 201 202 func TestTableEntry2(t *testing.T) { 203 defer testutils.AfterTest(t)() 204 catalog := MockCatalog() 205 defer catalog.Close() 206 207 txnMgr := txnbase.NewTxnManager(MockTxnStoreFactory(catalog), MockTxnFactory(catalog), types.NewMockHLCClock(1)) 208 txnMgr.Start(context.Background()) 209 defer txnMgr.Stop() 210 211 txn1, _ := txnMgr.StartTxn(nil) 212 name := "db1" 213 db, err := txn1.CreateDatabase(name, "", "") 214 assert.Nil(t, err) 215 schema := MockSchema(2, 0) 216 schema.Name = "tb1" 217 _, err = db.CreateRelation(schema) 218 assert.Nil(t, err) 219 220 for i := 0; i < 1000; i++ { 221 s := MockSchema(1, 0) 222 s.Name = fmt.Sprintf("xx%d", i) 223 _, err = db.CreateRelation(s) 224 assert.Nil(t, err) 225 } 226 err = txn1.Commit(context.Background()) 227 assert.Nil(t, err) 228 229 txn2, _ := txnMgr.StartTxn(nil) 230 db, err = txn2.GetDatabase(name) 231 assert.Nil(t, err) 232 rel, err := db.DropRelationByName(schema.Name) 233 assert.Nil(t, err) 234 t.Log(rel.String()) 235 db, err = txn2.DropDatabase(name) 236 assert.Nil(t, err) 237 t.Log(db.String()) 238 239 var wg sync.WaitGroup 240 txns := []txnif.AsyncTxn{txn2} 241 for i := 0; i < 10; i++ { 242 txn, _ := txnMgr.StartTxn(nil) 243 txns = append(txns, txn) 244 } 245 now := time.Now() 246 for _, txn := range txns { 247 wg.Add(1) 248 go func(ttxn txnif.AsyncTxn) { 249 defer wg.Done() 250 for i := 0; i < 1000; i++ { 251 database, err := ttxn.GetDatabase(name) 252 if err != nil { 253 // t.Logf("db-ttxn=%d, %s", ttxn.GetID(), err) 254 } else { 255 // t.Logf("db-ttxn=%d, %v", ttxn.GetID(), err) 256 _, err := database.GetRelationByName(schema.Name) 257 assert.NoError(t, err) 258 } 259 } 260 }(txn) 261 } 262 wg.Wait() 263 t.Log(time.Since(now)) 264 } 265 266 func TestDB1(t *testing.T) { 267 defer testutils.AfterTest(t)() 268 catalog := MockCatalog() 269 defer catalog.Close() 270 271 txnMgr := txnbase.NewTxnManager(MockTxnStoreFactory(catalog), MockTxnFactory(catalog), types.NewMockHLCClock(1)) 272 txnMgr.Start(context.Background()) 273 defer txnMgr.Stop() 274 name := "db1" 275 var wg sync.WaitGroup 276 flow := func() { 277 defer wg.Done() 278 txn, _ := txnMgr.StartTxn(nil) 279 _, err := txn.GetDatabase(name) 280 if moerr.IsMoErrCode(err, moerr.OkExpectedEOB) { 281 _, err = txn.CreateDatabase(name, "", "") 282 if err != nil { 283 return 284 } 285 } else { 286 _, err = txn.DropDatabase(name) 287 if err != nil { 288 return 289 } 290 } 291 err = txn.Commit(context.Background()) 292 assert.Nil(t, err) 293 } 294 295 for i := 0; i < 1000; i++ { 296 wg.Add(1) 297 go flow() 298 } 299 wg.Wait() 300 } 301 302 func TestTable1(t *testing.T) { 303 defer testutils.AfterTest(t)() 304 catalog := MockCatalog() 305 defer catalog.Close() 306 307 txnMgr := txnbase.NewTxnManager(MockTxnStoreFactory(catalog), MockTxnFactory(catalog), types.NewMockHLCClock(1)) 308 txnMgr.Start(context.Background()) 309 defer txnMgr.Stop() 310 name := "db1" 311 tbName := "tb1" 312 var wg sync.WaitGroup 313 flow := func() { 314 defer wg.Done() 315 txn, _ := txnMgr.StartTxn(nil) 316 db, err := txn.GetDatabase(name) 317 assert.Nil(t, err) 318 _, err = db.GetRelationByName(tbName) 319 if moerr.IsMoErrCode(err, moerr.OkExpectedEOB) { 320 schema := MockSchema(1, 0) 321 schema.Name = tbName 322 if _, err = db.CreateRelation(schema); err != nil { 323 return 324 } 325 } else { 326 if _, err = db.DropRelationByName(tbName); err != nil { 327 return 328 } 329 } 330 err = txn.Commit(context.Background()) 331 assert.Nil(t, err) 332 // t.Log(rel.String()) 333 } 334 { 335 txn, _ := txnMgr.StartTxn(nil) 336 _, err := txn.CreateDatabase(name, "", "") 337 assert.Nil(t, err) 338 err = txn.Commit(context.Background()) 339 assert.Nil(t, err) 340 } 341 for i := 0; i < 1000; i++ { 342 wg.Add(1) 343 go flow() 344 } 345 wg.Wait() 346 } 347 348 // UT Steps 349 // 1. Start Txn1, create a database "db", table "tb" and Object "obj1", then commit Txn1 350 // 1. Start Txn2, create a Object "obj2". Txn2 scan "tb" and "obj1, obj2" found 351 // 2. Start Txn3, scan "tb" and only "obj1" found 352 // 3. Commit Txn2 353 // 4. Txn3 scan "tb" and also only "obj1" found 354 // 5. Start Txn4, scan "tb" and both "obj1" and "obj2" found 355 func TestObject1(t *testing.T) { 356 defer testutils.AfterTest(t)() 357 catalog := MockCatalog() 358 defer catalog.Close() 359 txnMgr := txnbase.NewTxnManager(MockTxnStoreFactory(catalog), MockTxnFactory(catalog), types.NewMockHLCClock(1)) 360 txnMgr.Start(context.Background()) 361 defer txnMgr.Stop() 362 name := "db" 363 tbName := "tb" 364 txn1, _ := txnMgr.StartTxn(nil) 365 db, err := catalog.CreateDBEntry(name, "", "", txn1) 366 assert.Nil(t, err) 367 schema := MockSchema(1, 0) 368 schema.Name = tbName 369 tb, err := db.CreateTableEntry(schema, txn1, nil) 370 assert.Nil(t, err) 371 obj1, err := tb.CreateObject(txn1, ES_Appendable, nil, nil) 372 assert.Nil(t, err) 373 err = txn1.Commit(context.Background()) 374 assert.Nil(t, err) 375 t.Log(obj1.String()) 376 t.Log(tb.String()) 377 } 378 379 func TestAlterSchema(t *testing.T) { 380 schema := MockSchema(10, 5) 381 req := api.NewAddColumnReq(0, 0, "xyz", types.NewProtoType(types.T_int32), 2) 382 require.NoError(t, schema.ApplyAlterTable(req)) 383 require.Equal(t, 12, len(schema.NameMap)) 384 require.Equal(t, 12, len(schema.SeqnumMap)) 385 386 require.Equal(t, 2, schema.GetColIdx("xyz")) 387 require.Equal(t, uint16(10), schema.GetSeqnum("xyz")) 388 require.Equal(t, 2, schema.SeqnumMap[10]) 389 require.Equal(t, 6, schema.GetColIdx("mock_5")) 390 require.Equal(t, uint16(5), schema.GetSeqnum("mock_5")) 391 require.Equal(t, 11, schema.GetColIdx(PhyAddrColumnName)) 392 require.Equal(t, uint16(65535), schema.GetSeqnum(PhyAddrColumnName)) 393 require.Equal(t, true, schema.HasPK()) 394 require.Equal(t, true, schema.HasSortKey()) 395 require.Equal(t, "mock_5", schema.GetSingleSortKey().Name) 396 require.Equal(t, uint16(5), schema.GetSingleSortKey().SeqNum) 397 require.Equal(t, 6, schema.GetSingleSortKeyIdx()) 398 399 req = api.NewRemoveColumnReq(0, 0, 4, 3) 400 schema.ApplyAlterTable(req) 401 require.Equal(t, 11, len(schema.NameMap)) 402 require.Equal(t, 11, len(schema.SeqnumMap)) 403 404 require.Equal(t, 2, schema.GetColIdx("xyz")) 405 require.Equal(t, uint16(10), schema.GetSeqnum("xyz")) 406 require.Equal(t, 2, schema.SeqnumMap[10]) 407 require.Equal(t, 5, schema.GetColIdx("mock_5")) 408 require.Equal(t, uint16(5), schema.GetSeqnum("mock_5")) 409 require.Equal(t, 10, schema.GetColIdx(PhyAddrColumnName)) 410 require.Equal(t, uint16(65535), schema.GetSeqnum(PhyAddrColumnName)) 411 require.Equal(t, true, schema.HasPK()) 412 require.Equal(t, true, schema.HasSortKey()) 413 require.Equal(t, "mock_5", schema.GetSingleSortKey().Name) 414 require.Equal(t, uint16(5), schema.GetSingleSortKey().SeqNum) 415 require.Equal(t, 5, schema.GetSingleSortKeyIdx()) 416 417 }