github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/function/seqfunc.go (about) 1 // Copyright 2021 Matrix Origin 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 function 16 17 import ( 18 "fmt" 19 "math" 20 "strconv" 21 22 "github.com/matrixorigin/matrixone/pkg/catalog" 23 "github.com/matrixorigin/matrixone/pkg/common/moerr" 24 "github.com/matrixorigin/matrixone/pkg/container/types" 25 "github.com/matrixorigin/matrixone/pkg/container/vector" 26 "github.com/matrixorigin/matrixone/pkg/defines" 27 "github.com/matrixorigin/matrixone/pkg/sql/plan/function/functionUtil" 28 "github.com/matrixorigin/matrixone/pkg/txn/client" 29 "github.com/matrixorigin/matrixone/pkg/vm/engine" 30 "github.com/matrixorigin/matrixone/pkg/vm/process" 31 "golang.org/x/exp/constraints" 32 ) 33 34 // sequence functions 35 // XXX current impl of sequence starts its own transaction, which is debatable. 36 // We really should have done this the sameway as auto incr, but well, we did not. 37 // We may fix this in the future. For now, all code are moved from old seq without 38 // any change. 39 40 // seq function tests are not ported. mock table and txn are simply too much. 41 // we rely on bvt for sequence function tests. 42 43 var setEdge = true 44 45 // Retrieve values of this sequence. 46 // Set curval,lastval of current session. 47 // Set is_called to true if it is false, if is_]called is true Advance last_seq_num. 48 // Return advanced last_seq_num. 49 50 func Nextval(ivecs []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int) (err error) { 51 rs := vector.MustFunctionResult[types.Varlena](result) 52 ivec := vector.GenerateFunctionStrParameter(ivecs[0]) 53 54 // Here is the transaction 55 e := proc.Ctx.Value(defines.EngineKey{}).(engine.Engine) 56 txn := proc.TxnOperator 57 if txn == nil { 58 return moerr.NewInternalError(proc.Ctx, "Nextval: txn operator is nil") 59 } 60 61 // nextval is the real implementation of nextval function. 62 for i := uint64(0); i < uint64(length); i++ { 63 v, null := ivec.GetStrValue(i) 64 if null { 65 if err = rs.AppendBytes(nil, true); err != nil { 66 return 67 } 68 } else { 69 var res string 70 res, err = nextval(string(v), proc, e, txn) 71 if err == nil { 72 err = rs.AppendBytes(functionUtil.QuickStrToBytes(res), false) 73 } 74 if err != nil { 75 return 76 } 77 // set last val 78 if res != "" { 79 proc.SessionInfo.SeqLastValue[0] = res 80 } 81 } 82 } 83 return nil 84 } 85 86 func nextval(tblname string, proc *process.Process, e engine.Engine, txn client.TxnOperator) (string, error) { 87 db := proc.SessionInfo.Database 88 dbHandler, err := e.Database(proc.Ctx, db, txn) 89 if err != nil { 90 return "", err 91 } 92 rel, err := dbHandler.Relation(proc.Ctx, tblname, nil) 93 if err != nil { 94 return "", err 95 } 96 97 // Check is sequence table. 98 td, err := rel.TableDefs(proc.Ctx) 99 if err != nil { 100 return "", err 101 } 102 if td[len(td)-1].(*engine.PropertiesDef).Properties[0].Value != catalog.SystemSequenceRel { 103 return "", moerr.NewInternalError(proc.Ctx, "Table input is not a sequence") 104 } 105 106 values, err := proc.SessionInfo.SqlHelper.ExecSql(fmt.Sprintf("select * from `%s`.`%s`", db, tblname)) 107 if err != nil { 108 return "", err 109 } 110 if values == nil { 111 return "", moerr.NewInternalError(proc.Ctx, "Failed to get sequence meta data.") 112 } 113 114 switch values[0].(type) { 115 case int16: 116 // Get values store in sequence table. 117 lsn, minv, maxv, _, incrv, cycle, isCalled := values[0].(int16), values[1].(int16), values[2].(int16), 118 values[3].(int16), values[4].(int64), values[5].(bool), values[6].(bool) 119 // When iscalled is not set, set it and do not advance sequence number. 120 if !isCalled { 121 return setIsCalled(proc, rel, lsn, db, tblname) 122 } 123 // When incr is over the range of this datatype. 124 if incrv > math.MaxInt16 || incrv < math.MinInt16 { 125 if cycle { 126 return advanceSeq(lsn, minv, maxv, int16(incrv), cycle, incrv < 0, setEdge, rel, proc, db, tblname) 127 } else { 128 return "", moerr.NewInternalError(proc.Ctx, "Reached maximum value of sequence %s", tblname) 129 } 130 } 131 // Tranforming incrv to this datatype and make it positive for generic use. 132 return advanceSeq(lsn, minv, maxv, makePosIncr[int16](incrv), cycle, incrv < 0, !setEdge, rel, proc, db, tblname) 133 case int32: 134 lsn, minv, maxv, _, incrv, cycle, isCalled := values[0].(int32), values[1].(int32), values[2].(int32), 135 values[3].(int32), values[4].(int64), values[5].(bool), values[6].(bool) 136 if !isCalled { 137 return setIsCalled(proc, rel, lsn, db, tblname) 138 } 139 /* 140 no incrv can be bigger than maxint64 or smaller than minint64, therefore the following is noop 141 142 if incrv > math.MaxInt64 || incrv < math.MinInt64 { 143 if cycle { 144 return advanceSeq(lsn, minv, maxv, int32(incrv), cycle, incrv < 0, setEdge, rel, proc, db, tblname) 145 } else { 146 return "", moerr.NewInternalError(proc.Ctx, "Reached maximum value of sequence %s", tblname) 147 } 148 } 149 */ 150 return advanceSeq(lsn, minv, maxv, makePosIncr[int32](incrv), cycle, incrv < 0, !setEdge, rel, proc, db, tblname) 151 case int64: 152 lsn, minv, maxv, _, incrv, cycle, isCalled := values[0].(int64), values[1].(int64), values[2].(int64), 153 values[3].(int64), values[4].(int64), values[5].(bool), values[6].(bool) 154 if !isCalled { 155 return setIsCalled(proc, rel, lsn, db, tblname) 156 } 157 return advanceSeq(lsn, minv, maxv, makePosIncr[int64](incrv), cycle, incrv < 0, !setEdge, rel, proc, db, tblname) 158 case uint16: 159 lsn, minv, maxv, _, incrv, cycle, isCalled := values[0].(uint16), values[1].(uint16), values[2].(uint16), 160 values[3].(uint16), values[4].(int64), values[5].(bool), values[6].(bool) 161 if !isCalled { 162 return setIsCalled(proc, rel, lsn, db, tblname) 163 } 164 if incrv > math.MaxUint16 || -incrv > math.MaxUint16 { 165 if cycle { 166 return advanceSeq(lsn, minv, maxv, uint16(incrv), cycle, incrv < 0, setEdge, rel, proc, db, tblname) 167 } else { 168 return "", moerr.NewInternalError(proc.Ctx, "Reached maximum value of sequence %s", tblname) 169 } 170 } 171 return advanceSeq(lsn, minv, maxv, makePosIncr[uint16](incrv), cycle, incrv < 0, !setEdge, rel, proc, db, tblname) 172 case uint32: 173 lsn, minv, maxv, _, incrv, cycle, isCalled := values[0].(uint32), values[1].(uint32), values[2].(uint32), 174 values[3].(uint32), values[4].(int64), values[5].(bool), values[6].(bool) 175 if !isCalled { 176 return setIsCalled(proc, rel, lsn, db, tblname) 177 } 178 if incrv > math.MaxUint32 || -incrv > math.MaxUint32 { 179 if cycle { 180 return advanceSeq(lsn, minv, maxv, uint32(incrv), cycle, incrv < 0, setEdge, rel, proc, db, tblname) 181 } else { 182 return "", moerr.NewInternalError(proc.Ctx, "Reached maximum value of sequence %s", tblname) 183 } 184 } 185 return advanceSeq(lsn, minv, maxv, makePosIncr[uint32](incrv), cycle, incrv < 0, !setEdge, rel, proc, db, tblname) 186 case uint64: 187 lsn, minv, maxv, _, incrv, cycle, isCalled := values[0].(uint64), values[1].(uint64), values[2].(uint64), 188 values[3].(uint64), values[4].(int64), values[5].(bool), values[6].(bool) 189 if !isCalled { 190 return setIsCalled(proc, rel, lsn, db, tblname) 191 } 192 return advanceSeq(lsn, minv, maxv, makePosIncr[uint64](incrv), cycle, incrv < 0, !setEdge, rel, proc, db, tblname) 193 } 194 195 return "", moerr.NewInternalError(proc.Ctx, "Wrong types of sequence number or failed to read the sequence table") 196 } 197 198 func makePosIncr[T constraints.Integer](incr int64) T { 199 if incr < 0 { 200 return T(-incr) 201 } 202 return T(incr) 203 } 204 205 func advanceSeq[T constraints.Integer](lsn, minv, maxv, incrv T, 206 cycle, minus, setEdge bool, rel engine.Relation, proc *process.Process, db, tblname string) (string, error) { 207 if setEdge { 208 // Set lastseqnum to maxv when this is a descending sequence. 209 if minus { 210 return setSeq(proc, maxv, rel, db, tblname) 211 } 212 // Set lastseqnum to minv 213 return setSeq(proc, minv, rel, db, tblname) 214 } 215 var adseq T 216 if minus { 217 adseq = lsn - incrv 218 } else { 219 adseq = lsn + incrv 220 } 221 222 // check descending sequence and reach edge 223 if minus && (adseq < minv || adseq > lsn) { 224 if !cycle { 225 return "", moerr.NewInternalError(proc.Ctx, "Reached maximum value of sequence %s", tblname) 226 } 227 return setSeq(proc, maxv, rel, db, tblname) 228 } 229 230 // checkout ascending sequence and reach edge 231 if !minus && (adseq > maxv || adseq < lsn) { 232 if !cycle { 233 return "", moerr.NewInternalError(proc.Ctx, "Reached maximum value of sequence %s", tblname) 234 } 235 return setSeq(proc, minv, rel, db, tblname) 236 } 237 238 // Otherwise set to adseq. 239 return setSeq(proc, adseq, rel, db, tblname) 240 } 241 242 func setSeq[T constraints.Integer](proc *process.Process, setv T, rel engine.Relation, db, tbl string) (string, error) { 243 _, err := proc.SessionInfo.SqlHelper.ExecSql(fmt.Sprintf("update `%s`.`%s` set last_seq_num = %d", db, tbl, setv)) 244 if err != nil { 245 return "", err 246 } 247 248 tblId := rel.GetTableID(proc.Ctx) 249 ress := fmt.Sprint(setv) 250 251 // Set Curvalues here. Add new slot to proc's related field. 252 proc.SessionInfo.SeqAddValues[tblId] = ress 253 254 return ress, nil 255 } 256 257 func setIsCalled[T constraints.Integer](proc *process.Process, rel engine.Relation, lsn T, db, tbl string) (string, error) { 258 // Set is called to true. 259 _, err := proc.SessionInfo.SqlHelper.ExecSql(fmt.Sprintf("update `%s`.`%s` set is_called = true", db, tbl)) 260 if err != nil { 261 return "", err 262 } 263 264 tblId := rel.GetTableID(proc.Ctx) 265 ress := fmt.Sprint(lsn) 266 267 // Set Curvalues here. Add new slot to proc's related field. 268 proc.SessionInfo.SeqAddValues[tblId] = ress 269 270 return ress, nil 271 } 272 273 func Setval(ivecs []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int) (err error) { 274 rs := vector.MustFunctionResult[types.Varlena](result) 275 tblnames := vector.GenerateFunctionStrParameter(ivecs[0]) 276 setnums := vector.GenerateFunctionStrParameter(ivecs[1]) 277 var iscalled vector.FunctionParameterWrapper[bool] 278 if len(ivecs) > 2 { 279 iscalled = vector.GenerateFunctionFixedTypeParameter[bool](ivecs[2]) 280 } 281 282 // Txn 283 e := proc.Ctx.Value(defines.EngineKey{}).(engine.Engine) 284 txn := proc.TxnOperator 285 if txn == nil { 286 return moerr.NewInternalError(proc.Ctx, "Setval: txn operator is nil") 287 } 288 289 for i := uint64(0); i < uint64(length); i++ { 290 tn, tnNull := tblnames.GetStrValue(i) 291 sn, snNull := setnums.GetStrValue(i) 292 isc := true 293 iscNull := false 294 if iscalled != nil { 295 isc, iscNull = iscalled.GetValue(i) 296 } 297 298 if tnNull || snNull || iscNull { 299 if err = rs.AppendBytes(nil, true); err != nil { 300 return 301 } 302 } else { 303 var res string 304 res, err = setval(string(tn), string(sn), isc, proc, txn, e) 305 if err == nil { 306 err = rs.AppendBytes(functionUtil.QuickStrToBytes(res), false) 307 } 308 if err != nil { 309 return 310 } 311 } 312 } 313 return 314 } 315 316 func setval(tblname, setnum string, iscalled bool, proc *process.Process, txn client.TxnOperator, e engine.Engine) (string, error) { 317 db := proc.SessionInfo.Database 318 dbHandler, err := e.Database(proc.Ctx, db, txn) 319 if err != nil { 320 return "", err 321 } 322 rel, err := dbHandler.Relation(proc.Ctx, tblname, nil) 323 if err != nil { 324 return "", err 325 } 326 327 values, err := proc.SessionInfo.SqlHelper.ExecSql(fmt.Sprintf("select * from `%s`.`%s`", db, tblname)) 328 if err != nil { 329 return "", err 330 } 331 if values == nil { 332 return "", moerr.NewInternalError(proc.Ctx, "Failed to get sequence meta data.") 333 } 334 335 switch values[0].(type) { 336 case int16: 337 minv, maxv := values[1].(int16), values[2].(int16) 338 // Parse and compare. 339 setnum, err := strconv.ParseInt(setnum, 10, 64) 340 if err != nil { 341 return "", err 342 } 343 snum := int16(setnum) 344 if snum < minv || snum > maxv { 345 return "", moerr.NewInternalError(proc.Ctx, "Set value is not in range (minvalue, maxvlue).") 346 } 347 return setVal(proc, snum, iscalled, rel, db, tblname) 348 case int32: 349 minv, maxv := values[1].(int32), values[2].(int32) 350 setnum, err := strconv.ParseInt(setnum, 10, 64) 351 if err != nil { 352 return "", err 353 } 354 snum := int32(setnum) 355 if snum < minv || snum > maxv { 356 return "", moerr.NewInternalError(proc.Ctx, "Set value is not in range (minvalue, maxvlue).") 357 } 358 return setVal(proc, snum, iscalled, rel, db, tblname) 359 case int64: 360 minv, maxv := values[1].(int64), values[2].(int64) 361 setnum, err := strconv.ParseInt(setnum, 10, 64) 362 if err != nil { 363 return "", err 364 } 365 snum := setnum 366 if snum < minv || snum > maxv { 367 return "", moerr.NewInternalError(proc.Ctx, "Set value is not in range (minvalue, maxvlue).") 368 } 369 return setVal(proc, snum, iscalled, rel, db, tblname) 370 case uint16: 371 minv, maxv := values[1].(uint16), values[2].(uint16) 372 setnum, err := strconv.ParseUint(setnum, 10, 64) 373 if err != nil { 374 return "", err 375 } 376 snum := uint16(setnum) 377 if snum < minv || snum > maxv { 378 return "", moerr.NewInternalError(proc.Ctx, "Set value is not in range (minvalue, maxvlue).") 379 } 380 return setVal(proc, snum, iscalled, rel, db, tblname) 381 case uint32: 382 minv, maxv := values[1].(uint32), values[2].(uint32) 383 setnum, err := strconv.ParseUint(setnum, 10, 64) 384 if err != nil { 385 return "", err 386 } 387 snum := uint32(setnum) 388 if snum < minv || snum > maxv { 389 return "", moerr.NewInternalError(proc.Ctx, "Set value is not in range (minvalue, maxvlue).") 390 } 391 return setVal(proc, snum, iscalled, rel, db, tblname) 392 case uint64: 393 minv, maxv := values[1].(uint64), values[2].(uint64) 394 setnum, err := strconv.ParseUint(setnum, 10, 64) 395 if err != nil { 396 return "", err 397 } 398 snum := uint64(setnum) 399 if snum < minv || snum > maxv { 400 return "", moerr.NewInternalError(proc.Ctx, "Set value is not in range (minvalue, maxvlue).") 401 } 402 return setVal(proc, snum, iscalled, rel, db, tblname) 403 } 404 return "", moerr.NewInternalError(proc.Ctx, "Wrong types of sequence number or failed to read the sequence table") 405 } 406 407 func setVal[T constraints.Integer](proc *process.Process, setv T, setisCalled bool, rel engine.Relation, db, tbl string) (string, error) { 408 _, err := proc.SessionInfo.SqlHelper.ExecSql(fmt.Sprintf("update `%s`.`%s` set last_seq_num = %d", db, tbl, setv)) 409 if err != nil { 410 return "", err 411 } 412 413 ress := fmt.Sprint(setv) 414 if setisCalled { 415 tblId := rel.GetTableID(proc.Ctx) 416 417 proc.SessionInfo.SeqAddValues[tblId] = ress 418 419 // Only set lastvalue when it is already initialized. 420 if proc.SessionInfo.SeqLastValue[0] != "" { 421 proc.SessionInfo.SeqLastValue[0] = ress 422 } 423 } 424 425 return ress, nil 426 } 427 428 func Currval(ivecs []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int) (err error) { 429 rs := vector.MustFunctionResult[types.Varlena](result) 430 ivec := vector.GenerateFunctionStrParameter(ivecs[0]) 431 432 // Here is the transaction 433 e := proc.Ctx.Value(defines.EngineKey{}).(engine.Engine) 434 txn := proc.TxnOperator 435 if txn == nil { 436 return moerr.NewInternalError(proc.Ctx, "Currval: txn operator is nil") 437 } 438 439 dbHandler, err := e.Database(proc.Ctx, proc.SessionInfo.Database, txn) 440 if err != nil { 441 return 442 } 443 444 for i := uint64(0); i < uint64(length); i++ { 445 v, null := ivec.GetStrValue(i) 446 if null { 447 if err = rs.AppendBytes(nil, true); err != nil { 448 return 449 } 450 } else { 451 var rel engine.Relation 452 rel, err = dbHandler.Relation(proc.Ctx, string(v), nil) 453 if err != nil { 454 return 455 } 456 tblId := rel.GetTableID(proc.Ctx) 457 // Get cur values here. 458 ss, exists := proc.SessionInfo.SeqCurValues[tblId] 459 // If nextval called before this currval.Check add values 460 ss1, existsAdd := proc.SessionInfo.SeqAddValues[tblId] 461 if !exists && !existsAdd { 462 err = moerr.NewInternalError(proc.Ctx, "Currvalue of %s in current session is not initialized", v) 463 return 464 } 465 // Assign the values of SeqAddValues first, cause this values is the updated curvals. 466 if existsAdd { 467 err = rs.AppendBytes(functionUtil.QuickStrToBytes(ss1), false) 468 } else { 469 err = rs.AppendBytes(functionUtil.QuickStrToBytes(ss), false) 470 } 471 if err != nil { 472 return 473 } 474 } 475 } 476 return 477 } 478 479 func Lastval(ivecs []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int) (err error) { 480 // Get last value 481 lastv := proc.SessionInfo.SeqLastValue[0] 482 if lastv == "" { 483 return moerr.NewInternalError(proc.Ctx, "Last value of current session is not initialized.") 484 } 485 486 rs := vector.MustFunctionResult[types.Varlena](result) 487 for i := uint64(0); i < uint64(length); i++ { 488 if err = rs.AppendBytes(functionUtil.QuickStrToBytes(lastv), false); err != nil { 489 return 490 } 491 } 492 return 493 }