github.com/XiaoMi/Gaea@v1.2.5/models/shard.go (about) 1 // Copyright 2019 The Gaea Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package models 16 17 import ( 18 "fmt" 19 "github.com/XiaoMi/Gaea/core/errors" 20 "regexp" 21 "strconv" 22 ) 23 24 // constants of shard type 25 const ( 26 ShardDefault = "default" 27 ShardGlobal = "global" 28 ShardLinked = "linked" 29 ShardMod = "mod" 30 ShardHash = "hash" 31 ShardRange = "range" 32 ShardYear = "date_year" 33 ShardMonth = "date_month" 34 ShardDay = "date_day" 35 ShardMycatMod = "mycat_mod" 36 ShardMycatLong = "mycat_long" 37 ShardMycatString = "mycat_string" 38 ShardMycatMURMUR = "mycat_murmur" 39 ShardMycatPaddingMod = "mycat_padding_mod" 40 41 // PartitionLength length of partition 42 PartitionLength = 1024 43 44 // mod padding 45 PaddingModLeftEnd = 0 46 PaddingModRightEnd = 1 47 48 PaddingModDefaultPadFrom = PaddingModRightEnd 49 PaddingModDefaultPadLength = 18 50 PaddingModDefaultModBegin = 10 51 PaddingModDefaultModEnd = 16 52 PaddingModDefaultMod = 2 53 ) 54 55 // Shard means shard model in etcd 56 type Shard struct { 57 DB string `json:"db"` 58 Table string `json:"table"` 59 ParentTable string `json:"parent_table"` 60 Type string `json:"type"` // 表类型: 包括分表如hash/range/data,关联表如: linked 全局表如: global等 61 Key string `json:"key"` 62 Locations []int `json:"locations"` 63 Slices []string `json:"slices"` 64 DateRange []string `json:"date_range"` 65 TableRowLimit int `json:"table_row_limit"` 66 67 // only used in mycat logic database (schema) 68 Databases []string `json:"databases"` 69 70 // used in mycat partition long shard and partition string shard 71 PartitionCount string `json:"partition_count"` 72 PartitionLength string `json:"partition_length"` 73 74 // used in mycat partition string shard 75 HashSlice string `json:"hash_slice"` 76 77 // used in mycat murmur hash shard 78 Seed string `json:"seed"` 79 VirtualBucketTimes string `json:"virtual_bucket_times"` 80 81 // used in mycat padding mod shard 82 PadFrom string `json:"pad_from"` 83 PadLength string `json:"pad_length"` 84 ModBegin string `json:"mod_begin"` 85 ModEnd string `json:"mod_end"` 86 } 87 88 func (s *Shard) verify() error { 89 if err := s.verifyRuleSliceInfos(); err != nil { 90 return err 91 } 92 return nil 93 } 94 95 func (s *Shard) verifyRuleSliceInfos() error { 96 f, ok := ruleVerifyFuncMapping[s.Type] 97 if !ok { 98 return errors.ErrUnknownRuleType 99 } 100 return f(s) 101 } 102 103 // Encode encode json 104 func (s *Shard) Encode() []byte { 105 return JSONEncode(s) 106 } 107 108 func IsMycatShardingRule(ruleType string) bool { 109 return ruleType == ShardMod || ruleType == ShardMycatLong || ruleType == ShardMycatMURMUR || ruleType == ShardMycatPaddingMod || ruleType == ShardMycatString 110 } 111 112 var rangeDatabaseRegex = regexp.MustCompile(`^(\S+?)\[(\d+)-(\d+)\]$`) 113 114 // if a dbname is a database list, then parse the real dbnames and add to the result. 115 // the range contains left bound and right bound, which means [left, right]. 116 func getRealDatabases(dbs []string) ([]string, error) { 117 var ret []string 118 for _, db := range dbs { 119 if rangeDatabaseRegex.MatchString(db) { 120 matches := rangeDatabaseRegex.FindStringSubmatch(db) 121 if len(matches) != 4 { 122 return nil, fmt.Errorf("invalid database list: %s", db) 123 } 124 dbPrefix := matches[1] 125 leftBoundStr := matches[2] 126 rightBoundStr := matches[3] 127 leftBound, err := strconv.Atoi(leftBoundStr) 128 if err != nil { 129 return nil, fmt.Errorf("invalid left bound value of database list: %s", db) 130 } 131 rightBound, err := strconv.Atoi(rightBoundStr) 132 if err != nil { 133 return nil, fmt.Errorf("invalid right bound value of database list: %s", db) 134 } 135 if rightBound <= leftBound { 136 return nil, fmt.Errorf("invalid bound value of database list: %s", db) 137 } 138 for i := leftBound; i <= rightBound; i++ { 139 realDB := dbPrefix + strconv.Itoa(i) 140 ret = append(ret, realDB) 141 } 142 } else { 143 ret = append(ret, db) 144 } 145 } 146 return ret, nil 147 }