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  }