github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/tables/base.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 tables
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"sync"
    21  	"sync/atomic"
    22  
    23  	"github.com/matrixorigin/matrixone/pkg/fileservice"
    24  	"github.com/matrixorigin/matrixone/pkg/logutil"
    25  
    26  	"github.com/RoaringBitmap/roaring"
    27  	"github.com/matrixorigin/matrixone/pkg/common/bitmap"
    28  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    29  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    30  	"github.com/matrixorigin/matrixone/pkg/container/nulls"
    31  	"github.com/matrixorigin/matrixone/pkg/container/types"
    32  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    33  	"github.com/matrixorigin/matrixone/pkg/objectio"
    34  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/blockio"
    35  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    36  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    37  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    38  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/db/dbutils"
    39  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/data"
    40  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle"
    41  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
    42  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/index"
    43  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables/updates"
    44  )
    45  
    46  type BlockT[T common.IRef] interface {
    47  	common.IRef
    48  	Pin() *common.PinnedItem[T]
    49  	GetID() *common.ID
    50  }
    51  
    52  func DefaultTOmbstoneFactory(meta *catalog.ObjectEntry) data.Tombstone {
    53  	return updates.NewObjectMVCCHandle(meta)
    54  }
    55  
    56  type baseObject struct {
    57  	common.RefHelper
    58  	*sync.RWMutex
    59  	rt         *dbutils.Runtime
    60  	meta       *catalog.ObjectEntry
    61  	appendMVCC *updates.AppendMVCCHandle
    62  	impl       data.Object
    63  
    64  	node atomic.Pointer[Node]
    65  }
    66  
    67  func newBaseObject(
    68  	impl data.Object,
    69  	meta *catalog.ObjectEntry,
    70  	rt *dbutils.Runtime,
    71  ) *baseObject {
    72  	blk := &baseObject{
    73  		impl:       impl,
    74  		rt:         rt,
    75  		meta:       meta,
    76  		appendMVCC: updates.NewAppendMVCCHandle(meta),
    77  	}
    78  	blk.appendMVCC.SetAppendListener(blk.OnApplyAppend)
    79  	blk.RWMutex = meta.RWMutex
    80  	return blk
    81  }
    82  
    83  func (blk *baseObject) OnApplyAppend(n txnif.AppendNode) (err error) {
    84  	blk.meta.GetTable().AddRows(
    85  		uint64(n.GetMaxRow() - n.GetStartRow()),
    86  	)
    87  	return
    88  }
    89  func (blk *baseObject) Close() {
    90  	// TODO
    91  }
    92  
    93  func (blk *baseObject) GetRuntime() *dbutils.Runtime {
    94  	return blk.rt
    95  }
    96  
    97  func (blk *baseObject) PinNode() *Node {
    98  	n := blk.node.Load()
    99  	// if ref fails, reload.
   100  	// Note: avoid bad case where releasing happens before Ref()
   101  	for ; !n.RefIfHasRef(); n = blk.node.Load() {
   102  	}
   103  	return n
   104  }
   105  func (blk *baseObject) tryGetMVCC() *updates.ObjectMVCCHandle {
   106  	tombstone := blk.meta.GetTable().TryGetTombstone(blk.meta.ID)
   107  	if tombstone == nil {
   108  		return nil
   109  	}
   110  	return tombstone.(*updates.ObjectMVCCHandle)
   111  }
   112  func (blk *baseObject) getOrCreateMVCC() *updates.ObjectMVCCHandle {
   113  	return blk.meta.GetTable().GetOrCreateTombstone(blk.meta, DefaultTOmbstoneFactory).(*updates.ObjectMVCCHandle)
   114  }
   115  
   116  func (blk *baseObject) GCInMemeoryDeletesByTSForTest(ts types.TS) {
   117  	blk.Lock()
   118  	defer blk.Unlock()
   119  	mvcc := blk.tryGetMVCC()
   120  	if mvcc == nil {
   121  		return
   122  	}
   123  	mvcc.UpgradeDeleteChainByTSLocked(ts)
   124  }
   125  
   126  func (blk *baseObject) UpgradeAllDeleteChain() {
   127  	blk.Lock()
   128  	defer blk.Unlock()
   129  	mvcc := blk.tryGetMVCC()
   130  	if mvcc == nil {
   131  		return
   132  	}
   133  	mvcc.UpgradeAllDeleteChain()
   134  }
   135  
   136  func (blk *baseObject) Rows() (int, error) {
   137  	node := blk.PinNode()
   138  	defer node.Unref()
   139  	if !node.IsPersisted() {
   140  		blk.RLock()
   141  		defer blk.RUnlock()
   142  		rows, err := node.Rows()
   143  		return int(rows), err
   144  	} else {
   145  		rows, err := node.Rows()
   146  		return int(rows), err
   147  	}
   148  }
   149  func (blk *baseObject) Foreach(
   150  	ctx context.Context,
   151  	readSchema any,
   152  	blkID uint16,
   153  	colIdx int,
   154  	op func(v any, isNull bool, row int) error,
   155  	sels []uint32,
   156  	mp *mpool.MPool,
   157  ) error {
   158  	node := blk.PinNode()
   159  	defer node.Unref()
   160  	schema := readSchema.(*catalog.Schema)
   161  	if !node.IsPersisted() {
   162  		blk.RLock()
   163  		defer blk.RUnlock()
   164  		return node.MustMNode().Foreach(schema, blkID, colIdx, op, sels, mp)
   165  	} else {
   166  		return node.MustPNode().Foreach(ctx, schema, blkID, colIdx, op, sels, mp)
   167  	}
   168  }
   169  
   170  func (blk *baseObject) TryUpgrade() (err error) {
   171  	node := blk.node.Load()
   172  	if node.IsPersisted() {
   173  		return
   174  	}
   175  	pnode := newPersistedNode(blk)
   176  	nnode := NewNode(pnode)
   177  	nnode.Ref()
   178  
   179  	if !blk.node.CompareAndSwap(node, nnode) {
   180  		nnode.Unref()
   181  	} else {
   182  		node.Unref()
   183  	}
   184  	return
   185  }
   186  
   187  func (blk *baseObject) GetMeta() any { return blk.meta }
   188  func (blk *baseObject) CheckFlushTaskRetry(startts types.TS) bool {
   189  	if !blk.meta.IsAppendable() {
   190  		panic("not support")
   191  	}
   192  	if blk.meta.HasDropCommitted() {
   193  		panic("not support")
   194  	}
   195  	blk.RLock()
   196  	defer blk.RUnlock()
   197  	x := blk.appendMVCC.GetLatestAppendPrepareTSLocked()
   198  	return x.Greater(&startts)
   199  }
   200  func (blk *baseObject) GetFs() *objectio.ObjectFS { return blk.rt.Fs }
   201  func (blk *baseObject) GetID() *common.ID         { return blk.meta.AsCommonID() }
   202  
   203  func (blk *baseObject) fillInMemoryDeletesLocked(
   204  	txn txnif.TxnReader,
   205  	blkID uint16,
   206  	view *containers.BaseView,
   207  	rwlocker *sync.RWMutex,
   208  ) (err error) {
   209  	mvcc := blk.tryGetMVCC()
   210  	if mvcc == nil {
   211  		return
   212  	}
   213  	deleteHandle := mvcc.TryGetDeleteChain(blkID)
   214  	if deleteHandle == nil {
   215  		return
   216  	}
   217  	chain := deleteHandle.GetDeleteChain()
   218  	deletes, err := chain.CollectDeletesLocked(txn, rwlocker)
   219  	if err != nil || deletes.IsEmpty() {
   220  		return
   221  	}
   222  	if view.DeleteMask == nil {
   223  		view.DeleteMask = deletes
   224  	} else {
   225  		view.DeleteMask.Or(deletes)
   226  	}
   227  	return
   228  }
   229  
   230  func (blk *baseObject) buildMetalocation(bid uint16) (objectio.Location, error) {
   231  	if !blk.meta.ObjectPersisted() {
   232  		return nil, nil
   233  	}
   234  	stats, err := blk.meta.MustGetObjectStats()
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  	blkMaxRows := blk.meta.GetSchema().BlockMaxRows
   239  	blkRow := blkMaxRows
   240  	if bid == uint16(blk.meta.BlockCnt())-1 {
   241  		blkRow = stats.Rows() - uint32(bid)*blkMaxRows
   242  	}
   243  	metaloc := objectio.BuildLocation(stats.ObjectName(), stats.Extent(), blkRow, bid)
   244  	return metaloc, nil
   245  }
   246  
   247  func (blk *baseObject) LoadPersistedCommitTS(bid uint16) (vec containers.Vector, err error) {
   248  	if !blk.meta.IsAppendable() {
   249  		return
   250  	}
   251  	location, err := blk.buildMetalocation(bid)
   252  	if err != nil {
   253  		return
   254  	}
   255  	if location.IsEmpty() {
   256  		return
   257  	}
   258  	//Extend lifetime of vectors is without the function.
   259  	//need to copy. closeFunc will be nil.
   260  	vectors, _, err := blockio.LoadColumns2(
   261  		context.Background(),
   262  		[]uint16{objectio.SEQNUM_COMMITTS},
   263  		nil,
   264  		blk.rt.Fs.Service,
   265  		location,
   266  		fileservice.Policy(0),
   267  		true,
   268  		blk.rt.VectorPool.Transient,
   269  	)
   270  	if err != nil {
   271  		return
   272  	}
   273  	if vectors[0].GetType().Oid != types.T_TS {
   274  		panic(fmt.Sprintf("%s: bad commits layout", blk.meta.ID.String()))
   275  	}
   276  	vec = vectors[0]
   277  	return
   278  }
   279  
   280  func (blk *baseObject) LoadPersistedColumnData(
   281  	ctx context.Context, schema *catalog.Schema, colIdx int, mp *mpool.MPool, blkID uint16,
   282  ) (vec containers.Vector, err error) {
   283  	def := schema.ColDefs[colIdx]
   284  	location, err := blk.buildMetalocation(blkID)
   285  	if err != nil {
   286  		return nil, err
   287  	}
   288  	id := blk.meta.AsCommonID()
   289  	id.SetBlockOffset(blkID)
   290  	return LoadPersistedColumnData(
   291  		ctx,
   292  		blk.rt,
   293  		id,
   294  		def,
   295  		location,
   296  		mp,
   297  	)
   298  }
   299  
   300  func (blk *baseObject) loadLatestPersistedDeletes(
   301  	ctx context.Context,
   302  	blkID uint16,
   303  	txn txnif.TxnReader,
   304  	mp *mpool.MPool,
   305  ) (bat *containers.Batch, persistedByCN bool, deltalocCommitTS types.TS, visible bool, release func(), err error) {
   306  	blk.RLock()
   307  	mvcc := blk.tryGetMVCC()
   308  	if mvcc == nil {
   309  		blk.RUnlock()
   310  		return
   311  	}
   312  	node := mvcc.GetLatestMVCCNode(blkID)
   313  	if node == nil {
   314  		blk.RUnlock()
   315  		return
   316  	}
   317  	location := node.BaseNode.DeltaLoc
   318  	if location.IsEmpty() {
   319  		blk.RUnlock()
   320  		return
   321  	}
   322  	deltalocCommitTS = node.End
   323  	visible = node.IsVisible(txn)
   324  	blk.RUnlock()
   325  	pkName := blk.meta.GetSchema().GetPrimaryKey().Name
   326  	bat, persistedByCN, release, err = LoadPersistedDeletes(
   327  		ctx,
   328  		pkName,
   329  		blk.rt.Fs,
   330  		location,
   331  		mp,
   332  	)
   333  	return
   334  }
   335  func (blk *baseObject) FillPersistedDeletes(
   336  	ctx context.Context,
   337  	blkID uint16,
   338  	txn txnif.TxnReader,
   339  	view *containers.BaseView,
   340  	mp *mpool.MPool,
   341  ) (err error) {
   342  	return blk.foreachPersistedDeletesVisibleByTxn(
   343  		ctx,
   344  		txn,
   345  		blkID,
   346  		true,
   347  		func(i int, rowIdVec *vector.Vector) {
   348  			rowid := vector.GetFixedAt[types.Rowid](rowIdVec, i)
   349  			row := rowid.GetRowOffset()
   350  			if view.DeleteMask == nil {
   351  				view.DeleteMask = nulls.NewWithSize(int(row) + 1)
   352  			}
   353  			view.DeleteMask.Add(uint64(row))
   354  		},
   355  		nil,
   356  		mp,
   357  	)
   358  }
   359  
   360  func (blk *baseObject) fillPersistedDeletesInRange(
   361  	ctx context.Context,
   362  	blkID uint16,
   363  	start, end types.TS,
   364  	view *containers.BaseView,
   365  	mp *mpool.MPool,
   366  ) (err error) {
   367  	err = blk.foreachPersistedDeletesCommittedInRange(
   368  		ctx,
   369  		start,
   370  		end,
   371  		blkID,
   372  		true,
   373  		func(i int, rowIdVec *vector.Vector) {
   374  			rowid := vector.GetFixedAt[types.Rowid](rowIdVec, i)
   375  			row := rowid.GetRowOffset()
   376  			if view.DeleteMask == nil {
   377  				view.DeleteMask = nulls.NewWithSize(int(row) + 1)
   378  			}
   379  			view.DeleteMask.Add(uint64(row))
   380  		},
   381  		nil,
   382  		mp,
   383  	)
   384  	return err
   385  }
   386  
   387  func (blk *baseObject) persistedCollectDeleteMaskInRange(
   388  	ctx context.Context,
   389  	blkID uint16,
   390  	start, end types.TS,
   391  	mp *mpool.MPool,
   392  ) (deletes *nulls.Nulls, err error) {
   393  	err = blk.foreachPersistedDeletesCommittedInRange(
   394  		ctx,
   395  		start,
   396  		end,
   397  		blkID,
   398  		true,
   399  		func(i int, rowIdVec *vector.Vector) {
   400  			rowid := vector.GetFixedAt[types.Rowid](rowIdVec, i)
   401  			row := rowid.GetRowOffset()
   402  			if deletes == nil {
   403  				deletes = nulls.NewWithSize(int(row) + 1)
   404  			}
   405  			deletes.Add(uint64(row))
   406  		},
   407  		nil,
   408  		mp,
   409  	)
   410  	return
   411  }
   412  
   413  // for each deletes in [start,end]
   414  func (blk *baseObject) foreachPersistedDeletesCommittedInRange(
   415  	ctx context.Context,
   416  	start, end types.TS,
   417  	blkID uint16,
   418  	skipAbort bool,
   419  	loopOp func(int, *vector.Vector),
   420  	postOp func(*containers.Batch),
   421  	mp *mpool.MPool,
   422  ) (err error) {
   423  	loadFn := func() (bat *containers.Batch, persistedByCN bool, commitTS types.TS, visible bool, release func(), err error) {
   424  		mvcc := blk.tryGetMVCC()
   425  		if mvcc == nil {
   426  			return
   427  		}
   428  		// commitTS of deltalocation is the commitTS of deletes persisted by CN batches
   429  		location, deltalocCommitTS, deltalocStartTS := mvcc.GetDeltaLocAndCommitTS(blkID)
   430  		if location.IsEmpty() {
   431  			return
   432  		}
   433  
   434  		// quick check for early return.
   435  		persistedByCN, err = blockio.IsPersistedByCN(ctx, location, blk.rt.Fs.Service)
   436  		if err != nil {
   437  			return
   438  		}
   439  		if persistedByCN {
   440  			if deltalocCommitTS.Equal(&txnif.UncommitTS) {
   441  				return
   442  			}
   443  			if deltalocCommitTS.Less(&start) || deltalocCommitTS.Greater(&end) {
   444  				return
   445  			}
   446  		} else if deltalocStartTS.Less(&start) {
   447  			return
   448  		}
   449  
   450  		// IO
   451  		visible = true
   452  		pkName := blk.meta.GetSchema().GetPrimaryKey().Name
   453  		bat, release, err = LoadPersistedDeletesBySchema(
   454  			ctx,
   455  			pkName,
   456  			blk.rt.Fs,
   457  			location,
   458  			persistedByCN,
   459  			mp,
   460  		)
   461  		return
   462  	}
   463  	return blk.foreachPersistedDeletes(ctx, start, end, blkID, skipAbort, loadFn, loopOp, postOp, mp)
   464  }
   465  
   466  // for each deletes in [start,end]
   467  func (blk *baseObject) foreachPersistedDeletesVisibleByTxn(
   468  	ctx context.Context,
   469  	txn txnif.TxnReader,
   470  	blkID uint16,
   471  	skipAbort bool,
   472  	loopOp func(int, *vector.Vector),
   473  	postOp func(*containers.Batch),
   474  	mp *mpool.MPool,
   475  ) (err error) {
   476  	loadFn := func() (deletes *containers.Batch, persistedByCN bool, commitTS types.TS, visible bool, release func(), err error) {
   477  		// commitTS of deltalocation is the commitTS of deletes persisted by CN batches
   478  		return blk.loadLatestPersistedDeletes(ctx, blkID, txn, mp)
   479  	}
   480  	return blk.foreachPersistedDeletes(ctx, types.TS{}, txn.GetStartTS(), blkID, skipAbort, loadFn, loopOp, postOp, mp)
   481  }
   482  func (blk *baseObject) foreachPersistedDeletes(
   483  	ctx context.Context,
   484  	start, end types.TS,
   485  	blkID uint16,
   486  	skipAbort bool,
   487  	loadFn func() (bat *containers.Batch, persistedByCN bool, commitTS types.TS, visible bool, release func(), err error),
   488  	loopOp func(int, *vector.Vector),
   489  	postOp func(*containers.Batch),
   490  	mp *mpool.MPool,
   491  ) (err error) {
   492  	// commitTS of deltalocation is the commitTS of deletes persisted by CN batches
   493  	deletes, persistedByCN, deltalocCommitTS, visible, release, err := loadFn()
   494  	if deletes == nil || err != nil {
   495  		return
   496  	}
   497  	defer release()
   498  	defer deletes.Close()
   499  	if persistedByCN {
   500  		if !visible {
   501  			return
   502  		}
   503  		rowIdVec := deletes.Vecs[0].GetDownstreamVector()
   504  		for i := 0; i < deletes.Length(); i++ {
   505  			loopOp(i, rowIdVec)
   506  		}
   507  		commitTSVec := containers.NewConstFixed[types.TS](types.T_TS.ToType(), deltalocCommitTS, deletes.Length())
   508  		abortVec := containers.NewConstFixed[bool](types.T_bool.ToType(), false, deletes.Length())
   509  		deletes.AddVector(catalog.AttrCommitTs, commitTSVec)
   510  		deletes.AddVector(catalog.AttrAborted, abortVec)
   511  	} else {
   512  		abortVec := deletes.Vecs[3].GetDownstreamVector()
   513  		commitTsVec := deletes.Vecs[1].GetDownstreamVector()
   514  		rowIdVec := deletes.Vecs[0].GetDownstreamVector()
   515  
   516  		rstart, rend := blockio.FindIntervalForBlock(vector.MustFixedCol[types.Rowid](rowIdVec), objectio.NewBlockidWithObjectID(&blk.meta.ID, blkID))
   517  		for i := rstart; i < rend; i++ {
   518  			if skipAbort {
   519  				abort := vector.GetFixedAt[bool](abortVec, i)
   520  				if abort {
   521  					continue
   522  				}
   523  			}
   524  			commitTS := vector.GetFixedAt[types.TS](commitTsVec, i)
   525  			if commitTS.GreaterEq(&start) && commitTS.LessEq(&end) {
   526  				loopOp(i, rowIdVec)
   527  			}
   528  		}
   529  	}
   530  	if postOp != nil {
   531  		postOp(deletes)
   532  	}
   533  	return
   534  }
   535  func (blk *baseObject) Prefetch(idxes []uint16, blkID uint16) error {
   536  	node := blk.PinNode()
   537  	defer node.Unref()
   538  	if !node.IsPersisted() {
   539  		return nil
   540  	} else {
   541  		key, err := blk.buildMetalocation(blkID)
   542  		if err != nil {
   543  			return err
   544  		}
   545  		return blockio.Prefetch(idxes, []uint16{key.ID()}, blk.rt.Fs.Service, key)
   546  	}
   547  }
   548  
   549  func (blk *baseObject) ResolvePersistedColumnDatas(
   550  	ctx context.Context,
   551  	txn txnif.TxnReader,
   552  	readSchema *catalog.Schema,
   553  	blkID uint16,
   554  	colIdxs []int,
   555  	skipDeletes bool,
   556  	mp *mpool.MPool,
   557  ) (view *containers.BlockView, err error) {
   558  
   559  	view = containers.NewBlockView()
   560  	location, err := blk.buildMetalocation(blkID)
   561  	if err != nil {
   562  		return nil, err
   563  	}
   564  	id := blk.meta.AsCommonID()
   565  	id.SetBlockOffset(blkID)
   566  	vecs, err := LoadPersistedColumnDatas(
   567  		ctx, readSchema, blk.rt, id, colIdxs, location, mp,
   568  	)
   569  	if err != nil {
   570  		return nil, err
   571  	}
   572  	for i, vec := range vecs {
   573  		view.SetData(colIdxs[i], vec)
   574  	}
   575  
   576  	if skipDeletes {
   577  		return
   578  	}
   579  
   580  	defer func() {
   581  		if err != nil {
   582  			view.Close()
   583  		}
   584  	}()
   585  
   586  	blk.RLock()
   587  	err = blk.fillInMemoryDeletesLocked(txn, blkID, view.BaseView, blk.RWMutex)
   588  	blk.RUnlock()
   589  
   590  	if err = blk.FillPersistedDeletes(ctx, blkID, txn, view.BaseView, mp); err != nil {
   591  		return
   592  	}
   593  	return
   594  }
   595  
   596  func (blk *baseObject) ResolvePersistedColumnData(
   597  	ctx context.Context,
   598  	txn txnif.TxnReader,
   599  	readSchema *catalog.Schema,
   600  	blkID uint16,
   601  	colIdx int,
   602  	skipDeletes bool,
   603  	mp *mpool.MPool,
   604  ) (view *containers.ColumnView, err error) {
   605  	view = containers.NewColumnView(colIdx)
   606  	vec, err := blk.LoadPersistedColumnData(context.Background(), readSchema, colIdx, mp, blkID)
   607  	if err != nil {
   608  		return
   609  	}
   610  	view.SetData(vec)
   611  
   612  	if skipDeletes {
   613  		return
   614  	}
   615  
   616  	defer func() {
   617  		if err != nil {
   618  			view.Close()
   619  		}
   620  	}()
   621  
   622  	if err = blk.FillPersistedDeletes(ctx, blkID, txn, view.BaseView, mp); err != nil {
   623  		return
   624  	}
   625  
   626  	blk.RLock()
   627  	err = blk.fillInMemoryDeletesLocked(txn, blkID, view.BaseView, blk.RWMutex)
   628  	blk.RUnlock()
   629  	return
   630  }
   631  
   632  func (blk *baseObject) dedupWithLoad(
   633  	ctx context.Context,
   634  	txn txnif.TxnReader,
   635  	keys containers.Vector,
   636  	sels *nulls.Bitmap,
   637  	rowmask *roaring.Bitmap,
   638  	blkOffset uint16,
   639  	isAblk bool,
   640  	mp *mpool.MPool,
   641  ) (err error) {
   642  	schema := blk.meta.GetSchema()
   643  	def := schema.GetSingleSortKey()
   644  	view, err := blk.ResolvePersistedColumnData(
   645  		ctx,
   646  		txn,
   647  		schema,
   648  		blkOffset,
   649  		def.Idx,
   650  		false,
   651  		mp,
   652  	)
   653  	if err != nil {
   654  		return err
   655  	}
   656  	if rowmask != nil {
   657  		if view.DeleteMask == nil {
   658  			view.DeleteMask = common.RoaringToMOBitmap(rowmask)
   659  		} else {
   660  			common.MOOrRoaringBitmap(view.DeleteMask, rowmask)
   661  		}
   662  	}
   663  	defer view.Close()
   664  	var dedupFn any
   665  	if isAblk {
   666  		dedupFn = containers.MakeForeachVectorOp(
   667  			keys.GetType().Oid, dedupAlkFunctions, view.GetData(), view.DeleteMask, def, blk.LoadPersistedCommitTS, txn,
   668  		)
   669  	} else {
   670  		dedupFn = containers.MakeForeachVectorOp(
   671  			keys.GetType().Oid, dedupNABlkFunctions, view.GetData(), view.DeleteMask, def,
   672  		)
   673  	}
   674  	err = containers.ForeachVector(keys, dedupFn, sels)
   675  	return
   676  }
   677  
   678  func (blk *baseObject) PersistedBatchDedup(
   679  	ctx context.Context,
   680  	txn txnif.TxnReader,
   681  	isCommitting bool,
   682  	keys containers.Vector,
   683  	keysZM index.ZM,
   684  	rowmask *roaring.Bitmap,
   685  	isAblk bool,
   686  	bf objectio.BloomFilter,
   687  	mp *mpool.MPool,
   688  ) (err error) {
   689  	pkIndex, err := MakeImmuIndex(
   690  		ctx,
   691  		blk.meta,
   692  		bf,
   693  		blk.rt,
   694  	)
   695  	if err != nil {
   696  		return
   697  	}
   698  	for i := 0; i < blk.meta.BlockCnt(); i++ {
   699  		sels, err := pkIndex.BatchDedup(
   700  			ctx,
   701  			keys,
   702  			keysZM,
   703  			blk.rt,
   704  			uint32(i),
   705  		)
   706  		if err == nil || !moerr.IsMoErrCode(err, moerr.OkExpectedPossibleDup) {
   707  			continue
   708  		}
   709  		err = blk.dedupWithLoad(ctx, txn, keys, sels, rowmask, uint16(i), isAblk, mp)
   710  		if err != nil {
   711  			return err
   712  		}
   713  	}
   714  	return nil
   715  }
   716  
   717  func (blk *baseObject) getPersistedValue(
   718  	ctx context.Context,
   719  	txn txnif.TxnReader,
   720  	schema *catalog.Schema,
   721  	blkID uint16,
   722  	row, col int,
   723  	skipMemory bool,
   724  	mp *mpool.MPool,
   725  ) (v any, isNull bool, err error) {
   726  	view := containers.NewColumnView(col)
   727  	if err = blk.FillPersistedDeletes(ctx, blkID, txn, view.BaseView, mp); err != nil {
   728  		return
   729  	}
   730  	if !skipMemory {
   731  		blk.RLock()
   732  		err = blk.fillInMemoryDeletesLocked(txn, blkID, view.BaseView, blk.RWMutex)
   733  		blk.RUnlock()
   734  		if err != nil {
   735  			return
   736  		}
   737  	}
   738  	if view.DeleteMask.Contains(uint64(row)) {
   739  		err = moerr.NewNotFoundNoCtx()
   740  		return
   741  	}
   742  	view2, err := blk.ResolvePersistedColumnData(ctx, txn, schema, blkID, col, true, mp)
   743  	if err != nil {
   744  		return
   745  	}
   746  	defer view2.Close()
   747  	v, isNull = view2.GetValue(row)
   748  	return
   749  }
   750  
   751  func (blk *baseObject) DeletesInfo() string {
   752  	blk.RLock()
   753  	defer blk.RUnlock()
   754  	mvcc := blk.tryGetMVCC()
   755  	if mvcc == nil {
   756  		return ""
   757  	}
   758  	return mvcc.StringLocked(1, 0, "")
   759  }
   760  
   761  func (blk *baseObject) RangeDelete(
   762  	txn txnif.AsyncTxn,
   763  	blkID uint16,
   764  	start, end uint32,
   765  	pk containers.Vector,
   766  	dt handle.DeleteType) (node txnif.DeleteNode, err error) {
   767  	blk.Lock()
   768  	defer blk.Unlock()
   769  	blkMVCC := blk.getOrCreateMVCC().GetOrCreateDeleteChainLocked(blkID)
   770  	if err = blkMVCC.CheckNotDeleted(start, end, txn.GetStartTS()); err != nil {
   771  		return
   772  	}
   773  	node = blkMVCC.CreateDeleteNode(txn, dt)
   774  	node.RangeDeleteLocked(start, end, pk, common.MutMemAllocator)
   775  	return
   776  }
   777  
   778  func (blk *baseObject) TryDeleteByDeltaloc(
   779  	txn txnif.AsyncTxn,
   780  	blkID uint16,
   781  	deltaLoc objectio.Location) (node txnif.TxnEntry, ok bool, err error) {
   782  	if blk.meta.IsAppendable() {
   783  		return
   784  	}
   785  	blk.Lock()
   786  	defer blk.Unlock()
   787  	blkMVCC := blk.getOrCreateMVCC().GetOrCreateDeleteChainLocked(blkID)
   788  	return blkMVCC.TryDeleteByDeltalocLocked(txn, deltaLoc, true)
   789  }
   790  
   791  func (blk *baseObject) PPString(level common.PPLevel, depth int, prefix string, blkid int) string {
   792  	rows, err := blk.Rows()
   793  	if err != nil {
   794  		logutil.Warnf("get object rows failed, obj: %v, err: %v", blk.meta.ID.String(), err)
   795  	}
   796  	s := fmt.Sprintf("%s | [Rows=%d]", blk.meta.PPString(level, depth, prefix), rows)
   797  	if level >= common.PPL1 {
   798  		blk.RLock()
   799  		var appendstr, deletestr string
   800  		if blk.appendMVCC != nil {
   801  			appendstr = blk.appendMVCC.StringLocked()
   802  		}
   803  		if mvcc := blk.tryGetMVCC(); mvcc != nil {
   804  			if blkid >= 0 {
   805  				deletestr = mvcc.StringBlkLocked(level, 0, "", blkid)
   806  			} else {
   807  				deletestr = mvcc.StringLocked(level, 0, "")
   808  			}
   809  		}
   810  		blk.RUnlock()
   811  		if appendstr != "" {
   812  			s = fmt.Sprintf("%s\n Appends: %s", s, appendstr)
   813  		}
   814  		if deletestr != "" {
   815  			s = fmt.Sprintf("%s\n Deletes: %s", s, deletestr)
   816  		}
   817  	}
   818  	return s
   819  }
   820  
   821  func (blk *baseObject) HasDeleteIntentsPreparedIn(from, to types.TS) (found, isPersist bool) {
   822  	blk.RLock()
   823  	defer blk.RUnlock()
   824  	mvcc := blk.tryGetMVCC()
   825  	if mvcc == nil {
   826  		return
   827  	}
   828  	return mvcc.HasDeleteIntentsPreparedIn(from, to)
   829  }
   830  func (blk *baseObject) HasDeleteIntentsPreparedInByBlock(blkID uint16, from, to types.TS) (found, isPersist bool) {
   831  	blk.RLock()
   832  	defer blk.RUnlock()
   833  	mvcc := blk.tryGetMVCC()
   834  	if mvcc == nil {
   835  		return
   836  	}
   837  	return mvcc.HasInMemoryDeleteIntentsPreparedInByBlock(blkID, from, to)
   838  }
   839  func (blk *baseObject) CollectChangesInRange(
   840  	ctx context.Context,
   841  	blkID uint16,
   842  	startTs, endTs types.TS,
   843  	mp *mpool.MPool,
   844  ) (view *containers.BlockView, err error) {
   845  	view = containers.NewBlockView()
   846  	view.DeleteMask, err = blk.inMemoryCollectDeletesInRange(blkID, startTs, endTs)
   847  	blk.fillPersistedDeletesInRange(ctx, blkID, startTs, endTs, view.BaseView, mp)
   848  	return
   849  }
   850  
   851  func (blk *baseObject) inMemoryCollectDeletesInRange(blkID uint16, start, end types.TS) (deletes *nulls.Bitmap, err error) {
   852  	blk.RLock()
   853  	defer blk.RUnlock()
   854  	mvcc := blk.tryGetMVCC()
   855  	if mvcc == nil {
   856  		return
   857  	}
   858  	blkMvcc := mvcc.TryGetDeleteChain(blkID)
   859  	if blkMvcc == nil {
   860  		return
   861  	}
   862  	deleteChain := blkMvcc.GetDeleteChain()
   863  	deletes, err =
   864  		deleteChain.CollectDeletesInRangeWithLock(start, end, blk.RWMutex)
   865  	return
   866  }
   867  
   868  func (blk *baseObject) CollectDeleteInRange(
   869  	ctx context.Context,
   870  	start, end types.TS,
   871  	withAborted bool,
   872  	mp *mpool.MPool,
   873  ) (bat *containers.Batch, emtpyDelBlkIdx *bitmap.Bitmap, err error) {
   874  	emtpyDelBlkIdx = &bitmap.Bitmap{}
   875  	emtpyDelBlkIdx.InitWithSize(int64(blk.meta.BlockCnt()))
   876  	for blkID := uint16(0); blkID < uint16(blk.meta.BlockCnt()); blkID++ {
   877  		deletes, err := blk.CollectDeleteInRangeByBlock(ctx, blkID, start, end, withAborted, mp)
   878  		if err != nil {
   879  			return nil, nil, err
   880  		}
   881  		if deletes == nil || deletes.Length() == 0 {
   882  			emtpyDelBlkIdx.Add(uint64(blkID))
   883  		} else {
   884  			if bat == nil {
   885  				bat = containers.NewBatch()
   886  				bat.AddVector(catalog.AttrRowID, containers.MakeVector(types.T_Rowid.ToType(), mp))
   887  				bat.AddVector(catalog.AttrCommitTs, containers.MakeVector(types.T_TS.ToType(), mp))
   888  				bat.AddVector(catalog.AttrPKVal, containers.MakeVector(*deletes.GetVectorByName(catalog.AttrPKVal).GetType(), mp))
   889  				if withAborted {
   890  					bat.AddVector(catalog.AttrAborted, containers.MakeVector(types.T_bool.ToType(), mp))
   891  				}
   892  			}
   893  			bat.Extend(deletes)
   894  			deletes.Close()
   895  		}
   896  	}
   897  	return
   898  }
   899  
   900  func (blk *baseObject) CollectDeleteInRangeByBlock(
   901  	ctx context.Context,
   902  	blkID uint16,
   903  	start, end types.TS,
   904  	withAborted bool,
   905  	mp *mpool.MPool) (*containers.Batch, error) {
   906  	deletes, minTS, _, err := blk.inMemoryCollectDeleteInRange(
   907  		ctx,
   908  		blkID,
   909  		start,
   910  		end,
   911  		withAborted,
   912  		mp,
   913  	)
   914  	if err != nil {
   915  		if deletes != nil {
   916  			deletes.Close()
   917  		}
   918  		return nil, err
   919  	}
   920  	currentEnd := end
   921  	if !minTS.IsEmpty() && currentEnd.Greater(&minTS) {
   922  		currentEnd = minTS.Prev()
   923  	}
   924  	deletes, err = blk.PersistedCollectDeleteInRange(
   925  		ctx,
   926  		deletes,
   927  		blkID,
   928  		start,
   929  		currentEnd,
   930  		withAborted,
   931  		mp,
   932  	)
   933  	if err != nil {
   934  		if deletes != nil {
   935  			deletes.Close()
   936  		}
   937  		return nil, err
   938  	}
   939  	return deletes, nil
   940  }
   941  
   942  func (blk *baseObject) inMemoryCollectDeleteInRange(
   943  	ctx context.Context,
   944  	blkID uint16,
   945  	start, end types.TS,
   946  	withAborted bool,
   947  	mp *mpool.MPool,
   948  ) (bat *containers.Batch, minTS, persistedTS types.TS, err error) {
   949  	blk.RLock()
   950  	objMVCC := blk.tryGetMVCC()
   951  	if objMVCC == nil {
   952  		blk.RUnlock()
   953  		return
   954  	}
   955  	mvcc := objMVCC.TryGetDeleteChain(blkID)
   956  	blk.RUnlock()
   957  	if mvcc == nil {
   958  		return
   959  	}
   960  	return mvcc.InMemoryCollectDeleteInRange(ctx, start, end, withAborted, mp)
   961  }
   962  
   963  // collect the row if its committs is in [start,end]
   964  func (blk *baseObject) PersistedCollectDeleteInRange(
   965  	ctx context.Context,
   966  	b *containers.Batch,
   967  	blkID uint16,
   968  	start, end types.TS,
   969  	withAborted bool,
   970  	mp *mpool.MPool,
   971  ) (bat *containers.Batch, err error) {
   972  	if b != nil {
   973  		bat = b
   974  	}
   975  	t := types.T_int32.ToType()
   976  	sels := blk.rt.VectorPool.Transient.GetVector(&t)
   977  	defer sels.Close()
   978  	selsVec := sels.GetDownstreamVector()
   979  	blk.foreachPersistedDeletesCommittedInRange(
   980  		ctx,
   981  		start, end,
   982  		blkID,
   983  		!withAborted,
   984  		func(row int, rowIdVec *vector.Vector) {
   985  			_ = vector.AppendFixed[int32](selsVec, int32(row), false, mp)
   986  		},
   987  		func(delBat *containers.Batch) {
   988  			if sels.Length() == 0 {
   989  				return
   990  			}
   991  			if bat == nil {
   992  				bat = containers.NewBatchWithCapacity(len(delBat.Attrs))
   993  				for i, name := range delBat.Attrs {
   994  					if !withAborted && name == catalog.AttrAborted {
   995  						continue
   996  					}
   997  					bat.AddVector(
   998  						name,
   999  						blk.rt.VectorPool.Transient.GetVector(delBat.Vecs[i].GetType()),
  1000  					)
  1001  				}
  1002  			}
  1003  			for _, name := range bat.Attrs {
  1004  				retVec := bat.GetVectorByName(name)
  1005  				srcVec := delBat.GetVectorByName(name)
  1006  				retVec.PreExtend(sels.Length())
  1007  				retVec.GetDownstreamVector().Union(
  1008  					srcVec.GetDownstreamVector(),
  1009  					vector.MustFixedCol[int32](sels.GetDownstreamVector()),
  1010  					retVec.GetAllocator(),
  1011  				)
  1012  			}
  1013  		},
  1014  		mp,
  1015  	)
  1016  	return bat, nil
  1017  }
  1018  
  1019  func (blk *baseObject) OnReplayDelete(blkID uint16, node txnif.DeleteNode) (err error) {
  1020  	blk.getOrCreateMVCC().GetOrCreateDeleteChainLocked(blkID).OnReplayDeleteNode(node)
  1021  	err = node.OnApply()
  1022  	return
  1023  }
  1024  
  1025  func (blk *baseObject) OnReplayAppend(_ txnif.AppendNode) (err error) {
  1026  	panic("not supported")
  1027  }
  1028  
  1029  func (blk *baseObject) OnReplayAppendPayload(_ *containers.Batch) (err error) {
  1030  	panic("not supported")
  1031  }
  1032  
  1033  func (blk *baseObject) MakeAppender() (appender data.ObjectAppender, err error) {
  1034  	panic("not supported")
  1035  }
  1036  
  1037  func (blk *baseObject) GetTotalChanges() int {
  1038  	blk.RLock()
  1039  	defer blk.RUnlock()
  1040  	objMVCC := blk.tryGetMVCC()
  1041  	if objMVCC == nil {
  1042  		return 0
  1043  	}
  1044  	return int(objMVCC.GetDeleteCnt())
  1045  }
  1046  
  1047  func (blk *baseObject) IsAppendable() bool { return false }
  1048  
  1049  func (blk *baseObject) MutationInfo() string {
  1050  	rows, err := blk.Rows()
  1051  	blk.RLock()
  1052  	defer blk.RUnlock()
  1053  	if err != nil {
  1054  		logutil.Warnf("get object rows failed, obj: %v, err %v", blk.meta.ID.String(), err)
  1055  	}
  1056  	objMVCC := blk.tryGetMVCC()
  1057  	var deleteCnt uint32
  1058  	if objMVCC != nil {
  1059  		deleteCnt = objMVCC.GetDeleteCnt()
  1060  	}
  1061  	s := fmt.Sprintf("Block %s Mutation Info: Changes=%d/%d",
  1062  		blk.meta.AsCommonID().BlockString(),
  1063  		deleteCnt,
  1064  		rows)
  1065  	return s
  1066  }
  1067  
  1068  func (blk *baseObject) CollectAppendInRange(
  1069  	start, end types.TS, withAborted bool, mp *mpool.MPool,
  1070  ) (*containers.BatchWithVersion, error) {
  1071  	return nil, nil
  1072  }
  1073  
  1074  func (blk *baseObject) UpdateDeltaLoc(txn txnif.TxnReader, blkID uint16, deltaLoc objectio.Location) (bool, txnif.TxnEntry, error) {
  1075  	blk.Lock()
  1076  	defer blk.Unlock()
  1077  	mvcc := blk.getOrCreateMVCC().GetOrCreateDeleteChainLocked(blkID)
  1078  	return mvcc.UpdateDeltaLocLocked(txn, deltaLoc, false)
  1079  }
  1080  
  1081  func (blk *baseObject) GetDeltaPersistedTS() types.TS {
  1082  	blk.RLock()
  1083  	defer blk.RUnlock()
  1084  	objMVCC := blk.tryGetMVCC()
  1085  	if objMVCC == nil {
  1086  		return types.TS{}
  1087  	}
  1088  	return objMVCC.GetDeltaPersistedTS()
  1089  }