From c99b24eef4cd1e7e86548f311c06c358ade021c4 Mon Sep 17 00:00:00 2001 From: Etienne Petrel Date: Thu, 22 Sep 2022 01:58:37 +0000 Subject: Import wiredtiger: 132e8a3ba5cc8ab45dfcbc1ae904b2e5dd1be237 from branch mongodb-master ref: bb5c03d590..132e8a3ba5 for: 6.2.0-rc0 WT-9851 Support bounded cursor next and prev traversal in FLCS (#8273) --- src/third_party/wiredtiger/import.data | 2 +- src/third_party/wiredtiger/src/btree/bt_curnext.c | 17 +++++--- src/third_party/wiredtiger/src/btree/bt_curprev.c | 20 +++++++-- src/third_party/wiredtiger/src/btree/bt_cursor.c | 48 +++++++++++++--------- src/third_party/wiredtiger/src/cursor/cur_std.c | 3 -- .../wiredtiger/test/suite/test_cursor_bound02.py | 26 +++++++++--- .../wiredtiger/test/suite/test_cursor_bound03.py | 5 ++- .../wiredtiger/test/suite/test_cursor_bound04.py | 17 ++++---- src/third_party/wiredtiger/test/suite/wtbound.py | 35 ++++++++++++++-- 9 files changed, 121 insertions(+), 52 deletions(-) diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index 120590819ed..f7e0e6da729 100644 --- a/src/third_party/wiredtiger/import.data +++ b/src/third_party/wiredtiger/import.data @@ -2,5 +2,5 @@ "vendor": "wiredtiger", "github": "wiredtiger/wiredtiger.git", "branch": "mongodb-master", - "commit": "bb5c03d59037747b3c477bb58e4c82eb961e5589" + "commit": "132e8a3ba5cc8ab45dfcbc1ae904b2e5dd1be237" } diff --git a/src/third_party/wiredtiger/src/btree/bt_curnext.c b/src/third_party/wiredtiger/src/btree/bt_curnext.c index 2b99c6fbae3..1dc6b86854c 100644 --- a/src/third_party/wiredtiger/src/btree/bt_curnext.c +++ b/src/third_party/wiredtiger/src/btree/bt_curnext.c @@ -13,8 +13,9 @@ * Return the next entry on the append list. */ static inline int -__cursor_fix_append_next(WT_CURSOR_BTREE *cbt, bool newpage, bool restart) +__cursor_fix_append_next(WT_CURSOR_BTREE *cbt, bool newpage, bool restart, bool *key_out_of_boundsp) { + WT_DECL_RET; WT_SESSION_IMPL *session; session = CUR2S(cbt); @@ -38,7 +39,9 @@ __cursor_fix_append_next(WT_CURSOR_BTREE *cbt, bool newpage, bool restart) * it to 1, which is correct. */ __cursor_set_recno(cbt, cbt->recno + 1); - + if ((ret = __wt_btcur_bounds_early_exit(session, cbt, true, key_out_of_boundsp)) == WT_NOTFOUND) + WT_STAT_CONN_DATA_INCR(session, cursor_bounds_next_early_exit); + WT_RET(ret); /* * Fixed-width column store appends are inherently non-transactional. Even a non-visible update * by a concurrent or aborted transaction changes the effective end of the data. The effect is @@ -75,8 +78,9 @@ restart_read: * Move to the next, fixed-length column-store item. */ static inline int -__cursor_fix_next(WT_CURSOR_BTREE *cbt, bool newpage, bool restart) +__cursor_fix_next(WT_CURSOR_BTREE *cbt, bool newpage, bool restart, bool *key_out_of_boundsp) { + WT_DECL_RET; WT_PAGE *page; WT_SESSION_IMPL *session; @@ -107,6 +111,9 @@ __cursor_fix_next(WT_CURSOR_BTREE *cbt, bool newpage, bool restart) new_page: restart_read: + if ((ret = __wt_btcur_bounds_early_exit(session, cbt, true, key_out_of_boundsp)) == WT_NOTFOUND) + WT_STAT_CONN_DATA_INCR(session, cursor_bounds_next_early_exit); + WT_RET(ret); /* We only have one slot. */ cbt->slot = 0; @@ -833,7 +840,7 @@ __wt_btcur_next_prefix(WT_CURSOR_BTREE *cbt, WT_ITEM *prefix, bool truncating) WT_ASSERT(session, page != NULL); switch (page->type) { case WT_PAGE_COL_FIX: - ret = __cursor_fix_append_next(cbt, newpage, restart); + ret = __cursor_fix_append_next(cbt, newpage, restart, &key_out_of_bounds); break; case WT_PAGE_COL_VAR: ret = __cursor_var_append_next(cbt, newpage, restart, &skipped, &key_out_of_bounds); @@ -859,7 +866,7 @@ __wt_btcur_next_prefix(WT_CURSOR_BTREE *cbt, WT_ITEM *prefix, bool truncating) } else if (page != NULL) { switch (page->type) { case WT_PAGE_COL_FIX: - ret = __cursor_fix_next(cbt, newpage, restart); + ret = __cursor_fix_next(cbt, newpage, restart, &key_out_of_bounds); break; case WT_PAGE_COL_VAR: ret = __cursor_var_next(cbt, newpage, restart, &skipped, &key_out_of_bounds); diff --git a/src/third_party/wiredtiger/src/btree/bt_curprev.c b/src/third_party/wiredtiger/src/btree/bt_curprev.c index 20a0172ba7e..07d0053db65 100644 --- a/src/third_party/wiredtiger/src/btree/bt_curprev.c +++ b/src/third_party/wiredtiger/src/btree/bt_curprev.c @@ -120,8 +120,9 @@ restart: * Return the previous fixed-length entry on the append list. */ static inline int -__cursor_fix_append_prev(WT_CURSOR_BTREE *cbt, bool newpage, bool restart) +__cursor_fix_append_prev(WT_CURSOR_BTREE *cbt, bool newpage, bool restart, bool *key_out_of_boundsp) { + WT_DECL_RET; WT_SESSION_IMPL *session; session = CUR2S(cbt); @@ -184,6 +185,11 @@ __cursor_fix_append_prev(WT_CURSOR_BTREE *cbt, bool newpage, bool restart) else __cursor_set_recno(cbt, cbt->recno - 1); + if ((ret = __wt_btcur_bounds_early_exit(session, cbt, false, key_out_of_boundsp)) == + WT_NOTFOUND) + WT_STAT_CONN_DATA_INCR(session, cursor_bounds_prev_early_exit); + WT_RET(ret); + if (F_ISSET(&cbt->iface, WT_CURSTD_KEY_ONLY)) return (0); @@ -218,8 +224,9 @@ restart_read: * Move to the previous, fixed-length column-store item. */ static inline int -__cursor_fix_prev(WT_CURSOR_BTREE *cbt, bool newpage, bool restart) +__cursor_fix_prev(WT_CURSOR_BTREE *cbt, bool newpage, bool restart, bool *key_out_of_boundsp) { + WT_DECL_RET; WT_PAGE *page; WT_SESSION_IMPL *session; @@ -250,6 +257,11 @@ __cursor_fix_prev(WT_CURSOR_BTREE *cbt, bool newpage, bool restart) new_page: restart_read: + if ((ret = __wt_btcur_bounds_early_exit(session, cbt, false, key_out_of_boundsp)) == + WT_NOTFOUND) + WT_STAT_CONN_DATA_INCR(session, cursor_bounds_prev_early_exit); + WT_RET(ret); + /* We only have one slot. */ cbt->slot = 0; @@ -781,7 +793,7 @@ __wt_btcur_prev(WT_CURSOR_BTREE *cbt, bool truncating) WT_ASSERT(session, page != NULL); switch (page->type) { case WT_PAGE_COL_FIX: - ret = __cursor_fix_append_prev(cbt, newpage, restart); + ret = __cursor_fix_append_prev(cbt, newpage, restart, &key_out_of_bounds); break; case WT_PAGE_COL_VAR: ret = __cursor_var_append_prev(cbt, newpage, restart, &skipped, &key_out_of_bounds); @@ -800,7 +812,7 @@ __wt_btcur_prev(WT_CURSOR_BTREE *cbt, bool truncating) if (page != NULL) { switch (page->type) { case WT_PAGE_COL_FIX: - ret = __cursor_fix_prev(cbt, newpage, restart); + ret = __cursor_fix_prev(cbt, newpage, restart, &key_out_of_bounds); break; case WT_PAGE_COL_VAR: ret = __cursor_var_prev(cbt, newpage, restart, &skipped, &key_out_of_bounds); diff --git a/src/third_party/wiredtiger/src/btree/bt_cursor.c b/src/third_party/wiredtiger/src/btree/bt_cursor.c index 40d9337c1d6..9f294f18f2f 100644 --- a/src/third_party/wiredtiger/src/btree/bt_cursor.c +++ b/src/third_party/wiredtiger/src/btree/bt_cursor.c @@ -300,21 +300,24 @@ __wt_cursor_valid(WT_CURSOR_BTREE *cbt, WT_ITEM *key, uint64_t recno, bool *vali * update that's been deleted is not a valid key/value pair). */ if (cbt->ins != NULL) { - if (WT_CURSOR_BOUNDS_SET(&cbt->iface)) { + if (btree->type == BTREE_ROW && WT_CURSOR_BOUNDS_SET(&cbt->iface) && key == NULL) { /* Get the insert list key. */ - if (key == NULL && btree->type == BTREE_ROW) { - tmp_key.data = WT_INSERT_KEY(cbt->ins); - tmp_key.size = WT_INSERT_KEY_SIZE(cbt->ins); - WT_RET(__btcur_bounds_contains_key( - session, &cbt->iface, &tmp_key, WT_RECNO_OOB, &key_out_of_bounds, NULL)); - } else - WT_RET(__btcur_bounds_contains_key( - session, &cbt->iface, key, cbt->recno, &key_out_of_bounds, NULL)); - - /* The key value pair we were trying to return weren't within the given bounds. */ - if (key_out_of_bounds) - return (0); + tmp_key.data = WT_INSERT_KEY(cbt->ins); + tmp_key.size = WT_INSERT_KEY_SIZE(cbt->ins); } + /* + * A number of different scenarios are handled here, we can have a key provided to the + * function for row-store. If there isn't a key for row-store then we need to get it from + * the insert list. The key held on the cursor isn't considered here. Additionally column + * store is handled here by passing the recno. + */ + WT_RET(__btcur_bounds_contains_key(session, &cbt->iface, key == NULL ? &tmp_key : key, + cbt->recno, &key_out_of_bounds, NULL)); + + /* The key value pair we were trying to return weren't within the given bounds. */ + if (key_out_of_bounds) + return (0); + WT_RET(__wt_txn_read_upd_list(session, cbt, cbt->ins->upd)); if (cbt->upd_value->type != WT_UPDATE_INVALID) { if (cbt->upd_value->type == WT_UPDATE_TOMBSTONE) @@ -324,6 +327,19 @@ __wt_cursor_valid(WT_CURSOR_BTREE *cbt, WT_ITEM *key, uint64_t recno, bool *vali } } + /* + * The previous call to the contains key function handles insert list scenarios. If we don't + * have an insert list then we should check again against the recno. We can't check for + * row-store here as the key is extracted later in the function. + */ + if (btree->type != BTREE_ROW) { + WT_RET(__btcur_bounds_contains_key( + session, &cbt->iface, NULL, cbt->recno, &key_out_of_bounds, NULL)); + /* The key value pair we were trying to return weren't within the given bounds. */ + if (key_out_of_bounds) + return (0); + } + /* * If we don't have an insert object, or in the case of column-store, there's an insert object * but no update was visible to us and the key on the page is the same as the insert object's @@ -380,12 +396,6 @@ __wt_cursor_valid(WT_CURSOR_BTREE *cbt, WT_ITEM *key, uint64_t recno, bool *vali if (__wt_cell_type(cell) == WT_CELL_DEL) return (0); - WT_RET(__btcur_bounds_contains_key( - session, &cbt->iface, NULL, cbt->recno, &key_out_of_bounds, NULL)); - /* The key value pair we were trying to return weren't within the given bounds. */ - if (key_out_of_bounds) - return (0); - /* * Check for an update. For column store, modifications are handled with insert lists, so an * insert can have the same key as an on-page or history store object. Setting update here, diff --git a/src/third_party/wiredtiger/src/cursor/cur_std.c b/src/third_party/wiredtiger/src/cursor/cur_std.c index b047c06221c..4afd6533cf1 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_std.c +++ b/src/third_party/wiredtiger/src/cursor/cur_std.c @@ -1187,9 +1187,6 @@ __wt_cursor_bound(WT_CURSOR *cursor, const char *config) CURSOR_API_CALL_CONF(cursor, session, bound, config, cfg, NULL); - if (CUR2BT(cursor)->type == BTREE_COL_FIX) - WT_ERR_MSG(session, EINVAL, "setting bounds is not compatible with fixed column store."); - if (F_ISSET(cursor, WT_CURSTD_PREFIX_SEARCH)) WT_ERR_MSG(session, EINVAL, "setting bounds is not compatible with prefix search."); diff --git a/src/third_party/wiredtiger/test/suite/test_cursor_bound02.py b/src/third_party/wiredtiger/test/suite/test_cursor_bound02.py index 459c9aabd85..f6a73acfea7 100644 --- a/src/third_party/wiredtiger/test/suite/test_cursor_bound02.py +++ b/src/third_party/wiredtiger/test/suite/test_cursor_bound02.py @@ -46,6 +46,7 @@ class test_cursor_bound02(bound_base): key_formats = [ ('string', dict(key_format='S')), ('var', dict(key_format='r')), + ('fix', dict(key_format='r')), ('int', dict(key_format='i')), ('bytes', dict(key_format='u')), ('composite_string', dict(key_format='SSS')), @@ -55,6 +56,7 @@ class test_cursor_bound02(bound_base): value_formats = [ ('string', dict(value_format='S')), + ('fix-byte', dict(value_format='8t')), ('complex-string', dict(value_format='SS')), ] @@ -67,8 +69,10 @@ class test_cursor_bound02(bound_base): def test_bound_api(self): uri = self.uri + self.file_name create_params = 'value_format={},key_format={}'.format(self.value_format, self.key_format) - if self.use_colgroup: + if self.use_colgroup and self.value_format != '8t': create_params += self.gen_colgroup_create_param() + else: + self.use_colgroup = False self.session.create(uri, create_params) # Add in column groups. @@ -138,10 +142,15 @@ class test_cursor_bound02(bound_base): def test_bound_api_reset(self): + # Fixed length bit arrays don't work well with colgroups. + if (self.value_format == '8t' and self.use_colgroup): + return uri = self.uri + self.file_name create_params = 'value_format={},key_format={}'.format(self.value_format, self.key_format) - if self.use_colgroup: + if self.use_colgroup and self.value_format != '8t': create_params += self.gen_colgroup_create_param() + else: + self.use_colgroup = False self.session.create(uri, create_params) # Add in column groups. if self.use_colgroup: @@ -164,7 +173,7 @@ class test_cursor_bound02(bound_base): cursor.reset() self.assertEqual(self.set_bounds(cursor, 99, "lower"), 0) - # Test bound API: Test that cursor reset works the clearing bounds both ways. + # Test bound API: Test that cursor reset works the clearing bounds both ways. self.assertEqual(self.set_bounds(cursor, 50, "lower"), 0) cursor.reset() self.assertEqual(self.set_bounds(cursor, 20, "lower"), 0) @@ -191,10 +200,15 @@ class test_cursor_bound02(bound_base): cursor.reset() def test_bound_api_clear(self): + # Fixed length bit arrays don't work well with colgroups. + if (self.value_format == '8t' and self.use_colgroup): + return uri = self.uri + self.file_name create_params = 'value_format={},key_format={}'.format(self.value_format, self.key_format) - if self.use_colgroup: + if self.use_colgroup and self.value_format != '8t': create_params += self.gen_colgroup_create_param() + else: + self.use_colgroup = False self.session.create(uri, create_params) # Add in column groups. if self.use_colgroup: @@ -213,12 +227,12 @@ class test_cursor_bound02(bound_base): self.assertEqual(cursor.bound("action=clear,bound=lower"), 0) self.assertEqual(self.set_bounds(cursor, 10, "upper"), 0) - # Test bound API: Test that clearing the upper bound works. + # Test bound API: Test that clearing the upper bound works. self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: self.set_bounds(cursor, 99, "lower"), '/Invalid argument/') self.assertEqual(cursor.bound("action=clear,bound=upper"), 0) self.assertEqual(self.set_bounds(cursor, 99, "lower"), 0) - # Test bound API: Test that clearing both of the bounds works. + # Test bound API: Test that clearing both of the bounds works. cursor.reset() self.assertEqual(self.set_bounds(cursor, 50, "upper"), 0) self.assertEqual(cursor.bound("action=clear"), 0) diff --git a/src/third_party/wiredtiger/test/suite/test_cursor_bound03.py b/src/third_party/wiredtiger/test/suite/test_cursor_bound03.py index fcbbb7e4b78..3e7daa3e5fb 100644 --- a/src/third_party/wiredtiger/test/suite/test_cursor_bound03.py +++ b/src/third_party/wiredtiger/test/suite/test_cursor_bound03.py @@ -43,8 +43,8 @@ class test_cursor_bound03(bound_base): ] key_formats = [ - ('string', dict(key_format='S')), ('var', dict(key_format='r')), + ('string', dict(key_format='S')), ('int', dict(key_format='i')), ('bytes', dict(key_format='u')), ('composite_string', dict(key_format='SSS')), @@ -54,8 +54,9 @@ class test_cursor_bound03(bound_base): value_formats = [ ('string', dict(value_format='S')), + ('fix', dict(value_format='8t')) # FIX-ME-WT-9589: Fix bug complex colgroups not returning records within bounds. - # ('complex-string', dict(value_format='SS')), + #('complex-string', dict(value_format='SS')), ] config = [ diff --git a/src/third_party/wiredtiger/test/suite/test_cursor_bound04.py b/src/third_party/wiredtiger/test/suite/test_cursor_bound04.py index b3e6fe0bc27..e3061435731 100644 --- a/src/third_party/wiredtiger/test/suite/test_cursor_bound04.py +++ b/src/third_party/wiredtiger/test/suite/test_cursor_bound04.py @@ -56,6 +56,7 @@ class test_cursor_bound04(bound_base): value_formats = [ ('string', dict(value_format='S')), + ('fix', dict(value_format='8t')) # FIX-ME-WT-9589: Fix bug complex colgroups not returning records within bounds. # ('complex-string', dict(value_format='SS')), ] @@ -82,7 +83,7 @@ class test_cursor_bound04(bound_base): cursor.bound("action=clear,bound=lower") self.assertEqual(cursor.next(), 0) key = cursor.get_key() - self.assertEqual(key, self.check_key(self.start_key)) + self.assertEqual(key, self.check_key(1 if self.flcs else self.start_key)) cursor.reset() # Test bound api: Test lower bound setting with positioned cursor. @@ -114,7 +115,7 @@ class test_cursor_bound04(bound_base): self.set_bounds(cursor, 55, "upper") self.assertEqual(cursor.next(), 0) key = cursor.get_key() - self.assertEqual(key, self.check_key(self.start_key)) + self.assertEqual(key, self.check_key(1 if self.flcs else self.start_key)) cursor.set_key(self.gen_key(60)) self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: self.set_bounds(cursor, 50, "upper"), '/Invalid argument/') cursor.reset() @@ -122,7 +123,7 @@ class test_cursor_bound04(bound_base): self.set_bounds(cursor, 55, "upper") self.assertEqual(cursor.next(), 0) key = cursor.get_key() - self.assertEqual(key, self.check_key(self.start_key)) + self.assertEqual(key, self.check_key(1 if self.flcs else self.start_key)) cursor.set_key(self.gen_key(90)) self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: self.set_bounds(cursor, 50, "upper"), '/Invalid argument/') @@ -131,7 +132,7 @@ class test_cursor_bound04(bound_base): self.set_bounds(cursor, 55, "upper") self.assertEqual(cursor.next(), 0) key = cursor.get_key() - self.assertEqual(key, self.check_key(self.start_key)) + self.assertEqual(key, self.check_key(1 if self.flcs else self.start_key)) cursor.set_key(self.gen_key(10)) self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: self.set_bounds(cursor, 50, "upper"), '/Invalid argument/') @@ -150,7 +151,7 @@ class test_cursor_bound04(bound_base): self.set_bounds(cursor, 55, "upper") self.assertEqual(cursor.next(), 0) key = cursor.get_key() - self.assertEqual(key, self.check_key(self.start_key)) + self.assertEqual(key, self.check_key(1 if self.flcs else self.start_key)) self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: cursor.bound("bound=upper,inclusive=false"), '/Invalid argument/') cursor.reset() @@ -167,9 +168,9 @@ class test_cursor_bound04(bound_base): self.set_bounds(cursor, 55, "upper") self.assertEqual(cursor.next(), 0) key = cursor.get_key() - self.assertEqual(key, self.check_key(self.start_key)) + self.assertEqual(key, self.check_key(1 if self.flcs else self.start_key)) self.assertEqual(cursor.bound("action=clear"), 0) - self.cursor_traversal_bound(cursor, None, None, True, self.end_key - self.start_key) + self.cursor_traversal_bound(cursor, None, None, True, self.end_key - 1 if self.flcs else self.end_key - self.start_key) cursor.reset() cursor.close() @@ -229,7 +230,7 @@ class test_cursor_bound04(bound_base): key = cursor.get_key() self.assertEqual(key, self.check_key(45)) self.assertEqual(cursor.bound("action=clear"), 0) - self.cursor_traversal_bound(cursor, None, None, False, 45 - self.start_key) + self.cursor_traversal_bound(cursor, None, None, False, 45 - self.start_key if not self.flcs else 45 - 1) cursor.reset() self.set_bounds(cursor, 45, "upper") diff --git a/src/third_party/wiredtiger/test/suite/wtbound.py b/src/third_party/wiredtiger/test/suite/wtbound.py index 8e814327f0e..f5c86b57bbf 100644 --- a/src/third_party/wiredtiger/test/suite/wtbound.py +++ b/src/third_party/wiredtiger/test/suite/wtbound.py @@ -108,10 +108,18 @@ class bound_base(wttest.WiredTigerTestCase): end_key = 79 lower_inclusive = True upper_inclusive = True + flcs = False def create_session_and_cursor(self, cursor_config=None): uri = self.uri + self.file_name create_params = 'value_format={},key_format={}'.format(self.value_format, self.key_format) + + if (self.value_format == '8t'): + # Colgroups generation doesn't seem to work with 8t format. + self.use_colgroup = False + if (self.key_format == 'r'): + self.flcs = True + if self.use_colgroup: create_params += self.gen_colgroup_create_param() self.session.create(uri, create_params) @@ -127,7 +135,7 @@ class bound_base(wttest.WiredTigerTestCase): self.session.begin_transaction() for i in range(self.start_key, self.end_key + 1): - cursor[self.gen_key(i)] = self.gen_val("value" + str(i)) + cursor[self.gen_key(i)] = self.gen_val(str(i)) self.session.commit_transaction() if (self.evict): @@ -182,7 +190,8 @@ class bound_base(wttest.WiredTigerTestCase): tuple_val.append(self.recno(i)) elif key == "i": tuple_val.append(i) - + if (self.value_format == '8t'): + return int(int(i) & 0xff) if (len(self.value_format) == 1): return tuple_val[0] else: @@ -226,10 +235,11 @@ class bound_base(wttest.WiredTigerTestCase): def cursor_traversal_bound(self, cursor, lower_key, upper_key, next=None, expected_count=None): if next == None: - next = self.direction + next = self.next start_range = self.start_key end_range = self.end_key + flcs_start_range = start_range if (upper_key): if (upper_key < end_range): @@ -243,6 +253,15 @@ class bound_base(wttest.WiredTigerTestCase): if (not self.lower_inclusive): start_range += 1 + # Special handling for fixed length column store where implicit records may exist. + if (self.flcs): + if (lower_key is not None): + if (lower_key < start_range): + flcs_start_range = lower_key + if (not self.lower_inclusive): + flcs_start_range += 1 + else: + flcs_start_range = 1 count = ret = 0 while True: @@ -269,4 +288,12 @@ class bound_base(wttest.WiredTigerTestCase): if (expected_count != None): self.assertEqual(expected_count, count) else: - self.assertEqual(end_range - start_range + 1, count) + # As a result of fix length column store creating implicit records during eviction we + # have assert that we either walked the expected range or a range with additional + # implicit records. + if (self.flcs): + range_without_implicit = end_range - start_range + 1 + range_with_implicit = end_range - flcs_start_range + 1 + self.assertTrue(count == range_with_implicit or count == range_without_implicit) + else: + self.assertEqual(end_range - start_range + 1, count) -- cgit v1.2.1