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  }