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  }