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 }