github.com/XiaoMi/Gaea@v1.2.5/mysql/encoding.go (about)

     1  /*
     2  Copyright 2017 Google Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreedto in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // Copyright 2019 The Gaea Authors. All Rights Reserved.
    18  //
    19  // Licensed under the Apache License, Version 2.0 (the "License");
    20  // you may not use this file except in compliance with the License.
    21  // You may obtain a copy of the License at
    22  //
    23  //     http://www.apache.org/licenses/LICENSE-2.0
    24  //
    25  // Unless required by applicable law or agreed to in writing, software
    26  // distributed under the License is distributed on an "AS IS" BASIS,
    27  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    28  // See the License for the specific language governing permissions and
    29  // limitations under the License.
    30  
    31  package mysql
    32  
    33  import (
    34  	"bytes"
    35  	"encoding/binary"
    36  	"fmt"
    37  	"math"
    38  	"strconv"
    39  	"time"
    40  
    41  	"github.com/XiaoMi/Gaea/util/hack"
    42  )
    43  
    44  // This file contains the data encoding and decoding functions.
    45  
    46  //
    47  // Encoding methods.
    48  //
    49  // The same assumptions are made for all the encoding functions:
    50  // - there is enough space to write the data in the buffer. If not, we
    51  // will panic with out of bounds.
    52  // - all functions start writing at 'pos' in the buffer, and return the next position.
    53  
    54  // LenEncIntSize returns the number of bytes required to encode a
    55  // variable-length integer.
    56  func LenEncIntSize(i uint64) int {
    57  	switch {
    58  	case i < 251:
    59  		return 1
    60  	case i < 1<<16:
    61  		return 3
    62  	case i < 1<<24:
    63  		return 4
    64  	default:
    65  		return 9
    66  	}
    67  }
    68  
    69  // WriteLenEncInt write uint64 to []byte
    70  func WriteLenEncInt(data []byte, pos int, i uint64) int {
    71  	switch {
    72  	case i < 251:
    73  		data[pos] = byte(i)
    74  		return pos + 1
    75  	case i < 1<<16:
    76  		data[pos] = 0xfc
    77  		data[pos+1] = byte(i)
    78  		data[pos+2] = byte(i >> 8)
    79  		return pos + 3
    80  	case i < 1<<24:
    81  		data[pos] = 0xfd
    82  		data[pos+1] = byte(i)
    83  		data[pos+2] = byte(i >> 8)
    84  		data[pos+3] = byte(i >> 16)
    85  		return pos + 4
    86  	default:
    87  		data[pos] = 0xfe
    88  		data[pos+1] = byte(i)
    89  		data[pos+2] = byte(i >> 8)
    90  		data[pos+3] = byte(i >> 16)
    91  		data[pos+4] = byte(i >> 24)
    92  		data[pos+5] = byte(i >> 32)
    93  		data[pos+6] = byte(i >> 40)
    94  		data[pos+7] = byte(i >> 48)
    95  		data[pos+8] = byte(i >> 56)
    96  		return pos + 9
    97  	}
    98  }
    99  
   100  // AppendLenEncInt append LenEncInt []byte to data
   101  func AppendLenEncInt(data []byte, i uint64) []byte {
   102  	switch {
   103  	case i <= 250:
   104  		return append(data, byte(i))
   105  
   106  	case i <= 0xffff:
   107  		return append(data, 0xfc, byte(i), byte(i>>8))
   108  
   109  	case i <= 0xffffff:
   110  		return append(data, 0xfd, byte(i), byte(i>>8), byte(i>>16))
   111  
   112  	case i <= 0xffffffffffffffff:
   113  		return append(data, 0xfe, byte(i), byte(i>>8), byte(i>>16), byte(i>>24),
   114  			byte(i>>32), byte(i>>40), byte(i>>48), byte(i>>56))
   115  	}
   116  
   117  	return data
   118  }
   119  
   120  // LenNullString return lenght Null terminated string
   121  func LenNullString(value string) int {
   122  	return len(value) + 1
   123  }
   124  
   125  // WriteNullString write NULL terminated strign to []byte
   126  func WriteNullString(data []byte, pos int, value string) int {
   127  	pos += copy(data[pos:], value)
   128  	data[pos] = 0
   129  	return pos + 1
   130  }
   131  
   132  func writeEOFString(data []byte, pos int, value string) int {
   133  	pos += copy(data[pos:], value)
   134  	return pos
   135  }
   136  
   137  // WriteByte write byte to []byte
   138  func WriteByte(data []byte, pos int, value byte) int {
   139  	data[pos] = value
   140  	return pos + 1
   141  }
   142  
   143  // WriteBytes write byte to []byte
   144  func WriteBytes(data []byte, pos int, value []byte) int {
   145  	pos += copy(data[pos:], value)
   146  	return pos
   147  }
   148  
   149  // WriteUint16 write uint16 to []byte
   150  func WriteUint16(data []byte, pos int, value uint16) int {
   151  	data[pos] = byte(value)
   152  	data[pos+1] = byte(value >> 8)
   153  	return pos + 2
   154  }
   155  
   156  // AppendUint16 append uint16 to []byte
   157  func AppendUint16(data []byte, n uint16) []byte {
   158  	data = append(data, byte(n))
   159  	data = append(data, byte(n>>8))
   160  	return data
   161  }
   162  
   163  // WriteUint32 write uint32 to []byte
   164  func WriteUint32(data []byte, pos int, value uint32) int {
   165  	data[pos] = byte(value)
   166  	data[pos+1] = byte(value >> 8)
   167  	data[pos+2] = byte(value >> 16)
   168  	data[pos+3] = byte(value >> 24)
   169  	return pos + 4
   170  }
   171  
   172  // AppendUint32 append uint32 to []byte
   173  func AppendUint32(data []byte, n uint32) []byte {
   174  	data = append(data, byte(n))
   175  	data = append(data, byte(n>>8))
   176  	data = append(data, byte(n>>16))
   177  	data = append(data, byte(n>>24))
   178  	return data
   179  }
   180  
   181  // WriteUint64 write uint64 to []byte
   182  func WriteUint64(data []byte, pos int, value uint64) int {
   183  	data[pos] = byte(value)
   184  	data[pos+1] = byte(value >> 8)
   185  	data[pos+2] = byte(value >> 16)
   186  	data[pos+3] = byte(value >> 24)
   187  	data[pos+4] = byte(value >> 32)
   188  	data[pos+5] = byte(value >> 40)
   189  	data[pos+6] = byte(value >> 48)
   190  	data[pos+7] = byte(value >> 56)
   191  	return pos + 8
   192  }
   193  
   194  // AppendUint64 append uint64 to []byte
   195  func AppendUint64(data []byte, n uint64) []byte {
   196  	data = append(data, byte(n))
   197  	data = append(data, byte(n>>8))
   198  	data = append(data, byte(n>>16))
   199  	data = append(data, byte(n>>24))
   200  	data = append(data, byte(n>>32))
   201  	data = append(data, byte(n>>40))
   202  	data = append(data, byte(n>>48))
   203  	data = append(data, byte(n>>56))
   204  	return data
   205  }
   206  
   207  // LenEncStringSize  calculate length of lenenc_str
   208  // https://dev.mysql.com/doc/internals/en/describing-packets.html#type-lenenc_str
   209  func LenEncStringSize(value string) int {
   210  	l := len(value)
   211  	return LenEncIntSize(uint64(l)) + l
   212  }
   213  
   214  // WriteLenEncString write string to []byte, return pos
   215  func WriteLenEncString(data []byte, pos int, value string) int {
   216  	pos = WriteLenEncInt(data, pos, uint64(len(value)))
   217  	return writeEOFString(data, pos, value)
   218  }
   219  
   220  // AppendLenEncStringBytes append bytes of len enc string  to data
   221  func AppendLenEncStringBytes(data, b []byte) []byte {
   222  	data = AppendLenEncInt(data, uint64(len(b)))
   223  	data = append(data, b...)
   224  	return data
   225  }
   226  
   227  // WriteZeroes write 0 to []byte
   228  func WriteZeroes(data []byte, pos int, len int) int {
   229  	for i := 0; i < len; i++ {
   230  		data[pos+i] = 0
   231  	}
   232  	return pos + len
   233  }
   234  
   235  //
   236  // Decoding methods.
   237  //
   238  // The same assumptions are made for all the decoding functions:
   239  // - they return the decode data, the new position to read from, and ak 'ok' flag.
   240  // - all functions start reading at 'pos' in the buffer, and return the next position.
   241  //
   242  
   243  // ReadByte read one byte from []byte
   244  func ReadByte(data []byte, pos int) (byte, int, bool) {
   245  	if pos >= len(data) {
   246  		return 0, 0, false
   247  	}
   248  	return data[pos], pos + 1, true
   249  }
   250  
   251  // ReadBytes read []byte from pos with sized size
   252  func ReadBytes(data []byte, pos int, size int) ([]byte, int, bool) {
   253  	if pos+size-1 >= len(data) {
   254  		return nil, 0, false
   255  	}
   256  	return data[pos : pos+size], pos + size, true
   257  }
   258  
   259  // ReadBytesCopy returns a copy of the bytes in the packet.
   260  // Useful to remember contents of ephemeral packets.
   261  func ReadBytesCopy(data []byte, pos int, size int) ([]byte, int, bool) {
   262  	if pos+size-1 >= len(data) {
   263  		return nil, 0, false
   264  	}
   265  	result := make([]byte, size)
   266  	copy(result, data[pos:pos+size])
   267  	return result, pos + size, true
   268  }
   269  
   270  // ReadNullString read Null terminated string from []byte, return string,pos,if end.
   271  func ReadNullString(data []byte, pos int) (string, int, bool) {
   272  	end := bytes.IndexByte(data[pos:], 0)
   273  	if end == -1 {
   274  		return "", 0, false
   275  	}
   276  	return string(data[pos : pos+end]), pos + end + 1, true
   277  }
   278  
   279  // ReadNullString read Null terminated string from []byte, return byet,pos,if end.
   280  func ReadNullByte(data []byte, pos int) ([]byte, int, bool) {
   281  	end := bytes.IndexByte(data[pos:], 0)
   282  	if end == -1 {
   283  		return []byte{}, 0, false
   284  	}
   285  	return data[pos : pos+end], pos + end + 1, true
   286  }
   287  
   288  // ReadUint16 read uint32 from []byte
   289  func ReadUint16(data []byte, pos int) (uint16, int, bool) {
   290  	if pos+1 >= len(data) {
   291  		return 0, 0, false
   292  	}
   293  	return binary.LittleEndian.Uint16(data[pos : pos+2]), pos + 2, true
   294  }
   295  
   296  // ReadUint32 read uint32 from []byte
   297  func ReadUint32(data []byte, pos int) (uint32, int, bool) {
   298  	if pos+3 >= len(data) {
   299  		return 0, 0, false
   300  	}
   301  	return binary.LittleEndian.Uint32(data[pos : pos+4]), pos + 4, true
   302  }
   303  
   304  // ReadUint64 read uint64 from []byte
   305  func ReadUint64(data []byte, pos int) (uint64, int, bool) {
   306  	if pos+7 >= len(data) {
   307  		return 0, 0, false
   308  	}
   309  	return binary.LittleEndian.Uint64(data[pos : pos+8]), pos + 8, true
   310  }
   311  
   312  // ReadLenEncInt read info of len encoded int, return length, next pos(skip len self to data), is null, handle result
   313  // https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger
   314  func ReadLenEncInt(data []byte, pos int) (uint64, int, bool, bool) {
   315  	isNull := false
   316  	if pos >= len(data) {
   317  		return 0, 0, isNull, false
   318  	}
   319  	switch data[pos] {
   320  	// 251: NULL
   321  	case 0xfb:
   322  		isNull = true
   323  		return 0, pos + 1, isNull, true
   324  	case 0xfc:
   325  		// Encoded in the next 2 bytes.
   326  		if pos+2 >= len(data) {
   327  			return 0, 0, isNull, false
   328  		}
   329  		return uint64(data[pos+1]) |
   330  			uint64(data[pos+2])<<8, pos + 3, isNull, true
   331  	case 0xfd:
   332  		// Encoded in the next 3 bytes.
   333  		if pos+3 >= len(data) {
   334  			return 0, 0, isNull, false
   335  		}
   336  		return uint64(data[pos+1]) |
   337  			uint64(data[pos+2])<<8 |
   338  			uint64(data[pos+3])<<16, pos + 4, isNull, true
   339  	case 0xfe:
   340  		// Encoded in the next 8 bytes.
   341  		if pos+8 >= len(data) {
   342  			return 0, 0, isNull, false
   343  		}
   344  		return uint64(data[pos+1]) |
   345  			uint64(data[pos+2])<<8 |
   346  			uint64(data[pos+3])<<16 |
   347  			uint64(data[pos+4])<<24 |
   348  			uint64(data[pos+5])<<32 |
   349  			uint64(data[pos+6])<<40 |
   350  			uint64(data[pos+7])<<48 |
   351  			uint64(data[pos+8])<<56, pos + 9, isNull, true
   352  	}
   353  	// 0-250
   354  	return uint64(data[pos]), pos + 1, isNull, true
   355  }
   356  
   357  func readLenEncString(data []byte, pos int) (string, int, bool) {
   358  	size, pos, _, ok := ReadLenEncInt(data, pos)
   359  	if !ok {
   360  		return "", 0, false
   361  	}
   362  	s := int(size)
   363  	if pos+s-1 >= len(data) {
   364  		return "", 0, false
   365  	}
   366  	return string(data[pos : pos+s]), pos + s, true
   367  }
   368  
   369  // return next pos、handle result
   370  func skipLenEncString(data []byte, pos int) (int, bool) {
   371  	size, pos, _, ok := ReadLenEncInt(data, pos)
   372  	if !ok {
   373  		return 0, false
   374  	}
   375  	s := int(size)
   376  	if pos+s-1 >= len(data) {
   377  		return 0, false
   378  	}
   379  	return pos + s, true
   380  }
   381  
   382  // ReadLenEncStringAsBytes read len encoded string, return []byte format, next pos, is null, handle result
   383  func ReadLenEncStringAsBytes(data []byte, pos int) ([]byte, int, bool, bool) {
   384  	size, pos, isNull, ok := ReadLenEncInt(data, pos)
   385  	if !ok {
   386  		return nil, 0, isNull, false
   387  	}
   388  	s := int(size)
   389  	if pos+s-1 >= len(data) {
   390  		return nil, 0, isNull, false
   391  	}
   392  	return data[pos : pos+s], pos + s, isNull, true
   393  }
   394  
   395  // FormatBinaryDate format binary date type
   396  func FormatBinaryDate(n int, data []byte) ([]byte, error) {
   397  	switch n {
   398  	case 0:
   399  		return []byte("0000-00-00"), nil
   400  	case 4:
   401  		return []byte(fmt.Sprintf("%04d-%02d-%02d",
   402  			binary.LittleEndian.Uint16(data[:2]),
   403  			data[2],
   404  			data[3])), nil
   405  	default:
   406  		return nil, fmt.Errorf("invalid date packet length %d", n)
   407  	}
   408  }
   409  
   410  // FormatBinaryDateTime format binary datetime type
   411  func FormatBinaryDateTime(n int, data []byte) ([]byte, error) {
   412  	switch n {
   413  	case 0:
   414  		return []byte("0000-00-00 00:00:00"), nil
   415  	case 4:
   416  		return []byte(fmt.Sprintf("%04d-%02d-%02d 00:00:00",
   417  			binary.LittleEndian.Uint16(data[:2]),
   418  			data[2],
   419  			data[3])), nil
   420  	case 7:
   421  		return []byte(fmt.Sprintf(
   422  			"%04d-%02d-%02d %02d:%02d:%02d",
   423  			binary.LittleEndian.Uint16(data[:2]),
   424  			data[2],
   425  			data[3],
   426  			data[4],
   427  			data[5],
   428  			data[6])), nil
   429  	case 11:
   430  		return []byte(fmt.Sprintf(
   431  			"%04d-%02d-%02d %02d:%02d:%02d.%06d",
   432  			binary.LittleEndian.Uint16(data[:2]),
   433  			data[2],
   434  			data[3],
   435  			data[4],
   436  			data[5],
   437  			data[6],
   438  			binary.LittleEndian.Uint32(data[7:11]))), nil
   439  	default:
   440  		return nil, fmt.Errorf("invalid datetime packet length %d", n)
   441  	}
   442  }
   443  
   444  // FormatBinaryTime format binary time type
   445  func FormatBinaryTime(n int, data []byte) ([]byte, error) {
   446  	if n == 0 {
   447  		return []byte("0000-00-00"), nil
   448  	}
   449  
   450  	var sign byte
   451  	if data[0] == 1 {
   452  		sign = byte('-')
   453  	}
   454  
   455  	switch n {
   456  	case 8:
   457  		return []byte(fmt.Sprintf(
   458  			"%c%02d:%02d:%02d",
   459  			sign,
   460  			uint16(data[1])*24+uint16(data[5]),
   461  			data[6],
   462  			data[7],
   463  		)), nil
   464  	case 12:
   465  		return []byte(fmt.Sprintf(
   466  			"%c%02d:%02d:%02d.%06d",
   467  			sign,
   468  			uint16(data[1])*24+uint16(data[5]),
   469  			data[6],
   470  			data[7],
   471  			binary.LittleEndian.Uint32(data[8:12]),
   472  		)), nil
   473  	default:
   474  		return nil, fmt.Errorf("invalid time packet length %d", n)
   475  	}
   476  }
   477  
   478  // AppendBinaryValue encode binary-type value of prepare binary protocol according to type of value
   479  func AppendBinaryValue(data []byte, fieldType uint8, value interface{}) ([]byte, error) {
   480  	// constructor phase
   481  	var t []byte
   482  	switch v := value.(type) {
   483  	case int8:
   484  		t = make([]byte, 8)
   485  		WriteUint64(t, 0, uint64(v))
   486  	case int16:
   487  		t = make([]byte, 8)
   488  		WriteUint64(t, 0, uint64(v))
   489  	case int32:
   490  		t = make([]byte, 8)
   491  		WriteUint64(t, 0, uint64(v))
   492  	case int64:
   493  		t = make([]byte, 8)
   494  		WriteUint64(t, 0, uint64(v))
   495  	case int:
   496  		t = make([]byte, 8)
   497  		WriteUint64(t, 0, uint64(v))
   498  	case uint8:
   499  		t = make([]byte, 8)
   500  		WriteUint64(t, 0, uint64(v))
   501  	case uint16:
   502  		t = make([]byte, 8)
   503  		WriteUint64(t, 0, uint64(v))
   504  	case uint32:
   505  		t = make([]byte, 8)
   506  		WriteUint64(t, 0, uint64(v))
   507  	case uint64:
   508  		t = make([]byte, 8)
   509  		WriteUint64(t, 0, uint64(v))
   510  	case uint:
   511  		t = make([]byte, 8)
   512  		WriteUint64(t, 0, uint64(v))
   513  	case float64:
   514  		switch fieldType {
   515  		case TypeFloat:
   516  			t = make([]byte, 4)
   517  			WriteUint32(t, 0, math.Float32bits(float32(v)))
   518  		case TypeNewDecimal:
   519  			tmp := strconv.FormatFloat(v, 'f', -1, 64)
   520  			t = []byte(tmp)
   521  		default:
   522  			t = make([]byte, 8)
   523  			WriteUint64(t, 0, math.Float64bits(v))
   524  		}
   525  	case []byte:
   526  		t = v
   527  	case string:
   528  		switch fieldType {
   529  		case TypeDatetime, TypeTimestamp:
   530  			if v == "0000-00-00 00:00:00" {
   531  				t = append(t, 0)
   532  			} else {
   533  				ts, err := time.Parse("2006-01-02 15:04:05", v)
   534  				if err != nil {
   535  					var mysqlTypeStr string
   536  					if fieldType == TypeDatetime {
   537  						mysqlTypeStr = "TypeDatetime"
   538  					} else {
   539  						mysqlTypeStr = "TypeTimestamp"
   540  					}
   541  					return nil, fmt.Errorf("invalid %s %s", mysqlTypeStr, v)
   542  				}
   543  
   544  				t = append(t, 11)
   545  				t = AppendUint16(t, uint16(ts.Year()))
   546  				t = append(t, byte(int(ts.Month())), byte(ts.Day()), byte(ts.Hour()), byte(ts.Minute()), byte(ts.Second()))
   547  				microseconds := uint32(ts.Nanosecond() / 1000)
   548  				t = AppendUint32(t, microseconds)
   549  			}
   550  		case TypeDate:
   551  			// format: 2006-01-02
   552  			ts, err := time.Parse("2006-01-02", v)
   553  			if err != nil {
   554  				t = append(t, 0)
   555  			} else {
   556  				t = append(t, 4)
   557  				t = AppendUint16(t, uint16(ts.Year()))
   558  				t = append(t, byte(int(ts.Month())), byte(ts.Day()))
   559  			}
   560  		case TypeDuration:
   561  			timeValue, err := stringToMysqlTime(v)
   562  			if err != nil {
   563  				return nil, err
   564  			}
   565  
   566  			t = mysqlTimeToBinaryResult(timeValue)
   567  		default:
   568  			t = hack.Slice(v)
   569  		}
   570  	default:
   571  		return data, fmt.Errorf("invalid type %T", value)
   572  	}
   573  
   574  	// append phase
   575  	switch fieldType {
   576  	case TypeTiny:
   577  		data = append(data, t[0])
   578  		return data, nil
   579  	case TypeShort, TypeYear:
   580  		data = append(data, t[:2]...)
   581  		return data, nil
   582  	case TypeFloat, TypeInt24, TypeLong:
   583  		data = append(data, t[:4]...)
   584  		return data, nil
   585  	case TypeLonglong, TypeDouble:
   586  		data = append(data, t[:8]...)
   587  		return data, nil
   588  	case TypeNewDecimal, TypeJSON, TypeString, TypeVarString, TypeVarchar, TypeBit, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob:
   589  		tmp := make([]byte, 0, len(t)+9)
   590  		data = append(data, AppendLenEncStringBytes(tmp, t)...)
   591  		return data, nil
   592  	case TypeEnum, TypeSet, TypeDate, TypeDatetime, TypeDuration, TypeTimestamp, TypeNewDate:
   593  		data = append(data, t...)
   594  		return data, nil
   595  	default:
   596  		return data, fmt.Errorf("not supported field type")
   597  	}
   598  }