github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/txn/txnimpl/relation.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 "fmt" 19 "sync" 20 21 pkgcatalog "github.com/matrixorigin/matrixone/pkg/catalog" 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/containers" 25 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle" 26 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model" 28 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 29 ) 30 31 var _ handle.RelationIt = (*txnRelationIt)(nil) 32 33 type txnRelationIt struct { 34 *sync.RWMutex 35 txnDB *txnDB 36 linkIt *common.GenericSortedDListIt[*catalog.TableEntry] 37 itered bool // linkIt has no dummy head, use this to avoid duplicate filter logic for the very first entry 38 curr *catalog.TableEntry 39 err error 40 } 41 42 func newRelationIt(db *txnDB) *txnRelationIt { 43 it := &txnRelationIt{ 44 RWMutex: db.entry.RWMutex, 45 linkIt: db.entry.MakeTableIt(true), 46 txnDB: db, 47 } 48 it.Next() 49 return it 50 } 51 52 func (it *txnRelationIt) Close() error { return nil } 53 54 func (it *txnRelationIt) GetError() error { return it.err } 55 func (it *txnRelationIt) Valid() bool { 56 if it.err != nil { 57 return false 58 } 59 return it.linkIt.Valid() 60 } 61 62 func (it *txnRelationIt) Next() { 63 var err error 64 var valid bool 65 txn := it.txnDB.store.txn 66 for { 67 if it.itered { 68 it.linkIt.Next() 69 } 70 it.itered = true 71 node := it.linkIt.Get() 72 if node == nil { 73 it.curr = nil 74 break 75 } 76 entry := node.GetPayload() 77 entry.RLock() 78 // SystemDB can hold table created by different tenant, filter needed. 79 // while the 3 shared tables are not affected 80 if it.txnDB.entry.IsSystemDB() && !isSysTable(entry.GetSchema().Name) && 81 entry.GetSchema().AcInfo.TenantID != txn.GetTenantID() { 82 entry.RUnlock() 83 continue 84 } 85 valid, err = entry.IsVisible(it.txnDB.store.txn.GetStartTS(), entry.RWMutex) 86 entry.RUnlock() 87 if err != nil { 88 it.err = err 89 break 90 } 91 if valid { 92 it.curr = entry 93 break 94 } 95 } 96 } 97 98 func (it *txnRelationIt) GetCurr() *catalog.TableEntry { 99 return it.curr 100 } 101 102 func (it *txnRelationIt) GetRelation() handle.Relation { 103 table, _ := it.txnDB.getOrSetTable(it.curr.ID) 104 return newRelation(table) 105 } 106 107 type txnRelation struct { 108 *txnbase.TxnRelation 109 table *txnTable 110 } 111 112 func newRelation(table *txnTable) *txnRelation { 113 rel := &txnRelation{ 114 TxnRelation: &txnbase.TxnRelation{ 115 Txn: table.store.txn, 116 }, 117 table: table, 118 } 119 return rel 120 } 121 122 func (h *txnRelation) ID() uint64 { return h.table.entry.GetID() } 123 func (h *txnRelation) String() string { return h.table.entry.String() } 124 func (h *txnRelation) SimplePPString(level common.PPLevel) string { 125 s := h.table.entry.String() 126 if level < common.PPL1 { 127 return s 128 } 129 it := h.MakeBlockIt() 130 for it.Valid() { 131 block := it.GetBlock() 132 s = fmt.Sprintf("%s\n%s", s, block.String()) 133 it.Next() 134 } 135 return s 136 } 137 138 func (h *txnRelation) Close() error { return nil } 139 func (h *txnRelation) GetMeta() any { return h.table.entry } 140 func (h *txnRelation) Schema() any { return h.table.entry.GetSchema() } 141 142 func (h *txnRelation) Rows() int64 { 143 if h.table.entry.GetDB().IsSystemDB() && h.table.entry.IsVirtual() { 144 if h.table.entry.GetSchema().Name == pkgcatalog.MO_DATABASE { 145 return int64(h.table.entry.GetCatalog().CoarseDBCnt()) 146 } else if h.table.entry.GetSchema().Name == pkgcatalog.MO_TABLES { 147 return int64(h.table.entry.GetCatalog().CoarseTableCnt()) 148 } else if h.table.entry.GetSchema().Name == pkgcatalog.MO_COLUMNS { 149 return int64(h.table.entry.GetCatalog().CoarseColumnCnt()) 150 } 151 panic("logic error") 152 } 153 return int64(h.table.entry.GetRows()) 154 } 155 func (h *txnRelation) GetCardinality(attr string) int64 { return 0 } 156 157 func (h *txnRelation) BatchDedup(col containers.Vector) error { 158 return h.Txn.GetStore().BatchDedup(h.table.entry.GetDB().ID, h.table.entry.GetID(), col) 159 } 160 161 func (h *txnRelation) Append(data *containers.Batch) error { 162 return h.Txn.GetStore().Append(h.table.entry.GetDB().ID, h.table.entry.GetID(), data) 163 } 164 165 func (h *txnRelation) AddBlksWithMetaLoc( 166 pkVecs []containers.Vector, 167 file string, 168 metaLocs []string, 169 flag int32) error { 170 return h.Txn.GetStore().AddBlksWithMetaLoc( 171 h.table.entry.GetDB().ID, 172 h.table.entry.GetID(), 173 pkVecs, 174 file, 175 metaLocs, 176 flag, 177 ) 178 } 179 180 func (h *txnRelation) GetSegment(id uint64) (seg handle.Segment, err error) { 181 fp := h.table.entry.AsCommonID() 182 fp.SegmentID = id 183 return h.Txn.GetStore().GetSegment(h.table.entry.GetDB().ID, fp) 184 } 185 186 func (h *txnRelation) CreateSegment(is1PC bool) (seg handle.Segment, err error) { 187 return h.Txn.GetStore().CreateSegment(h.table.entry.GetDB().ID, h.table.entry.GetID(), is1PC) 188 } 189 190 func (h *txnRelation) CreateNonAppendableSegment(is1PC bool) (seg handle.Segment, err error) { 191 return h.Txn.GetStore().CreateNonAppendableSegment(h.table.entry.GetDB().ID, h.table.entry.GetID(), is1PC) 192 } 193 194 func (h *txnRelation) SoftDeleteSegment(id uint64) (err error) { 195 fp := h.table.entry.AsCommonID() 196 fp.SegmentID = id 197 return h.Txn.GetStore().SoftDeleteSegment(h.table.entry.GetDB().ID, fp) 198 } 199 200 func (h *txnRelation) MakeSegmentIt() handle.SegmentIt { 201 return newSegmentIt(h.table) 202 } 203 204 func (h *txnRelation) MakeBlockIt() handle.BlockIt { 205 return newRelationBlockIt(h) 206 } 207 208 func (h *txnRelation) GetByFilter(filter *handle.Filter) (*common.ID, uint32, error) { 209 return h.Txn.GetStore().GetByFilter(h.table.entry.GetDB().ID, h.table.entry.GetID(), filter) 210 } 211 212 func (h *txnRelation) GetValueByFilter(filter *handle.Filter, col int) (v any, err error) { 213 id, row, err := h.GetByFilter(filter) 214 if err != nil { 215 return 216 } 217 v, err = h.GetValue(id, row, uint16(col)) 218 return 219 } 220 221 func (h *txnRelation) UpdateByFilter(filter *handle.Filter, col uint16, v any) (err error) { 222 id, row, err := h.table.GetByFilter(filter) 223 if err != nil { 224 return 225 } 226 schema := h.table.entry.GetSchema() 227 bat := containers.NewBatch() 228 defer bat.Close() 229 for _, def := range schema.ColDefs { 230 if def.IsPhyAddr() { 231 continue 232 } 233 var colVal any 234 if int(col) == def.Idx { 235 colVal = v 236 } else { 237 colVal, err = h.table.GetValue(id, row, uint16(def.Idx)) 238 if err != nil { 239 return err 240 } 241 } 242 vec := containers.MakeVector(def.Type, def.Nullable()) 243 vec.Append(colVal) 244 bat.AddVector(def.Name, vec) 245 } 246 if err = h.table.RangeDelete(id, row, row, handle.DT_Normal); err != nil { 247 return 248 } 249 err = h.Append(bat) 250 // FIXME!: We need to revert previous delete if append fails. 251 return 252 } 253 254 func (h *txnRelation) DeleteByFilter(filter *handle.Filter) (err error) { 255 id, row, err := h.GetByFilter(filter) 256 if err != nil { 257 return 258 } 259 return h.RangeDelete(id, row, row, handle.DT_Normal) 260 } 261 262 func (h *txnRelation) DeleteByPhyAddrKeys(keys containers.Vector) (err error) { 263 id := &common.ID{ 264 TableID: h.table.entry.ID, 265 } 266 var row uint32 267 dbId := h.table.entry.GetDB().ID 268 err = keys.Foreach(func(key any, _ int) (err error) { 269 id.SegmentID, id.BlockID, row = model.DecodePhyAddrKeyFromValue(key) 270 err = h.Txn.GetStore().RangeDelete(dbId, id, row, row, handle.DT_Normal) 271 return 272 }, nil) 273 return 274 } 275 276 func (h *txnRelation) DeleteByPhyAddrKey(key any) error { 277 sid, bid, row := model.DecodePhyAddrKeyFromValue(key) 278 id := &common.ID{ 279 TableID: h.table.entry.ID, 280 SegmentID: sid, 281 BlockID: bid, 282 } 283 return h.Txn.GetStore().RangeDelete(h.table.entry.GetDB().ID, id, row, row, handle.DT_Normal) 284 } 285 286 func (h *txnRelation) RangeDelete(id *common.ID, start, end uint32, dt handle.DeleteType) error { 287 return h.Txn.GetStore().RangeDelete(h.table.entry.GetDB().ID, id, start, end, dt) 288 } 289 290 func (h *txnRelation) GetValueByPhyAddrKey(key any, col int) (any, error) { 291 sid, bid, row := model.DecodePhyAddrKeyFromValue(key) 292 id := &common.ID{ 293 TableID: h.table.entry.ID, 294 SegmentID: sid, 295 BlockID: bid, 296 } 297 return h.Txn.GetStore().GetValue(h.table.entry.GetDB().ID, id, row, uint16(col)) 298 } 299 300 func (h *txnRelation) GetValue(id *common.ID, row uint32, col uint16) (any, error) { 301 return h.Txn.GetStore().GetValue(h.table.entry.GetDB().ID, id, row, col) 302 } 303 304 func (h *txnRelation) LogTxnEntry(entry txnif.TxnEntry, readed []*common.ID) (err error) { 305 return h.Txn.GetStore().LogTxnEntry(h.table.entry.GetDB().ID, h.table.entry.GetID(), entry, readed) 306 } 307 308 func (h *txnRelation) GetDB() (handle.Database, error) { 309 return h.Txn.GetStore().GetDatabase(h.GetMeta().(*catalog.TableEntry).GetDB().GetName()) 310 } 311 312 func (h *txnRelation) UpdateConstraint(cstr []byte) (err error) { 313 return h.table.UpdateConstraint(cstr) 314 }