github.com/XiaoMi/Gaea@v1.2.5/proxy/sequence/mysql.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 sequence 16 17 import ( 18 "errors" 19 "fmt" 20 "strconv" 21 "strings" 22 "sync" 23 24 "github.com/XiaoMi/Gaea/backend" 25 ) 26 27 // MySQLSequence struct of sequence number with specific sequence name 28 type MySQLSequence struct { 29 slice *backend.Slice 30 pkName string 31 seqName string 32 lock *sync.Mutex 33 curr int64 34 max int64 35 sql string 36 } 37 38 // NewMySQLSequence init sequence item 39 // TODO: 直接注入slice需要考虑关闭的问题, 目前是在Namespace中管理Slice的关闭的. 如果单独使用MySQLSequence, 需要注意. 40 func NewMySQLSequence(slice *backend.Slice, seqName, pkName string) *MySQLSequence { 41 t := &MySQLSequence{ 42 slice: slice, 43 seqName: seqName, 44 pkName: pkName, 45 lock: new(sync.Mutex), 46 curr: 0, 47 max: 0, 48 sql: "SELECT mycat_seq_nextval('" + seqName + "') as seq_val", 49 } 50 return t 51 } 52 53 // NextSeq get next sequence number 54 func (s *MySQLSequence) NextSeq() (int64, error) { 55 s.lock.Lock() 56 defer s.lock.Unlock() 57 if s.curr >= s.max { 58 err := s.getSeqFromDB() 59 if err != nil { 60 return 0, err 61 } 62 } 63 s.curr++ 64 return s.curr, nil 65 } 66 67 // GetPKName return sequence column 68 func (s *MySQLSequence) GetPKName() string { 69 return s.pkName 70 } 71 72 func (s *MySQLSequence) getSeqFromDB() error { 73 conn, err := s.slice.GetMasterConn() 74 if err != nil { 75 return err 76 } 77 defer conn.Recycle() 78 79 err = conn.UseDB("mycat") 80 if err != nil { 81 return err 82 } 83 84 r, err := conn.Execute(s.sql, 0) 85 if err != nil { 86 return err 87 } 88 89 ret, err := r.Resultset.GetString(0, 0) 90 if err != nil { 91 return err 92 } 93 94 ns := strings.Split(ret, ",") 95 if len(ns) != 2 { 96 return errors.New(fmt.Sprintf("invalid mycat sequence value %s %s", s.seqName, ret)) 97 } 98 99 curr, _ := strconv.ParseInt(ns[0], 10, 64) 100 incr, _ := strconv.ParseInt(ns[1], 10, 64) 101 s.max = curr + incr 102 s.curr = curr 103 return nil 104 }