diff options
author | Etienne Petrel <etienne.petrel@mongodb.com> | 2023-01-16 21:21:37 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-01-16 22:01:30 +0000 |
commit | bee900479c804e95b1911b2d52649979339b337c (patch) | |
tree | 20175efc6fd652f929e90eb70eac28d1fca52a35 | |
parent | 92ea08ca32da862891326ce503f7d2427a439361 (diff) | |
download | mongo-bee900479c804e95b1911b2d52649979339b337c.tar.gz |
Import wiredtiger: 5133661db11a85871a33305941cd185992aadf1b from branch mongodb-master
ref: dcf227fa94..5133661db1
for: 6.3.0-rc0
WT-9786 API improvements for cursor get key and get value
28 files changed, 576 insertions, 24 deletions
diff --git a/src/third_party/wiredtiger/examples/c/ex_all.c b/src/third_party/wiredtiger/examples/c/ex_all.c index ccbc71c5215..3c325b0f62a 100644 --- a/src/third_party/wiredtiger/examples/c/ex_all.c +++ b/src/third_party/wiredtiger/examples/c/ex_all.c @@ -192,6 +192,14 @@ cursor_ops(WT_SESSION *session) } { + /*! [Get the raw key and value for the current record.] */ + WT_ITEM key; /* Get the raw key and value for the current record. */ + WT_ITEM value; /* Get the raw key and value for the current record. */ + error_check(cursor->get_raw_key_value(cursor, &key, &value)); + /*! [Get the raw key and value for the current record.] */ + } + + { /*! [Set the cursor's raw value] */ WT_ITEM value; /* Set the cursor's raw value. */ value.data = "another value"; diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index 2785ed446a9..99dfa5d5bea 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": "dcf227fa94d49f9c930ee52bfb25a733d77f5dbd" + "commit": "5133661db11a85871a33305941cd185992aadf1b" } diff --git a/src/third_party/wiredtiger/lang/python/wiredtiger.i b/src/third_party/wiredtiger/lang/python/wiredtiger.i index 7108f4219d3..18145f6a157 100644 --- a/src/third_party/wiredtiger/lang/python/wiredtiger.i +++ b/src/third_party/wiredtiger/lang/python/wiredtiger.i @@ -630,6 +630,9 @@ COMPARE_NOTFOUND_OK(__wt_cursor::_search_near) %ignore __wt_modify::offset; %ignore __wt_modify::size; +/* Replace get_raw_key_value method with a Python equivalent */ +%ignore __wt_cursor::get_raw_key_value; + /* Next, override methods that return integers via arguments. */ %ignore __wt_cursor::compare(WT_CURSOR *, WT_CURSOR *, int *); %ignore __wt_cursor::equals(WT_CURSOR *, WT_CURSOR *, int *); @@ -646,8 +649,10 @@ OVERRIDE_METHOD(__wt_cursor, WT_CURSOR, search_near, (self)) %typemap(in,numinputs=0) (char **datap, int *sizep) (char *data, int size) { $1 = &data; $2 = &size; } %typemap(in,numinputs=0) (char **charp, int *sizep) (char *data, int size) { $1 = &data; $2 = &size; } %typemap(in,numinputs=0) (char **metadatap, int *metadatasizep, char **datap, int *datasizep) (char *metadata, int metadatasize, char *data, int datasize) { $1 = &metadata; $2 = &metadatasize; $3 = &data; $4 = &datasize; } +%typemap(in,numinputs=0) (char **key_datap, int *key_sizep, char **value_datap, int *value_sizep) (char *key_data, int key_size, char *value_data, int value_size) { $1 = &key_data; $2 = &key_size; $3 = &value_data; $4 = &value_size; } %typemap(frearg) (char **datap, int *sizep) ""; %typemap(frearg) (char **metadatap, int *metadatasizep, char **datap, int *datasizep) ""; +%typemap(frearg) (char **key_datap, int *key_sizep, char **value_datap, int *value_sizep) ""; %typemap(argout) (char **charp, int *sizep) { if (*$1) $result = PyUnicode_FromStringAndSize(*$1, *$2); @@ -665,6 +670,20 @@ OVERRIDE_METHOD(__wt_cursor, WT_CURSOR, search_near, (self)) $result = metadata; data = PyBytes_FromStringAndSize(*$3, *$4); $result = SWIG_Python_AppendOutput($result, data); + } else { + SWIG_exception_fail(SWIG_AttributeError, "invalid pointer argument"); + } +} + +%typemap(argout)(char **key_datap, int *key_sizep, char **value_datap, int *value_sizep) ( + PyObject *key_data, PyObject *value_data) { + if (*$1 && *$3) { + key_data = PyBytes_FromStringAndSize(*$1, *$2); + $result = key_data; + value_data = PyBytes_FromStringAndSize(*$3, *$4); + $result = SWIG_Python_AppendOutput($result, value_data); + } else { + SWIG_exception_fail(SWIG_AttributeError, "invalid pointer argument"); } } @@ -781,6 +800,18 @@ typedef int int_void; return (ret); } + int_void _get_raw_key_value(char **key_datap, int *key_sizep, char **value_datap, int *value_sizep) { + WT_ITEM k, v; + int ret = $self->get_raw_key_value($self, &k, &v); + if (ret == 0) { + *key_datap = (char *)k.data; + *key_sizep = (int)k.size; + *value_datap = (char *)v.data; + *value_sizep = (int)v.size; + } + return (ret); + } + int_void _get_value(char **datap, int *sizep) { WT_ITEM v; int ret = $self->get_value($self, &v); @@ -927,6 +958,17 @@ typedef int int_void; else: return unpack(self.value_format, self._get_value()) + def get_raw_key_value(self): + '''get_raw_key_value(self) -> object + + @copydoc WT_CURSOR::get_raw_key_value + Returns a tuple containing both the key and the value.''' + + result = self._get_raw_key_value() + keys = unpack(self.key_format, result[0]) + values = unpack(self.value_format, result[1]) + return (keys[0], values[0]) + def set_key(self, *args): '''set_key(self) -> None diff --git a/src/third_party/wiredtiger/src/cursor/cur_backup.c b/src/third_party/wiredtiger/src/cursor/cur_backup.c index 008bdc646cd..43c6436b993 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_backup.c +++ b/src/third_party/wiredtiger/src/cursor/cur_backup.c @@ -253,6 +253,7 @@ __wt_curbackup_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *other, { WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __wt_cursor_get_value_notsup, /* get-value */ + __wt_cursor_get_raw_key_value_notsup, /* get-raw-key-value */ __wt_cursor_set_key_notsup, /* set-key */ __wt_cursor_set_value_notsup, /* set-value */ __wt_cursor_compare_notsup, /* compare */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_config.c b/src/third_party/wiredtiger/src/cursor/cur_config.c index f01f05ffe7a..e9be107ef50 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_config.c +++ b/src/third_party/wiredtiger/src/cursor/cur_config.c @@ -36,6 +36,7 @@ __wt_curconfig_open( { WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __wt_cursor_get_value, /* get-value */ + __wt_cursor_get_raw_key_value, /* get-raw-key-value */ __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __wt_cursor_compare_notsup, /* compare */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_ds.c b/src/third_party/wiredtiger/src/cursor/cur_ds.c index 9f1e01f14b5..5750c270362 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_ds.c +++ b/src/third_party/wiredtiger/src/cursor/cur_ds.c @@ -432,6 +432,7 @@ __wt_curds_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owner, con { WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __wt_cursor_get_value, /* get-value */ + __wt_cursor_get_raw_key_value, /* get-raw-key-value */ __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __curds_compare, /* compare */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_dump.c b/src/third_party/wiredtiger/src/cursor/cur_dump.c index 46ba23b7e0e..1e05d63f8a8 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_dump.c +++ b/src/third_party/wiredtiger/src/cursor/cur_dump.c @@ -394,6 +394,7 @@ __wt_curdump_create(WT_CURSOR *child, WT_CURSOR *owner, WT_CURSOR **cursorp) { WT_CURSOR_STATIC_INIT(iface, __curdump_get_key, /* get-key */ __curdump_get_value, /* get-value */ + __wt_cursor_get_raw_key_value_notsup, /* get-raw-key-value */ __curdump_set_key, /* set-key */ __curdump_set_value, /* set-value */ __wt_cursor_compare_notsup, /* compare */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_file.c b/src/third_party/wiredtiger/src/cursor/cur_file.c index 49781ec79b4..5f8edb1d2c6 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_file.c +++ b/src/third_party/wiredtiger/src/cursor/cur_file.c @@ -943,6 +943,7 @@ __curfile_create(WT_SESSION_IMPL *session, WT_CURSOR *owner, const char *cfg[], { WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __wt_cursor_get_value, /* get-value */ + __wt_cursor_get_raw_key_value, /* get-raw-key-value */ __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __curfile_compare, /* compare */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_hs.c b/src/third_party/wiredtiger/src/cursor/cur_hs.c index b73d4e344ee..fe4ac858d4e 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_hs.c +++ b/src/third_party/wiredtiger/src/cursor/cur_hs.c @@ -1232,6 +1232,7 @@ __wt_curhs_open(WT_SESSION_IMPL *session, WT_CURSOR *owner, WT_CURSOR **cursorp) { WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __wt_cursor_get_value, /* get-value */ + __wt_cursor_get_raw_key_value_notsup, /* get-raw-key-value */ __curhs_set_key, /* set-key */ __curhs_set_value, /* set-value */ __curhs_compare, /* compare */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_index.c b/src/third_party/wiredtiger/src/cursor/cur_index.c index 91c9a423000..2162db2232e 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_index.c +++ b/src/third_party/wiredtiger/src/cursor/cur_index.c @@ -562,6 +562,7 @@ __wt_curindex_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owner, { WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __curindex_get_value, /* get-value */ + __wt_cursor_get_raw_key_value_notsup, /* get-raw-key-value */ __wt_cursor_set_key, /* set-key */ __curindex_set_value, /* set-value */ __curindex_compare, /* compare */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_join.c b/src/third_party/wiredtiger/src/cursor/cur_join.c index 2fe64b4f7a4..76710450fa4 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_join.c +++ b/src/third_party/wiredtiger/src/cursor/cur_join.c @@ -561,6 +561,7 @@ __curjoin_entry_member( WT_CURSOR *c; WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __wt_cursor_get_value, /* get-value */ + __wt_cursor_get_raw_key_value, /* get-raw-key-value */ __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __wt_cursor_compare_notsup, /* compare */ @@ -1210,6 +1211,7 @@ __wt_curjoin_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owner, c { WT_CURSOR_STATIC_INIT(iface, __curjoin_get_key, /* get-key */ __curjoin_get_value, /* get-value */ + __wt_cursor_get_raw_key_value_notsup, /* get-raw-key-value */ __wt_cursor_set_key_notsup, /* set-key */ __wt_cursor_set_value_notsup, /* set-value */ __wt_cursor_compare_notsup, /* compare */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_log.c b/src/third_party/wiredtiger/src/cursor/cur_log.c index 8361012543f..c5a90dc9c48 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_log.c +++ b/src/third_party/wiredtiger/src/cursor/cur_log.c @@ -327,6 +327,7 @@ __wt_curlog_open(WT_SESSION_IMPL *session, const char *uri, const char *cfg[], W WT_CONNECTION_IMPL *conn; WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __wt_cursor_get_value, /* get-value */ + __wt_cursor_get_raw_key_value, /* get-raw-key-value */ __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __curlog_compare, /* compare */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_metadata.c b/src/third_party/wiredtiger/src/cursor/cur_metadata.c index 5b2ecbebda2..e830370b4ea 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_metadata.c +++ b/src/third_party/wiredtiger/src/cursor/cur_metadata.c @@ -560,6 +560,7 @@ __wt_curmetadata_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owne { WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __wt_cursor_get_value, /* get-value */ + __wt_cursor_get_raw_key_value, /* get-raw-key-value */ __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __curmetadata_compare, /* compare */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_stat.c b/src/third_party/wiredtiger/src/cursor/cur_stat.c index bf8e1351e54..1908676eb1d 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_stat.c +++ b/src/third_party/wiredtiger/src/cursor/cur_stat.c @@ -601,6 +601,7 @@ __wt_curstat_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *other, c WT_CONNECTION_IMPL *conn; WT_CURSOR_STATIC_INIT(iface, __curstat_get_key, /* get-key */ __curstat_get_value, /* get-value */ + __wt_cursor_get_raw_key_value_notsup, /* get-raw-key-value */ __curstat_set_key, /* set-key */ __curstat_set_value, /* set-value */ __wt_cursor_compare_notsup, /* compare */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_std.c b/src/third_party/wiredtiger/src/cursor/cur_std.c index d68fbaf2a26..229568a71f6 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_std.c +++ b/src/third_party/wiredtiger/src/cursor/cur_std.c @@ -74,6 +74,18 @@ __wt_cursor_get_value_notsup(WT_CURSOR *cursor, ...) } /* + * __wt_cursor_get_raw_key_value_notsup -- + * WT_CURSOR.get_raw_key_value not-supported. + */ +int +__wt_cursor_get_raw_key_value_notsup(WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value) +{ + WT_UNUSED(key); + WT_UNUSED(value); + return (__wt_cursor_notsup(cursor)); +} + +/* * __wt_cursor_set_key_notsup -- * WT_CURSOR.set_key not-supported. */ @@ -568,6 +580,42 @@ err: } /* + * __wt_cursor_get_raw_key_value -- + * WT_CURSOR->get_raw_key_value default implementation + */ +int +__wt_cursor_get_raw_key_value(WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value) +{ + WT_DECL_RET; + WT_SESSION_IMPL *session; + + CURSOR_API_CALL(cursor, session, get_value, NULL); + + if ((key != NULL) && !F_ISSET(cursor, WT_CURSTD_KEY_SET)) + WT_ERR(__wt_cursor_kv_not_set(cursor, true)); + + if ((value != NULL) && !F_ISSET(cursor, WT_CURSTD_VALUE_SET)) + WT_ERR(__wt_cursor_kv_not_set(cursor, false)); + + /* Force an allocated copy when using cursor copy debug. */ + if (FLD_ISSET(S2C(session)->debug_flags, WT_CONN_DEBUG_CURSOR_COPY)) + WT_ERR(__wt_buf_grow(session, &cursor->value, cursor->value.size)); + + if (key != NULL) { + key->data = cursor->key.data; + key->size = cursor->key.size; + } + + if (value != NULL) { + value->data = cursor->value.data; + value->size = cursor->value.size; + } + +err: + API_END_RET(session, ret); +} + +/* * __wt_cursor_set_value -- * WT_CURSOR->set_value default implementation. */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_table.c b/src/third_party/wiredtiger/src/cursor/cur_table.c index 418707c44fb..c132c76fd56 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_table.c +++ b/src/third_party/wiredtiger/src/cursor/cur_table.c @@ -87,6 +87,7 @@ __wt_apply_single_idx(WT_SESSION_IMPL *session, WT_INDEX *idx, WT_CURSOR *cur, { WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __wt_cursor_get_value, /* get-value */ + __wt_cursor_get_raw_key_value, /* get-raw-key-value */ __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __wt_cursor_compare_notsup, /* compare */ @@ -1046,6 +1047,7 @@ __wt_curtable_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owner, { WT_CURSOR_STATIC_INIT(iface, __wt_curtable_get_key, /* get-key */ __wt_curtable_get_value, /* get-value */ + __wt_cursor_get_raw_key_value_notsup, /* get-raw-key-value */ __wt_curtable_set_key, /* set-key */ __wt_curtable_set_value, /* set-value */ __curtable_compare, /* compare */ diff --git a/src/third_party/wiredtiger/src/cursor/cur_version.c b/src/third_party/wiredtiger/src/cursor/cur_version.c index c1387993aac..021a9d07527 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_version.c +++ b/src/third_party/wiredtiger/src/cursor/cur_version.c @@ -601,6 +601,7 @@ __wt_curversion_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owner { WT_CURSOR_STATIC_INIT(iface, __curversion_get_key, /* get-key */ __curversion_get_value, /* get-value */ + __wt_cursor_get_raw_key_value_notsup, /* get-raw-key-value */ __curversion_set_key, /* set-key */ __wt_cursor_set_value_notsup, /* set-value */ __wt_cursor_compare_notsup, /* compare */ diff --git a/src/third_party/wiredtiger/src/docs/cursors.dox b/src/third_party/wiredtiger/src/docs/cursors.dox index 5616e6b3a80..237141aa5d1 100644 --- a/src/third_party/wiredtiger/src/docs/cursors.dox +++ b/src/third_party/wiredtiger/src/docs/cursors.dox @@ -70,6 +70,9 @@ WT_CURSOR::set_key and WT_CURSOR::set_value in raw mode, the WT_ITEM should be equivalent to calling WT_EXTENSION_API::struct_pack for the cursor's \c key_format or \c value_format, respectively. +WT_CURSOR::get_raw_key_value can be used to obtain both the key and value +in raw format in a single function call. + The @ex_ref{ex_schema.c} example creates a table where the value format is \c "5sHq", where the initial string is the country, the short is a year, and the long is a population. diff --git a/src/third_party/wiredtiger/src/include/cursor.h b/src/third_party/wiredtiger/src/include/cursor.h index e69808e67f0..d701d7f2a4f 100644 --- a/src/third_party/wiredtiger/src/include/cursor.h +++ b/src/third_party/wiredtiger/src/include/cursor.h @@ -12,29 +12,29 @@ /* * 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, \ - largest_key, bound, cache, reopen, checkpoint_id, 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, checkpoint_id, close, largest_key, \ - reconfigure, bound, 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 */ \ - {NULL, 0, NULL, 0, 0}, /* WT_ITEM lower bound */ \ - {NULL, 0, NULL, 0, 0}, /* WT_ITEM upper bound */ \ - 0 /* uint32_t flags */ \ +#define WT_CURSOR_STATIC_INIT(n, get_key, get_value, get_raw_key_value, set_key, set_value, \ + compare, equals, next, prev, reset, search, search_near, insert, modify, update, remove, \ + reserve, reconfigure, largest_key, bound, cache, reopen, checkpoint_id, close) \ + static const WT_CURSOR n = { \ + NULL, /* session */ \ + NULL, /* uri */ \ + NULL, /* key_format */ \ + NULL, /* value_format */ \ + get_key, get_value, get_raw_key_value, set_key, set_value, compare, equals, next, prev, \ + reset, search, search_near, insert, modify, update, remove, reserve, checkpoint_id, close, \ + largest_key, reconfigure, bound, 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 */ \ + {NULL, 0, NULL, 0, 0}, /* WT_ITEM lower bound */ \ + {NULL, 0, NULL, 0, 0}, /* WT_ITEM upper bound */ \ + 0 /* uint32_t flags */ \ } /* Call a function without the evict reposition cursor flag, restore afterwards. */ diff --git a/src/third_party/wiredtiger/src/include/extern.h b/src/third_party/wiredtiger/src/include/extern.h index 0a136d9865c..926b52ca75d 100644 --- a/src/third_party/wiredtiger/src/include/extern.h +++ b/src/third_party/wiredtiger/src/include/extern.h @@ -601,6 +601,10 @@ extern int __wt_cursor_get_keyv(WT_CURSOR *cursor, uint64_t flags, va_list ap) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern int __wt_cursor_get_raw_key(WT_CURSOR *cursor, WT_ITEM *key) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); +extern int __wt_cursor_get_raw_key_value(WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value) + WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); +extern int __wt_cursor_get_raw_key_value_notsup(WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value) + WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern int __wt_cursor_get_raw_value(WT_CURSOR *cursor, WT_ITEM *value) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern int __wt_cursor_get_value(WT_CURSOR *cursor, ...) diff --git a/src/third_party/wiredtiger/src/include/wiredtiger.in b/src/third_party/wiredtiger/src/include/wiredtiger.in index cb099a97b4e..5a5cdbdcbe5 100644 --- a/src/third_party/wiredtiger/src/include/wiredtiger.in +++ b/src/third_party/wiredtiger/src/include/wiredtiger.in @@ -260,6 +260,27 @@ struct __wt_cursor { int __F(get_value)(WT_CURSOR *cursor, ...); /*! + * Get the raw key and value for the current record. + * + * @snippet ex_all.c Get the raw key and value for the current record. + * + * @snippet ex_all.c Set the cursor's record number key + * + * @param cursor the cursor handle + * @param key pointer to an item that will contains the current record's raw key + * @param value pointer to an item that will contains the current record's raw value + * + * The caller can optionally pass in NULL for either key or value to retrieve only + * the other of the key or value. + * + * If an error occurs during this operation, a flag will be set in the + * cursor, and the next operation to access the key will fail. This + * simplifies error handling in applications. + * @errors + */ + int __F(get_raw_key_value)(WT_CURSOR *cursor, WT_ITEM* key, WT_ITEM* value); + + /*! * Set the key for the next operation. * * @snippet ex_all.c Set the cursor's string key diff --git a/src/third_party/wiredtiger/src/lsm/lsm_cursor.c b/src/third_party/wiredtiger/src/lsm/lsm_cursor.c index fcd42f67771..c64733669ce 100644 --- a/src/third_party/wiredtiger/src/lsm/lsm_cursor.c +++ b/src/third_party/wiredtiger/src/lsm/lsm_cursor.c @@ -1681,6 +1681,7 @@ __wt_clsm_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *owner, cons WT_CONFIG_ITEM cval; WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __wt_cursor_get_value, /* get-value */ + __wt_cursor_get_raw_key_value, /* get-value */ __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __clsm_compare, /* compare */ diff --git a/src/third_party/wiredtiger/test/suite/test_cursor22.py b/src/third_party/wiredtiger/test/suite/test_cursor22.py new file mode 100644 index 00000000000..1dc9bc50e17 --- /dev/null +++ b/src/third_party/wiredtiger/test/suite/test_cursor22.py @@ -0,0 +1,95 @@ +#!/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_cursor22.py +# Test cursor get_raw_key_value + +import wttest + +class test_cursor22(wttest.WiredTigerTestCase): + uri = "table:test_cursor22" + + def check_get_key_and_value(self, cursor, expected_key, expected_value): + key = cursor.get_key() + value = cursor.get_value() + self.assertEquals(key, expected_key) + self.assertEquals(value, expected_value) + + def check_get_raw_key_value(self, cursor, expected_key, expected_value): + (key, value) = cursor.get_raw_key_value() + self.assertEquals(key, expected_key) + self.assertEquals(value, expected_value) + + def test_cursor22(self): + self.session.create(self.uri, 'key_format=S,value_format=S') + cursor = self.session.open_cursor(self.uri) + + # Insert some data + self.session.begin_transaction() + for i in range(1, 10): + cursor.set_key("key" + str(i)) + cursor.set_value("value" + str(100+i)) + cursor.insert() + self.session.commit_transaction() + + # Check the data using get_key() and get_value() + self.session.begin_transaction() + cursor.reset() + for i in range(1, 10): + cursor.next() + self.check_get_key_and_value(cursor=cursor, expected_key="key" + str(i), expected_value="value" + str(100+i)) + self.session.commit_transaction() + + # Check the data using get_raw_key_value() + self.session.begin_transaction() + cursor.reset() + for i in range(1, 10): + cursor.next() + self.check_get_raw_key_value(cursor=cursor, expected_key="key" + str(i), expected_value="value" + str(100+i)) + self.session.commit_transaction() + + # Check the less common usage of get_raw_key_value() + self.session.begin_transaction() + cursor.reset() + cursor.next() + # Get only the key (and ignore the value) + (key, _) = cursor.get_raw_key_value() + # Check we can ignore the result completely, without an issue + cursor.get_raw_key_value() + # Get only the value (and ignore the key) + (_, value) = cursor.get_raw_key_value() + self.assertEquals(key, "key1") + self.assertEquals(value, "value101") + self.session.commit_transaction() + + cursor.close() + self.session.close() + + +if __name__ == '__main__': + wttest.run()
\ No newline at end of file diff --git a/src/third_party/wiredtiger/test/suite/test_cursor23.py b/src/third_party/wiredtiger/test/suite/test_cursor23.py new file mode 100644 index 00000000000..7f93a966d3a --- /dev/null +++ b/src/third_party/wiredtiger/test/suite/test_cursor23.py @@ -0,0 +1,104 @@ +#!/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_cursor23.py +# Test cursor get_raw_key_value using complex schema + +import wiredtiger, wttest +from wtdataset import SimpleDataSet, ComplexDataSet, ComplexLSMDataSet +from wtscenario import make_scenarios + +class test_cursor23(wttest.WiredTigerTestCase): + scenarios = make_scenarios([ + ('file-S', dict(type='file:', keyfmt='S', valfmt='S', dataset=SimpleDataSet, complex=False)), + ('lsm-S', dict(type='lsm:', keyfmt='S', valfmt='S', dataset=SimpleDataSet, complex=False)), + ('table-S', dict(type='table:', keyfmt='S', valfmt='S', dataset=SimpleDataSet, complex=False)), + ('table-S-complex-lsm', dict(type='table:', keyfmt='S', valfmt='S', + dataset=ComplexLSMDataSet, complex=True)), + ]) + + def check_get_key_and_value(self, cursor, expected_key, expected_value): + key = cursor.get_key() + value = cursor.get_value() + self.assertEquals(key, expected_key) + self.assertEquals(value, expected_value) + + def check_get_raw_key_value(self, cursor, expected_key, expected_value): + (key, value) = cursor.get_raw_key_value() + self.assertEquals(key, expected_key) + self.assertEquals(value, expected_value) + + def test_cursor23(self): + uri = self.type + "test_cursor23" + ds = self.dataset(self, uri, 100, key_format=self.keyfmt, value_format=self.valfmt) + ds.populate() + + cursor = self.session.open_cursor(uri) + + if self.complex: + # Check the data using get_key() and get_value() + self.session.begin_transaction() + cursor.reset() + cursor.next() + self.check_get_key_and_value(cursor=cursor, expected_key=f'{1:015d}', expected_value=['1:', 1, '32:', '81:']) + cursor.next() + self.check_get_key_and_value(cursor=cursor, expected_key=f'{2:015d}', expected_value=['2: ', 2, '64: ', '63: ']) + cursor.next() + self.check_get_key_and_value(cursor=cursor, expected_key=f'{3:015d}', expected_value=['3: a', 3, '96: a', '45: a']) + self.session.commit_transaction() + + # Try to check the data using get_raw_key_value(), but it's not supported + self.session.begin_transaction() + cursor.reset() + cursor.next() + msg = '/Unsupported cursor operation: Operation not supported/' + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: cursor.get_raw_key_value(), msg) + self.session.commit_transaction() + else: + # Check the data using get_key() and get_value() + self.session.begin_transaction() + cursor.reset() + for i in range(1, 10): + cursor.next() + self.check_get_key_and_value(cursor=cursor, expected_key=f'{i:015d}'.format(i), expected_value=f'{i}: abcdefghijklmnopqrstuvwxyz'.format(i)) + self.session.commit_transaction() + + # Check the data using get_raw_key_and_value() + self.session.begin_transaction() + cursor.reset() + for i in range(1, 10): + cursor.next() + self.check_get_raw_key_value(cursor=cursor, expected_key=f'{i:015d}'.format(i), expected_value=f'{i}: abcdefghijklmnopqrstuvwxyz'.format(i)) + self.session.commit_transaction() + + cursor.close() + self.session.close() + + +if __name__ == '__main__': + wttest.run()
\ No newline at end of file diff --git a/src/third_party/wiredtiger/test/unittest/tests/cursors/test_cursor_get_raw_key_value.cpp b/src/third_party/wiredtiger/test/unittest/tests/cursors/test_cursor_get_raw_key_value.cpp new file mode 100644 index 00000000000..3b57bcb33fc --- /dev/null +++ b/src/third_party/wiredtiger/test/unittest/tests/cursors/test_cursor_get_raw_key_value.cpp @@ -0,0 +1,159 @@ +/*- + * Copyright (c) 2014-present MongoDB, Inc. + * Copyright (c) 2008-2014 WiredTiger, Inc. + * All rights reserved. + * + * See the file LICENSE for redistribution information. + */ + +#include <catch2/catch.hpp> +#include "wiredtiger.h" +#include "wt_internal.h" +#include "../utils.h" +#include "../wrappers/connection_wrapper.h" +#include "../wrappers/item_wrapper.h" + +void +init_wt_item(WT_ITEM &item) +{ + item.data = nullptr; + item.size = 0; + item.mem = nullptr; + item.memsize = 0; + item.flags = 0; +} + +int +insert_key_value(WT_CURSOR *cursor, const char *key, const char *value) +{ + item_wrapper item_key(key); + item_wrapper item_value(value); + __wt_cursor_set_raw_key(cursor, item_key.get_item()); + __wt_cursor_set_raw_value(cursor, item_value.get_item()); + return cursor->insert(cursor); +} + +bool +require_get_key_value(WT_CURSOR *cursor, const char *expected_key, const char *expected_value) +{ + const char *key = nullptr; + const char *value = nullptr; + REQUIRE(cursor->get_key(cursor, &key) == 0); + REQUIRE(cursor->get_value(cursor, &value) == 0); + + bool keys_match = strcmp(key, expected_key) == 0; + bool values_match = strcmp(value, expected_value) == 0; + REQUIRE(keys_match); + REQUIRE(values_match); + + return keys_match && values_match; +} + +bool +check_item(WT_ITEM *item, const char *expected) +{ + bool match = true; + if (expected != nullptr) { + const char *key = static_cast<const char *>(item->data); + REQUIRE(key != nullptr); + match = strcmp(key, expected) == 0; + } + REQUIRE(match); + return match; +} + +bool +require_get_raw_key_value(WT_CURSOR *cursor, const char *expected_key, const char *expected_value) +{ + WT_ITEM item_key; + init_wt_item(item_key); + WT_ITEM item_value; + init_wt_item(item_value); + + WT_ITEM *p_item_key = (expected_key == nullptr) ? nullptr : &item_key; + WT_ITEM *p_item_value = (expected_value == nullptr) ? nullptr : &item_value; + + REQUIRE(cursor->get_raw_key_value(cursor, p_item_key, p_item_value) == 0); + + bool keys_match = check_item(p_item_key, expected_key); + bool values_match = check_item(p_item_value, expected_value); + + return keys_match && values_match; +} + +TEST_CASE("Cursor: get key and value()", "[cursor]") +{ + ConnectionWrapper conn(DB_HOME); + WT_SESSION_IMPL *session_impl = conn.createSession(); + std::string uri = "table:cursor_test"; + std::string file = "file:cursor_test.wt"; + + WT_SESSION *session = &session_impl->iface; + + REQUIRE(session->create(session, uri.c_str(), "key_format=S,value_format=S") == 0); + + WT_CURSOR *cursor = nullptr; + REQUIRE(session->open_cursor(session, uri.c_str(), nullptr, nullptr, &cursor) == 0); + + // Insert some values + REQUIRE(insert_key_value(cursor, "key1", "value1") == 0); + REQUIRE(insert_key_value(cursor, "key2", "value2") == 0); + REQUIRE(insert_key_value(cursor, "key3", "value3") == 0); + REQUIRE(insert_key_value(cursor, "key4", "value4") == 0); + REQUIRE(insert_key_value(cursor, "key5", "value5") == 0); + + SECTION("Check the values using get_key() and get_value()") + { + REQUIRE(cursor->reset(cursor) == 0); + REQUIRE(cursor->next(cursor) == 0); + REQUIRE(require_get_key_value(cursor, "key1", "value1")); + REQUIRE(cursor->next(cursor) == 0); + REQUIRE(require_get_key_value(cursor, "key2", "value2")); + REQUIRE(cursor->next(cursor) == 0); + REQUIRE(require_get_key_value(cursor, "key3", "value3")); + REQUIRE(cursor->next(cursor) == 0); + REQUIRE(require_get_key_value(cursor, "key4", "value4")); + REQUIRE(cursor->next(cursor) == 0); + REQUIRE(require_get_key_value(cursor, "key5", "value5")); + REQUIRE(cursor->next(cursor) == WT_NOTFOUND); + } + + SECTION("Check the values using get_raw_key_value()") + { + REQUIRE(cursor->reset(cursor) == 0); + REQUIRE(cursor->next(cursor) == 0); + REQUIRE(require_get_raw_key_value(cursor, "key1", "value1")); + REQUIRE(cursor->next(cursor) == 0); + REQUIRE(require_get_raw_key_value(cursor, "key2", "value2")); + REQUIRE(cursor->next(cursor) == 0); + REQUIRE(require_get_raw_key_value(cursor, "key3", "value3")); + REQUIRE(require_get_raw_key_value(cursor, nullptr, "value3")); + REQUIRE(require_get_raw_key_value(cursor, "key3", nullptr)); + REQUIRE(cursor->next(cursor) == 0); + REQUIRE(require_get_raw_key_value(cursor, "key4", "value4")); + REQUIRE(cursor->next(cursor) == 0); + REQUIRE(require_get_raw_key_value(cursor, "key5", "value5")); + REQUIRE(cursor->next(cursor) == WT_NOTFOUND); + } + + SECTION("Check get_raw_key_value() on a cursor type that does not support it") + { + WT_CURSOR *version_cursor = nullptr; + REQUIRE(session->open_cursor(session, file.c_str(), nullptr, "debug=(dump_version=true)", + &version_cursor) == 0); + WT_ITEM item_key; + init_wt_item(item_key); + WT_ITEM item_value; + init_wt_item(item_value); + + // get_raw_key_value() is not supported on a version cursor + REQUIRE( + version_cursor->get_raw_key_value(version_cursor, &item_key, &item_value) == ENOTSUP); + + REQUIRE(version_cursor->close(version_cursor) == 0); + } + + REQUIRE(cursor->close(cursor) == 0); + + REQUIRE(session->close(session, nullptr) == 0); +} diff --git a/src/third_party/wiredtiger/test/unittest/tests/utils.cpp b/src/third_party/wiredtiger/test/unittest/tests/utils.cpp index 3906fd7aef8..f7f33052976 100644 --- a/src/third_party/wiredtiger/test/unittest/tests/utils.cpp +++ b/src/third_party/wiredtiger/test/unittest/tests/utils.cpp @@ -39,6 +39,7 @@ wiredtigerCleanup(std::string const &home) remove_wrapper(home + "/WiredTiger.turtle"); remove_wrapper(home + "/WiredTiger.wt"); remove_wrapper(home + "/WiredTigerHS.wt"); + remove_wrapper(home + "/cursor_test.wt"); remove_wrapper(home); } diff --git a/src/third_party/wiredtiger/test/unittest/tests/wrappers/item_wrapper.cpp b/src/third_party/wiredtiger/test/unittest/tests/wrappers/item_wrapper.cpp new file mode 100644 index 00000000000..26b3f43cbeb --- /dev/null +++ b/src/third_party/wiredtiger/test/unittest/tests/wrappers/item_wrapper.cpp @@ -0,0 +1,25 @@ +/*- + * Copyright (c) 2014-present MongoDB, Inc. + * Copyright (c) 2008-2014 WiredTiger, Inc. + * All rights reserved. + * + * See the file LICENSE for redistribution information. + */ + +#include "wiredtiger.h" +#include "item_wrapper.h" + +item_wrapper::item_wrapper(const char *string) : _string(string) +{ + _item.data = _string.c_str(); + _item.size = _string.length() + 1; + _item.mem = nullptr; + _item.memsize = 0; + _item.flags = 0; +} + +item_wrapper::~item_wrapper() +{ + _item.data = nullptr; + _item.size = 0; +} diff --git a/src/third_party/wiredtiger/test/unittest/tests/wrappers/item_wrapper.h b/src/third_party/wiredtiger/test/unittest/tests/wrappers/item_wrapper.h new file mode 100644 index 00000000000..0dba5dc3041 --- /dev/null +++ b/src/third_party/wiredtiger/test/unittest/tests/wrappers/item_wrapper.h @@ -0,0 +1,26 @@ +/*- + * Copyright (c) 2014-present MongoDB, Inc. + * Copyright (c) 2008-2014 WiredTiger, Inc. + * All rights reserved. + * + * See the file LICENSE for redistribution information. + */ + +#pragma once + +#include <string> + +class item_wrapper { + public: + explicit item_wrapper(const char *string); + ~item_wrapper(); + WT_ITEM * + get_item() + { + return &_item; + }; + + private: + WT_ITEM _item; + std::string _string; +}; |