github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/lockop/fetch.go (about)

     1  // Copyright 2023 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 lockop
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"math"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/container/types"
    23  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    24  	"github.com/matrixorigin/matrixone/pkg/pb/lock"
    25  	"golang.org/x/exp/constraints"
    26  )
    27  
    28  var (
    29  	minUUID = [16]byte{}
    30  	maxUUID = [16]byte{
    31  		math.MaxInt8,
    32  		math.MaxInt8,
    33  		math.MaxInt8,
    34  		math.MaxInt8,
    35  		math.MaxInt8,
    36  		math.MaxInt8,
    37  		math.MaxInt8,
    38  		math.MaxInt8,
    39  		math.MaxInt8,
    40  		math.MaxInt8,
    41  		math.MaxInt8,
    42  		math.MaxInt8,
    43  		math.MaxInt8,
    44  		math.MaxInt8,
    45  		math.MaxInt8,
    46  		math.MaxInt8}
    47  )
    48  
    49  // GetFetchRowsFunc get FetchLockRowsFunc based on primary key type
    50  func GetFetchRowsFunc(t types.Type) FetchLockRowsFunc {
    51  	switch t.Oid {
    52  	case types.T_bool:
    53  		return fetchBoolRows
    54  	case types.T_bit:
    55  		return fetchUint64Rows
    56  	case types.T_int8:
    57  		return fetchInt8Rows
    58  	case types.T_int16:
    59  		return fetchInt16Rows
    60  	case types.T_int32:
    61  		return fetchInt32Rows
    62  	case types.T_int64:
    63  		return fetchInt64Rows
    64  	case types.T_uint8:
    65  		return fetchUint8Rows
    66  	case types.T_uint16:
    67  		return fetchUint16Rows
    68  	case types.T_uint32:
    69  		return fetchUint32Rows
    70  	case types.T_uint64:
    71  		return fetchUint64Rows
    72  	case types.T_float32:
    73  		return fetchFloat32Rows
    74  	case types.T_float64:
    75  		return fetchFloat64Rows
    76  	case types.T_date:
    77  		return fetchDateRows
    78  	case types.T_time:
    79  		return fetchTimeRows
    80  	case types.T_datetime:
    81  		return fetchDateTimeRows
    82  	case types.T_timestamp:
    83  		return fetchTimestampRows
    84  	case types.T_decimal64:
    85  		return fetchDecimal64Rows
    86  	case types.T_decimal128:
    87  		return fetchDecimal128Rows
    88  	case types.T_uuid:
    89  		return fetchUUIDRows
    90  	case types.T_char, types.T_varchar, types.T_binary, types.T_varbinary:
    91  		return fetchVarlenaRows
    92  		// T_json, T_blob, T_array_float32 etc. cannot be PK.
    93  	case types.T_enum:
    94  		return fetchEnumRows
    95  	default:
    96  		panic(fmt.Sprintf("not support for %s", t.String()))
    97  	}
    98  }
    99  
   100  func fetchBoolRows(
   101  	vec *vector.Vector,
   102  	parker *types.Packer,
   103  	tp types.Type,
   104  	max int,
   105  	lockTable bool,
   106  	filter RowsFilter,
   107  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   108  	fn := func(v bool) []byte {
   109  		parker.Reset()
   110  		parker.EncodeBool(v)
   111  		return parker.Bytes()
   112  	}
   113  	return true, [][]byte{fn(false), fn(true)},
   114  		lock.Granularity_Range
   115  }
   116  
   117  func fetchInt8Rows(
   118  	vec *vector.Vector,
   119  	parker *types.Packer,
   120  	tp types.Type,
   121  	max int,
   122  	lockTable bool,
   123  	filter RowsFilter,
   124  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   125  	fn := func(v int8) []byte {
   126  		parker.Reset()
   127  		parker.EncodeInt8(v)
   128  		return parker.Bytes()
   129  	}
   130  	if lockTable {
   131  		min := fn(math.MinInt8)
   132  		max := fn(math.MaxInt8)
   133  		return true, [][]byte{min, max},
   134  			lock.Granularity_Range
   135  	}
   136  	return fetchFixedRows(
   137  		vec,
   138  		max,
   139  		fn,
   140  		filter,
   141  		filterCols)
   142  }
   143  
   144  func fetchInt16Rows(
   145  	vec *vector.Vector,
   146  	parker *types.Packer,
   147  	tp types.Type,
   148  	max int,
   149  	lockTable bool,
   150  	filter RowsFilter,
   151  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   152  	fn := func(v int16) []byte {
   153  		parker.Reset()
   154  		parker.EncodeInt16(v)
   155  		return parker.Bytes()
   156  	}
   157  	if lockTable {
   158  		min := fn(math.MinInt16)
   159  		max := fn(math.MaxInt16)
   160  		return true, [][]byte{min, max},
   161  			lock.Granularity_Range
   162  	}
   163  	return fetchFixedRows(
   164  		vec,
   165  		max,
   166  		fn,
   167  		filter,
   168  		filterCols)
   169  }
   170  
   171  func fetchInt32Rows(
   172  	vec *vector.Vector,
   173  	parker *types.Packer,
   174  	tp types.Type,
   175  	max int,
   176  	lockTable bool,
   177  	filter RowsFilter,
   178  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   179  	fn := func(v int32) []byte {
   180  		parker.Reset()
   181  		parker.EncodeInt32(v)
   182  		return parker.Bytes()
   183  	}
   184  	if lockTable {
   185  		min := fn(math.MinInt32)
   186  		max := fn(math.MaxInt32)
   187  		return true, [][]byte{min, max},
   188  			lock.Granularity_Range
   189  	}
   190  	return fetchFixedRows(
   191  		vec,
   192  		max,
   193  		fn,
   194  		filter,
   195  		filterCols)
   196  }
   197  
   198  func fetchInt64Rows(
   199  	vec *vector.Vector,
   200  	parker *types.Packer,
   201  	tp types.Type,
   202  	max int,
   203  	lockTable bool,
   204  	filter RowsFilter,
   205  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   206  	fn := func(v int64) []byte {
   207  		parker.Reset()
   208  		parker.EncodeInt64(v)
   209  		return parker.Bytes()
   210  	}
   211  	if lockTable {
   212  		min := fn(math.MinInt64)
   213  		max := fn(math.MaxInt64)
   214  		return true, [][]byte{min, max},
   215  			lock.Granularity_Range
   216  	}
   217  	return fetchFixedRows(
   218  		vec,
   219  		max,
   220  		fn,
   221  		filter,
   222  		filterCols)
   223  }
   224  
   225  func fetchUint8Rows(
   226  	vec *vector.Vector,
   227  	parker *types.Packer,
   228  	tp types.Type,
   229  	max int,
   230  	lockTable bool,
   231  	filter RowsFilter,
   232  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   233  	fn := func(v uint8) []byte {
   234  		parker.Reset()
   235  		parker.EncodeUint8(v)
   236  		return parker.Bytes()
   237  	}
   238  	if lockTable {
   239  		min := fn(0)
   240  		max := fn(math.MaxUint8)
   241  		return true, [][]byte{min, max},
   242  			lock.Granularity_Range
   243  	}
   244  	return fetchFixedRows(
   245  		vec,
   246  		max,
   247  		fn,
   248  		filter,
   249  		filterCols)
   250  }
   251  
   252  func fetchUint16Rows(
   253  	vec *vector.Vector,
   254  	parker *types.Packer,
   255  	tp types.Type,
   256  	max int,
   257  	lockTable bool,
   258  	filter RowsFilter,
   259  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   260  	fn := func(v uint16) []byte {
   261  		parker.Reset()
   262  		parker.EncodeUint16(v)
   263  		return parker.Bytes()
   264  	}
   265  	if lockTable {
   266  		min := fn(0)
   267  		max := fn(math.MaxUint16)
   268  		return true, [][]byte{min, max},
   269  			lock.Granularity_Range
   270  	}
   271  	return fetchFixedRows(
   272  		vec,
   273  		max,
   274  		fn,
   275  		filter,
   276  		filterCols)
   277  }
   278  
   279  func fetchUint32Rows(
   280  	vec *vector.Vector,
   281  	parker *types.Packer,
   282  	tp types.Type,
   283  	max int,
   284  	lockTable bool,
   285  	filter RowsFilter,
   286  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   287  	fn := func(v uint32) []byte {
   288  		parker.Reset()
   289  		parker.EncodeUint32(v)
   290  		return parker.Bytes()
   291  	}
   292  	if lockTable {
   293  		min := fn(0)
   294  		max := fn(math.MaxUint32)
   295  		return true, [][]byte{min, max},
   296  			lock.Granularity_Range
   297  	}
   298  	return fetchFixedRows(
   299  		vec,
   300  		max,
   301  		fn,
   302  		filter,
   303  		filterCols)
   304  }
   305  
   306  func fetchUint64Rows(
   307  	vec *vector.Vector,
   308  	parker *types.Packer,
   309  	tp types.Type,
   310  	max int,
   311  	lockTable bool,
   312  	filter RowsFilter,
   313  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   314  	fn := func(v uint64) []byte {
   315  		parker.Reset()
   316  		parker.EncodeUint64(v)
   317  		return parker.Bytes()
   318  	}
   319  	if lockTable {
   320  		min := fn(0)
   321  		max := fn(math.MaxUint64)
   322  		return true, [][]byte{min, max},
   323  			lock.Granularity_Range
   324  	}
   325  	return fetchFixedRows(
   326  		vec,
   327  		max,
   328  		fn,
   329  		filter,
   330  		filterCols)
   331  }
   332  
   333  func fetchFloat32Rows(
   334  	vec *vector.Vector,
   335  	parker *types.Packer,
   336  	tp types.Type,
   337  	max int,
   338  	lockTable bool,
   339  	filter RowsFilter,
   340  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   341  	fn := func(v float32) []byte {
   342  		parker.Reset()
   343  		parker.EncodeFloat32(v)
   344  		return parker.Bytes()
   345  	}
   346  	if lockTable {
   347  		min := fn(math.SmallestNonzeroFloat32)
   348  		max := fn(math.MaxFloat32)
   349  		return true, [][]byte{min, max},
   350  			lock.Granularity_Range
   351  	}
   352  	return fetchFixedRows(
   353  		vec,
   354  		max,
   355  		fn,
   356  		filter,
   357  		filterCols)
   358  }
   359  
   360  func fetchFloat64Rows(
   361  	vec *vector.Vector,
   362  	parker *types.Packer,
   363  	tp types.Type,
   364  	max int,
   365  	lockTable bool,
   366  	filter RowsFilter,
   367  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   368  	fn := func(v float64) []byte {
   369  		parker.Reset()
   370  		parker.EncodeFloat64(v)
   371  		return parker.Bytes()
   372  	}
   373  	if lockTable {
   374  		min := fn(math.SmallestNonzeroFloat64)
   375  		max := fn(math.MaxFloat64)
   376  		return true, [][]byte{min, max},
   377  			lock.Granularity_Range
   378  	}
   379  	return fetchFixedRows(
   380  		vec,
   381  		max,
   382  		fn,
   383  		filter,
   384  		filterCols)
   385  }
   386  
   387  func fetchDateRows(
   388  	vec *vector.Vector,
   389  	parker *types.Packer,
   390  	tp types.Type,
   391  	max int,
   392  	lockTable bool,
   393  	filter RowsFilter,
   394  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   395  	fn := func(v types.Date) []byte {
   396  		parker.Reset()
   397  		parker.EncodeDate(v)
   398  		return parker.Bytes()
   399  	}
   400  	if lockTable {
   401  		min := fn(math.MinInt32)
   402  		max := fn(math.MaxInt32)
   403  		return true, [][]byte{min, max},
   404  			lock.Granularity_Range
   405  	}
   406  	return fetchFixedRows(
   407  		vec,
   408  		max,
   409  		fn,
   410  		filter,
   411  		filterCols)
   412  }
   413  
   414  func fetchTimeRows(
   415  	vec *vector.Vector,
   416  	parker *types.Packer,
   417  	tp types.Type,
   418  	max int,
   419  	lockTable bool,
   420  	filter RowsFilter,
   421  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   422  	fn := func(v types.Time) []byte {
   423  		parker.Reset()
   424  		parker.EncodeTime(v)
   425  		return parker.Bytes()
   426  	}
   427  	if lockTable {
   428  		min := fn(math.MinInt64)
   429  		max := fn(math.MaxInt64)
   430  		return true, [][]byte{min, max},
   431  			lock.Granularity_Range
   432  	}
   433  	return fetchFixedRows(
   434  		vec,
   435  		max,
   436  		fn,
   437  		filter,
   438  		filterCols)
   439  }
   440  
   441  func fetchEnumRows(
   442  	vec *vector.Vector,
   443  	parker *types.Packer,
   444  	tp types.Type,
   445  	max int,
   446  	lockTable bool,
   447  	filter RowsFilter,
   448  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   449  	fn := func(v types.Enum) []byte {
   450  		parker.Reset()
   451  		parker.EncodeEnum(v)
   452  		return parker.Bytes()
   453  	}
   454  	if lockTable {
   455  		min := fn(0)
   456  		max := fn(math.MaxUint16)
   457  		return true, [][]byte{min, max},
   458  			lock.Granularity_Range
   459  	}
   460  	return fetchFixedRows(
   461  		vec,
   462  		max,
   463  		fn,
   464  		filter,
   465  		filterCols)
   466  }
   467  
   468  func fetchDateTimeRows(
   469  	vec *vector.Vector,
   470  	parker *types.Packer,
   471  	tp types.Type,
   472  	max int,
   473  	lockTable bool,
   474  	filter RowsFilter,
   475  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   476  	fn := func(v types.Datetime) []byte {
   477  		parker.Reset()
   478  		parker.EncodeDatetime(v)
   479  		return parker.Bytes()
   480  	}
   481  	if lockTable {
   482  		min := fn(math.MinInt64)
   483  		max := fn(math.MaxInt64)
   484  		return true, [][]byte{min, max},
   485  			lock.Granularity_Range
   486  	}
   487  	return fetchFixedRows(
   488  		vec,
   489  		max,
   490  		fn,
   491  		filter,
   492  		filterCols)
   493  }
   494  
   495  func fetchTimestampRows(
   496  	vec *vector.Vector,
   497  	parker *types.Packer,
   498  	tp types.Type,
   499  	max int,
   500  	lockTable bool,
   501  	filter RowsFilter,
   502  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   503  	fn := func(v types.Timestamp) []byte {
   504  		parker.Reset()
   505  		parker.EncodeTimestamp(v)
   506  		return parker.Bytes()
   507  	}
   508  	if lockTable {
   509  		min := fn(math.MinInt64)
   510  		max := fn(math.MaxInt64)
   511  		return true, [][]byte{min, max},
   512  			lock.Granularity_Range
   513  	}
   514  	return fetchFixedRows(
   515  		vec,
   516  		max,
   517  		fn,
   518  		filter,
   519  		filterCols)
   520  }
   521  
   522  func fetchDecimal64Rows(
   523  	vec *vector.Vector,
   524  	parker *types.Packer,
   525  	tp types.Type,
   526  	max int,
   527  	lockTable bool,
   528  	filter RowsFilter,
   529  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   530  	fn := func(v types.Decimal64) []byte {
   531  		parker.Reset()
   532  		parker.EncodeDecimal64(v)
   533  		return parker.Bytes()
   534  	}
   535  	if lockTable {
   536  		maxDecimal64 := types.Decimal64(999999999999999999)
   537  		min := fn(maxDecimal64.Minus())
   538  		max := fn(maxDecimal64)
   539  		return true, [][]byte{min, max},
   540  			lock.Granularity_Range
   541  	}
   542  	return fetchFixedRows(
   543  		vec,
   544  		max,
   545  		fn,
   546  		filter,
   547  		filterCols)
   548  }
   549  
   550  func fetchDecimal128Rows(
   551  	vec *vector.Vector,
   552  	parker *types.Packer,
   553  	tp types.Type,
   554  	max int,
   555  	lockTable bool,
   556  	filter RowsFilter,
   557  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   558  	fn := func(v types.Decimal128) []byte {
   559  		parker.Reset()
   560  		parker.EncodeDecimal128(v)
   561  		return parker.Bytes()
   562  	}
   563  	if lockTable {
   564  		maxDecimal128, _, _ := types.Parse128("99999999999999999999999999999999999999")
   565  		min := fn(maxDecimal128.Minus())
   566  		max := fn(maxDecimal128)
   567  		return true, [][]byte{min, max},
   568  			lock.Granularity_Range
   569  	}
   570  	return fetchFixedRowsWithCompare(
   571  		vec,
   572  		max,
   573  		fn,
   574  		func(v1, v2 types.Decimal128) int {
   575  			return v1.Compare(v2)
   576  		},
   577  		filter,
   578  		filterCols,
   579  	)
   580  }
   581  
   582  func fetchUUIDRows(
   583  	vec *vector.Vector,
   584  	parker *types.Packer,
   585  	tp types.Type,
   586  	max int,
   587  	lockTable bool,
   588  	filter RowsFilter,
   589  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   590  	fn := func(v types.Uuid) []byte {
   591  		parker.Reset()
   592  		parker.EncodeStringType(v[:])
   593  		return parker.Bytes()
   594  	}
   595  	if lockTable {
   596  		min := fn(minUUID)
   597  		max := fn(maxUUID)
   598  		return true, [][]byte{min, max},
   599  			lock.Granularity_Range
   600  	}
   601  	return fetchFixedRowsWithCompare(
   602  		vec,
   603  		max,
   604  		func(v types.Uuid) []byte {
   605  			parker.Reset()
   606  			parker.EncodeStringType(v[:])
   607  			return parker.Bytes()
   608  		},
   609  		func(v1, v2 types.Uuid) int {
   610  			return bytes.Compare(v1[:], v2[:])
   611  		},
   612  		filter,
   613  		filterCols,
   614  	)
   615  }
   616  
   617  func fetchVarlenaRows(
   618  	vec *vector.Vector,
   619  	parker *types.Packer,
   620  	tp types.Type,
   621  	max int,
   622  	lockTable bool,
   623  	filter RowsFilter,
   624  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   625  	fn := func(v []byte) []byte {
   626  		parker.Reset()
   627  		parker.EncodeStringType(v[:])
   628  		return parker.Bytes()
   629  	}
   630  	if lockTable {
   631  		min := fn([]byte{0})
   632  		max := fn(getMax(int(tp.Width)))
   633  		return true, [][]byte{min, max},
   634  			lock.Granularity_Range
   635  	}
   636  
   637  	n := vec.Length()
   638  	data, area := vector.MustVarlenaRawData(vec)
   639  	if n == 1 {
   640  		if filter != nil &&
   641  			!filter(0, filterCols) {
   642  			return false, nil, lock.Granularity_Row
   643  		}
   644  		return true, [][]byte{fn(data[0].GetByteSlice(area))},
   645  			lock.Granularity_Row
   646  	}
   647  
   648  	if n > max {
   649  		var min, max []byte
   650  		initialized := false
   651  		applied := 0
   652  		for i := 0; i < n; i++ {
   653  			if filter != nil &&
   654  				!filter(i, filterCols) {
   655  				continue
   656  			}
   657  			applied++
   658  			v := data[i].GetByteSlice(area)
   659  			if !initialized {
   660  				min, max = v, v
   661  				initialized = true
   662  				continue
   663  			}
   664  			if bytes.Compare(v, min) < 0 {
   665  				min = v
   666  			}
   667  			if bytes.Compare(v, max) > 0 {
   668  				max = v
   669  			}
   670  		}
   671  
   672  		if applied == 0 {
   673  			return false, nil, lock.Granularity_Row
   674  		}
   675  		rows := [][]byte{fn(min), fn(max)}
   676  		if bytes.Equal(rows[0], rows[1]) {
   677  			return true, rows[:1], lock.Granularity_Row
   678  		}
   679  		return true, rows, lock.Granularity_Range
   680  	}
   681  	rows := make([][]byte, 0, n)
   682  	for idx := range data {
   683  		if filter != nil &&
   684  			!filter(idx, filterCols) {
   685  			continue
   686  		}
   687  		rows = append(rows, fn(data[idx].GetByteSlice(area)))
   688  	}
   689  	return len(rows) > 0, rows, lock.Granularity_Row
   690  }
   691  
   692  func fetchFixedRows[T constraints.Ordered](
   693  	vec *vector.Vector,
   694  	max int,
   695  	fn func(v T) []byte,
   696  	filter RowsFilter,
   697  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   698  	return fetchFixedRowsWithCompare(
   699  		vec,
   700  		max,
   701  		fn,
   702  		func(v1, v2 T) int {
   703  			if v1 < v2 {
   704  				return -1
   705  			} else if v1 > v2 {
   706  				return 1
   707  			}
   708  			return 0
   709  		},
   710  		filter,
   711  		filterCols,
   712  	)
   713  }
   714  
   715  func fetchFixedRowsWithCompare[T any](
   716  	vec *vector.Vector,
   717  	max int,
   718  	fn func(v T) []byte,
   719  	compare func(a, b T) int,
   720  	filter RowsFilter,
   721  	filterCols []int32) (bool, [][]byte, lock.Granularity) {
   722  	n := vec.Length()
   723  	values := vector.MustFixedCol[T](vec)
   724  	if n == 1 {
   725  		if filter != nil && !filter(0, filterCols) {
   726  			return false, nil, lock.Granularity_Row
   727  		}
   728  		return true, [][]byte{fn(values[0])}, lock.Granularity_Row
   729  	}
   730  	if n > max {
   731  		var min, max T
   732  		initialized := false
   733  		applied := 0
   734  		for row, v := range values {
   735  			if filter != nil &&
   736  				!filter(row, filterCols) {
   737  				continue
   738  			}
   739  			applied++
   740  			if !initialized {
   741  				min, max = v, v
   742  				initialized = true
   743  				continue
   744  			}
   745  			if compare(v, min) < 0 {
   746  				min = v
   747  			}
   748  			if compare(v, max) > 0 {
   749  				max = v
   750  			}
   751  		}
   752  
   753  		if applied == 0 {
   754  			return false, nil, lock.Granularity_Row
   755  		}
   756  		rows := [][]byte{fn(min), fn(max)}
   757  		if bytes.Equal(rows[0], rows[1]) {
   758  			return true, rows[:1], lock.Granularity_Row
   759  		}
   760  		return true, rows, lock.Granularity_Range
   761  	}
   762  	rows := make([][]byte, 0, n)
   763  	for row, v := range values {
   764  		if filter != nil &&
   765  			!filter(row, filterCols) {
   766  			continue
   767  		}
   768  		rows = append(rows, fn(v))
   769  	}
   770  	return len(rows) > 0, rows, lock.Granularity_Row
   771  }
   772  
   773  func getMax(size int) []byte {
   774  	v := make([]byte, size)
   775  	for idx := range v {
   776  		v[idx] = math.MaxUint8
   777  	}
   778  	return v
   779  }