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  }