github.com/matrixorigin/matrixone@v1.2.0/pkg/container/types/tuple.go (about)

     1  /*
     2   * tuple.go
     3   *
     4   * This source file is part of the FoundationDB open source project
     5   *
     6   * Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
     7   *
     8   * Licensed under the Apache License, Version 2.0 (the "License");
     9   * you may not use this file except in compliance with the License.
    10   * You may obtain a copy of the License at
    11   *
    12   *     http://www.apache.org/licenses/LICENSE-2.0
    13   *
    14   * Unless required by applicable law or agreed to in writing, software
    15   * distributed under the License is distributed on an "AS IS" BASIS,
    16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    17   * See the License for the specific language governing permissions and
    18   * limitations under the License.
    19   *
    20   * Portions of this file are additionally subject to the following
    21   * copyright.
    22   *
    23   * Copyright (C) 2022 Matrix Origin.
    24   *
    25   * Modified the behavior of the tuple.
    26   */
    27  
    28  package types
    29  
    30  import (
    31  	"bytes"
    32  	"encoding/binary"
    33  	"fmt"
    34  	"math"
    35  	"strconv"
    36  	"strings"
    37  	"unsafe"
    38  
    39  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    40  
    41  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    42  )
    43  
    44  /*
    45   * Tuple type is used for encoding multiColumns to single column
    46   * for example:
    47   * we create table (a int8, b int8, primary key(a, b))
    48   * we need to create composite primary key to combine a and b
    49   * we have one method to generate the primary key([]byte):
    50   *    var a int8 = 1, var b int8 = 1
    51   *    packer := newPacker()
    52   *    packer.EncodeInt8(a)
    53   *    packer.EncodeInt8(b)
    54   *    var byteArr []byte
    55   *    byteArr = packer.GetBuf()
    56   * we have one method recover from []byte to tuple
    57   *    var tuple Tuple
    58   *    tuple, err = Unpack(byteArr)
    59   *    tuple[0] = 1
    60   *    tuple[1] = 1
    61   *
    62   * in the composite_primary_key_util.go, we default use method2 to encode tupleElement
    63   */
    64  
    65  type TupleElement any
    66  
    67  type Tuple []TupleElement
    68  
    69  func (tp Tuple) String() string {
    70  	return printTuple(tp)
    71  }
    72  
    73  func (tp Tuple) ErrString(scales []int32) string {
    74  	var res strings.Builder
    75  	if len(tp) > 1 {
    76  		res.WriteString("(")
    77  	}
    78  	for i, t := range tp {
    79  		switch t := t.(type) {
    80  		case bool, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64:
    81  			res.WriteString(fmt.Sprintf("%v", t))
    82  		case []byte:
    83  			res.WriteString(*(*string)(unsafe.Pointer(&t)))
    84  		case Date:
    85  			res.WriteString(fmt.Sprintf("%v", t.String()))
    86  		case Time:
    87  			res.WriteString(fmt.Sprintf("%v", t.String()))
    88  		case Datetime:
    89  			res.WriteString(fmt.Sprintf("%v", t.String()))
    90  		case Timestamp:
    91  			res.WriteString(fmt.Sprintf("%v", t.String()))
    92  		case Decimal64:
    93  			res.WriteString(fmt.Sprintf("%v", t.Format(scales[i])))
    94  		case Decimal128:
    95  			res.WriteString(fmt.Sprintf("%v", t.Format(scales[i])))
    96  		default:
    97  			res.WriteString(fmt.Sprintf("%v", t))
    98  		}
    99  		if i != len(tp)-1 {
   100  			res.WriteString(",")
   101  		}
   102  	}
   103  	if len(tp) > 1 {
   104  		res.WriteString(")")
   105  	}
   106  	return res.String()
   107  }
   108  
   109  func (tp Tuple) SQLStrings(scales []int32) []string {
   110  	res := make([]string, 0, len(tp))
   111  	for i, t := range tp {
   112  		switch t := t.(type) {
   113  		case bool, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64:
   114  			res = append(res, fmt.Sprintf("%v", t))
   115  		case []byte:
   116  			s := *(*string)(unsafe.Pointer(&t))
   117  			res = append(res, strconv.Quote(s))
   118  		case Date:
   119  			res = append(res, fmt.Sprintf("'%v'", t.String()))
   120  		case Time:
   121  			res = append(res, fmt.Sprintf("'%v'", t.String()))
   122  		case Datetime:
   123  			res = append(res, fmt.Sprintf("'%v'", t.String()))
   124  		case Timestamp:
   125  			res = append(res, fmt.Sprintf("'%v'", t.String()))
   126  		case Decimal64:
   127  			res = append(res, fmt.Sprintf("%v", t.Format(scales[i])))
   128  		case Decimal128:
   129  			res = append(res, fmt.Sprintf("%v", t.Format(scales[i])))
   130  		default:
   131  			res = append(res, fmt.Sprintf("%v", t))
   132  		}
   133  	}
   134  	return res
   135  }
   136  
   137  func printTuple(tuple Tuple) string {
   138  	var res strings.Builder
   139  	for i, t := range tuple {
   140  		switch t := t.(type) {
   141  		case bool:
   142  			res.WriteString(fmt.Sprintf("(bool: %v)", t))
   143  		case int8:
   144  			res.WriteString(fmt.Sprintf("(int8: %v)", t))
   145  		case int16:
   146  			res.WriteString(fmt.Sprintf("(int16: %v)", t))
   147  		case int32:
   148  			res.WriteString(fmt.Sprintf("(int32: %v)", t))
   149  		case int64:
   150  			res.WriteString(fmt.Sprintf("(int64: %v)", t))
   151  		case uint8:
   152  			res.WriteString(fmt.Sprintf("(uint8: %v)", t))
   153  		case uint16:
   154  			res.WriteString(fmt.Sprintf("(uint16: %v)", t))
   155  		case uint32:
   156  			res.WriteString(fmt.Sprintf("(uint32: %v)", t))
   157  		case uint64:
   158  			res.WriteString(fmt.Sprintf("(uint64: %v)", t))
   159  		case Date:
   160  			res.WriteString(fmt.Sprintf("(date: %v)", t.String()))
   161  		case Time:
   162  			res.WriteString(fmt.Sprintf("(time: %v)", t.String()))
   163  		case Datetime:
   164  			res.WriteString(fmt.Sprintf("(datetime: %v)", t.String()))
   165  		case Timestamp:
   166  			res.WriteString(fmt.Sprintf("(timestamp: %v)", t.String()))
   167  		case Decimal64:
   168  			res.WriteString(fmt.Sprintf("(decimal64: %v)", t.Format(0)))
   169  		case Decimal128:
   170  			res.WriteString(fmt.Sprintf("(decimal128: %v)", t.Format(0)))
   171  		case []byte:
   172  			res.WriteString(fmt.Sprintf("([]byte: %v)", t))
   173  		case float32:
   174  			res.WriteString(fmt.Sprintf("(float32: %v)", t))
   175  		case float64:
   176  			res.WriteString(fmt.Sprintf("(float64: %v)", t))
   177  		default:
   178  			res.WriteString(fmt.Sprintf("(unorganizedType: %v)", t))
   179  		}
   180  		if i != len(tuple)-1 {
   181  			res.WriteString(",")
   182  		}
   183  	}
   184  	res.WriteString(")")
   185  	return res.String()
   186  }
   187  
   188  const nilCode = 0x00
   189  const bytesCode = 0x01
   190  const intZeroCode = 0x14
   191  const float32Code = 0x20
   192  const float64Code = 0x21
   193  const falseCode = 0x26
   194  const trueCode = 0x27
   195  const int8Code = 0x28
   196  const int16Code = 0x29
   197  const int32Code = 0x3a
   198  const int64Code = 0x3b
   199  const uint8Code = 0x3c
   200  const uint16Code = 0x3d
   201  const uint32Code = 0x3e
   202  const uint64Code = 0x40
   203  const dateCode = 0x41
   204  const datetimeCode = 0x42
   205  const timestampCode = 0x43
   206  const decimal64Code = 0x44
   207  const decimal128Code = 0x45
   208  const stringTypeCode = 0x46
   209  const timeCode = 0x47
   210  const enumCode = 0x50 // TODO: reorder the list to put timeCode next to date type code?
   211  const bitCode = 0x51
   212  
   213  var sizeLimits = []uint64{
   214  	1<<(0*8) - 1,
   215  	1<<(1*8) - 1,
   216  	1<<(2*8) - 1,
   217  	1<<(3*8) - 1,
   218  	1<<(4*8) - 1,
   219  	1<<(5*8) - 1,
   220  	1<<(6*8) - 1,
   221  	1<<(7*8) - 1,
   222  	1<<(8*8) - 1,
   223  }
   224  
   225  func bisectLeft(u uint64) int {
   226  	var n int
   227  	for sizeLimits[n] < u {
   228  		n++
   229  	}
   230  	return n
   231  }
   232  
   233  func adjustFloatBytes(b []byte, encode bool) {
   234  	if (encode && b[0]&0x80 != 0x00) || (!encode && b[0]&0x80 == 0x00) {
   235  		// Negative numbers: flip all of the bytes.
   236  		for i := 0; i < len(b); i++ {
   237  			b[i] = b[i] ^ 0xff
   238  		}
   239  	} else {
   240  		// Positive number: flip just the sign bit.
   241  		b[0] = b[0] ^ 0x80
   242  	}
   243  }
   244  
   245  const PackerMemUnit = 64
   246  
   247  type Packer struct {
   248  	buf      []byte
   249  	size     int
   250  	capacity int
   251  	mp       *mpool.MPool
   252  }
   253  
   254  func NewPacker(mp *mpool.MPool) *Packer {
   255  	bytes, err := mp.Alloc(PackerMemUnit)
   256  	if err != nil {
   257  		panic(err)
   258  	}
   259  	return &Packer{
   260  		buf:      bytes,
   261  		size:     0,
   262  		capacity: PackerMemUnit,
   263  		mp:       mp,
   264  	}
   265  }
   266  
   267  func NewPackerArray(length int, mp *mpool.MPool) []*Packer {
   268  	packerArr := make([]*Packer, length)
   269  	for num := range packerArr {
   270  		bytes, err := mp.Alloc(PackerMemUnit)
   271  		if err != nil {
   272  			panic(err)
   273  		}
   274  		packerArr[num] = &Packer{
   275  			buf:      bytes,
   276  			size:     0,
   277  			capacity: PackerMemUnit,
   278  			mp:       mp,
   279  		}
   280  	}
   281  	return packerArr
   282  }
   283  
   284  func (p *Packer) FreeMem() {
   285  	if p.buf != nil {
   286  		p.mp.Free(p.buf)
   287  		p.size = 0
   288  		p.capacity = 0
   289  		p.buf = nil
   290  	}
   291  }
   292  
   293  func (p *Packer) Reset() {
   294  	p.size = 0
   295  }
   296  
   297  func (p *Packer) putByte(b byte) {
   298  	if p.size < p.capacity {
   299  		p.buf[p.size] = b
   300  		p.size++
   301  	} else {
   302  		p.buf, _ = p.mp.Grow(p.buf, p.capacity+PackerMemUnit)
   303  		p.capacity += PackerMemUnit
   304  		p.buf[p.size] = b
   305  		p.size++
   306  	}
   307  }
   308  
   309  func (p *Packer) putBytes(bs []byte) {
   310  	if p.size+len(bs) < p.capacity {
   311  		for _, b := range bs {
   312  			p.buf[p.size] = b
   313  			p.size++
   314  		}
   315  	} else {
   316  		incrementSize := ((len(bs) / PackerMemUnit) + 1) * PackerMemUnit
   317  		p.buf, _ = p.mp.Grow(p.buf, p.capacity+incrementSize)
   318  		p.capacity += incrementSize
   319  		for _, b := range bs {
   320  			p.buf[p.size] = b
   321  			p.size++
   322  		}
   323  	}
   324  }
   325  
   326  func (p *Packer) putBytesNil(b []byte, i int) {
   327  	for i >= 0 {
   328  		p.putBytes(b[:i+1])
   329  		p.putByte(0xFF)
   330  		b = b[i+1:]
   331  		i = bytes.IndexByte(b, 0x00)
   332  	}
   333  	p.putBytes(b)
   334  }
   335  
   336  func (p *Packer) encodeBytes(code byte, b []byte) {
   337  	p.putByte(code)
   338  	if i := bytes.IndexByte(b, 0x00); i >= 0 {
   339  		p.putBytesNil(b, i)
   340  	} else {
   341  		p.putBytes(b)
   342  	}
   343  	p.putByte(0x00)
   344  }
   345  
   346  func (p *Packer) encodeUint(i uint64) {
   347  	if i == 0 {
   348  		p.putByte(intZeroCode)
   349  		return
   350  	}
   351  
   352  	n := bisectLeft(i)
   353  	var scratch [8]byte
   354  
   355  	p.putByte(byte(intZeroCode + n))
   356  	binary.BigEndian.PutUint64(scratch[:], i)
   357  
   358  	p.putBytes(scratch[8-n:])
   359  }
   360  
   361  func (p *Packer) encodeInt(i int64) {
   362  	if i >= 0 {
   363  		p.encodeUint(uint64(i))
   364  		return
   365  	}
   366  
   367  	n := bisectLeft(uint64(-i))
   368  	var scratch [8]byte
   369  
   370  	p.putByte(byte(intZeroCode - n))
   371  	offsetEncoded := int64(sizeLimits[n]) + i
   372  	binary.BigEndian.PutUint64(scratch[:], uint64(offsetEncoded))
   373  
   374  	p.putBytes(scratch[8-n:])
   375  }
   376  
   377  func (p *Packer) encodeFloat32(f float32) {
   378  	var scratch [4]byte
   379  	binary.BigEndian.PutUint32(scratch[:], math.Float32bits(f))
   380  	adjustFloatBytes(scratch[:], true)
   381  
   382  	p.putByte(float32Code)
   383  	p.putBytes(scratch[:])
   384  }
   385  
   386  func (p *Packer) encodeFloat64(d float64) {
   387  	var scratch [8]byte
   388  	binary.BigEndian.PutUint64(scratch[:], math.Float64bits(d))
   389  	adjustFloatBytes(scratch[:], true)
   390  
   391  	p.putByte(float64Code)
   392  	p.putBytes(scratch[:])
   393  }
   394  
   395  func (p *Packer) EncodeInt8(e int8) {
   396  	p.putByte(int8Code)
   397  	p.encodeInt(int64(e))
   398  }
   399  
   400  func (p *Packer) EncodeInt16(e int16) {
   401  	p.putByte(int16Code)
   402  	p.encodeInt(int64(e))
   403  }
   404  
   405  func (p *Packer) EncodeInt32(e int32) {
   406  	p.putByte(int32Code)
   407  	p.encodeInt(int64(e))
   408  }
   409  
   410  func (p *Packer) EncodeInt64(e int64) {
   411  	p.putByte(int64Code)
   412  	p.encodeInt(e)
   413  }
   414  
   415  func (p *Packer) EncodeUint8(e uint8) {
   416  	p.putByte(uint8Code)
   417  	p.encodeUint(uint64(e))
   418  }
   419  
   420  func (p *Packer) EncodeUint16(e uint16) {
   421  	p.putByte(uint16Code)
   422  	p.encodeUint(uint64(e))
   423  }
   424  
   425  func (p *Packer) EncodeUint32(e uint32) {
   426  	p.putByte(uint32Code)
   427  	p.encodeUint(uint64(e))
   428  }
   429  
   430  func (p *Packer) EncodeUint64(e uint64) {
   431  	p.putByte(uint64Code)
   432  	p.encodeUint(e)
   433  }
   434  
   435  func (p *Packer) EncodeFloat32(e float32) {
   436  	p.encodeFloat32(e)
   437  }
   438  
   439  func (p *Packer) EncodeFloat64(e float64) {
   440  	p.encodeFloat64(e)
   441  }
   442  
   443  func (p *Packer) EncodeNull() {
   444  	p.putByte(nilCode)
   445  }
   446  
   447  func (p *Packer) EncodeBool(e bool) {
   448  	if e {
   449  		p.putByte(trueCode)
   450  	} else {
   451  		p.putByte(falseCode)
   452  	}
   453  }
   454  
   455  func (p *Packer) EncodeDate(e Date) {
   456  	p.putByte(dateCode)
   457  	p.encodeInt(int64(e))
   458  }
   459  
   460  func (p *Packer) EncodeTime(e Time) {
   461  	p.putByte(timeCode)
   462  	p.encodeInt(int64(e))
   463  }
   464  
   465  func (p *Packer) EncodeDatetime(e Datetime) {
   466  	p.putByte(datetimeCode)
   467  	p.encodeInt(int64(e))
   468  }
   469  
   470  func (p *Packer) EncodeTimestamp(e Timestamp) {
   471  	p.putByte(timestampCode)
   472  	p.encodeInt(int64(e))
   473  }
   474  
   475  func (p *Packer) EncodeEnum(e Enum) {
   476  	p.putByte(enumCode)
   477  	p.EncodeUint16(uint16(e))
   478  }
   479  
   480  func (p *Packer) EncodeDecimal64(e Decimal64) {
   481  	p.putByte(decimal64Code)
   482  	b := *(*[8]byte)(unsafe.Pointer(&e))
   483  	b[7] ^= 0x80
   484  	for i := 7; i >= 0; i-- {
   485  		p.putByte(b[i])
   486  	}
   487  }
   488  
   489  func (p *Packer) EncodeDecimal128(e Decimal128) {
   490  	p.putByte(decimal128Code)
   491  	b := *(*[16]byte)(unsafe.Pointer(&e))
   492  	b[15] ^= 0x80
   493  	for i := 15; i >= 0; i-- {
   494  		p.putByte(b[i])
   495  	}
   496  }
   497  
   498  func (p *Packer) EncodeStringType(e []byte) {
   499  	p.putByte(stringTypeCode)
   500  	p.encodeBytes(bytesCode, e)
   501  }
   502  
   503  func (p *Packer) EncodeBit(e uint64) {
   504  	p.putByte(bitCode)
   505  	p.encodeUint(e)
   506  }
   507  
   508  func (p *Packer) GetBuf() []byte {
   509  	return p.buf[:p.size]
   510  }
   511  
   512  func (p *Packer) Bytes() []byte {
   513  	ret := make([]byte, p.size)
   514  	copy(ret, p.buf[:p.size])
   515  	return ret
   516  }
   517  
   518  func findTerminator(b []byte) int {
   519  	bp := b
   520  	var length int
   521  
   522  	for {
   523  		idx := bytes.IndexByte(bp, 0x00)
   524  		length += idx
   525  		if idx+1 == len(bp) || bp[idx+1] != 0xFF {
   526  			break
   527  		}
   528  		length += 2
   529  		bp = bp[idx+2:]
   530  	}
   531  
   532  	return length
   533  }
   534  
   535  func decodeBytes(b []byte) ([]byte, int) {
   536  	idx := findTerminator(b[1:])
   537  	return bytes.ReplaceAll(b[1:idx+1], []byte{0x00, 0xFF}, []byte{0x00}), idx + 2
   538  }
   539  
   540  func decodeInt(code byte, b []byte) (interface{}, int) {
   541  	if b[0] == intZeroCode {
   542  		switch code {
   543  		case int8Code:
   544  			return int8(0), 1
   545  		case int16Code:
   546  			return int16(0), 1
   547  		case int32Code:
   548  			return int32(0), 1
   549  		case dateCode:
   550  			return Date(0), 1
   551  		case datetimeCode:
   552  			return Datetime(0), 1
   553  		case timestampCode:
   554  			return Timestamp(0), 1
   555  		default:
   556  			return int64(0), 1
   557  		}
   558  	}
   559  
   560  	var neg bool
   561  
   562  	n := int(b[0]) - intZeroCode
   563  	if n < 0 {
   564  		n = -n
   565  		neg = true
   566  	}
   567  
   568  	bp := make([]byte, 8)
   569  	copy(bp[8-n:], b[1:n+1])
   570  
   571  	var ret int64
   572  	binary.Read(bytes.NewBuffer(bp), binary.BigEndian, &ret)
   573  
   574  	if neg {
   575  		switch code {
   576  		case int8Code:
   577  			return int8(ret - int64(sizeLimits[n])), n + 1
   578  		case int16Code:
   579  			return int16(ret - int64(sizeLimits[n])), n + 1
   580  		case int32Code:
   581  			return int32(ret - int64(sizeLimits[n])), n + 1
   582  		case dateCode:
   583  			return Date(ret - int64(sizeLimits[n])), n + 1
   584  		case datetimeCode:
   585  			return Datetime(ret - int64(sizeLimits[n])), n + 1
   586  		case timestampCode:
   587  			return Timestamp(ret - int64(sizeLimits[n])), n + 1
   588  		default:
   589  			return ret - int64(sizeLimits[n]), n + 1
   590  		}
   591  	}
   592  	switch code {
   593  	case int8Code:
   594  		return int8(ret), n + 1
   595  	case int16Code:
   596  		return int16(ret), n + 1
   597  	case int32Code:
   598  		return int32(ret), n + 1
   599  	case dateCode:
   600  		return Date(ret), n + 1
   601  	case datetimeCode:
   602  		return Datetime(ret), n + 1
   603  	case timestampCode:
   604  		return Timestamp(ret), n + 1
   605  	case enumCode:
   606  		return Enum(ret), n + 1
   607  	default:
   608  		return ret, n + 1
   609  	}
   610  }
   611  
   612  func decodeUint(code byte, b []byte) (interface{}, int) {
   613  	if b[0] == intZeroCode {
   614  		switch code {
   615  		case uint8Code:
   616  			return uint8(0), 1
   617  		case uint16Code:
   618  			return uint16(0), 1
   619  		case uint32Code:
   620  			return uint32(0), 1
   621  		}
   622  		return uint64(0), 1
   623  	}
   624  	n := int(b[0]) - intZeroCode
   625  
   626  	bp := make([]byte, 8)
   627  	copy(bp[8-n:], b[1:n+1])
   628  
   629  	var ret uint64
   630  	binary.Read(bytes.NewBuffer(bp), binary.BigEndian, &ret)
   631  
   632  	switch code {
   633  	case uint8Code:
   634  		return uint8(ret), n + 1
   635  	case uint16Code:
   636  		return uint16(ret), n + 1
   637  	case uint32Code:
   638  		return uint32(ret), n + 1
   639  	default:
   640  		return ret, n + 1
   641  	}
   642  }
   643  
   644  func decodeFloat32(b []byte) (float32, int) {
   645  	bp := make([]byte, 4)
   646  	copy(bp, b[1:])
   647  	adjustFloatBytes(bp, false)
   648  	var ret float32
   649  	binary.Read(bytes.NewBuffer(bp), binary.BigEndian, &ret)
   650  	return ret, 5
   651  }
   652  
   653  func decodeFloat64(b []byte) (float64, int) {
   654  	bp := make([]byte, 8)
   655  	copy(bp, b[1:])
   656  	adjustFloatBytes(bp, false)
   657  	var ret float64
   658  	binary.Read(bytes.NewBuffer(bp), binary.BigEndian, &ret)
   659  	return ret, 9
   660  }
   661  
   662  func decodeDecimal64(b []byte) (Decimal64, int) {
   663  	bp := make([]byte, 8)
   664  	copy(bp, b[:])
   665  	bp[0] ^= 0x80
   666  	for i := 0; i < 4; i++ {
   667  		bp[i] ^= bp[7-i]
   668  		bp[7-i] ^= bp[i]
   669  		bp[i] ^= bp[7-i]
   670  	}
   671  	ret := *(*Decimal64)(unsafe.Pointer(&bp[0]))
   672  	return ret, 9
   673  }
   674  
   675  func decodeDecimal128(b []byte) (Decimal128, int) {
   676  	bp := make([]byte, 16)
   677  	copy(bp, b[:])
   678  	bp[0] ^= 0x80
   679  	for i := 0; i < 8; i++ {
   680  		bp[i] ^= bp[15-i]
   681  		bp[15-i] ^= bp[i]
   682  		bp[i] ^= bp[15-i]
   683  	}
   684  	ret := *(*Decimal128)(unsafe.Pointer(&bp[0]))
   685  	return ret, 17
   686  }
   687  
   688  var DecodeTuple = decodeTuple
   689  
   690  func decodeTuple(b []byte) (Tuple, int, []T, error) {
   691  	var t Tuple
   692  
   693  	var i int
   694  	var schema = make([]T, 0)
   695  	for i < len(b) {
   696  		var el interface{}
   697  		var off int
   698  
   699  		switch {
   700  		case b[i] == nilCode:
   701  			schema = append(schema, T_any)
   702  			el = nil
   703  			off = 1
   704  		case b[i] == int8Code:
   705  			schema = append(schema, T_int8)
   706  			el, off = decodeInt(int8Code, b[i+1:])
   707  			off += 1
   708  		case b[i] == int16Code:
   709  			schema = append(schema, T_int16)
   710  			el, off = decodeInt(int16Code, b[i+1:])
   711  			off += 1
   712  		case b[i] == int32Code:
   713  			schema = append(schema, T_int32)
   714  			el, off = decodeInt(int32Code, b[i+1:])
   715  			off += 1
   716  		case b[i] == int64Code:
   717  			schema = append(schema, T_int64)
   718  			el, off = decodeInt(int64Code, b[i+1:])
   719  			off += 1
   720  		case b[i] == uint8Code:
   721  			schema = append(schema, T_uint8)
   722  			el, off = decodeUint(uint8Code, b[i+1:])
   723  			off += 1
   724  		case b[i] == uint16Code:
   725  			schema = append(schema, T_uint16)
   726  			el, off = decodeUint(uint16Code, b[i+1:])
   727  			off += 1
   728  		case b[i] == uint32Code:
   729  			schema = append(schema, T_uint32)
   730  			el, off = decodeUint(uint32Code, b[i+1:])
   731  			off += 1
   732  		case b[i] == uint64Code:
   733  			schema = append(schema, T_uint64)
   734  			el, off = decodeUint(uint64Code, b[i+1:])
   735  			off += 1
   736  		case b[i] == trueCode:
   737  			schema = append(schema, T_bool)
   738  			el = true
   739  			off = 1
   740  		case b[i] == falseCode:
   741  			schema = append(schema, T_bool)
   742  			el = false
   743  			off = 1
   744  		case b[i] == float32Code:
   745  			schema = append(schema, T_float32)
   746  			el, off = decodeFloat32(b[i:])
   747  		case b[i] == float64Code:
   748  			schema = append(schema, T_float64)
   749  			el, off = decodeFloat64(b[i:])
   750  		case b[i] == dateCode:
   751  			schema = append(schema, T_date)
   752  			el, off = decodeInt(dateCode, b[i+1:])
   753  			off += 1
   754  		case b[i] == datetimeCode:
   755  			schema = append(schema, T_datetime)
   756  			el, off = decodeInt(datetimeCode, b[i+1:])
   757  			off += 1
   758  		case b[i] == timestampCode:
   759  			schema = append(schema, T_timestamp)
   760  			el, off = decodeInt(timestampCode, b[i+1:])
   761  			off += 1
   762  		case b[i] == timeCode:
   763  			schema = append(schema, T_time)
   764  			el, off = decodeInt(timeCode, b[i+1:])
   765  			off += 1
   766  		case b[i] == decimal64Code:
   767  			schema = append(schema, T_decimal64)
   768  			el, off = decodeDecimal64(b[i+1:])
   769  		case b[i] == decimal128Code:
   770  			schema = append(schema, T_decimal128)
   771  			el, off = decodeDecimal128(b[i+1:])
   772  		case b[i] == stringTypeCode:
   773  			schema = append(schema, T_varchar)
   774  			el, off = decodeBytes(b[i+1:])
   775  			off += 1
   776  		case b[i] == bitCode:
   777  			schema = append(schema, T_bit)
   778  			el, off = decodeUint(uint64Code, b[i+1:])
   779  			off += 1
   780  		case b[i] == enumCode:
   781  			schema = append(schema, T_enum)
   782  			//TODO: need to verify @YANGGMM
   783  			el, off = decodeUint(uint16Code, b[i+1:])
   784  			off += 1
   785  		default:
   786  			return nil, i, nil, moerr.NewInternalErrorNoCtx("unable to decode tuple element with unknown typecode %02x", b[i])
   787  		}
   788  		t = append(t, el)
   789  		i += off
   790  	}
   791  
   792  	return t, i, schema, nil
   793  }
   794  
   795  func Unpack(b []byte) (Tuple, error) {
   796  	t, _, _, err := decodeTuple(b)
   797  	return t, err
   798  }
   799  
   800  func UnpackWithSchema(b []byte) (Tuple, []T, error) {
   801  	t, _, schema, err := decodeTuple(b)
   802  	return t, schema, err
   803  }