github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/disttae/database.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 disttae 16 17 import ( 18 "context" 19 "strconv" 20 "strings" 21 22 "github.com/matrixorigin/matrixone/pkg/catalog" 23 "github.com/matrixorigin/matrixone/pkg/common/moerr" 24 "github.com/matrixorigin/matrixone/pkg/vm/engine" 25 "github.com/matrixorigin/matrixone/pkg/vm/engine/disttae/cache" 26 ) 27 28 var _ engine.Database = new(database) 29 30 func (db *database) Relations(ctx context.Context) ([]string, error) { 31 var rels []string 32 33 db.txn.createMap.Range(func(k, _ any) bool { 34 key := k.(tableKey) 35 if key.databaseId == db.databaseId { 36 rels = append(rels, key.name) 37 } 38 return true 39 }) 40 tbls, _ := db.txn.catalog.Tables(getAccountId(ctx), db.databaseId, db.txn.meta.SnapshotTS) 41 rels = append(rels, tbls...) 42 return rels, nil 43 } 44 45 func (db *database) getTableNameById(ctx context.Context, id uint64) string { 46 tblName := "" 47 db.txn.createMap.Range(func(k, _ any) bool { 48 key := k.(tableKey) 49 if key.databaseId == db.databaseId && key.tableId == id { 50 tblName = key.name 51 return false 52 } 53 return true 54 }) 55 56 if tblName == "" { 57 tbls, tblIds := db.txn.catalog.Tables(getAccountId(ctx), db.databaseId, db.txn.meta.SnapshotTS) 58 for idx, tblId := range tblIds { 59 if tblId == id { 60 tblName = tbls[idx] 61 break 62 } 63 } 64 } 65 return tblName 66 } 67 68 func (db *database) getRelationById(ctx context.Context, id uint64) (string, engine.Relation, error) { 69 tblName := db.getTableNameById(ctx, id) 70 if tblName == "" { 71 return "", nil, moerr.NewInternalError(ctx, "can not find table by id %d", id) 72 } 73 rel, err := db.Relation(ctx, tblName) 74 return tblName, rel, err 75 } 76 77 func (db *database) Relation(ctx context.Context, name string) (engine.Relation, error) { 78 if v, ok := db.txn.tableMap.Load(genTableKey(ctx, name, db.databaseId)); ok { 79 return v.(*table), nil 80 } 81 if v, ok := db.txn.createMap.Load(genTableKey(ctx, name, db.databaseId)); ok { 82 return v.(*table), nil 83 } 84 if db.databaseName == "mo_catalog" { 85 if name == catalog.MO_DATABASE { 86 id := uint64(catalog.MO_DATABASE_ID) 87 defs := catalog.MoDatabaseTableDefs 88 return db.openSysTable(genTableKey(ctx, name, db.databaseId), id, name, defs), nil 89 } 90 if name == catalog.MO_TABLES { 91 id := uint64(catalog.MO_TABLES_ID) 92 defs := catalog.MoTablesTableDefs 93 return db.openSysTable(genTableKey(ctx, name, db.databaseId), id, name, defs), nil 94 } 95 if name == catalog.MO_COLUMNS { 96 id := uint64(catalog.MO_COLUMNS_ID) 97 defs := catalog.MoColumnsTableDefs 98 return db.openSysTable(genTableKey(ctx, name, db.databaseId), id, name, defs), nil 99 100 } 101 } 102 key := &cache.TableItem{ 103 Name: name, 104 DatabaseId: db.databaseId, 105 AccountId: getAccountId(ctx), 106 Ts: db.txn.meta.SnapshotTS, 107 } 108 if ok := db.txn.catalog.GetTable(key); !ok { 109 return nil, moerr.NewParseError(ctx, "table %q does not exist", name) 110 } 111 parts := db.txn.db.getPartitions(db.databaseId, key.Id) 112 tbl := &table{ 113 db: db, 114 parts: parts, 115 tableId: key.Id, 116 tableName: key.Name, 117 defs: key.Defs, 118 tableDef: key.TableDef, 119 primaryIdx: key.PrimaryIdx, 120 clusterByIdx: key.ClusterByIdx, 121 relKind: key.Kind, 122 viewdef: key.ViewDef, 123 comment: key.Comment, 124 partition: key.Partition, 125 createSql: key.CreateSql, 126 constraint: key.Constraint, 127 } 128 columnLength := len(key.TableDef.Cols) - 1 //we use this data to fetch zonemap, but row_id has no zonemap 129 meta, err := db.txn.getTableMeta(ctx, db.databaseId, genMetaTableName(key.Id), 130 true, columnLength, true) 131 if err != nil { 132 return nil, err 133 } 134 tbl.meta = meta 135 tbl.updated = false 136 db.txn.tableMap.Store(genTableKey(ctx, name, db.databaseId), tbl) 137 return tbl, nil 138 } 139 140 func (db *database) Delete(ctx context.Context, name string) error { 141 var id uint64 142 143 k := genTableKey(ctx, name, db.databaseId) 144 if _, ok := db.txn.createMap.Load(k); ok { 145 db.txn.createMap.Delete(k) 146 return nil 147 } else if v, ok := db.txn.tableMap.Load(k); ok { 148 id = v.(*table).tableId 149 db.txn.tableMap.Delete(k) 150 } else { 151 key := &cache.TableItem{ 152 Name: name, 153 DatabaseId: db.databaseId, 154 AccountId: getAccountId(ctx), 155 Ts: db.txn.meta.SnapshotTS, 156 } 157 if ok := db.txn.catalog.GetTable(key); !ok { 158 return moerr.GetOkExpectedEOB() 159 } 160 id = key.Id 161 } 162 bat, err := genDropTableTuple(id, db.databaseId, name, db.databaseName, db.txn.proc.Mp()) 163 if err != nil { 164 return err 165 } 166 if err := db.txn.WriteBatch(DELETE, catalog.MO_CATALOG_ID, catalog.MO_TABLES_ID, 167 catalog.MO_CATALOG, catalog.MO_TABLES, bat, db.txn.dnStores[0], -1); err != nil { 168 return err 169 } 170 return nil 171 } 172 173 func (db *database) Truncate(ctx context.Context, name string) (uint64, error) { 174 var oldId uint64 175 176 newId, err := db.txn.allocateID(ctx) 177 if err != nil { 178 return 0, err 179 } 180 k := genTableKey(ctx, name, db.databaseId) 181 if v, ok := db.txn.createMap.Load(k); ok { 182 oldId = v.(*table).tableId 183 v.(*table).tableId = newId 184 } else if v, ok := db.txn.tableMap.Load(k); ok { 185 oldId = v.(*table).tableId 186 } else { 187 key := &cache.TableItem{ 188 Name: name, 189 DatabaseId: db.databaseId, 190 AccountId: getAccountId(ctx), 191 Ts: db.txn.meta.SnapshotTS, 192 } 193 if ok := db.txn.catalog.GetTable(key); !ok { 194 return 0, moerr.GetOkExpectedEOB() 195 } 196 oldId = key.Id 197 } 198 bat, err := genTruncateTableTuple(newId, db.databaseId, 199 genMetaTableName(oldId)+name, db.databaseName, db.txn.proc.Mp()) 200 if err != nil { 201 return 0, err 202 } 203 for i := range db.txn.dnStores { 204 if err := db.txn.WriteBatch(DELETE, catalog.MO_CATALOG_ID, catalog.MO_TABLES_ID, 205 catalog.MO_CATALOG, catalog.MO_TABLES, bat, db.txn.dnStores[i], -1); err != nil { 206 return 0, err 207 } 208 } 209 return newId, nil 210 } 211 212 func (db *database) GetDatabaseId(ctx context.Context) string { 213 return strconv.FormatUint(db.databaseId, 10) 214 } 215 216 func (db *database) Create(ctx context.Context, name string, defs []engine.TableDef) error { 217 comment := getTableComment(defs) 218 accountId, userId, roleId := getAccessInfo(ctx) 219 tableId, err := db.txn.allocateID(ctx) 220 if err != nil { 221 return err 222 } 223 tbl := new(table) 224 { 225 for _, def := range defs { // copy from tae 226 switch defVal := def.(type) { 227 case *engine.PropertiesDef: 228 for _, property := range defVal.Properties { 229 switch strings.ToLower(property.Key) { 230 case catalog.SystemRelAttr_Comment: // Watch priority over commentDef 231 tbl.comment = property.Value 232 case catalog.SystemRelAttr_Kind: 233 tbl.relKind = property.Value 234 case catalog.SystemRelAttr_CreateSQL: 235 tbl.createSql = property.Value // I don't trust this information. 236 default: 237 } 238 } 239 case *engine.ViewDef: 240 tbl.viewdef = defVal.View 241 case *engine.PartitionDef: 242 tbl.partition = defVal.Partition 243 case *engine.ConstraintDef: 244 tbl.constraint, err = defVal.MarshalBinary() 245 if err != nil { 246 return err 247 } 248 } 249 } 250 } 251 cols, err := genColumns(accountId, name, db.databaseName, tableId, db.databaseId, defs) 252 if err != nil { 253 return err 254 } 255 { 256 sql := getSql(ctx) 257 bat, err := genCreateTableTuple(tbl, sql, accountId, userId, roleId, name, 258 tableId, db.databaseId, db.databaseName, comment, db.txn.proc.Mp()) 259 if err != nil { 260 return err 261 } 262 if err := db.txn.WriteBatch(INSERT, catalog.MO_CATALOG_ID, catalog.MO_TABLES_ID, 263 catalog.MO_CATALOG, catalog.MO_TABLES, bat, db.txn.dnStores[0], -1); err != nil { 264 return err 265 } 266 } 267 tbl.primaryIdx = -1 268 tbl.clusterByIdx = -1 269 for i, col := range cols { 270 bat, err := genCreateColumnTuple(col, db.txn.proc.Mp()) 271 if err != nil { 272 return err 273 } 274 if err := db.txn.WriteBatch(INSERT, catalog.MO_CATALOG_ID, catalog.MO_COLUMNS_ID, 275 catalog.MO_CATALOG, catalog.MO_COLUMNS, bat, db.txn.dnStores[0], -1); err != nil { 276 return err 277 } 278 if col.constraintType == catalog.SystemColPKConstraint { 279 tbl.primaryIdx = i 280 } 281 if col.isClusterBy == 1 { 282 tbl.clusterByIdx = i 283 } 284 } 285 tbl.db = db 286 tbl.defs = defs 287 tbl.tableName = name 288 tbl.tableId = tableId 289 tbl.parts = db.txn.db.getPartitions(db.databaseId, tableId) 290 tbl.getTableDef() 291 db.txn.createMap.Store(genTableKey(ctx, name, db.databaseId), tbl) 292 return nil 293 } 294 295 func (db *database) openSysTable(key tableKey, id uint64, name string, 296 defs []engine.TableDef) engine.Relation { 297 parts := db.txn.db.getPartitions(db.databaseId, id) 298 tbl := &table{ 299 db: db, 300 tableId: id, 301 tableName: name, 302 defs: defs, 303 parts: parts, 304 primaryIdx: -1, 305 clusterByIdx: -1, 306 } 307 tbl.getTableDef() 308 return tbl 309 }