Skip to content
Snippets Groups Projects
Unverified Commit f08565d6 authored by Boyu Tan's avatar Boyu Tan Committed by GitHub
Browse files

[MatrixCamp] Add Built-in function lpad (#2070)

parent 62f94168
No related branches found
No related tags found
No related merge requests found
......@@ -31,4 +31,4 @@ pkg/sql/colexec/extend/overload/*.go
!pkg/sql/colexec/extend/overload/init.go
pkg/vm/engine/tpe/tuplecodec/clusterstore
pkg/vm/engine/tpe/tuplecodec/read_profile
pkg/vm/engine/tpe/engine/read_profile
\ No newline at end of file
pkg/vm/engine/tpe/engine/read_profile
// Copyright 2021 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package multi
import (
"errors"
"fmt"
"github.com/matrixorigin/matrixone/pkg/builtin"
"github.com/matrixorigin/matrixone/pkg/container/nulls"
"github.com/matrixorigin/matrixone/pkg/container/types"
"github.com/matrixorigin/matrixone/pkg/container/vector"
"github.com/matrixorigin/matrixone/pkg/sql/colexec/extend"
"github.com/matrixorigin/matrixone/pkg/sql/colexec/extend/overload"
"github.com/matrixorigin/matrixone/pkg/vectorize/lpad"
"github.com/matrixorigin/matrixone/pkg/vm/process"
)
var ArgAndRets_Lpad = []argsAndRet{
{[]types.T{types.T_varchar, types.T_int64, types.T_varchar}, types.T_varchar},
}
func init() {
extend.FunctionRegistry["lpad"] = builtin.Lpad
for _, item := range ArgAndRets_Lpad {
overload.AppendFunctionRets(builtin.Lpad, item.args, item.ret)
}
extend.MultiReturnTypes[builtin.Lpad] = func(es []extend.Extend) types.T {
return getMultiReturnType(builtin.Lpad, es)
}
extend.MultiStrings[builtin.Lpad] = func(es []extend.Extend) string {
return fmt.Sprintf("lpad(%s, %s, %s)", es[0], es[1], es[2])
}
overload.OpTypes[builtin.Lpad] = overload.Multi
overload.MultiOps[builtin.Lpad] = []*overload.MultiOp{
{
Min: 3,
Max: 3,
Typ: types.T_varchar,
ReturnType: types.T_varchar,
Fn: func(vecs []*vector.Vector, proc *process.Process, cs []bool) (*vector.Vector, error) {
vs := vecs[0].Col.(*types.Bytes) //Get the first arg
if !cs[1] && vecs[1].Typ.Oid != types.T_int64 {
return nil, errors.New("The second argument of the lpad function must be an int64 constant")
}
if !cs[2] && vecs[2].Typ.Oid != types.T_varchar {
return nil, errors.New("The third argument of the lpad function must be an string constant")
}
lens := vecs[1].Col.([]int64)
padds := vecs[2].Col.(*types.Bytes)
for _, num := range lens {
if num < 0 {
vec, err := process.Get(proc, 24*int64(len(vs.Lengths)), types.Type{Oid: types.T_varchar, Size: 24})
if err != nil {
return nil, err
}
nulls.Set(vec.Nsp, vecs[0].Nsp)
temp := ""
lengths_temp := []uint32{}
offsets_temp := []uint32{}
for k := 0; k < len(vs.Lengths); k++ {
temp += "NULL"
lengths_temp = append(lengths_temp, 4)
if len(offsets_temp) == 0 {
offsets_temp = append(offsets_temp, 0)
} else {
offsets_temp = append(offsets_temp, offsets_temp[len(offsets_temp)-1]+4)
}
}
res := &types.Bytes{
Data: []byte(temp),
Lengths: lengths_temp,
Offsets: offsets_temp,
}
vector.SetCol(vec, res)
return vec, nil
}
}
//use vecs[0] as return
if vecs[0].Ref == 1 || vecs[0].Ref == 0 {
vecs[0].Ref = 0
temp := lpad.LpadVarchar(vs, lens, padds)
vs.Data = make([]byte, len(temp.Data))
vs.Lengths = make([]uint32, len(temp.Lengths))
vs.Offsets = make([]uint32, len(temp.Offsets))
copy(vs.Data, temp.Data)
copy(vs.Lengths, temp.Lengths)
copy(vs.Offsets, temp.Offsets)
return vecs[0], nil
}
vec, err := process.Get(proc, 24*int64(len(vs.Lengths)), types.Type{Oid: types.T_varchar, Size: 24})
if err != nil {
return nil, err
}
nulls.Set(vec.Nsp, vecs[0].Nsp)
vector.SetCol(vec, lpad.LpadVarchar(vs, lens, padds))
return vec, nil
// digits := int64(0)
// vs := vecs[0].Col.([]uint8)
// if len(vecs) > 1 {
// if !cs[1] && vecs[1].Typ.Oid != types.T_int64 {
// return nil, errors.New("The second argument of the round function must be an int64 constant")
// }
// digits = vecs[1].Col.([]int64)[0]
// }
// if vecs[0].Ref == 1 || vecs[0].Ref == 0 {
// vecs[0].Ref = 0
// floor.FloorUint8(vs, vs, digits)
// return vecs[0], nil
// }
// vec, err := process.Get(proc, int64(len(vs)), types.Type{Oid: types.T_uint8, Size: 1})
// if err != nil {
// return nil, err
// }
// rs := encoding.DecodeUint8Slice(vec.Data)
// rs = rs[:len(vs)]
// vec.Col = rs
// nulls.Set(vec.Nsp, vecs[0].Nsp)
// vector.SetCol(vec, floor.FloorUint8(vs, rs, digits))
// return vec, nil
},
},
}
}
......@@ -42,4 +42,5 @@ const (
DayOfYear
Month
Weekday
Lpad
)
// Copyright 2022 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package lpad
import "github.com/matrixorigin/matrixone/pkg/container/types"
var (
LpadVarchar func(*types.Bytes, []int64, *types.Bytes) *types.Bytes
)
func init() {
LpadVarchar = lpadVarcharPure
}
func lpadVarcharPure(a *types.Bytes, b []int64, c *types.Bytes) *types.Bytes {
var res *types.Bytes = &types.Bytes{}
//in fact,the length of three slice is the same with each other
for i := 0; i < len(a.Lengths); i++ {
if a.Lengths[i] > uint32(b[0]) { //length less
res.Offsets = append(res.Offsets, uint32(len(res.Data)))
res.Data = append(res.Data, a.Data[a.Offsets[i]:a.Offsets[i]+uint32(b[0])]...)
res.Lengths = append(res.Lengths, uint32(b[0]))
} else {
lens := uint32(b[0]) - a.Lengths[i]
t1 := lens / c.Lengths[0]
t2 := lens % c.Lengths[0]
temp := []byte{}
for j := 0; j < int(t1); j++ {
temp = append(temp, c.Data[c.Offsets[0]:c.Offsets[0]+c.Lengths[0]]...)
}
temp = append(temp, c.Data[c.Offsets[0]:c.Offsets[0]+t2]...)
temp = append(temp, a.Data[a.Offsets[i]:a.Offsets[i]+a.Lengths[i]]...)
res.Offsets = append(res.Offsets, uint32(len(res.Data)))
res.Data = append(res.Data, temp...)
res.Lengths = append(res.Lengths, uint32(len(temp)))
}
}
return res
}
// Copyright 2022 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package lpad
import (
"testing"
"github.com/matrixorigin/matrixone/pkg/container/types"
"github.com/stretchr/testify/require"
)
func TestLpadVarchar(t *testing.T) {
//Test values
// origins := []string{"hi", "hi","hishjajsa","hish&sa*(#jsa","hish&sa*(#jsa","hishjajsa"}
origins := &types.Bytes{
Data: []byte("hihihishjajsahish&sa*(#jsahish&sa*(#jsahishjajsaabc"),
Offsets: []uint32{0, 2, 4, 13, 26, 39, 48},
Lengths: []uint32{2, 2, 9, 13, 13, 9, 3},
}
origins_int64 := []int64{22}
// origins_padd := []string{"??", "??", "??saso","?^^%$so","?^^%$so","^%so"}
origins_padd := &types.Bytes{
Data: []byte("??so"),
Offsets: []uint32{0},
Lengths: []uint32{4},
}
//Predefined Correct Values
results := []string{"??so??so??so??so??sohi", "??so??so??so??so??sohi", "??so??so??so?hishjajsa",
"??so??so?hish&sa*(#jsa","??so??so?hish&sa*(#jsa", "??so??so??so?hishjajsa","??so??so??so??so??sabc"}
or := LpadVarchar(origins, origins_int64, origins_padd)
for i, _ := range results {
require.Equal(t, []byte(results[i]), or.Data[or.Offsets[i]:or.Offsets[i]+or.Lengths[i]])
}
}
......@@ -18,10 +18,11 @@ import (
"bytes"
"encoding/binary"
"fmt"
"github.com/matrixorigin/matrixone/pkg/encoding"
"reflect"
"sync"
"unsafe"
"github.com/matrixorigin/matrixone/pkg/encoding"
)
var pool = sync.Pool{
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment