github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/testdata/indexed_batch_mutation (about)

     1  # Set a key within the indexed batch.
     2  new-batch
     3  set foo foo
     4  ----
     5  
     6  # Construct an iterator over the indexed batch.
     7  
     8  new-batch-iter i0
     9  ----
    10  
    11  # The key we set should be visible.
    12  
    13  iter iter=i0
    14  first
    15  next
    16  ----
    17  foo: (foo, .)
    18  .
    19  
    20  # Set a new key, while the above iterator is still open.
    21  
    22  mutate
    23  set bar bar
    24  ----
    25  
    26  # The new key should be invisible.
    27  
    28  iter iter=i0
    29  prev
    30  next
    31  ----
    32  foo: (foo, .)
    33  .
    34  
    35  # A set-options operation should refresh the Iterator's view of the batch. The
    36  # bar key should now be visibile.
    37  
    38  iter iter=i0
    39  set-options
    40  first
    41  next
    42  next
    43  ----
    44  .
    45  bar: (bar, .)
    46  foo: (foo, .)
    47  .
    48  
    49  # Delete foo with a range deletion.
    50  
    51  mutate
    52  del-range f g
    53  ----
    54  
    55  # Both keys should still be visible.
    56  
    57  iter iter=i0
    58  prev
    59  prev
    60  ----
    61  foo: (foo, .)
    62  bar: (bar, .)
    63  
    64  # After refreshing the iterator's view of the batch, foo should be deleted.
    65  
    66  iter iter=i0
    67  set-options
    68  seek-ge foo
    69  seek-lt foo
    70  ----
    71  .
    72  .
    73  bar: (bar, .)
    74  
    75  # Write a range key set and a point key.
    76  
    77  mutate
    78  range-key-set a c @1 boop
    79  set b b
    80  ----
    81  
    82  # The mutations should not be visible.
    83  
    84  iter iter=i0
    85  prev
    86  next
    87  ----
    88  .
    89  bar: (bar, .)
    90  
    91  # But refreshing the batch through a call to SetOptions should surface them.
    92  
    93  iter iter=i0
    94  set-options
    95  first
    96  next
    97  next
    98  ----
    99  .
   100  a: (., [a-c) @1=boop UPDATED)
   101  b: (b, [a-c) @1=boop)
   102  bar: (bar, [a-c) @1=boop)
   103  
   104  # Remove part of the range key to fragment it.
   105  
   106  mutate
   107  range-key-del ace arc
   108  ----
   109  
   110  iter iter=i0
   111  next
   112  prev
   113  prev
   114  prev
   115  prev
   116  ----
   117  .
   118  bar: (bar, [a-c) @1=boop UPDATED)
   119  b: (b, [a-c) @1=boop)
   120  a: (., [a-c) @1=boop)
   121  .
   122  
   123  iter iter=i0
   124  set-options
   125  first
   126  next
   127  next
   128  next
   129  ----
   130  .
   131  a: (., [a-ace) @1=boop UPDATED)
   132  arc: (., [arc-c) @1=boop UPDATED)
   133  b: (b, [arc-c) @1=boop)
   134  bar: (bar, [arc-c) @1=boop)
   135  
   136  # Create a new indexed batch and a new iterator over it.
   137  
   138  new-batch
   139  set foo foo
   140  ----
   141  
   142  new-batch-iter i1
   143  ----
   144  
   145  iter iter=i1
   146  first
   147  next
   148  ----
   149  foo: (foo, .)
   150  .
   151  
   152  # Test interactions with cloned iterators.
   153  # First, apply mutations to the batch. They should remain invisible.
   154  
   155  mutate
   156  set bar bar
   157  range-key-set a z @1 boop
   158  del-range f g
   159  ----
   160  
   161  iter iter=i1
   162  first
   163  next
   164  ----
   165  foo: (foo, .)
   166  .
   167  
   168  # Clone i1 to create i2.
   169  
   170  clone from=i1 to=i2 refresh-batch=false
   171  ----
   172  
   173  # i1 unchanged.
   174  
   175  iter iter=i1
   176  first
   177  next
   178  ----
   179  foo: (foo, .)
   180  .
   181  
   182  # i2 sees exactly the same stale state as i1 until SetOptions is called to
   183  # explicitly refresh the view of the underlying batch.
   184  
   185  iter iter=i2
   186  first
   187  next
   188  set-options
   189  first
   190  next
   191  next
   192  ----
   193  foo: (foo, .)
   194  .
   195  .
   196  a: (., [a-z) @1=boop UPDATED)
   197  bar: (bar, [a-z) @1=boop)
   198  .
   199  
   200  # Clone i1 to create i3, this time passing RefreshBatchView: true. This clone
   201  # should view the updated view of the underlying batch.
   202  clone from=i1 to=i3 refresh-batch=true
   203  ----
   204  
   205  iter iter=i3
   206  first
   207  next
   208  ----
   209  a: (., [a-z) @1=boop UPDATED)
   210  bar: (bar, [a-z) @1=boop)
   211  
   212  # i1 should still have the old, stale view of the batch.
   213  
   214  iter iter=i1
   215  first
   216  next
   217  ----
   218  foo: (foo, .)
   219  .
   220  
   221  # Mutate the underlying batch again.
   222  
   223  mutate
   224  set foo foo
   225  range-key-set a z @2 bax
   226  del-range b c
   227  ----
   228  
   229  # The new mutations should be invisible until SetOptions is called.
   230  
   231  iter iter=i1
   232  first
   233  next
   234  set-options
   235  first
   236  next
   237  next
   238  ----
   239  foo: (foo, .)
   240  .
   241  .
   242  a: (., [a-z) @2=bax, @1=boop UPDATED)
   243  foo: (foo, [a-z) @2=bax, @1=boop)
   244  .
   245  
   246  iter iter=i2
   247  first
   248  next
   249  next
   250  set-options
   251  first
   252  next
   253  next
   254  ----
   255  a: (., [a-z) @1=boop UPDATED)
   256  bar: (bar, [a-z) @1=boop)
   257  .
   258  .
   259  a: (., [a-z) @2=bax, @1=boop UPDATED)
   260  foo: (foo, [a-z) @2=bax, @1=boop)
   261  .
   262  
   263  # Commit a separate batch to the underlying engine.
   264  batch
   265  range-key-set a z @5 poi
   266  set apple apple
   267  ----
   268  
   269  # The writes to the underlying engine should be invisible.
   270  
   271  iter iter=i1
   272  first
   273  next
   274  next
   275  ----
   276  a: (., [a-z) @2=bax, @1=boop UPDATED)
   277  foo: (foo, [a-z) @2=bax, @1=boop)
   278  .
   279  
   280  # Clone i1 to create i4.
   281  
   282  clone from=i1 to=i4 refresh-batch=false
   283  ----
   284  
   285  iter iter=i4
   286  first
   287  next
   288  next
   289  ----
   290  a: (., [a-z) @2=bax, @1=boop UPDATED)
   291  foo: (foo, [a-z) @2=bax, @1=boop)
   292  .
   293  
   294  # Refresh i4's view of its batch. It should still not see the newly committed
   295  # writes.
   296  
   297  iter iter=i4
   298  set-options
   299  first
   300  next
   301  next
   302  ----
   303  .
   304  a: (., [a-z) @2=bax, @1=boop UPDATED)
   305  foo: (foo, [a-z) @2=bax, @1=boop)
   306  .
   307  
   308  # Create a new iterator i5 over the indexed batch [not a Clone]. It should see
   309  # all committed writes and uncommitted writes.
   310  
   311  new-batch-iter i5
   312  ----
   313  
   314  iter iter=i5
   315  first
   316  next
   317  next
   318  next
   319  ----
   320  a: (., [a-z) @5=poi, @2=bax, @1=boop UPDATED)
   321  apple: (apple, [a-z) @5=poi, @2=bax, @1=boop)
   322  foo: (foo, [a-z) @5=poi, @2=bax, @1=boop)
   323  .
   324  
   325  # Mutate all the open iterators' underlying batch.
   326  
   327  mutate
   328  range-key-set a z @6 yaya
   329  set c c
   330  ----
   331  
   332  # The iterators should still not see the committed writes, even after refreshing
   333  # to observe more recent batch writes.
   334  
   335  iter iter=i1
   336  first
   337  next
   338  next
   339  ----
   340  a: (., [a-z) @2=bax, @1=boop UPDATED)
   341  foo: (foo, [a-z) @2=bax, @1=boop)
   342  .
   343  
   344  iter iter=i4
   345  first
   346  next
   347  next
   348  set-options
   349  first
   350  next
   351  next
   352  ----
   353  a: (., [a-z) @2=bax, @1=boop UPDATED)
   354  foo: (foo, [a-z) @2=bax, @1=boop)
   355  .
   356  .
   357  a: (., [a-z) @6=yaya, @2=bax, @1=boop UPDATED)
   358  c: (c, [a-z) @6=yaya, @2=bax, @1=boop)
   359  foo: (foo, [a-z) @6=yaya, @2=bax, @1=boop)
   360  
   361  # Test a scenario where constructing an Iterator should NOT use the cached
   362  # fragmented tombstones / range keys, because the new Iterator is a Clone which
   363  # must read at an earlier batch sequence number.
   364  
   365  # Reset and start a new batch.
   366  
   367  reset
   368  ----
   369  
   370  new-batch
   371  set foo foo
   372  ----
   373  
   374  new-batch-iter i1
   375  ----
   376  
   377  iter iter=i1
   378  first
   379  next
   380  ----
   381  foo: (foo, .)
   382  .
   383  
   384  # Apply a range deletion and a range key.
   385  
   386  mutate
   387  del-range a z
   388  range-key-set a z @1 foo
   389  ----
   390  
   391  # Create a new iterator which will see both the range deletion and the range
   392  # key, and cache both on the batch so that future iterators constructed over the
   393  # batch do not need to.
   394  
   395  new-batch-iter i2
   396  ----
   397  
   398  iter iter=i2
   399  first
   400  next
   401  ----
   402  a: (., [a-z) @1=foo UPDATED)
   403  .
   404  
   405  # Clone the original iterator from before the delete range and the range key
   406  # were created. It should not use the cached fragments of range deletions or
   407  # range keys, and should not see the effects of either.
   408  
   409  clone from=i1 to=i3 refresh-batch=false
   410  ----
   411  
   412  iter iter=i3
   413  first
   414  next
   415  ----
   416  foo: (foo, .)
   417  .
   418  
   419  reset
   420  ----
   421  
   422  new-batch
   423  range-key-set a c @1 poi
   424  range-key-set b d @2 yaya
   425  ----
   426  
   427  new-batch-iter i1
   428  ----
   429  
   430  # The batch contains 2 range keys, but the skiplist of fragmented range keys
   431  # contains 3 elements (a-b, b-c, c-d).
   432  
   433  iter iter=i1
   434  first
   435  next
   436  next
   437  ----
   438  a: (., [a-b) @1=poi UPDATED)
   439  b: (., [b-c) @2=yaya, @1=poi UPDATED)
   440  c: (., [c-d) @2=yaya UPDATED)
   441  
   442  # Add a new range key to the batch. The batch contains 3 internal range keys,
   443  # and the skiplist of fragmented range keys contains 3 elements.
   444  
   445  mutate
   446  range-key-set e f @3 foo
   447  ----
   448  
   449  # Refreshing the iterator's view of the batch through SetOptions should surface
   450  # the new range key. An earlier bug incorrectly compared the number of
   451  # fragmented range keys to the number of internal batch range keys in order to
   452  # determine when to refresh the iterator.
   453  
   454  iter iter=i1
   455  first
   456  next
   457  next
   458  set-options
   459  first
   460  next
   461  next
   462  next
   463  seek-ge bat
   464  ----
   465  a: (., [a-b) @1=poi UPDATED)
   466  b: (., [b-c) @2=yaya, @1=poi UPDATED)
   467  c: (., [c-d) @2=yaya UPDATED)
   468  .
   469  a: (., [a-b) @1=poi UPDATED)
   470  b: (., [b-c) @2=yaya, @1=poi UPDATED)
   471  c: (., [c-d) @2=yaya UPDATED)
   472  e: (., [e-f) @3=foo UPDATED)
   473  bat: (., [b-c) @2=yaya, @1=poi UPDATED)
   474  
   475  # Mutate the range key under the interleaving iterator's current position in the
   476  # indexed batch.
   477  #
   478  # The last `seek-ge` operation landed on the range key [b-c). The top-level
   479  # *bitable.Iterator needs to step the iterator again to see if there's a
   480  # coincident point key at (`bat`), which would've advanced the interleaving
   481  # iterator to the range key with bounds [c,d), so the underlying interleaving
   482  # iterator is positioned ahead at:
   483  #
   484  #     c: (., [c-d) @2=yaya)
   485  #
   486  # If we call set-options to refresh the iterator's view of the indexed batch,
   487  # the range-key-unset [c,d)@2 becomes visible, and the range key that the
   488  # underlying interleaving iterator is positioned over should not be visible.
   489  #
   490  # A bug previously allowed this range key to be visible when seeking into this
   491  # span's bounds (see the optimization in InterleavingIter.SeekGE). Now, the call
   492  # to SetOptions clears the interleaving iterator's positional state to avoid the
   493  # SeekGE optimization.
   494  
   495  mutate
   496  range-key-unset b d @2
   497  ----
   498  
   499  iter iter=i1
   500  set-options
   501  seek-ge cat
   502  ----
   503  .
   504  e: (., [e-f) @3=foo UPDATED)
   505  
   506  reset
   507  ----
   508  
   509  batch
   510  range-key-set a e @1 foo
   511  ----
   512  
   513  flush
   514  ----
   515  
   516  new-batch
   517  ----
   518  
   519  new-batch-iter batchiter
   520  ----
   521  
   522  new-db-iter dbiter
   523  ----
   524  
   525  # Test RangeKeyChanged() semantics.
   526  # Seeking to the same prefix returns RangeKeyChanged()=false.
   527  # Seeking to a new prefix returns RangeKeyChanged()=true.
   528  # Seeking to the same prefix with a SetOptions call in between returns
   529  # RangeKeyChanged()=true.
   530  
   531  iter iter=dbiter
   532  seek-prefix-ge b@3
   533  seek-prefix-ge b@4
   534  seek-prefix-ge c@3
   535  seek-prefix-ge d@3
   536  set-options
   537  seek-prefix-ge d@1
   538  ----
   539  b@3: (., [b-"b\x00") @1=foo UPDATED)
   540  b@4: (., [b-"b\x00") @1=foo)
   541  c@3: (., [c-"c\x00") @1=foo UPDATED)
   542  d@3: (., [d-"d\x00") @1=foo UPDATED)
   543  .
   544  d@1: (., [d-"d\x00") @1=foo UPDATED)
   545  
   546  # Test the same semantics on a batch iterator.
   547  
   548  iter iter=batchiter
   549  seek-prefix-ge b@3
   550  seek-prefix-ge b@4
   551  seek-prefix-ge c@3
   552  seek-prefix-ge d@3
   553  set-options
   554  seek-prefix-ge d@1
   555  ----
   556  b@3: (., [b-"b\x00") @1=foo UPDATED)
   557  b@4: (., [b-"b\x00") @1=foo)
   558  c@3: (., [c-"c\x00") @1=foo UPDATED)
   559  d@3: (., [d-"d\x00") @1=foo UPDATED)
   560  .
   561  d@1: (., [d-"d\x00") @1=foo UPDATED)
   562  
   563  # Test mutating the indexed batch's range keys, overlapping the existing seek
   564  # position. It should not see the new mutations, but after a call to SetOptions
   565  # it should AND it should return RangeKeyChanged()=true.
   566  
   567  mutate
   568  range-key-set d e @2 foo
   569  ----
   570  
   571  iter iter=batchiter
   572  seek-prefix-ge d@2
   573  set-options
   574  seek-prefix-ge d@2
   575  ----
   576  d@2: (., [d-"d\x00") @1=foo)
   577  .
   578  d@2: (., [d-"d\x00") @2=foo, @1=foo UPDATED)
   579  
   580  # Test cloning an iterator with a range-key mask block property filter
   581  # configured. If the cloned and the clonee iterators have different suffixes
   582  # configured, their suffixes should be respected. Previously, the
   583  # RangeKeyMasking.Filter option was a footgun, because it was a single mutable
   584  # instance. Cloning the iterator without supplying new iterator options would
   585  # result in two iterators using the same filter.
   586  
   587  reset
   588  ----
   589  
   590  batch
   591  range-key-set a e @5 foo
   592  set b@4 b@4
   593  ----
   594  
   595  new-db-iter iter-a
   596  ----
   597  
   598  iter iter=iter-a
   599  set-options mask-suffix=@3 mask-filter=true
   600  seek-ge a
   601  next
   602  next
   603  ----
   604  .
   605  a: (., [a-e) @5=foo UPDATED)
   606  b@4: (b@4, [a-e) @5=foo)
   607  .
   608  
   609  clone from=iter-a to=iter-b refresh-batch=false
   610  ----
   611  
   612  iter iter=iter-b
   613  set-options mask-suffix=@6
   614  seek-ge a
   615  next
   616  ----
   617  .
   618  a: (., [a-e) @5=foo UPDATED)
   619  .
   620  
   621  iter iter=iter-a
   622  seek-ge a
   623  next
   624  next
   625  ----
   626  a: (., [a-e) @5=foo UPDATED)
   627  b@4: (b@4, [a-e) @5=foo)
   628  .