github.com/matrixorigin/matrixone@v1.2.0/pkg/txn/storage/memorystorage/storage_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 memorystorage 16 17 import ( 18 "context" 19 "encoding" 20 "testing" 21 "time" 22 23 "github.com/matrixorigin/matrixone/pkg/pb/plan" 24 25 "github.com/matrixorigin/matrixone/pkg/common/moerr" 26 "github.com/matrixorigin/matrixone/pkg/common/mpool" 27 "github.com/matrixorigin/matrixone/pkg/container/batch" 28 "github.com/matrixorigin/matrixone/pkg/container/types" 29 "github.com/matrixorigin/matrixone/pkg/container/vector" 30 "github.com/matrixorigin/matrixone/pkg/pb/timestamp" 31 "github.com/matrixorigin/matrixone/pkg/pb/txn" 32 "github.com/matrixorigin/matrixone/pkg/testutil" 33 "github.com/matrixorigin/matrixone/pkg/vm/engine" 34 "github.com/matrixorigin/matrixone/pkg/vm/engine/memoryengine" 35 "github.com/stretchr/testify/assert" 36 ) 37 38 func testDatabase( 39 t *testing.T, 40 newStorage func() (*Storage, error), 41 ) { 42 mp := mpool.MustNewZero() 43 ctx, cancel := context.WithTimeout(context.Background(), time.Hour) 44 defer cancel() 45 46 // new 47 s, err := newStorage() 48 assert.Nil(t, err) 49 defer s.Close(ctx) 50 51 // txn 52 txnMeta := txn.TxnMeta{ 53 ID: []byte("1"), 54 Status: txn.TxnStatus_Active, 55 SnapshotTS: timestamp.Timestamp{ 56 PhysicalTime: 1, 57 LogicalTime: 1, 58 }, 59 } 60 defer func() { 61 _, err := s.Commit(ctx, txnMeta) 62 assert.Nil(t, err) 63 }() 64 65 // open database 66 { 67 resp := &memoryengine.OpenDatabaseResp{} 68 err := testRead( 69 ctx, t, s, txnMeta, 70 memoryengine.OpOpenDatabase, 71 &memoryengine.OpenDatabaseReq{ 72 Name: "foo", 73 }, 74 resp, 75 ) 76 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrNoDB)) 77 } 78 79 // create database 80 { 81 resp := &memoryengine.CreateDatabaseResp{} 82 err := testWrite( 83 ctx, t, s, txnMeta, 84 memoryengine.OpCreateDatabase, 85 &memoryengine.CreateDatabaseReq{ 86 Name: "foo", 87 }, 88 resp, 89 ) 90 assert.Nil(t, err) 91 assert.NotEmpty(t, resp.ID) 92 } 93 94 // get databases 95 { 96 resp := &memoryengine.GetDatabasesResp{} 97 err := testRead( 98 ctx, t, s, txnMeta, 99 memoryengine.OpGetDatabases, 100 &memoryengine.GetDatabasesReq{}, 101 resp, 102 ) 103 assert.Nil(t, err) 104 assert.Equal(t, 1, len(resp.Names)) 105 assert.Equal(t, "foo", resp.Names[0]) 106 } 107 108 // open database 109 var dbID ID 110 { 111 resp := &memoryengine.OpenDatabaseResp{} 112 err := testRead( 113 ctx, t, s, txnMeta, 114 memoryengine.OpOpenDatabase, 115 &memoryengine.OpenDatabaseReq{ 116 Name: "foo", 117 }, 118 resp, 119 ) 120 assert.Nil(t, err) 121 assert.NotNil(t, resp.ID) 122 dbID = resp.ID 123 124 // delete database 125 defer func() { 126 { 127 resp := &memoryengine.DeleteDatabaseResp{} 128 err := testWrite( 129 ctx, t, s, txnMeta, 130 memoryengine.OpDeleteDatabase, 131 &memoryengine.DeleteDatabaseReq{ 132 Name: "foo", 133 }, 134 resp, 135 ) 136 assert.Nil(t, err) 137 assert.NotEmpty(t, resp.ID) 138 } 139 { 140 resp := &memoryengine.GetDatabasesResp{} 141 err := testRead( 142 ctx, t, s, txnMeta, 143 memoryengine.OpGetDatabases, 144 &memoryengine.GetDatabasesReq{}, 145 resp, 146 ) 147 assert.Nil(t, err) 148 for _, name := range resp.Names { 149 if name == "foo" { 150 t.Fatal() 151 } 152 } 153 } 154 }() 155 } 156 157 // open relation 158 { 159 resp := &memoryengine.OpenRelationResp{} 160 err := testRead( 161 ctx, t, s, txnMeta, 162 memoryengine.OpOpenRelation, 163 &memoryengine.OpenRelationReq{ 164 DatabaseID: dbID, 165 Name: "table", 166 }, 167 resp, 168 ) 169 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrNoSuchTable)) 170 } 171 172 // create relation 173 { 174 defA := &engine.AttributeDef{ 175 Attr: engine.Attribute{ 176 Name: "a", 177 Type: types.T_int64.ToType(), 178 Primary: true, 179 }, 180 } 181 defB := &engine.AttributeDef{ 182 Attr: engine.Attribute{ 183 Name: "b", 184 Type: types.T_int64.ToType(), 185 Primary: false, 186 }, 187 } 188 defC := &engine.ConstraintDef{ 189 Cts: []engine.Constraint{ 190 &engine.PrimaryKeyDef{ 191 Pkey: &plan.PrimaryKeyDef{ 192 PkeyColName: "a", 193 Names: []string{"a"}, 194 }, 195 }, 196 }, 197 } 198 199 resp := &memoryengine.CreateRelationResp{} 200 err := testWrite( 201 ctx, t, s, txnMeta, 202 memoryengine.OpCreateRelation, 203 &memoryengine.CreateRelationReq{ 204 DatabaseID: dbID, 205 Name: "table", 206 Type: memoryengine.RelationTable, 207 Defs: []engine.TableDefPB{ 208 defA.ToPBVersion(), 209 defB.ToPBVersion(), 210 defC.ToPBVersion(), 211 }, 212 }, 213 resp, 214 ) 215 assert.Nil(t, err) 216 assert.NotEmpty(t, resp.ID) 217 } 218 219 // get relations 220 { 221 resp := &memoryengine.GetRelationsResp{} 222 err := testRead( 223 ctx, t, s, txnMeta, 224 memoryengine.OpGetRelations, 225 &memoryengine.GetRelationsReq{ 226 DatabaseID: dbID, 227 }, 228 resp, 229 ) 230 assert.Nil(t, err) 231 assert.Equal(t, 1, len(resp.Names)) 232 assert.Equal(t, "table", resp.Names[0]) 233 } 234 235 // open relation 236 var relID ID 237 { 238 resp := &memoryengine.OpenRelationResp{} 239 err := testRead( 240 ctx, t, s, txnMeta, 241 memoryengine.OpOpenRelation, 242 &memoryengine.OpenRelationReq{ 243 DatabaseID: dbID, 244 Name: "table", 245 }, 246 resp, 247 ) 248 assert.Nil(t, err) 249 assert.NotNil(t, resp.ID) 250 relID = resp.ID 251 assert.Equal(t, memoryengine.RelationTable, resp.Type) 252 } 253 _ = relID 254 255 // get relation defs 256 { 257 resp := &memoryengine.GetTableDefsResp{} 258 err := testRead( 259 ctx, t, s, txnMeta, 260 memoryengine.OpGetTableDefs, 261 &memoryengine.GetTableDefsReq{ 262 TableID: relID, 263 }, 264 resp, 265 ) 266 assert.Nil(t, err) 267 assert.Equal(t, 3, len(resp.Defs)) 268 } 269 270 // write 271 { 272 colA := testutil.NewVector( 273 5, 274 types.T_int64.ToType(), 275 mp, 276 false, 277 []int64{ 278 1, 2, 3, 4, 5, 279 }, 280 ) 281 colB := testutil.NewVector( 282 5, 283 types.T_int64.ToType(), 284 mp, 285 false, 286 []int64{ 287 6, 7, 8, 9, 10, 288 }, 289 ) 290 bat := batch.New(false, []string{"a", "b"}) 291 bat.Vecs[0] = colA 292 bat.Vecs[1] = colB 293 bat.SetRowCount(5) 294 resp := &memoryengine.WriteResp{} 295 err := testWrite( 296 ctx, t, s, txnMeta, 297 memoryengine.OpWrite, 298 &memoryengine.WriteReq{ 299 TableID: relID, 300 Batch: bat, 301 }, 302 resp, 303 ) 304 assert.Nil(t, err) 305 } 306 307 // read 308 var iterID ID 309 { 310 resp := &memoryengine.NewTableIterResp{} 311 err := testRead( 312 ctx, t, s, txnMeta, 313 memoryengine.OpNewTableIter, 314 &memoryengine.NewTableIterReq{ 315 TableID: relID, 316 }, 317 resp, 318 ) 319 assert.Nil(t, err) 320 assert.NotEmpty(t, resp.IterID) 321 iterID = resp.IterID 322 } 323 { 324 resp := &memoryengine.ReadResp{} 325 err := testRead( 326 ctx, t, s, txnMeta, 327 memoryengine.OpRead, 328 &memoryengine.ReadReq{ 329 IterID: iterID, 330 ColNames: []string{"a", "b"}, 331 }, 332 resp, 333 ) 334 assert.Nil(t, err) 335 assert.NotNil(t, resp.Batch) 336 assert.Equal(t, 5, resp.Batch.RowCount()) 337 } 338 339 // delete by primary key 340 { 341 colA := testutil.NewVector( 342 1, 343 types.T_int64.ToType(), 344 mp, 345 false, 346 []int64{ 347 1, 348 }, 349 ) 350 resp := &memoryengine.DeleteResp{} 351 err := testWrite( 352 ctx, t, s, txnMeta, 353 memoryengine.OpDelete, 354 &memoryengine.DeleteReq{ 355 TableID: relID, 356 ColumnName: "a", 357 Vector: colA, 358 }, 359 resp, 360 ) 361 assert.Nil(t, err) 362 } 363 364 // read after delete 365 { 366 resp := &memoryengine.NewTableIterResp{} 367 err := testRead( 368 ctx, t, s, txnMeta, 369 memoryengine.OpNewTableIter, 370 &memoryengine.NewTableIterReq{ 371 TableID: relID, 372 }, 373 resp, 374 ) 375 assert.Nil(t, err) 376 assert.NotEmpty(t, resp.IterID) 377 iterID = resp.IterID 378 } 379 { 380 resp := &memoryengine.ReadResp{} 381 err := testRead( 382 ctx, t, s, txnMeta, 383 memoryengine.OpRead, 384 &memoryengine.ReadReq{ 385 IterID: iterID, 386 ColNames: []string{"a", "b"}, 387 }, 388 resp, 389 ) 390 assert.Nil(t, err) 391 assert.NotNil(t, resp.Batch) 392 assert.Equal(t, 4, resp.Batch.RowCount()) 393 } 394 395 // delete by non-primary key 396 { 397 colB := testutil.NewVector( 398 1, 399 types.T_int64.ToType(), 400 mp, 401 false, 402 []int64{ 403 8, 404 }, 405 ) 406 resp := &memoryengine.DeleteResp{} 407 err := testWrite( 408 ctx, t, s, txnMeta, 409 memoryengine.OpDelete, 410 &memoryengine.DeleteReq{ 411 TableID: relID, 412 ColumnName: "b", 413 Vector: colB, 414 }, 415 resp, 416 ) 417 assert.Nil(t, err) 418 } 419 420 // read after delete 421 { 422 resp := &memoryengine.NewTableIterResp{} 423 err := testRead( 424 ctx, t, s, txnMeta, 425 memoryengine.OpNewTableIter, 426 &memoryengine.NewTableIterReq{ 427 TableID: relID, 428 }, 429 resp, 430 ) 431 assert.Nil(t, err) 432 assert.NotEmpty(t, resp.IterID) 433 iterID = resp.IterID 434 } 435 { 436 resp := &memoryengine.ReadResp{} 437 err := testRead( 438 ctx, t, s, txnMeta, 439 memoryengine.OpRead, 440 &memoryengine.ReadReq{ 441 IterID: iterID, 442 ColNames: []string{"a", "b"}, 443 }, 444 resp, 445 ) 446 assert.Nil(t, err) 447 assert.NotNil(t, resp.Batch) 448 assert.Equal(t, 3, resp.Batch.RowCount()) 449 } 450 451 // write after delete 452 { 453 colA := testutil.NewVector( 454 1, 455 types.T_int64.ToType(), 456 mp, 457 false, 458 []int64{ 459 1, 460 }, 461 ) 462 colB := testutil.NewVector( 463 1, 464 types.T_int64.ToType(), 465 mp, 466 false, 467 []int64{ 468 6, 469 }, 470 ) 471 bat := batch.New(false, []string{"a", "b"}) 472 bat.Vecs[0] = colA 473 bat.Vecs[1] = colB 474 bat.SetRowCount(1) 475 resp := &memoryengine.WriteResp{} 476 err := testWrite( 477 ctx, t, s, txnMeta, 478 memoryengine.OpWrite, 479 &memoryengine.WriteReq{ 480 TableID: relID, 481 Batch: bat, 482 }, 483 resp, 484 ) 485 assert.Nil(t, err) 486 } 487 488 // delete relation 489 { 490 resp := &memoryengine.DeleteRelationResp{} 491 err := testWrite( 492 ctx, t, s, txnMeta, 493 memoryengine.OpDeleteRelation, 494 &memoryengine.DeleteRelationReq{ 495 DatabaseID: dbID, 496 Name: "table", 497 }, 498 resp, 499 ) 500 assert.Nil(t, err) 501 assert.NotEmpty(t, resp.ID) 502 } 503 { 504 resp := &memoryengine.GetRelationsResp{} 505 err := testRead( 506 ctx, t, s, txnMeta, 507 memoryengine.OpGetRelations, 508 &memoryengine.GetRelationsReq{ 509 DatabaseID: dbID, 510 }, 511 resp, 512 ) 513 assert.Nil(t, err) 514 assert.Equal(t, 0, len(resp.Names)) 515 } 516 517 // new relation without primary key 518 { 519 defA := &engine.AttributeDef{ 520 Attr: engine.Attribute{ 521 Name: "a", 522 Type: types.T_int64.ToType(), 523 }, 524 } 525 defB := &engine.AttributeDef{ 526 Attr: engine.Attribute{ 527 Name: "b", 528 Type: types.T_int64.ToType(), 529 }, 530 } 531 532 resp := &memoryengine.CreateRelationResp{} 533 err := testWrite( 534 ctx, t, s, txnMeta, 535 memoryengine.OpCreateRelation, 536 &memoryengine.CreateRelationReq{ 537 DatabaseID: dbID, 538 Name: "table", 539 Type: memoryengine.RelationTable, 540 Defs: []engine.TableDefPB{ 541 defA.ToPBVersion(), 542 defB.ToPBVersion(), 543 }, 544 }, 545 resp, 546 ) 547 assert.Nil(t, err) 548 assert.NotEmpty(t, resp.ID) 549 relID = resp.ID 550 } 551 552 // write 553 { 554 colA := testutil.NewVector( 555 5, 556 types.T_int64.ToType(), 557 mp, 558 false, 559 []int64{ 560 1, 2, 3, 4, 5, 561 }, 562 ) 563 colB := testutil.NewVector( 564 5, 565 types.T_int64.ToType(), 566 mp, 567 false, 568 []int64{ 569 6, 7, 8, 9, 10, 570 }, 571 ) 572 bat := batch.New(false, []string{"a", "b"}) 573 bat.Vecs[0] = colA 574 bat.Vecs[1] = colB 575 bat.SetRowCount(5) 576 resp := &memoryengine.WriteResp{} 577 err := testWrite( 578 ctx, t, s, txnMeta, 579 memoryengine.OpWrite, 580 &memoryengine.WriteReq{ 581 TableID: relID, 582 Batch: bat, 583 }, 584 resp, 585 ) 586 assert.Nil(t, err) 587 } 588 589 // delete by primary key 590 { 591 colA := testutil.NewVector( 592 1, 593 types.T_int64.ToType(), 594 mp, 595 false, 596 []int64{ 597 1, 598 }, 599 ) 600 resp := &memoryengine.DeleteResp{} 601 err := testWrite( 602 ctx, t, s, txnMeta, 603 memoryengine.OpDelete, 604 &memoryengine.DeleteReq{ 605 TableID: relID, 606 ColumnName: "a", 607 Vector: colA, 608 }, 609 resp, 610 ) 611 assert.Nil(t, err) 612 } 613 614 // read after delete 615 { 616 resp := &memoryengine.NewTableIterResp{} 617 err := testRead( 618 ctx, t, s, txnMeta, 619 memoryengine.OpNewTableIter, 620 &memoryengine.NewTableIterReq{ 621 TableID: relID, 622 }, 623 resp, 624 ) 625 assert.Nil(t, err) 626 assert.NotEmpty(t, resp.IterID) 627 iterID = resp.IterID 628 } 629 { 630 resp := &memoryengine.ReadResp{} 631 err := testRead( 632 ctx, t, s, txnMeta, 633 memoryengine.OpRead, 634 &memoryengine.ReadReq{ 635 IterID: iterID, 636 ColNames: []string{"a", "b"}, 637 }, 638 resp, 639 ) 640 assert.Nil(t, err) 641 assert.NotNil(t, resp.Batch) 642 assert.Equal(t, 4, resp.Batch.RowCount()) 643 } 644 645 // delete by non-primary key 646 { 647 colB := testutil.NewVector( 648 1, 649 types.T_int64.ToType(), 650 mp, 651 false, 652 []int64{ 653 8, 654 }, 655 ) 656 resp := &memoryengine.DeleteResp{} 657 err := testWrite( 658 ctx, t, s, txnMeta, 659 memoryengine.OpDelete, 660 &memoryengine.DeleteReq{ 661 TableID: relID, 662 ColumnName: "b", 663 Vector: colB, 664 }, 665 resp, 666 ) 667 assert.Nil(t, err) 668 } 669 670 // read after delete 671 { 672 resp := &memoryengine.NewTableIterResp{} 673 err := testRead( 674 ctx, t, s, txnMeta, 675 memoryengine.OpNewTableIter, 676 &memoryengine.NewTableIterReq{ 677 TableID: relID, 678 }, 679 resp, 680 ) 681 assert.Nil(t, err) 682 assert.NotEmpty(t, resp.IterID) 683 iterID = resp.IterID 684 } 685 var rowIDs *vector.Vector 686 { 687 resp := &memoryengine.ReadResp{} 688 err := testRead( 689 ctx, t, s, txnMeta, 690 memoryengine.OpRead, 691 &memoryengine.ReadReq{ 692 IterID: iterID, 693 ColNames: []string{"a", "b", rowIDColumnName}, 694 }, 695 resp, 696 ) 697 assert.Nil(t, err) 698 assert.NotNil(t, resp.Batch) 699 assert.Equal(t, 3, resp.Batch.RowCount()) 700 rowIDs = resp.Batch.Vecs[2] 701 } 702 703 // delete by row id 704 { 705 resp := &memoryengine.DeleteResp{} 706 err := testWrite( 707 ctx, t, s, txnMeta, 708 memoryengine.OpDelete, 709 &memoryengine.DeleteReq{ 710 TableID: relID, 711 ColumnName: rowIDColumnName, 712 Vector: rowIDs, 713 }, 714 resp, 715 ) 716 assert.Nil(t, err) 717 } 718 719 // read after delete 720 { 721 resp := &memoryengine.NewTableIterResp{} 722 err := testRead( 723 ctx, t, s, txnMeta, 724 memoryengine.OpNewTableIter, 725 &memoryengine.NewTableIterReq{ 726 TableID: relID, 727 }, 728 resp, 729 ) 730 assert.Nil(t, err) 731 assert.NotEmpty(t, resp.IterID) 732 iterID = resp.IterID 733 } 734 { 735 resp := &memoryengine.ReadResp{} 736 err := testRead( 737 ctx, t, s, txnMeta, 738 memoryengine.OpRead, 739 &memoryengine.ReadReq{ 740 IterID: iterID, 741 ColNames: []string{"a", "b", rowIDColumnName}, 742 }, 743 resp, 744 ) 745 assert.Nil(t, err) 746 assert.Nil(t, resp.Batch) 747 } 748 749 t.Run("duplicated db", func(t *testing.T) { 750 tx1 := txn.TxnMeta{ 751 ID: []byte("1"), 752 Status: txn.TxnStatus_Active, 753 SnapshotTS: timestamp.Timestamp{ 754 PhysicalTime: 1, 755 LogicalTime: 1, 756 }, 757 } 758 tx2 := txn.TxnMeta{ 759 ID: []byte("1"), 760 Status: txn.TxnStatus_Active, 761 SnapshotTS: timestamp.Timestamp{ 762 PhysicalTime: 1, 763 LogicalTime: 1, 764 }, 765 } 766 { 767 resp := &memoryengine.CreateDatabaseResp{} 768 err := testWrite( 769 ctx, t, s, tx1, 770 memoryengine.OpCreateDatabase, 771 &memoryengine.CreateDatabaseReq{ 772 Name: "bar", 773 }, 774 resp, 775 ) 776 assert.Nil(t, err) 777 assert.NotEmpty(t, resp.ID) 778 } 779 { 780 resp := &memoryengine.CreateDatabaseResp{} 781 err := testWrite( 782 ctx, t, s, tx2, 783 memoryengine.OpCreateDatabase, 784 &memoryengine.CreateDatabaseReq{ 785 Name: "bar", 786 }, 787 resp, 788 ) 789 assert.NotNil(t, err) 790 } 791 }) 792 793 } 794 795 func testRead[ 796 Resp encoding.BinaryUnmarshaler, 797 Req encoding.BinaryMarshaler, 798 ]( 799 ctx context.Context, 800 t *testing.T, 801 s *Storage, 802 txnMeta txn.TxnMeta, 803 op uint32, 804 req Req, 805 resp Resp, 806 ) error { 807 808 buf, err := req.MarshalBinary() 809 if err != nil { 810 return err 811 } 812 813 res, err := s.Read(ctx, txnMeta, op, buf) 814 if err != nil { 815 return err 816 } 817 818 data, err := res.Read() 819 if err != nil { 820 return err 821 } 822 823 return resp.UnmarshalBinary(data) 824 } 825 826 func testWrite[ 827 Resp encoding.BinaryUnmarshaler, 828 Req encoding.BinaryMarshaler, 829 ]( 830 ctx context.Context, 831 t *testing.T, 832 s *Storage, 833 txnMeta txn.TxnMeta, 834 op uint32, 835 req Req, 836 resp Resp, 837 ) error { 838 839 buf, err := req.MarshalBinary() 840 if err != nil { 841 return err 842 } 843 844 data, err := s.Write(ctx, txnMeta, op, buf) 845 if err != nil { 846 return err 847 } 848 849 return resp.UnmarshalBinary(data) 850 }