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  }