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 }