github.com/matrixorigin/matrixone@v1.2.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.IsVisibleWithLock(it.txn, 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.ID }
   105  func (db *txnDatabase) GetName() string      { return db.txnDB.entry.GetName() }
   106  func (db *txnDatabase) String() string       { return db.txnDB.entry.String() }
   107  func (db *txnDatabase) IsSubscription() bool { return db.txnDB.entry.IsSubscription() }
   108  func (db *txnDatabase) GetCreateSql() string { return db.txnDB.entry.GetCreateSql() }
   109  
   110  func (db *txnDatabase) CreateRelation(def any) (rel handle.Relation, err error) {
   111  	return db.Txn.GetStore().CreateRelation(db.txnDB.entry.ID, def)
   112  }
   113  
   114  func (db *txnDatabase) CreateRelationWithID(def any, tableId uint64) (rel handle.Relation, err error) {
   115  	return db.Txn.GetStore().CreateRelationWithTableId(db.txnDB.entry.ID, tableId, def)
   116  }
   117  
   118  func (db *txnDatabase) DropRelationByName(name string) (rel handle.Relation, err error) {
   119  	return db.Txn.GetStore().DropRelationByName(db.txnDB.entry.ID, name)
   120  }
   121  
   122  func (db *txnDatabase) DropRelationByID(id uint64) (rel handle.Relation, err error) {
   123  	return db.Txn.GetStore().DropRelationByID(db.txnDB.entry.ID, id)
   124  }
   125  
   126  func cloneLatestSchema(meta *catalog.TableEntry) *catalog.Schema {
   127  	latest := meta.MVCCChain.GetLatestCommittedNodeLocked()
   128  	if latest != nil {
   129  		return latest.BaseNode.Schema.Clone()
   130  	}
   131  	return meta.GetLastestSchemaLocked().Clone()
   132  }
   133  
   134  func (db *txnDatabase) TruncateByName(name string) (rel handle.Relation, err error) {
   135  	newTableId := db.txnDB.entry.GetCatalog().IDAlloctor.NextTable()
   136  
   137  	oldRel, err := db.DropRelationByName(name)
   138  	if err != nil {
   139  		err = moerr.NewInternalErrorNoCtx("%v: truncate %s error", err, name)
   140  		return
   141  	}
   142  	meta := oldRel.GetMeta().(*catalog.TableEntry)
   143  	schema := cloneLatestSchema(meta)
   144  	db.Txn.BindAccessInfo(schema.AcInfo.TenantID, schema.AcInfo.UserID, schema.AcInfo.RoleID)
   145  	rel, err = db.CreateRelationWithID(schema, newTableId)
   146  	if err != nil {
   147  		err = moerr.NewInternalErrorNoCtx("%v: truncate %s error", err, name)
   148  	}
   149  	return
   150  }
   151  
   152  func (db *txnDatabase) TruncateWithID(name string, newTableId uint64) (rel handle.Relation, err error) {
   153  
   154  	oldRel, err := db.DropRelationByName(name)
   155  	if err != nil {
   156  		err = moerr.NewInternalErrorNoCtx("%v: truncate %s error", err, name)
   157  		return
   158  	}
   159  	meta := oldRel.GetMeta().(*catalog.TableEntry)
   160  	schema := cloneLatestSchema(meta)
   161  	db.Txn.BindAccessInfo(schema.AcInfo.TenantID, schema.AcInfo.UserID, schema.AcInfo.RoleID)
   162  	rel, err = db.CreateRelationWithID(schema, newTableId)
   163  	if err != nil {
   164  		err = moerr.NewInternalErrorNoCtx("%v: truncate %s error", err, name)
   165  	}
   166  	return
   167  }
   168  
   169  func (db *txnDatabase) TruncateByID(id uint64, newTableId uint64) (rel handle.Relation, err error) {
   170  
   171  	oldRel, err := db.DropRelationByID(id)
   172  	if err != nil {
   173  		err = moerr.NewInternalErrorNoCtx("%v: truncate error", err)
   174  		return
   175  	}
   176  	meta := oldRel.GetMeta().(*catalog.TableEntry)
   177  	schema := cloneLatestSchema(meta)
   178  	db.Txn.BindAccessInfo(schema.AcInfo.TenantID, schema.AcInfo.UserID, schema.AcInfo.RoleID)
   179  	rel, err = db.CreateRelationWithID(schema, newTableId)
   180  	if err != nil {
   181  		err = moerr.NewInternalErrorNoCtx("%v: truncate %d error", err, id)
   182  	}
   183  	return
   184  }
   185  
   186  func (db *txnDatabase) GetRelationByName(name string) (rel handle.Relation, err error) {
   187  	return db.Txn.GetStore().GetRelationByName(db.txnDB.entry.ID, name)
   188  }
   189  
   190  func (db *txnDatabase) GetRelationByID(id uint64) (rel handle.Relation, err error) {
   191  	return db.Txn.GetStore().GetRelationByID(db.txnDB.entry.ID, id)
   192  }
   193  
   194  func (db *txnDatabase) UnsafeGetRelation(id uint64) (rel handle.Relation, err error) {
   195  	return db.Txn.GetStore().UnsafeGetRelation(db.txnDB.entry.ID, id)
   196  }
   197  
   198  func (db *txnDatabase) MakeRelationIt() (it handle.RelationIt) {
   199  	return newRelationIt(db.txnDB)
   200  }
   201  
   202  func (db *txnDatabase) RelationCnt() int64                  { return 0 }
   203  func (db *txnDatabase) Relations() (rels []handle.Relation) { return }
   204  func (db *txnDatabase) Close() error                        { return nil }
   205  func (db *txnDatabase) GetMeta() any                        { return db.txnDB.entry }