github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/colexec/mergeorder/order_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 mergeorder
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"fmt"
    21  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    22  	"testing"
    23  
    24  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    25  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    26  	"github.com/matrixorigin/matrixone/pkg/container/types"
    27  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    28  	"github.com/matrixorigin/matrixone/pkg/testutil"
    29  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    30  	"github.com/stretchr/testify/require"
    31  )
    32  
    33  const (
    34  	Rows          = 10     // default rows
    35  	BenchmarkRows = 100000 // default rows for benchmark
    36  )
    37  
    38  // add unit tests for cases
    39  type orderTestCase struct {
    40  	arg    *Argument
    41  	types  []types.Type
    42  	proc   *process.Process
    43  	cancel context.CancelFunc
    44  }
    45  
    46  func TestString(t *testing.T) {
    47  	tcs := []orderTestCase{
    48  		newTestCase([]types.Type{{Oid: types.T_int8}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 0}}),
    49  		newTestCase([]types.Type{{Oid: types.T_int8}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}}),
    50  		newTestCase([]types.Type{{Oid: types.T_int8}, {Oid: types.T_int64}}, []*plan.OrderBySpec{{Expr: newExpression(1), Flag: 0}}),
    51  		newTestCase([]types.Type{{Oid: types.T_int8}, {Oid: types.T_int64}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}}),
    52  		newTestCase([]types.Type{{Oid: types.T_int8}, {Oid: types.T_int64}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}, {Expr: newExpression(1), Flag: 0}}),
    53  	}
    54  	buf := new(bytes.Buffer)
    55  	for _, tc := range tcs {
    56  		String(tc.arg, buf)
    57  	}
    58  }
    59  
    60  func TestPrepare(t *testing.T) {
    61  	tcs := []orderTestCase{
    62  		newTestCase([]types.Type{{Oid: types.T_int8}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 0}}),
    63  		newTestCase([]types.Type{{Oid: types.T_int8}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}}),
    64  		newTestCase([]types.Type{{Oid: types.T_int8}, {Oid: types.T_int64}}, []*plan.OrderBySpec{{Expr: newExpression(1), Flag: 0}}),
    65  		newTestCase([]types.Type{{Oid: types.T_int8}, {Oid: types.T_int64}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}}),
    66  		newTestCase([]types.Type{{Oid: types.T_int8}, {Oid: types.T_int64}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}, {Expr: newExpression(1), Flag: 0}}),
    67  	}
    68  	for _, tc := range tcs {
    69  		err := Prepare(tc.proc, tc.arg)
    70  		require.NoError(t, err)
    71  	}
    72  }
    73  
    74  func TestOrder(t *testing.T) {
    75  	tcs := []orderTestCase{
    76  		newTestCase([]types.Type{{Oid: types.T_int8}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 0}}),
    77  		newTestCase([]types.Type{{Oid: types.T_int8}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}}),
    78  		newTestCase([]types.Type{{Oid: types.T_int8}, {Oid: types.T_int64}}, []*plan.OrderBySpec{{Expr: newExpression(1), Flag: 0}}),
    79  		newTestCase([]types.Type{{Oid: types.T_int8}, {Oid: types.T_int64}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}}),
    80  		newTestCase([]types.Type{{Oid: types.T_int8}, {Oid: types.T_int64}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}, {Expr: newExpression(1), Flag: 0}}),
    81  	}
    82  
    83  	for tci, tc := range tcs {
    84  		err := Prepare(tc.proc, tc.arg)
    85  		require.NoError(t, err)
    86  		tc.proc.Reg.MergeReceivers[0].Ch <- newIntBatch(tc.types, tc.proc, Rows, tc.arg.Fs)
    87  		tc.proc.Reg.MergeReceivers[0].Ch <- &batch.Batch{}
    88  		tc.proc.Reg.MergeReceivers[0].Ch <- nil
    89  		tc.proc.Reg.MergeReceivers[1].Ch <- newIntBatch(tc.types, tc.proc, Rows, tc.arg.Fs)
    90  		tc.proc.Reg.MergeReceivers[1].Ch <- &batch.Batch{}
    91  		tc.proc.Reg.MergeReceivers[1].Ch <- nil
    92  		for {
    93  			if ok, err := Call(0, tc.proc, tc.arg, false, false); ok || err != nil {
    94  				require.NoError(t, err)
    95  				// do the result check
    96  				if len(tc.arg.Fs) > 0 {
    97  					desc := tc.arg.Fs[0].Flag&plan.OrderBySpec_DESC != 0
    98  					index := tc.arg.Fs[0].Expr.Expr.(*plan.Expr_Col).Col.ColPos
    99  					bat := tc.proc.Reg.InputBatch
   100  					vec := bat.Vecs[index]
   101  					if vec.Typ.Oid == types.T_int8 {
   102  						i8c := vector.MustTCols[int8](vec)
   103  						if desc {
   104  							for j := range i8c {
   105  								if j > 0 {
   106  									require.True(t, i8c[j] <= i8c[j-1], fmt.Sprintf("tc %d require desc, but get %v", tci, i8c))
   107  								}
   108  							}
   109  						} else {
   110  							for j := range i8c {
   111  								if j > 0 {
   112  									require.True(t, i8c[j] >= i8c[j-1])
   113  								}
   114  							}
   115  						}
   116  					} else if vec.Typ.Oid == types.T_int64 {
   117  						i64c := vector.MustTCols[int64](vec)
   118  						if desc {
   119  							for j := range i64c {
   120  								if j > 0 {
   121  									require.True(t, i64c[j] <= i64c[j-1])
   122  								}
   123  							}
   124  						} else {
   125  							for j := range i64c {
   126  								if j > 0 {
   127  									require.True(t, i64c[j] >= i64c[j-1])
   128  								}
   129  							}
   130  						}
   131  					}
   132  				}
   133  
   134  				if tc.proc.Reg.InputBatch != nil {
   135  					tc.proc.Reg.InputBatch.Clean(tc.proc.Mp())
   136  				}
   137  				break
   138  			}
   139  		}
   140  		for i := 0; i < len(tc.proc.Reg.MergeReceivers); i++ { // simulating the end of a pipeline
   141  			for len(tc.proc.Reg.MergeReceivers[i].Ch) > 0 {
   142  				bat := <-tc.proc.Reg.MergeReceivers[i].Ch
   143  				if bat != nil {
   144  					bat.Clean(tc.proc.Mp())
   145  				}
   146  			}
   147  		}
   148  		require.Equal(t, tc.proc.Mp().CurrNB(), int64(0))
   149  	}
   150  }
   151  
   152  func BenchmarkOrder(b *testing.B) {
   153  	for i := 0; i < b.N; i++ {
   154  		tcs := []orderTestCase{
   155  			newTestCase([]types.Type{{Oid: types.T_int8}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 0}}),
   156  			newTestCase([]types.Type{{Oid: types.T_int8}}, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}}),
   157  		}
   158  		t := new(testing.T)
   159  		for _, tc := range tcs {
   160  			err := Prepare(tc.proc, tc.arg)
   161  			require.NoError(t, err)
   162  			tc.proc.Reg.MergeReceivers[0].Ch <- newRandomBatch(tc.types, tc.proc, BenchmarkRows)
   163  			tc.proc.Reg.MergeReceivers[0].Ch <- &batch.Batch{}
   164  			tc.proc.Reg.MergeReceivers[0].Ch <- nil
   165  			tc.proc.Reg.MergeReceivers[1].Ch <- newRandomBatch(tc.types, tc.proc, BenchmarkRows)
   166  			tc.proc.Reg.MergeReceivers[1].Ch <- &batch.Batch{}
   167  			tc.proc.Reg.MergeReceivers[1].Ch <- nil
   168  			for {
   169  				if ok, err := Call(0, tc.proc, tc.arg, false, false); ok || err != nil {
   170  					if tc.proc.Reg.InputBatch != nil {
   171  						tc.proc.Reg.InputBatch.Clean(tc.proc.Mp())
   172  					}
   173  					break
   174  				}
   175  			}
   176  			for i := 0; i < len(tc.proc.Reg.MergeReceivers); i++ { // simulating the end of a pipeline
   177  				for len(tc.proc.Reg.MergeReceivers[i].Ch) > 0 {
   178  					bat := <-tc.proc.Reg.MergeReceivers[i].Ch
   179  					if bat != nil {
   180  						bat.Clean(tc.proc.Mp())
   181  					}
   182  				}
   183  			}
   184  		}
   185  	}
   186  }
   187  
   188  func newTestCase(ts []types.Type, fs []*plan.OrderBySpec) orderTestCase {
   189  	proc := testutil.NewProcessWithMPool(mpool.MustNewZero())
   190  	proc.Reg.MergeReceivers = make([]*process.WaitRegister, 2)
   191  	ctx, cancel := context.WithCancel(context.Background())
   192  	proc.Reg.MergeReceivers[0] = &process.WaitRegister{
   193  		Ctx: ctx,
   194  		Ch:  make(chan *batch.Batch, 3),
   195  	}
   196  	proc.Reg.MergeReceivers[1] = &process.WaitRegister{
   197  		Ctx: ctx,
   198  		Ch:  make(chan *batch.Batch, 3),
   199  	}
   200  	return orderTestCase{
   201  		types: ts,
   202  		proc:  proc,
   203  		arg: &Argument{
   204  			Fs: fs,
   205  		},
   206  		cancel: cancel,
   207  	}
   208  }
   209  
   210  func newExpression(pos int32) *plan.Expr {
   211  	return &plan.Expr{
   212  		Expr: &plan.Expr_Col{
   213  			Col: &plan.ColRef{
   214  				ColPos: pos,
   215  			},
   216  		},
   217  	}
   218  }
   219  
   220  func newIntBatch(ts []types.Type, proc *process.Process, rows int64, fs []*plan.OrderBySpec) *batch.Batch {
   221  	vs := make([]*vector.Vector, len(ts))
   222  	for i, t := range ts {
   223  		generateDescData := false
   224  		for _, f := range fs {
   225  			if f.Flag == plan.OrderBySpec_DESC {
   226  				index := f.Expr.Expr.(*plan.Expr_Col).Col.ColPos
   227  				if int(index) == i {
   228  					generateDescData = true
   229  				}
   230  			}
   231  		}
   232  
   233  		if t.Oid == types.T_int8 {
   234  			values := make([]int8, rows)
   235  			if generateDescData {
   236  				for j := range values {
   237  					values[j] = int8(-j)
   238  				}
   239  			} else {
   240  				for j := range values {
   241  					values[j] = int8(j + 1)
   242  				}
   243  			}
   244  			vs[i] = testutil.NewVector(int(rows), t, proc.Mp(), false, values)
   245  		} else if t.Oid == types.T_int64 {
   246  			values := make([]int64, rows)
   247  			if generateDescData {
   248  				for j := range values {
   249  					values[j] = int64(-j)
   250  				}
   251  			} else {
   252  				for j := range values {
   253  					values[j] = int64(j + 1)
   254  				}
   255  			}
   256  			vs[i] = testutil.NewVector(int(rows), t, proc.Mp(), false, values)
   257  		}
   258  	}
   259  	zs := make([]int64, rows)
   260  	for i := range zs {
   261  		zs[i] = 1
   262  	}
   263  	return testutil.NewBatchWithVectors(vs, zs)
   264  }
   265  
   266  func newRandomBatch(ts []types.Type, proc *process.Process, rows int64) *batch.Batch {
   267  	return testutil.NewBatch(ts, false, int(rows), proc.Mp())
   268  }