github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/disttae/cache/catalog.go (about)

     1  // Copyright 2022 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 cache
    16  
    17  import (
    18  	"sort"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/catalog"
    21  	"github.com/matrixorigin/matrixone/pkg/compress"
    22  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    23  	"github.com/matrixorigin/matrixone/pkg/container/types"
    24  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    25  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    26  	"github.com/matrixorigin/matrixone/pkg/pb/timestamp"
    27  	"github.com/matrixorigin/matrixone/pkg/vm/engine"
    28  	"github.com/tidwall/btree"
    29  )
    30  
    31  func NewCatalog() *CatalogCache {
    32  	return &CatalogCache{
    33  		tables: &tableCache{
    34  			data:       btree.NewBTreeG(tableItemLess),
    35  			rowidIndex: btree.NewBTreeG(tableItemRowidLess),
    36  		},
    37  		databases: &databaseCache{
    38  			data:       btree.NewBTreeG(databaseItemLess),
    39  			rowidIndex: btree.NewBTreeG(databaseItemRowidLess),
    40  		},
    41  	}
    42  }
    43  
    44  func (cc *CatalogCache) GC(ts timestamp.Timestamp) {
    45  	{ // table cache gc
    46  		var items []*TableItem
    47  
    48  		cc.tables.data.Scan(func(item *TableItem) bool {
    49  			if len(items) > GcBuffer {
    50  				return false
    51  			}
    52  			if item.Ts.Less(ts) {
    53  				items = append(items, item)
    54  			}
    55  			return true
    56  		})
    57  		for _, item := range items {
    58  			cc.tables.data.Delete(item)
    59  			if !item.deleted {
    60  				cc.tables.rowidIndex.Delete(item)
    61  			}
    62  		}
    63  	}
    64  	{ // database cache gc
    65  		var items []*DatabaseItem
    66  
    67  		cc.databases.data.Scan(func(item *DatabaseItem) bool {
    68  			if len(items) > GcBuffer {
    69  				return false
    70  			}
    71  			if item.Ts.Less(ts) {
    72  				items = append(items, item)
    73  			}
    74  			return true
    75  		})
    76  		for _, item := range items {
    77  			cc.databases.data.Delete(item)
    78  			if !item.deleted {
    79  				cc.databases.rowidIndex.Delete(item)
    80  			}
    81  		}
    82  	}
    83  }
    84  
    85  func (cc *CatalogCache) Tables(accountId uint32, databaseId uint64,
    86  	ts timestamp.Timestamp) ([]string, []uint64) {
    87  	var rs []string
    88  	var rids []uint64
    89  
    90  	key := &TableItem{
    91  		AccountId:  accountId,
    92  		DatabaseId: databaseId,
    93  	}
    94  	mp := make(map[uint64]uint8)
    95  	cc.tables.data.Ascend(key, func(item *TableItem) bool {
    96  		if item.AccountId != accountId {
    97  			return false
    98  		}
    99  		if item.DatabaseId != databaseId {
   100  			return false
   101  		}
   102  		if item.Ts.Greater(ts) {
   103  			return true
   104  		}
   105  		if _, ok := mp[item.Id]; !ok {
   106  			mp[item.Id] = 0
   107  			if !item.deleted {
   108  				rs = append(rs, item.Name)
   109  				rids = append(rids, item.Id)
   110  			}
   111  		}
   112  		return true
   113  	})
   114  	return rs, rids
   115  }
   116  
   117  func (cc *CatalogCache) Databases(accountId uint32, ts timestamp.Timestamp) []string {
   118  	var rs []string
   119  
   120  	key := &DatabaseItem{
   121  		AccountId: accountId,
   122  	}
   123  	mp := make(map[string]uint8)
   124  	cc.databases.data.Ascend(key, func(item *DatabaseItem) bool {
   125  		if item.AccountId != accountId {
   126  			return false
   127  		}
   128  		if item.Ts.Greater(ts) {
   129  			return true
   130  		}
   131  		if _, ok := mp[item.Name]; !ok {
   132  			mp[item.Name] = 0
   133  			if !item.deleted {
   134  				rs = append(rs, item.Name)
   135  			}
   136  		}
   137  		return true
   138  	})
   139  	return rs
   140  }
   141  
   142  func (cc *CatalogCache) GetTable(tbl *TableItem) bool {
   143  	var find bool
   144  	var ts timestamp.Timestamp
   145  
   146  	cc.tables.data.Ascend(tbl, func(item *TableItem) bool {
   147  		if item.deleted && item.AccountId == tbl.AccountId &&
   148  			item.DatabaseId == tbl.DatabaseId && item.Name == tbl.Name {
   149  			if !ts.IsEmpty() {
   150  				return false
   151  			}
   152  			ts = item.Ts
   153  			return true
   154  		}
   155  		if !item.deleted && item.AccountId == tbl.AccountId &&
   156  			item.DatabaseId == tbl.DatabaseId && item.Name == tbl.Name &&
   157  			(ts.IsEmpty() || ts.Equal(item.Ts)) {
   158  			find = true
   159  			tbl.Id = item.Id
   160  			tbl.Defs = item.Defs
   161  			tbl.Kind = item.Kind
   162  			tbl.Comment = item.Comment
   163  			tbl.ViewDef = item.ViewDef
   164  			tbl.TableDef = item.TableDef
   165  			tbl.Constraint = item.Constraint
   166  			tbl.Partition = item.Partition
   167  			tbl.CreateSql = item.CreateSql
   168  			tbl.PrimaryIdx = item.PrimaryIdx
   169  			tbl.ClusterByIdx = item.ClusterByIdx
   170  		}
   171  		return false
   172  	})
   173  	return find
   174  }
   175  
   176  func (cc *CatalogCache) GetDatabase(db *DatabaseItem) bool {
   177  	var find bool
   178  
   179  	cc.databases.data.Ascend(db, func(item *DatabaseItem) bool {
   180  		if !item.deleted && item.AccountId == db.AccountId &&
   181  			item.Name == db.Name {
   182  			find = true
   183  			db.Id = item.Id
   184  		}
   185  		return false
   186  	})
   187  	return find
   188  }
   189  
   190  func (cc *CatalogCache) DeleteTable(bat *batch.Batch) {
   191  	rowids := vector.MustTCols[types.Rowid](bat.GetVector(MO_ROWID_IDX))
   192  	timestamps := vector.MustTCols[types.TS](bat.GetVector(MO_TIMESTAMP_IDX))
   193  	for i, rowid := range rowids {
   194  		if item, ok := cc.tables.rowidIndex.Get(&TableItem{Rowid: rowid}); ok {
   195  			newItem := &TableItem{
   196  				deleted:    true,
   197  				Id:         item.Id,
   198  				Name:       item.Name,
   199  				Rowid:      item.Rowid,
   200  				AccountId:  item.AccountId,
   201  				DatabaseId: item.DatabaseId,
   202  				Ts:         timestamps[i].ToTimestamp(),
   203  			}
   204  			cc.tables.data.Set(newItem)
   205  		}
   206  	}
   207  }
   208  
   209  func (cc *CatalogCache) DeleteDatabase(bat *batch.Batch) {
   210  	rowids := vector.MustTCols[types.Rowid](bat.GetVector(MO_ROWID_IDX))
   211  	timestamps := vector.MustTCols[types.TS](bat.GetVector(MO_TIMESTAMP_IDX))
   212  	for i, rowid := range rowids {
   213  		if item, ok := cc.databases.rowidIndex.Get(&DatabaseItem{Rowid: rowid}); ok {
   214  			newItem := &DatabaseItem{
   215  				deleted:   true,
   216  				Id:        item.Id,
   217  				Name:      item.Name,
   218  				Rowid:     item.Rowid,
   219  				AccountId: item.AccountId,
   220  				Ts:        timestamps[i].ToTimestamp(),
   221  			}
   222  			cc.databases.data.Set(newItem)
   223  		}
   224  	}
   225  }
   226  
   227  func (cc *CatalogCache) InsertTable(bat *batch.Batch) {
   228  	rowids := vector.MustTCols[types.Rowid](bat.GetVector(MO_ROWID_IDX))
   229  	timestamps := vector.MustTCols[types.TS](bat.GetVector(MO_TIMESTAMP_IDX))
   230  	accounts := vector.MustTCols[uint32](bat.GetVector(catalog.MO_TABLES_ACCOUNT_ID_IDX + MO_OFF))
   231  	names := vector.MustStrCols(bat.GetVector(catalog.MO_TABLES_REL_NAME_IDX + MO_OFF))
   232  	ids := vector.MustTCols[uint64](bat.GetVector(catalog.MO_TABLES_REL_ID_IDX + MO_OFF))
   233  	databaseIds := vector.MustTCols[uint64](bat.GetVector(catalog.MO_TABLES_RELDATABASE_ID_IDX + MO_OFF))
   234  	kinds := vector.MustStrCols(bat.GetVector(catalog.MO_TABLES_RELKIND_IDX + MO_OFF))
   235  	comments := vector.MustStrCols(bat.GetVector(catalog.MO_TABLES_REL_COMMENT_IDX + MO_OFF))
   236  	createSqls := vector.MustStrCols(bat.GetVector(catalog.MO_TABLES_REL_CREATESQL_IDX + MO_OFF))
   237  	viewDefs := vector.MustStrCols(bat.GetVector(catalog.MO_TABLES_VIEWDEF_IDX + MO_OFF))
   238  	paritions := vector.MustStrCols(bat.GetVector(catalog.MO_TABLES_PARTITIONED_IDX + MO_OFF))
   239  	constraints := vector.MustBytesCols(bat.GetVector(catalog.MO_TABLES_CONSTRAINT_IDX + MO_OFF))
   240  	for i, account := range accounts {
   241  		item := new(TableItem)
   242  		item.Id = ids[i]
   243  		item.Name = names[i]
   244  		item.AccountId = account
   245  		item.DatabaseId = databaseIds[i]
   246  		item.Ts = timestamps[i].ToTimestamp()
   247  		item.Kind = kinds[i]
   248  		item.ViewDef = viewDefs[i]
   249  		item.Constraint = constraints[i]
   250  		item.Comment = comments[i]
   251  		item.Partition = paritions[i]
   252  		item.CreateSql = createSqls[i]
   253  		item.PrimaryIdx = -1
   254  		item.ClusterByIdx = -1
   255  		copy(item.Rowid[:], rowids[i][:])
   256  		cc.tables.data.Set(item)
   257  		cc.tables.rowidIndex.Set(item)
   258  	}
   259  }
   260  
   261  func (cc *CatalogCache) InsertColumns(bat *batch.Batch) {
   262  	var tblKey tableItemKey
   263  
   264  	mp := make(map[tableItemKey]columns) // TableItem -> columns
   265  	key := new(TableItem)
   266  	// get table key info
   267  	timestamps := vector.MustTCols[types.TS](bat.GetVector(MO_TIMESTAMP_IDX))
   268  	accounts := vector.MustTCols[uint32](bat.GetVector(catalog.MO_COLUMNS_ACCOUNT_ID_IDX + MO_OFF))
   269  	databaseIds := vector.MustTCols[uint64](bat.GetVector(catalog.MO_COLUMNS_ATT_DATABASE_ID_IDX + MO_OFF))
   270  	tableNames := vector.MustStrCols(bat.GetVector(catalog.MO_COLUMNS_ATT_RELNAME_IDX + MO_OFF))
   271  	// get columns info
   272  	names := vector.MustStrCols(bat.GetVector(catalog.MO_COLUMNS_ATTNAME_IDX + MO_OFF))
   273  	comments := vector.MustStrCols(bat.GetVector(catalog.MO_COLUMNS_ATT_COMMENT_IDX + MO_OFF))
   274  	isHiddens := vector.MustTCols[int8](bat.GetVector(catalog.MO_COLUMNS_ATT_IS_HIDDEN_IDX + MO_OFF))
   275  	isAutos := vector.MustTCols[int8](bat.GetVector(catalog.MO_COLUMNS_ATT_IS_AUTO_INCREMENT_IDX + MO_OFF))
   276  	constraintTypes := vector.MustStrCols(bat.GetVector(catalog.MO_COLUMNS_ATT_CONSTRAINT_TYPE_IDX + MO_OFF))
   277  	typs := vector.MustBytesCols(bat.GetVector(catalog.MO_COLUMNS_ATTTYP_IDX + MO_OFF))
   278  	hasDefs := vector.MustTCols[int8](bat.GetVector(catalog.MO_COLUMNS_ATTHASDEF_IDX + MO_OFF))
   279  	defaultExprs := vector.MustBytesCols(bat.GetVector(catalog.MO_COLUMNS_ATT_DEFAULT_IDX + MO_OFF))
   280  	hasUpdates := vector.MustTCols[int8](bat.GetVector(catalog.MO_COLUMNS_ATT_HAS_UPDATE_IDX + MO_OFF))
   281  	updateExprs := vector.MustBytesCols(bat.GetVector(catalog.MO_COLUMNS_ATT_UPDATE_IDX + MO_OFF))
   282  	nums := vector.MustTCols[int32](bat.GetVector(catalog.MO_COLUMNS_ATTNUM_IDX + MO_OFF))
   283  	clusters := vector.MustTCols[int8](bat.GetVector(catalog.MO_COLUMNS_ATT_IS_CLUSTERBY + MO_OFF))
   284  	for i, account := range accounts {
   285  		key.AccountId = account
   286  		key.Name = tableNames[i]
   287  		key.DatabaseId = databaseIds[i]
   288  		key.Ts = timestamps[i].ToTimestamp()
   289  		tblKey.Name = key.Name
   290  		tblKey.AccountId = key.AccountId
   291  		tblKey.DatabaseId = key.DatabaseId
   292  		tblKey.NodeId = key.Ts.NodeID
   293  		tblKey.LogicalTime = key.Ts.LogicalTime
   294  		tblKey.PhysicalTime = uint64(key.Ts.PhysicalTime)
   295  		if _, ok := cc.tables.data.Get(key); ok {
   296  			col := column{
   297  				num:             nums[i],
   298  				name:            names[i],
   299  				comment:         comments[i],
   300  				isHidden:        isHiddens[i],
   301  				isAutoIncrement: isAutos[i],
   302  				hasDef:          hasDefs[i],
   303  				hasUpdate:       hasUpdates[i],
   304  				constraintType:  constraintTypes[i],
   305  				isClusterBy:     clusters[i],
   306  			}
   307  			col.typ = append(col.typ, typs[i]...)
   308  			col.updateExpr = append(col.updateExpr, updateExprs[i]...)
   309  			col.defaultExpr = append(col.defaultExpr, defaultExprs[i]...)
   310  			mp[tblKey] = append(mp[tblKey], col)
   311  		}
   312  	}
   313  	for k, cols := range mp {
   314  		sort.Sort(cols)
   315  		key.Name = k.Name
   316  		key.AccountId = k.AccountId
   317  		key.DatabaseId = k.DatabaseId
   318  		key.Ts = timestamp.Timestamp{
   319  			NodeID:       k.NodeId,
   320  			PhysicalTime: int64(k.PhysicalTime),
   321  			LogicalTime:  k.LogicalTime,
   322  		}
   323  		item, _ := cc.tables.data.Get(key)
   324  		defs := make([]engine.TableDef, 0, len(cols))
   325  		defs = append(defs, genTableDefOfComment(item.Comment))
   326  		for i, col := range cols {
   327  			if col.constraintType == catalog.SystemColPKConstraint {
   328  				item.PrimaryIdx = i
   329  			}
   330  			if col.isClusterBy == 1 {
   331  				item.ClusterByIdx = i
   332  			}
   333  			defs = append(defs, genTableDefOfColumn(col))
   334  		}
   335  		item.Defs = defs
   336  		item.TableDef = getTableDef(item.Name, defs)
   337  	}
   338  }
   339  
   340  func (cc *CatalogCache) InsertDatabase(bat *batch.Batch) {
   341  	rowids := vector.MustTCols[types.Rowid](bat.GetVector(MO_ROWID_IDX))
   342  	timestamps := vector.MustTCols[types.TS](bat.GetVector(MO_TIMESTAMP_IDX))
   343  	accounts := vector.MustTCols[uint32](bat.GetVector(catalog.MO_DATABASE_ACCOUNT_ID_IDX + MO_OFF))
   344  	names := vector.MustStrCols(bat.GetVector(catalog.MO_DATABASE_DAT_NAME_IDX + MO_OFF))
   345  	ids := vector.MustTCols[uint64](bat.GetVector(catalog.MO_DATABASE_DAT_ID_IDX + MO_OFF))
   346  	for i, account := range accounts {
   347  		item := new(DatabaseItem)
   348  		item.Id = ids[i]
   349  		item.Name = names[i]
   350  		item.AccountId = account
   351  		item.Ts = timestamps[i].ToTimestamp()
   352  		copy(item.Rowid[:], rowids[i][:])
   353  		cc.databases.data.Set(item)
   354  		cc.databases.rowidIndex.Set(item)
   355  	}
   356  }
   357  
   358  func genTableDefOfComment(comment string) engine.TableDef {
   359  	return &engine.CommentDef{
   360  		Comment: comment,
   361  	}
   362  }
   363  
   364  func genTableDefOfColumn(col column) engine.TableDef {
   365  	var attr engine.Attribute
   366  
   367  	attr.Name = col.name
   368  	attr.ID = uint64(col.num)
   369  	attr.Alg = compress.Lz4
   370  	attr.Comment = col.comment
   371  	attr.IsHidden = col.isHidden == 1
   372  	attr.ClusterBy = col.isClusterBy == 1
   373  	attr.AutoIncrement = col.isAutoIncrement == 1
   374  	if err := types.Decode(col.typ, &attr.Type); err != nil {
   375  		panic(err)
   376  	}
   377  	if col.hasDef == 1 {
   378  		attr.Default = new(plan.Default)
   379  		if err := types.Decode(col.defaultExpr, attr.Default); err != nil {
   380  			panic(err)
   381  		}
   382  	}
   383  	if col.hasUpdate == 1 {
   384  		attr.OnUpdate = new(plan.OnUpdate)
   385  		if err := types.Decode(col.updateExpr, attr.OnUpdate); err != nil {
   386  			panic(err)
   387  		}
   388  	}
   389  	if col.constraintType == catalog.SystemColPKConstraint {
   390  		attr.Primary = true
   391  	}
   392  	return &engine.AttributeDef{Attr: attr}
   393  }
   394  
   395  // getTableDef only return all cols and their index.
   396  func getTableDef(name string, defs []engine.TableDef) *plan.TableDef {
   397  	var cols []*plan.ColDef
   398  
   399  	i := int32(0)
   400  	name2index := make(map[string]int32)
   401  	for _, def := range defs {
   402  		if attr, ok := def.(*engine.AttributeDef); ok {
   403  			name2index[attr.Attr.Name] = i
   404  			cols = append(cols, &plan.ColDef{
   405  				ColId: attr.Attr.ID,
   406  				Name:  attr.Attr.Name,
   407  				Typ: &plan.Type{
   408  					Id:        int32(attr.Attr.Type.Oid),
   409  					Width:     attr.Attr.Type.Width,
   410  					Size:      attr.Attr.Type.Size,
   411  					Precision: attr.Attr.Type.Precision,
   412  					Scale:     attr.Attr.Type.Scale,
   413  					AutoIncr:  attr.Attr.AutoIncrement,
   414  				},
   415  				Primary:  attr.Attr.Primary,
   416  				Default:  attr.Attr.Default,
   417  				OnUpdate: attr.Attr.OnUpdate,
   418  				Comment:  attr.Attr.Comment,
   419  			})
   420  			i++
   421  		}
   422  	}
   423  	return &plan.TableDef{
   424  		Name:          name,
   425  		Cols:          cols,
   426  		Name2ColIndex: name2index,
   427  	}
   428  }