1
0
Fork 0
forked from forgejo/forgejo

Integrate public as bindata optionally (#293)

* Dropped unused codekit config

* Integrated dynamic and static bindata for public

* Ignore public bindata

* Add a general generate make task

* Integrated flexible public assets into web command

* Updated vendoring, added all missiong govendor deps

* Made the linter happy with the bindata and dynamic code

* Moved public bindata definition to modules directory

* Ignoring the new bindata path now

* Updated to the new public modules import path

* Updated public bindata command and drop the new prefix
This commit is contained in:
Thomas Boerger 2016-11-29 17:26:36 +01:00 committed by Lunny Xiao
parent 4680c349dd
commit b6a95a8cb3
691 changed files with 305318 additions and 1272 deletions

68
vendor/github.com/pingcap/tidb/util/auth.go generated vendored Normal file
View file

@ -0,0 +1,68 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package util
import (
"crypto/sha1"
"encoding/hex"
"github.com/juju/errors"
)
// CalcPassword is the algorithm convert hashed password to auth string.
// See: https://dev.mysql.com/doc/internals/en/secure-password-authentication.html
// SHA1( password ) XOR SHA1( "20-bytes random data from server" <concat> SHA1( SHA1( password ) ) )
func CalcPassword(scramble, sha1pwd []byte) []byte {
if len(sha1pwd) == 0 {
return nil
}
// scrambleHash = SHA1(scramble + SHA1(sha1pwd))
// inner Hash
hash := Sha1Hash(sha1pwd)
// outer Hash
crypt := sha1.New()
crypt.Write(scramble)
crypt.Write(hash)
scramble = crypt.Sum(nil)
// token = scrambleHash XOR stage1Hash
for i := range scramble {
scramble[i] ^= sha1pwd[i]
}
return scramble
}
// Sha1Hash is an util function to calculate sha1 hash.
func Sha1Hash(bs []byte) []byte {
crypt := sha1.New()
crypt.Write(bs)
return crypt.Sum(nil)
}
// EncodePassword converts plaintext password to hashed hex string.
func EncodePassword(pwd string) string {
if len(pwd) == 0 {
return ""
}
hash := Sha1Hash([]byte(pwd))
return hex.EncodeToString(hash)
}
// DecodePassword converts hex string password to byte array.
func DecodePassword(pwd string) ([]byte, error) {
x, err := hex.DecodeString(pwd)
if err != nil {
return nil, errors.Trace(err)
}
return x, nil
}

6
vendor/github.com/pingcap/tidb/util/bytes/bytes.go generated vendored Normal file
View file

@ -0,0 +1,6 @@
package bytes
// CloneBytes returns a deep copy of slice b.
func CloneBytes(b []byte) []byte {
return append([]byte(nil), b...)
}

369
vendor/github.com/pingcap/tidb/util/charset/charset.go generated vendored Normal file
View file

@ -0,0 +1,369 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package charset
import (
"strings"
"github.com/juju/errors"
)
// Charset is a charset.
// Now we only support MySQL.
type Charset struct {
Name string
DefaultCollation *Collation
Collations map[string]*Collation
Desc string
Maxlen int
}
// Collation is a collation.
// Now we only support MySQL.
type Collation struct {
ID int
CharsetName string
Name string
IsDefault bool
}
var charsets = make(map[string]*Charset)
// All the supported charsets should be in the following table.
var charsetInfos = []*Charset{
{"utf8", nil, make(map[string]*Collation), "UTF-8 Unicode", 3},
{"latin1", nil, make(map[string]*Collation), "cp1252 West European", 1},
{"utf8mb4", nil, make(map[string]*Collation), "UTF-8 Unicode", 4},
{"ascii", nil, make(map[string]*Collation), "US ASCII", 1},
}
func init() {
for _, c := range charsetInfos {
charsets[c.Name] = c
}
for _, c := range collations {
charset, ok := charsets[c.CharsetName]
if !ok {
continue
}
charset.Collations[c.Name] = c
if c.IsDefault {
charset.DefaultCollation = c
}
}
}
// Desc is a charset description.
type Desc struct {
Name string
Desc string
DefaultCollation string
Maxlen int
}
// GetAllCharsets gets all charset descriptions in the local charsets.
func GetAllCharsets() []*Desc {
descs := make([]*Desc, 0, len(charsets))
// The charsetInfos is an array, so the iterate order will be stable.
for _, ci := range charsetInfos {
c, ok := charsets[ci.Name]
if !ok {
continue
}
desc := &Desc{
Name: c.Name,
DefaultCollation: c.DefaultCollation.Name,
Desc: c.Desc,
Maxlen: c.Maxlen,
}
descs = append(descs, desc)
}
return descs
}
// ValidCharsetAndCollation checks the charset and the collation validity
// and retuns a boolean.
func ValidCharsetAndCollation(cs string, co string) bool {
// We will use utf8 as a default charset.
if cs == "" {
cs = "utf8"
}
c, ok := charsets[cs]
if !ok {
return false
}
if co == "" {
return true
}
_, ok = c.Collations[co]
if !ok {
return false
}
return true
}
// GetDefaultCollation returns the default collation for charset
func GetDefaultCollation(charset string) (string, error) {
c, ok := charsets[charset]
if !ok {
return "", errors.Errorf("Unkown charset %s", charset)
}
return c.DefaultCollation.Name, nil
}
// GetCharsetInfo returns charset and collation for cs as name.
func GetCharsetInfo(cs string) (string, string, error) {
c, ok := charsets[strings.ToLower(cs)]
if !ok {
return "", "", errors.Errorf("Unknown charset %s", cs)
}
return c.Name, c.DefaultCollation.Name, nil
}
// GetCollations returns a list for all collations.
func GetCollations() []*Collation {
return collations
}
const (
// CharsetBin is used for marking binary charset.
CharsetBin = "binary"
// CollationBin is the default collation for CharsetBin.
CollationBin = "binary"
)
var collations = []*Collation{
{1, "big5", "big5_chinese_ci", true},
{2, "latin2", "latin2_czech_cs", false},
{3, "dec8", "dec8_swedish_ci", true},
{4, "cp850", "cp850_general_ci", true},
{5, "latin1", "latin1_german1_ci", false},
{6, "hp8", "hp8_english_ci", true},
{7, "koi8r", "koi8r_general_ci", true},
{8, "latin1", "latin1_swedish_ci", true},
{9, "latin2", "latin2_general_ci", true},
{10, "swe7", "swe7_swedish_ci", true},
{11, "ascii", "ascii_general_ci", true},
{12, "ujis", "ujis_japanese_ci", true},
{13, "sjis", "sjis_japanese_ci", true},
{14, "cp1251", "cp1251_bulgarian_ci", false},
{15, "latin1", "latin1_danish_ci", false},
{16, "hebrew", "hebrew_general_ci", true},
{18, "tis620", "tis620_thai_ci", true},
{19, "euckr", "euckr_korean_ci", true},
{20, "latin7", "latin7_estonian_cs", false},
{21, "latin2", "latin2_hungarian_ci", false},
{22, "koi8u", "koi8u_general_ci", true},
{23, "cp1251", "cp1251_ukrainian_ci", false},
{24, "gb2312", "gb2312_chinese_ci", true},
{25, "greek", "greek_general_ci", true},
{26, "cp1250", "cp1250_general_ci", true},
{27, "latin2", "latin2_croatian_ci", false},
{28, "gbk", "gbk_chinese_ci", true},
{29, "cp1257", "cp1257_lithuanian_ci", false},
{30, "latin5", "latin5_turkish_ci", true},
{31, "latin1", "latin1_german2_ci", false},
{32, "armscii8", "armscii8_general_ci", true},
{33, "utf8", "utf8_general_ci", true},
{34, "cp1250", "cp1250_czech_cs", false},
{35, "ucs2", "ucs2_general_ci", true},
{36, "cp866", "cp866_general_ci", true},
{37, "keybcs2", "keybcs2_general_ci", true},
{38, "macce", "macce_general_ci", true},
{39, "macroman", "macroman_general_ci", true},
{40, "cp852", "cp852_general_ci", true},
{41, "latin7", "latin7_general_ci", true},
{42, "latin7", "latin7_general_cs", false},
{43, "macce", "macce_bin", false},
{44, "cp1250", "cp1250_croatian_ci", false},
{45, "utf8mb4", "utf8mb4_general_ci", true},
{46, "utf8mb4", "utf8mb4_bin", false},
{47, "latin1", "latin1_bin", false},
{48, "latin1", "latin1_general_ci", false},
{49, "latin1", "latin1_general_cs", false},
{50, "cp1251", "cp1251_bin", false},
{51, "cp1251", "cp1251_general_ci", true},
{52, "cp1251", "cp1251_general_cs", false},
{53, "macroman", "macroman_bin", false},
{54, "utf16", "utf16_general_ci", true},
{55, "utf16", "utf16_bin", false},
{56, "utf16le", "utf16le_general_ci", true},
{57, "cp1256", "cp1256_general_ci", true},
{58, "cp1257", "cp1257_bin", false},
{59, "cp1257", "cp1257_general_ci", true},
{60, "utf32", "utf32_general_ci", true},
{61, "utf32", "utf32_bin", false},
{62, "utf16le", "utf16le_bin", false},
{63, "binary", "binary", true},
{64, "armscii8", "armscii8_bin", false},
{65, "ascii", "ascii_bin", false},
{66, "cp1250", "cp1250_bin", false},
{67, "cp1256", "cp1256_bin", false},
{68, "cp866", "cp866_bin", false},
{69, "dec8", "dec8_bin", false},
{70, "greek", "greek_bin", false},
{71, "hebrew", "hebrew_bin", false},
{72, "hp8", "hp8_bin", false},
{73, "keybcs2", "keybcs2_bin", false},
{74, "koi8r", "koi8r_bin", false},
{75, "koi8u", "koi8u_bin", false},
{77, "latin2", "latin2_bin", false},
{78, "latin5", "latin5_bin", false},
{79, "latin7", "latin7_bin", false},
{80, "cp850", "cp850_bin", false},
{81, "cp852", "cp852_bin", false},
{82, "swe7", "swe7_bin", false},
{83, "utf8", "utf8_bin", false},
{84, "big5", "big5_bin", false},
{85, "euckr", "euckr_bin", false},
{86, "gb2312", "gb2312_bin", false},
{87, "gbk", "gbk_bin", false},
{88, "sjis", "sjis_bin", false},
{89, "tis620", "tis620_bin", false},
{90, "ucs2", "ucs2_bin", false},
{91, "ujis", "ujis_bin", false},
{92, "geostd8", "geostd8_general_ci", true},
{93, "geostd8", "geostd8_bin", false},
{94, "latin1", "latin1_spanish_ci", false},
{95, "cp932", "cp932_japanese_ci", true},
{96, "cp932", "cp932_bin", false},
{97, "eucjpms", "eucjpms_japanese_ci", true},
{98, "eucjpms", "eucjpms_bin", false},
{99, "cp1250", "cp1250_polish_ci", false},
{101, "utf16", "utf16_unicode_ci", false},
{102, "utf16", "utf16_icelandic_ci", false},
{103, "utf16", "utf16_latvian_ci", false},
{104, "utf16", "utf16_romanian_ci", false},
{105, "utf16", "utf16_slovenian_ci", false},
{106, "utf16", "utf16_polish_ci", false},
{107, "utf16", "utf16_estonian_ci", false},
{108, "utf16", "utf16_spanish_ci", false},
{109, "utf16", "utf16_swedish_ci", false},
{110, "utf16", "utf16_turkish_ci", false},
{111, "utf16", "utf16_czech_ci", false},
{112, "utf16", "utf16_danish_ci", false},
{113, "utf16", "utf16_lithuanian_ci", false},
{114, "utf16", "utf16_slovak_ci", false},
{115, "utf16", "utf16_spanish2_ci", false},
{116, "utf16", "utf16_roman_ci", false},
{117, "utf16", "utf16_persian_ci", false},
{118, "utf16", "utf16_esperanto_ci", false},
{119, "utf16", "utf16_hungarian_ci", false},
{120, "utf16", "utf16_sinhala_ci", false},
{121, "utf16", "utf16_german2_ci", false},
{122, "utf16", "utf16_croatian_ci", false},
{123, "utf16", "utf16_unicode_520_ci", false},
{124, "utf16", "utf16_vietnamese_ci", false},
{128, "ucs2", "ucs2_unicode_ci", false},
{129, "ucs2", "ucs2_icelandic_ci", false},
{130, "ucs2", "ucs2_latvian_ci", false},
{131, "ucs2", "ucs2_romanian_ci", false},
{132, "ucs2", "ucs2_slovenian_ci", false},
{133, "ucs2", "ucs2_polish_ci", false},
{134, "ucs2", "ucs2_estonian_ci", false},
{135, "ucs2", "ucs2_spanish_ci", false},
{136, "ucs2", "ucs2_swedish_ci", false},
{137, "ucs2", "ucs2_turkish_ci", false},
{138, "ucs2", "ucs2_czech_ci", false},
{139, "ucs2", "ucs2_danish_ci", false},
{140, "ucs2", "ucs2_lithuanian_ci", false},
{141, "ucs2", "ucs2_slovak_ci", false},
{142, "ucs2", "ucs2_spanish2_ci", false},
{143, "ucs2", "ucs2_roman_ci", false},
{144, "ucs2", "ucs2_persian_ci", false},
{145, "ucs2", "ucs2_esperanto_ci", false},
{146, "ucs2", "ucs2_hungarian_ci", false},
{147, "ucs2", "ucs2_sinhala_ci", false},
{148, "ucs2", "ucs2_german2_ci", false},
{149, "ucs2", "ucs2_croatian_ci", false},
{150, "ucs2", "ucs2_unicode_520_ci", false},
{151, "ucs2", "ucs2_vietnamese_ci", false},
{159, "ucs2", "ucs2_general_mysql500_ci", false},
{160, "utf32", "utf32_unicode_ci", false},
{161, "utf32", "utf32_icelandic_ci", false},
{162, "utf32", "utf32_latvian_ci", false},
{163, "utf32", "utf32_romanian_ci", false},
{164, "utf32", "utf32_slovenian_ci", false},
{165, "utf32", "utf32_polish_ci", false},
{166, "utf32", "utf32_estonian_ci", false},
{167, "utf32", "utf32_spanish_ci", false},
{168, "utf32", "utf32_swedish_ci", false},
{169, "utf32", "utf32_turkish_ci", false},
{170, "utf32", "utf32_czech_ci", false},
{171, "utf32", "utf32_danish_ci", false},
{172, "utf32", "utf32_lithuanian_ci", false},
{173, "utf32", "utf32_slovak_ci", false},
{174, "utf32", "utf32_spanish2_ci", false},
{175, "utf32", "utf32_roman_ci", false},
{176, "utf32", "utf32_persian_ci", false},
{177, "utf32", "utf32_esperanto_ci", false},
{178, "utf32", "utf32_hungarian_ci", false},
{179, "utf32", "utf32_sinhala_ci", false},
{180, "utf32", "utf32_german2_ci", false},
{181, "utf32", "utf32_croatian_ci", false},
{182, "utf32", "utf32_unicode_520_ci", false},
{183, "utf32", "utf32_vietnamese_ci", false},
{192, "utf8", "utf8_unicode_ci", false},
{193, "utf8", "utf8_icelandic_ci", false},
{194, "utf8", "utf8_latvian_ci", false},
{195, "utf8", "utf8_romanian_ci", false},
{196, "utf8", "utf8_slovenian_ci", false},
{197, "utf8", "utf8_polish_ci", false},
{198, "utf8", "utf8_estonian_ci", false},
{199, "utf8", "utf8_spanish_ci", false},
{200, "utf8", "utf8_swedish_ci", false},
{201, "utf8", "utf8_turkish_ci", false},
{202, "utf8", "utf8_czech_ci", false},
{203, "utf8", "utf8_danish_ci", false},
{204, "utf8", "utf8_lithuanian_ci", false},
{205, "utf8", "utf8_slovak_ci", false},
{206, "utf8", "utf8_spanish2_ci", false},
{207, "utf8", "utf8_roman_ci", false},
{208, "utf8", "utf8_persian_ci", false},
{209, "utf8", "utf8_esperanto_ci", false},
{210, "utf8", "utf8_hungarian_ci", false},
{211, "utf8", "utf8_sinhala_ci", false},
{212, "utf8", "utf8_german2_ci", false},
{213, "utf8", "utf8_croatian_ci", false},
{214, "utf8", "utf8_unicode_520_ci", false},
{215, "utf8", "utf8_vietnamese_ci", false},
{223, "utf8", "utf8_general_mysql500_ci", false},
{224, "utf8mb4", "utf8mb4_unicode_ci", false},
{225, "utf8mb4", "utf8mb4_icelandic_ci", false},
{226, "utf8mb4", "utf8mb4_latvian_ci", false},
{227, "utf8mb4", "utf8mb4_romanian_ci", false},
{228, "utf8mb4", "utf8mb4_slovenian_ci", false},
{229, "utf8mb4", "utf8mb4_polish_ci", false},
{230, "utf8mb4", "utf8mb4_estonian_ci", false},
{231, "utf8mb4", "utf8mb4_spanish_ci", false},
{232, "utf8mb4", "utf8mb4_swedish_ci", false},
{233, "utf8mb4", "utf8mb4_turkish_ci", false},
{234, "utf8mb4", "utf8mb4_czech_ci", false},
{235, "utf8mb4", "utf8mb4_danish_ci", false},
{236, "utf8mb4", "utf8mb4_lithuanian_ci", false},
{237, "utf8mb4", "utf8mb4_slovak_ci", false},
{238, "utf8mb4", "utf8mb4_spanish2_ci", false},
{239, "utf8mb4", "utf8mb4_roman_ci", false},
{240, "utf8mb4", "utf8mb4_persian_ci", false},
{241, "utf8mb4", "utf8mb4_esperanto_ci", false},
{242, "utf8mb4", "utf8mb4_hungarian_ci", false},
{243, "utf8mb4", "utf8mb4_sinhala_ci", false},
{244, "utf8mb4", "utf8mb4_german2_ci", false},
{245, "utf8mb4", "utf8mb4_croatian_ci", false},
{246, "utf8mb4", "utf8mb4_unicode_520_ci", false},
{247, "utf8mb4", "utf8mb4_vietnamese_ci", false},
}

View file

@ -0,0 +1,258 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package charset
import (
"strings"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/charmap"
"golang.org/x/text/encoding/japanese"
"golang.org/x/text/encoding/korean"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/encoding/traditionalchinese"
"golang.org/x/text/encoding/unicode"
)
// Lookup returns the encoding with the specified label, and its canonical
// name. It returns nil and the empty string if label is not one of the
// standard encodings for HTML. Matching is case-insensitive and ignores
// leading and trailing whitespace.
func Lookup(label string) (e encoding.Encoding, name string) {
label = strings.ToLower(strings.Trim(label, "\t\n\r\f "))
enc := encodings[label]
return enc.e, enc.name
}
var encodings = map[string]struct {
e encoding.Encoding
name string
}{
"unicode-1-1-utf-8": {encoding.Nop, "utf-8"},
"utf-8": {encoding.Nop, "utf-8"},
"utf8": {encoding.Nop, "utf-8"},
"866": {charmap.CodePage866, "ibm866"},
"cp866": {charmap.CodePage866, "ibm866"},
"csibm866": {charmap.CodePage866, "ibm866"},
"ibm866": {charmap.CodePage866, "ibm866"},
"csisolatin2": {charmap.ISO8859_2, "iso-8859-2"},
"iso-8859-2": {charmap.ISO8859_2, "iso-8859-2"},
"iso-ir-101": {charmap.ISO8859_2, "iso-8859-2"},
"iso8859-2": {charmap.ISO8859_2, "iso-8859-2"},
"iso88592": {charmap.ISO8859_2, "iso-8859-2"},
"iso_8859-2": {charmap.ISO8859_2, "iso-8859-2"},
"iso_8859-2:1987": {charmap.ISO8859_2, "iso-8859-2"},
"l2": {charmap.ISO8859_2, "iso-8859-2"},
"latin2": {charmap.ISO8859_2, "iso-8859-2"},
"csisolatin3": {charmap.ISO8859_3, "iso-8859-3"},
"iso-8859-3": {charmap.ISO8859_3, "iso-8859-3"},
"iso-ir-109": {charmap.ISO8859_3, "iso-8859-3"},
"iso8859-3": {charmap.ISO8859_3, "iso-8859-3"},
"iso88593": {charmap.ISO8859_3, "iso-8859-3"},
"iso_8859-3": {charmap.ISO8859_3, "iso-8859-3"},
"iso_8859-3:1988": {charmap.ISO8859_3, "iso-8859-3"},
"l3": {charmap.ISO8859_3, "iso-8859-3"},
"latin3": {charmap.ISO8859_3, "iso-8859-3"},
"csisolatin4": {charmap.ISO8859_4, "iso-8859-4"},
"iso-8859-4": {charmap.ISO8859_4, "iso-8859-4"},
"iso-ir-110": {charmap.ISO8859_4, "iso-8859-4"},
"iso8859-4": {charmap.ISO8859_4, "iso-8859-4"},
"iso88594": {charmap.ISO8859_4, "iso-8859-4"},
"iso_8859-4": {charmap.ISO8859_4, "iso-8859-4"},
"iso_8859-4:1988": {charmap.ISO8859_4, "iso-8859-4"},
"l4": {charmap.ISO8859_4, "iso-8859-4"},
"latin4": {charmap.ISO8859_4, "iso-8859-4"},
"csisolatincyrillic": {charmap.ISO8859_5, "iso-8859-5"},
"cyrillic": {charmap.ISO8859_5, "iso-8859-5"},
"iso-8859-5": {charmap.ISO8859_5, "iso-8859-5"},
"iso-ir-144": {charmap.ISO8859_5, "iso-8859-5"},
"iso8859-5": {charmap.ISO8859_5, "iso-8859-5"},
"iso88595": {charmap.ISO8859_5, "iso-8859-5"},
"iso_8859-5": {charmap.ISO8859_5, "iso-8859-5"},
"iso_8859-5:1988": {charmap.ISO8859_5, "iso-8859-5"},
"arabic": {charmap.ISO8859_6, "iso-8859-6"},
"asmo-708": {charmap.ISO8859_6, "iso-8859-6"},
"csiso88596e": {charmap.ISO8859_6, "iso-8859-6"},
"csiso88596i": {charmap.ISO8859_6, "iso-8859-6"},
"csisolatinarabic": {charmap.ISO8859_6, "iso-8859-6"},
"ecma-114": {charmap.ISO8859_6, "iso-8859-6"},
"iso-8859-6": {charmap.ISO8859_6, "iso-8859-6"},
"iso-8859-6-e": {charmap.ISO8859_6, "iso-8859-6"},
"iso-8859-6-i": {charmap.ISO8859_6, "iso-8859-6"},
"iso-ir-127": {charmap.ISO8859_6, "iso-8859-6"},
"iso8859-6": {charmap.ISO8859_6, "iso-8859-6"},
"iso88596": {charmap.ISO8859_6, "iso-8859-6"},
"iso_8859-6": {charmap.ISO8859_6, "iso-8859-6"},
"iso_8859-6:1987": {charmap.ISO8859_6, "iso-8859-6"},
"csisolatingreek": {charmap.ISO8859_7, "iso-8859-7"},
"ecma-118": {charmap.ISO8859_7, "iso-8859-7"},
"elot_928": {charmap.ISO8859_7, "iso-8859-7"},
"greek": {charmap.ISO8859_7, "iso-8859-7"},
"greek8": {charmap.ISO8859_7, "iso-8859-7"},
"iso-8859-7": {charmap.ISO8859_7, "iso-8859-7"},
"iso-ir-126": {charmap.ISO8859_7, "iso-8859-7"},
"iso8859-7": {charmap.ISO8859_7, "iso-8859-7"},
"iso88597": {charmap.ISO8859_7, "iso-8859-7"},
"iso_8859-7": {charmap.ISO8859_7, "iso-8859-7"},
"iso_8859-7:1987": {charmap.ISO8859_7, "iso-8859-7"},
"sun_eu_greek": {charmap.ISO8859_7, "iso-8859-7"},
"csiso88598e": {charmap.ISO8859_8, "iso-8859-8"},
"csisolatinhebrew": {charmap.ISO8859_8, "iso-8859-8"},
"hebrew": {charmap.ISO8859_8, "iso-8859-8"},
"iso-8859-8": {charmap.ISO8859_8, "iso-8859-8"},
"iso-8859-8-e": {charmap.ISO8859_8, "iso-8859-8"},
"iso-ir-138": {charmap.ISO8859_8, "iso-8859-8"},
"iso8859-8": {charmap.ISO8859_8, "iso-8859-8"},
"iso88598": {charmap.ISO8859_8, "iso-8859-8"},
"iso_8859-8": {charmap.ISO8859_8, "iso-8859-8"},
"iso_8859-8:1988": {charmap.ISO8859_8, "iso-8859-8"},
"visual": {charmap.ISO8859_8, "iso-8859-8"},
"csiso88598i": {charmap.ISO8859_8, "iso-8859-8-i"},
"iso-8859-8-i": {charmap.ISO8859_8, "iso-8859-8-i"},
"logical": {charmap.ISO8859_8, "iso-8859-8-i"},
"csisolatin6": {charmap.ISO8859_10, "iso-8859-10"},
"iso-8859-10": {charmap.ISO8859_10, "iso-8859-10"},
"iso-ir-157": {charmap.ISO8859_10, "iso-8859-10"},
"iso8859-10": {charmap.ISO8859_10, "iso-8859-10"},
"iso885910": {charmap.ISO8859_10, "iso-8859-10"},
"l6": {charmap.ISO8859_10, "iso-8859-10"},
"latin6": {charmap.ISO8859_10, "iso-8859-10"},
"iso-8859-13": {charmap.ISO8859_13, "iso-8859-13"},
"iso8859-13": {charmap.ISO8859_13, "iso-8859-13"},
"iso885913": {charmap.ISO8859_13, "iso-8859-13"},
"iso-8859-14": {charmap.ISO8859_14, "iso-8859-14"},
"iso8859-14": {charmap.ISO8859_14, "iso-8859-14"},
"iso885914": {charmap.ISO8859_14, "iso-8859-14"},
"csisolatin9": {charmap.ISO8859_15, "iso-8859-15"},
"iso-8859-15": {charmap.ISO8859_15, "iso-8859-15"},
"iso8859-15": {charmap.ISO8859_15, "iso-8859-15"},
"iso885915": {charmap.ISO8859_15, "iso-8859-15"},
"iso_8859-15": {charmap.ISO8859_15, "iso-8859-15"},
"l9": {charmap.ISO8859_15, "iso-8859-15"},
"iso-8859-16": {charmap.ISO8859_16, "iso-8859-16"},
"cskoi8r": {charmap.KOI8R, "koi8-r"},
"koi": {charmap.KOI8R, "koi8-r"},
"koi8": {charmap.KOI8R, "koi8-r"},
"koi8-r": {charmap.KOI8R, "koi8-r"},
"koi8_r": {charmap.KOI8R, "koi8-r"},
"koi8-u": {charmap.KOI8U, "koi8-u"},
"csmacintosh": {charmap.Macintosh, "macintosh"},
"mac": {charmap.Macintosh, "macintosh"},
"macintosh": {charmap.Macintosh, "macintosh"},
"x-mac-roman": {charmap.Macintosh, "macintosh"},
"dos-874": {charmap.Windows874, "windows-874"},
"iso-8859-11": {charmap.Windows874, "windows-874"},
"iso8859-11": {charmap.Windows874, "windows-874"},
"iso885911": {charmap.Windows874, "windows-874"},
"tis-620": {charmap.Windows874, "windows-874"},
"windows-874": {charmap.Windows874, "windows-874"},
"cp1250": {charmap.Windows1250, "windows-1250"},
"windows-1250": {charmap.Windows1250, "windows-1250"},
"x-cp1250": {charmap.Windows1250, "windows-1250"},
"cp1251": {charmap.Windows1251, "windows-1251"},
"windows-1251": {charmap.Windows1251, "windows-1251"},
"x-cp1251": {charmap.Windows1251, "windows-1251"},
"ansi_x3.4-1968": {charmap.Windows1252, "windows-1252"},
"ascii": {charmap.Windows1252, "windows-1252"},
"cp1252": {charmap.Windows1252, "windows-1252"},
"cp819": {charmap.Windows1252, "windows-1252"},
"csisolatin1": {charmap.Windows1252, "windows-1252"},
"ibm819": {charmap.Windows1252, "windows-1252"},
"iso-8859-1": {charmap.Windows1252, "windows-1252"},
"iso-ir-100": {charmap.Windows1252, "windows-1252"},
"iso8859-1": {charmap.Windows1252, "windows-1252"},
"iso88591": {charmap.Windows1252, "windows-1252"},
"iso_8859-1": {charmap.Windows1252, "windows-1252"},
"iso_8859-1:1987": {charmap.Windows1252, "windows-1252"},
"l1": {charmap.Windows1252, "windows-1252"},
"latin1": {charmap.Windows1252, "windows-1252"},
"us-ascii": {charmap.Windows1252, "windows-1252"},
"windows-1252": {charmap.Windows1252, "windows-1252"},
"x-cp1252": {charmap.Windows1252, "windows-1252"},
"cp1253": {charmap.Windows1253, "windows-1253"},
"windows-1253": {charmap.Windows1253, "windows-1253"},
"x-cp1253": {charmap.Windows1253, "windows-1253"},
"cp1254": {charmap.Windows1254, "windows-1254"},
"csisolatin5": {charmap.Windows1254, "windows-1254"},
"iso-8859-9": {charmap.Windows1254, "windows-1254"},
"iso-ir-148": {charmap.Windows1254, "windows-1254"},
"iso8859-9": {charmap.Windows1254, "windows-1254"},
"iso88599": {charmap.Windows1254, "windows-1254"},
"iso_8859-9": {charmap.Windows1254, "windows-1254"},
"iso_8859-9:1989": {charmap.Windows1254, "windows-1254"},
"l5": {charmap.Windows1254, "windows-1254"},
"latin5": {charmap.Windows1254, "windows-1254"},
"windows-1254": {charmap.Windows1254, "windows-1254"},
"x-cp1254": {charmap.Windows1254, "windows-1254"},
"cp1255": {charmap.Windows1255, "windows-1255"},
"windows-1255": {charmap.Windows1255, "windows-1255"},
"x-cp1255": {charmap.Windows1255, "windows-1255"},
"cp1256": {charmap.Windows1256, "windows-1256"},
"windows-1256": {charmap.Windows1256, "windows-1256"},
"x-cp1256": {charmap.Windows1256, "windows-1256"},
"cp1257": {charmap.Windows1257, "windows-1257"},
"windows-1257": {charmap.Windows1257, "windows-1257"},
"x-cp1257": {charmap.Windows1257, "windows-1257"},
"cp1258": {charmap.Windows1258, "windows-1258"},
"windows-1258": {charmap.Windows1258, "windows-1258"},
"x-cp1258": {charmap.Windows1258, "windows-1258"},
"x-mac-cyrillic": {charmap.MacintoshCyrillic, "x-mac-cyrillic"},
"x-mac-ukrainian": {charmap.MacintoshCyrillic, "x-mac-cyrillic"},
"chinese": {simplifiedchinese.GBK, "gbk"},
"csgb2312": {simplifiedchinese.GBK, "gbk"},
"csiso58gb231280": {simplifiedchinese.GBK, "gbk"},
"gb2312": {simplifiedchinese.GBK, "gbk"},
"gb_2312": {simplifiedchinese.GBK, "gbk"},
"gb_2312-80": {simplifiedchinese.GBK, "gbk"},
"gbk": {simplifiedchinese.GBK, "gbk"},
"iso-ir-58": {simplifiedchinese.GBK, "gbk"},
"x-gbk": {simplifiedchinese.GBK, "gbk"},
"gb18030": {simplifiedchinese.GB18030, "gb18030"},
"hz-gb-2312": {simplifiedchinese.HZGB2312, "hz-gb-2312"},
"big5": {traditionalchinese.Big5, "big5"},
"big5-hkscs": {traditionalchinese.Big5, "big5"},
"cn-big5": {traditionalchinese.Big5, "big5"},
"csbig5": {traditionalchinese.Big5, "big5"},
"x-x-big5": {traditionalchinese.Big5, "big5"},
"cseucpkdfmtjapanese": {japanese.EUCJP, "euc-jp"},
"euc-jp": {japanese.EUCJP, "euc-jp"},
"x-euc-jp": {japanese.EUCJP, "euc-jp"},
"csiso2022jp": {japanese.ISO2022JP, "iso-2022-jp"},
"iso-2022-jp": {japanese.ISO2022JP, "iso-2022-jp"},
"csshiftjis": {japanese.ShiftJIS, "shift_jis"},
"ms_kanji": {japanese.ShiftJIS, "shift_jis"},
"shift-jis": {japanese.ShiftJIS, "shift_jis"},
"shift_jis": {japanese.ShiftJIS, "shift_jis"},
"sjis": {japanese.ShiftJIS, "shift_jis"},
"windows-31j": {japanese.ShiftJIS, "shift_jis"},
"x-sjis": {japanese.ShiftJIS, "shift_jis"},
"cseuckr": {korean.EUCKR, "euc-kr"},
"csksc56011987": {korean.EUCKR, "euc-kr"},
"euc-kr": {korean.EUCKR, "euc-kr"},
"iso-ir-149": {korean.EUCKR, "euc-kr"},
"korean": {korean.EUCKR, "euc-kr"},
"ks_c_5601-1987": {korean.EUCKR, "euc-kr"},
"ks_c_5601-1989": {korean.EUCKR, "euc-kr"},
"ksc5601": {korean.EUCKR, "euc-kr"},
"ksc_5601": {korean.EUCKR, "euc-kr"},
"windows-949": {korean.EUCKR, "euc-kr"},
"csiso2022kr": {encoding.Replacement, "replacement"},
"iso-2022-kr": {encoding.Replacement, "replacement"},
"iso-2022-cn": {encoding.Replacement, "replacement"},
"iso-2022-cn-ext": {encoding.Replacement, "replacement"},
"utf-16be": {unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM), "utf-16be"},
"utf-16": {unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM), "utf-16le"},
"utf-16le": {unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM), "utf-16le"},
"x-user-defined": {charmap.XUserDefined, "x-user-defined"},
}

197
vendor/github.com/pingcap/tidb/util/codec/bytes.go generated vendored Normal file
View file

@ -0,0 +1,197 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package codec
import (
"bytes"
"encoding/binary"
"runtime"
"unsafe"
"github.com/juju/errors"
)
const (
encGroupSize = 8
encMarker = byte(0xFF)
encPad = byte(0x0)
)
var (
pads = make([]byte, encGroupSize)
encPads = []byte{encPad}
)
// EncodeBytes guarantees the encoded value is in ascending order for comparison,
// encoding with the following rule:
// [group1][marker1]...[groupN][markerN]
// group is 8 bytes slice which is padding with 0.
// marker is `0xFF - padding 0 count`
// For example:
// [] -> [0, 0, 0, 0, 0, 0, 0, 0, 247]
// [1, 2, 3] -> [1, 2, 3, 0, 0, 0, 0, 0, 250]
// [1, 2, 3, 0] -> [1, 2, 3, 0, 0, 0, 0, 0, 251]
// [1, 2, 3, 4, 5, 6, 7, 8] -> [1, 2, 3, 4, 5, 6, 7, 8, 255, 0, 0, 0, 0, 0, 0, 0, 0, 247]
// Refer: https://github.com/facebook/mysql-5.6/wiki/MyRocks-record-format#memcomparable-format
func EncodeBytes(b []byte, data []byte) []byte {
// Allocate more space to avoid unnecessary slice growing.
// Assume that the byte slice size is about `(len(data) / encGroupSize + 1) * (encGroupSize + 1)` bytes,
// that is `(len(data) / 8 + 1) * 9` in our implement.
dLen := len(data)
reallocSize := (dLen/encGroupSize + 1) * (encGroupSize + 1)
result := reallocBytes(b, reallocSize)
for idx := 0; idx <= dLen; idx += encGroupSize {
remain := dLen - idx
padCount := 0
if remain >= encGroupSize {
result = append(result, data[idx:idx+encGroupSize]...)
} else {
padCount = encGroupSize - remain
result = append(result, data[idx:]...)
result = append(result, pads[:padCount]...)
}
marker := encMarker - byte(padCount)
result = append(result, marker)
}
return result
}
func decodeBytes(b []byte, reverse bool) ([]byte, []byte, error) {
data := make([]byte, 0, len(b))
for {
if len(b) < encGroupSize+1 {
return nil, nil, errors.New("insufficient bytes to decode value")
}
groupBytes := b[:encGroupSize+1]
if reverse {
reverseBytes(groupBytes)
}
group := groupBytes[:encGroupSize]
marker := groupBytes[encGroupSize]
// Check validity of marker.
padCount := encMarker - marker
realGroupSize := encGroupSize - padCount
if padCount > encGroupSize {
return nil, nil, errors.Errorf("invalid marker byte, group bytes %q", groupBytes)
}
data = append(data, group[:realGroupSize]...)
b = b[encGroupSize+1:]
if marker != encMarker {
// Check validity of padding bytes.
if bytes.Count(group[realGroupSize:], encPads) != int(padCount) {
return nil, nil, errors.Errorf("invalid padding byte, group bytes %q", groupBytes)
}
break
}
}
return b, data, nil
}
// DecodeBytes decodes bytes which is encoded by EncodeBytes before,
// returns the leftover bytes and decoded value if no error.
func DecodeBytes(b []byte) ([]byte, []byte, error) {
return decodeBytes(b, false)
}
// EncodeBytesDesc first encodes bytes using EncodeBytes, then bitwise reverses
// encoded value to guarantee the encoded value is in descending order for comparison.
func EncodeBytesDesc(b []byte, data []byte) []byte {
n := len(b)
b = EncodeBytes(b, data)
reverseBytes(b[n:])
return b
}
// DecodeBytesDesc decodes bytes which is encoded by EncodeBytesDesc before,
// returns the leftover bytes and decoded value if no error.
func DecodeBytesDesc(b []byte) ([]byte, []byte, error) {
return decodeBytes(b, true)
}
// EncodeCompactBytes joins bytes with its length into a byte slice. It is more
// efficient in both space and time compare to EncodeBytes. Note that the encoded
// result is not memcomparable.
func EncodeCompactBytes(b []byte, data []byte) []byte {
b = reallocBytes(b, binary.MaxVarintLen64+len(data))
b = EncodeVarint(b, int64(len(data)))
return append(b, data...)
}
// DecodeCompactBytes decodes bytes which is encoded by EncodeCompactBytes before.
func DecodeCompactBytes(b []byte) ([]byte, []byte, error) {
b, n, err := DecodeVarint(b)
if err != nil {
return nil, nil, errors.Trace(err)
}
if int64(len(b)) < n {
return nil, nil, errors.Errorf("insufficient bytes to decode value, expected length: %v", n)
}
return b[n:], b[:n], nil
}
// See https://golang.org/src/crypto/cipher/xor.go
const wordSize = int(unsafe.Sizeof(uintptr(0)))
const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64"
func fastReverseBytes(b []byte) {
n := len(b)
w := n / wordSize
if w > 0 {
bw := *(*[]uintptr)(unsafe.Pointer(&b))
for i := 0; i < w; i++ {
bw[i] = ^bw[i]
}
}
for i := w * wordSize; i < n; i++ {
b[i] = ^b[i]
}
}
func safeReverseBytes(b []byte) {
for i := range b {
b[i] = ^b[i]
}
}
func reverseBytes(b []byte) {
if supportsUnaligned {
fastReverseBytes(b)
return
}
safeReverseBytes(b)
}
// like realloc.
func reallocBytes(b []byte, n int) []byte {
newSize := len(b) + n
if cap(b) < newSize {
bs := make([]byte, len(b), newSize)
copy(bs, b)
return bs
}
// slice b has capability to store n bytes
return b
}

165
vendor/github.com/pingcap/tidb/util/codec/codec.go generated vendored Normal file
View file

@ -0,0 +1,165 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package codec
import (
"time"
"github.com/juju/errors"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/util/types"
)
const (
nilFlag byte = iota
bytesFlag
compactBytesFlag
intFlag
uintFlag
floatFlag
decimalFlag
durationFlag
)
func encode(b []byte, vals []types.Datum, comparable bool) ([]byte, error) {
for _, val := range vals {
switch val.Kind() {
case types.KindInt64:
b = append(b, intFlag)
b = EncodeInt(b, val.GetInt64())
case types.KindUint64:
b = append(b, uintFlag)
b = EncodeUint(b, val.GetUint64())
case types.KindFloat32, types.KindFloat64:
b = append(b, floatFlag)
b = EncodeFloat(b, val.GetFloat64())
case types.KindString, types.KindBytes:
b = encodeBytes(b, val.GetBytes(), comparable)
case types.KindMysqlTime:
b = encodeBytes(b, []byte(val.GetMysqlTime().String()), comparable)
case types.KindMysqlDuration:
// duration may have negative value, so we cannot use String to encode directly.
b = append(b, durationFlag)
b = EncodeInt(b, int64(val.GetMysqlDuration().Duration))
case types.KindMysqlDecimal:
b = append(b, decimalFlag)
b = EncodeDecimal(b, val.GetMysqlDecimal())
case types.KindMysqlHex:
b = append(b, intFlag)
b = EncodeInt(b, int64(val.GetMysqlHex().ToNumber()))
case types.KindMysqlBit:
b = append(b, uintFlag)
b = EncodeUint(b, uint64(val.GetMysqlBit().ToNumber()))
case types.KindMysqlEnum:
b = append(b, uintFlag)
b = EncodeUint(b, uint64(val.GetMysqlEnum().ToNumber()))
case types.KindMysqlSet:
b = append(b, uintFlag)
b = EncodeUint(b, uint64(val.GetMysqlSet().ToNumber()))
case types.KindNull:
b = append(b, nilFlag)
default:
return nil, errors.Errorf("unsupport encode type %d", val.Kind())
}
}
return b, nil
}
func encodeBytes(b []byte, v []byte, comparable bool) []byte {
if comparable {
b = append(b, bytesFlag)
b = EncodeBytes(b, v)
} else {
b = append(b, compactBytesFlag)
b = EncodeCompactBytes(b, v)
}
return b
}
// EncodeKey appends the encoded values to byte slice b, returns the appended
// slice. It guarantees the encoded value is in ascending order for comparison.
func EncodeKey(b []byte, v ...types.Datum) ([]byte, error) {
return encode(b, v, true)
}
// EncodeValue appends the encoded values to byte slice b, returning the appended
// slice. It does not guarantee the order for comparison.
func EncodeValue(b []byte, v ...types.Datum) ([]byte, error) {
return encode(b, v, false)
}
// Decode decodes values from a byte slice generated with EncodeKey or EncodeValue
// before.
func Decode(b []byte) ([]types.Datum, error) {
if len(b) < 1 {
return nil, errors.New("invalid encoded key")
}
var (
flag byte
err error
values = make([]types.Datum, 0, 1)
)
for len(b) > 0 {
flag = b[0]
b = b[1:]
var d types.Datum
switch flag {
case intFlag:
var v int64
b, v, err = DecodeInt(b)
d.SetInt64(v)
case uintFlag:
var v uint64
b, v, err = DecodeUint(b)
d.SetUint64(v)
case floatFlag:
var v float64
b, v, err = DecodeFloat(b)
d.SetFloat64(v)
case bytesFlag:
var v []byte
b, v, err = DecodeBytes(b)
d.SetBytes(v)
case compactBytesFlag:
var v []byte
b, v, err = DecodeCompactBytes(b)
d.SetBytes(v)
case decimalFlag:
var v mysql.Decimal
b, v, err = DecodeDecimal(b)
d.SetValue(v)
case durationFlag:
var r int64
b, r, err = DecodeInt(b)
if err == nil {
// use max fsp, let outer to do round manually.
v := mysql.Duration{Duration: time.Duration(r), Fsp: mysql.MaxFsp}
d.SetValue(v)
}
case nilFlag:
default:
return nil, errors.Errorf("invalid encoded key flag %v", flag)
}
if err != nil {
return nil, errors.Trace(err)
}
values = append(values, d)
}
return values, nil
}

183
vendor/github.com/pingcap/tidb/util/codec/decimal.go generated vendored Normal file
View file

@ -0,0 +1,183 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package codec
import (
"bytes"
"math/big"
"github.com/juju/errors"
"github.com/pingcap/tidb/mysql"
)
const (
negativeSign int64 = 8
zeroSign int64 = 16
positiveSign int64 = 24
)
func codecSign(value int64) int64 {
if value < 0 {
return negativeSign
}
return positiveSign
}
func encodeExp(expValue int64, expSign int64, valSign int64) int64 {
if expSign == negativeSign {
expValue = -expValue
}
if expSign != valSign {
expValue = ^expValue
}
return expValue
}
func decodeExp(expValue int64, expSign int64, valSign int64) int64 {
if expSign != valSign {
expValue = ^expValue
}
if expSign == negativeSign {
expValue = -expValue
}
return expValue
}
func codecValue(value []byte, valSign int64) {
if valSign == negativeSign {
reverseBytes(value)
}
}
// EncodeDecimal encodes a decimal d into a byte slice which can be sorted lexicographically later.
// EncodeDecimal guarantees that the encoded value is in ascending order for comparison.
// Decimal encoding:
// Byte -> value sign
// Byte -> exp sign
// EncodeInt -> exp value
// EncodeBytes -> abs value bytes
func EncodeDecimal(b []byte, d mysql.Decimal) []byte {
if d.Equals(mysql.ZeroDecimal) {
return append(b, byte(zeroSign))
}
v := d.BigIntValue()
valSign := codecSign(int64(v.Sign()))
absVal := new(big.Int)
absVal.Abs(v)
value := []byte(absVal.String())
// Trim right side "0", like "12.34000" -> "12.34" or "0.1234000" -> "0.1234".
if d.Exponent() != 0 {
value = bytes.TrimRight(value, "0")
}
// Get exp and value, format is "value":"exp".
// like "12.34" -> "0.1234":"2".
// like "-0.01234" -> "-0.1234":"-1".
exp := int64(0)
div := big.NewInt(10)
for ; ; exp++ {
if absVal.Sign() == 0 {
break
}
absVal = absVal.Div(absVal, div)
}
expVal := exp + int64(d.Exponent())
expSign := codecSign(expVal)
// For negtive exp, do bit reverse for exp.
// For negtive decimal, do bit reverse for exp and value.
expVal = encodeExp(expVal, expSign, valSign)
codecValue(value, valSign)
b = append(b, byte(valSign))
b = append(b, byte(expSign))
b = EncodeInt(b, expVal)
b = EncodeBytes(b, value)
return b
}
// DecodeDecimal decodes bytes to decimal.
// DecodeFloat decodes a float from a byte slice
// Decimal decoding:
// Byte -> value sign
// Byte -> exp sign
// DecodeInt -> exp value
// DecodeBytes -> abs value bytes
func DecodeDecimal(b []byte) ([]byte, mysql.Decimal, error) {
var (
r = b
d mysql.Decimal
err error
)
// Decode value sign.
valSign := int64(r[0])
r = r[1:]
if valSign == zeroSign {
d, err = mysql.ParseDecimal("0")
return r, d, errors.Trace(err)
}
// Decode exp sign.
expSign := int64(r[0])
r = r[1:]
// Decode exp value.
expVal := int64(0)
r, expVal, err = DecodeInt(r)
if err != nil {
return r, d, errors.Trace(err)
}
expVal = decodeExp(expVal, expSign, valSign)
// Decode abs value bytes.
value := []byte{}
r, value, err = DecodeBytes(r)
if err != nil {
return r, d, errors.Trace(err)
}
codecValue(value, valSign)
// Generate decimal string value.
var decimalStr []byte
if valSign == negativeSign {
decimalStr = append(decimalStr, '-')
}
if expVal <= 0 {
// Like decimal "0.1234" or "0.01234".
decimalStr = append(decimalStr, '0')
decimalStr = append(decimalStr, '.')
decimalStr = append(decimalStr, bytes.Repeat([]byte{'0'}, -int(expVal))...)
decimalStr = append(decimalStr, value...)
} else {
// Like decimal "12.34".
decimalStr = append(decimalStr, value[:expVal]...)
decimalStr = append(decimalStr, '.')
decimalStr = append(decimalStr, value[expVal:]...)
}
d, err = mysql.ParseDecimal(string(decimalStr))
return r, d, errors.Trace(err)
}

65
vendor/github.com/pingcap/tidb/util/codec/float.go generated vendored Normal file
View file

@ -0,0 +1,65 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package codec
import (
"math"
"github.com/juju/errors"
)
func encodeFloatToCmpUint64(f float64) uint64 {
u := math.Float64bits(f)
if f >= 0 {
u |= signMask
} else {
u = ^u
}
return u
}
func decodeCmpUintToFloat(u uint64) float64 {
if u&signMask > 0 {
u &= ^signMask
} else {
u = ^u
}
return math.Float64frombits(u)
}
// EncodeFloat encodes a float v into a byte slice which can be sorted lexicographically later.
// EncodeFloat guarantees that the encoded value is in ascending order for comparison.
func EncodeFloat(b []byte, v float64) []byte {
u := encodeFloatToCmpUint64(v)
return EncodeUint(b, u)
}
// DecodeFloat decodes a float from a byte slice generated with EncodeFloat before.
func DecodeFloat(b []byte) ([]byte, float64, error) {
b, u, err := DecodeUint(b)
return b, decodeCmpUintToFloat(u), errors.Trace(err)
}
// EncodeFloatDesc encodes a float v into a byte slice which can be sorted lexicographically later.
// EncodeFloatDesc guarantees that the encoded value is in descending order for comparison.
func EncodeFloatDesc(b []byte, v float64) []byte {
u := encodeFloatToCmpUint64(v)
return EncodeUintDesc(b, u)
}
// DecodeFloatDesc decodes a float from a byte slice generated with EncodeFloatDesc before.
func DecodeFloatDesc(b []byte) ([]byte, float64, error) {
b, u, err := DecodeUintDesc(b)
return b, decodeCmpUintToFloat(u), errors.Trace(err)
}

170
vendor/github.com/pingcap/tidb/util/codec/number.go generated vendored Normal file
View file

@ -0,0 +1,170 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package codec
import (
"encoding/binary"
"github.com/juju/errors"
)
const signMask uint64 = 0x8000000000000000
func encodeIntToCmpUint(v int64) uint64 {
u := uint64(v)
if u&signMask > 0 {
u &= ^signMask
} else {
u |= signMask
}
return u
}
func decodeCmpUintToInt(u uint64) int64 {
if u&signMask > 0 {
u &= ^signMask
} else {
u |= signMask
}
return int64(u)
}
// EncodeInt appends the encoded value to slice b and returns the appended slice.
// EncodeInt guarantees that the encoded value is in ascending order for comparison.
func EncodeInt(b []byte, v int64) []byte {
var data [8]byte
u := encodeIntToCmpUint(v)
binary.BigEndian.PutUint64(data[:], u)
return append(b, data[:]...)
}
// EncodeIntDesc appends the encoded value to slice b and returns the appended slice.
// EncodeIntDesc guarantees that the encoded value is in descending order for comparison.
func EncodeIntDesc(b []byte, v int64) []byte {
var data [8]byte
u := encodeIntToCmpUint(v)
binary.BigEndian.PutUint64(data[:], ^u)
return append(b, data[:]...)
}
// DecodeInt decodes value encoded by EncodeInt before.
// It returns the leftover un-decoded slice, decoded value if no error.
func DecodeInt(b []byte) ([]byte, int64, error) {
if len(b) < 8 {
return nil, 0, errors.New("insufficient bytes to decode value")
}
u := binary.BigEndian.Uint64(b[:8])
v := decodeCmpUintToInt(u)
b = b[8:]
return b, v, nil
}
// DecodeIntDesc decodes value encoded by EncodeInt before.
// It returns the leftover un-decoded slice, decoded value if no error.
func DecodeIntDesc(b []byte) ([]byte, int64, error) {
if len(b) < 8 {
return nil, 0, errors.New("insufficient bytes to decode value")
}
u := binary.BigEndian.Uint64(b[:8])
v := decodeCmpUintToInt(^u)
b = b[8:]
return b, v, nil
}
// EncodeUint appends the encoded value to slice b and returns the appended slice.
// EncodeUint guarantees that the encoded value is in ascending order for comparison.
func EncodeUint(b []byte, v uint64) []byte {
var data [8]byte
binary.BigEndian.PutUint64(data[:], v)
return append(b, data[:]...)
}
// EncodeUintDesc appends the encoded value to slice b and returns the appended slice.
// EncodeUintDesc guarantees that the encoded value is in descending order for comparison.
func EncodeUintDesc(b []byte, v uint64) []byte {
var data [8]byte
binary.BigEndian.PutUint64(data[:], ^v)
return append(b, data[:]...)
}
// DecodeUint decodes value encoded by EncodeUint before.
// It returns the leftover un-decoded slice, decoded value if no error.
func DecodeUint(b []byte) ([]byte, uint64, error) {
if len(b) < 8 {
return nil, 0, errors.New("insufficient bytes to decode value")
}
v := binary.BigEndian.Uint64(b[:8])
b = b[8:]
return b, v, nil
}
// DecodeUintDesc decodes value encoded by EncodeInt before.
// It returns the leftover un-decoded slice, decoded value if no error.
func DecodeUintDesc(b []byte) ([]byte, uint64, error) {
if len(b) < 8 {
return nil, 0, errors.New("insufficient bytes to decode value")
}
data := b[:8]
v := binary.BigEndian.Uint64(data)
b = b[8:]
return b, ^v, nil
}
// EncodeVarint appends the encoded value to slice b and returns the appended slice.
// Note that the encoded result is not memcomparable.
func EncodeVarint(b []byte, v int64) []byte {
var data [binary.MaxVarintLen64]byte
n := binary.PutVarint(data[:], v)
return append(b, data[:n]...)
}
// DecodeVarint decodes value encoded by EncodeVarint before.
// It returns the leftover un-decoded slice, decoded value if no error.
func DecodeVarint(b []byte) ([]byte, int64, error) {
v, n := binary.Varint(b)
if n > 0 {
return b[n:], v, nil
}
if n < 0 {
return nil, 0, errors.New("value larger than 64 bits")
}
return nil, 0, errors.New("insufficient bytes to decode value")
}
// EncodeUvarint appends the encoded value to slice b and returns the appended slice.
// Note that the encoded result is not memcomparable.
func EncodeUvarint(b []byte, v uint64) []byte {
var data [binary.MaxVarintLen64]byte
n := binary.PutUvarint(data[:], v)
return append(b, data[:n]...)
}
// DecodeUvarint decodes value encoded by EncodeUvarint before.
// It returns the leftover un-decoded slice, decoded value if no error.
func DecodeUvarint(b []byte) ([]byte, uint64, error) {
v, n := binary.Uvarint(b)
if n > 0 {
return b[n:], v, nil
}
if n < 0 {
return nil, 0, errors.New("value larger than 64 bits")
}
return nil, 0, errors.New("insufficient bytes to decode value")
}

View file

@ -0,0 +1,47 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package distinct
import (
"github.com/juju/errors"
"github.com/pingcap/tidb/util/codec"
"github.com/pingcap/tidb/util/types"
)
// CreateDistinctChecker creates a new distinct checker.
func CreateDistinctChecker() *Checker {
return &Checker{
existingKeys: make(map[string]bool),
}
}
// Checker stores existing keys and checks if given data is distinct.
type Checker struct {
existingKeys map[string]bool
}
// Check checks if values is distinct.
func (d *Checker) Check(values []interface{}) (bool, error) {
bs, err := codec.EncodeValue([]byte{}, types.MakeDatums(values...)...)
if err != nil {
return false, errors.Trace(err)
}
key := string(bs)
_, ok := d.existingKeys[key]
if ok {
return false, nil
}
d.existingKeys[key] = true
return true, nil
}

43
vendor/github.com/pingcap/tidb/util/hack/hack.go generated vendored Normal file
View file

@ -0,0 +1,43 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package hack
import (
"reflect"
"unsafe"
)
// String converts slice to string without copy.
// Use at your own risk.
func String(b []byte) (s string) {
if len(b) == 0 {
return ""
}
pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))
pstring.Data = pbytes.Data
pstring.Len = pbytes.Len
return
}
// Slice converts string to slice without copy.
// Use at your own risk.
func Slice(s string) (b []byte) {
pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))
pbytes.Data = pstring.Data
pbytes.Len = pstring.Len
pbytes.Cap = pstring.Len
return
}

97
vendor/github.com/pingcap/tidb/util/prefix_helper.go generated vendored Normal file
View file

@ -0,0 +1,97 @@
// Copyright 2014 The ql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSES/QL-LICENSE file.
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package util
import (
"bytes"
"github.com/juju/errors"
"github.com/pingcap/tidb/kv"
)
// ScanMetaWithPrefix scans metadata with the prefix.
func ScanMetaWithPrefix(retriever kv.Retriever, prefix kv.Key, filter func(kv.Key, []byte) bool) error {
iter, err := retriever.Seek(prefix)
if err != nil {
return errors.Trace(err)
}
defer iter.Close()
for {
if err != nil {
return errors.Trace(err)
}
if iter.Valid() && iter.Key().HasPrefix(prefix) {
if !filter(iter.Key(), iter.Value()) {
break
}
err = iter.Next()
if err != nil {
return errors.Trace(err)
}
} else {
break
}
}
return nil
}
// DelKeyWithPrefix deletes keys with prefix.
func DelKeyWithPrefix(rm kv.RetrieverMutator, prefix kv.Key) error {
var keys []kv.Key
iter, err := rm.Seek(prefix)
if err != nil {
return errors.Trace(err)
}
defer iter.Close()
for {
if err != nil {
return errors.Trace(err)
}
if iter.Valid() && iter.Key().HasPrefix(prefix) {
keys = append(keys, iter.Key().Clone())
err = iter.Next()
if err != nil {
return errors.Trace(err)
}
} else {
break
}
}
for _, key := range keys {
err := rm.Delete(key)
if err != nil {
return errors.Trace(err)
}
}
return nil
}
// RowKeyPrefixFilter returns a function which checks whether currentKey has decoded rowKeyPrefix as prefix.
func RowKeyPrefixFilter(rowKeyPrefix kv.Key) kv.FnKeyCmp {
return func(currentKey kv.Key) bool {
// Next until key without prefix of this record.
return !bytes.HasPrefix(currentKey, rowKeyPrefix)
}
}

View file

@ -0,0 +1,81 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package segmentmap
import (
"hash/crc32"
"github.com/juju/errors"
)
// SegmentMap is used for handle a big map slice by slice.
// It's not thread safe.
type SegmentMap struct {
size int64
maps []map[string]interface{}
crcTable *crc32.Table
}
// NewSegmentMap create a new SegmentMap.
func NewSegmentMap(size int64) (*SegmentMap, error) {
if size <= 0 {
return nil, errors.Errorf("Invalid size: %d", size)
}
sm := &SegmentMap{
maps: make([]map[string]interface{}, size),
size: size,
}
for i := int64(0); i < size; i++ {
sm.maps[i] = make(map[string]interface{})
}
sm.crcTable = crc32.MakeTable(crc32.Castagnoli)
return sm, nil
}
// Get is the same as map[k].
func (sm *SegmentMap) Get(key []byte) (interface{}, bool) {
idx := int64(crc32.Checksum(key, sm.crcTable)) % sm.size
val, ok := sm.maps[idx][string(key)]
return val, ok
}
// GetSegment gets the map specific by index.
func (sm *SegmentMap) GetSegment(index int64) (map[string]interface{}, error) {
if index >= sm.size || index < 0 {
return nil, errors.Errorf("index out of bound: %d", index)
}
return sm.maps[index], nil
}
// Set if key not exists, returns whether already exists.
func (sm *SegmentMap) Set(key []byte, value interface{}, force bool) bool {
idx := int64(crc32.Checksum(key, sm.crcTable)) % sm.size
k := string(key)
_, exist := sm.maps[idx][k]
if exist && !force {
return exist
}
sm.maps[idx][k] = value
return exist
}
// SegmentCount returns how many inner segments.
func (sm *SegmentMap) SegmentCount() int64 {
return sm.size
}

View file

@ -0,0 +1,36 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package sqlexec
import (
"github.com/pingcap/tidb/ast"
"github.com/pingcap/tidb/context"
)
// RestrictedSQLExecutor is an interface provides executing restricted sql statement.
// Why we need this interface?
// When we execute some management statements, we need to operate system tables.
// For example when executing create user statement, we need to check if the user already
// exists in the mysql.User table and insert a new row if not exists. In this case, we need
// a convenience way to manipulate system tables. The most simple way is executing sql statement.
// In order to execute sql statement in stmts package, we add this interface to solve dependence problem.
// And in the same time, we do not want this interface becomes a general way to run sql statement.
// We hope this could be used with some restrictions such as only allowing system tables as target,
// do not allowing recursion call.
// For more infomation please refer to the comments in session.ExecRestrictedSQL().
// This is implemented in session.go.
type RestrictedSQLExecutor interface {
// ExecRestrictedSQL run sql statement in ctx with some restriction.
ExecRestrictedSQL(ctx context.Context, sql string) (ast.RecordSet, error)
}

View file

@ -0,0 +1,53 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package stringutil
import (
"bytes"
"strings"
)
// See: https://dev.mysql.com/doc/refman/5.7/en/string-literals.html#character-escape-sequences
const validEscapeChars = `0'"bntrz\\%_`
// RemoveUselessBackslash removes backslashs which could be ignored in the string literal.
// See: https://dev.mysql.com/doc/refman/5.7/en/string-literals.html
// " Each of these sequences begins with a backslash (“\”), known as the escape character.
// MySQL recognizes the escape sequences shown in Table 9.1, “Special Character Escape Sequences”.
// For all other escape sequences, backslash is ignored. That is, the escaped character is
// interpreted as if it was not escaped. For example, “\x” is just “x”. These sequences are case sensitive.
// For example, “\b” is interpreted as a backspace, but “\B” is interpreted as “B”."
func RemoveUselessBackslash(s string) string {
var (
buf bytes.Buffer
i = 0
)
for i < len(s)-1 {
if s[i] != '\\' {
buf.WriteByte(s[i])
i++
continue
}
next := s[i+1]
if strings.IndexByte(validEscapeChars, next) != -1 {
buf.WriteByte(s[i])
}
buf.WriteByte(next)
i += 2
}
if i == len(s)-1 {
buf.WriteByte(s[i])
}
return buf.String()
}

72
vendor/github.com/pingcap/tidb/util/types/compare.go generated vendored Normal file
View file

@ -0,0 +1,72 @@
// Copyright 2014 The ql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSES/QL-LICENSE file.
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package types
// CompareInt64 returns an integer comparing the int64 x to y.
func CompareInt64(x, y int64) int {
if x < y {
return -1
} else if x == y {
return 0
}
return 1
}
// CompareUint64 returns an integer comparing the uint64 x to y.
func CompareUint64(x, y uint64) int {
if x < y {
return -1
} else if x == y {
return 0
}
return 1
}
// CompareFloat64 returns an integer comparing the float64 x to y.
func CompareFloat64(x, y float64) int {
if x < y {
return -1
} else if x == y {
return 0
}
return 1
}
// CompareString returns an integer comparing the string x to y.
func CompareString(x, y string) int {
if x < y {
return -1
} else if x == y {
return 0
}
return 1
}
// Compare returns an integer comparing the interface a with b.
// a > b -> 1
// a = b -> 0
// a < b -> -1
func Compare(a, b interface{}) (int, error) {
aDatum := NewDatum(a)
bDatum := NewDatum(b)
return aDatum.CompareDatum(bDatum)
}

437
vendor/github.com/pingcap/tidb/util/types/convert.go generated vendored Normal file
View file

@ -0,0 +1,437 @@
// Copyright 2014 The ql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSES/QL-LICENSE file.
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"math"
"strconv"
"strings"
"unicode"
"github.com/juju/errors"
"github.com/pingcap/tidb/mysql"
)
// InvConv returns a failed convertion error.
func invConv(val interface{}, tp byte) (interface{}, error) {
return nil, errors.Errorf("cannot convert %v (type %T) to type %s", val, val, TypeStr(tp))
}
func truncateStr(str string, flen int) string {
if flen != UnspecifiedLength && len(str) > flen {
str = str[:flen]
}
return str
}
var unsignedUpperBound = map[byte]uint64{
mysql.TypeTiny: math.MaxUint8,
mysql.TypeShort: math.MaxUint16,
mysql.TypeInt24: mysql.MaxUint24,
mysql.TypeLong: math.MaxUint32,
mysql.TypeLonglong: math.MaxUint64,
mysql.TypeBit: math.MaxUint64,
mysql.TypeEnum: math.MaxUint64,
mysql.TypeSet: math.MaxUint64,
}
var signedUpperBound = map[byte]int64{
mysql.TypeTiny: math.MaxInt8,
mysql.TypeShort: math.MaxInt16,
mysql.TypeInt24: mysql.MaxInt24,
mysql.TypeLong: math.MaxInt32,
mysql.TypeLonglong: math.MaxInt64,
}
var signedLowerBound = map[byte]int64{
mysql.TypeTiny: math.MinInt8,
mysql.TypeShort: math.MinInt16,
mysql.TypeInt24: mysql.MinInt24,
mysql.TypeLong: math.MinInt32,
mysql.TypeLonglong: math.MinInt64,
}
func convertFloatToInt(val float64, lowerBound int64, upperBound int64, tp byte) (int64, error) {
val = RoundFloat(val)
if val < float64(lowerBound) {
return lowerBound, overflow(val, tp)
}
if val > float64(upperBound) {
return upperBound, overflow(val, tp)
}
return int64(val), nil
}
func convertIntToInt(val int64, lowerBound int64, upperBound int64, tp byte) (int64, error) {
if val < lowerBound {
return lowerBound, overflow(val, tp)
}
if val > upperBound {
return upperBound, overflow(val, tp)
}
return val, nil
}
func convertUintToInt(val uint64, upperBound int64, tp byte) (int64, error) {
if val > uint64(upperBound) {
return upperBound, overflow(val, tp)
}
return int64(val), nil
}
func convertToInt(val interface{}, target *FieldType) (int64, error) {
tp := target.Tp
lowerBound := signedLowerBound[tp]
upperBound := signedUpperBound[tp]
switch v := val.(type) {
case bool:
if v {
return 1, nil
}
return 0, nil
case uint64:
return convertUintToInt(v, upperBound, tp)
case int:
return convertIntToInt(int64(v), lowerBound, upperBound, tp)
case int64:
return convertIntToInt(int64(v), lowerBound, upperBound, tp)
case float32:
return convertFloatToInt(float64(v), lowerBound, upperBound, tp)
case float64:
return convertFloatToInt(float64(v), lowerBound, upperBound, tp)
case string:
fval, err := StrToFloat(v)
if err != nil {
return 0, errors.Trace(err)
}
return convertFloatToInt(fval, lowerBound, upperBound, tp)
case []byte:
fval, err := StrToFloat(string(v))
if err != nil {
return 0, errors.Trace(err)
}
return convertFloatToInt(fval, lowerBound, upperBound, tp)
case mysql.Time:
// 2011-11-10 11:11:11.999999 -> 20111110111112
ival := v.ToNumber().Round(0).IntPart()
return convertIntToInt(ival, lowerBound, upperBound, tp)
case mysql.Duration:
// 11:11:11.999999 -> 111112
ival := v.ToNumber().Round(0).IntPart()
return convertIntToInt(ival, lowerBound, upperBound, tp)
case mysql.Decimal:
fval, _ := v.Float64()
return convertFloatToInt(fval, lowerBound, upperBound, tp)
case mysql.Hex:
return convertFloatToInt(v.ToNumber(), lowerBound, upperBound, tp)
case mysql.Bit:
return convertFloatToInt(v.ToNumber(), lowerBound, upperBound, tp)
case mysql.Enum:
return convertFloatToInt(v.ToNumber(), lowerBound, upperBound, tp)
case mysql.Set:
return convertFloatToInt(v.ToNumber(), lowerBound, upperBound, tp)
}
return 0, typeError(val, target)
}
func convertIntToUint(val int64, upperBound uint64, tp byte) (uint64, error) {
if val < 0 {
return 0, overflow(val, tp)
}
if uint64(val) > upperBound {
return upperBound, overflow(val, tp)
}
return uint64(val), nil
}
func convertUintToUint(val uint64, upperBound uint64, tp byte) (uint64, error) {
if val > upperBound {
return upperBound, overflow(val, tp)
}
return val, nil
}
func convertFloatToUint(val float64, upperBound uint64, tp byte) (uint64, error) {
val = RoundFloat(val)
if val < 0 {
return uint64(int64(val)), overflow(val, tp)
}
if val > float64(upperBound) {
return upperBound, overflow(val, tp)
}
return uint64(val), nil
}
// typeError returns error for invalid value type.
func typeError(v interface{}, target *FieldType) error {
return errors.Errorf("cannot use %v (type %T) in assignment to, or comparison with, column type %s)",
v, v, target.String())
}
func isCastType(tp byte) bool {
switch tp {
case mysql.TypeString, mysql.TypeDuration, mysql.TypeDatetime,
mysql.TypeDate, mysql.TypeLonglong, mysql.TypeNewDecimal:
return true
}
return false
}
// Cast casts val to certain types and does not return error.
func Cast(val interface{}, target *FieldType) (interface{}, error) {
if !isCastType(target.Tp) {
return nil, errors.Errorf("unknown cast type - %v", target)
}
return Convert(val, target)
}
// Convert converts the val with type tp.
func Convert(val interface{}, target *FieldType) (v interface{}, err error) {
d := NewDatum(val)
ret, err := d.ConvertTo(target)
if err != nil {
return ret.GetValue(), errors.Trace(err)
}
return ret.GetValue(), nil
}
// StrToInt converts a string to an integer in best effort.
// TODO: handle overflow and add unittest.
func StrToInt(str string) (int64, error) {
str = strings.TrimSpace(str)
if len(str) == 0 {
return 0, nil
}
negative := false
i := 0
if str[i] == '-' {
negative = true
i++
} else if str[i] == '+' {
i++
}
r := int64(0)
for ; i < len(str); i++ {
if !unicode.IsDigit(rune(str[i])) {
break
}
r = r*10 + int64(str[i]-'0')
}
if negative {
r = -r
}
// TODO: if i < len(str), we should return an error.
return r, nil
}
// StrToFloat converts a string to a float64 in best effort.
func StrToFloat(str string) (float64, error) {
str = strings.TrimSpace(str)
if len(str) == 0 {
return 0, nil
}
// MySQL uses a very loose conversation, e.g, 123.abc -> 123
// We should do a trade off whether supporting this feature or using a strict mode.
// Now we use a strict mode.
return strconv.ParseFloat(str, 64)
}
// ToInt64 converts an interface to an int64.
func ToInt64(value interface{}) (int64, error) {
return convertToInt(value, NewFieldType(mysql.TypeLonglong))
}
// ToFloat64 converts an interface to a float64.
func ToFloat64(value interface{}) (float64, error) {
switch v := value.(type) {
case bool:
if v {
return 1, nil
}
return 0, nil
case int:
return float64(v), nil
case int64:
return float64(v), nil
case uint64:
return float64(v), nil
case float32:
return float64(v), nil
case float64:
return float64(v), nil
case string:
return StrToFloat(v)
case []byte:
return StrToFloat(string(v))
case mysql.Time:
f, _ := v.ToNumber().Float64()
return f, nil
case mysql.Duration:
f, _ := v.ToNumber().Float64()
return f, nil
case mysql.Decimal:
vv, _ := v.Float64()
return vv, nil
case mysql.Hex:
return v.ToNumber(), nil
case mysql.Bit:
return v.ToNumber(), nil
case mysql.Enum:
return v.ToNumber(), nil
case mysql.Set:
return v.ToNumber(), nil
default:
return 0, errors.Errorf("cannot convert %v(type %T) to float64", value, value)
}
}
// ToDecimal converts an interface to a Decimal.
func ToDecimal(value interface{}) (mysql.Decimal, error) {
switch v := value.(type) {
case bool:
if v {
return mysql.ConvertToDecimal(1)
}
return mysql.ConvertToDecimal(0)
case []byte:
return mysql.ConvertToDecimal(string(v))
case mysql.Time:
return v.ToNumber(), nil
case mysql.Duration:
return v.ToNumber(), nil
default:
return mysql.ConvertToDecimal(value)
}
}
// ToString converts an interface to a string.
func ToString(value interface{}) (string, error) {
switch v := value.(type) {
case bool:
if v {
return "1", nil
}
return "0", nil
case int:
return strconv.FormatInt(int64(v), 10), nil
case int64:
return strconv.FormatInt(int64(v), 10), nil
case uint64:
return strconv.FormatUint(uint64(v), 10), nil
case float32:
return strconv.FormatFloat(float64(v), 'f', -1, 32), nil
case float64:
return strconv.FormatFloat(float64(v), 'f', -1, 64), nil
case string:
return v, nil
case []byte:
return string(v), nil
case mysql.Time:
return v.String(), nil
case mysql.Duration:
return v.String(), nil
case mysql.Decimal:
return v.String(), nil
case mysql.Hex:
return v.ToString(), nil
case mysql.Bit:
return v.ToString(), nil
case mysql.Enum:
return v.String(), nil
case mysql.Set:
return v.String(), nil
default:
return "", errors.Errorf("cannot convert %v(type %T) to string", value, value)
}
}
// ToBool converts an interface to a bool.
// We will use 1 for true, and 0 for false.
func ToBool(value interface{}) (int64, error) {
isZero := false
switch v := value.(type) {
case bool:
isZero = (v == false)
case int:
isZero = (v == 0)
case int64:
isZero = (v == 0)
case uint64:
isZero = (v == 0)
case float32:
isZero = (v == 0)
case float64:
isZero = (v == 0)
case string:
if len(v) == 0 {
isZero = true
} else {
n, err := StrToInt(v)
if err != nil {
return 0, err
}
isZero = (n == 0)
}
case []byte:
if len(v) == 0 {
isZero = true
} else {
n, err := StrToInt(string(v))
if err != nil {
return 0, err
}
isZero = (n == 0)
}
case mysql.Time:
isZero = v.IsZero()
case mysql.Duration:
isZero = (v.Duration == 0)
case mysql.Decimal:
vv, _ := v.Float64()
isZero = (vv == 0)
case mysql.Hex:
isZero = (v.ToNumber() == 0)
case mysql.Bit:
isZero = (v.ToNumber() == 0)
case mysql.Enum:
isZero = (v.ToNumber() == 0)
case mysql.Set:
isZero = (v.ToNumber() == 0)
default:
return 0, errors.Errorf("cannot convert %v(type %T) to bool", value, value)
}
if isZero {
return 0, nil
}
return 1, nil
}

1249
vendor/github.com/pingcap/tidb/util/types/datum.go generated vendored Normal file

File diff suppressed because it is too large Load diff

310
vendor/github.com/pingcap/tidb/util/types/etc.go generated vendored Normal file
View file

@ -0,0 +1,310 @@
// Copyright 2014 The ql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSES/QL-LICENSE file.
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"fmt"
"io"
"strings"
"github.com/juju/errors"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/parser/opcode"
"github.com/pingcap/tidb/terror"
"github.com/pingcap/tidb/util/charset"
)
// IsTypeBlob returns a boolean indicating whether the tp is a blob type.
func IsTypeBlob(tp byte) bool {
switch tp {
case mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeBlob, mysql.TypeLongBlob:
return true
default:
return false
}
}
// IsTypeChar returns a boolean indicating
// whether the tp is the char type like a string type or a varchar type.
func IsTypeChar(tp byte) bool {
switch tp {
case mysql.TypeString, mysql.TypeVarchar:
return true
default:
return false
}
}
var type2Str = map[byte]string{
mysql.TypeBit: "bit",
mysql.TypeBlob: "text",
mysql.TypeDate: "date",
mysql.TypeDatetime: "datetime",
mysql.TypeDecimal: "decimal",
mysql.TypeNewDecimal: "decimal",
mysql.TypeDouble: "double",
mysql.TypeEnum: "enum",
mysql.TypeFloat: "float",
mysql.TypeGeometry: "geometry",
mysql.TypeInt24: "mediumint",
mysql.TypeLong: "int",
mysql.TypeLonglong: "bigint",
mysql.TypeLongBlob: "longtext",
mysql.TypeMediumBlob: "mediumtext",
mysql.TypeNull: "null",
mysql.TypeSet: "set",
mysql.TypeShort: "smallint",
mysql.TypeString: "char",
mysql.TypeDuration: "time",
mysql.TypeTimestamp: "timestamp",
mysql.TypeTiny: "tinyint",
mysql.TypeTinyBlob: "tinytext",
mysql.TypeVarchar: "varchar",
mysql.TypeVarString: "var_string",
mysql.TypeYear: "year",
}
// TypeStr converts tp to a string.
func TypeStr(tp byte) (r string) {
return type2Str[tp]
}
// TypeToStr converts a field to a string.
// It is used for converting Text to Blob,
// or converting Char to Binary.
// Args:
// tp: type enum
// cs: charset
func TypeToStr(tp byte, cs string) (r string) {
ts := type2Str[tp]
if cs != charset.CharsetBin {
return ts
}
if IsTypeBlob(tp) {
ts = strings.Replace(ts, "text", "blob", 1)
} else if IsTypeChar(tp) {
ts = strings.Replace(ts, "char", "binary", 1)
}
return ts
}
// EOFAsNil filtrates errors,
// If err is equal to io.EOF returns nil.
func EOFAsNil(err error) error {
if terror.ErrorEqual(err, io.EOF) {
return nil
}
return errors.Trace(err)
}
// InvOp2 returns an invalid operation error.
func InvOp2(x, y interface{}, o opcode.Op) (interface{}, error) {
return nil, errors.Errorf("Invalid operation: %v %v %v (mismatched types %T and %T)", x, o, y, x, y)
}
// UndOp returns an undefined error.
func UndOp(x interface{}, o opcode.Op) (interface{}, error) {
return nil, errors.Errorf("Invalid operation: %v%v (operator %v not defined on %T)", o, x, o, x)
}
// Overflow returns an overflowed error.
func overflow(v interface{}, tp byte) error {
return errors.Errorf("constant %v overflows %s", v, TypeStr(tp))
}
// TODO: collate should return errors from Compare.
func collate(x, y []interface{}) (r int) {
nx, ny := len(x), len(y)
switch {
case nx == 0 && ny != 0:
return -1
case nx == 0 && ny == 0:
return 0
case nx != 0 && ny == 0:
return 1
}
r = 1
if nx > ny {
x, y, r = y, x, -r
}
for i, xi := range x {
// TODO: we may remove collate later, so here just panic error.
c, err := Compare(xi, y[i])
if err != nil {
panic(fmt.Sprintf("should never happend %v", err))
}
if c != 0 {
return c * r
}
}
if nx == ny {
return 0
}
return -r
}
// Collators maps a boolean value to a collated function.
var Collators = map[bool]func(a, b []interface{}) int{false: collateDesc, true: collate}
func collateDesc(a, b []interface{}) int {
return -collate(a, b)
}
// IsOrderedType returns a boolean
// whether the type of y can be used by order by.
func IsOrderedType(v interface{}) (r bool) {
switch v.(type) {
case int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64,
float32, float64, string, []byte,
mysql.Decimal, mysql.Time, mysql.Duration,
mysql.Hex, mysql.Bit, mysql.Enum, mysql.Set:
return true
}
return false
}
// Clone copies an interface to another interface.
// It does a deep copy.
func Clone(from interface{}) (interface{}, error) {
if from == nil {
return nil, nil
}
switch x := from.(type) {
case uint8, uint16, uint32, uint64, float32, float64,
int16, int8, bool, string, int, int64, int32,
mysql.Time, mysql.Duration, mysql.Decimal,
mysql.Hex, mysql.Bit, mysql.Enum, mysql.Set:
return x, nil
case []byte:
target := make([]byte, len(from.([]byte)))
copy(target, from.([]byte))
return target, nil
case []interface{}:
var r []interface{}
for _, v := range from.([]interface{}) {
vv, err := Clone(v)
if err != nil {
return nil, err
}
r = append(r, vv)
}
return r, nil
default:
return nil, errors.Errorf("Clone invalid type %T", from)
}
}
func convergeType(a interface{}, hasDecimal, hasFloat *bool) (x interface{}) {
x = a
switch v := a.(type) {
case bool:
// treat bool as 1 and 0
if v {
x = int64(1)
} else {
x = int64(0)
}
case int:
x = int64(v)
case int8:
x = int64(v)
case int16:
x = int64(v)
case int32:
x = int64(v)
case int64:
x = int64(v)
case uint:
x = uint64(v)
case uint8:
x = uint64(v)
case uint16:
x = uint64(v)
case uint32:
x = uint64(v)
case uint64:
x = uint64(v)
case float32:
x = float64(v)
*hasFloat = true
case float64:
x = float64(v)
*hasFloat = true
case mysql.Decimal:
x = v
*hasDecimal = true
}
return
}
// Coerce changes type.
// If a or b is Decimal, changes the both to Decimal.
// Else if a or b is Float, changes the both to Float.
func Coerce(a, b interface{}) (x, y interface{}) {
var hasDecimal bool
var hasFloat bool
x = convergeType(a, &hasDecimal, &hasFloat)
y = convergeType(b, &hasDecimal, &hasFloat)
if hasDecimal {
d, err := mysql.ConvertToDecimal(x)
if err == nil {
x = d
}
d, err = mysql.ConvertToDecimal(y)
if err == nil {
y = d
}
} else if hasFloat {
switch v := x.(type) {
case int64:
x = float64(v)
case uint64:
x = float64(v)
case mysql.Hex:
x = v.ToNumber()
case mysql.Bit:
x = v.ToNumber()
case mysql.Enum:
x = v.ToNumber()
case mysql.Set:
x = v.ToNumber()
}
switch v := y.(type) {
case int64:
y = float64(v)
case uint64:
y = float64(v)
case mysql.Hex:
y = v.ToNumber()
case mysql.Bit:
y = v.ToNumber()
case mysql.Enum:
y = v.ToNumber()
case mysql.Set:
y = v.ToNumber()
}
}
return
}

1045
vendor/github.com/pingcap/tidb/util/types/field_type.go generated vendored Normal file

File diff suppressed because it is too large Load diff

111
vendor/github.com/pingcap/tidb/util/types/helper.go generated vendored Normal file
View file

@ -0,0 +1,111 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"math"
"github.com/juju/errors"
"github.com/pingcap/tidb/mysql"
)
// RoundFloat rounds float val to the nearest integer value with float64 format, like GNU rint function.
// RoundFloat uses default rounding mode, see http://www.gnu.org/software/libc/manual/html_node/Rounding.html
// so we will choose the even number if the result is midway between two representable value.
// e.g, 1.5 -> 2, 2.5 -> 2.
func RoundFloat(f float64) float64 {
if math.Remainder(f, 1.0) < 0 {
return math.Ceil(f)
}
return math.Floor(f)
}
func getMaxFloat(flen int, decimal int) float64 {
intPartLen := flen - decimal
f := math.Pow10(intPartLen)
f -= math.Pow10(-decimal)
return f
}
func truncateFloat(f float64, decimal int) float64 {
pow := math.Pow10(decimal)
t := (f - math.Floor(f)) * pow
round := RoundFloat(t)
f = math.Floor(f) + round/pow
return f
}
// TruncateFloat tries to truncate f.
// If the result exceeds the max/min float that flen/decimal allowed, returns the max/min float allowed.
func TruncateFloat(f float64, flen int, decimal int) (float64, error) {
if math.IsNaN(f) {
// nan returns 0
return 0, nil
}
maxF := getMaxFloat(flen, decimal)
if !math.IsInf(f, 0) {
f = truncateFloat(f, decimal)
}
if f > maxF {
f = maxF
} else if f < -maxF {
f = -maxF
}
return f, nil
}
// CalculateSum adds v to sum.
func CalculateSum(sum interface{}, v interface{}) (interface{}, error) {
// for avg and sum calculation
// avg and sum use decimal for integer and decimal type, use float for others
// see https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html
var (
data interface{}
err error
)
switch y := v.(type) {
case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
data, err = mysql.ConvertToDecimal(v)
case mysql.Decimal:
data = y
case nil:
data = nil
default:
data, err = ToFloat64(v)
}
if err != nil {
return nil, errors.Trace(err)
}
if data == nil {
return sum, nil
}
switch x := sum.(type) {
case nil:
return data, nil
case float64:
return x + data.(float64), nil
case mysql.Decimal:
return x.Add(data.(mysql.Decimal)), nil
default:
return nil, errors.Errorf("invalid value %v(%T) for aggregate", x, x)
}
}

191
vendor/github.com/pingcap/tidb/util/types/overflow.go generated vendored Normal file
View file

@ -0,0 +1,191 @@
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"math"
"github.com/juju/errors"
)
// ErrArithOverflow is the error for arthimetic operation overflow.
var ErrArithOverflow = errors.New("operation overflow")
// AddUint64 adds uint64 a and b if no overflow, else returns error.
func AddUint64(a uint64, b uint64) (uint64, error) {
if math.MaxUint64-a < b {
return 0, errors.Trace(ErrArithOverflow)
}
return a + b, nil
}
// AddInt64 adds int64 a and b if no overflow, otherwise returns error.
func AddInt64(a int64, b int64) (int64, error) {
if (a > 0 && b > 0 && math.MaxInt64-a < b) ||
(a < 0 && b < 0 && math.MinInt64-a > b) {
return 0, errors.Trace(ErrArithOverflow)
}
return a + b, nil
}
// AddInteger adds uint64 a and int64 b and returns uint64 if no overflow error.
func AddInteger(a uint64, b int64) (uint64, error) {
if b >= 0 {
return AddUint64(a, uint64(b))
}
if uint64(-b) > a {
return 0, errors.Trace(ErrArithOverflow)
}
return a - uint64(-b), nil
}
// SubUint64 substracts uint64 a with b and returns uint64 if no overflow error.
func SubUint64(a uint64, b uint64) (uint64, error) {
if a < b {
return 0, errors.Trace(ErrArithOverflow)
}
return a - b, nil
}
// SubInt64 substracts int64 a with b and returns int64 if no overflow error.
func SubInt64(a int64, b int64) (int64, error) {
if (a > 0 && b < 0 && math.MaxInt64-a < -b) ||
(a < 0 && b > 0 && math.MinInt64-a > -b) ||
(a == 0 && b == math.MinInt64) {
return 0, errors.Trace(ErrArithOverflow)
}
return a - b, nil
}
// SubUintWithInt substracts uint64 a with int64 b and returns uint64 if no overflow error.
func SubUintWithInt(a uint64, b int64) (uint64, error) {
if b < 0 {
return AddUint64(a, uint64(-b))
}
return SubUint64(a, uint64(b))
}
// SubIntWithUint substracts int64 a with uint64 b and returns uint64 if no overflow error.
func SubIntWithUint(a int64, b uint64) (uint64, error) {
if a < 0 || uint64(a) < b {
return 0, errors.Trace(ErrArithOverflow)
}
return uint64(a) - b, nil
}
// MulUint64 multiplies uint64 a and b and returns uint64 if no overflow error.
func MulUint64(a uint64, b uint64) (uint64, error) {
if b > 0 && a > math.MaxUint64/b {
return 0, errors.Trace(ErrArithOverflow)
}
return a * b, nil
}
// MulInt64 multiplies int64 a and b and returns int64 if no overflow error.
func MulInt64(a int64, b int64) (int64, error) {
if a == 0 || b == 0 {
return 0, nil
}
var (
res uint64
err error
negative = false
)
if a > 0 && b > 0 {
res, err = MulUint64(uint64(a), uint64(b))
} else if a < 0 && b < 0 {
res, err = MulUint64(uint64(-a), uint64(-b))
} else if a < 0 && b > 0 {
negative = true
res, err = MulUint64(uint64(-a), uint64(b))
} else {
negative = true
res, err = MulUint64(uint64(a), uint64(-b))
}
if err != nil {
return 0, errors.Trace(err)
}
if negative {
// negative result
if res > math.MaxInt64+1 {
return 0, errors.Trace(ErrArithOverflow)
}
return -int64(res), nil
}
// positive result
if res > math.MaxInt64 {
return 0, errors.Trace(ErrArithOverflow)
}
return int64(res), nil
}
// MulInteger multiplies uint64 a and int64 b, and returns uint64 if no overflow error.
func MulInteger(a uint64, b int64) (uint64, error) {
if a == 0 || b == 0 {
return 0, nil
}
if b < 0 {
return 0, errors.Trace(ErrArithOverflow)
}
return MulUint64(a, uint64(b))
}
// DivInt64 divides int64 a with b, returns int64 if no overflow error.
// It just checks overflow, if b is zero, a "divide by zero" panic throws.
func DivInt64(a int64, b int64) (int64, error) {
if a == math.MinInt64 && b == -1 {
return 0, errors.Trace(ErrArithOverflow)
}
return a / b, nil
}
// DivUintWithInt divides uint64 a with int64 b, returns uint64 if no overflow error.
// It just checks overflow, if b is zero, a "divide by zero" panic throws.
func DivUintWithInt(a uint64, b int64) (uint64, error) {
if b < 0 {
if a != 0 && uint64(-b) <= a {
return 0, errors.Trace(ErrArithOverflow)
}
return 0, nil
}
return a / uint64(b), nil
}
// DivIntWithUint divides int64 a with uint64 b, returns uint64 if no overflow error.
// It just checks overflow, if b is zero, a "divide by zero" panic throws.
func DivIntWithUint(a int64, b uint64) (uint64, error) {
if a < 0 {
if uint64(-a) >= b {
return 0, errors.Trace(ErrArithOverflow)
}
return 0, nil
}
return uint64(a) / b, nil
}