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 }