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  }