github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/sequence.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package dbs 15 16 import ( 17 "math" 18 19 "github.com/cznic/mathutil" 20 "github.com/whtcorpsinc/errors" 21 "github.com/whtcorpsinc/BerolinaSQL/ast" 22 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 23 "github.com/whtcorpsinc/milevadb/dbs/soliton" 24 "github.com/whtcorpsinc/milevadb/schemareplicant" 25 "github.com/whtcorpsinc/milevadb/spacetime" 26 math2 "github.com/whtcorpsinc/milevadb/soliton/math" 27 ) 28 29 func onCreateSequence(d *dbsCtx, t *spacetime.Meta, job *perceptron.Job) (ver int64, _ error) { 30 schemaID := job.SchemaID 31 tbInfo := &perceptron.BlockInfo{} 32 if err := job.DecodeArgs(tbInfo); err != nil { 33 // Invalid arguments, cancel this job. 34 job.State = perceptron.JobStateCancelled 35 return ver, errors.Trace(err) 36 } 37 38 tbInfo.State = perceptron.StateNone 39 err := checkBlockNotExists(d, t, schemaID, tbInfo.Name.L) 40 if err != nil { 41 if schemareplicant.ErrDatabaseNotExists.Equal(err) || schemareplicant.ErrBlockExists.Equal(err) { 42 job.State = perceptron.JobStateCancelled 43 } 44 return ver, errors.Trace(err) 45 } 46 47 ver, err = uFIDelateSchemaVersion(t, job) 48 if err != nil { 49 return ver, errors.Trace(err) 50 } 51 52 switch tbInfo.State { 53 case perceptron.StateNone: 54 // none -> public 55 tbInfo.State = perceptron.StatePublic 56 tbInfo.UFIDelateTS = t.StartTS 57 err = createSequenceWithCheck(t, job, schemaID, tbInfo) 58 if err != nil { 59 return ver, errors.Trace(err) 60 } 61 // Finish this job. 62 job.FinishBlockJob(perceptron.JobStateDone, perceptron.StatePublic, ver, tbInfo) 63 asyncNotifyEvent(d, &soliton.Event{Tp: perceptron.CausetActionCreateSequence, BlockInfo: tbInfo}) 64 return ver, nil 65 default: 66 return ver, ErrInvalidDBSState.GenWithStackByArgs("sequence", tbInfo.State) 67 } 68 } 69 70 func createSequenceWithCheck(t *spacetime.Meta, job *perceptron.Job, schemaID int64, tbInfo *perceptron.BlockInfo) error { 71 err := checkBlockInfoValid(tbInfo) 72 if err != nil { 73 job.State = perceptron.JobStateCancelled 74 return errors.Trace(err) 75 } 76 var sequenceBase int64 77 if tbInfo.Sequence.Increment >= 0 { 78 sequenceBase = tbInfo.Sequence.Start - 1 79 } else { 80 sequenceBase = tbInfo.Sequence.Start + 1 81 } 82 return t.CreateSequenceAndSetSeqValue(schemaID, tbInfo, sequenceBase) 83 } 84 85 func handleSequenceOptions(SeqOptions []*ast.SequenceOption, sequenceInfo *perceptron.SequenceInfo) { 86 var ( 87 minSetFlag bool 88 maxSetFlag bool 89 startSetFlag bool 90 ) 91 for _, op := range SeqOptions { 92 switch op.Tp { 93 case ast.SequenceOptionIncrementBy: 94 sequenceInfo.Increment = op.IntValue 95 case ast.SequenceStartWith: 96 sequenceInfo.Start = op.IntValue 97 startSetFlag = true 98 case ast.SequenceMinValue: 99 sequenceInfo.MinValue = op.IntValue 100 minSetFlag = true 101 case ast.SequenceMaxValue: 102 sequenceInfo.MaxValue = op.IntValue 103 maxSetFlag = true 104 case ast.SequenceCache: 105 sequenceInfo.CacheValue = op.IntValue 106 case ast.SequenceNoCache: 107 sequenceInfo.Cache = false 108 case ast.SequenceCycle: 109 sequenceInfo.Cycle = true 110 case ast.SequenceNoCycle: 111 sequenceInfo.Cycle = false 112 } 113 } 114 // Fill the default value, min/max/start should be adjusted with the sign of sequenceInfo.Increment. 115 if !(minSetFlag && maxSetFlag && startSetFlag) { 116 if sequenceInfo.Increment >= 0 { 117 if !minSetFlag { 118 sequenceInfo.MinValue = perceptron.DefaultPositiveSequenceMinValue 119 } 120 if !startSetFlag { 121 sequenceInfo.Start = mathutil.MaxInt64(sequenceInfo.MinValue, perceptron.DefaultPositiveSequenceStartValue) 122 } 123 if !maxSetFlag { 124 sequenceInfo.MaxValue = perceptron.DefaultPositiveSequenceMaxValue 125 } 126 } else { 127 if !maxSetFlag { 128 sequenceInfo.MaxValue = perceptron.DefaultNegativeSequenceMaxValue 129 } 130 if !startSetFlag { 131 sequenceInfo.Start = mathutil.MinInt64(sequenceInfo.MaxValue, perceptron.DefaultNegativeSequenceStartValue) 132 } 133 if !minSetFlag { 134 sequenceInfo.MinValue = perceptron.DefaultNegativeSequenceMinValue 135 } 136 } 137 } 138 } 139 140 func validateSequenceOptions(seqInfo *perceptron.SequenceInfo) bool { 141 // To ensure that cache * increment will never overflows. 142 var maxIncrement int64 143 if seqInfo.Increment == 0 { 144 // Increment shouldn't be set as 0. 145 return false 146 } 147 if seqInfo.CacheValue <= 0 { 148 // Cache value should be bigger than 0. 149 return false 150 } 151 maxIncrement = math2.Abs(seqInfo.Increment) 152 153 return seqInfo.MaxValue >= seqInfo.Start && 154 seqInfo.MaxValue > seqInfo.MinValue && 155 seqInfo.Start >= seqInfo.MinValue && 156 seqInfo.MaxValue != math.MaxInt64 && 157 seqInfo.MinValue != math.MinInt64 && 158 seqInfo.CacheValue < (math.MaxInt64-maxIncrement)/maxIncrement 159 } 160 161 func buildSequenceInfo(stmt *ast.CreateSequenceStmt, ident ast.Ident) (*perceptron.SequenceInfo, error) { 162 sequenceInfo := &perceptron.SequenceInfo{ 163 Cache: perceptron.DefaultSequenceCacheBool, 164 Cycle: perceptron.DefaultSequenceCycleBool, 165 CacheValue: perceptron.DefaultSequenceCacheValue, 166 Increment: perceptron.DefaultSequenceIncrementValue, 167 } 168 169 // Handle causet comment options. 170 for _, op := range stmt.TblOptions { 171 switch op.Tp { 172 case ast.BlockOptionComment: 173 sequenceInfo.Comment = op.StrValue 174 case ast.BlockOptionEngine: 175 // BlockOptionEngine will always be 'InnoDB', thus we do nothing in this branch to avoid error happening. 176 default: 177 return nil, ErrSequenceUnsupportedBlockOption.GenWithStackByArgs(op.StrValue) 178 } 179 } 180 handleSequenceOptions(stmt.SeqOptions, sequenceInfo) 181 if !validateSequenceOptions(sequenceInfo) { 182 return nil, ErrSequenceInvalidData.GenWithStackByArgs(ident.Schema.L, ident.Name.L) 183 } 184 return sequenceInfo, nil 185 }