github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/compile/compile_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 compile 16 17 import ( 18 "context" 19 "fmt" 20 "github.com/matrixorigin/matrixone/pkg/txn/client" 21 "os" 22 "testing" 23 "time" 24 25 "github.com/matrixorigin/matrixone/pkg/catalog" 26 "github.com/matrixorigin/matrixone/pkg/defines" 27 28 "github.com/matrixorigin/matrixone/pkg/common/reuse" 29 30 "github.com/golang/mock/gomock" 31 "github.com/matrixorigin/matrixone/pkg/cnservice/cnclient" 32 "github.com/matrixorigin/matrixone/pkg/common/buffer" 33 "github.com/matrixorigin/matrixone/pkg/container/batch" 34 mock_frontend "github.com/matrixorigin/matrixone/pkg/frontend/test" 35 "github.com/matrixorigin/matrixone/pkg/pb/plan" 36 "github.com/matrixorigin/matrixone/pkg/pb/txn" 37 "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql" 38 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 39 plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" 40 "github.com/matrixorigin/matrixone/pkg/testutil" 41 "github.com/matrixorigin/matrixone/pkg/testutil/testengine" 42 "github.com/matrixorigin/matrixone/pkg/util/fault" 43 "github.com/matrixorigin/matrixone/pkg/vm/engine" 44 "github.com/matrixorigin/matrixone/pkg/vm/process" 45 "github.com/stretchr/testify/require" 46 ) 47 48 type compileTestCase struct { 49 sql string 50 pn *plan.Plan 51 e engine.Engine 52 stmt tree.Statement 53 proc *process.Process 54 } 55 56 var ( 57 tcs []compileTestCase 58 ) 59 60 func init() { 61 tcs = []compileTestCase{ 62 newTestCase("select 1", new(testing.T)), 63 newTestCase("select * from R", new(testing.T)), 64 newTestCase("select * from R where uid > 1", new(testing.T)), 65 newTestCase("select * from R order by uid", new(testing.T)), 66 newTestCase("select * from R order by uid limit 1", new(testing.T)), 67 newTestCase("select * from R limit 1", new(testing.T)), 68 newTestCase("select * from R limit 2, 1", new(testing.T)), 69 newTestCase("select count(*) from R", new(testing.T)), 70 newTestCase("select * from R join S on R.uid = S.uid", new(testing.T)), 71 newTestCase("select * from R left join S on R.uid = S.uid", new(testing.T)), 72 newTestCase("select * from R right join S on R.uid = S.uid", new(testing.T)), 73 newTestCase("select * from R join S on R.uid > S.uid", new(testing.T)), 74 newTestCase("select * from R limit 10", new(testing.T)), 75 newTestCase("select count(*) from R group by uid", new(testing.T)), 76 newTestCase("select count(distinct uid) from R", new(testing.T)), 77 // xxx because memEngine can not handle Halloween Problem 78 // newTestCase("insert into R values('991', '992', '993')", new(testing.T)), 79 // newTestCase("insert into R select * from S", new(testing.T)), 80 // newTestCase("update R set uid=110 where orderid='abcd'", new(testing.T)), 81 newTestCase(fmt.Sprintf("load data infile {\"filepath\"=\"%s/../../../test/distributed/resources/load_data/parallel.txt.gz\", \"compression\"=\"gzip\"} into table pressTbl FIELDS TERMINATED BY '|' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n' parallel 'true';", GetFilePath()), new(testing.T)), 82 } 83 } 84 85 func testPrint(_ *batch.Batch) error { 86 return nil 87 } 88 89 type Ws struct { 90 } 91 92 func (w *Ws) IncrStatementID(ctx context.Context, commit bool) error { 93 return nil 94 } 95 96 func (w *Ws) RollbackLastStatement(ctx context.Context) error { 97 return nil 98 } 99 100 func (w *Ws) Commit(ctx context.Context) ([]txn.TxnRequest, error) { 101 return nil, nil 102 } 103 104 func (w *Ws) Rollback(ctx context.Context) error { 105 return nil 106 } 107 108 func (w *Ws) UpdateSnapshotWriteOffset() { 109 } 110 111 func (w *Ws) GetSnapshotWriteOffset() int { 112 return 0 113 } 114 115 func (w *Ws) Adjust(_ uint64) error { 116 return nil 117 } 118 119 func (w *Ws) StartStatement() {} 120 func (w *Ws) EndStatement() {} 121 func (w *Ws) IncrSQLCount() {} 122 func (w *Ws) GetSQLCount() uint64 { return 0 } 123 124 func (w *Ws) CloneSnapshotWS() client.Workspace { 125 return nil 126 } 127 128 func (w *Ws) BindTxnOp(op client.TxnOperator) { 129 } 130 131 func TestCompile(t *testing.T) { 132 cnclient.NewCNClient("test", new(cnclient.ClientConfig)) 133 ctrl := gomock.NewController(t) 134 ctx := defines.AttachAccountId(context.TODO(), catalog.System_Account) 135 txnOperator := mock_frontend.NewMockTxnOperator(ctrl) 136 txnOperator.EXPECT().Commit(gomock.Any()).Return(nil).AnyTimes() 137 txnOperator.EXPECT().Rollback(ctx).Return(nil).AnyTimes() 138 txnOperator.EXPECT().GetWorkspace().Return(&Ws{}).AnyTimes() 139 txnOperator.EXPECT().Txn().Return(txn.TxnMeta{}).AnyTimes() 140 txnOperator.EXPECT().ResetRetry(gomock.Any()).AnyTimes() 141 txnOperator.EXPECT().TxnOptions().Return(txn.TxnOptions{}).AnyTimes() 142 txnOperator.EXPECT().NextSequence().Return(uint64(0)).AnyTimes() 143 txnOperator.EXPECT().EnterRunSql().Return().AnyTimes() 144 txnOperator.EXPECT().ExitRunSql().Return().AnyTimes() 145 txnClient := mock_frontend.NewMockTxnClient(ctrl) 146 txnClient.EXPECT().New(gomock.Any(), gomock.Any()).Return(txnOperator, nil).AnyTimes() 147 for _, tc := range tcs { 148 tc.proc.TxnClient = txnClient 149 tc.proc.TxnOperator = txnOperator 150 tc.proc.Ctx = ctx 151 c := NewCompile("test", "test", tc.sql, "", "", ctx, tc.e, tc.proc, tc.stmt, false, nil, time.Now()) 152 err := c.Compile(ctx, tc.pn, testPrint) 153 require.NoError(t, err) 154 c.getAffectedRows() 155 _, err = c.Run(0) 156 require.NoError(t, err) 157 // Enable memory check 158 tc.proc.FreeVectors() 159 require.Equal(t, int64(0), tc.proc.Mp().CurrNB()) 160 tc.proc.SessionInfo.Buf.Free() 161 } 162 } 163 164 func TestCompileWithFaults(t *testing.T) { 165 // Enable this line to trigger the Hung. 166 // fault.Enable() 167 var ctx = defines.AttachAccountId(context.Background(), catalog.System_Account) 168 cnclient.NewCNClient("test", new(cnclient.ClientConfig)) 169 fault.AddFaultPoint(ctx, "panic_in_batch_append", ":::", "panic", 0, "") 170 tc := newTestCase("select * from R join S on R.uid = S.uid", t) 171 tc.proc.Ctx = ctx 172 c := NewCompile("test", "test", tc.sql, "", "", ctx, tc.e, tc.proc, nil, false, nil, time.Now()) 173 err := c.Compile(ctx, tc.pn, testPrint) 174 require.NoError(t, err) 175 c.getAffectedRows() 176 _, err = c.Run(0) 177 require.NoError(t, err) 178 } 179 180 func newTestCase(sql string, t *testing.T) compileTestCase { 181 proc := testutil.NewProcess() 182 proc.SessionInfo.Buf = buffer.New() 183 e, _, compilerCtx := testengine.New(defines.AttachAccountId(context.Background(), catalog.System_Account)) 184 stmts, err := mysql.Parse(compilerCtx.GetContext(), sql, 1, 0) 185 require.NoError(t, err) 186 pn, err := plan2.BuildPlan(compilerCtx, stmts[0], false) 187 if err != nil { 188 panic(err) 189 } 190 require.NoError(t, err) 191 return compileTestCase{ 192 e: e, 193 sql: sql, 194 proc: proc, 195 pn: pn, 196 stmt: stmts[0], 197 } 198 } 199 200 func TestCompileShouldReturnCtxError(t *testing.T) { 201 { 202 c := reuse.Alloc[Compile](nil) 203 c.proc = &process.Process{} 204 ctx, cancel := context.WithTimeout(context.TODO(), 100*time.Millisecond) 205 c.proc.Ctx = ctx 206 time.Sleep(time.Second) 207 require.True(t, c.shouldReturnCtxErr()) 208 cancel() 209 require.True(t, c.shouldReturnCtxErr()) 210 } 211 212 { 213 c := reuse.Alloc[Compile](nil) 214 c.proc = &process.Process{} 215 ctx, cancel := context.WithTimeout(context.TODO(), 500*time.Millisecond) 216 c.proc.Ctx = ctx 217 cancel() 218 require.False(t, c.shouldReturnCtxErr()) 219 time.Sleep(time.Second) 220 require.False(t, c.shouldReturnCtxErr()) 221 } 222 } 223 224 func GetFilePath() string { 225 dir, _ := os.Getwd() 226 return dir 227 }