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  }