github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/catalog/schema.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 catalog 16 17 import ( 18 "bytes" 19 "encoding/json" 20 "fmt" 21 "io" 22 "sort" 23 "strings" 24 "time" 25 26 pkgcatalog "github.com/matrixorigin/matrixone/pkg/catalog" 27 "github.com/matrixorigin/matrixone/pkg/common/moerr" 28 "github.com/matrixorigin/matrixone/pkg/container/types" 29 "github.com/matrixorigin/matrixone/pkg/logutil" 30 "github.com/matrixorigin/matrixone/pkg/objectio" 31 apipb "github.com/matrixorigin/matrixone/pkg/pb/api" 32 "github.com/matrixorigin/matrixone/pkg/pb/plan" 33 "github.com/tidwall/pretty" 34 35 "github.com/matrixorigin/matrixone/pkg/container/vector" 36 "github.com/matrixorigin/matrixone/pkg/vm/engine" 37 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" 38 ) 39 40 func i82bool(v int8) bool { 41 return v == 1 42 } 43 44 func IsFakePkName(name string) bool { 45 return name == pkgcatalog.FakePrimaryKeyColName 46 } 47 48 type ColDef struct { 49 Name string 50 Idx int // indicates its position in all coldefs 51 SeqNum uint16 // 52 Type types.Type 53 Hidden bool // Hidden Column is generated by compute layer, keep hidden from user 54 PhyAddr bool // PhyAddr Column is generated by tae as rowid 55 NullAbility bool 56 AutoIncrement bool 57 Primary bool 58 SortIdx int8 // indicates its position in all sort keys 59 SortKey bool 60 Comment string 61 ClusterBy bool 62 FakePK bool // TODO: use column.flag instead of column.fakepk 63 Default []byte 64 OnUpdate []byte 65 EnumValues string 66 } 67 68 func (def *ColDef) GetName() string { return def.Name } 69 func (def *ColDef) GetType() types.Type { return def.Type } 70 71 func (def *ColDef) Nullable() bool { return def.NullAbility } 72 func (def *ColDef) IsHidden() bool { return def.Hidden } 73 func (def *ColDef) IsPhyAddr() bool { return def.PhyAddr } 74 func (def *ColDef) IsPrimary() bool { return def.Primary } 75 func (def *ColDef) IsRealPrimary() bool { return def.Primary && !def.FakePK } 76 func (def *ColDef) IsAutoIncrement() bool { return def.AutoIncrement } 77 func (def *ColDef) IsSortKey() bool { return def.SortKey } 78 func (def *ColDef) IsClusterBy() bool { return def.ClusterBy } 79 80 type SortKey struct { 81 Defs []*ColDef 82 search map[int]int 83 isPrimary bool 84 } 85 86 func NewSortKey() *SortKey { 87 return &SortKey{ 88 Defs: make([]*ColDef, 0), 89 search: make(map[int]int), 90 } 91 } 92 93 func (cpk *SortKey) AddDef(def *ColDef) (ok bool) { 94 _, found := cpk.search[def.Idx] 95 if found { 96 return false 97 } 98 if def.IsPrimary() { 99 cpk.isPrimary = true 100 } 101 cpk.Defs = append(cpk.Defs, def) 102 sort.Slice(cpk.Defs, func(i, j int) bool { return cpk.Defs[i].SortIdx < cpk.Defs[j].SortIdx }) 103 cpk.search[def.Idx] = int(def.SortIdx) 104 return true 105 } 106 107 func (cpk *SortKey) IsPrimary() bool { return cpk.isPrimary } 108 func (cpk *SortKey) Size() int { return len(cpk.Defs) } 109 func (cpk *SortKey) GetDef(pos int) *ColDef { return cpk.Defs[pos] } 110 func (cpk *SortKey) HasColumn(idx int) (found bool) { _, found = cpk.search[idx]; return } 111 func (cpk *SortKey) GetSingleIdx() int { return cpk.Defs[0].Idx } 112 113 type Schema struct { 114 Version uint32 115 CatalogVersion uint32 116 AcInfo accessInfo 117 Name string 118 ColDefs []*ColDef 119 Comment string 120 Partitioned int8 // 1: the table has partitions ; 0: no partition 121 Partition string // the info about partitions when the table has partitions 122 Relkind string 123 Createsql string 124 View string 125 Constraint []byte 126 127 // do not send to cn 128 BlockMaxRows uint32 129 // for aobj, there're at most one blk 130 ObjectMaxBlocks uint16 131 Extra *apipb.SchemaExtra 132 133 // do not write down, reconstruct them when reading 134 NameMap map[string]int // name -> logical idx 135 SeqnumMap map[uint16]int // seqnum -> logical idx 136 SortKey *SortKey 137 PhyAddrKey *ColDef 138 139 isSecondaryIndexTable bool 140 } 141 142 func NewEmptySchema(name string) *Schema { 143 return &Schema{ 144 Name: name, 145 ColDefs: make([]*ColDef, 0), 146 NameMap: make(map[string]int), 147 SeqnumMap: make(map[uint16]int), 148 Extra: &apipb.SchemaExtra{}, 149 } 150 } 151 152 func (s *Schema) Clone() *Schema { 153 buf, err := s.Marshal() 154 if err != nil { 155 panic(err) 156 } 157 ns := NewEmptySchema(s.Name) 158 r := bytes.NewBuffer(buf) 159 if _, err = ns.ReadFromWithVersion(r, IOET_WALTxnCommand_Table_CurrVer); err != nil { 160 panic(err) 161 } 162 return ns 163 } 164 165 func (s *Schema) IsSecondaryIndexTable() bool { 166 return s.isSecondaryIndexTable 167 } 168 169 // ApplyAlterTable modify the schema in place. Unless you know what you are doing, it is 170 // recommended to close schema first and then apply alter table. 171 func (s *Schema) ApplyAlterTable(req *apipb.AlterTableReq) error { 172 switch req.Kind { 173 case apipb.AlterKind_UpdatePolicy: 174 p := req.GetUpdatePolicy() 175 s.Extra.MaxOsizeMergedObj = p.GetMaxOsizeMergedObj() 176 s.Extra.MinOsizeQuailifed = p.GetMinOsizeQuailifed() 177 s.Extra.MaxObjOnerun = p.GetMaxObjOnerun() 178 s.Extra.MinCnMergeSize = p.GetMinCnMergeSize() 179 s.Extra.Hints = p.GetHints() 180 case apipb.AlterKind_UpdateConstraint: 181 s.Constraint = req.GetUpdateCstr().GetConstraints() 182 case apipb.AlterKind_UpdateComment: 183 s.Comment = req.GetUpdateComment().GetComment() 184 case apipb.AlterKind_RenameColumn: 185 rename := req.GetRenameCol() 186 var targetCol *ColDef 187 for _, def := range s.ColDefs { 188 if def.Name == rename.NewName { 189 return moerr.NewInternalErrorNoCtx("duplicate column %q", def.Name) 190 } 191 if def.Name == rename.OldName { 192 targetCol = def 193 } 194 } 195 if targetCol == nil { 196 return moerr.NewInternalErrorNoCtx("column %q not found", rename.OldName) 197 } 198 if targetCol.SeqNum != uint16(rename.SequenceNum) { 199 return moerr.NewInternalErrorNoCtx("unmatched seqnumn: %d != %d", targetCol.SeqNum, rename.SequenceNum) 200 } 201 targetCol.Name = rename.NewName 202 // a -> b, z -> a, m -> z 203 // only m column deletion should be sent to cn. a and z can be seen as update according to pk, <tid-colname> 204 s.Extra.DroppedAttrs = append(s.Extra.DroppedAttrs, rename.OldName) 205 s.removeDroppedName(rename.NewName) 206 logutil.Infof("[Alter] rename column %s %s %d", rename.OldName, rename.NewName, targetCol.SeqNum) 207 case apipb.AlterKind_AddColumn: 208 add := req.GetAddColumn() 209 logutil.Infof("[Alter] add column %s(%s)@%d", add.Column.Name, types.T(add.Column.Typ.Id), add.InsertPosition) 210 logicalIdx := int(add.InsertPosition) 211 // assume there is a rowid column at the end when alter normal table 212 if logicalIdx < 0 || logicalIdx >= len(s.ColDefs)-1 { 213 logicalIdx = len(s.ColDefs) - 1 214 } 215 216 newcol := colDefFromPlan(add.Column, logicalIdx, uint16(s.Extra.NextColSeqnum)) 217 s.NameMap[newcol.Name] = logicalIdx 218 s.SeqnumMap[newcol.SeqNum] = logicalIdx 219 220 // pending list has at least a rowid column 221 fixed, pending := s.ColDefs[:logicalIdx], s.ColDefs[logicalIdx:] 222 s.ColDefs = make([]*ColDef, 0, len(s.ColDefs)+1) 223 s.ColDefs = append(s.ColDefs, fixed...) 224 s.ColDefs = append(s.ColDefs, newcol) 225 for _, col := range pending { 226 col.Idx = len(s.ColDefs) 227 s.NameMap[col.Name] = col.Idx 228 s.ColDefs = append(s.ColDefs, col) 229 } 230 231 s.Extra.ColumnChanged = true 232 s.removeDroppedName(newcol.Name) 233 s.Extra.NextColSeqnum += 1 234 return s.Finalize(true) // rebuild sortkey 235 case apipb.AlterKind_DropColumn: 236 drop := req.GetDropColumn() 237 coldef := s.ColDefs[drop.LogicalIdx] 238 if coldef.SeqNum != uint16(drop.SequenceNum) { 239 return moerr.NewInternalErrorNoCtx("unmatched idx and seqnumn") 240 } 241 if coldef.IsAutoIncrement() || coldef.IsClusterBy() || coldef.IsPrimary() || coldef.IsPhyAddr() { 242 return moerr.NewInternalErrorNoCtx("drop a column with constraint") 243 } 244 logutil.Infof("[Alter] drop column %s %d %d", coldef.Name, coldef.Idx, coldef.SeqNum) 245 delete(s.NameMap, coldef.Name) 246 delete(s.SeqnumMap, coldef.SeqNum) 247 fixed, pending := s.ColDefs[:coldef.Idx], s.ColDefs[coldef.Idx+1:] 248 s.ColDefs = fixed 249 for _, col := range pending { 250 col.Idx = len(s.ColDefs) 251 s.NameMap[col.Name] = col.Idx 252 s.ColDefs = append(s.ColDefs, col) 253 } 254 s.Extra.DroppedAttrs = append(s.Extra.DroppedAttrs, coldef.Name) 255 s.Extra.ColumnChanged = true 256 return s.Finalize(true) 257 case apipb.AlterKind_RenameTable: 258 rename := req.GetRenameTable() 259 if rename.OldName != s.Name { 260 return moerr.NewInternalErrorNoCtx("unmatched old schema name") 261 } 262 if s.Extra.OldName == "" { 263 s.Extra.OldName = s.Name 264 } 265 logutil.Infof("[Alter] rename table %s -> %s", s.Name, rename.NewName) 266 s.Name = rename.NewName 267 case apipb.AlterKind_AddPartition: 268 newPartitionDef := req.GetAddPartition().GetPartitionDef() 269 bytes, err := newPartitionDef.MarshalPartitionInfo() 270 if err != nil { 271 return err 272 } 273 s.Partition = string(bytes) 274 default: 275 return moerr.NewNYINoCtx("unsupported alter kind: %v", req.Kind) 276 } 277 return nil 278 } 279 280 func (s *Schema) EstimateRowSize() (size int) { 281 for _, col := range s.ColDefs { 282 size += col.Type.TypeSize() 283 } 284 return 285 } 286 287 func (s *Schema) IsSameColumns(other *Schema) bool { 288 return s.Extra.NextColSeqnum == other.Extra.NextColSeqnum && 289 len(s.ColDefs) == len(other.ColDefs) 290 } 291 292 func (s *Schema) removeDroppedName(name string) { 293 idx := -1 294 for i, s := range s.Extra.DroppedAttrs { 295 if s == name { 296 idx = i 297 } 298 } 299 if idx >= 0 { 300 s.Extra.DroppedAttrs = append(s.Extra.DroppedAttrs[:idx], s.Extra.DroppedAttrs[idx+1:]...) 301 } 302 } 303 304 func (s *Schema) HasPK() bool { return s.SortKey != nil && s.SortKey.IsPrimary() } 305 func (s *Schema) HasSortKey() bool { return s.SortKey != nil } 306 307 // GetSingleSortKey should be call only if IsSinglePK is checked 308 func (s *Schema) GetSingleSortKey() *ColDef { return s.SortKey.Defs[0] } 309 func (s *Schema) GetSingleSortKeyIdx() int { return s.SortKey.Defs[0].Idx } 310 func (s *Schema) GetSingleSortKeyType() types.Type { return s.GetSingleSortKey().Type } 311 312 // Can't identify fake pk with column.flag. Column.flag is not ready in 0.8.0. 313 // TODO: Use column.flag instead of column.name to idntify fake pk. 314 func (s *Schema) getFakePrimaryKey() *ColDef { 315 idx, ok := s.NameMap[pkgcatalog.FakePrimaryKeyColName] 316 if !ok { 317 // should just call logutil.Fatal 318 logutil.Debugf("fake primary key not existed: %v", s.String()) 319 panic("fake primary key not existed") 320 } 321 return s.ColDefs[idx] 322 } 323 324 // GetPrimaryKey gets the primary key, including fake primary key. 325 func (s *Schema) GetPrimaryKey() *ColDef { 326 if s.HasPK() { 327 return s.ColDefs[s.SortKey.GetSingleIdx()] 328 } 329 return s.getFakePrimaryKey() 330 } 331 332 func (s *Schema) MustGetExtraBytes() []byte { 333 data, err := s.Extra.Marshal() 334 if err != nil { 335 panic(err) 336 } 337 return data 338 } 339 340 func (s *Schema) MustRestoreExtra(data []byte) { 341 s.Extra = &apipb.SchemaExtra{} 342 if err := s.Extra.Unmarshal(data); err != nil { 343 panic(err) 344 } 345 } 346 347 func (s *Schema) ReadFromWithVersion(r io.Reader, ver uint16) (n int64, err error) { 348 var sn2 int 349 if sn2, err = r.Read(types.EncodeUint32(&s.BlockMaxRows)); err != nil { 350 return 351 } 352 n += int64(sn2) 353 if sn2, err = r.Read(types.EncodeUint16(&s.ObjectMaxBlocks)); err != nil { 354 return 355 } 356 n += int64(sn2) 357 if sn2, err = r.Read(types.EncodeUint32(&s.Version)); err != nil { 358 return 359 } 360 n += int64(sn2) 361 362 if ver <= IOET_WALTxnCommand_Table_V1 { 363 s.CatalogVersion = pkgcatalog.CatalogVersion_V1 364 } else { 365 if sn2, err = r.Read(types.EncodeUint32(&s.CatalogVersion)); err != nil { 366 return 367 } 368 n += int64(sn2) 369 } 370 371 var sn int64 372 if sn, err = s.AcInfo.ReadFrom(r); err != nil { 373 return 374 } 375 n += sn 376 if s.Name, sn, err = objectio.ReadString(r); err != nil { 377 return 378 } 379 n += sn 380 if s.Comment, sn, err = objectio.ReadString(r); err != nil { 381 return 382 } 383 n += sn 384 if _, err = r.Read(types.EncodeInt8(&s.Partitioned)); err != nil { 385 return 386 } 387 n += 1 388 if s.Partition, sn, err = objectio.ReadString(r); err != nil { 389 return 390 } 391 n += sn 392 if s.Relkind, sn, err = objectio.ReadString(r); err != nil { 393 return 394 } 395 n += sn 396 if s.Createsql, sn, err = objectio.ReadString(r); err != nil { 397 return 398 } 399 n += sn 400 401 if s.View, sn, err = objectio.ReadString(r); err != nil { 402 return 403 } 404 n += sn 405 if s.Constraint, sn, err = objectio.ReadBytes(r); err != nil { 406 return 407 } 408 n += sn 409 extraData, sn, err := objectio.ReadBytes(r) 410 if err != nil { 411 return 412 } 413 s.MustRestoreExtra(extraData) 414 n += sn 415 colCnt := uint16(0) 416 if sn2, err = r.Read(types.EncodeUint16(&colCnt)); err != nil { 417 return 418 } 419 n += int64(sn2) 420 colBuf := make([]byte, types.TSize) 421 for i := uint16(0); i < colCnt; i++ { 422 def := new(ColDef) 423 if sn2, err = r.Read(types.EncodeUint16(&def.SeqNum)); err != nil { 424 return 425 } 426 n += int64(sn2) 427 if _, err = r.Read(colBuf); err != nil { 428 return 429 } 430 n += int64(types.TSize) 431 def.Type = types.DecodeType(colBuf) 432 if def.Name, sn, err = objectio.ReadString(r); err != nil { 433 return 434 } 435 n += sn 436 if def.Comment, sn, err = objectio.ReadString(r); err != nil { 437 return 438 } 439 n += sn 440 if sn2, err = r.Read(types.EncodeBool(&def.NullAbility)); err != nil { 441 return 442 } 443 n += int64(sn2) 444 if sn2, err = r.Read(types.EncodeBool(&def.Hidden)); err != nil { 445 return 446 } 447 n += int64(sn2) 448 if sn2, err = r.Read(types.EncodeBool(&def.PhyAddr)); err != nil { 449 return 450 } 451 n += int64(sn2) 452 if sn2, err = r.Read(types.EncodeBool(&def.AutoIncrement)); err != nil { 453 return 454 } 455 n += int64(sn2) 456 if sn2, err = r.Read(types.EncodeInt8(&def.SortIdx)); err != nil { 457 return 458 } 459 n += int64(sn2) 460 if sn2, err = r.Read(types.EncodeBool(&def.Primary)); err != nil { 461 return 462 } 463 n += int64(sn2) 464 if sn2, err = r.Read(types.EncodeBool(&def.SortKey)); err != nil { 465 return 466 } 467 n += int64(sn2) 468 if sn2, err = r.Read(types.EncodeBool(&def.ClusterBy)); err != nil { 469 return 470 } 471 n += int64(sn2) 472 if def.Default, sn, err = objectio.ReadBytes(r); err != nil { 473 return 474 } 475 n += sn 476 if def.OnUpdate, sn, err = objectio.ReadBytes(r); err != nil { 477 return 478 } 479 n += sn 480 if ver <= IOET_WALTxnCommand_Table_V2 { 481 def.EnumValues = "" 482 } else { 483 if def.EnumValues, sn, err = objectio.ReadString(r); err != nil { 484 return 485 } 486 n += sn 487 } 488 if err = s.AppendColDef(def); err != nil { 489 return 490 } 491 } 492 err = s.Finalize(true) 493 return 494 } 495 496 func (s *Schema) Marshal() (buf []byte, err error) { 497 var w bytes.Buffer 498 if _, err = w.Write(types.EncodeUint32(&s.BlockMaxRows)); err != nil { 499 return 500 } 501 if _, err = w.Write(types.EncodeUint16(&s.ObjectMaxBlocks)); err != nil { 502 return 503 } 504 if _, err = w.Write(types.EncodeUint32(&s.Version)); err != nil { 505 return 506 } 507 if _, err = w.Write(types.EncodeUint32(&s.CatalogVersion)); err != nil { 508 return 509 } 510 if _, err = s.AcInfo.WriteTo(&w); err != nil { 511 return 512 } 513 if _, err = objectio.WriteString(s.Name, &w); err != nil { 514 return 515 } 516 if _, err = objectio.WriteString(s.Comment, &w); err != nil { 517 return 518 } 519 if _, err = w.Write(types.EncodeInt8(&s.Partitioned)); err != nil { 520 return 521 } 522 if _, err = objectio.WriteString(s.Partition, &w); err != nil { 523 return 524 } 525 if _, err = objectio.WriteString(s.Relkind, &w); err != nil { 526 return 527 } 528 if _, err = objectio.WriteString(s.Createsql, &w); err != nil { 529 return 530 } 531 if _, err = objectio.WriteString(s.View, &w); err != nil { 532 return 533 } 534 if _, err = objectio.WriteBytes(s.Constraint, &w); err != nil { 535 return 536 } 537 if _, err = objectio.WriteBytes(s.MustGetExtraBytes(), &w); err != nil { 538 return 539 } 540 length := uint16(len(s.ColDefs)) 541 if _, err = w.Write(types.EncodeUint16(&length)); err != nil { 542 return 543 } 544 for _, def := range s.ColDefs { 545 if _, err = w.Write(types.EncodeUint16(&def.SeqNum)); err != nil { 546 return 547 } 548 if _, err = w.Write(types.EncodeType(&def.Type)); err != nil { 549 return 550 } 551 if _, err = objectio.WriteString(def.Name, &w); err != nil { 552 return 553 } 554 if _, err = objectio.WriteString(def.Comment, &w); err != nil { 555 return 556 } 557 if _, err = w.Write(types.EncodeBool(&def.NullAbility)); err != nil { 558 return 559 } 560 if _, err = w.Write(types.EncodeBool(&def.Hidden)); err != nil { 561 return 562 } 563 if _, err = w.Write(types.EncodeBool(&def.PhyAddr)); err != nil { 564 return 565 } 566 if _, err = w.Write(types.EncodeBool(&def.AutoIncrement)); err != nil { 567 return 568 } 569 if _, err = w.Write(types.EncodeInt8(&def.SortIdx)); err != nil { 570 return 571 } 572 if _, err = w.Write(types.EncodeBool(&def.Primary)); err != nil { 573 return 574 } 575 if _, err = w.Write(types.EncodeBool(&def.SortKey)); err != nil { 576 return 577 } 578 if _, err = w.Write(types.EncodeBool(&def.ClusterBy)); err != nil { 579 return 580 } 581 if _, err = objectio.WriteBytes(def.Default, &w); err != nil { 582 return 583 } 584 if _, err = objectio.WriteBytes(def.OnUpdate, &w); err != nil { 585 return 586 } 587 588 if _, err = objectio.WriteString(def.EnumValues, &w); err != nil { 589 return 590 } 591 } 592 buf = w.Bytes() 593 return 594 } 595 596 func (s *Schema) ReadFromBatch(bat *containers.Batch, offset int, targetTid uint64) (next int) { 597 nameVec := bat.GetVectorByName(pkgcatalog.SystemColAttr_RelName) 598 tidVec := bat.GetVectorByName(pkgcatalog.SystemColAttr_RelID) 599 seenRowid := false 600 for { 601 if offset >= nameVec.Length() { 602 break 603 } 604 name := string(nameVec.Get(offset).([]byte)) 605 id := tidVec.Get(offset).(uint64) 606 // every schema has 1 rowid column as last column, if have one, break 607 if name != s.Name || targetTid != id || seenRowid { 608 break 609 } 610 def := new(ColDef) 611 def.Name = string(bat.GetVectorByName((pkgcatalog.SystemColAttr_Name)).Get(offset).([]byte)) 612 data := bat.GetVectorByName((pkgcatalog.SystemColAttr_Type)).Get(offset).([]byte) 613 types.Decode(data, &def.Type) 614 nullable := bat.GetVectorByName((pkgcatalog.SystemColAttr_NullAbility)).Get(offset).(int8) 615 def.NullAbility = !i82bool(nullable) 616 isHidden := bat.GetVectorByName((pkgcatalog.SystemColAttr_IsHidden)).Get(offset).(int8) 617 def.Hidden = i82bool(isHidden) 618 isClusterBy := bat.GetVectorByName((pkgcatalog.SystemColAttr_IsClusterBy)).Get(offset).(int8) 619 def.ClusterBy = i82bool(isClusterBy) 620 if def.ClusterBy { 621 def.SortKey = true 622 } 623 isAutoIncrement := bat.GetVectorByName((pkgcatalog.SystemColAttr_IsAutoIncrement)).Get(offset).(int8) 624 def.AutoIncrement = i82bool(isAutoIncrement) 625 def.Comment = string(bat.GetVectorByName((pkgcatalog.SystemColAttr_Comment)).Get(offset).([]byte)) 626 def.OnUpdate = bat.GetVectorByName((pkgcatalog.SystemColAttr_Update)).Get(offset).([]byte) 627 def.Default = bat.GetVectorByName((pkgcatalog.SystemColAttr_DefaultExpr)).Get(offset).([]byte) 628 def.Idx = int(bat.GetVectorByName((pkgcatalog.SystemColAttr_Num)).Get(offset).(int32)) - 1 629 def.SeqNum = bat.GetVectorByName(pkgcatalog.SystemColAttr_Seqnum).Get(offset).(uint16) 630 def.EnumValues = string(bat.GetVectorByName((pkgcatalog.SystemColAttr_EnumValues)).Get(offset).([]byte)) 631 s.NameMap[def.Name] = def.Idx 632 s.ColDefs = append(s.ColDefs, def) 633 if def.Name == PhyAddrColumnName { 634 seenRowid = true 635 def.PhyAddr = true 636 } 637 constraint := string(bat.GetVectorByName(pkgcatalog.SystemColAttr_ConstraintType).Get(offset).([]byte)) 638 if constraint == "p" { 639 def.SortKey = true 640 def.Primary = true 641 } 642 offset++ 643 } 644 return offset 645 } 646 647 func (s *Schema) AppendColDef(def *ColDef) (err error) { 648 def.Idx = len(s.ColDefs) 649 s.ColDefs = append(s.ColDefs, def) 650 _, existed := s.NameMap[def.Name] 651 if existed { 652 err = moerr.NewConstraintViolationNoCtx("duplicate column \"%s\"", def.Name) 653 return 654 } 655 s.NameMap[def.Name] = def.Idx 656 return 657 } 658 659 func (s *Schema) AppendCol(name string, typ types.Type) error { 660 def := &ColDef{ 661 Name: name, 662 Type: typ, 663 SortIdx: -1, 664 NullAbility: true, 665 } 666 return s.AppendColDef(def) 667 } 668 669 func (s *Schema) AppendSortKey(name string, typ types.Type, idx int, isPrimary bool) error { 670 def := &ColDef{ 671 Name: name, 672 Type: typ, 673 SortIdx: int8(idx), 674 SortKey: true, 675 } 676 def.Primary = isPrimary 677 return s.AppendColDef(def) 678 } 679 680 func (s *Schema) AppendPKCol(name string, typ types.Type, idx int) error { 681 def := &ColDef{ 682 Name: name, 683 Type: typ, 684 SortIdx: int8(idx), 685 SortKey: true, 686 Primary: true, 687 NullAbility: false, 688 } 689 return s.AppendColDef(def) 690 } 691 692 func (s *Schema) AppendFakePKCol() error { 693 typ := types.T_uint64.ToType() 694 typ.Width = 64 695 def := &ColDef{ 696 Name: pkgcatalog.FakePrimaryKeyColName, 697 Type: typ, 698 SortIdx: -1, 699 NullAbility: true, 700 FakePK: true, 701 Primary: true, 702 Hidden: true, 703 AutoIncrement: true, 704 ClusterBy: false, 705 } 706 return s.AppendColDef(def) 707 } 708 709 // non-cn doesn't set IsPrimary in attr, so isPrimary is used explicitly here 710 func (s *Schema) AppendSortColWithAttribute(attr engine.Attribute, sorIdx int, isPrimary bool) error { 711 def, err := ColDefFromAttribute(attr) 712 if err != nil { 713 return err 714 } 715 716 def.SortKey = true 717 def.SortIdx = int8(sorIdx) 718 def.Primary = isPrimary 719 720 return s.AppendColDef(def) 721 } 722 723 func colDefFromPlan(col *plan.ColDef, idx int, seqnum uint16) *ColDef { 724 newcol := &ColDef{ 725 Name: col.Name, 726 Idx: idx, 727 SeqNum: seqnum, 728 Type: vector.ProtoTypeToType(&col.Typ), 729 Hidden: col.Hidden, 730 // PhyAddr false 731 // Null later 732 AutoIncrement: col.Typ.AutoIncr, 733 // Primary false 734 SortIdx: -1, 735 // SortKey false 736 Comment: col.Comment, 737 // ClusterBy false 738 } 739 if col.Default != nil { 740 newcol.NullAbility = col.Default.NullAbility 741 newcol.Default, _ = types.Encode(col.Default) 742 } 743 if col.OnUpdate != nil { 744 newcol.OnUpdate, _ = types.Encode(col.OnUpdate) 745 } 746 return newcol 747 } 748 749 // make a basic coldef without sortKey info 750 func ColDefFromAttribute(attr engine.Attribute) (*ColDef, error) { 751 var err error 752 def := &ColDef{ 753 Name: attr.Name, 754 Type: attr.Type, 755 Hidden: attr.IsHidden, 756 SortIdx: -1, 757 Comment: attr.Comment, 758 AutoIncrement: attr.AutoIncrement, 759 ClusterBy: attr.ClusterBy, 760 Default: []byte(""), 761 OnUpdate: []byte(""), 762 EnumValues: attr.EnumVlaues, 763 } 764 if attr.Default != nil { 765 def.NullAbility = attr.Default.NullAbility 766 if def.Default, err = types.Encode(attr.Default); err != nil { 767 return nil, err 768 } 769 } 770 if attr.OnUpdate != nil { 771 if def.OnUpdate, err = types.Encode(attr.OnUpdate); err != nil { 772 return nil, err 773 } 774 } 775 return def, nil 776 } 777 778 func (s *Schema) AppendColWithAttribute(attr engine.Attribute) error { 779 def, err := ColDefFromAttribute(attr) 780 if err != nil { 781 return err 782 } 783 return s.AppendColDef(def) 784 } 785 786 func (s *Schema) String() string { 787 buf, _ := json.Marshal(s) 788 return string(pretty.Pretty(buf)) 789 } 790 791 func (s *Schema) Attrs() []string { 792 if len(s.ColDefs) == 0 { 793 return make([]string, 0) 794 } 795 attrs := make([]string, 0, len(s.ColDefs)-1) 796 for _, def := range s.ColDefs { 797 if def.IsPhyAddr() { 798 continue 799 } 800 attrs = append(attrs, def.Name) 801 } 802 return attrs 803 } 804 805 func (s *Schema) Types() []types.Type { 806 if len(s.ColDefs) == 0 { 807 return make([]types.Type, 0) 808 } 809 ts := make([]types.Type, 0, len(s.ColDefs)-1) 810 for _, def := range s.ColDefs { 811 if def.IsPhyAddr() { 812 continue 813 } 814 ts = append(ts, def.Type) 815 } 816 return ts 817 } 818 819 func (s *Schema) AllTypes() []types.Type { 820 if len(s.ColDefs) == 0 { 821 return make([]types.Type, 0) 822 } 823 ts := make([]types.Type, 0, len(s.ColDefs)) 824 for _, def := range s.ColDefs { 825 ts = append(ts, def.Type) 826 } 827 return ts 828 } 829 830 func (s *Schema) AllNames() []string { 831 if len(s.ColDefs) == 0 { 832 return make([]string, 0) 833 } 834 names := make([]string, 0, len(s.ColDefs)) 835 for _, def := range s.ColDefs { 836 names = append(names, def.Name) 837 } 838 return names 839 } 840 841 func (s *Schema) AllSeqnums() []uint16 { 842 if len(s.ColDefs) == 0 { 843 return make([]uint16, 0) 844 } 845 keys := make([]uint16, 0, len(s.ColDefs)) 846 for _, col := range s.ColDefs { 847 keys = append(keys, col.SeqNum) 848 } 849 return keys 850 } 851 852 // Finalize runs various checks and create shortcuts to phyaddr and sortkey 853 // Note: NameMap is already set before calling Finalize 854 func (s *Schema) Finalize(withoutPhyAddr bool) (err error) { 855 if s == nil { 856 err = moerr.NewConstraintViolationNoCtx("no schema") 857 return 858 } 859 if !withoutPhyAddr { 860 phyAddrDef := &ColDef{ 861 Name: PhyAddrColumnName, 862 Comment: PhyAddrColumnComment, 863 Type: objectio.RowidType, 864 Hidden: true, 865 NullAbility: false, 866 PhyAddr: true, 867 } 868 if err = s.AppendColDef(phyAddrDef); err != nil { 869 return 870 } 871 } 872 873 // sortColIdx is sort key index list. as of now, sort key is pk 874 sortColIdx := make([]int, 0) 875 // check duplicate column names 876 names := make(map[string]bool) 877 for idx, def := range s.ColDefs { 878 // Check column sequence idx validility 879 if idx != def.Idx { 880 return moerr.NewInvalidInputNoCtx(fmt.Sprintf("schema: wrong column index %d specified for \"%s\"", def.Idx, def.Name)) 881 } 882 // init seqnum for every column on new schema 883 if s.Extra.NextColSeqnum == 0 { 884 def.SeqNum = uint16(idx) 885 } 886 // Check unique name 887 if _, ok := names[def.Name]; ok { 888 return moerr.NewInvalidInputNoCtx("schema: duplicate column \"%s\"", def.Name) 889 } 890 names[def.Name] = true 891 // Fake pk 892 if IsFakePkName(def.Name) { 893 def.FakePK = true 894 def.SortKey = false 895 def.SortIdx = -1 896 } 897 if def.IsSortKey() { 898 sortColIdx = append(sortColIdx, idx) 899 } 900 if def.IsPhyAddr() { 901 // reading rowid is special, give it uint16Max, do not affect reading normal columns 902 def.SeqNum = objectio.SEQNUM_ROWID 903 s.SeqnumMap[def.SeqNum] = idx 904 s.PhyAddrKey = def 905 } else { 906 s.SeqnumMap[def.SeqNum] = idx 907 } 908 } 909 910 // init column sequence. 911 if s.Extra.NextColSeqnum == 0 { 912 if s.PhyAddrKey != nil { 913 s.Extra.NextColSeqnum = uint32(len(s.ColDefs)) - 1 914 } else { 915 s.Extra.NextColSeqnum = uint32(len(s.ColDefs)) 916 } 917 } 918 919 if len(sortColIdx) == 1 { 920 def := s.ColDefs[sortColIdx[0]] 921 if def.SortIdx != 0 { 922 err = moerr.NewConstraintViolationNoCtx("bad sort idx %d, should be 0", def.SortIdx) 923 return 924 } 925 s.SortKey = NewSortKey() 926 s.SortKey.AddDef(def) 927 } else if len(sortColIdx) > 1 { 928 // schema has a primary key or a cluster by key, or nothing for now 929 panic("schema: multiple sort keys") 930 } 931 s.isSecondaryIndexTable = strings.Contains(s.Name, "__mo_index_secondary_") 932 return 933 } 934 935 // GetColIdx returns column index for the given column name 936 // if found, otherwise returns -1. 937 func (s *Schema) GetColIdx(attr string) int { 938 idx, ok := s.NameMap[attr] 939 if !ok { 940 return -1 941 } 942 return idx 943 } 944 945 func (s *Schema) GetSeqnum(attr string) uint16 { 946 return s.ColDefs[s.GetColIdx(attr)].SeqNum 947 } 948 949 func GetAttrIdx(attrs []string, name string) int { 950 for i, attr := range attrs { 951 if attr == name { 952 return i 953 } 954 } 955 panic("logic error") 956 } 957 958 func MockSchema(colCnt int, pkIdx int) *Schema { 959 schema := NewEmptySchema(time.Now().String()) 960 prefix := "mock_" 961 962 constraintDef := &engine.ConstraintDef{ 963 Cts: make([]engine.Constraint, 0), 964 } 965 966 for i := 0; i < colCnt; i++ { 967 if pkIdx == i { 968 colName := fmt.Sprintf("%s%d", prefix, i) 969 _ = schema.AppendPKCol(colName, types.T_int32.ToType(), 0) 970 pkConstraint := &engine.PrimaryKeyDef{ 971 Pkey: &plan.PrimaryKeyDef{ 972 PkeyColName: colName, 973 Names: []string{colName}, 974 }, 975 } 976 constraintDef.Cts = append(constraintDef.Cts, pkConstraint) 977 } else { 978 _ = schema.AppendCol(fmt.Sprintf("%s%d", prefix, i), types.T_int32.ToType()) 979 } 980 } 981 schema.Constraint, _ = constraintDef.MarshalBinary() 982 983 _ = schema.Finalize(false) 984 return schema 985 } 986 987 func MockSnapShotSchema() *Schema { 988 schema := NewEmptySchema("mo_snapshot") 989 990 constraintDef := &engine.ConstraintDef{ 991 Cts: make([]engine.Constraint, 0), 992 } 993 994 schema.AppendCol("col0", types.T_uint64.ToType()) 995 schema.AppendCol("col1", types.T_uint64.ToType()) 996 schema.AppendCol("ts", types.T_int64.ToType()) 997 schema.AppendCol("col3", types.T_enum.ToType()) 998 schema.AppendCol("col4", types.T_uint64.ToType()) 999 schema.AppendCol("col5", types.T_uint64.ToType()) 1000 schema.AppendCol("col6", types.T_uint64.ToType()) 1001 schema.AppendCol("id", types.T_uint64.ToType()) 1002 schema.Constraint, _ = constraintDef.MarshalBinary() 1003 1004 _ = schema.Finalize(false) 1005 return schema 1006 } 1007 1008 // MockSchemaAll if char/varchar is needed, colCnt = 14, otherwise colCnt = 12 1009 // pkIdx == -1 means no pk defined 1010 func MockSchemaAll(colCnt int, pkIdx int, from ...int) *Schema { 1011 schema := NewEmptySchema(time.Now().String()) 1012 prefix := "mock_" 1013 start := 0 1014 if len(from) > 0 { 1015 start = from[0] 1016 } 1017 1018 constraintDef := &engine.ConstraintDef{ 1019 Cts: make([]engine.Constraint, 0), 1020 } 1021 1022 for i := 0; i < colCnt; i++ { 1023 if i < start { 1024 continue 1025 } 1026 name := fmt.Sprintf("%s%d", prefix, i) 1027 var typ types.Type 1028 switch i % 20 { 1029 case 0: 1030 typ = types.T_int8.ToType() 1031 typ.Width = 8 1032 case 1: 1033 typ = types.T_int16.ToType() 1034 typ.Width = 16 1035 case 2: 1036 typ = types.T_int32.ToType() 1037 typ.Width = 32 1038 case 3: 1039 typ = types.T_int64.ToType() 1040 typ.Width = 64 1041 case 4: 1042 typ = types.T_uint8.ToType() 1043 typ.Width = 8 1044 case 5: 1045 typ = types.T_uint16.ToType() 1046 typ.Width = 16 1047 case 6: 1048 typ = types.T_uint32.ToType() 1049 typ.Width = 32 1050 case 7: 1051 typ = types.T_uint64.ToType() 1052 typ.Width = 64 1053 case 8: 1054 typ = types.T_float32.ToType() 1055 typ.Width = 32 1056 case 9: 1057 typ = types.T_float64.ToType() 1058 typ.Width = 64 1059 case 10: 1060 typ = types.T_date.ToType() 1061 typ.Width = 32 1062 case 11: 1063 typ = types.T_datetime.ToType() 1064 typ.Width = 64 1065 case 12: 1066 typ = types.T_varchar.ToType() 1067 typ.Width = 100 1068 case 13: 1069 typ = types.T_char.ToType() 1070 typ.Width = 100 1071 case 14: 1072 typ = types.T_timestamp.ToType() 1073 typ.Width = 64 1074 case 15: 1075 typ = types.T_decimal64.ToType() 1076 typ.Width = 64 1077 case 16: 1078 typ = types.T_decimal128.ToType() 1079 typ.Width = 128 1080 case 17: 1081 typ = types.T_bool.ToType() 1082 typ.Width = 8 1083 case 18: 1084 typ = types.T_array_float32.ToType() 1085 typ.Width = 100 1086 case 19: 1087 typ = types.T_array_float64.ToType() 1088 typ.Width = 100 1089 } 1090 1091 if pkIdx == i { 1092 _ = schema.AppendPKCol(name, typ, 0) 1093 pkConstraint := &engine.PrimaryKeyDef{ 1094 Pkey: &plan.PrimaryKeyDef{ 1095 PkeyColName: name, 1096 Names: []string{name}, 1097 }, 1098 } 1099 constraintDef.Cts = append(constraintDef.Cts, pkConstraint) 1100 } else { 1101 _ = schema.AppendCol(name, typ) 1102 schema.ColDefs[len(schema.ColDefs)-1].NullAbility = true 1103 } 1104 } 1105 // if pk not existed, mock fake pk 1106 if pkIdx == -1 { 1107 schema.AppendFakePKCol() 1108 schema.ColDefs[len(schema.ColDefs)-1].NullAbility = true 1109 } 1110 1111 schema.BlockMaxRows = 1000 1112 schema.ObjectMaxBlocks = 10 1113 schema.Constraint, _ = constraintDef.MarshalBinary() 1114 _ = schema.Finalize(false) 1115 return schema 1116 }