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  }