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 }