github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/disttae/logtailreplay/rows_iter_test.go (about) 1 // Copyright 2023 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 logtailreplay 16 17 import ( 18 "context" 19 "testing" 20 21 "github.com/matrixorigin/matrixone/pkg/common/mpool" 22 "github.com/matrixorigin/matrixone/pkg/container/types" 23 "github.com/matrixorigin/matrixone/pkg/container/vector" 24 "github.com/matrixorigin/matrixone/pkg/objectio" 25 "github.com/matrixorigin/matrixone/pkg/pb/api" 26 "github.com/stretchr/testify/require" 27 ) 28 29 func TestPartitionStateRowsIter(t *testing.T) { 30 state := NewPartitionState(false) 31 ctx := context.Background() 32 pool := mpool.MustNewZero() 33 packer := types.NewPacker(pool) 34 defer packer.FreeMem() 35 36 { 37 // empty rows 38 iter := state.NewRowsIter(types.BuildTS(0, 0), nil, false) 39 n := 0 40 for iter.Next() { 41 n++ 42 } 43 require.Equal(t, 0, n) 44 require.Nil(t, iter.Close()) 45 } 46 47 { 48 // iter again 49 iter := state.NewRowsIter(types.BuildTS(0, 0), nil, false) 50 n := 0 51 for iter.Next() { 52 n++ 53 } 54 require.Equal(t, 0, n) 55 require.Nil(t, iter.Close()) 56 } 57 58 const num = 128 59 60 sid := objectio.NewSegmentid() 61 buildRowID := func(i int) types.Rowid { 62 blk := objectio.NewBlockid(sid, uint16(i), 0) 63 return *objectio.NewRowid(blk, uint32(0)) 64 } 65 66 { 67 // insert number i at time i with (i+1) row id 68 rowIDVec := vector.NewVec(types.T_Rowid.ToType()) 69 tsVec := vector.NewVec(types.T_TS.ToType()) 70 vec1 := vector.NewVec(types.T_int64.ToType()) 71 for i := 0; i < num; i++ { 72 vector.AppendFixed(rowIDVec, buildRowID(i+1), false, pool) 73 vector.AppendFixed(tsVec, types.BuildTS(int64(i), 0), false, pool) 74 vector.AppendFixed(vec1, int64(i), false, pool) 75 } 76 state.HandleRowsInsert(ctx, &api.Batch{ 77 Attrs: []string{"rowid", "time", "a"}, 78 Vecs: []api.Vector{ 79 mustVectorToProto(rowIDVec), 80 mustVectorToProto(tsVec), 81 mustVectorToProto(vec1), 82 }, 83 }, 0, packer) 84 } 85 86 // rows iter 87 for i := 0; i < num; i++ { 88 ts := types.BuildTS(int64(i), 0) 89 iter := state.NewRowsIter(ts, nil, false) 90 n := 0 91 rowIDs := make(map[types.Rowid]bool) 92 for iter.Next() { 93 n++ 94 entry := iter.Entry() 95 rowIDs[entry.RowID] = true 96 // RowExists 97 require.True(t, state.RowExists(entry.RowID, ts)) 98 } 99 require.Equal(t, i+1, n) 100 require.Equal(t, i+1, len(rowIDs)) 101 require.Nil(t, iter.Close()) 102 } 103 104 // primary key iter 105 for i := 0; i < num; i++ { 106 ts := types.BuildTS(int64(i), 0) 107 bs := EncodePrimaryKey(int64(i), packer) 108 iter := state.NewPrimaryKeyIter(ts, Exact(bs)) 109 n := 0 110 for iter.Next() { 111 n++ 112 } 113 require.Equal(t, 1, n) 114 require.Nil(t, iter.Close()) 115 modified, _ := state.PKExistInMemBetween(ts.Prev(), ts.Next(), [][]byte{bs}) 116 require.True(t, modified) 117 } 118 119 { 120 // insert duplicated rows 121 rowIDVec := vector.NewVec(types.T_Rowid.ToType()) 122 tsVec := vector.NewVec(types.T_TS.ToType()) 123 vec1 := vector.NewVec(types.T_int64.ToType()) 124 for i := 0; i < num; i++ { 125 vector.AppendFixed(rowIDVec, buildRowID(i+1), false, pool) 126 vector.AppendFixed(tsVec, types.BuildTS(int64(i), 1), false, pool) 127 vector.AppendFixed(vec1, int64(i), false, pool) 128 } 129 state.HandleRowsInsert(ctx, &api.Batch{ 130 Attrs: []string{"rowid", "time", "a"}, 131 Vecs: []api.Vector{ 132 mustVectorToProto(rowIDVec), 133 mustVectorToProto(tsVec), 134 mustVectorToProto(vec1), 135 }, 136 }, 0, packer) 137 } 138 139 // rows iter 140 for i := 0; i < num; i++ { 141 iter := state.NewRowsIter(types.BuildTS(int64(i), 0), nil, false) 142 n := 0 143 rowIDs := make(map[types.Rowid]bool) 144 for iter.Next() { 145 n++ 146 entry := iter.Entry() 147 rowIDs[entry.RowID] = true 148 } 149 require.Equal(t, i+1, n) 150 require.Equal(t, i+1, len(rowIDs)) 151 require.Nil(t, iter.Close()) 152 } 153 154 deleteAt := 1000 155 { 156 // delete number i at (deleteAt+i) with (i+1) row id 157 rowIDVec := vector.NewVec(types.T_Rowid.ToType()) 158 tsVec := vector.NewVec(types.T_TS.ToType()) 159 for i := 0; i < num; i++ { 160 vector.AppendFixed(rowIDVec, buildRowID(i+1), false, pool) 161 vector.AppendFixed(tsVec, types.BuildTS(int64(deleteAt+i), 1), false, pool) 162 } 163 state.HandleRowsDelete(ctx, &api.Batch{ 164 Attrs: []string{"rowid", "time"}, 165 Vecs: []api.Vector{ 166 mustVectorToProto(rowIDVec), 167 mustVectorToProto(tsVec), 168 }, 169 }, packer) 170 } 171 172 for i := 0; i < num; i++ { 173 { 174 // rows iter 175 iter := state.NewRowsIter(types.BuildTS(int64(deleteAt+i), 0), nil, false) 176 rowIDs := make(map[types.Rowid]bool) 177 n := 0 178 for iter.Next() { 179 n++ 180 entry := iter.Entry() 181 rowIDs[entry.RowID] = true 182 } 183 require.Equal(t, num-i, n) 184 require.Equal(t, num-i, len(rowIDs)) 185 require.Nil(t, iter.Close()) 186 } 187 188 { 189 // deleted rows iter 190 blockID, _ := buildRowID(i + 1).Decode() 191 iter := state.NewRowsIter(types.BuildTS(int64(deleteAt+i+1), 0), &blockID, true) 192 rowIDs := make(map[types.Rowid]bool) 193 n := 0 194 for iter.Next() { 195 n++ 196 entry := iter.Entry() 197 rowIDs[entry.RowID] = true 198 } 199 require.Equal(t, 1, n, "num is %d", i) 200 require.Equal(t, 1, len(rowIDs)) 201 require.Nil(t, iter.Close()) 202 } 203 204 { 205 // primary key change detection 206 ts := types.BuildTS(int64(deleteAt+i), 0) 207 key := EncodePrimaryKey(int64(i), packer) 208 modified, _ := state.PKExistInMemBetween( 209 ts.Prev(), 210 ts.Next(), 211 [][]byte{key}, 212 ) 213 require.True(t, modified) 214 } 215 216 { 217 // primary key iter 218 key := EncodePrimaryKey(int64(i), packer) 219 iter := state.NewPrimaryKeyIter(types.BuildTS(int64(deleteAt+i+1), 0), Exact(key)) 220 n := 0 221 for iter.Next() { 222 n++ 223 } 224 iter.Close() 225 require.Equal(t, 0, n) // not visible 226 } 227 228 } 229 230 deleteAt = 2000 231 { 232 // duplicate delete 233 rowIDVec := vector.NewVec(types.T_Rowid.ToType()) 234 tsVec := vector.NewVec(types.T_TS.ToType()) 235 for i := 0; i < num; i++ { 236 vector.AppendFixed(rowIDVec, buildRowID(i+1), false, pool) 237 vector.AppendFixed(tsVec, types.BuildTS(int64(deleteAt+i), 1), false, pool) 238 } 239 state.HandleRowsDelete(ctx, &api.Batch{ 240 Attrs: []string{"rowid", "time", "a"}, 241 Vecs: []api.Vector{ 242 mustVectorToProto(rowIDVec), 243 mustVectorToProto(tsVec), 244 }, 245 }, packer) 246 } 247 248 for i := 0; i < num; i++ { 249 { 250 blockID, _ := buildRowID(i + 1).Decode() 251 iter := state.NewRowsIter(types.BuildTS(int64(deleteAt+i), 0), &blockID, true) 252 rowIDs := make(map[types.Rowid]bool) 253 n := 0 254 for iter.Next() { 255 n++ 256 entry := iter.Entry() 257 rowIDs[entry.RowID] = true 258 } 259 require.Equal(t, 1, n) 260 require.Equal(t, 1, len(rowIDs)) 261 require.Nil(t, iter.Close()) 262 } 263 } 264 265 } 266 267 func TestInsertAndDeleteAtTheSameTimestamp(t *testing.T) { 268 state := NewPartitionState(false) 269 ctx := context.Background() 270 pool := mpool.MustNewZero() 271 packer := types.NewPacker(pool) 272 defer packer.FreeMem() 273 274 const num = 128 275 276 sid := objectio.NewSegmentid() 277 buildRowID := func(i int) types.Rowid { 278 blk := objectio.NewBlockid(sid, uint16(i), 0) 279 return *objectio.NewRowid(blk, uint32(0)) 280 } 281 282 { 283 // insert number i at time i with (i+1) row id 284 rowIDVec := vector.NewVec(types.T_Rowid.ToType()) 285 tsVec := vector.NewVec(types.T_TS.ToType()) 286 vec1 := vector.NewVec(types.T_int64.ToType()) 287 for i := 0; i < num; i++ { 288 vector.AppendFixed(rowIDVec, buildRowID(i+1), false, pool) 289 vector.AppendFixed(tsVec, types.BuildTS(int64(i), 0), false, pool) 290 vector.AppendFixed(vec1, int64(i), false, pool) 291 } 292 state.HandleRowsInsert(ctx, &api.Batch{ 293 Attrs: []string{"rowid", "time", "a"}, 294 Vecs: []api.Vector{ 295 mustVectorToProto(rowIDVec), 296 mustVectorToProto(tsVec), 297 mustVectorToProto(vec1), 298 }, 299 }, 0, packer) 300 } 301 302 { 303 // delete number i at the same time 304 rowIDVec := vector.NewVec(types.T_Rowid.ToType()) 305 tsVec := vector.NewVec(types.T_TS.ToType()) 306 for i := 0; i < num; i++ { 307 vector.AppendFixed(rowIDVec, buildRowID(i+1), false, pool) 308 vector.AppendFixed(tsVec, types.BuildTS(int64(i), 1), false, pool) 309 } 310 state.HandleRowsDelete(ctx, &api.Batch{ 311 Attrs: []string{"rowid", "time"}, 312 Vecs: []api.Vector{ 313 mustVectorToProto(rowIDVec), 314 mustVectorToProto(tsVec), 315 }, 316 }, packer) 317 } 318 319 { 320 // should be deleted 321 iter := state.NewRowsIter( 322 types.BuildTS(num*2, 0), 323 nil, 324 false, 325 ) 326 n := 0 327 for iter.Next() { 328 n++ 329 } 330 require.Equal(t, 0, n) 331 require.Nil(t, iter.Close()) 332 } 333 334 { 335 // iter deleted 336 iter := state.NewRowsIter( 337 types.BuildTS(num*2, 0), 338 nil, 339 true, 340 ) 341 n := 0 342 for iter.Next() { 343 n++ 344 } 345 require.Equal(t, num, n) 346 require.Nil(t, iter.Close()) 347 } 348 349 // should be detectable 350 for i := 0; i < num; i++ { 351 ts := types.BuildTS(int64(i), 0) 352 key := EncodePrimaryKey(int64(i), packer) 353 modified, _ := state.PKExistInMemBetween(ts.Prev(), ts.Next(), [][]byte{key}) 354 require.True(t, modified) 355 } 356 357 } 358 359 func TestDeleteBeforeInsertAtTheSameTime(t *testing.T) { 360 state := NewPartitionState(false) 361 ctx := context.Background() 362 pool := mpool.MustNewZero() 363 packer := types.NewPacker(pool) 364 defer packer.FreeMem() 365 366 const num = 128 367 368 sid := objectio.NewSegmentid() 369 buildRowID := func(i int) types.Rowid { 370 blk := objectio.NewBlockid(sid, uint16(i), 0) 371 return *objectio.NewRowid(blk, uint32(0)) 372 } 373 374 { 375 // delete number i at time i with (i+1) row id 376 rowIDVec := vector.NewVec(types.T_Rowid.ToType()) 377 tsVec := vector.NewVec(types.T_TS.ToType()) 378 for i := 0; i < num; i++ { 379 vector.AppendFixed(rowIDVec, buildRowID(i+1), false, pool) 380 vector.AppendFixed(tsVec, types.BuildTS(int64(i), 1), false, pool) 381 } 382 state.HandleRowsDelete(ctx, &api.Batch{ 383 Attrs: []string{"rowid", "time"}, 384 Vecs: []api.Vector{ 385 mustVectorToProto(rowIDVec), 386 mustVectorToProto(tsVec), 387 }, 388 }, packer) 389 } 390 391 { 392 // insert number i at time i with (i+1) row id 393 rowIDVec := vector.NewVec(types.T_Rowid.ToType()) 394 tsVec := vector.NewVec(types.T_TS.ToType()) 395 vec1 := vector.NewVec(types.T_int64.ToType()) 396 for i := 0; i < num; i++ { 397 vector.AppendFixed(rowIDVec, buildRowID(i+1), false, pool) 398 vector.AppendFixed(tsVec, types.BuildTS(int64(i), 0), false, pool) 399 vector.AppendFixed(vec1, int64(i), false, pool) 400 } 401 state.HandleRowsInsert(ctx, &api.Batch{ 402 Attrs: []string{"rowid", "time", "a"}, 403 Vecs: []api.Vector{ 404 mustVectorToProto(rowIDVec), 405 mustVectorToProto(tsVec), 406 mustVectorToProto(vec1), 407 }, 408 }, 0, packer) 409 } 410 411 { 412 // should be deleted 413 iter := state.NewRowsIter( 414 types.BuildTS(num*2, 0), 415 nil, 416 false, 417 ) 418 n := 0 419 for iter.Next() { 420 n++ 421 } 422 require.Equal(t, 0, n) 423 require.Nil(t, iter.Close()) 424 } 425 426 { 427 // iter deleted 428 iter := state.NewRowsIter( 429 types.BuildTS(num*2, 0), 430 nil, 431 true, 432 ) 433 n := 0 434 for iter.Next() { 435 n++ 436 } 437 require.Equal(t, num, n) 438 require.Nil(t, iter.Close()) 439 } 440 441 // should be detectable 442 for i := 0; i < num; i++ { 443 ts := types.BuildTS(int64(i), 0) 444 key := EncodePrimaryKey(int64(i), packer) 445 modified, _ := state.PKExistInMemBetween(ts.Prev(), ts.Next(), [][]byte{key}) 446 require.True(t, modified) 447 } 448 449 } 450 451 func TestPrimaryKeyModifiedWithDeleteOnly(t *testing.T) { 452 state := NewPartitionState(false) 453 ctx := context.Background() 454 pool := mpool.MustNewZero() 455 packer := types.NewPacker(pool) 456 defer packer.FreeMem() 457 458 const num = 128 459 460 sid := objectio.NewSegmentid() 461 buildRowID := func(i int) types.Rowid { 462 blk := objectio.NewBlockid(sid, uint16(i), 0) 463 return *objectio.NewRowid(blk, uint32(0)) 464 } 465 466 { 467 // delete number i at time i with (i+1) row id 468 rowIDVec := vector.NewVec(types.T_Rowid.ToType()) 469 tsVec := vector.NewVec(types.T_TS.ToType()) 470 primaryKeyVec := vector.NewVec(types.T_int64.ToType()) 471 for i := 0; i < num; i++ { 472 vector.AppendFixed(rowIDVec, buildRowID(i+1), false, pool) 473 vector.AppendFixed(tsVec, types.BuildTS(int64(i), 1), false, pool) 474 vector.AppendFixed(primaryKeyVec, int64(i), false, pool) 475 } 476 state.HandleRowsDelete(ctx, &api.Batch{ 477 Attrs: []string{"rowid", "time", "i"}, 478 Vecs: []api.Vector{ 479 mustVectorToProto(rowIDVec), 480 mustVectorToProto(tsVec), 481 mustVectorToProto(primaryKeyVec), // with primary key 482 }, 483 }, packer) 484 } 485 486 // should be detectable 487 for i := 0; i < num; i++ { 488 ts := types.BuildTS(int64(i), 0) 489 key := EncodePrimaryKey(int64(i), packer) 490 modified, _ := state.PKExistInMemBetween(ts.Prev(), ts.Next(), [][]byte{key}) 491 require.True(t, modified) 492 } 493 494 }