github.com/matrixorigin/matrixone@v0.7.0/pkg/txn/storage/memorystorage/memtable/table_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 memtable 16 17 import ( 18 "context" 19 "testing" 20 21 "github.com/matrixorigin/matrixone/pkg/common/moerr" 22 "github.com/matrixorigin/matrixone/pkg/pb/timestamp" 23 "github.com/matrixorigin/matrixone/pkg/vm/engine/memoryengine" 24 "github.com/stretchr/testify/assert" 25 ) 26 27 type TestRow struct { 28 key Int 29 value int 30 } 31 32 func (t TestRow) Key() Int { 33 return t.key 34 } 35 36 func (t TestRow) Value() int { 37 return t.value 38 } 39 40 func (t TestRow) Indexes() []Tuple { 41 return []Tuple{ 42 {Text("foo"), Int(t.value)}, 43 } 44 } 45 46 func (t TestRow) UniqueIndexes() []Tuple { 47 return []Tuple{ 48 {Int(t.value)}, 49 } 50 } 51 52 func TestTable(t *testing.T) { 53 54 table := NewTable[Int, int, TestRow]() 55 tx := NewTransaction("1", Time{}, Serializable) 56 row := TestRow{key: 42, value: 1} 57 58 // insert 59 err := table.Insert(tx, row) 60 assert.Nil(t, err) 61 62 // get 63 r, err := table.Get(tx, Int(42)) 64 assert.Nil(t, err) 65 assert.Equal(t, 1, r) 66 67 // update 68 row.value = 2 69 err = table.Update(tx, row) 70 assert.Nil(t, err) 71 72 r, err = table.Get(tx, Int(42)) 73 assert.Nil(t, err) 74 assert.Equal(t, 2, r) 75 76 // index 77 entries, err := table.Index(tx, Tuple{ 78 Text("foo"), Int(1), 79 }) 80 assert.Nil(t, err) 81 assert.Equal(t, 0, len(entries)) 82 entries, err = table.Index(tx, Tuple{ 83 Text("foo"), Int(2), 84 }) 85 assert.Nil(t, err) 86 assert.Equal(t, 1, len(entries)) 87 assert.Equal(t, Int(42), entries[0].Key) 88 89 // delete 90 err = table.Delete(tx, Int(42)) 91 assert.Nil(t, err) 92 93 } 94 95 // time util 96 func ts(i int64) Time { 97 return Time{ 98 Timestamp: timestamp.Timestamp{ 99 PhysicalTime: i, 100 }, 101 } 102 } 103 104 func TestTableIsolation(t *testing.T) { 105 106 // table 107 table := NewTable[Int, int, TestRow]() 108 109 // tx 1 110 tx1 := NewTransaction("1", ts(1), SnapshotIsolation) 111 112 // tx 2 113 tx2 := NewTransaction("2", ts(2), SnapshotIsolation) 114 err := table.Insert(tx2, TestRow{ 115 key: 1, 116 value: 2, 117 }) 118 assert.Nil(t, err) 119 v, err := table.Get(tx2, 1) 120 assert.Nil(t, err) 121 assert.Equal(t, 2, v) 122 err = tx2.Commit(ts(3)) 123 assert.Nil(t, err) 124 125 // duplicated key 126 err = table.Insert(tx1, TestRow{ 127 key: 1, 128 value: 3, 129 }) 130 assert.NotNil(t, err) 131 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrDuplicate)) 132 133 // read committed 134 iter := table.NewIter(tx1) 135 n := 0 136 for ok := iter.First(); ok; ok = iter.Next() { 137 n++ 138 } 139 assert.Equal(t, 0, n) 140 141 tx3 := NewTransaction("3", Time{ 142 Timestamp: timestamp.Timestamp{ 143 PhysicalTime: 3, 144 }, 145 }, SnapshotIsolation) 146 iter = table.NewIter(tx3) 147 n = 0 148 for ok := iter.First(); ok; ok = iter.Next() { 149 n++ 150 } 151 assert.Equal(t, 1, n) 152 153 } 154 155 type Issue5388Row struct { 156 RowID memoryengine.ID 157 A int 158 B int 159 } 160 161 func (i Issue5388Row) Key() memoryengine.ID { 162 return i.RowID 163 } 164 165 func (i Issue5388Row) Value() Issue5388Row { 166 return i 167 } 168 169 func (i Issue5388Row) Indexes() []Tuple { 170 return nil 171 } 172 173 func (i Issue5388Row) UniqueIndexes() []Tuple { 174 return nil 175 } 176 177 func TestIssue5388(t *testing.T) { 178 table := NewTable[memoryengine.ID, Issue5388Row, Issue5388Row]() 179 180 newID := func() ID { 181 id, err := memoryengine.RandomIDGenerator.NewID(context.Background()) 182 assert.Nil(t, err) 183 return id 184 } 185 186 // insert 10, 10 187 tx1 := NewTransaction("1", ts(1), SnapshotIsolation) 188 id1 := newID() 189 assert.Nil(t, table.Insert(tx1, Issue5388Row{ 190 RowID: id1, 191 A: 10, 192 B: 10, 193 })) 194 assert.Nil(t, tx1.Commit(ts(1))) 195 196 tx2 := NewTransaction("2", ts(2), SnapshotIsolation) 197 // set a = a - 1 198 assert.Nil(t, table.Delete(tx2, id1)) 199 id2 := newID() 200 assert.Nil(t, table.Insert(tx2, Issue5388Row{ 201 RowID: id2, 202 A: 9, 203 B: 10, 204 })) 205 // set b = b + 1 206 assert.Nil(t, table.Delete(tx2, id2)) 207 id3 := newID() 208 assert.Nil(t, table.Insert(tx2, Issue5388Row{ 209 RowID: id3, 210 A: 9, 211 B: 11, 212 })) 213 214 // concurrent tx 215 tx3 := NewTransaction("3", ts(3), SnapshotIsolation) 216 217 // read before tx2 commit 218 iter := table.NewIter(tx3) 219 n := 0 220 for ok := iter.First(); ok; ok = iter.Next() { 221 n++ 222 _, value, err := iter.Read() 223 assert.Nil(t, err) 224 assert.Equal(t, 10, value.A) 225 assert.Equal(t, 10, value.B) 226 } 227 assert.Equal(t, 1, n) 228 229 // tx2 commit 230 assert.Nil(t, tx2.Commit(ts(4))) 231 232 // read after tx2 commit 233 iter = table.NewIter(tx3) 234 n = 0 235 for ok := iter.First(); ok; ok = iter.Next() { 236 n++ 237 _, value, err := iter.Read() 238 assert.Nil(t, err) 239 assert.Equal(t, 10, value.A) 240 assert.Equal(t, 10, value.B) 241 } 242 assert.Equal(t, 1, n) 243 244 } 245 246 func TestUniqueIndex(t *testing.T) { 247 table := NewTable[Int, int, TestRow]() 248 tx1 := NewTransaction("1", ts(1), Serializable) 249 tx2 := NewTransaction("2", ts(1), Serializable) 250 251 row := TestRow{key: 42, value: 1} 252 253 err := table.Insert(tx1, row) 254 assert.Nil(t, err) 255 256 err = table.Insert(tx2, row) 257 assert.Nil(t, err) 258 259 err = tx1.Commit(ts(2)) 260 assert.Nil(t, err) 261 262 err = tx2.Commit(ts(2)) 263 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrDuplicate)) 264 } 265 266 func TestFilterVersions(t *testing.T) { 267 table := NewTable[Int, int, TestRow]() 268 269 for i := 0; i < 10; i++ { 270 row := TestRow{key: 42, value: i} 271 tx1 := NewTransaction("foo", ts(int64(i)), SnapshotIsolation) 272 err := table.Upsert(tx1, row) 273 assert.Nil(t, err) 274 err = tx1.Commit(ts(int64(i))) 275 assert.Nil(t, err) 276 } 277 278 err := table.FilterVersions(func(key Int, versions []Version[int]) (filtered []Version[int], err error) { 279 return nil, nil 280 }) 281 assert.Nil(t, err) 282 283 }