github.com/matrixorigin/matrixone@v1.2.0/pkg/container/types/array.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 types
    16  
    17  import (
    18  	"bytes"
    19  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    20  	"io"
    21  	"strconv"
    22  	"strings"
    23  )
    24  
    25  // NOTE: vecf32 and vecf64 in SQL is internally represented using T_array_float32 and T_array_float64.
    26  // array is used to avoid potential conflicts with the already existing vector class from vectorized execution engine.
    27  
    28  const (
    29  	MaxArrayDimension        = MaxVarcharLen
    30  	DefaultArraysToStringSep = " "
    31  )
    32  
    33  // BytesToArray bytes should be of little-endian format
    34  func BytesToArray[T RealNumbers](input []byte) (res []T) {
    35  	return DecodeSlice[T](input)
    36  }
    37  
    38  func ArrayToBytes[T RealNumbers](input []T) []byte {
    39  	return EncodeSlice[T](input)
    40  }
    41  
    42  func ArrayToString[T RealNumbers](input []T) string {
    43  	var buffer bytes.Buffer
    44  	_, _ = io.WriteString(&buffer, "[")
    45  	for i, value := range input {
    46  		if i > 0 {
    47  			_, _ = io.WriteString(&buffer, ", ")
    48  		}
    49  
    50  		// following the similar logic of float32 and float64 from
    51  		// - output.go #extractRowFromVector()
    52  		// - mysql_protocol.go #makeResultSetTextRow() MYSQL_TYPE_FLOAT  & MYSQL_TYPE_DOUBLE
    53  		// NOTE: vector does not handle NaN and Inf.
    54  		switch value := any(value).(type) {
    55  		case float32:
    56  			_, _ = io.WriteString(&buffer, strconv.FormatFloat(float64(value), 'f', -1, 32))
    57  		case float64:
    58  			_, _ = io.WriteString(&buffer, strconv.FormatFloat(value, 'f', -1, 64))
    59  		}
    60  	}
    61  	_, _ = io.WriteString(&buffer, "]")
    62  	return buffer.String()
    63  }
    64  
    65  func ArraysToString[T RealNumbers](input [][]T, sep string) string {
    66  	strValues := make([]string, len(input))
    67  	for i, row := range input {
    68  		strValues[i] = ArrayToString[T](row)
    69  	}
    70  	return strings.Join(strValues, sep)
    71  }
    72  
    73  func StringToArray[T RealNumbers](str string) ([]T, error) {
    74  	input := strings.ReplaceAll(str, " ", "")
    75  
    76  	if !(strings.HasPrefix(input, "[") && strings.HasSuffix(input, "]")) {
    77  		return nil, moerr.NewInternalErrorNoCtx("malformed vector input: %s", str)
    78  	}
    79  
    80  	if len(input) == 2 {
    81  		// We don't handle empty vector like "[]"
    82  		return nil, moerr.NewInternalErrorNoCtx("malformed vector input: %s", str)
    83  	}
    84  
    85  	// remove "[" and "]"
    86  	input = input[1 : len(input)-1]
    87  
    88  	numStrs := strings.Split(input, ",")
    89  	if len(numStrs) > MaxArrayDimension {
    90  		return nil, moerr.NewInternalErrorNoCtx("typeLen is over the MaxVectorLen: %v", MaxArrayDimension)
    91  	}
    92  	result := make([]T, len(numStrs))
    93  
    94  	var t T
    95  	var err error
    96  	for i, numStr := range numStrs {
    97  		t, err = stringToT[T](numStr)
    98  		if err != nil {
    99  			return nil, err
   100  		}
   101  		result[i] = t
   102  	}
   103  
   104  	return result, nil
   105  }
   106  
   107  // StringToArrayToBytes convert "[1,2,3]" --> []float32{1.0,2.0,3.0} --> []bytes{11,33...}
   108  func StringToArrayToBytes[T RealNumbers](input string) ([]byte, error) {
   109  	// Convert "[1,2,3]" --> []float32{1.0, 2.0, 3.0}
   110  	a, err := StringToArray[T](input)
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  	// Convert []float32{1.0, 2.0, 3.0} --> []byte{11, 33, 45, 56,.....}
   115  	return ArrayToBytes[T](a), nil
   116  }
   117  
   118  func BytesToArrayToString[T RealNumbers](input []byte) string {
   119  	// Convert []byte{11, 33, 45, 56,.....} --> []float32{1.0, 2.0, 3.0}
   120  	a := BytesToArray[T](input)
   121  
   122  	// Convert []float32{1.0, 2.0, 3.0} --> "[1,2,3]"
   123  	return ArrayToString[T](a)
   124  }