github.com/matrixorigin/matrixone@v1.2.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 "context" 19 "fmt" 20 "sync" 21 22 "github.com/matrixorigin/matrixone/pkg/common/moerr" 23 "github.com/matrixorigin/matrixone/pkg/objectio" 24 apipb "github.com/matrixorigin/matrixone/pkg/pb/api" 25 26 "github.com/matrixorigin/matrixone/pkg/container/types" 27 28 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog" 29 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 30 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" 31 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle" 32 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 33 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 34 ) 35 36 var _ handle.RelationIt = (*txnRelationIt)(nil) 37 38 type txnRelationIt struct { 39 *sync.RWMutex 40 txnDB *txnDB 41 linkIt *common.GenericSortedDListIt[*catalog.TableEntry] 42 itered bool // linkIt has no dummy head, use this to avoid duplicate filter logic for the very first entry 43 curr *catalog.TableEntry 44 err error 45 } 46 47 func newRelationIt(db *txnDB) *txnRelationIt { 48 it := &txnRelationIt{ 49 RWMutex: db.entry.RWMutex, 50 linkIt: db.entry.MakeTableIt(true), 51 txnDB: db, 52 } 53 it.Next() 54 return it 55 } 56 57 func (it *txnRelationIt) Close() error { return nil } 58 59 func (it *txnRelationIt) GetError() error { return it.err } 60 func (it *txnRelationIt) Valid() bool { 61 if it.err != nil { 62 return false 63 } 64 return it.linkIt.Valid() 65 } 66 67 func (it *txnRelationIt) Next() { 68 var err error 69 var valid bool 70 txn := it.txnDB.store.txn 71 for { 72 if it.itered { 73 it.linkIt.Next() 74 } 75 it.itered = true 76 node := it.linkIt.Get() 77 if node == nil { 78 it.curr = nil 79 break 80 } 81 entry := node.GetPayload() 82 entry.RLock() 83 // SystemDB can hold table created by different tenant, filter needed. 84 // while the 3 shared tables are not affected 85 if it.txnDB.entry.IsSystemDB() && !isSysTable(entry.GetLastestSchemaLocked().Name) && 86 entry.GetLastestSchemaLocked().AcInfo.TenantID != txn.GetTenantID() { 87 entry.RUnlock() 88 continue 89 } 90 valid, err = entry.IsVisibleWithLock(it.txnDB.store.txn, entry.RWMutex) 91 entry.RUnlock() 92 if err != nil { 93 it.err = err 94 break 95 } 96 if valid { 97 it.curr = entry 98 break 99 } 100 } 101 } 102 103 func (it *txnRelationIt) GetCurr() *catalog.TableEntry { 104 return it.curr 105 } 106 107 func (it *txnRelationIt) GetRelation() handle.Relation { 108 table, _ := it.txnDB.getOrSetTable(it.curr.ID) 109 return newRelation(table) 110 } 111 112 type txnRelation struct { 113 *txnbase.TxnRelation 114 table *txnTable 115 } 116 117 func newRelation(table *txnTable) *txnRelation { 118 rel := &txnRelation{ 119 TxnRelation: &txnbase.TxnRelation{ 120 Txn: table.store.txn, 121 }, 122 table: table, 123 } 124 return rel 125 } 126 127 func (h *txnRelation) ID() uint64 { return h.table.entry.GetID() } 128 func (h *txnRelation) String() string { return h.table.entry.String() } 129 func (h *txnRelation) SimplePPString(level common.PPLevel) string { 130 s := h.table.entry.String() 131 if level < common.PPL1 { 132 return s 133 } 134 it := h.MakeObjectIt() 135 for it.Valid() { 136 object := it.GetObject() 137 defer object.Close() 138 s = fmt.Sprintf("%s\n%s", s, object.String()) 139 it.Next() 140 } 141 return s 142 } 143 144 func (h *txnRelation) Close() error { return nil } 145 func (h *txnRelation) GetMeta() any { return h.table.entry } 146 147 // Schema return schema in txnTable, not the lastest schema in TableEntry 148 func (h *txnRelation) Schema() any { return h.table.GetLocalSchema() } 149 150 func (h *txnRelation) GetCardinality(attr string) int64 { return 0 } 151 152 func (h *txnRelation) BatchDedup(col containers.Vector) error { 153 return h.Txn.GetStore().BatchDedup(h.table.entry.GetDB().ID, h.table.entry.GetID(), col) 154 } 155 156 func (h *txnRelation) Append(ctx context.Context, data *containers.Batch) error { 157 if !h.table.GetLocalSchema().IsSameColumns(h.table.GetMeta().GetLastestSchemaLocked()) { 158 return moerr.NewInternalErrorNoCtx("schema changed, please rollback and retry") 159 } 160 return h.Txn.GetStore().Append(ctx, h.table.entry.GetDB().ID, h.table.entry.GetID(), data) 161 } 162 163 func (h *txnRelation) AddObjsWithMetaLoc(ctx context.Context, stats containers.Vector) error { 164 return h.Txn.GetStore().AddObjsWithMetaLoc( 165 ctx, 166 h.table.entry.GetDB().ID, 167 h.table.entry.GetID(), 168 stats, 169 ) 170 } 171 172 func (h *txnRelation) GetObject(id *types.Objectid) (obj handle.Object, err error) { 173 fp := h.table.entry.AsCommonID() 174 fp.SetObjectID(id) 175 return h.Txn.GetStore().GetObject(fp) 176 } 177 178 func (h *txnRelation) CreateObject(is1PC bool) (obj handle.Object, err error) { 179 return h.Txn.GetStore().CreateObject(h.table.entry.GetDB().ID, h.table.entry.GetID(), is1PC) 180 } 181 182 func (h *txnRelation) CreateNonAppendableObject(is1PC bool, opt *objectio.CreateObjOpt) (obj handle.Object, err error) { 183 return h.Txn.GetStore().CreateNonAppendableObject(h.table.entry.GetDB().ID, h.table.entry.GetID(), is1PC, opt) 184 } 185 186 func (h *txnRelation) SoftDeleteObject(id *types.Objectid) (err error) { 187 fp := h.table.entry.AsCommonID() 188 fp.SetObjectID(id) 189 return h.Txn.GetStore().SoftDeleteObject(fp) 190 } 191 192 func (h *txnRelation) MakeObjectItOnSnap() handle.ObjectIt { 193 return newObjectItOnSnap(h.table) 194 } 195 196 func (h *txnRelation) MakeObjectIt() handle.ObjectIt { 197 return newObjectIt(h.table) 198 } 199 200 func (h *txnRelation) GetByFilter( 201 ctx context.Context, filter *handle.Filter, 202 ) (*common.ID, uint32, error) { 203 return h.Txn.GetStore().GetByFilter(ctx, h.table.entry.GetDB().ID, h.table.entry.GetID(), filter) 204 } 205 206 func (h *txnRelation) GetValueByFilter( 207 ctx context.Context, filter *handle.Filter, col int, 208 ) (v any, isNull bool, err error) { 209 id, row, err := h.GetByFilter(ctx, filter) 210 if err != nil { 211 return 212 } 213 v, isNull, err = h.GetValue(id, row, uint16(col)) 214 return 215 } 216 217 func (h *txnRelation) UpdateByFilter(ctx context.Context, filter *handle.Filter, col uint16, v any, isNull bool) (err error) { 218 id, row, err := h.table.GetByFilter(ctx, filter) 219 if err != nil { 220 return 221 } 222 schema := h.table.GetLocalSchema() 223 pkDef := schema.GetPrimaryKey() 224 pkVec := makeWorkspaceVector(pkDef.Type) 225 defer pkVec.Close() 226 pkVal, _, err := h.table.GetValue(ctx, id, row, uint16(pkDef.Idx)) 227 if err != nil { 228 return err 229 } 230 pkVec.Append(pkVal, false) 231 bat := containers.NewBatch() 232 defer bat.Close() 233 for _, def := range schema.ColDefs { 234 if def.IsPhyAddr() { 235 continue 236 } 237 var colVal any 238 var colValIsNull bool 239 if int(col) == def.Idx { 240 colVal = v 241 colValIsNull = isNull 242 } else { 243 colVal, colValIsNull, err = h.table.GetValue(ctx, id, row, uint16(def.Idx)) 244 if err != nil { 245 return err 246 } 247 } 248 vec := makeWorkspaceVector(def.Type) 249 vec.Append(colVal, colValIsNull) 250 bat.AddVector(def.Name, vec) 251 } 252 if err = h.table.RangeDelete(id, row, row, pkVec, handle.DT_Normal); err != nil { 253 return 254 } 255 err = h.Append(ctx, bat) 256 // FIXME!: We need to revert previous delete if append fails. 257 return 258 } 259 260 func (h *txnRelation) DeleteByFilter(ctx context.Context, filter *handle.Filter) (err error) { 261 id, row, err := h.GetByFilter(ctx, filter) 262 if err != nil { 263 return 264 } 265 return h.RangeDelete(id, row, row, handle.DT_Normal) 266 } 267 268 func (h *txnRelation) DeleteByPhyAddrKeys(keys containers.Vector, pkVec containers.Vector) (err error) { 269 id := h.table.entry.AsCommonID() 270 var row uint32 271 var pk containers.Vector 272 err = containers.ForeachVectorWindow( 273 keys, 0, keys.Length(), 274 func(rid types.Rowid, _ bool, offset int) (err error) { 275 id.BlockID, row = rid.Decode() 276 if pkVec != nil && pkVec.Length() > 0 { 277 pk = pkVec.Window(offset, 1) 278 } 279 err = h.Txn.GetStore().RangeDelete( 280 id, 281 row, 282 row, 283 pk, 284 handle.DT_Normal, 285 ) 286 return 287 }, nil, nil) 288 return 289 } 290 291 // Only used by test. 292 func (h *txnRelation) DeleteByPhyAddrKey(key any) error { 293 rid := key.(types.Rowid) 294 bid, row := rid.Decode() 295 id := h.table.entry.AsCommonID() 296 id.BlockID = bid 297 schema := h.table.GetLocalSchema() 298 pkDef := schema.GetPrimaryKey() 299 pkVec := makeWorkspaceVector(pkDef.Type) 300 defer pkVec.Close() 301 val, _, err := h.table.GetValue(h.table.store.ctx, id, row, uint16(pkDef.Idx)) 302 if err != nil { 303 return err 304 } 305 pkVec.Append(val, false) 306 return h.Txn.GetStore().RangeDelete(id, row, row, pkVec, handle.DT_Normal) 307 } 308 309 func (h *txnRelation) RangeDelete(id *common.ID, start, end uint32, dt handle.DeleteType) error { 310 schema := h.table.GetLocalSchema() 311 pkDef := schema.GetPrimaryKey() 312 pkVec := h.table.store.rt.VectorPool.Small.GetVector(&pkDef.Type) 313 defer pkVec.Close() 314 for row := start; row <= end; row++ { 315 pkVal, _, err := h.table.GetValue(h.table.store.GetContext(), id, row, uint16(pkDef.Idx)) 316 if err != nil { 317 return err 318 } 319 pkVec.Append(pkVal, false) 320 } 321 return h.Txn.GetStore().RangeDelete(id, start, end, pkVec, dt) 322 } 323 func (h *txnRelation) TryDeleteByDeltaloc(id *common.ID, deltaloc objectio.Location) (ok bool, err error) { 324 return h.Txn.GetStore().TryDeleteByDeltaloc(id, deltaloc) 325 } 326 327 // Only used by test. 328 func (h *txnRelation) GetValueByPhyAddrKey(key any, col int) (any, bool, error) { 329 rid := key.(types.Rowid) 330 bid, row := rid.Decode() 331 id := h.table.entry.AsCommonID() 332 id.BlockID = bid 333 return h.Txn.GetStore().GetValue(id, row, uint16(col)) 334 } 335 336 func (h *txnRelation) GetValue(id *common.ID, row uint32, col uint16) (any, bool, error) { 337 return h.Txn.GetStore().GetValue(id, row, col) 338 } 339 340 func (h *txnRelation) LogTxnEntry(entry txnif.TxnEntry, readed []*common.ID) (err error) { 341 return h.Txn.GetStore().LogTxnEntry(h.table.entry.GetDB().ID, h.table.entry.GetID(), entry, readed) 342 } 343 344 func (h *txnRelation) GetDB() (handle.Database, error) { 345 return h.Txn.GetStore().GetDatabase(h.GetMeta().(*catalog.TableEntry).GetDB().GetName()) 346 } 347 348 func (h *txnRelation) AlterTable(ctx context.Context, req *apipb.AlterTableReq) (err error) { 349 return h.table.AlterTable(ctx, req) 350 }