github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/txn_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 frontend 16 17 import ( 18 "context" 19 "sync" 20 "testing" 21 "time" 22 23 "github.com/fagongzi/goetty/v2/buf" 24 "github.com/golang/mock/gomock" 25 "github.com/smartystreets/goconvey/convey" 26 27 "github.com/matrixorigin/matrixone/pkg/common/moerr" 28 "github.com/matrixorigin/matrixone/pkg/defines" 29 mock_frontend "github.com/matrixorigin/matrixone/pkg/frontend/test" 30 "github.com/matrixorigin/matrixone/pkg/pb/timestamp" 31 "github.com/matrixorigin/matrixone/pkg/pb/txn" 32 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 33 "github.com/matrixorigin/matrixone/pkg/txn/client" 34 "github.com/matrixorigin/matrixone/pkg/txn/clock" 35 "github.com/matrixorigin/matrixone/pkg/vm/engine" 36 ) 37 38 var _ client.Workspace = (*testWorkspace)(nil) 39 40 type testWorkspace struct { 41 start bool 42 incr bool 43 mu sync.Mutex 44 stack []uint64 45 stmtId uint64 46 reportErr1 bool 47 } 48 49 func (txn *testWorkspace) UpdateSnapshotWriteOffset() { 50 //TODO implement me 51 panic("implement me") 52 } 53 54 func (txn *testWorkspace) GetSnapshotWriteOffset() int { 55 //TODO implement me 56 panic("implement me") 57 } 58 59 func newTestWorkspace() *testWorkspace { 60 return &testWorkspace{} 61 } 62 63 func (txn *testWorkspace) StartStatement() { 64 if txn.start { 65 panic("BUG: StartStatement called twice") 66 } 67 txn.start = true 68 txn.incr = false 69 } 70 71 func (txn *testWorkspace) EndStatement() { 72 if !txn.start { 73 panic("BUG: StartStatement not called") 74 } 75 76 txn.start = false 77 txn.incr = false 78 } 79 80 func (txn *testWorkspace) IncrStatementID(ctx context.Context, commit bool) error { 81 if !commit { 82 if !txn.start { 83 panic("BUG: StartStatement not called") 84 } 85 if txn.incr { 86 panic("BUG: IncrStatementID called twice") 87 } 88 txn.incr = true 89 } 90 txn.mu.Lock() 91 defer txn.mu.Unlock() 92 txn.stack = append(txn.stack, txn.stmtId) 93 txn.stmtId++ 94 return nil 95 } 96 97 func (txn *testWorkspace) RollbackLastStatement(ctx context.Context) error { 98 txn.mu.Lock() 99 defer txn.mu.Unlock() 100 if txn.reportErr1 { 101 return moerr.NewInternalError(ctx, "rollback statement failed.") 102 } 103 if len(txn.stack) == 0 { 104 panic("BUG: unbalance happens") 105 } 106 txn.stmtId-- 107 lastStmtId := txn.stack[len(txn.stack)-1] 108 if txn.stmtId != lastStmtId { 109 panic("BUG: wrong stmt id") 110 } 111 txn.stack = txn.stack[:len(txn.stack)-1] 112 txn.incr = false 113 return nil 114 } 115 116 func (t *testWorkspace) WriteOffset() uint64 { 117 //TODO implement me 118 panic("implement me") 119 } 120 121 func (t *testWorkspace) Adjust(writeOffset uint64) error { 122 //TODO implement me 123 panic("implement me") 124 } 125 126 func (t *testWorkspace) Commit(ctx context.Context) ([]txn.TxnRequest, error) { 127 //TODO implement me 128 panic("implement me") 129 } 130 131 func (t *testWorkspace) Rollback(ctx context.Context) error { 132 //TODO implement me 133 panic("implement me") 134 } 135 136 func (t *testWorkspace) IncrSQLCount() { 137 //TODO implement me 138 panic("implement me") 139 } 140 141 func (t *testWorkspace) GetSQLCount() uint64 { 142 //TODO implement me 143 panic("implement me") 144 } 145 146 func (t *testWorkspace) CloneSnapshotWS() client.Workspace { 147 //TODO implement me 148 panic("implement me") 149 } 150 151 func (t *testWorkspace) BindTxnOp(op client.TxnOperator) { 152 //TODO implement me 153 panic("implement me") 154 } 155 156 func TestWorkspace(t *testing.T) { 157 convey.Convey("no panic", t, func() { 158 convey.So( 159 func() { 160 wsp := newTestWorkspace() 161 wsp.StartStatement() 162 wsp.EndStatement() 163 }, 164 convey.ShouldNotPanic, 165 ) 166 }) 167 convey.Convey("end panic", t, func() { 168 convey.So( 169 func() { 170 wsp := newTestWorkspace() 171 wsp.EndStatement() 172 }, 173 convey.ShouldPanic, 174 ) 175 }) 176 convey.Convey("start panic 1", t, func() { 177 convey.So( 178 func() { 179 wsp := newTestWorkspace() 180 wsp.StartStatement() 181 wsp.StartStatement() 182 }, 183 convey.ShouldPanic, 184 ) 185 }) 186 convey.Convey("incr panic 1", t, func() { 187 convey.So( 188 func() { 189 wsp := newTestWorkspace() 190 //no start 191 err := wsp.IncrStatementID(context.TODO(), false) 192 convey.So(err, convey.ShouldBeNil) 193 }, 194 convey.ShouldPanic, 195 ) 196 }) 197 convey.Convey("incr panic 2", t, func() { 198 convey.So( 199 func() { 200 wsp := newTestWorkspace() 201 wsp.StartStatement() 202 err := wsp.IncrStatementID(context.TODO(), false) 203 convey.So(err, convey.ShouldBeNil) 204 //incr twice 205 err = wsp.IncrStatementID(context.TODO(), false) 206 convey.So(err, convey.ShouldBeNil) 207 }, 208 convey.ShouldPanic, 209 ) 210 }) 211 convey.Convey("rollback last statement panic 1", t, func() { 212 convey.So( 213 func() { 214 wsp := newTestWorkspace() 215 wsp.StartStatement() 216 err := wsp.RollbackLastStatement(context.TODO()) 217 convey.So(err, convey.ShouldBeNil) 218 }, 219 convey.ShouldPanic, 220 ) 221 }) 222 convey.Convey("rollback last statement panic 2", t, func() { 223 convey.So( 224 func() { 225 wsp := newTestWorkspace() 226 wsp.StartStatement() 227 err := wsp.IncrStatementID(context.TODO(), false) 228 convey.So(err, convey.ShouldBeNil) 229 err = wsp.RollbackLastStatement(context.TODO()) 230 convey.So(err, convey.ShouldBeNil) 231 err = wsp.RollbackLastStatement(context.TODO()) 232 convey.So(err, convey.ShouldBeNil) 233 }, 234 convey.ShouldPanic, 235 ) 236 }) 237 } 238 239 func newMockErrSession(t *testing.T, ctx context.Context, ctrl *gomock.Controller) *Session { 240 txnClient := mock_frontend.NewMockTxnClient(ctrl) 241 txnClient.EXPECT().New(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( 242 func(ctx context.Context, commitTS timestamp.Timestamp, options ...TxnOption) (client.TxnOperator, error) { 243 txnOperator := mock_frontend.NewMockTxnOperator(ctrl) 244 txnOperator.EXPECT().Txn().Return(txn.TxnMeta{}).AnyTimes() 245 txnOperator.EXPECT().Rollback(gomock.Any()).Return(moerr.NewInternalError(ctx, "throw error")).AnyTimes() 246 txnOperator.EXPECT().Commit(gomock.Any()).Return(nil).AnyTimes() 247 wsp := newTestWorkspace() 248 txnOperator.EXPECT().GetWorkspace().Return(wsp).AnyTimes() 249 return txnOperator, nil 250 }).AnyTimes() 251 eng := mock_frontend.NewMockEngine(ctrl) 252 eng.EXPECT().New(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 253 eng.EXPECT().Hints().Return(engine.Hints{ 254 CommitOrRollbackTimeout: time.Second, 255 }).AnyTimes() 256 257 var gSys GlobalSystemVariables 258 InitGlobalSystemVariables(&gSys) 259 260 ses := newTestSession(t, ctrl) 261 getGlobalPu().TxnClient = txnClient 262 getGlobalPu().StorageEngine = eng 263 ses.txnHandler.storage = eng 264 var c clock.Clock 265 _ = ses.GetTxnHandler().CreateTempStorage(c) 266 return ses 267 } 268 269 func newMockErrSession2(t *testing.T, ctx context.Context, ctrl *gomock.Controller) *Session { 270 txnClient := mock_frontend.NewMockTxnClient(ctrl) 271 txnClient.EXPECT().New(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( 272 func(ctx context.Context, commitTS timestamp.Timestamp, options ...TxnOption) (client.TxnOperator, error) { 273 txnOperator := mock_frontend.NewMockTxnOperator(ctrl) 274 txnOperator.EXPECT().Txn().Return(txn.TxnMeta{}).AnyTimes() 275 txnOperator.EXPECT().Rollback(gomock.Any()).Return(nil).AnyTimes() 276 txnOperator.EXPECT().Commit(gomock.Any()).Return(nil).AnyTimes() 277 wsp := newTestWorkspace() 278 wsp.reportErr1 = true 279 txnOperator.EXPECT().GetWorkspace().Return(wsp).AnyTimes() 280 return txnOperator, nil 281 }).AnyTimes() 282 eng := mock_frontend.NewMockEngine(ctrl) 283 eng.EXPECT().New(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 284 eng.EXPECT().Hints().Return(engine.Hints{ 285 CommitOrRollbackTimeout: time.Second, 286 }).AnyTimes() 287 288 var gSys GlobalSystemVariables 289 InitGlobalSystemVariables(&gSys) 290 ses := newTestSession(t, ctrl) 291 getGlobalPu().TxnClient = txnClient 292 getGlobalPu().StorageEngine = eng 293 ses.txnHandler.storage = eng 294 295 var c clock.Clock 296 _ = ses.GetTxnHandler().CreateTempStorage(c) 297 return ses 298 } 299 300 func Test_rollbackStatement(t *testing.T) { 301 convey.Convey("normal rollback", t, func() { 302 ctrl := gomock.NewController(t) 303 defer ctrl.Finish() 304 305 ctx := defines.AttachAccountId(context.TODO(), sysAccountID) 306 txnClient := mock_frontend.NewMockTxnClient(ctrl) 307 txnClient.EXPECT().New(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( 308 func(ctx context.Context, commitTS timestamp.Timestamp, options ...TxnOption) (client.TxnOperator, error) { 309 txnOperator := mock_frontend.NewMockTxnOperator(ctrl) 310 txnOperator.EXPECT().Txn().Return(txn.TxnMeta{}).AnyTimes() 311 txnOperator.EXPECT().Rollback(gomock.Any()).Return(nil).AnyTimes() 312 txnOperator.EXPECT().Commit(gomock.Any()).Return(nil).AnyTimes() 313 wsp := newTestWorkspace() 314 txnOperator.EXPECT().GetWorkspace().Return(wsp).AnyTimes() 315 return txnOperator, nil 316 }).AnyTimes() 317 eng := mock_frontend.NewMockEngine(ctrl) 318 eng.EXPECT().New(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 319 eng.EXPECT().Hints().Return(engine.Hints{ 320 CommitOrRollbackTimeout: time.Second, 321 }).AnyTimes() 322 323 ioses := mock_frontend.NewMockIOSession(ctrl) 324 ioses.EXPECT().OutBuf().Return(buf.NewByteBuf(1024)).AnyTimes() 325 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 326 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 327 ioses.EXPECT().Ref().AnyTimes() 328 329 var gSys GlobalSystemVariables 330 InitGlobalSystemVariables(&gSys) 331 332 ses := newTestSession(t, ctrl) 333 getGlobalPu().TxnClient = txnClient 334 ses.txnHandler.storage = eng 335 336 ec := newTestExecCtx(ctx, ctrl) 337 ec.ses = ses 338 //case1. autocommit && not_begin. Insert Stmt (need not to be committed in the active txn) 339 ec.txnOpt = FeTxnOption{ 340 autoCommit: true, 341 } 342 343 err := ses.GetTxnHandler().Create(ec) 344 convey.So(err, convey.ShouldBeNil) 345 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), convey.ShouldBeFalse) 346 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_AUTOCOMMIT), convey.ShouldBeTrue) 347 convey.So(!ses.GetTxnHandler().InMultiStmtTransactionMode(), convey.ShouldBeTrue) 348 ec.stmt = &tree.Insert{} 349 err = ses.GetTxnHandler().Rollback(ec) 350 convey.So(err, convey.ShouldBeNil) 351 t2 := ses.txnHandler.GetTxn() 352 convey.So(t2, convey.ShouldBeNil) 353 354 //case2.1 autocommit && begin && CreateSequence (need to be committed in the active txn) 355 ec.txnOpt = FeTxnOption{ 356 autoCommit: true, 357 byBegin: true, 358 } 359 err = ses.GetTxnHandler().Create(ec) 360 convey.So(err, convey.ShouldBeNil) 361 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), convey.ShouldBeTrue) 362 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_NOT_AUTOCOMMIT), convey.ShouldBeFalse) 363 convey.So(!ses.GetTxnHandler().InMultiStmtTransactionMode(), convey.ShouldBeFalse) 364 convey.So(ses.GetTxnHandler().InActiveTxn() && 365 NeedToBeCommittedInActiveTransaction(&tree.CreateSequence{}), convey.ShouldBeTrue) 366 ec.stmt = &tree.CreateSequence{} 367 err = ses.GetTxnHandler().Rollback(ec) 368 convey.So(err, convey.ShouldBeNil) 369 t2 = ses.txnHandler.GetTxn() 370 convey.So(t2, convey.ShouldBeNil) 371 372 //case2.2 not_autocommit && not_begin && CreateSequence (need to be committed in the active txn) 373 ec.txnOpt = FeTxnOption{ 374 autoCommit: false, 375 } 376 err = ses.txnHandler.Create(ec) 377 convey.So(err, convey.ShouldBeNil) 378 err = ses.GetTxnHandler().SetAutocommit(ec, true, false) 379 convey.So(err, convey.ShouldBeNil) 380 _ = ses.txnHandler.GetTxn() 381 convey.So(err, convey.ShouldBeNil) 382 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), convey.ShouldBeFalse) 383 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_NOT_AUTOCOMMIT), convey.ShouldBeTrue) 384 convey.So(!ses.GetTxnHandler().InMultiStmtTransactionMode(), convey.ShouldBeFalse) 385 convey.So(ses.GetTxnHandler().InActiveTxn() && 386 NeedToBeCommittedInActiveTransaction(&tree.CreateSequence{}), convey.ShouldBeTrue) 387 ec.stmt = &tree.CreateSequence{} 388 err = ses.GetTxnHandler().Rollback(ec) 389 convey.So(err, convey.ShouldBeNil) 390 t2 = ses.txnHandler.GetTxn() 391 convey.So(t2, convey.ShouldBeNil) 392 393 //case3.1 not_autocommit && not_begin && Insert Stmt (need not to be committed in the active txn) 394 ec.txnOpt = FeTxnOption{ 395 autoCommit: false, 396 } 397 err = ses.txnHandler.Create(ec) 398 convey.So(err, convey.ShouldBeNil) 399 err = ses.GetTxnHandler().SetAutocommit(ec, true, false) 400 var txnOp TxnOperator 401 convey.So(err, convey.ShouldBeNil) 402 txnOp = ses.txnHandler.GetTxn() 403 convey.So(err, convey.ShouldBeNil) 404 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), convey.ShouldBeFalse) 405 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_NOT_AUTOCOMMIT), convey.ShouldBeTrue) 406 convey.So(!ses.GetTxnHandler().InMultiStmtTransactionMode(), convey.ShouldBeFalse) 407 convey.So(ses.GetTxnHandler().InActiveTxn() && 408 NeedToBeCommittedInActiveTransaction(&tree.Insert{}), convey.ShouldBeFalse) 409 convey.So(txnOp != nil && !ses.IsDerivedStmt(), convey.ShouldBeTrue) 410 //called incrStatement 411 txnOp.GetWorkspace().StartStatement() 412 err = txnOp.GetWorkspace().IncrStatementID(ctx, false) 413 convey.So(err, convey.ShouldBeNil) 414 ec.stmt = &tree.Insert{} 415 err = ses.GetTxnHandler().Rollback(ec) 416 convey.So(err, convey.ShouldBeNil) 417 t2 = ses.txnHandler.GetTxn() 418 convey.So(t2, convey.ShouldNotBeNil) 419 420 //case3.2 not_autocommit && begin && Insert Stmt (need not to be committed in the active txn) 421 ec.txnOpt = FeTxnOption{ 422 autoCommit: false, 423 byBegin: true, 424 } 425 err = ses.txnHandler.Create(ec) 426 convey.So(err, convey.ShouldBeNil) 427 err = ses.GetTxnHandler().SetAutocommit(ec, true, false) 428 convey.So(err, convey.ShouldBeNil) 429 err = ses.GetTxnHandler().Create(ec) 430 convey.So(err, convey.ShouldBeNil) 431 txnOp = ses.GetTxnHandler().GetTxn() 432 convey.So(err, convey.ShouldBeNil) 433 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), convey.ShouldBeTrue) 434 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_NOT_AUTOCOMMIT), convey.ShouldBeTrue) 435 convey.So(!ses.GetTxnHandler().InMultiStmtTransactionMode(), convey.ShouldBeFalse) 436 convey.So(ses.GetTxnHandler().InActiveTxn() && 437 NeedToBeCommittedInActiveTransaction(&tree.Insert{}), convey.ShouldBeFalse) 438 convey.So(txnOp != nil && !ses.IsDerivedStmt(), convey.ShouldBeTrue) 439 //called incrStatement 440 txnOp.GetWorkspace().StartStatement() 441 err = txnOp.GetWorkspace().IncrStatementID(ctx, false) 442 convey.So(err, convey.ShouldBeNil) 443 ec.stmt = &tree.Insert{} 444 err = ses.GetTxnHandler().Rollback(ec) 445 convey.So(err, convey.ShouldBeNil) 446 t2 = ses.txnHandler.GetTxn() 447 convey.So(t2, convey.ShouldNotBeNil) 448 449 }) 450 451 convey.Convey("abnormal rollback", t, func() { 452 ctrl := gomock.NewController(t) 453 defer ctrl.Finish() 454 455 ctx := defines.AttachAccountId(context.TODO(), sysAccountID) 456 ses := newMockErrSession(t, ctx, ctrl) 457 ec := newTestExecCtx(ctx, ctrl) 458 ec.ses = ses 459 //case1. autocommit && not_begin. Insert Stmt (need not to be committed in the active txn) 460 ec.txnOpt = FeTxnOption{ 461 autoCommit: true, 462 } 463 err := ses.GetTxnHandler().Create(ec) 464 convey.So(err, convey.ShouldBeNil) 465 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), convey.ShouldBeFalse) 466 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_AUTOCOMMIT), convey.ShouldBeTrue) 467 convey.So(!ses.GetTxnHandler().InMultiStmtTransactionMode(), convey.ShouldBeTrue) 468 ec.stmt = &tree.Insert{} 469 err = ses.GetTxnHandler().Rollback(ec) 470 convey.So(err, convey.ShouldNotBeNil) 471 t2 := ses.txnHandler.GetTxn() 472 convey.So(t2, convey.ShouldBeNil) 473 }) 474 } 475 476 func Test_rollbackStatement2(t *testing.T) { 477 convey.Convey("abnormal rollback", t, func() { 478 ctrl := gomock.NewController(t) 479 defer ctrl.Finish() 480 481 ctx := defines.AttachAccountId(context.TODO(), sysAccountID) 482 ses := newMockErrSession(t, ctx, ctrl) 483 ec := newTestExecCtx(ctx, ctrl) 484 ec.ses = ses 485 486 //case1. autocommit && not_begin. Insert Stmt (need not to be committed in the active txn) 487 ec.txnOpt = FeTxnOption{ 488 autoCommit: true, 489 } 490 err := ses.GetTxnHandler().Create(ec) 491 convey.So(err, convey.ShouldBeNil) 492 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), convey.ShouldBeFalse) 493 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_AUTOCOMMIT), convey.ShouldBeTrue) 494 convey.So(!ses.GetTxnHandler().InMultiStmtTransactionMode(), convey.ShouldBeTrue) 495 ec.stmt = &tree.Insert{} 496 err = ses.GetTxnHandler().Rollback(ec) 497 convey.So(err, convey.ShouldNotBeNil) 498 t2 := ses.txnHandler.GetTxn() 499 convey.So(t2, convey.ShouldBeNil) 500 }) 501 } 502 503 func Test_rollbackStatement3(t *testing.T) { 504 convey.Convey("abnormal rollback", t, func() { 505 ctrl := gomock.NewController(t) 506 defer ctrl.Finish() 507 508 ctx := defines.AttachAccountId(context.TODO(), sysAccountID) 509 ses := newMockErrSession(t, ctx, ctrl) 510 ec := newTestExecCtx(ctx, ctrl) 511 ec.ses = ses 512 513 //case2.1 autocommit && begin && CreateSequence (need to be committed in the active txn) 514 ec.txnOpt = FeTxnOption{ 515 autoCommit: true, 516 byBegin: true, 517 } 518 err := ses.GetTxnHandler().Create(ec) 519 convey.So(err, convey.ShouldBeNil) 520 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), convey.ShouldBeTrue) 521 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_NOT_AUTOCOMMIT), convey.ShouldBeFalse) 522 convey.So(!ses.GetTxnHandler().InMultiStmtTransactionMode(), convey.ShouldBeFalse) 523 convey.So(ses.GetTxnHandler().InActiveTxn() && 524 NeedToBeCommittedInActiveTransaction(&tree.CreateSequence{}), convey.ShouldBeTrue) 525 ec.stmt = &tree.CreateSequence{} 526 err = ses.GetTxnHandler().Rollback(ec) 527 convey.So(err, convey.ShouldNotBeNil) 528 t2 := ses.txnHandler.GetTxn() 529 convey.So(t2, convey.ShouldBeNil) 530 }) 531 } 532 533 func Test_rollbackStatement4(t *testing.T) { 534 convey.Convey("abnormal rollback", t, func() { 535 ctrl := gomock.NewController(t) 536 defer ctrl.Finish() 537 538 ctx := defines.AttachAccountId(context.TODO(), sysAccountID) 539 ses := newMockErrSession(t, ctx, ctrl) 540 ec := newTestExecCtx(ctx, ctrl) 541 ec.ses = ses 542 //case2.2 not_autocommit && not_begin && CreateSequence (need to be committed in the active txn) 543 err := ses.GetTxnHandler().Create(ec) 544 convey.So(err, convey.ShouldBeNil) 545 err = ses.GetTxnHandler().SetAutocommit(ec, true, false) 546 convey.So(err, convey.ShouldBeNil) 547 _ = ses.txnHandler.GetTxn() 548 convey.So(err, convey.ShouldBeNil) 549 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), convey.ShouldBeFalse) 550 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_NOT_AUTOCOMMIT), convey.ShouldBeTrue) 551 convey.So(!ses.GetTxnHandler().InMultiStmtTransactionMode(), convey.ShouldBeFalse) 552 convey.So(ses.GetTxnHandler().InActiveTxn() && 553 NeedToBeCommittedInActiveTransaction(&tree.CreateSequence{}), convey.ShouldBeTrue) 554 ec.stmt = &tree.CreateSequence{} 555 err = ses.GetTxnHandler().Rollback(ec) 556 convey.So(err, convey.ShouldNotBeNil) 557 t2 := ses.txnHandler.GetTxn() 558 convey.So(t2, convey.ShouldBeNil) 559 }) 560 } 561 562 func Test_rollbackStatement5(t *testing.T) { 563 convey.Convey("abnormal rollback", t, func() { 564 ctrl := gomock.NewController(t) 565 defer ctrl.Finish() 566 567 ctx := defines.AttachAccountId(context.TODO(), sysAccountID) 568 ses := newMockErrSession2(t, ctx, ctrl) 569 var txnOp TxnOperator 570 ec := newTestExecCtx(ctx, ctrl) 571 ec.ses = ses 572 //case3.1 not_autocommit && not_begin && Insert Stmt (need not to be committed in the active txn) 573 err := ses.GetTxnHandler().Create(ec) 574 convey.So(err, convey.ShouldBeNil) 575 err = ses.GetTxnHandler().SetAutocommit(ec, true, false) 576 convey.So(err, convey.ShouldBeNil) 577 txnOp = ses.txnHandler.GetTxn() 578 convey.So(err, convey.ShouldBeNil) 579 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), convey.ShouldBeFalse) 580 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_NOT_AUTOCOMMIT), convey.ShouldBeTrue) 581 convey.So(!ses.GetTxnHandler().InMultiStmtTransactionMode(), convey.ShouldBeFalse) 582 convey.So(ses.GetTxnHandler().InActiveTxn() && 583 NeedToBeCommittedInActiveTransaction(&tree.Insert{}), convey.ShouldBeFalse) 584 convey.So(txnOp != nil && !ses.IsDerivedStmt(), convey.ShouldBeTrue) 585 //called incrStatement 586 txnOp.GetWorkspace().StartStatement() 587 err = txnOp.GetWorkspace().IncrStatementID(ctx, false) 588 convey.So(err, convey.ShouldBeNil) 589 ec.stmt = &tree.Insert{} 590 err = ses.GetTxnHandler().Rollback(ec) 591 convey.So(err, convey.ShouldNotBeNil) 592 t2 := ses.txnHandler.GetTxn() 593 convey.So(t2, convey.ShouldBeNil) 594 }) 595 } 596 597 func Test_rollbackStatement6(t *testing.T) { 598 convey.Convey("abnormal rollback", t, func() { 599 ctrl := gomock.NewController(t) 600 defer ctrl.Finish() 601 602 ctx := defines.AttachAccountId(context.TODO(), sysAccountID) 603 ses := newMockErrSession2(t, ctx, ctrl) 604 var txnOp TxnOperator 605 ec := newTestExecCtx(ctx, ctrl) 606 ec.ses = ses 607 608 //case3.2 not_autocommit && begin && Insert Stmt (need not to be committed in the active txn) 609 err := ses.GetTxnHandler().SetAutocommit(ec, true, false) 610 convey.So(err, convey.ShouldBeNil) 611 ec.txnOpt = FeTxnOption{ 612 byBegin: true, 613 } 614 err = ses.GetTxnHandler().Create(ec) 615 convey.So(err, convey.ShouldBeNil) 616 txnOp = ses.GetTxnHandler().GetTxn() 617 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), convey.ShouldBeTrue) 618 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_NOT_AUTOCOMMIT), convey.ShouldBeTrue) 619 convey.So(!ses.GetTxnHandler().InMultiStmtTransactionMode(), convey.ShouldBeFalse) 620 convey.So(ses.GetTxnHandler().InActiveTxn() && 621 NeedToBeCommittedInActiveTransaction(&tree.Insert{}), convey.ShouldBeFalse) 622 convey.So(txnOp != nil && !ses.IsDerivedStmt(), convey.ShouldBeTrue) 623 //called incrStatement 624 txnOp.GetWorkspace().StartStatement() 625 err = txnOp.GetWorkspace().IncrStatementID(ctx, false) 626 convey.So(err, convey.ShouldBeNil) 627 ec.stmt = &tree.Insert{} 628 err = ses.GetTxnHandler().Rollback(ec) 629 convey.So(err, convey.ShouldNotBeNil) 630 t2 := ses.txnHandler.GetTxn() 631 convey.So(t2, convey.ShouldBeNil) 632 }) 633 convey.Convey("abnormal rollback -- rollback whole txn", t, func() { 634 ctrl := gomock.NewController(t) 635 defer ctrl.Finish() 636 637 ctx := defines.AttachAccountId(context.TODO(), sysAccountID) 638 ses := newMockErrSession(t, ctx, ctrl) 639 var txnOp TxnOperator 640 ec := newTestExecCtx(ctx, ctrl) 641 ec.ses = ses 642 //case3.2 not_autocommit && begin && Insert Stmt (need not to be committed in the active txn) 643 err := ses.GetTxnHandler().SetAutocommit(ec, true, false) 644 convey.So(err, convey.ShouldBeNil) 645 ec.txnOpt = FeTxnOption{ 646 byBegin: true, 647 } 648 err = ses.GetTxnHandler().Create(ec) 649 convey.So(err, convey.ShouldBeNil) 650 txnOp = ses.GetTxnHandler().GetTxn() 651 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), convey.ShouldBeTrue) 652 convey.So(ses.GetTxnHandler().OptionBitsIsSet(OPTION_NOT_AUTOCOMMIT), convey.ShouldBeTrue) 653 convey.So(!ses.GetTxnHandler().InMultiStmtTransactionMode(), convey.ShouldBeFalse) 654 convey.So(ses.GetTxnHandler().InActiveTxn() && 655 NeedToBeCommittedInActiveTransaction(&tree.Insert{}), convey.ShouldBeFalse) 656 convey.So(txnOp != nil && !ses.IsDerivedStmt(), convey.ShouldBeTrue) 657 //called incrStatement 658 txnOp.GetWorkspace().StartStatement() 659 err = txnOp.GetWorkspace().IncrStatementID(ctx, false) 660 convey.So(err, convey.ShouldBeNil) 661 ec.stmt = &tree.Insert{} 662 ec.txnOpt.byRollback = isErrorRollbackWholeTxn(getRandomErrorRollbackWholeTxn()) 663 err = ses.GetTxnHandler().Rollback(ec) 664 convey.So(err, convey.ShouldNotBeNil) 665 t2 := ses.txnHandler.GetTxn() 666 convey.So(t2, convey.ShouldBeNil) 667 }) 668 }