github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/index_metadata.go (about)

     1  // Copyright 2021 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 colexec
    16  
    17  import (
    18  	"context"
    19  	"strconv"
    20  	"time"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/sql/plan/function"
    23  	"github.com/matrixorigin/matrixone/pkg/txn/client"
    24  
    25  	"github.com/matrixorigin/matrixone/pkg/catalog"
    26  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    27  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    28  	"github.com/matrixorigin/matrixone/pkg/container/types"
    29  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    30  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    31  	"github.com/matrixorigin/matrixone/pkg/vm/engine"
    32  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    33  )
    34  
    35  const (
    36  	ALLOCID_INDEX_KEY = "index_key"
    37  )
    38  const (
    39  	// 'mo_indexes' table
    40  	MO_INDEX_ID          = "id"
    41  	MO_INDEX_TABLE_ID    = "table_id"
    42  	MO_INDEX_DATABASE_ID = "database_id"
    43  	MO_INDEX_NAME        = "name"
    44  	// MO_INDEX_TYPE can have values : unique, primary or multiple.
    45  	// It is better called as MO_INDEX_CATEGORY. But for now, we will keep it as MO_INDEX_TYPE.
    46  	// The INDEX_TYPE in MYSQL has values BTREE, FULLTEXT, HASH, RTREE
    47  	// Ref: https://dev.mysql.com/doc/mysql-infoschema-excerpt/5.7/en/information-schema-statistics-table.html
    48  	MO_INDEX_TYPE                 = "type"
    49  	MO_INDEX_ALGORITHM            = "algo"
    50  	MO_INDEX_ALGORITHM_TABLE_TYPE = "algo_table_type"
    51  	MO_INDEX_ALGORITHM_PARAMS     = "algo_params"
    52  	MO_INDEX_IS_VISIBLE           = "is_visible"
    53  	MO_INDEX_HIDDEN               = "hidden"
    54  	MO_INDEX_COMMENT              = "comment"
    55  	MO_INDEX_OPTIONS              = "options"
    56  	MO_INDEX_COLUMN_NAME          = "column_name"
    57  	MO_INDEX_ORDINAL_POSITION     = "ordinal_position"
    58  	MO_INDEX_TABLE_NAME           = "index_table_name"
    59  	MO_INDEX_PRIKEY               = catalog.CPrimaryKeyColName
    60  )
    61  
    62  // Column type mapping of table 'mo_indexes'
    63  var MO_INDEX_COLTYPE = map[string]types.T{
    64  	MO_INDEX_ID:                   types.T_uint64,
    65  	MO_INDEX_TABLE_ID:             types.T_uint64,
    66  	MO_INDEX_DATABASE_ID:          types.T_uint64,
    67  	MO_INDEX_NAME:                 types.T_varchar,
    68  	MO_INDEX_TYPE:                 types.T_varchar,
    69  	MO_INDEX_ALGORITHM:            types.T_varchar,
    70  	MO_INDEX_ALGORITHM_TABLE_TYPE: types.T_varchar,
    71  	MO_INDEX_ALGORITHM_PARAMS:     types.T_varchar,
    72  	MO_INDEX_IS_VISIBLE:           types.T_int8,
    73  	MO_INDEX_HIDDEN:               types.T_int8,
    74  	MO_INDEX_COMMENT:              types.T_varchar,
    75  	MO_INDEX_COLUMN_NAME:          types.T_varchar,
    76  	MO_INDEX_ORDINAL_POSITION:     types.T_uint32,
    77  	MO_INDEX_OPTIONS:              types.T_text,
    78  	MO_INDEX_TABLE_NAME:           types.T_varchar,
    79  	MO_INDEX_PRIKEY:               types.T_varchar,
    80  }
    81  
    82  const (
    83  	INDEX_TYPE_PRIMARY  = "PRIMARY"
    84  	INDEX_TYPE_UNIQUE   = "UNIQUE"
    85  	INDEX_TYPE_MULTIPLE = "MULTIPLE"
    86  )
    87  
    88  // InsertIndexMetadata :Synchronize the index metadata information of the table to the index metadata table
    89  func InsertIndexMetadata(eg engine.Engine, ctx context.Context, db engine.Database, proc *process.Process, tblName string) error {
    90  	databaseId, err := strconv.ParseUint(db.GetDatabaseId(ctx), 10, 64)
    91  	if err != nil {
    92  		return moerr.NewInternalError(ctx, "The databaseid of '%v' is not a valid number", databaseId)
    93  	}
    94  
    95  	relation, err := db.Relation(ctx, tblName, nil)
    96  	if err != nil {
    97  		return err
    98  	}
    99  	tableId := relation.GetTableID(ctx)
   100  
   101  	tableDefs, err := relation.TableDefs(ctx)
   102  	if err != nil {
   103  		return err
   104  	}
   105  	var ct *engine.ConstraintDef
   106  	for _, def := range tableDefs {
   107  		if constraintDef, ok := def.(*engine.ConstraintDef); ok {
   108  			ct = constraintDef
   109  			break
   110  		}
   111  	}
   112  	if ct == nil {
   113  		return nil
   114  	}
   115  
   116  	hasIndex := false
   117  	for _, constraint := range ct.Cts {
   118  		if _, ok := constraint.(*engine.IndexDef); ok {
   119  			hasIndex = true
   120  			break
   121  		}
   122  		if pkdef, ok := constraint.(*engine.PrimaryKeyDef); ok {
   123  			if pkdef.Pkey.PkeyColName != catalog.FakePrimaryKeyColName {
   124  				hasIndex = true
   125  				break
   126  			}
   127  		}
   128  	}
   129  
   130  	if !hasIndex {
   131  		return nil
   132  	}
   133  
   134  	relIndex, err := GetNewRelation(eg, catalog.MO_CATALOG, catalog.MO_INDEXES, proc.TxnOperator, ctx)
   135  	if err != nil {
   136  		return err
   137  	}
   138  
   139  	indexMetaBatch, err := buildInsertIndexMetaBatch(tableId, databaseId, ct, eg, proc)
   140  	if err != nil {
   141  		return err
   142  	}
   143  	err = relIndex.Write(ctx, indexMetaBatch)
   144  	if err != nil {
   145  		return err
   146  	}
   147  	return nil
   148  }
   149  
   150  // InsertOneIndexMetadata :Synchronize the single index metadata information into the index metadata table
   151  func InsertOneIndexMetadata(eg engine.Engine, ctx context.Context, db engine.Database, proc *process.Process, tblName string, idxdef *plan.IndexDef) error {
   152  	databaseId, err := strconv.ParseUint(db.GetDatabaseId(ctx), 10, 64)
   153  	if err != nil {
   154  		return moerr.NewInternalError(ctx, "The databaseid of '%v' is not a valid number", databaseId)
   155  	}
   156  	relation, err := db.Relation(ctx, tblName, nil)
   157  	if err != nil {
   158  		return err
   159  	}
   160  	tableId := relation.GetTableID(ctx)
   161  	relIndex, err := GetNewRelation(eg, catalog.MO_CATALOG, catalog.MO_INDEXES, proc.TxnOperator, ctx)
   162  	if err != nil {
   163  		return err
   164  	}
   165  
   166  	ct := &engine.ConstraintDef{
   167  		Cts: []engine.Constraint{
   168  			&engine.IndexDef{
   169  				Indexes: []*plan.IndexDef{idxdef},
   170  			},
   171  		},
   172  	}
   173  
   174  	indexMetaBatch, err := buildInsertIndexMetaBatch(tableId, databaseId, ct, eg, proc)
   175  	if err != nil {
   176  		return err
   177  	}
   178  	err = relIndex.Write(ctx, indexMetaBatch)
   179  	if err != nil {
   180  		return err
   181  	}
   182  	return nil
   183  }
   184  
   185  func buildInsertIndexMetaBatch(tableId uint64, databaseId uint64, ct *engine.ConstraintDef, eg engine.Engine, proc *process.Process) (*batch.Batch, error) {
   186  	bat := &batch.Batch{
   187  		Attrs: make([]string, 16),
   188  		Vecs:  make([]*vector.Vector, 16),
   189  		Cnt:   1,
   190  	}
   191  	bat.Attrs[0] = MO_INDEX_ID
   192  	bat.Attrs[1] = MO_INDEX_TABLE_ID
   193  	bat.Attrs[2] = MO_INDEX_DATABASE_ID
   194  	bat.Attrs[3] = MO_INDEX_NAME
   195  	bat.Attrs[4] = MO_INDEX_TYPE
   196  	bat.Attrs[5] = MO_INDEX_ALGORITHM
   197  	bat.Attrs[6] = MO_INDEX_ALGORITHM_TABLE_TYPE
   198  	bat.Attrs[7] = MO_INDEX_ALGORITHM_PARAMS
   199  	bat.Attrs[8] = MO_INDEX_IS_VISIBLE
   200  	bat.Attrs[9] = MO_INDEX_HIDDEN
   201  	bat.Attrs[10] = MO_INDEX_COMMENT
   202  	bat.Attrs[11] = MO_INDEX_COLUMN_NAME
   203  	bat.Attrs[12] = MO_INDEX_ORDINAL_POSITION
   204  	bat.Attrs[13] = MO_INDEX_OPTIONS
   205  	bat.Attrs[14] = MO_INDEX_TABLE_NAME
   206  	bat.Attrs[15] = MO_INDEX_PRIKEY
   207  
   208  	vec_id := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_ID].ToType())
   209  	bat.Vecs[0] = vec_id
   210  
   211  	vec_table_id := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_TABLE_ID].ToType())
   212  	bat.Vecs[1] = vec_table_id
   213  
   214  	vec_database_id := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_DATABASE_ID].ToType())
   215  	bat.Vecs[2] = vec_database_id
   216  
   217  	vec_name := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_NAME].ToType())
   218  	bat.Vecs[3] = vec_name
   219  
   220  	vec_type := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_TYPE].ToType())
   221  	bat.Vecs[4] = vec_type
   222  
   223  	vec_algo := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_ALGORITHM].ToType())
   224  	bat.Vecs[5] = vec_algo
   225  
   226  	vec_algo_table_type := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_ALGORITHM_TABLE_TYPE].ToType())
   227  	bat.Vecs[6] = vec_algo_table_type
   228  
   229  	vec_algo_params := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_ALGORITHM_PARAMS].ToType())
   230  	bat.Vecs[7] = vec_algo_params
   231  
   232  	vec_visible := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_IS_VISIBLE].ToType())
   233  	bat.Vecs[8] = vec_visible
   234  
   235  	vec_hidden := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_HIDDEN].ToType())
   236  	bat.Vecs[9] = vec_hidden
   237  
   238  	vec_comment := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_COMMENT].ToType())
   239  	bat.Vecs[10] = vec_comment
   240  
   241  	vec_column_name := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_COLUMN_NAME].ToType())
   242  	bat.Vecs[11] = vec_column_name
   243  
   244  	vec_ordinal_position := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_ORDINAL_POSITION].ToType())
   245  	bat.Vecs[12] = vec_ordinal_position
   246  
   247  	vec_options := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_OPTIONS].ToType())
   248  	bat.Vecs[13] = vec_options
   249  
   250  	vec_index_table := proc.GetVector(MO_INDEX_COLTYPE[MO_INDEX_TABLE_NAME].ToType())
   251  	bat.Vecs[14] = vec_index_table
   252  
   253  	var indexId uint64
   254  	var err error
   255  	defer func() {
   256  		if err != nil {
   257  			bat.Clean(proc.Mp())
   258  		}
   259  	}()
   260  
   261  	for _, constraint := range ct.Cts {
   262  		switch def := constraint.(type) {
   263  		case *engine.IndexDef:
   264  			for _, index := range def.Indexes {
   265  				ctx, cancelFunc := context.WithTimeout(proc.Ctx, time.Second*30)
   266  
   267  				indexId, err = eg.AllocateIDByKey(ctx, ALLOCID_INDEX_KEY)
   268  				cancelFunc()
   269  				if err != nil {
   270  					return nil, err
   271  				}
   272  
   273  				for i, part := range index.Parts {
   274  					//NOTE: buildInsertIndexMetaBatch function is used in UT only.
   275  					part = catalog.ResolveAlias(part)
   276  					err = vector.AppendFixed(vec_id, indexId, false, proc.Mp())
   277  					if err != nil {
   278  						return nil, err
   279  					}
   280  					err = vector.AppendFixed(vec_table_id, tableId, false, proc.Mp())
   281  					if err != nil {
   282  						return nil, err
   283  					}
   284  					err = vector.AppendFixed(vec_database_id, databaseId, false, proc.Mp())
   285  					if err != nil {
   286  						return nil, err
   287  					}
   288  					err = vector.AppendBytes(vec_name, []byte(index.IndexName), false, proc.Mp())
   289  					if err != nil {
   290  						return nil, err
   291  					}
   292  					if index.Unique {
   293  						err = vector.AppendBytes(vec_type, []byte(INDEX_TYPE_UNIQUE), false, proc.Mp())
   294  					} else {
   295  						err = vector.AppendBytes(vec_type, []byte(INDEX_TYPE_MULTIPLE), false, proc.Mp())
   296  					}
   297  					if err != nil {
   298  						return nil, err
   299  					}
   300  
   301  					if len(index.IndexAlgo) == 0 {
   302  						err = vector.AppendBytes(vec_algo, []byte(""), true, proc.Mp())
   303  					} else {
   304  						err = vector.AppendBytes(vec_algo, []byte(index.IndexAlgo), false, proc.Mp())
   305  					}
   306  					if err != nil {
   307  						return nil, err
   308  					}
   309  
   310  					if len(index.IndexAlgoTableType) == 0 {
   311  						err = vector.AppendBytes(vec_algo_table_type, []byte(""), true, proc.Mp())
   312  					} else {
   313  						err = vector.AppendBytes(vec_algo_table_type, []byte(index.IndexAlgoTableType), false, proc.Mp())
   314  					}
   315  					if err != nil {
   316  						return nil, err
   317  					}
   318  
   319  					if len(index.IndexAlgoParams) == 0 {
   320  						err = vector.AppendBytes(vec_algo_params, []byte(""), true, proc.Mp())
   321  					} else {
   322  						err = vector.AppendBytes(vec_algo_params, []byte(index.IndexAlgoParams), false, proc.Mp())
   323  					}
   324  					if err != nil {
   325  						return nil, err
   326  					}
   327  
   328  					err = vector.AppendFixed(vec_visible, int8(1), false, proc.Mp())
   329  					if err != nil {
   330  						return nil, err
   331  					}
   332  					err = vector.AppendFixed(vec_hidden, int8(0), false, proc.Mp())
   333  					if err != nil {
   334  						return nil, err
   335  					}
   336  					err = vector.AppendBytes(vec_comment, []byte(index.Comment), false, proc.Mp())
   337  					if err != nil {
   338  						return nil, err
   339  					}
   340  					err = vector.AppendBytes(vec_column_name, []byte(part), false, proc.Mp())
   341  					if err != nil {
   342  						return nil, err
   343  					}
   344  					err = vector.AppendFixed(vec_ordinal_position, uint32(i+1), false, proc.Mp())
   345  					if err != nil {
   346  						return nil, err
   347  					}
   348  					err = vector.AppendBytes(vec_options, []byte(""), true, proc.Mp())
   349  					if err != nil {
   350  						return nil, err
   351  					}
   352  					if index.TableExist {
   353  						err = vector.AppendBytes(vec_index_table, []byte(index.IndexTableName), false, proc.Mp())
   354  					} else {
   355  						err = vector.AppendBytes(vec_index_table, []byte(""), true, proc.Mp())
   356  					}
   357  					if err != nil {
   358  						return nil, err
   359  					}
   360  				}
   361  			}
   362  		case *engine.PrimaryKeyDef:
   363  			ctx, cancelFunc := context.WithTimeout(proc.Ctx, time.Second*30)
   364  			defer cancelFunc()
   365  			indexId, err = eg.AllocateIDByKey(ctx, ALLOCID_INDEX_KEY)
   366  			if err != nil {
   367  				return nil, err
   368  			}
   369  			if def.Pkey.PkeyColName != catalog.FakePrimaryKeyColName {
   370  				for i, colName := range def.Pkey.Names {
   371  					err = vector.AppendFixed(vec_id, indexId, false, proc.Mp())
   372  					if err != nil {
   373  						return nil, err
   374  					}
   375  					err = vector.AppendFixed(vec_table_id, tableId, false, proc.Mp())
   376  					if err != nil {
   377  						return nil, err
   378  					}
   379  					err = vector.AppendFixed(vec_database_id, databaseId, false, proc.Mp())
   380  					if err != nil {
   381  						return nil, err
   382  					}
   383  					err = vector.AppendBytes(vec_name, []byte("PRIMARY"), false, proc.Mp())
   384  					if err != nil {
   385  						return nil, err
   386  					}
   387  					err = vector.AppendBytes(vec_type, []byte(INDEX_TYPE_PRIMARY), false, proc.Mp())
   388  					if err != nil {
   389  						return nil, err
   390  					}
   391  
   392  					err = vector.AppendBytes(vec_algo, []byte(""), true, proc.Mp())
   393  					if err != nil {
   394  						return nil, err
   395  					}
   396  					err = vector.AppendBytes(vec_algo_table_type, []byte(""), true, proc.Mp())
   397  					if err != nil {
   398  						return nil, err
   399  					}
   400  					err = vector.AppendBytes(vec_algo_params, []byte(""), true, proc.Mp())
   401  					if err != nil {
   402  						return nil, err
   403  					}
   404  
   405  					err = vector.AppendFixed(vec_visible, int8(1), false, proc.Mp())
   406  					if err != nil {
   407  						return nil, err
   408  					}
   409  					err = vector.AppendFixed(vec_hidden, int8(0), false, proc.Mp())
   410  					if err != nil {
   411  						return nil, err
   412  					}
   413  					err = vector.AppendBytes(vec_comment, []byte(""), false, proc.Mp())
   414  					if err != nil {
   415  						return nil, err
   416  					}
   417  					err = vector.AppendBytes(vec_column_name, []byte(colName), false, proc.Mp())
   418  					if err != nil {
   419  						return nil, err
   420  					}
   421  					err = vector.AppendFixed(vec_ordinal_position, uint32(i+1), false, proc.Mp())
   422  					if err != nil {
   423  						return nil, err
   424  					}
   425  					err = vector.AppendBytes(vec_options, []byte(""), true, proc.Mp())
   426  					if err != nil {
   427  						return nil, err
   428  					}
   429  					err = vector.AppendBytes(vec_index_table, []byte(""), true, proc.Mp())
   430  					if err != nil {
   431  						return nil, err
   432  					}
   433  				}
   434  			}
   435  
   436  		}
   437  	}
   438  
   439  	// processing composite primary key
   440  	var vecPrikey *vector.Vector
   441  	vecPrikey, err = function.RunFunctionDirectly(proc, function.SerialFunctionEncodeID, []*vector.Vector{vec_id, vec_column_name}, vec_id.Length())
   442  	if err != nil {
   443  		return nil, err
   444  	}
   445  	bat.Vecs[12] = vecPrikey
   446  
   447  	bat.SetRowCount(bat.GetVector(0).Length())
   448  	return bat, nil
   449  }
   450  
   451  func GetNewRelation(eg engine.Engine, dbName, tbleName string, txn client.TxnOperator, ctx context.Context) (engine.Relation, error) {
   452  	dbHandler, err := eg.Database(ctx, dbName, txn)
   453  	if err != nil {
   454  		return nil, err
   455  	}
   456  	tableHandler, err := dbHandler.Relation(ctx, tbleName, nil)
   457  	if err != nil {
   458  		return nil, err
   459  	}
   460  	return tableHandler, nil
   461  }