github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/evalExpression_test.go (about) 1 // Copyright 2021 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 colexec 16 17 import ( 18 "testing" 19 20 "github.com/matrixorigin/matrixone/pkg/container/batch" 21 "github.com/matrixorigin/matrixone/pkg/container/types" 22 "github.com/matrixorigin/matrixone/pkg/container/vector" 23 "github.com/matrixorigin/matrixone/pkg/pb/plan" 24 "github.com/matrixorigin/matrixone/pkg/sql/plan/function" 25 "github.com/matrixorigin/matrixone/pkg/testutil" 26 "github.com/matrixorigin/matrixone/pkg/vm/process" 27 "github.com/stretchr/testify/require" 28 ) 29 30 func TestFixedExpressionExecutor(t *testing.T) { 31 proc := testutil.NewProcess() 32 33 // Expr_C 34 con := makePlan2Int64ConstExprWithType(218311) 35 conExprExecutor, err := NewExpressionExecutor(proc, con) 36 require.NoError(t, err) 37 38 emptyBatch := &batch.Batch{} 39 emptyBatch.SetRowCount(10) 40 vec, err := conExprExecutor.Eval(proc, []*batch.Batch{emptyBatch}) 41 require.NoError(t, err) 42 curr1 := proc.Mp().CurrNB() 43 { 44 require.Equal(t, 10, vec.Length()) 45 require.Equal(t, types.T_int64.ToType(), *vec.GetType()) 46 require.Equal(t, int64(218311), vector.MustFixedCol[int64](vec)[0]) 47 require.Equal(t, false, vec.GetNulls().Contains(0)) 48 } 49 _, err = conExprExecutor.Eval(proc, []*batch.Batch{emptyBatch}) 50 require.NoError(t, err) 51 require.Equal(t, curr1, proc.Mp().CurrNB()) // check memory reuse 52 conExprExecutor.Free() 53 require.Equal(t, int64(0), proc.Mp().CurrNB()) 54 55 // Expr_T 56 ety := &plan.Expr{ 57 Expr: &plan.Expr_T{T: &plan.TargetType{}}, 58 Typ: plan.Type{ 59 Id: int32(types.T_decimal128), 60 Width: 30, 61 Scale: 6, 62 NotNullable: true, 63 }, 64 } 65 curr2 := proc.Mp().CurrNB() 66 typExpressionExecutor, err := NewExpressionExecutor(proc, ety) 67 require.NoError(t, err) 68 69 emptyBatch.SetRowCount(5) 70 vec, err = typExpressionExecutor.Eval(proc, []*batch.Batch{emptyBatch}) 71 require.NoError(t, err) 72 { 73 require.Equal(t, 5, vec.Length()) 74 require.Equal(t, types.T_decimal128, vec.GetType().Oid) 75 require.Equal(t, int32(30), vec.GetType().Width) 76 require.Equal(t, int32(6), vec.GetType().Scale) 77 } 78 typExpressionExecutor.Free() 79 require.Equal(t, curr2, proc.Mp().CurrNB()) 80 } 81 82 func TestColumnExpressionExecutor(t *testing.T) { 83 proc := testutil.NewProcess() 84 85 col := &plan.Expr{ 86 Expr: &plan.Expr_Col{ 87 Col: &plan.ColRef{ 88 RelPos: 0, 89 ColPos: 2, 90 }, 91 }, 92 Typ: plan.Type{ 93 Id: int32(types.T_int32), 94 NotNullable: true, 95 }, 96 } 97 colExprExecutor, err := NewExpressionExecutor(proc, col) 98 require.NoError(t, err) 99 100 bat := testutil.NewBatch( 101 []types.Type{types.T_int8.ToType(), types.T_int16.ToType(), types.T_int32.ToType(), types.T_int64.ToType()}, 102 true, 10, proc.Mp()) 103 curr := proc.Mp().CurrNB() 104 vec, err := colExprExecutor.Eval(proc, []*batch.Batch{bat}) 105 require.NoError(t, err) 106 { 107 require.Equal(t, types.T_int32.ToType(), *vec.GetType()) 108 require.Equal(t, 10, vec.Length()) 109 } 110 colExprExecutor.Free() // cannot free the vec of batch 111 require.Equal(t, curr, proc.Mp().CurrNB()) 112 } 113 114 func TestFunctionExpressionExecutor(t *testing.T) { 115 { 116 proc := testutil.NewProcess() 117 118 bat := testutil.NewBatchWithVectors( 119 []*vector.Vector{ 120 testutil.NewVector(2, types.T_int64.ToType(), proc.Mp(), false, []int64{1, 2}), 121 }, make([]int64, 2)) 122 123 currStart := proc.Mp().CurrNB() 124 fExprExecutor := &FunctionExpressionExecutor{} 125 err := fExprExecutor.Init(proc, 2, types.T_int64.ToType(), 126 func(params []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int) error { 127 v1 := vector.GenerateFunctionFixedTypeParameter[int64](params[0]) 128 v2 := vector.GenerateFunctionFixedTypeParameter[int64](params[1]) 129 rs := vector.MustFunctionResult[int64](result) 130 for i := 0; i < length; i++ { 131 v11, null11 := v1.GetValue(uint64(i)) 132 v22, null22 := v2.GetValue(uint64(i)) 133 if null11 || null22 { 134 err := rs.Append(0, true) 135 if err != nil { 136 return err 137 } 138 } else { 139 err := rs.Append(v11+v22, false) 140 if err != nil { 141 return err 142 } 143 } 144 } 145 return nil 146 }, nil) 147 require.NoError(t, err) 148 149 col1 := &plan.Expr{ 150 Expr: &plan.Expr_Col{ 151 Col: &plan.ColRef{ 152 RelPos: 0, 153 ColPos: 0, 154 }, 155 }, 156 Typ: plan.Type{ 157 Id: int32(types.T_int64), 158 NotNullable: true, 159 }, 160 } 161 col2 := makePlan2Int64ConstExprWithType(100) 162 executor1, err := NewExpressionExecutor(proc, col1) 163 require.NoError(t, err) 164 executor2, err := NewExpressionExecutor(proc, col2) 165 require.NoError(t, err) 166 fExprExecutor.SetParameter(0, executor1) 167 fExprExecutor.SetParameter(1, executor2) 168 169 vec, err := fExprExecutor.Eval(proc, []*batch.Batch{bat}) 170 require.NoError(t, err) 171 curr3 := proc.Mp().CurrNB() 172 { 173 require.Equal(t, 2, vec.Length()) 174 require.Equal(t, types.T_int64.ToType(), *vec.GetType()) 175 require.Equal(t, int64(101), vector.MustFixedCol[int64](vec)[0]) // 1+100 176 require.Equal(t, int64(102), vector.MustFixedCol[int64](vec)[1]) // 2+100 177 } 178 _, err = fExprExecutor.Eval(proc, []*batch.Batch{bat}) 179 require.NoError(t, err) 180 require.Equal(t, curr3, proc.Mp().CurrNB()) 181 fExprExecutor.Free() 182 proc.FreeVectors() 183 require.Equal(t, currStart, proc.Mp().CurrNB()) 184 } 185 186 // test memory leak if constant fold happens 187 { 188 proc := testutil.NewProcess() 189 190 col1 := makePlan2BoolConstExprWithType(true) 191 col2 := makePlan2BoolConstExprWithType(true) 192 193 fExpr := &plan.Expr{ 194 Typ: plan.Type{ 195 Id: int32(types.T_bool), 196 NotNullable: true, 197 }, 198 Expr: &plan.Expr_F{ 199 F: &plan.Function{ 200 Func: &plan.ObjectRef{ 201 ObjName: function.AndFunctionName, 202 Obj: function.AndFunctionEncodedID, 203 }, 204 Args: []*plan.Expr{col1, col2}, 205 }, 206 }, 207 } 208 currNb := proc.Mp().CurrNB() 209 executor, err := NewExpressionExecutor(proc, fExpr) 210 require.NoError(t, err) 211 _, ok := executor.(*FixedVectorExpressionExecutor) 212 require.Equal(t, true, ok) 213 executor.Free() 214 proc.FreeVectors() 215 require.Equal(t, currNb, proc.Mp().CurrNB()) 216 } 217 } 218 219 // some util code copied from package `plan`. 220 func makePlan2Int64ConstExprWithType(v int64) *plan.Expr { 221 return &plan.Expr{ 222 Expr: makePlan2Int64ConstExpr(v), 223 Typ: plan.Type{ 224 Id: int32(types.T_int64), 225 NotNullable: true, 226 }, 227 } 228 } 229 230 func makePlan2Int64ConstExpr(v int64) *plan.Expr_Lit { 231 return &plan.Expr_Lit{Lit: &plan.Literal{ 232 Isnull: false, 233 Value: &plan.Literal_I64Val{ 234 I64Val: v, 235 }, 236 }} 237 } 238 239 func makePlan2BoolConstExprWithType(b bool) *plan.Expr { 240 return &plan.Expr{ 241 Expr: makePlan2BoolConstExpr(b), 242 Typ: plan.Type{ 243 Id: int32(types.T_bool), 244 NotNullable: true, 245 }, 246 } 247 } 248 249 func makePlan2BoolConstExpr(b bool) *plan.Expr_Lit { 250 return &plan.Expr_Lit{Lit: &plan.Literal{ 251 Isnull: false, 252 Value: &plan.Literal_Bval{ 253 Bval: b, 254 }, 255 }} 256 }