github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/testdata/merging_iter (about) 1 # Format for define command: 2 # Levels are ordered from higher to lower, and each new level starts with an L 3 # Each level is defined using an even number of lines where every pair of lines represents 4 # a file. The files within a level are ordered from smaller to larger keys. 5 # Each file is defined using: the first line specifies the smallest and largest internal 6 # keys and the second line the point key-value pairs in the sstable in order. The rangedel 7 # key-value pairs should also be in increasing order relative to the other rangedel pairs. 8 # The largest file key can take the form of <userkey>.RANGEDEL.72057594037927935, which 9 # represents the range deletion sentinel. 10 11 # The rangedel should not delete any points in any sstable. The two files were involved in a 12 # compaction and then the second file got moved to a lower level. 13 define 14 L 15 a.SET.30 e.RANGEDEL.72057594037927935 16 a.SET.30:30 c.SET.27:27 a.RANGEDEL.8:f 17 L 18 e.SET.10 g.SET.20 19 e.SET.10:10 g.SET.20:20 e.RANGEDEL.8:f 20 ---- 21 1: 22 000000:[a#30,SET-e#inf,RANGEDEL] 23 2: 24 000001:[e#10,SET-g#20,SET] 25 26 # isNextEntryDeleted() should not allow the rangedel to act on the points in the lower sstable 27 # that are after it. 28 iter 29 first 30 next 31 next 32 next 33 next 34 stats 35 reset-stats 36 stats 37 ---- 38 a#30,1:30 39 c#27,1:27 40 e#10,1:10 41 g#20,1:20 42 . 43 {BlockBytes:116 BlockBytesInCache:0 BlockReadDuration:0s KeyBytes:5 ValueBytes:8 PointCount:5 PointsCoveredByRangeTombstones:0 SeparatedPointValue:{Count:0 ValueBytes:0 ValueBytesFetched:0}} 44 {BlockBytes:0 BlockBytesInCache:0 BlockReadDuration:0s KeyBytes:0 ValueBytes:0 PointCount:0 PointsCoveredByRangeTombstones:0 SeparatedPointValue:{Count:0 ValueBytes:0 ValueBytesFetched:0}} 45 46 # seekGE() should not allow the rangedel to act on points in the lower sstable that are after it. 47 iter 48 seek-ge d 49 next 50 next 51 ---- 52 e#10,1:10 53 g#20,1:20 54 . 55 56 # isPrevEntryDeleted() should not allow the rangedel to act on the points in the lower sstable 57 # that are after it. 58 iter 59 last 60 prev 61 prev 62 prev 63 ---- 64 g#20,1:20 65 e#10,1:10 66 c#27,1:27 67 a#30,1:30 68 69 # seekLT() should not allow the rangedel to act on points in the lower sstable that are after it. 70 iter 71 seek-lt h 72 prev 73 prev 74 prev 75 ---- 76 g#20,1:20 77 e#10,1:10 78 c#27,1:27 79 a#30,1:30 80 81 # We keep the rangedel alive by having a point in the higher level past the first point in the 82 # lower level. This rangedel hides that first point in the lower level but we should not seek to 83 # h and hide the second point. 84 define 85 L 86 a.SET.15 f.SET.16 87 a.SET.15:15 c.SET.13:13 f.SET.16:16 a.RANGEDEL.12:h 88 L 89 e.SET.10 g.SET.15 90 e.SET.10:10 g.SET.15:15 91 ---- 92 1: 93 000002:[a#15,SET-f#16,SET] 94 2: 95 000003:[e#10,SET-g#15,SET] 96 97 iter 98 first 99 next 100 next 101 next 102 ---- 103 a#15,1:15 104 c#13,1:13 105 f#16,1:16 106 g#15,1:15 107 108 iter 109 seek-ge d 110 next 111 ---- 112 f#16,1:16 113 g#15,1:15 114 115 iter 116 last 117 prev 118 prev 119 prev 120 ---- 121 g#15,1:15 122 f#16,1:16 123 c#13,1:13 124 a#15,1:15 125 126 # The rangedel should not delete any points in any sstable. The two files were involved in an 127 # compaction and then the first file got moved to a lower level. 128 define 129 L 130 c.SET.30 f.RANGEDEL.0 131 c.SET.30:30 d.SET.27:27 a.RANGEDEL.8:f 132 L 133 a.SET.10 c.RANGEDEL.72057594037927935 134 a.SET.10:10 b.SET.12:12 a.RANGEDEL.8:f 135 ---- 136 1: 137 000004:[c#30,SET-f#0,RANGEDEL] 138 2: 139 000005:[a#10,SET-c#inf,RANGEDEL] 140 141 # isNextEntryDeleted() should not allow the rangedel to act on the points in the lower sstable 142 # that are before it. 143 iter 144 first 145 next 146 next 147 next 148 ---- 149 a#10,1:10 150 b#12,1:12 151 c#30,1:30 152 d#27,1:27 153 154 # seekGE() should not allow the rangedel to act on points in the lower sstable that are before it. 155 iter 156 seek-ge a 157 next 158 next 159 next 160 ---- 161 a#10,1:10 162 b#12,1:12 163 c#30,1:30 164 d#27,1:27 165 166 # isPrevEntryDeleted() should not allow the rangedel to act on the points in the lower sstable 167 # that are before it. 168 iter 169 last 170 prev 171 prev 172 prev 173 ---- 174 d#27,1:27 175 c#30,1:30 176 b#12,1:12 177 a#10,1:10 178 179 # seekLT() should not allow the rangedel to act on points in the lower sstable that are before it. 180 iter 181 seek-lt e 182 prev 183 prev 184 prev 185 ---- 186 d#27,1:27 187 c#30,1:30 188 b#12,1:12 189 a#10,1:10 190 191 # We keep the rangedel alive in prev iteration by having a point in the higher level before 192 # the last point in the lower level. This rangedel hides that first point in the lower level 193 # but we should not seek to a and hide the second point. 194 define 195 L 196 c.SET.15 g.SET.16 197 c.SET.15:15 f.SET.13:13 g.SET.16:16 a.RANGEDEL.12:h 198 L 199 b.SET.14 d.SET.10 200 b.SET.14:14 d.SET.10:10 201 ---- 202 1: 203 000006:[c#15,SET-g#16,SET] 204 2: 205 000007:[b#14,SET-d#10,SET] 206 207 iter 208 last 209 prev 210 prev 211 prev 212 ---- 213 g#16,1:16 214 f#13,1:13 215 c#15,1:15 216 b#14,1:14 217 218 iter 219 seek-lt f 220 prev 221 ---- 222 c#15,1:15 223 b#14,1:14 224 225 # The rangedel should not delete anything. 226 define 227 L 228 a.SET.30 e.RANGEDEL.72057594037927935 229 a.SET.30:30 c.SET.27:27 a.RANGEDEL.8:g 230 L 231 e.SET.10 g.SET.20 232 e.SET.10:10 g.SET.20:20 e.RANGEDEL.8:g 233 ---- 234 1: 235 000008:[a#30,SET-e#inf,RANGEDEL] 236 2: 237 000009:[e#10,SET-g#20,SET] 238 239 # When doing seek-lt f, the rangedel should not apply to e in the lower sstable. This is the 240 # reason we cannot just use largest user key to constrain the rangedel and we need to 241 # know whether it is the sentinel key. 242 iter 243 seek-lt f 244 prev 245 prev 246 ---- 247 e#10,1:10 248 c#27,1:27 249 a#30,1:30 250 251 iter 252 seek-ge e 253 next 254 ---- 255 e#10,1:10 256 g#20,1:20 257 258 iter 259 first 260 seek-ge e 261 next 262 ---- 263 a#30,1:30 264 e#10,1:10 265 g#20,1:20 266 267 iter 268 first 269 next 270 next 271 next 272 next 273 ---- 274 a#30,1:30 275 c#27,1:27 276 e#10,1:10 277 g#20,1:20 278 . 279 280 # Verify that switching directions respects lower/upper bound. 281 282 define 283 L 284 a.SET.9 d.SET.6 285 a.SET.9:9 b.SET.8:8 c.SET.7:7 d.SET.6:6 286 ---- 287 1: 288 000010:[a#9,SET-d#6,SET] 289 290 # Verify the lower bound is respected in switchToMinHeap() when the 291 # heap is empty. 292 293 iter 294 set-bounds lower=c 295 seek-ge c 296 prev 297 prev 298 next 299 ---- 300 c#7,1:7 301 . 302 . 303 c#7,1:7 304 305 # Verify the upper bound is respected in switchToMaxHeap() when the 306 # heap is empty. 307 308 iter 309 set-bounds upper=c 310 seek-lt c 311 next 312 next 313 prev 314 ---- 315 b#8,1:8 316 . 317 . 318 b#8,1:8 319 320 # Verify the lower bound is respected in switchToMinHeap() when the 321 # heap is not empty. 322 323 define 324 L 325 a.SET.9 d.SET.6 326 a.SET.9:9 b.SET.8:8 c.SET.7:7 d.SET.6:6 327 L 328 c.SET.5 f.SET.2 329 c.SET.5:5 d.SET.4:4 e.SET.3:3 f.SET.2:2 330 ---- 331 1: 332 000011:[a#9,SET-d#6,SET] 333 2: 334 000012:[c#5,SET-f#2,SET] 335 336 iter 337 set-bounds lower=d 338 seek-ge d 339 prev 340 prev 341 next 342 next 343 ---- 344 d#6,1:6 345 . 346 . 347 d#6,1:6 348 d#4,1:4 349 350 # Check the behavior of reverse prefix iteration. 351 352 iter 353 seek-prefix-ge d 354 prev 355 next 356 ---- 357 d#6,1:6 358 err=pebble: unsupported reverse prefix iteration 359 err=pebble: unsupported reverse prefix iteration 360 361 # Verify the upper bound is respected in switchToMaxHeap() when the 362 # heap is not empty. 363 364 define 365 L 366 c.SET.9 f.SET.6 367 c.SET.9:9 d.SET.8:8 e.SET.7:7 f.SET.6:6 368 L 369 a.SET.5 d.SET.2 370 a.SET.5:5 b.SET.4:4 c.SET.3:3 d.SET.2:2 371 ---- 372 1: 373 000013:[c#9,SET-f#6,SET] 374 2: 375 000014:[a#5,SET-d#2,SET] 376 377 iter 378 set-bounds upper=d 379 seek-lt d 380 next 381 next 382 prev 383 prev 384 ---- 385 c#3,1:3 386 . 387 . 388 c#3,1:3 389 c#9,1:9 390 391 # Verify that the tombstone for the current level is updated correctly 392 # when we advance the iterator on the level and step into a new 393 # sstable. In the scenario below, the keys "c" and "d" should not show 394 # up in the iteration output. 395 396 define 397 L 398 a.SET.2 a.SET.2 399 a.SET.2:2 400 c.RANGEDEL.4 e.RANGEDEL.72057594037927935 401 c.RANGEDEL.4:e 402 f.SET.3 f.SET.3 403 f.SET.3:3 404 L 405 a.SET.0 f.SET.0 406 a.SET.0:1 b.SET.0:1 c.SET.0:1 d.SET.0:1 e.SET.0:1 f.SET.0:1 407 ---- 408 1: 409 000015:[a#2,SET-a#2,SET] 410 000016:[c#4,RANGEDEL-e#inf,RANGEDEL] 411 000017:[f#3,SET-f#3,SET] 412 2: 413 000018:[a#0,SET-f#0,SET] 414 415 iter 416 first 417 next 418 next 419 next 420 next 421 next 422 next 423 next 424 ---- 425 a#2,1:2 426 a#0,1:1 427 b#0,1:1 428 e#0,1:1 429 f#3,1:3 430 f#0,1:1 431 . 432 . 433 434 iter 435 last 436 prev 437 prev 438 prev 439 prev 440 prev 441 prev 442 prev 443 ---- 444 f#0,1:1 445 f#3,1:3 446 e#0,1:1 447 b#0,1:1 448 a#0,1:1 449 a#2,1:2 450 . 451 . 452 453 # Verify the upper bound is respected when switching directions at a RANGEDEL 454 # boundary. 455 456 define 457 L 458 kq.RANGEDEL.100 p.RANGEDEL.72057594037927935 459 kq.RANGEDEL.100:p 460 L 461 b.SET.90 o.SET.65 462 b.SET.90:90 cat.SET.70:70 g.SET.80:80 o.SET.65:65 463 L 464 a.SET.41 z.RANGEDEL.72057594037927935 465 a.SET.41:41 koujdlp.MERGE.37:37 ok.SET.46:46 v.SET.43:43 v.RANGEDEL.19:z 466 ---- 467 1: 468 000019:[kq#100,RANGEDEL-p#inf,RANGEDEL] 469 2: 470 000020:[b#90,SET-o#65,SET] 471 3: 472 000021:[a#41,SET-z#inf,RANGEDEL] 473 474 iter 475 set-bounds upper=n 476 seek-ge krgywquurww 477 prev 478 ---- 479 . 480 koujdlp#37,2:37 481 482 # Verify the lower bound is respected when switching directions at a RANGEDEL 483 # boundary. 484 485 define 486 L 487 a.SET.103 jyk.RANGEDEL.72057594037927935 488 a.SET.103:103 imd.SET.793:793 iwoeionch.SET.792:792 c.RANGEDEL.101:jyk 489 L 490 b.SET.90 o.SET.65 491 b.SET.90:90 cat.SET.70:70 g.SET.80:80 o.SET.65:65 492 L 493 all.SET.0 zk.SET.722 494 all.SET.0:0 c.SET.0:0 zk.SET.722:722 495 ---- 496 1: 497 000022:[a#103,SET-jyk#inf,RANGEDEL] 498 2: 499 000023:[b#90,SET-o#65,SET] 500 3: 501 000024:[all#0,SET-zk#722,SET] 502 503 iter 504 set-bounds lower=cz upper=jd 505 seek-lt jd 506 next 507 ---- 508 iwoeionch#792,1:792 509 . 510 511 # Exercise the early stopping behavior for prefix iteration when encountering 512 # range deletion tombstones. Keys a, d are not deleted, while the rest are. 513 define 514 L 515 a.SET.10 d.SET.10 516 a.SET.10:a10 b.SET.10:b10 c.SET.10:c10 d.SET.10:d10 b.RANGEDEL.12:d 517 ---- 518 1: 519 000025:[a#10,SET-d#10,SET] 520 521 iter 522 first 523 next 524 next 525 ---- 526 a#10,1:a10 527 d#10,1:d10 528 . 529 530 # The seek to c finds d since iteration cannot stop at c as it matches the 531 # prefix, and when it steps to d, it finds d is not deleted. Note that 532 # mergingIter is an InternalIterator and does not need to guarantee prefix 533 # match -- that is job of the higher-level Iterator. So "seek-prefix-ge c" is 534 # allowed to return d. 535 iter 536 seek-prefix-ge a false 537 seek-prefix-ge aa true 538 seek-prefix-ge b true 539 seek-prefix-ge c true 540 seek-prefix-ge d true 541 ---- 542 a#10,1:a10 543 . 544 . 545 d#10,1:d10 546 d#10,1:d10 547 548 iter 549 seek-prefix-ge a false 550 next 551 seek-prefix-ge b false 552 seek-prefix-ge d true 553 next 554 ---- 555 a#10,1:a10 556 . 557 . 558 d#10,1:d10 559 . 560 561 # Create a sstable which has a range tombstone that covers 4 points in the 562 # same sstable. This tests the PointsCoveredByRangeTombstones and PointCount 563 # stats. 564 define 565 L 566 a.SET.30 g.RANGEDEL.72057594037927935 567 a.SET.30:30 a.RANGEDEL.20:g b.SET.19:19 c.SET.18:18 d.SET.17:17 e.SET.16:16 f.SET.21:21 568 ---- 569 1: 570 000026:[a#30,SET-g#inf,RANGEDEL] 571 572 iter 573 first 574 stats 575 reset-stats 576 stats 577 next 578 stats 579 next 580 stats 581 next 582 stats 583 ---- 584 a#30,1:30 585 {BlockBytes:97 BlockBytesInCache:0 BlockReadDuration:0s KeyBytes:1 ValueBytes:2 PointCount:1 PointsCoveredByRangeTombstones:0 SeparatedPointValue:{Count:0 ValueBytes:0 ValueBytesFetched:0}} 586 {BlockBytes:0 BlockBytesInCache:0 BlockReadDuration:0s KeyBytes:0 ValueBytes:0 PointCount:0 PointsCoveredByRangeTombstones:0 SeparatedPointValue:{Count:0 ValueBytes:0 ValueBytesFetched:0}} 587 f#21,1:21 588 {BlockBytes:0 BlockBytesInCache:0 BlockReadDuration:0s KeyBytes:5 ValueBytes:10 PointCount:5 PointsCoveredByRangeTombstones:4 SeparatedPointValue:{Count:0 ValueBytes:0 ValueBytesFetched:0}} 589 . 590 {BlockBytes:0 BlockBytesInCache:0 BlockReadDuration:0s KeyBytes:6 ValueBytes:10 PointCount:6 PointsCoveredByRangeTombstones:4 SeparatedPointValue:{Count:0 ValueBytes:0 ValueBytesFetched:0}} 591 . 592 {BlockBytes:0 BlockBytesInCache:0 BlockReadDuration:0s KeyBytes:6 ValueBytes:10 PointCount:6 PointsCoveredByRangeTombstones:4 SeparatedPointValue:{Count:0 ValueBytes:0 ValueBytesFetched:0}}