github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/plan/function/builtin/multi/lpad.go (about)

     1  // Copyright 2021 - 2022 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 multi
    16  
    17  import (
    18  	"math"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/container/nulls"
    21  	"github.com/matrixorigin/matrixone/pkg/container/types"
    22  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    23  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    24  )
    25  
    26  const (
    27  	MaxSpacePerRowOfLpad  = int64(16 * 1024 * 1024)
    28  	ParameterSourceString = int(0)
    29  	ParameterLengths      = int(1)
    30  	ParameterPadString    = int(2)
    31  )
    32  
    33  /*
    34  First Parameter: source string
    35  Second Parameter: length
    36  Third Parameter: pad string
    37  */
    38  func Lpad(vecs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    39  	if vecs[0].IsScalarNull() || vecs[1].IsScalarNull() || vecs[2].IsScalarNull() {
    40  		return proc.AllocScalarNullVector(vecs[0].Typ), nil
    41  	}
    42  	sourceStr := vector.MustStrCols(vecs[ParameterSourceString]) //Get the first arg
    43  
    44  	//characters length not bytes length
    45  	lengthsOfChars := getLensForLpad(vecs[ParameterLengths].Col)
    46  
    47  	//pad string
    48  	padStr := vector.MustStrCols(vecs[ParameterPadString])
    49  
    50  	constVectors := []bool{vecs[ParameterSourceString].IsScalar(), vecs[ParameterLengths].IsScalar(), vecs[ParameterPadString].IsScalar()}
    51  	inputNulls := []*nulls.Nulls{vecs[ParameterSourceString].Nsp, vecs[ParameterLengths].Nsp, vecs[ParameterPadString].Nsp}
    52  	//evaluate bytes space for every row
    53  	rowCount := vector.Length(vecs[ParameterSourceString])
    54  
    55  	var resultVec *vector.Vector = nil
    56  	resultValues := make([]string, rowCount)
    57  	resultNUll := nulls.NewWithSize(rowCount)
    58  
    59  	fillLpad(sourceStr, lengthsOfChars, padStr, rowCount, constVectors, resultValues, resultNUll, inputNulls)
    60  
    61  	resultVec = vector.NewWithStrings(types.T_varchar.ToType(), resultValues, resultNUll, proc.Mp())
    62  	return resultVec, nil
    63  }
    64  
    65  func getLensForLpad(col interface{}) []int64 {
    66  	switch vs := col.(type) {
    67  	case []int64:
    68  		return vs
    69  	case []float64:
    70  		res := make([]int64, 0, len(vs))
    71  		for _, v := range vs {
    72  			if v > float64(math.MaxInt64) {
    73  				res = append(res, math.MaxInt64)
    74  			} else if v < float64(math.MinInt64) {
    75  				res = append(res, math.MinInt64)
    76  			} else {
    77  				res = append(res, int64(v))
    78  			}
    79  		}
    80  		return res
    81  	case []uint64:
    82  		res := make([]int64, 0, len(vs))
    83  		for _, v := range vs {
    84  			if v > uint64(math.MaxInt64) {
    85  				res = append(res, math.MaxInt64)
    86  			} else {
    87  				res = append(res, int64(v))
    88  			}
    89  		}
    90  		return res
    91  	}
    92  	panic("unexpected parameter types were received")
    93  }
    94  
    95  func fillLpad(sourceStr []string, lengths []int64, padStr []string, rowCount int, constVectors []bool, results []string, resultNUll *nulls.Nulls, inputNulls []*nulls.Nulls) {
    96  	for i := 0; i < rowCount; i++ {
    97  		if ui := uint64(i); nulls.Contains(inputNulls[ParameterSourceString], ui) ||
    98  			nulls.Contains(inputNulls[ParameterLengths], ui) ||
    99  			nulls.Contains(inputNulls[ParameterPadString], ui) {
   100  			//null
   101  			nulls.Add(resultNUll, ui)
   102  			continue
   103  		}
   104  		//1.count characters in source and pad
   105  		var source string
   106  		if constVectors[ParameterSourceString] {
   107  			source = sourceStr[0]
   108  		} else {
   109  			source = sourceStr[i]
   110  		}
   111  		sourceRune := []rune(string(source))
   112  		sourceCharCnt := int64(len(sourceRune))
   113  		var pad string
   114  		if constVectors[ParameterPadString] {
   115  			pad = padStr[0]
   116  		} else {
   117  			pad = padStr[i]
   118  		}
   119  		padLen := len(pad)
   120  		if padLen == 0 {
   121  			//empty string
   122  			continue
   123  		}
   124  		padRune := []rune(string(pad))
   125  		padCharCnt := int64(len(padRune))
   126  		var targetLength int64
   127  		if constVectors[ParameterLengths] {
   128  			targetLength = lengths[0]
   129  		} else {
   130  			targetLength = lengths[i]
   131  		}
   132  
   133  		if targetLength < 0 || targetLength > MaxSpacePerRowOfLpad {
   134  			//NULL
   135  			nulls.Add(resultNUll, uint64(i))
   136  		} else if targetLength == 0 {
   137  			//empty string
   138  		} else if targetLength < sourceCharCnt {
   139  			//shorten source string
   140  			sourcePart := sourceRune[:targetLength]
   141  			sourcePartSlice := string(sourcePart)
   142  			results[i] = sourcePartSlice
   143  		} else if targetLength >= sourceCharCnt {
   144  			//calculate the space count
   145  			r := targetLength - sourceCharCnt
   146  			//complete pad count
   147  			p := r / padCharCnt
   148  			//partial pad count
   149  			m := r % padCharCnt
   150  			padPartSlice := string(padRune[:m])
   151  			for j := int64(0); j < p; j++ {
   152  				results[i] += pad
   153  			}
   154  			if m != 0 {
   155  				results[i] += padPartSlice
   156  			}
   157  			results[i] += source
   158  		}
   159  	}
   160  }