github.com/matrixorigin/matrixone@v1.2.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  	"fmt"
    19  	"math"
    20  	"sort"
    21  	"sync"
    22  
    23  	plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan"
    24  	"github.com/matrixorigin/matrixone/pkg/sql/util"
    25  
    26  	"github.com/matrixorigin/matrixone/pkg/catalog"
    27  	"github.com/matrixorigin/matrixone/pkg/compress"
    28  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    29  	"github.com/matrixorigin/matrixone/pkg/container/types"
    30  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    31  	"github.com/matrixorigin/matrixone/pkg/logutil"
    32  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    33  	"github.com/matrixorigin/matrixone/pkg/pb/timestamp"
    34  	"github.com/matrixorigin/matrixone/pkg/vm/engine"
    35  	"github.com/tidwall/btree"
    36  )
    37  
    38  func NewCatalog() *CatalogCache {
    39  	return &CatalogCache{
    40  		tables: &tableCache{
    41  			data:       btree.NewBTreeG(tableItemLess),
    42  			rowidIndex: btree.NewBTreeG(tableItemRowidLess),
    43  			tableGuard: newTableGuard(),
    44  		},
    45  		databases: &databaseCache{
    46  			data:       btree.NewBTreeG(databaseItemLess),
    47  			rowidIndex: btree.NewBTreeG(databaseItemRowidLess),
    48  		},
    49  		mu: struct {
    50  			sync.Mutex
    51  			start types.TS
    52  			end   types.TS
    53  		}{start: types.MaxTs()},
    54  	}
    55  }
    56  
    57  func (cc *CatalogCache) UpdateDuration(start types.TS, end types.TS) {
    58  	cc.mu.Lock()
    59  	defer cc.mu.Unlock()
    60  	cc.mu.start = start
    61  	cc.mu.end = end
    62  }
    63  
    64  var _ = (&CatalogCache{}).UpdateStart
    65  
    66  func (cc *CatalogCache) UpdateStart(ts types.TS) {
    67  	cc.mu.Lock()
    68  	defer cc.mu.Unlock()
    69  	if cc.mu.start != types.MaxTs() {
    70  		cc.mu.start = ts
    71  	}
    72  }
    73  
    74  func (cc *CatalogCache) CanServe(ts types.TS) bool {
    75  	cc.mu.Lock()
    76  	defer cc.mu.Unlock()
    77  	return ts.GreaterEq(&cc.mu.start) && ts.LessEq(&cc.mu.end)
    78  }
    79  
    80  func (cc *CatalogCache) GC(ts timestamp.Timestamp) {
    81  	{ // table cache gc
    82  		var items []*TableItem
    83  
    84  		cc.tables.data.Scan(func(item *TableItem) bool {
    85  			if len(items) > GcBuffer {
    86  				return false
    87  			}
    88  			if item.Ts.Less(ts) {
    89  				items = append(items, item)
    90  			}
    91  			return true
    92  		})
    93  		for _, item := range items {
    94  			cc.tables.data.Delete(item)
    95  			if !item.deleted {
    96  				cc.tables.rowidIndex.Delete(item)
    97  			}
    98  		}
    99  	}
   100  	{ // database cache gc
   101  		var items []*DatabaseItem
   102  
   103  		cc.databases.data.Scan(func(item *DatabaseItem) bool {
   104  			if len(items) > GcBuffer {
   105  				return false
   106  			}
   107  			if item.Ts.Less(ts) {
   108  				items = append(items, item)
   109  			}
   110  			return true
   111  		})
   112  		for _, item := range items {
   113  			cc.databases.data.Delete(item)
   114  			if !item.deleted {
   115  				cc.databases.rowidIndex.Delete(item)
   116  			}
   117  		}
   118  	}
   119  }
   120  
   121  type tableIdNameKey struct {
   122  	id   uint64
   123  	name string
   124  }
   125  
   126  func (cc *CatalogCache) Tables(accountId uint32, databaseId uint64,
   127  	ts timestamp.Timestamp) ([]string, []uint64) {
   128  	var rs []string
   129  	var rids []uint64
   130  
   131  	key := &TableItem{
   132  		AccountId:  accountId,
   133  		DatabaseId: databaseId,
   134  	}
   135  	mp := make(map[tableIdNameKey]uint8)
   136  	cc.tables.data.Ascend(key, func(item *TableItem) bool {
   137  		if item.AccountId != accountId {
   138  			return false
   139  		}
   140  		if item.DatabaseId != databaseId {
   141  			return false
   142  		}
   143  		// In previous impl table id is used to deduplicate, but this a corner case: rename table t to newt, and rename newt back to t.
   144  		// In this case newt is first found deleted and taking the place of active t's tableid.
   145  		// What's more, if a table is truncated, a name can be occuppied by different ids. only use name to to dedup is also inadequate.
   146  		if item.Ts.Greater(ts) {
   147  			return true
   148  		}
   149  		key := tableIdNameKey{id: item.Id, name: item.Name}
   150  		if _, ok := mp[key]; !ok {
   151  			mp[key] = 0
   152  			if !item.deleted {
   153  				rs = append(rs, item.Name)
   154  				rids = append(rids, item.Id)
   155  			}
   156  		}
   157  		return true
   158  	})
   159  	return rs, rids
   160  }
   161  
   162  func (cc *CatalogCache) GetTableById(databaseId, tblId uint64) *TableItem {
   163  	var rel *TableItem
   164  
   165  	key := &TableItem{
   166  		DatabaseId: databaseId,
   167  	}
   168  	// If account is much, the performance is very bad.
   169  	cc.tables.data.Ascend(key, func(item *TableItem) bool {
   170  		if item.Id == tblId {
   171  			rel = item
   172  			return false
   173  		}
   174  		return true
   175  	})
   176  	return rel
   177  }
   178  
   179  // GetTableByName returns the table item whose name is tableName in the database.
   180  func (cc *CatalogCache) GetTableByName(databaseID uint64, tableName string) *TableItem {
   181  	var rel *TableItem
   182  	key := &TableItem{
   183  		DatabaseId: databaseID,
   184  	}
   185  	cc.tables.data.Ascend(key, func(item *TableItem) bool {
   186  		if item.Name == tableName {
   187  			rel = item
   188  			return false
   189  		}
   190  		return true
   191  	})
   192  	return rel
   193  }
   194  
   195  func (cc *CatalogCache) Databases(accountId uint32, ts timestamp.Timestamp) []string {
   196  	var rs []string
   197  
   198  	key := &DatabaseItem{
   199  		AccountId: accountId,
   200  	}
   201  	mp := make(map[string]uint8)
   202  	cc.databases.data.Ascend(key, func(item *DatabaseItem) bool {
   203  		if item.AccountId != accountId {
   204  			return false
   205  		}
   206  		if item.Ts.Greater(ts) {
   207  			return true
   208  		}
   209  		if _, ok := mp[item.Name]; !ok {
   210  			mp[item.Name] = 0
   211  			if !item.deleted {
   212  				rs = append(rs, item.Name)
   213  			}
   214  		}
   215  		return true
   216  	})
   217  	return rs
   218  }
   219  
   220  func (cc *CatalogCache) GetTable(tbl *TableItem) bool {
   221  	var find bool
   222  	var ts timestamp.Timestamp
   223  	/**
   224  	In push mode.
   225  	It is necessary to distinguish the case create table/drop table
   226  	from truncate table.
   227  
   228  	CORNER CASE 1:
   229  	begin;
   230  	create table t1(a int);//table id x. catalog.insertTable(table id x)
   231  	insert into t1 values (1);
   232  	drop table t1; //same table id x. catalog.deleteTable(table id x)
   233  	commit;
   234  
   235  	CORNER CASE 2:
   236  	create table t1(a int); //table id x.
   237  	begin;
   238  	insert into t1 values (1);
   239  	-- @session:id=1{
   240  	truncate table t1;//insert table id y, then delete table id x. catalog.insertTable(table id y). catalog.deleteTable(table id x)
   241  	-- @session}
   242  	commit;
   243  
   244  	CORNER CASE 3:
   245  	create table t1(a int); //table id x.
   246  	begin;
   247  	truncate t1;//table id x changed to x1
   248  	truncate t1;//table id x1 changed to x2
   249  	truncate t1;//table id x2 changed to x3
   250  	commit;//catalog.insertTable(table id x1,x2,x3). catalog.deleteTable(table id x,x1,x2)
   251  
   252  	To be clear that the TableItem in catalogCache is sorted by the table id.
   253  	*/
   254  	var tableId uint64
   255  	deleted := make(map[uint64]bool)
   256  	inserted := make(map[uint64]*TableItem)
   257  	tbl.Id = math.MaxUint64
   258  	cc.tables.data.Ascend(tbl, func(item *TableItem) bool {
   259  		if item.deleted && item.AccountId == tbl.AccountId &&
   260  			item.DatabaseId == tbl.DatabaseId && item.Name == tbl.Name {
   261  			if !ts.IsEmpty() {
   262  				//if it is the truncate operation, we collect deleteTable together.
   263  				if item.Ts.Equal(ts) {
   264  					deleted[item.Id] = true
   265  					return true
   266  				} else {
   267  					return false
   268  				}
   269  			}
   270  			ts = item.Ts
   271  			tableId = item.Id
   272  			deleted[item.Id] = true
   273  			return true
   274  		}
   275  		if !item.deleted && item.AccountId == tbl.AccountId &&
   276  			item.DatabaseId == tbl.DatabaseId && item.Name == tbl.Name &&
   277  			(ts.IsEmpty() || ts.Equal(item.Ts) && tableId != item.Id) {
   278  			//if it is the truncate operation, we collect insertTable together first.
   279  			if !ts.IsEmpty() && ts.Equal(item.Ts) && tableId != item.Id {
   280  				inserted[item.Id] = item
   281  				return true
   282  			} else {
   283  				find = true
   284  				copyTableItem(tbl, item)
   285  				return false
   286  			}
   287  		}
   288  		if find {
   289  			return false
   290  		}
   291  		return false
   292  	})
   293  
   294  	if find {
   295  		return true
   296  	}
   297  
   298  	//handle truncate operation independently
   299  	//remove deleted item from inserted item
   300  	for rowid := range deleted {
   301  		delete(inserted, rowid)
   302  	}
   303  
   304  	//if there is no inserted item, it means that the table is deleted.
   305  	if len(inserted) == 0 {
   306  		return false
   307  	}
   308  
   309  	//if there is more than one inserted item, it means that it is wrong
   310  	if len(inserted) > 1 {
   311  		panic(fmt.Sprintf("account %d database %d has multiple tables %s",
   312  			tbl.AccountId, tbl.DatabaseId, tbl.Name))
   313  	}
   314  
   315  	//get item
   316  	for _, item := range inserted {
   317  		copyTableItem(tbl, item)
   318  	}
   319  
   320  	return true
   321  }
   322  
   323  func (cc *CatalogCache) GetDatabase(db *DatabaseItem) bool {
   324  	var find bool
   325  	var ts timestamp.Timestamp
   326  	var databaseId uint64
   327  
   328  	deleted := make(map[uint64]bool)
   329  	inserted := make(map[uint64]*DatabaseItem)
   330  	db.Id = math.MaxUint64
   331  
   332  	cc.databases.data.Ascend(db, func(item *DatabaseItem) bool {
   333  		if item.deleted && item.AccountId == db.AccountId && item.Name == db.Name {
   334  			if !ts.IsEmpty() {
   335  				if item.Ts.Equal(ts) {
   336  					deleted[item.Id] = true
   337  					return true
   338  				} else {
   339  					return false
   340  				}
   341  			}
   342  			ts = item.Ts
   343  			databaseId = item.Id
   344  			deleted[item.Id] = true
   345  			return true
   346  		}
   347  
   348  		if !item.deleted && item.AccountId == db.AccountId && item.Name == db.Name &&
   349  			(ts.IsEmpty() || ts.Equal(item.Ts) && databaseId != item.Id) {
   350  			if !ts.IsEmpty() && ts.Equal(item.Ts) && databaseId != item.Id {
   351  				inserted[item.Id] = item
   352  				return true
   353  			} else {
   354  				find = true
   355  				copyDatabaseItem(db, item)
   356  				return false
   357  			}
   358  		}
   359  		return false
   360  	})
   361  
   362  	if find {
   363  		return true
   364  	}
   365  
   366  	for rowid := range deleted {
   367  		delete(inserted, rowid)
   368  	}
   369  
   370  	//if there is no inserted item, it means that the database is deleted.
   371  	if len(inserted) == 0 {
   372  		return false
   373  	}
   374  
   375  	//if there is more than one inserted item, it means that it is wrong
   376  	if len(inserted) > 1 {
   377  		panic(fmt.Sprintf("account %d has multiple database %s", db.AccountId, db.Name))
   378  	}
   379  
   380  	//get item
   381  	for _, item := range inserted {
   382  		copyDatabaseItem(db, item)
   383  	}
   384  	return true
   385  }
   386  
   387  func (cc *CatalogCache) DeleteTable(bat *batch.Batch) {
   388  	rowids := vector.MustFixedCol[types.Rowid](bat.GetVector(MO_ROWID_IDX))
   389  	timestamps := vector.MustFixedCol[types.TS](bat.GetVector(MO_TIMESTAMP_IDX))
   390  	for i, rowid := range rowids {
   391  		if item, ok := cc.tables.rowidIndex.Get(&TableItem{Rowid: rowid}); ok {
   392  			newItem := &TableItem{
   393  				deleted:    true,
   394  				Id:         item.Id,
   395  				Name:       item.Name,
   396  				Rowid:      item.Rowid,
   397  				AccountId:  item.AccountId,
   398  				DatabaseId: item.DatabaseId,
   399  				Ts:         timestamps[i].ToTimestamp(),
   400  			}
   401  			cc.tables.addTableItem(newItem)
   402  
   403  			key := TableKey{
   404  				AccountId:  item.AccountId,
   405  				DatabaseId: item.DatabaseId,
   406  				Name:       item.Name,
   407  			}
   408  
   409  			oldVersion := cc.tables.tableGuard.getSchemaVersion(key)
   410  
   411  			if oldVersion != nil && oldVersion.TableId != item.Id {
   412  				// drop old table for alter table stmt
   413  				oldVersion.Version = math.MaxUint32
   414  				cc.tables.tableGuard.setSchemaVersion(key, oldVersion)
   415  			} else {
   416  				// normal drop table stmt
   417  				cc.tables.tableGuard.setSchemaVersion(key, &TableVersion{
   418  					Version: math.MaxUint32,
   419  					Ts:      &item.Ts,
   420  				})
   421  			}
   422  		}
   423  	}
   424  }
   425  
   426  func (cc *CatalogCache) DeleteDatabase(bat *batch.Batch) {
   427  	rowids := vector.MustFixedCol[types.Rowid](bat.GetVector(MO_ROWID_IDX))
   428  	timestamps := vector.MustFixedCol[types.TS](bat.GetVector(MO_TIMESTAMP_IDX))
   429  	for i, rowid := range rowids {
   430  		if item, ok := cc.databases.rowidIndex.Get(&DatabaseItem{Rowid: rowid}); ok {
   431  			newItem := &DatabaseItem{
   432  				deleted:   true,
   433  				Id:        item.Id,
   434  				Name:      item.Name,
   435  				Rowid:     item.Rowid,
   436  				AccountId: item.AccountId,
   437  				Typ:       item.Typ,
   438  				CreateSql: item.CreateSql,
   439  				Ts:        timestamps[i].ToTimestamp(),
   440  			}
   441  			cc.databases.data.Set(newItem)
   442  		}
   443  	}
   444  }
   445  
   446  func (cc *CatalogCache) InsertTable(bat *batch.Batch) {
   447  	rowids := vector.MustFixedCol[types.Rowid](bat.GetVector(MO_ROWID_IDX))
   448  	timestamps := vector.MustFixedCol[types.TS](bat.GetVector(MO_TIMESTAMP_IDX))
   449  	accounts := vector.MustFixedCol[uint32](bat.GetVector(catalog.MO_TABLES_ACCOUNT_ID_IDX + MO_OFF))
   450  	names := bat.GetVector(catalog.MO_TABLES_REL_NAME_IDX + MO_OFF)
   451  	ids := vector.MustFixedCol[uint64](bat.GetVector(catalog.MO_TABLES_REL_ID_IDX + MO_OFF))
   452  	databaseIds := vector.MustFixedCol[uint64](bat.GetVector(catalog.MO_TABLES_RELDATABASE_ID_IDX + MO_OFF))
   453  	kinds := bat.GetVector(catalog.MO_TABLES_RELKIND_IDX + MO_OFF)
   454  	comments := bat.GetVector(catalog.MO_TABLES_REL_COMMENT_IDX + MO_OFF)
   455  	createSqls := bat.GetVector(catalog.MO_TABLES_REL_CREATESQL_IDX + MO_OFF)
   456  	viewDefs := bat.GetVector(catalog.MO_TABLES_VIEWDEF_IDX + MO_OFF)
   457  	partitioneds := vector.MustFixedCol[int8](bat.GetVector(catalog.MO_TABLES_PARTITIONED_IDX + MO_OFF))
   458  	paritions := bat.GetVector(catalog.MO_TABLES_PARTITION_INFO_IDX + MO_OFF)
   459  	constraints := bat.GetVector(catalog.MO_TABLES_CONSTRAINT_IDX + MO_OFF)
   460  	versions := vector.MustFixedCol[uint32](bat.GetVector(catalog.MO_TABLES_VERSION_IDX + MO_OFF))
   461  	catalogVersions := vector.MustFixedCol[uint32](bat.GetVector(catalog.MO_TABLES_CATALOG_VERSION_IDX + MO_OFF))
   462  	for i, account := range accounts {
   463  		item := new(TableItem)
   464  		item.Id = ids[i]
   465  		item.Name = names.GetStringAt(i)
   466  		item.AccountId = account
   467  		item.DatabaseId = databaseIds[i]
   468  		item.Ts = timestamps[i].ToTimestamp()
   469  		item.Kind = kinds.GetStringAt(i)
   470  		item.ViewDef = viewDefs.GetStringAt(i)
   471  		item.Constraint = append(item.Constraint, constraints.GetBytesAt(i)...)
   472  		item.Comment = comments.GetStringAt(i)
   473  		item.Partitioned = partitioneds[i]
   474  		item.Partition = paritions.GetStringAt(i)
   475  		item.CreateSql = createSqls.GetStringAt(i)
   476  		item.Version = versions[i]
   477  		item.CatalogVersion = catalogVersions[i]
   478  		item.PrimaryIdx = -1
   479  		item.PrimarySeqnum = -1
   480  		item.ClusterByIdx = -1
   481  		copy(item.Rowid[:], rowids[i][:])
   482  		// invalid old name table
   483  		exist, ok := cc.tables.rowidIndex.Get(&TableItem{Rowid: rowids[i]})
   484  		if ok && exist.Name != item.Name {
   485  			logutil.Infof("rename invalidate %d-%s,v%d@%s", exist.Id, exist.Name, exist.Version, item.Ts.String())
   486  			newItem := &TableItem{
   487  				deleted:    true,
   488  				Id:         exist.Id,
   489  				Name:       exist.Name,
   490  				Rowid:      exist.Rowid,
   491  				AccountId:  exist.AccountId,
   492  				DatabaseId: exist.DatabaseId,
   493  				Version:    exist.Version,
   494  				Ts:         item.Ts,
   495  			}
   496  			cc.tables.addTableItem(newItem)
   497  
   498  			key := TableKey{
   499  				AccountId:  account,
   500  				DatabaseId: item.DatabaseId,
   501  				Name:       exist.Name,
   502  			}
   503  			cc.tables.tableGuard.setSchemaVersion(key, &TableVersion{
   504  				Version: math.MaxUint32,
   505  				Ts:      &item.Ts,
   506  				TableId: item.Id,
   507  			})
   508  		}
   509  
   510  		key := TableKey{
   511  			AccountId:  account,
   512  			DatabaseId: item.DatabaseId,
   513  			Name:       item.Name,
   514  		}
   515  
   516  		cc.tables.tableGuard.setSchemaVersion(key, &TableVersion{
   517  			Version: item.Version,
   518  			Ts:      &item.Ts,
   519  			TableId: item.Id,
   520  		})
   521  		cc.tables.addTableItem(item)
   522  		cc.tables.rowidIndex.Set(item)
   523  	}
   524  }
   525  
   526  func (cc *CatalogCache) InsertColumns(bat *batch.Batch) {
   527  	var tblKey tableItemKey
   528  
   529  	mp := make(map[tableItemKey]columns) // TableItem -> columns
   530  	key := new(TableItem)
   531  	rowids := vector.MustFixedCol[types.Rowid](bat.GetVector(MO_ROWID_IDX))
   532  	// get table key info
   533  	timestamps := vector.MustFixedCol[types.TS](bat.GetVector(MO_TIMESTAMP_IDX))
   534  	accounts := vector.MustFixedCol[uint32](bat.GetVector(catalog.MO_COLUMNS_ACCOUNT_ID_IDX + MO_OFF))
   535  	databaseIds := vector.MustFixedCol[uint64](bat.GetVector(catalog.MO_COLUMNS_ATT_DATABASE_ID_IDX + MO_OFF))
   536  	tableNames := bat.GetVector(catalog.MO_COLUMNS_ATT_RELNAME_IDX + MO_OFF)
   537  	tableIds := vector.MustFixedCol[uint64](bat.GetVector(catalog.MO_COLUMNS_ATT_RELNAME_ID_IDX + MO_OFF))
   538  	// get columns info
   539  	names := bat.GetVector(catalog.MO_COLUMNS_ATTNAME_IDX + MO_OFF)
   540  	comments := bat.GetVector(catalog.MO_COLUMNS_ATT_COMMENT_IDX + MO_OFF)
   541  	isHiddens := vector.MustFixedCol[int8](bat.GetVector(catalog.MO_COLUMNS_ATT_IS_HIDDEN_IDX + MO_OFF))
   542  	isAutos := vector.MustFixedCol[int8](bat.GetVector(catalog.MO_COLUMNS_ATT_IS_AUTO_INCREMENT_IDX + MO_OFF))
   543  	constraintTypes := bat.GetVector(catalog.MO_COLUMNS_ATT_CONSTRAINT_TYPE_IDX + MO_OFF)
   544  	typs := bat.GetVector(catalog.MO_COLUMNS_ATTTYP_IDX + MO_OFF)
   545  	hasDefs := vector.MustFixedCol[int8](bat.GetVector(catalog.MO_COLUMNS_ATTHASDEF_IDX + MO_OFF))
   546  	defaultExprs := bat.GetVector(catalog.MO_COLUMNS_ATT_DEFAULT_IDX + MO_OFF)
   547  	hasUpdates := vector.MustFixedCol[int8](bat.GetVector(catalog.MO_COLUMNS_ATT_HAS_UPDATE_IDX + MO_OFF))
   548  	updateExprs := bat.GetVector(catalog.MO_COLUMNS_ATT_UPDATE_IDX + MO_OFF)
   549  	nums := vector.MustFixedCol[int32](bat.GetVector(catalog.MO_COLUMNS_ATTNUM_IDX + MO_OFF))
   550  	clusters := vector.MustFixedCol[int8](bat.GetVector(catalog.MO_COLUMNS_ATT_IS_CLUSTERBY + MO_OFF))
   551  	seqnums := vector.MustFixedCol[uint16](bat.GetVector(catalog.MO_COLUMNS_ATT_SEQNUM_IDX + MO_OFF))
   552  	enumValues := bat.GetVector(catalog.MO_COLUMNS_ATT_ENUM_IDX + MO_OFF)
   553  	for i, account := range accounts {
   554  		key.AccountId = account
   555  		key.Name = tableNames.GetStringAt(i)
   556  		key.DatabaseId = databaseIds[i]
   557  		key.Ts = timestamps[i].ToTimestamp()
   558  		key.Id = tableIds[i]
   559  		tblKey.Name = key.Name
   560  		tblKey.AccountId = key.AccountId
   561  		tblKey.DatabaseId = key.DatabaseId
   562  		tblKey.NodeId = key.Ts.NodeID
   563  		tblKey.LogicalTime = key.Ts.LogicalTime
   564  		tblKey.PhysicalTime = uint64(key.Ts.PhysicalTime)
   565  		tblKey.Id = tableIds[i]
   566  		if _, ok := cc.tables.data.Get(key); ok {
   567  			col := column{
   568  				num:             nums[i],
   569  				name:            names.GetStringAt(i),
   570  				comment:         comments.GetStringAt(i),
   571  				isHidden:        isHiddens[i],
   572  				isAutoIncrement: isAutos[i],
   573  				hasDef:          hasDefs[i],
   574  				hasUpdate:       hasUpdates[i],
   575  				constraintType:  constraintTypes.GetStringAt(i),
   576  				isClusterBy:     clusters[i],
   577  				seqnum:          seqnums[i],
   578  				enumValues:      enumValues.GetStringAt(i),
   579  			}
   580  			copy(col.rowid[:], rowids[i][:])
   581  			col.typ = append(col.typ, typs.GetBytesAt(i)...)
   582  			col.updateExpr = append(col.updateExpr, updateExprs.GetBytesAt(i)...)
   583  			col.defaultExpr = append(col.defaultExpr, defaultExprs.GetBytesAt(i)...)
   584  			mp[tblKey] = append(mp[tblKey], col)
   585  		}
   586  	}
   587  	for k, cols := range mp {
   588  		sort.Sort(cols)
   589  		key.Name = k.Name
   590  		key.AccountId = k.AccountId
   591  		key.DatabaseId = k.DatabaseId
   592  		key.Ts = timestamp.Timestamp{
   593  			NodeID:       k.NodeId,
   594  			PhysicalTime: int64(k.PhysicalTime),
   595  			LogicalTime:  k.LogicalTime,
   596  		}
   597  		key.Id = k.Id
   598  		item, _ := cc.tables.data.Get(key)
   599  		defs := make([]engine.TableDef, 0, len(cols))
   600  		defs = append(defs, genTableDefOfComment(item.Comment))
   601  		item.Rowids = make([]types.Rowid, len(cols))
   602  		for i, col := range cols {
   603  			if col.constraintType == catalog.SystemColPKConstraint {
   604  				item.PrimaryIdx = i
   605  				item.PrimarySeqnum = int(col.seqnum)
   606  			}
   607  			if col.isClusterBy == 1 {
   608  				item.ClusterByIdx = i
   609  			}
   610  			defs = append(defs, genTableDefOfColumn(col))
   611  			copy(item.Rowids[i][:], col.rowid[:])
   612  		}
   613  		item.Defs = defs
   614  		item.TableDef = getTableDef(item, defs)
   615  	}
   616  }
   617  
   618  func (cc *CatalogCache) InsertDatabase(bat *batch.Batch) {
   619  	rowids := vector.MustFixedCol[types.Rowid](bat.GetVector(MO_ROWID_IDX))
   620  	timestamps := vector.MustFixedCol[types.TS](bat.GetVector(MO_TIMESTAMP_IDX))
   621  	accounts := vector.MustFixedCol[uint32](bat.GetVector(catalog.MO_DATABASE_ACCOUNT_ID_IDX + MO_OFF))
   622  	names := bat.GetVector(catalog.MO_DATABASE_DAT_NAME_IDX + MO_OFF)
   623  	ids := vector.MustFixedCol[uint64](bat.GetVector(catalog.MO_DATABASE_DAT_ID_IDX + MO_OFF))
   624  	typs := bat.GetVector(catalog.MO_DATABASE_DAT_TYPE_IDX + MO_OFF)
   625  	createSqls := bat.GetVector(catalog.MO_DATABASE_CREATESQL_IDX + MO_OFF)
   626  	for i, account := range accounts {
   627  		item := new(DatabaseItem)
   628  		item.Id = ids[i]
   629  		item.Name = names.GetStringAt(i)
   630  		item.AccountId = account
   631  		item.Ts = timestamps[i].ToTimestamp()
   632  		item.Typ = typs.GetStringAt(i)
   633  		item.CreateSql = createSqls.GetStringAt(i)
   634  		copy(item.Rowid[:], rowids[i][:])
   635  		cc.databases.data.Set(item)
   636  		cc.databases.rowidIndex.Set(item)
   637  	}
   638  }
   639  
   640  func genTableDefOfComment(comment string) engine.TableDef {
   641  	return &engine.CommentDef{
   642  		Comment: comment,
   643  	}
   644  }
   645  
   646  func genTableDefOfColumn(col column) engine.TableDef {
   647  	var attr engine.Attribute
   648  
   649  	attr.Name = col.name
   650  	attr.ID = uint64(col.num)
   651  	attr.Alg = compress.Lz4
   652  	attr.Comment = col.comment
   653  	attr.IsHidden = col.isHidden == 1
   654  	attr.ClusterBy = col.isClusterBy == 1
   655  	attr.AutoIncrement = col.isAutoIncrement == 1
   656  	attr.Seqnum = col.seqnum
   657  	attr.EnumVlaues = col.enumValues
   658  	if err := types.Decode(col.typ, &attr.Type); err != nil {
   659  		panic(err)
   660  	}
   661  	attr.Default = new(plan.Default)
   662  	if col.hasDef == 1 {
   663  		if err := types.Decode(col.defaultExpr, attr.Default); err != nil {
   664  			panic(err)
   665  		}
   666  	}
   667  	if col.hasUpdate == 1 {
   668  		attr.OnUpdate = new(plan.OnUpdate)
   669  		if err := types.Decode(col.updateExpr, attr.OnUpdate); err != nil {
   670  			panic(err)
   671  		}
   672  	}
   673  	if col.constraintType == catalog.SystemColPKConstraint {
   674  		attr.Primary = true
   675  	}
   676  	return &engine.AttributeDef{Attr: attr}
   677  }
   678  
   679  /*
   680  // getTableDef only return all cols and their index.
   681  func getTableDef(name string, defs []engine.TableDef) *plan.TableDef {
   682  	var cols []*plan.ColDef
   683  
   684  	i := int32(0)
   685  	name2index := make(map[string]int32)
   686  	for _, def := range defs {
   687  		if attr, ok := def.(*engine.AttributeDef); ok {
   688  			name2index[attr.Attr.Name] = i
   689  			cols = append(cols, &plan.ColDef{
   690  				ColId: attr.Attr.ID,
   691  				Name:  attr.Attr.Name,
   692  				Typ: &plan.Type{
   693  					Id:         int32(attr.Attr.Type.Oid),
   694  					Width:      attr.Attr.Type.Width,
   695  					Scale:      attr.Attr.Type.Scale,
   696  					AutoIncr:   attr.Attr.AutoIncrement,
   697  					Enumvalues: attr.Attr.EnumVlaues,
   698  				},
   699  				Primary:  attr.Attr.Primary,
   700  				Default:  attr.Attr.Default,
   701  				OnUpdate: attr.Attr.OnUpdate,
   702  				Comment:  attr.Attr.Comment,
   703  				Hidden:   attr.Attr.IsHidden,
   704  				Seqnum:   uint32(attr.Attr.Seqnum),
   705  			})
   706  			i++
   707  		}
   708  	}
   709  	return &plan.TableDef{
   710  		Name:          name,
   711  		Cols:          cols,
   712  		Name2ColIndex: name2index,
   713  	}
   714  }
   715  */
   716  
   717  // GetSchemaVersion returns the version of table
   718  func (cc *CatalogCache) GetSchemaVersion(name TableKey) *TableVersion {
   719  	return cc.tables.tableGuard.getSchemaVersion(name)
   720  }
   721  
   722  // addTableItem inserts a new table item.
   723  func (c *tableCache) addTableItem(item *TableItem) {
   724  	c.data.Set(item)
   725  }
   726  
   727  func getTableDef(tblItem *TableItem, coldefs []engine.TableDef) *plan.TableDef {
   728  	var clusterByDef *plan.ClusterByDef
   729  	var cols []*plan.ColDef
   730  	var defs []*plan.TableDef_DefType
   731  	var properties []*plan.Property
   732  	var TableType string
   733  	var Createsql string
   734  	var partitionInfo *plan.PartitionByDef
   735  	var viewSql *plan.ViewDef
   736  	var foreignKeys []*plan.ForeignKeyDef
   737  	var primarykey *plan.PrimaryKeyDef
   738  	var indexes []*plan.IndexDef
   739  	var refChildTbls []uint64
   740  
   741  	i := int32(0)
   742  	name2index := make(map[string]int32)
   743  	for _, def := range coldefs {
   744  		if attr, ok := def.(*engine.AttributeDef); ok {
   745  			name2index[attr.Attr.Name] = i
   746  			cols = append(cols, &plan.ColDef{
   747  				ColId: attr.Attr.ID,
   748  				Name:  attr.Attr.Name,
   749  				Typ: plan.Type{
   750  					Id:          int32(attr.Attr.Type.Oid),
   751  					Width:       attr.Attr.Type.Width,
   752  					Scale:       attr.Attr.Type.Scale,
   753  					AutoIncr:    attr.Attr.AutoIncrement,
   754  					Table:       tblItem.Name,
   755  					NotNullable: attr.Attr.Default != nil && !attr.Attr.Default.NullAbility,
   756  					Enumvalues:  attr.Attr.EnumVlaues,
   757  				},
   758  				Primary:   attr.Attr.Primary,
   759  				Default:   attr.Attr.Default,
   760  				OnUpdate:  attr.Attr.OnUpdate,
   761  				Comment:   attr.Attr.Comment,
   762  				ClusterBy: attr.Attr.ClusterBy,
   763  				Hidden:    attr.Attr.IsHidden,
   764  				Seqnum:    uint32(attr.Attr.Seqnum),
   765  			})
   766  			if attr.Attr.ClusterBy {
   767  				clusterByDef = &plan.ClusterByDef{
   768  					Name: attr.Attr.Name,
   769  				}
   770  			}
   771  			i++
   772  		}
   773  	}
   774  
   775  	if tblItem.Comment != "" {
   776  		properties = append(properties, &plan.Property{
   777  			Key:   catalog.SystemRelAttr_Comment,
   778  			Value: tblItem.Comment,
   779  		})
   780  	}
   781  
   782  	if tblItem.Partitioned > 0 {
   783  		p := &plan.PartitionByDef{}
   784  		err := p.UnMarshalPartitionInfo(([]byte)(tblItem.Partition))
   785  		if err != nil {
   786  			//panic(fmt.Sprintf("cannot unmarshal partition metadata information: %s", err))
   787  			return nil
   788  		}
   789  		partitionInfo = p
   790  	}
   791  
   792  	if tblItem.ViewDef != "" {
   793  		viewSql = &plan.ViewDef{
   794  			View: tblItem.ViewDef,
   795  		}
   796  	}
   797  
   798  	if len(tblItem.Constraint) > 0 {
   799  		c := &engine.ConstraintDef{}
   800  		err := c.UnmarshalBinary(tblItem.Constraint)
   801  		if err != nil {
   802  			//panic(fmt.Sprintf("cannot unmarshal table constraint information: %s", err))
   803  			return nil
   804  		}
   805  		for _, ct := range c.Cts {
   806  			switch k := ct.(type) {
   807  			case *engine.IndexDef:
   808  				indexes = k.Indexes
   809  			case *engine.ForeignKeyDef:
   810  				foreignKeys = k.Fkeys
   811  			case *engine.RefChildTableDef:
   812  				refChildTbls = k.Tables
   813  			case *engine.PrimaryKeyDef:
   814  				primarykey = k.Pkey
   815  			case *engine.StreamConfigsDef:
   816  				properties = append(properties, k.Configs...)
   817  			}
   818  		}
   819  	}
   820  
   821  	properties = append(properties, &plan.Property{
   822  		Key:   catalog.SystemRelAttr_Kind,
   823  		Value: tblItem.Kind,
   824  	})
   825  	TableType = tblItem.Kind
   826  
   827  	if tblItem.CreateSql != "" {
   828  		properties = append(properties, &plan.Property{
   829  			Key:   catalog.SystemRelAttr_CreateSQL,
   830  			Value: tblItem.CreateSql,
   831  		})
   832  		Createsql = tblItem.CreateSql
   833  	}
   834  
   835  	if len(properties) > 0 {
   836  		defs = append(defs, &plan.TableDef_DefType{
   837  			Def: &plan.TableDef_DefType_Properties{
   838  				Properties: &plan.PropertiesDef{
   839  					Properties: properties,
   840  				},
   841  			},
   842  		})
   843  	}
   844  
   845  	if primarykey != nil && primarykey.PkeyColName == catalog.CPrimaryKeyColName {
   846  		primarykey.CompPkeyCol = plan2.GetColDefFromTable(cols, catalog.CPrimaryKeyColName)
   847  	}
   848  	if clusterByDef != nil && util.JudgeIsCompositeClusterByColumn(clusterByDef.Name) {
   849  		clusterByDef.CompCbkeyCol = plan2.GetColDefFromTable(cols, clusterByDef.Name)
   850  	}
   851  
   852  	return &plan.TableDef{
   853  		TblId:         tblItem.Id,
   854  		Name:          tblItem.Name,
   855  		Cols:          cols,
   856  		Name2ColIndex: name2index,
   857  		Defs:          defs,
   858  		TableType:     TableType,
   859  		Createsql:     Createsql,
   860  		Pkey:          primarykey,
   861  		ViewSql:       viewSql,
   862  		Partition:     partitionInfo,
   863  		Fkeys:         foreignKeys,
   864  		RefChildTbls:  refChildTbls,
   865  		ClusterBy:     clusterByDef,
   866  		Indexes:       indexes,
   867  		Version:       tblItem.Version,
   868  	}
   869  }