summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Chen <luke.chen@mongodb.com>2021-10-05 15:11:58 +1100
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-10-05 04:40:31 +0000
commit434b3b99b0cd5db494d0f6d38bd2ff76f7e4f0b8 (patch)
tree926582772527df4eff0666f1bc7cad3a672456e2
parent97b2d24bef8dea8f6d9e069be6b810c9c0a9b5af (diff)
downloadmongo-434b3b99b0cd5db494d0f6d38bd2ff76f7e4f0b8.tar.gz
Import wiredtiger: 2b1f3d0eec137ceaab33071c1109507c5ebd0b0e from branch mongodb-master
ref: 2e1c641875..2b1f3d0eec for: 5.1.0 WT-7992 Provide API to return the last key in a table regardless of visibility
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_cursor.c10
-rw-r--r--src/third_party/wiredtiger/import.data2
-rw-r--r--src/third_party/wiredtiger/lang/python/wiredtiger.i1
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_backup.c1
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_config.c1
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_ds.c1
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_dump.c1
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_file.c1
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_hs.c1
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_index.c1
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_join.c2
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_log.c1
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_metadata.c1
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_stat.c1
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_std.c46
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_table.c27
-rw-r--r--src/third_party/wiredtiger/src/docs/cursor-ops.dox10
-rw-r--r--src/third_party/wiredtiger/src/docs/spell.ok1
-rw-r--r--src/third_party/wiredtiger/src/include/cursor.h42
-rw-r--r--src/third_party/wiredtiger/src/include/extern.h2
-rw-r--r--src/third_party/wiredtiger/src/include/wiredtiger.in13
-rw-r--r--src/third_party/wiredtiger/src/lsm/lsm_cursor.c1
-rw-r--r--src/third_party/wiredtiger/test/suite/test_cursor17.py236
23 files changed, 381 insertions, 22 deletions
diff --git a/src/third_party/wiredtiger/examples/c/ex_cursor.c b/src/third_party/wiredtiger/examples/c/ex_cursor.c
index ac4fc1d22bc..14b8e866e8f 100644
--- a/src/third_party/wiredtiger/examples/c/ex_cursor.c
+++ b/src/third_party/wiredtiger/examples/c/ex_cursor.c
@@ -38,6 +38,7 @@ int cursor_search_near(WT_CURSOR *cursor);
int cursor_insert(WT_CURSOR *cursor);
int cursor_update(WT_CURSOR *cursor);
int cursor_remove(WT_CURSOR *cursor);
+int cursor_largest_key(WT_CURSOR *cursor);
static const char *home;
@@ -155,6 +156,14 @@ cursor_remove(WT_CURSOR *cursor)
}
/*! [cursor remove] */
+/*! [cursor largest key] */
+int
+cursor_largest_key(WT_CURSOR *cursor)
+{
+ return (cursor->largest_key(cursor));
+}
+/*! [cursor largest key] */
+
int
main(int argc, char *argv[])
{
@@ -197,6 +206,7 @@ main(int argc, char *argv[])
error_check(cursor_search_near(cursor));
error_check(cursor_update(cursor));
error_check(cursor_remove(cursor));
+ error_check(cursor_largest_key(cursor));
error_check(cursor->close(cursor));
/* Note: closing the connection implicitly closes open session(s). */
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data
index f5ec0ccfbb2..5f48424ce4c 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": "2e1c64187513b3afe4a03b3d9d9aac998b6a0c94"
+ "commit": "2b1f3d0eec137ceaab33071c1109507c5ebd0b0e"
}
diff --git a/src/third_party/wiredtiger/lang/python/wiredtiger.i b/src/third_party/wiredtiger/lang/python/wiredtiger.i
index 0105a5a70d6..5d221c6863b 100644
--- a/src/third_party/wiredtiger/lang/python/wiredtiger.i
+++ b/src/third_party/wiredtiger/lang/python/wiredtiger.i
@@ -582,6 +582,7 @@ NOTFOUND_OK(__wt_cursor::remove)
NOTFOUND_OK(__wt_cursor::search)
NOTFOUND_OK(__wt_cursor::update)
NOTFOUND_OK(__wt_cursor::_modify)
+NOTFOUND_OK(__wt_cursor::largest_key)
ANY_OK(__wt_modify::__wt_modify)
ANY_OK(__wt_modify::~__wt_modify)
diff --git a/src/third_party/wiredtiger/src/cursor/cur_backup.c b/src/third_party/wiredtiger/src/cursor/cur_backup.c
index fd416d3c452..820ea49aca0 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_backup.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_backup.c
@@ -268,6 +268,7 @@ __wt_curbackup_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *other,
__wt_cursor_notsup, /* remove */
__wt_cursor_notsup, /* reserve */
__wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__curbackup_close); /* close */
diff --git a/src/third_party/wiredtiger/src/cursor/cur_config.c b/src/third_party/wiredtiger/src/cursor/cur_config.c
index ade673bba41..0fbf1066b27 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_config.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_config.c
@@ -51,6 +51,7 @@ __wt_curconfig_open(
__wt_cursor_notsup, /* remove */
__wt_cursor_notsup, /* reserve */
__wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__curconfig_close);
diff --git a/src/third_party/wiredtiger/src/cursor/cur_ds.c b/src/third_party/wiredtiger/src/cursor/cur_ds.c
index 7139f1a8b08..c3e28dd5f59 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_ds.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_ds.c
@@ -425,6 +425,7 @@ __wt_curds_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owner, con
__curds_remove, /* remove */
__curds_reserve, /* reserve */
__wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__curds_close); /* close */
diff --git a/src/third_party/wiredtiger/src/cursor/cur_dump.c b/src/third_party/wiredtiger/src/cursor/cur_dump.c
index be4c1c7ef34..64e273f801b 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_dump.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_dump.c
@@ -396,6 +396,7 @@ __wt_curdump_create(WT_CURSOR *child, WT_CURSOR *owner, WT_CURSOR **cursorp)
__curdump_remove, /* remove */
__wt_cursor_notsup, /* reserve */
__wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__curdump_close); /* close */
diff --git a/src/third_party/wiredtiger/src/cursor/cur_file.c b/src/third_party/wiredtiger/src/cursor/cur_file.c
index ce54fd23abf..23c0a37776c 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_file.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_file.c
@@ -671,6 +671,7 @@ __curfile_create(WT_SESSION_IMPL *session, WT_CURSOR *owner, const char *cfg[],
__curfile_remove, /* remove */
__curfile_reserve, /* reserve */
__wt_cursor_reconfigure, /* reconfigure */
+ __wt_cursor_largest_key, /* largest_key */
__curfile_cache, /* cache */
__curfile_reopen, /* reopen */
__curfile_close); /* close */
diff --git a/src/third_party/wiredtiger/src/cursor/cur_hs.c b/src/third_party/wiredtiger/src/cursor/cur_hs.c
index 2a2657b828b..00d419915ac 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_hs.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_hs.c
@@ -1097,6 +1097,7 @@ __wt_curhs_open(WT_SESSION_IMPL *session, WT_CURSOR *owner, WT_CURSOR **cursorp)
__curhs_remove, /* remove */
__wt_cursor_notsup, /* reserve */
__wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__curhs_close); /* close */
diff --git a/src/third_party/wiredtiger/src/cursor/cur_index.c b/src/third_party/wiredtiger/src/cursor/cur_index.c
index ea57c060196..c5c17e92453 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_index.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_index.c
@@ -453,6 +453,7 @@ __wt_curindex_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owner,
__wt_cursor_notsup, /* remove */
__wt_cursor_notsup, /* reserve */
__wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__curindex_close); /* close */
diff --git a/src/third_party/wiredtiger/src/cursor/cur_join.c b/src/third_party/wiredtiger/src/cursor/cur_join.c
index 7f00ea9bc3d..b721fe9d0ee 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_join.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_join.c
@@ -576,6 +576,7 @@ __curjoin_entry_member(
__wt_cursor_notsup, /* remove */
__wt_cursor_notsup, /* reserve */
__wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__wt_cursor_notsup); /* close */
@@ -1222,6 +1223,7 @@ __wt_curjoin_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owner, c
__wt_cursor_notsup, /* remove */
__wt_cursor_notsup, /* reserve */
__wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__curjoin_close); /* close */
diff --git a/src/third_party/wiredtiger/src/cursor/cur_log.c b/src/third_party/wiredtiger/src/cursor/cur_log.c
index f40ef6b7d1a..281050785d4 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_log.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_log.c
@@ -340,6 +340,7 @@ __wt_curlog_open(WT_SESSION_IMPL *session, const char *uri, const char *cfg[], W
__wt_cursor_notsup, /* remove */
__wt_cursor_notsup, /* reserve */
__wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__curlog_close); /* close */
diff --git a/src/third_party/wiredtiger/src/cursor/cur_metadata.c b/src/third_party/wiredtiger/src/cursor/cur_metadata.c
index cfd0191a782..f0b04128704 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_metadata.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_metadata.c
@@ -575,6 +575,7 @@ __wt_curmetadata_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owne
__curmetadata_remove, /* remove */
__wt_cursor_notsup, /* reserve */
__wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__curmetadata_close); /* close */
diff --git a/src/third_party/wiredtiger/src/cursor/cur_stat.c b/src/third_party/wiredtiger/src/cursor/cur_stat.c
index cafa0c49b35..ca78b4bff52 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_stat.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_stat.c
@@ -608,6 +608,7 @@ __wt_curstat_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *other, c
__wt_cursor_notsup, /* remove */
__wt_cursor_notsup, /* reserve */
__wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__curstat_close); /* close */
diff --git a/src/third_party/wiredtiger/src/cursor/cur_std.c b/src/third_party/wiredtiger/src/cursor/cur_std.c
index 776ad980d3f..ce683c17698 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_std.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_std.c
@@ -1114,6 +1114,52 @@ err:
}
/*
+ * __wt_cursor_largest_key --
+ * WT_CURSOR->largest_key default implementation..
+ */
+int
+__wt_cursor_largest_key(WT_CURSOR *cursor)
+{
+ WT_DECL_ITEM(key);
+ WT_DECL_RET;
+ WT_SESSION_IMPL *session;
+ bool ignore_tombstone;
+
+ ignore_tombstone = F_ISSET(cursor, WT_CURSTD_IGNORE_TOMBSTONE);
+ CURSOR_API_CALL(cursor, session, largest_key, NULL);
+
+ if (F_ISSET(session->txn, WT_TXN_SHARED_TS_READ))
+ WT_ERR_MSG(session, EINVAL, "largest key cannot be called with a read timestamp");
+
+ WT_ERR(__wt_scr_alloc(session, 0, &key));
+
+ /* Reset the cursor to give up the cursor position. */
+ WT_ERR(cursor->reset(cursor));
+
+ /* Ignore deletion */
+ F_SET(cursor, WT_CURSTD_IGNORE_TOMBSTONE);
+
+ /* Call cursor prev with read uncommitted isolation level. */
+ WT_WITH_TXN_ISOLATION(session, WT_ISO_READ_UNCOMMITTED, ret = cursor->prev(cursor));
+ WT_ERR(ret);
+
+ /* Copy the key as we will reset the cursor after that. */
+ WT_ERR(__wt_buf_set(session, key, cursor->key.data, cursor->key.size));
+ WT_ERR(cursor->reset(cursor));
+ WT_ERR(__wt_buf_set(session, &cursor->key, key->data, key->size));
+ /* Set the key as external. */
+ F_SET(cursor, WT_CURSTD_KEY_EXT);
+
+err:
+ if (!ignore_tombstone)
+ F_CLR(cursor, WT_CURSTD_IGNORE_TOMBSTONE);
+ __wt_scr_free(session, &key);
+ if (ret != 0)
+ WT_TRET(cursor->reset(cursor));
+ API_END_RET(session, ret);
+}
+
+/*
* __wt_cursor_dup_position --
* Set a cursor to another cursor's position.
*/
diff --git a/src/third_party/wiredtiger/src/cursor/cur_table.c b/src/third_party/wiredtiger/src/cursor/cur_table.c
index e4505544544..68776b18ba3 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_table.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_table.c
@@ -102,6 +102,7 @@ __wt_apply_single_idx(WT_SESSION_IMPL *session, WT_INDEX *idx, WT_CURSOR *cur,
__wt_cursor_notsup, /* remove */
__wt_cursor_notsup, /* reserve */
__wt_cursor_reconfigure_notsup, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__wt_cursor_notsup); /* close */
@@ -789,6 +790,31 @@ err:
}
/*
+ * __curtable_largest_key --
+ * WT_CURSOR->largest_key method for the table cursor type.
+ */
+static int
+__curtable_largest_key(WT_CURSOR *cursor)
+{
+ WT_CURSOR *primary;
+ WT_CURSOR_TABLE *ctable;
+ WT_DECL_RET;
+ WT_SESSION_IMPL *session;
+
+ ctable = (WT_CURSOR_TABLE *)cursor;
+ JOINABLE_CURSOR_API_CALL(cursor, session, largest_key, NULL);
+
+ WT_ERR(cursor->reset(cursor));
+ primary = *ctable->cg_cursors;
+ WT_ERR(primary->largest_key(primary));
+
+err:
+ if (ret != 0)
+ WT_TRET(cursor->reset(cursor));
+ API_END_RET(session, ret);
+}
+
+/*
* __curtable_close --
* WT_CURSOR->close method for the table cursor type.
*/
@@ -968,6 +994,7 @@ __wt_curtable_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owner,
__curtable_remove, /* remove */
__curtable_reserve, /* reserve */
__wt_cursor_reconfigure, /* reconfigure */
+ __curtable_largest_key, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__curtable_close); /* close */
diff --git a/src/third_party/wiredtiger/src/docs/cursor-ops.dox b/src/third_party/wiredtiger/src/docs/cursor-ops.dox
index c9d75295ddc..82b763b563f 100644
--- a/src/third_party/wiredtiger/src/docs/cursor-ops.dox
+++ b/src/third_party/wiredtiger/src/docs/cursor-ops.dox
@@ -103,6 +103,16 @@ fail with ::WT_DUPLICATE_KEY if the record previously exists, and
WT_CURSOR::update and WT_CURSOR::remove will fail with ::WT_NOTFOUND if the
record does not previously exist.
+@snippet ex_cursor.c cursor largest key
+
+The WT_SESSION::largest_key \c gets the largest key in a table regardless of
+visibility.
+
+It can only be called without a read timestamp, otherwise it returns an invalid
+argument error. Any following prev or next calls will behave as if they were
+invoked on an unpositioned cursor no matter the largest key call is successful
+or not.
+
@section cursor_error Cursor position after error
After any cursor handle method failure, the cursor's position is
diff --git a/src/third_party/wiredtiger/src/docs/spell.ok b/src/third_party/wiredtiger/src/docs/spell.ok
index f34eace96d9..6a5b7f8dd5d 100644
--- a/src/third_party/wiredtiger/src/docs/spell.ok
+++ b/src/third_party/wiredtiger/src/docs/spell.ok
@@ -658,6 +658,7 @@ unescaped
unicode
uninstall
unittest
+unpositioned
untyped
uri
useconds
diff --git a/src/third_party/wiredtiger/src/include/cursor.h b/src/third_party/wiredtiger/src/include/cursor.h
index 569da6aabaa..85797573e23 100644
--- a/src/third_party/wiredtiger/src/include/cursor.h
+++ b/src/third_party/wiredtiger/src/include/cursor.h
@@ -12,27 +12,27 @@
/*
* Initialize a static WT_CURSOR structure.
*/
-#define WT_CURSOR_STATIC_INIT(n, get_key, get_value, set_key, set_value, compare, equals, next, \
- prev, reset, search, search_near, insert, modify, update, remove, reserve, reconfigure, cache, \
- reopen, close) \
- static const WT_CURSOR n = { \
- NULL, /* session */ \
- NULL, /* uri */ \
- NULL, /* key_format */ \
- NULL, /* value_format */ \
- get_key, get_value, set_key, set_value, compare, equals, next, prev, reset, search, \
- search_near, insert, modify, update, remove, reserve, close, reconfigure, cache, reopen, \
- 0, /* uri_hash */ \
- {NULL, NULL}, /* TAILQ_ENTRY q */ \
- 0, /* recno key */ \
- {0}, /* recno raw buffer */ \
- NULL, /* json_private */ \
- NULL, /* lang_private */ \
- {NULL, 0, NULL, 0, 0}, /* WT_ITEM key */ \
- {NULL, 0, NULL, 0, 0}, /* WT_ITEM value */ \
- 0, /* int saved_err */ \
- NULL, /* internal_uri */ \
- 0 /* uint32_t flags */ \
+#define WT_CURSOR_STATIC_INIT(n, get_key, get_value, set_key, set_value, compare, equals, next, \
+ prev, reset, search, search_near, insert, modify, update, remove, reserve, reconfigure, \
+ largest_key, cache, reopen, close) \
+ static const WT_CURSOR n = { \
+ NULL, /* session */ \
+ NULL, /* uri */ \
+ NULL, /* key_format */ \
+ NULL, /* value_format */ \
+ get_key, get_value, set_key, set_value, compare, equals, next, prev, reset, search, \
+ search_near, insert, modify, update, remove, reserve, close, reconfigure, largest_key, \
+ cache, reopen, 0, /* uri_hash */ \
+ {NULL, NULL}, /* TAILQ_ENTRY q */ \
+ 0, /* recno key */ \
+ {0}, /* recno raw buffer */ \
+ NULL, /* json_private */ \
+ NULL, /* lang_private */ \
+ {NULL, 0, NULL, 0, 0}, /* WT_ITEM key */ \
+ {NULL, 0, NULL, 0, 0}, /* WT_ITEM value */ \
+ 0, /* int saved_err */ \
+ NULL, /* internal_uri */ \
+ 0 /* uint32_t flags */ \
}
struct __wt_cursor_backup {
diff --git a/src/third_party/wiredtiger/src/include/extern.h b/src/third_party/wiredtiger/src/include/extern.h
index 266762fe94f..0d7a550094c 100644
--- a/src/third_party/wiredtiger/src/include/extern.h
+++ b/src/third_party/wiredtiger/src/include/extern.h
@@ -577,6 +577,8 @@ extern int __wt_cursor_key_order_init(WT_CURSOR_BTREE *cbt)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_cursor_kv_not_set(WT_CURSOR *cursor, bool key) WT_GCC_FUNC_DECL_ATTRIBUTE((cold))
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_cursor_largest_key(WT_CURSOR *cursor)
+ WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_cursor_modify_notsup(WT_CURSOR *cursor, WT_MODIFY *entries, int nentries)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_cursor_modify_value_format_notsup(WT_CURSOR *cursor, WT_MODIFY *entries,
diff --git a/src/third_party/wiredtiger/src/include/wiredtiger.in b/src/third_party/wiredtiger/src/include/wiredtiger.in
index df084165b41..44eb86b1a32 100644
--- a/src/third_party/wiredtiger/src/include/wiredtiger.in
+++ b/src/third_party/wiredtiger/src/include/wiredtiger.in
@@ -661,6 +661,19 @@ struct __wt_cursor {
*/
int __F(reconfigure)(WT_CURSOR *cursor, const char *config);
+ /*!
+ * Get the largest key of the cursor regardless of visibility.
+ * The cursor is not positioned after calling this api. Only supported by data cursors.
+ *
+ * @snippet ex_all.c Reset the cursor
+ *
+ * @param cursor the cursor handle
+ * @errors
+ * If \c read_timestamp is set, EINVAL is returned.
+ * Also, calling \c WT_CURSOR::get_key after this api call returns EINVAL.
+ */
+ int __F(largest_key)(WT_CURSOR *cursor);
+
/*
* Protected fields, only to be used by cursor implementations.
*/
diff --git a/src/third_party/wiredtiger/src/lsm/lsm_cursor.c b/src/third_party/wiredtiger/src/lsm/lsm_cursor.c
index 4c3aa2a3204..f1503d9bbf3 100644
--- a/src/third_party/wiredtiger/src/lsm/lsm_cursor.c
+++ b/src/third_party/wiredtiger/src/lsm/lsm_cursor.c
@@ -1685,6 +1685,7 @@ __wt_clsm_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owner, cons
__clsm_remove, /* remove */
__clsm_reserve, /* reserve */
__wt_cursor_reconfigure, /* reconfigure */
+ __wt_cursor_notsup, /* largest_key */
__wt_cursor_notsup, /* cache */
__wt_cursor_reopen_notsup, /* reopen */
__wt_clsm_close); /* close */
diff --git a/src/third_party/wiredtiger/test/suite/test_cursor17.py b/src/third_party/wiredtiger/test/suite/test_cursor17.py
new file mode 100644
index 00000000000..322b82a65f8
--- /dev/null
+++ b/src/third_party/wiredtiger/test/suite/test_cursor17.py
@@ -0,0 +1,236 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-present MongoDB, Inc.
+# Public Domain 2008-2014 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# test_cursor17.py
+# Test the largest_key interface under various scenarios.
+#
+import wttest
+import wiredtiger
+from wtdataset import SimpleDataSet, ComplexDataSet, ComplexLSMDataSet
+from wtscenario import make_scenarios
+
+class test_cursor17(wttest.WiredTigerTestCase):
+ tablename = 'test_cursor17'
+
+ # Enable the lsm tests once it is supported.
+ types = [
+ ('file-row', dict(type='file:', keyformat='i', valueformat='i', dataset=SimpleDataSet)),
+ ('table-row', dict(type='table:', keyformat='i', valueformat='i', dataset=SimpleDataSet)),
+ ('file-var', dict(type='file:', keyformat='r', valueformat='i', dataset=SimpleDataSet)),
+ ('table-var', dict(type='table:', keyformat='r', valueformat='i', dataset=SimpleDataSet)),
+ ('file-fix', dict(type='file:', keyformat='r', valueformat='8t', dataset=SimpleDataSet)),
+ # ('lsm', dict(type='lsm:', keyformat='i', valueformat='i', dataset=SimpleDataSet)),
+ ('table-r-complex', dict(type='table:', keyformat='r', valueformat=None,
+ dataset=ComplexDataSet)),
+ # ('table-i-complex-lsm', dict(type='table:', keyformat='i', valueformat=None,
+ # dataset=ComplexLSMDataSet)),
+ ]
+
+ scenarios = make_scenarios(types)
+
+ def populate(self, rownum):
+ if self.valueformat != None:
+ self.ds = self.dataset(self, self.type + self.tablename, rownum, key_format=self.keyformat, value_format=self.valueformat)
+ else:
+ self.ds = self.dataset(self, self.type + self.tablename, rownum, key_format=self.keyformat)
+ self.ds.populate()
+
+ def test_globally_deleted_key(self):
+ self.populate(100)
+
+ # Delete the largest key.
+ cursor = self.session.open_cursor(self.type + self.tablename, None)
+ self.session.begin_transaction()
+ cursor.set_key(100)
+ self.assertEqual(cursor.remove(), 0)
+ self.session.commit_transaction()
+
+ # Verify the key is not visible.
+ self.session.begin_transaction()
+ cursor.set_key(100)
+ if self.valueformat != '8t':
+ self.assertEqual(cursor.search(), wiredtiger.WT_NOTFOUND)
+ else:
+ self.assertEqual(cursor.search(), 0)
+ self.session.rollback_transaction()
+
+ # Verify the largest key.
+ self.session.begin_transaction()
+ self.assertEqual(cursor.largest_key(), 0)
+ self.assertEqual(cursor.get_key(), 100)
+ self.session.rollback_transaction()
+
+ # Verify the key is still not visible after the largest call.
+ self.session.begin_transaction()
+ cursor.set_key(100)
+ if self.valueformat != '8t':
+ self.assertEqual(cursor.search(), wiredtiger.WT_NOTFOUND)
+ else:
+ self.assertEqual(cursor.search(), 0)
+ self.session.rollback_transaction()
+
+ # Use evict cursor to evict the key from memory.
+ evict_cursor = self.session.open_cursor(self.type + self.tablename, None, "debug=(release_evict)")
+ evict_cursor.set_key(100)
+ if self.valueformat != '8t':
+ self.assertEquals(evict_cursor.search(), wiredtiger.WT_NOTFOUND)
+ else:
+ self.assertEquals(evict_cursor.search(), 0)
+ evict_cursor.close()
+
+ # Verify the largest key changed.
+ self.session.begin_transaction()
+ self.assertEqual(cursor.largest_key(), 0)
+ if self.valueformat != '8t':
+ self.assertEqual(cursor.get_key(), 99)
+ else:
+ self.assertEquals(cursor.get_key(), 100)
+ self.session.rollback_transaction()
+
+ def test_uncommitted_insert(self):
+ self.populate(100)
+
+ session2 = self.setUpSessionOpen(self.conn)
+ cursor2 = session2.open_cursor(self.type + self.tablename, None)
+ session2.begin_transaction()
+ cursor2[101] = self.ds.value(101)
+
+ cursor = self.session.open_cursor(self.type + self.tablename, None)
+
+ # Verify the largest key.
+ self.session.begin_transaction()
+ self.assertEqual(cursor.largest_key(), 0)
+ self.assertEqual(cursor.get_key(), 101)
+ self.session.rollback_transaction()
+
+ session2.rollback_transaction()
+
+ def test_read_timestamp(self):
+ self.populate(100)
+
+ cursor = self.session.open_cursor(self.type + self.tablename, None)
+ self.session.begin_transaction('read_timestamp=' + self.timestamp_str(5))
+ # Expect the largest key to throw.
+ with self.expectedStderrPattern("largest key cannot be called with a read timestamp"):
+ try:
+ cursor.largest_key()
+ except wiredtiger.WiredTigerError as e:
+ gotException = True
+ self.pr('got expected exception: ' + str(e))
+ self.assertTrue(str(e).find('nvalid argument') >= 0)
+ self.assertTrue(gotException, msg = 'expected exception')
+ self.session.rollback_transaction()
+
+ def test_not_positioned(self):
+ self.populate(100)
+
+ cursor = self.session.open_cursor(self.type + self.tablename, None)
+ # Verify the largest key.
+ self.session.begin_transaction()
+ self.assertEqual(cursor.largest_key(), 0)
+ self.assertEqual(cursor.get_key(), 100)
+
+ # Call prev
+ self.assertEqual(cursor.prev(), 0)
+ self.assertEqual(cursor.get_key(), 100)
+
+ # Verify the largest key again.
+ self.assertEqual(cursor.largest_key(), 0)
+ self.assertEqual(cursor.get_key(), 100)
+
+ self.assertEqual(cursor.next(), 0)
+ self.assertEqual(cursor.get_key(), 1)
+ self.session.rollback_transaction()
+
+ def test_get_value(self):
+ self.populate(100)
+
+ cursor = self.session.open_cursor(self.type + self.tablename, None)
+ # Verify the largest key.
+ self.session.begin_transaction()
+ self.assertEqual(cursor.largest_key(), 0)
+ self.assertEqual(cursor.get_key(), 100)
+ with self.expectedStderrPattern("requires value be set"):
+ try:
+ cursor.get_value()
+ except wiredtiger.WiredTigerError as e:
+ gotException = True
+ self.pr('got expected exception: ' + str(e))
+ self.assertTrue(str(e).find('nvalid argument') >= 0)
+ self.assertTrue(gotException, msg = 'expected exception')
+ self.session.rollback_transaction()
+
+ def test_empty_table(self):
+ self.populate(0)
+
+ cursor = self.session.open_cursor(self.type + self.tablename, None)
+ # Verify the largest key.
+ self.session.begin_transaction()
+ self.assertEquals(cursor.largest_key(), wiredtiger.WT_NOTFOUND)
+ self.session.rollback_transaction()
+
+ def test_fast_truncate(self):
+ self.populate(100)
+
+ # evict all the pages
+ evict_cursor = self.session.open_cursor(self.type + self.tablename, None, "debug=(release_evict)")
+ self.session.begin_transaction()
+ for i in range(1, 101):
+ evict_cursor.set_key(i)
+ self.assertEquals(evict_cursor.search(), 0)
+ self.session.rollback_transaction()
+ evict_cursor.close()
+
+ # truncate
+ cursor = self.session.open_cursor(self.type + self.tablename, None)
+ self.session.begin_transaction()
+ cursor.set_key(1)
+ self.session.truncate(None, cursor, None, None)
+ self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(5))
+
+ # verify the largest key
+ self.session.begin_transaction()
+ self.assertEqual(cursor.largest_key(), 0)
+ self.assertEqual(cursor.get_key(), 100)
+ self.session.rollback_transaction()
+
+ def test_slow_truncate(self):
+ self.populate(100)
+
+ # truncate
+ cursor = self.session.open_cursor(self.type + self.tablename, None)
+ self.session.begin_transaction()
+ cursor.set_key(100)
+ self.session.truncate(None, cursor, None, None)
+ self.session.commit_transaction('commit_timestamp=' + self.timestamp_str(5))
+
+ # verify the largest key
+ self.session.begin_transaction()
+ self.assertEqual(cursor.largest_key(), 0)
+ self.assertEqual(cursor.get_key(), 100)
+ self.session.rollback_transaction()