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 }