github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/builtin_miscellaneous_vec.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 memex
    15  
    16  import (
    17  	"bytes"
    18  	"encoding/binary"
    19  	"fmt"
    20  	"math"
    21  	"net"
    22  	"strings"
    23  	"sync/atomic"
    24  	"time"
    25  
    26  	"github.com/google/uuid"
    27  	"github.com/whtcorpsinc/milevadb/stochastikctx/variable"
    28  	"github.com/whtcorpsinc/milevadb/types"
    29  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    30  )
    31  
    32  func (b *builtinInetNtoaSig) vecEvalString(input *chunk.Chunk, result *chunk.DeferredCauset) error {
    33  	n := input.NumEvents()
    34  	buf, err := b.bufSlabPredictor.get(types.ETInt, n)
    35  	if err != nil {
    36  		return err
    37  	}
    38  	defer b.bufSlabPredictor.put(buf)
    39  	if err := b.args[0].VecEvalInt(b.ctx, input, buf); err != nil {
    40  		return err
    41  	}
    42  
    43  	result.ReserveString(n)
    44  	i64s := buf.Int64s()
    45  	ip := make(net.IP, net.IPv4len)
    46  	for i := 0; i < n; i++ {
    47  		val := i64s[i]
    48  		if buf.IsNull(i) || val < 0 || uint64(val) > math.MaxUint32 {
    49  			result.AppendNull()
    50  			continue
    51  		}
    52  		binary.BigEndian.PutUint32(ip, uint32(val))
    53  		ipv4 := ip.To4()
    54  		if ipv4 == nil {
    55  			//Not a vaild ipv4 address.
    56  			result.AppendNull()
    57  			continue
    58  		}
    59  		result.AppendString(ipv4.String())
    60  	}
    61  	return nil
    62  }
    63  
    64  func (b *builtinInetNtoaSig) vectorized() bool {
    65  	return true
    66  }
    67  
    68  func (b *builtinIsIPv4Sig) vecEvalInt(input *chunk.Chunk, result *chunk.DeferredCauset) error {
    69  	n := input.NumEvents()
    70  	buf, err := b.bufSlabPredictor.get(types.ETString, n)
    71  	if err != nil {
    72  		return err
    73  	}
    74  	defer b.bufSlabPredictor.put(buf)
    75  	if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil {
    76  		return err
    77  	}
    78  	result.ResizeInt64(n, false)
    79  	i64s := result.Int64s()
    80  	for i := 0; i < n; i++ {
    81  		// Note that even when the i-th input string is null, the output is
    82  		// 0 instead of null, therefore we do not set the null bit mask in
    83  		// result's corresponding event.
    84  		// See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_is-ipv4
    85  		if isIPv4(buf.GetString(i)) {
    86  			i64s[i] = 1
    87  		} else {
    88  			i64s[i] = 0
    89  		}
    90  	}
    91  	return nil
    92  }
    93  
    94  func (b *builtinIsIPv4Sig) vectorized() bool {
    95  	return true
    96  }
    97  func (b *builtinJSONAnyValueSig) vectorized() bool {
    98  	return true
    99  }
   100  
   101  func (b *builtinJSONAnyValueSig) vecEvalJSON(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   102  	return b.args[0].VecEvalJSON(b.ctx, input, result)
   103  }
   104  
   105  func (b *builtinRealAnyValueSig) vectorized() bool {
   106  	return true
   107  }
   108  
   109  func (b *builtinRealAnyValueSig) vecEvalReal(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   110  	return b.args[0].VecEvalReal(b.ctx, input, result)
   111  }
   112  
   113  func (b *builtinStringAnyValueSig) vectorized() bool {
   114  	return true
   115  }
   116  
   117  func (b *builtinStringAnyValueSig) vecEvalString(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   118  	return b.args[0].VecEvalString(b.ctx, input, result)
   119  }
   120  
   121  func (b *builtinIsIPv6Sig) vectorized() bool {
   122  	return true
   123  }
   124  
   125  func (b *builtinIsIPv6Sig) vecEvalInt(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   126  	n := input.NumEvents()
   127  	buf, err := b.bufSlabPredictor.get(types.ETString, n)
   128  	if err != nil {
   129  		return err
   130  	}
   131  	defer b.bufSlabPredictor.put(buf)
   132  	if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil {
   133  		return err
   134  	}
   135  	result.ResizeInt64(n, false)
   136  	i64s := result.Int64s()
   137  	for i := 0; i < n; i++ {
   138  		// Note that even when the i-th input string is null, the output is
   139  		// 0 instead of null, therefore we do not set the null bit mask in
   140  		// result's corresponding event.
   141  		// See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_is-ipv6
   142  		if buf.IsNull(i) {
   143  			i64s[i] = 0
   144  		} else {
   145  			ipStr := buf.GetString(i)
   146  			if ip := net.ParseIP(ipStr); ip != nil && !isIPv4(ipStr) {
   147  				i64s[i] = 1
   148  			} else {
   149  				i64s[i] = 0
   150  			}
   151  		}
   152  	}
   153  	return nil
   154  }
   155  
   156  func (b *builtinNameConstStringSig) vectorized() bool {
   157  	return true
   158  }
   159  
   160  func (b *builtinNameConstStringSig) vecEvalString(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   161  	return b.args[1].VecEvalString(b.ctx, input, result)
   162  }
   163  
   164  func (b *builtinDecimalAnyValueSig) vectorized() bool {
   165  	return true
   166  }
   167  
   168  func (b *builtinDecimalAnyValueSig) vecEvalDecimal(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   169  	return b.args[0].VecEvalDecimal(b.ctx, input, result)
   170  }
   171  
   172  func (b *builtinUUIDSig) vectorized() bool {
   173  	return true
   174  }
   175  
   176  func (b *builtinUUIDSig) vecEvalString(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   177  	n := input.NumEvents()
   178  	result.ReserveString(n)
   179  	var id uuid.UUID
   180  	var err error
   181  	for i := 0; i < n; i++ {
   182  		id, err = uuid.NewUUID()
   183  		if err != nil {
   184  			return err
   185  		}
   186  		result.AppendString(id.String())
   187  	}
   188  	return nil
   189  }
   190  
   191  func (b *builtinNameConstDurationSig) vectorized() bool {
   192  	return true
   193  }
   194  
   195  func (b *builtinNameConstDurationSig) vecEvalDuration(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   196  	return b.args[1].VecEvalDuration(b.ctx, input, result)
   197  }
   198  
   199  func (b *builtinLockSig) vectorized() bool {
   200  	return true
   201  }
   202  
   203  // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_get-dagger
   204  // The dagger function will do nothing.
   205  // Warning: get_lock() function is parsed but ignored.
   206  func (b *builtinLockSig) vecEvalInt(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   207  	n := input.NumEvents()
   208  	result.ResizeInt64(n, false)
   209  	i64s := result.Int64s()
   210  	for i := range i64s {
   211  		i64s[i] = 1
   212  	}
   213  	return nil
   214  }
   215  
   216  func (b *builtinDurationAnyValueSig) vectorized() bool {
   217  	return true
   218  }
   219  
   220  func (b *builtinDurationAnyValueSig) vecEvalDuration(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   221  	return b.args[0].VecEvalDuration(b.ctx, input, result)
   222  }
   223  
   224  func (b *builtinIntAnyValueSig) vectorized() bool {
   225  	return true
   226  }
   227  
   228  func (b *builtinIntAnyValueSig) vecEvalInt(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   229  	return b.args[0].VecEvalInt(b.ctx, input, result)
   230  }
   231  
   232  func (b *builtinIsIPv4CompatSig) vectorized() bool {
   233  	return true
   234  }
   235  
   236  func (b *builtinIsIPv4CompatSig) vecEvalInt(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   237  	n := input.NumEvents()
   238  	buf, err := b.bufSlabPredictor.get(types.ETString, n)
   239  	if err != nil {
   240  		return err
   241  	}
   242  	defer b.bufSlabPredictor.put(buf)
   243  	if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil {
   244  		return err
   245  	}
   246  	result.ResizeInt64(n, false)
   247  	i64s := result.Int64s()
   248  	prefixCompat := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
   249  	for i := 0; i < n; i++ {
   250  		if buf.IsNull(i) {
   251  			i64s[i] = 0
   252  		} else {
   253  			// Note that the input should be IP address in byte format.
   254  			// For IPv4, it should be byte slice with 4 bytes.
   255  			// For IPv6, it should be byte slice with 16 bytes.
   256  			// See example https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_is-ipv4-compat
   257  			ipAddress := buf.GetBytes(i)
   258  			if len(ipAddress) != net.IPv6len || !bytes.HasPrefix(ipAddress, prefixCompat) {
   259  				//Not an IPv6 address, return false
   260  				i64s[i] = 0
   261  			} else {
   262  				i64s[i] = 1
   263  			}
   264  		}
   265  	}
   266  	return nil
   267  }
   268  
   269  func (b *builtinNameConstIntSig) vectorized() bool {
   270  	return true
   271  }
   272  
   273  func (b *builtinNameConstIntSig) vecEvalInt(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   274  	return b.args[1].VecEvalInt(b.ctx, input, result)
   275  }
   276  
   277  func (b *builtinNameConstTimeSig) vectorized() bool {
   278  	return true
   279  }
   280  
   281  func (b *builtinNameConstTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   282  	return b.args[1].VecEvalTime(b.ctx, input, result)
   283  }
   284  
   285  func (b *builtinSleepSig) vectorized() bool {
   286  	return true
   287  }
   288  
   289  // vecEvalInt evals a builtinSleepSig in a vectorized manner.
   290  // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_sleep
   291  func (b *builtinSleepSig) vecEvalInt(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   292  	n := input.NumEvents()
   293  	buf, err := b.bufSlabPredictor.get(types.ETReal, n)
   294  	if err != nil {
   295  		return err
   296  	}
   297  	defer b.bufSlabPredictor.put(buf)
   298  
   299  	err = b.args[0].VecEvalReal(b.ctx, input, buf)
   300  	if err != nil {
   301  		return err
   302  	}
   303  
   304  	result.ResizeInt64(n, false)
   305  	i64s := result.Int64s()
   306  
   307  	for i := 0; i < n; i++ {
   308  		isNull := buf.IsNull(i)
   309  		val := buf.GetFloat64(i)
   310  
   311  		sessVars := b.ctx.GetStochastikVars()
   312  		if isNull || val < 0 {
   313  			if sessVars.StrictALLEGROSQLMode {
   314  				return errIncorrectArgs.GenWithStackByArgs("sleep")
   315  			}
   316  			err := errIncorrectArgs.GenWithStackByArgs("sleep")
   317  			sessVars.StmtCtx.AppendWarning(err)
   318  			continue
   319  		}
   320  
   321  		if val > math.MaxFloat64/float64(time.Second.Nanoseconds()) {
   322  			return errIncorrectArgs.GenWithStackByArgs("sleep")
   323  		}
   324  
   325  		if isKilled := doSleep(val, sessVars); isKilled {
   326  			for j := i; j < n; j++ {
   327  				i64s[j] = 1
   328  			}
   329  			return nil
   330  		}
   331  	}
   332  
   333  	return nil
   334  }
   335  
   336  func doSleep(secs float64, sessVars *variable.StochastikVars) (isKilled bool) {
   337  	if secs <= 0.0 {
   338  		return false
   339  	}
   340  	dur := time.Duration(secs * float64(time.Second.Nanoseconds()))
   341  	ticker := time.NewTicker(10 * time.Millisecond)
   342  	defer ticker.Stop()
   343  	timer := time.NewTimer(dur)
   344  	for {
   345  		select {
   346  		case <-ticker.C:
   347  			if atomic.CompareAndSwapUint32(&sessVars.Killed, 1, 0) {
   348  				timer.Stop()
   349  				return true
   350  			}
   351  		case <-timer.C:
   352  			return false
   353  		}
   354  	}
   355  }
   356  
   357  func (b *builtinIsIPv4MappedSig) vectorized() bool {
   358  	return true
   359  }
   360  
   361  func (b *builtinIsIPv4MappedSig) vecEvalInt(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   362  	n := input.NumEvents()
   363  	buf, err := b.bufSlabPredictor.get(types.ETString, n)
   364  	if err != nil {
   365  		return err
   366  	}
   367  	defer b.bufSlabPredictor.put(buf)
   368  	if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil {
   369  		return err
   370  	}
   371  	result.ResizeInt64(n, false)
   372  	i64s := result.Int64s()
   373  	prefixMapped := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
   374  	for i := 0; i < n; i++ {
   375  		if buf.IsNull(i) {
   376  			i64s[i] = 0
   377  		} else {
   378  			// Note that the input should be IP address in byte format.
   379  			// For IPv4, it should be byte slice with 4 bytes.
   380  			// For IPv6, it should be byte slice with 16 bytes.
   381  			// See example https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_is-ipv4-mapped
   382  			ipAddress := buf.GetBytes(i)
   383  			if len(ipAddress) != net.IPv6len || !bytes.HasPrefix(ipAddress, prefixMapped) {
   384  				//Not an IPv6 address, return false
   385  				i64s[i] = 0
   386  			} else {
   387  				i64s[i] = 1
   388  			}
   389  		}
   390  	}
   391  	return nil
   392  }
   393  
   394  func (b *builtinNameConstDecimalSig) vectorized() bool {
   395  	return true
   396  }
   397  
   398  func (b *builtinNameConstDecimalSig) vecEvalDecimal(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   399  	return b.args[1].VecEvalDecimal(b.ctx, input, result)
   400  }
   401  
   402  func (b *builtinNameConstJSONSig) vectorized() bool {
   403  	return true
   404  }
   405  
   406  func (b *builtinNameConstJSONSig) vecEvalJSON(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   407  	return b.args[1].VecEvalJSON(b.ctx, input, result)
   408  }
   409  
   410  func (b *builtinInet6AtonSig) vectorized() bool {
   411  	return true
   412  }
   413  
   414  // vecEvalString evals a builtinInet6AtonSig.
   415  // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_inet6-aton
   416  func (b *builtinInet6AtonSig) vecEvalString(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   417  	n := input.NumEvents()
   418  	buf, err := b.bufSlabPredictor.get(types.ETString, n)
   419  	if err != nil {
   420  		return err
   421  	}
   422  	defer b.bufSlabPredictor.put(buf)
   423  	if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil {
   424  		return err
   425  	}
   426  
   427  	var (
   428  		resv4 []byte
   429  		resv6 []byte
   430  		res   []byte
   431  	)
   432  	result.ReserveString(n)
   433  	for i := 0; i < n; i++ {
   434  		if buf.IsNull(i) {
   435  			result.AppendNull()
   436  			continue
   437  		}
   438  		val := buf.GetString(i)
   439  		if len(val) == 0 {
   440  			result.AppendNull()
   441  			continue
   442  		}
   443  		ip := net.ParseIP(val)
   444  		if ip == nil {
   445  			result.AppendNull()
   446  			continue
   447  		}
   448  		var isMappedIpv6 bool
   449  		ipTo4 := ip.To4()
   450  		if ipTo4 != nil && strings.Contains(val, ":") {
   451  			//mapped ipv6 address.
   452  			isMappedIpv6 = true
   453  		}
   454  
   455  		if isMappedIpv6 || ipTo4 == nil {
   456  			if resv6 == nil {
   457  				resv6 = make([]byte, net.IPv6len)
   458  			}
   459  			res = resv6
   460  		} else {
   461  			if resv4 == nil {
   462  				resv4 = make([]byte, net.IPv4len)
   463  			}
   464  			res = resv4
   465  		}
   466  
   467  		if isMappedIpv6 {
   468  			copy(res[12:], ipTo4)
   469  			res[11] = 0xff
   470  			res[10] = 0xff
   471  		} else if ipTo4 == nil {
   472  			copy(res, ip.To16())
   473  		} else {
   474  			copy(res, ipTo4)
   475  		}
   476  		result.AppendBytes(res)
   477  	}
   478  	return nil
   479  }
   480  
   481  func (b *builtinTimeAnyValueSig) vectorized() bool {
   482  	return true
   483  }
   484  
   485  func (b *builtinTimeAnyValueSig) vecEvalTime(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   486  	return b.args[0].VecEvalTime(b.ctx, input, result)
   487  }
   488  
   489  func (b *builtinInetAtonSig) vectorized() bool {
   490  	return true
   491  }
   492  
   493  func (b *builtinInetAtonSig) vecEvalInt(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   494  	n := input.NumEvents()
   495  	buf, err := b.bufSlabPredictor.get(types.ETString, n)
   496  	if err != nil {
   497  		return err
   498  	}
   499  	defer b.bufSlabPredictor.put(buf)
   500  	if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil {
   501  		return err
   502  	}
   503  	var (
   504  		byteResult, res uint64
   505  		dotCount        int
   506  	)
   507  	result.ResizeInt64(n, false)
   508  	i64s := result.Int64s()
   509  	result.MergeNulls(buf)
   510  	for i := 0; i < n; i++ {
   511  		if result.IsNull(i) {
   512  			continue
   513  		}
   514  		ipAddr := buf.GetString(i)
   515  		if len(ipAddr) == 0 || ipAddr[len(ipAddr)-1] == '.' {
   516  			// ip address should not end with '.'.
   517  			result.SetNull(i, true)
   518  			continue
   519  		}
   520  		//reset
   521  		byteResult = 0
   522  		res = 0
   523  		dotCount = 0
   524  		for _, c := range ipAddr {
   525  			if c >= '0' && c <= '9' {
   526  				digit := uint64(c - '0')
   527  				byteResult = byteResult*10 + digit
   528  				if byteResult > 255 {
   529  					result.SetNull(i, true)
   530  					break
   531  				}
   532  			} else if c == '.' {
   533  				dotCount++
   534  				if dotCount > 3 {
   535  					result.SetNull(i, true)
   536  					break
   537  				}
   538  				res = (res << 8) + byteResult
   539  				byteResult = 0
   540  			} else {
   541  				result.SetNull(i, true)
   542  				break // illegal char (not number or .)
   543  			}
   544  		}
   545  		// 127 		-> 0.0.0.127
   546  		// 127.255 	-> 127.0.0.255
   547  		// 127.256	-> NULL
   548  		// 127.2.1	-> 127.2.0.1
   549  		if !result.IsNull(i) {
   550  			if dotCount == 1 {
   551  				res <<= 16
   552  			}
   553  			if dotCount == 2 {
   554  				res <<= 8
   555  			}
   556  			i64s[i] = int64((res << 8) + byteResult)
   557  		}
   558  	}
   559  	return nil
   560  }
   561  
   562  func (b *builtinInet6NtoaSig) vectorized() bool {
   563  	return true
   564  }
   565  
   566  func (b *builtinInet6NtoaSig) vecEvalString(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   567  	n := input.NumEvents()
   568  	val, err := b.bufSlabPredictor.get(types.ETString, n)
   569  	if err != nil {
   570  		return err
   571  	}
   572  	defer b.bufSlabPredictor.put(val)
   573  	if err := b.args[0].VecEvalString(b.ctx, input, val); err != nil {
   574  		return err
   575  	}
   576  	result.ReserveString(n)
   577  	for i := 0; i < n; i++ {
   578  		if val.IsNull(i) {
   579  			result.AppendNull()
   580  			continue
   581  		}
   582  		valI := val.GetString(i)
   583  		ip := net.IP(valI).String()
   584  		if len(valI) == net.IPv6len && !strings.Contains(ip, ":") {
   585  			ip = fmt.Sprintf("::ffff:%s", ip)
   586  		}
   587  		if net.ParseIP(ip) == nil {
   588  			result.AppendNull()
   589  			continue
   590  		}
   591  		result.AppendString(ip)
   592  	}
   593  	return nil
   594  }
   595  
   596  func (b *builtinNameConstRealSig) vectorized() bool {
   597  	return true
   598  }
   599  
   600  func (b *builtinNameConstRealSig) vecEvalReal(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   601  	return b.args[1].VecEvalReal(b.ctx, input, result)
   602  }
   603  
   604  func (b *builtinReleaseLockSig) vectorized() bool {
   605  	return true
   606  }
   607  
   608  // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_release-dagger
   609  // The release dagger function will do nothing.
   610  // Warning: release_lock() function is parsed but ignored.
   611  func (b *builtinReleaseLockSig) vecEvalInt(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   612  	n := input.NumEvents()
   613  	result.ResizeInt64(n, false)
   614  	i64s := result.Int64s()
   615  	for i := range i64s {
   616  		i64s[i] = 1
   617  	}
   618  	return nil
   619  }