github.com/matrixorigin/matrixone@v0.7.0/pkg/frontend/internal_executor_test.go (about)

     1  // Copyright 2022 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 frontend
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"testing"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    23  	"github.com/matrixorigin/matrixone/pkg/config"
    24  	"github.com/matrixorigin/matrixone/pkg/defines"
    25  	ie "github.com/matrixorigin/matrixone/pkg/util/internalExecutor"
    26  	"github.com/stretchr/testify/assert"
    27  	"github.com/stretchr/testify/require"
    28  )
    29  
    30  func mockResultSet() *MysqlResultSet {
    31  	set := &MysqlResultSet{}
    32  	col := &MysqlColumn{}
    33  	col.SetName("test")
    34  	col.SetColumnType(defines.MYSQL_TYPE_LONG)
    35  	col.SetSigned(true)
    36  	set.AddColumn(col)
    37  	set.AddRow([]any{42})
    38  	return set
    39  }
    40  
    41  type miniExec struct {
    42  	sess *Session
    43  }
    44  
    45  func (e *miniExec) doComQuery(context.Context, string) error {
    46  	_ = e.sess.GetMysqlProtocol()
    47  	return nil
    48  }
    49  func (e *miniExec) SetSession(sess *Session) {
    50  	e.sess = sess
    51  }
    52  
    53  func TestIe(t *testing.T) {
    54  	ctx := context.TODO()
    55  	pu := config.NewParameterUnit(&config.FrontendParameters{}, nil, nil, nil, nil)
    56  
    57  	// Mock autoIncrCaches
    58  	aic := defines.AutoIncrCaches{}
    59  
    60  	executor := newIe(pu, &miniExec{}, aic)
    61  	executor.ApplySessionOverride(ie.NewOptsBuilder().Username("dump").Finish())
    62  	sess := executor.newCmdSession(ctx, ie.NewOptsBuilder().Database("mo_catalog").Internal(true).Finish())
    63  	assert.Equal(t, "dump", sess.GetMysqlProtocol().GetUserName())
    64  
    65  	err := executor.Exec(ctx, "whatever", ie.NewOptsBuilder().Finish())
    66  	assert.NoError(t, err)
    67  	res := executor.Query(ctx, "whatever", ie.NewOptsBuilder().Finish())
    68  	assert.NoError(t, err)
    69  	assert.Equal(t, uint64(0), res.RowCount())
    70  }
    71  
    72  func TestIeProto(t *testing.T) {
    73  	pu := config.NewParameterUnit(&config.FrontendParameters{}, nil, nil, nil, nil)
    74  
    75  	// Mock autoIncrCaches
    76  	aic := defines.AutoIncrCaches{}
    77  
    78  	executor := NewInternalExecutor(pu, aic)
    79  	p := executor.proto
    80  	assert.True(t, p.IsEstablished())
    81  	p.SetEstablished()
    82  	p.Quit()
    83  	p.ResetStatistics()
    84  	_ = p.GetStats()
    85  	_ = p.ConnectionID()
    86  	ctx := context.TODO()
    87  	assert.Panics(t, func() { p.GetRequest([]byte{1}) })
    88  	assert.Panics(t, func() { p.Peer() })
    89  	assert.Nil(t, p.SendColumnDefinitionPacket(ctx, nil, 1))
    90  	assert.Nil(t, p.SendColumnCountPacket(1))
    91  	assert.Nil(t, p.SendEOFPacketIf(0, 1))
    92  	assert.Nil(t, p.sendOKPacket(1, 1, 0, 0, ""))
    93  	assert.Nil(t, p.sendEOFOrOkPacket(0, 1))
    94  
    95  	p.stashResult = true
    96  	p.SendResponse(ctx, &Response{
    97  		category:     OkResponse,
    98  		status:       0,
    99  		affectedRows: 1,
   100  		data:         nil,
   101  	})
   102  	assert.Nil(t, nil, p.result.resultSet)
   103  	assert.Equal(t, uint64(1), p.result.affectedRows)
   104  	p.SendResponse(ctx, &Response{
   105  		category: ResultResponse,
   106  		status:   0,
   107  		data: &MysqlExecutionResult{
   108  			affectedRows: 1,
   109  			mrs:          mockResultSet(),
   110  		},
   111  	})
   112  	v, _ := p.result.Value(ctx, 0, 0)
   113  	assert.Equal(t, 42, v.(int))
   114  
   115  	p.ResetStatistics()
   116  	assert.NoError(t, p.SendResultSetTextBatchRowSpeedup(mockResultSet(), 1))
   117  	r := p.swapOutResult()
   118  	v, e := r.Value(ctx, 0, 0)
   119  	assert.NoError(t, e)
   120  	assert.Equal(t, 42, v.(int))
   121  	p.ResetStatistics()
   122  	assert.NoError(t, p.SendResultSetTextBatchRow(mockResultSet(), 1))
   123  	r = p.swapOutResult()
   124  	v, e = r.Value(ctx, 0, 0)
   125  	assert.NoError(t, e)
   126  	assert.Equal(t, 42, v.(int))
   127  	assert.Equal(t, uint64(1), r.affectedRows)
   128  	p.ResetStatistics()
   129  
   130  	r = p.swapOutResult()
   131  	assert.Equal(t, uint64(0), r.resultSet.GetRowCount())
   132  }
   133  
   134  func TestIeResult(t *testing.T) {
   135  	set := mockResultSet()
   136  	result := &internalExecResult{affectedRows: 1, resultSet: set, err: moerr.NewInternalError(context.TODO(), "random")}
   137  	require.Equal(t, "internal error: random", result.Error().Error())
   138  	require.Equal(t, uint64(1), result.ColumnCount())
   139  	require.Equal(t, uint64(1), result.RowCount())
   140  	n, ty, s, e := result.Column(context.TODO(), 0)
   141  	require.NoError(t, e)
   142  	require.Equal(t, "test", n)
   143  	require.Equal(t, defines.MYSQL_TYPE_LONG, defines.MysqlType(ty))
   144  	require.True(t, s)
   145  	_, _, _, e = result.Column(context.TODO(), 1)
   146  	require.Error(t, e)
   147  	r, e := result.Row(context.TODO(), 0)
   148  	require.Equal(t, 42, r[0].(int))
   149  	require.NoError(t, e)
   150  	_, e = result.Row(context.TODO(), 1)
   151  	require.Error(t, e)
   152  	v, e := result.Value(context.TODO(), 0, 0)
   153  	require.NoError(t, e)
   154  	require.Equal(t, 42, v.(int))
   155  	v, e = result.ValueByName(context.TODO(), 0, "test")
   156  	require.NoError(t, e)
   157  	require.Equal(t, 42, v.(int))
   158  	str, e := result.StringValueByName(context.TODO(), 0, "test")
   159  	require.NoError(t, e)
   160  	require.Equal(t, "42", str)
   161  	str, e = result.StringValueByName(context.TODO(), 0, "tet")
   162  	require.Error(t, e)
   163  	require.Equal(t, "", str)
   164  }
   165  
   166  func DebugPrintInternalResult(ctx context.Context, res ie.InternalExecResult) string {
   167  	buf := &bytes.Buffer{}
   168  	for i := uint64(0); i < res.ColumnCount(); i++ {
   169  		col, _, _, _ := res.Column(context.TODO(), i)
   170  		buf.WriteString(col + ": ")
   171  		for j := uint64(0); j < res.RowCount(); j++ {
   172  			s, _ := res.StringValueByName(ctx, j, col)
   173  			buf.WriteString(" | ")
   174  			buf.WriteString(s)
   175  		}
   176  		buf.WriteString("\n")
   177  	}
   178  	return buf.String()
   179  }