github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/txn/txnimpl/database.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 txnimpl
    16  
    17  import (
    18  	"sync"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    23  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    24  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle"
    25  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
    26  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase"
    27  )
    28  
    29  type txnDBIt struct {
    30  	*sync.RWMutex
    31  	txn    txnif.AsyncTxn
    32  	linkIt *common.GenericSortedDListIt[*catalog.DBEntry]
    33  	itered bool // linkIt has no dummy head, use this to avoid duplicate filter logic for the very first entry
    34  	curr   *catalog.DBEntry
    35  	err    error
    36  }
    37  
    38  func newDBIt(txn txnif.AsyncTxn, c *catalog.Catalog) *txnDBIt {
    39  	it := &txnDBIt{
    40  		RWMutex: c.RWMutex,
    41  		txn:     txn,
    42  		linkIt:  c.MakeDBIt(true),
    43  	}
    44  	it.Next()
    45  	return it
    46  }
    47  
    48  func (it *txnDBIt) Close() error    { return nil }
    49  func (it *txnDBIt) GetError() error { return it.err }
    50  func (it *txnDBIt) Valid() bool {
    51  	if it.err != nil {
    52  		return false
    53  	}
    54  	return it.linkIt.Valid()
    55  }
    56  
    57  func (it *txnDBIt) Next() {
    58  	var err error
    59  	var valid bool
    60  	for {
    61  		if it.itered {
    62  			it.linkIt.Next()
    63  		}
    64  		node := it.linkIt.Get()
    65  		it.itered = true
    66  		if node == nil {
    67  			it.curr = nil
    68  			break
    69  		}
    70  		curr := node.GetPayload()
    71  		curr.RLock()
    72  		if curr.GetTenantID() == it.txn.GetTenantID() || isSysSharedDB(curr.GetName()) {
    73  			valid, err = curr.IsVisible(it.txn.GetStartTS(), curr.RWMutex)
    74  		}
    75  		curr.RUnlock()
    76  		if err != nil {
    77  			it.err = err
    78  			break
    79  		}
    80  		if valid {
    81  			it.curr = curr
    82  			break
    83  		}
    84  	}
    85  }
    86  
    87  func (it *txnDBIt) GetCurr() *catalog.DBEntry { return it.curr }
    88  
    89  type txnDatabase struct {
    90  	*txnbase.TxnDatabase
    91  	txnDB *txnDB
    92  }
    93  
    94  func newDatabase(db *txnDB) *txnDatabase {
    95  	dbase := &txnDatabase{
    96  		TxnDatabase: &txnbase.TxnDatabase{
    97  			Txn: db.store.txn,
    98  		},
    99  		txnDB: db,
   100  	}
   101  	return dbase
   102  
   103  }
   104  func (db *txnDatabase) GetID() uint64   { return db.txnDB.entry.GetID() }
   105  func (db *txnDatabase) GetName() string { return db.txnDB.entry.GetName() }
   106  func (db *txnDatabase) String() string  { return db.txnDB.entry.String() }
   107  
   108  func (db *txnDatabase) CreateRelation(def any) (rel handle.Relation, err error) {
   109  	return db.Txn.GetStore().CreateRelation(db.txnDB.entry.ID, def)
   110  }
   111  
   112  func (db *txnDatabase) CreateRelationWithID(def any, tableId uint64) (rel handle.Relation, err error) {
   113  	return db.Txn.GetStore().CreateRelationWithTableId(db.txnDB.entry.ID, tableId, def)
   114  }
   115  
   116  func (db *txnDatabase) DropRelationByName(name string) (rel handle.Relation, err error) {
   117  	return db.Txn.GetStore().DropRelationByName(db.txnDB.entry.ID, name)
   118  }
   119  
   120  func (db *txnDatabase) DropRelationByID(id uint64) (rel handle.Relation, err error) {
   121  	return db.Txn.GetStore().DropRelationByID(db.txnDB.entry.ID, id)
   122  }
   123  
   124  func (db *txnDatabase) TruncateByName(name string) (rel handle.Relation, err error) {
   125  	newTableId := db.txnDB.entry.GetCatalog().IDAlloctor.NextTable()
   126  
   127  	oldRel, err := db.DropRelationByName(name)
   128  	if err != nil {
   129  		err = moerr.NewInternalErrorNoCtx("%v: truncate %s error", err, name)
   130  		return
   131  	}
   132  	meta := oldRel.GetMeta().(*catalog.TableEntry)
   133  	schema := meta.GetSchema().Clone()
   134  	latest := meta.MVCCChain.GetLatestCommittedNode()
   135  	if latest != nil {
   136  		schema.Constraint = []byte(latest.(*catalog.TableMVCCNode).SchemaConstraints)
   137  	}
   138  	db.Txn.BindAccessInfo(schema.AcInfo.TenantID, schema.AcInfo.UserID, schema.AcInfo.RoleID)
   139  	rel, err = db.CreateRelationWithID(schema, newTableId)
   140  	if err != nil {
   141  		err = moerr.NewInternalErrorNoCtx("%v: truncate %s error", err, name)
   142  	}
   143  	return
   144  }
   145  
   146  func (db *txnDatabase) TruncateWithID(name string, newTableId uint64) (rel handle.Relation, err error) {
   147  
   148  	oldRel, err := db.DropRelationByName(name)
   149  	if err != nil {
   150  		err = moerr.NewInternalErrorNoCtx("%v: truncate %s error", err, name)
   151  		return
   152  	}
   153  	meta := oldRel.GetMeta().(*catalog.TableEntry)
   154  	schema := meta.GetSchema().Clone()
   155  	latest := meta.MVCCChain.GetLatestCommittedNode()
   156  	if latest != nil {
   157  		schema.Constraint = []byte(latest.(*catalog.TableMVCCNode).SchemaConstraints)
   158  	}
   159  	db.Txn.BindAccessInfo(schema.AcInfo.TenantID, schema.AcInfo.UserID, schema.AcInfo.RoleID)
   160  	rel, err = db.CreateRelationWithID(schema, newTableId)
   161  	if err != nil {
   162  		err = moerr.NewInternalErrorNoCtx("%v: truncate %s error", err, name)
   163  	}
   164  	return
   165  }
   166  
   167  func (db *txnDatabase) TruncateByID(id uint64, newTableId uint64) (rel handle.Relation, err error) {
   168  
   169  	oldRel, err := db.DropRelationByID(id)
   170  	if err != nil {
   171  		err = moerr.NewInternalErrorNoCtx("%v: truncate %d error", err, id)
   172  		return
   173  	}
   174  	meta := oldRel.GetMeta().(*catalog.TableEntry)
   175  	schema := meta.GetSchema().Clone()
   176  	latest := meta.MVCCChain.GetLatestCommittedNode()
   177  	if latest != nil {
   178  		schema.Constraint = []byte(latest.(*catalog.TableMVCCNode).SchemaConstraints)
   179  	}
   180  	db.Txn.BindAccessInfo(schema.AcInfo.TenantID, schema.AcInfo.UserID, schema.AcInfo.RoleID)
   181  	rel, err = db.CreateRelationWithID(schema, newTableId)
   182  	if err != nil {
   183  		err = moerr.NewInternalErrorNoCtx("%v: truncate %d error", err, id)
   184  	}
   185  	return
   186  }
   187  
   188  func (db *txnDatabase) GetRelationByName(name string) (rel handle.Relation, err error) {
   189  	return db.Txn.GetStore().GetRelationByName(db.txnDB.entry.ID, name)
   190  }
   191  
   192  func (db *txnDatabase) GetRelationByID(id uint64) (rel handle.Relation, err error) {
   193  	return db.Txn.GetStore().GetRelationByID(db.txnDB.entry.ID, id)
   194  }
   195  
   196  func (db *txnDatabase) UnsafeGetRelation(id uint64) (rel handle.Relation, err error) {
   197  	return db.Txn.GetStore().UnsafeGetRelation(db.txnDB.entry.ID, id)
   198  }
   199  
   200  func (db *txnDatabase) MakeRelationIt() (it handle.RelationIt) {
   201  	return newRelationIt(db.txnDB)
   202  }
   203  
   204  func (db *txnDatabase) RelationCnt() int64                  { return 0 }
   205  func (db *txnDatabase) Relations() (rels []handle.Relation) { return }
   206  func (db *txnDatabase) Close() error                        { return nil }
   207  func (db *txnDatabase) GetMeta() any                        { return db.txnDB.entry }