diff options
author | Will Korteland <will.korteland@mongodb.com> | 2022-01-25 05:44:35 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-01-25 06:13:47 +0000 |
commit | 1ee0f0d306a35ec87654ae7f651571efebb3f624 (patch) | |
tree | 0ea68128a9e47951a7f1d8ff7ae8817504194663 /src/third_party/wiredtiger | |
parent | 37201537844c11d477db81a308a36448c174f71d (diff) | |
download | mongo-1ee0f0d306a35ec87654ae7f651571efebb3f624.tar.gz |
Import wiredtiger: 7ecb3f4a13db0f7a5476012dab95f9369649f863 from branch mongodb-master
ref: 9443b440b5..7ecb3f4a13
for: 5.3.0
WT-8289 Provide a means to get K/V pair on duplicate key error
Diffstat (limited to 'src/third_party/wiredtiger')
-rw-r--r-- | src/third_party/wiredtiger/import.data | 2 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/btree/bt_cursor.c | 28 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/cursor/cur_table.c | 20 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/include/wiredtiger.in | 64 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/suite/test_cursor20.py | 66 |
5 files changed, 130 insertions, 50 deletions
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index b5fa1ae4190..0d4327401f9 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": "9443b440b5788d34f376939230fb22f241ce7ff3" + "commit": "7ecb3f4a13db0f7a5476012dab95f9369649f863" } diff --git a/src/third_party/wiredtiger/src/btree/bt_cursor.c b/src/third_party/wiredtiger/src/btree/bt_cursor.c index 68fa71f7679..60a567b56a8 100644 --- a/src/third_party/wiredtiger/src/btree/bt_cursor.c +++ b/src/third_party/wiredtiger/src/btree/bt_cursor.c @@ -898,11 +898,9 @@ retry: * If not overwriting, fail if the key exists, else insert the key/value pair. */ if (!F_ISSET(cursor, WT_CURSTD_OVERWRITE) && cbt->compare == 0) { - WT_WITH_UPDATE_VALUE_SKIP_BUF( - ret = __wt_cursor_valid(cbt, cbt->tmp, WT_RECNO_OOB, &valid)); - WT_ERR(ret); + WT_ERR(__wt_cursor_valid(cbt, cbt->tmp, WT_RECNO_OOB, &valid)); if (valid) - WT_ERR(WT_DUPLICATE_KEY); + goto duplicate; } ret = __cursor_row_modify(cbt, &cbt->iface.value, WT_UPDATE_STANDARD); @@ -926,13 +924,11 @@ retry: */ if (!F_ISSET(cursor, WT_CURSTD_OVERWRITE)) { if (cbt->compare == 0) { - WT_WITH_UPDATE_VALUE_SKIP_BUF( - ret = __wt_cursor_valid(cbt, NULL, cbt->recno, &valid)); - WT_ERR(ret); + WT_ERR(__wt_cursor_valid(cbt, NULL, cbt->recno, &valid)); if (valid) - WT_ERR(WT_DUPLICATE_KEY); + goto duplicate; } else if (__cursor_fix_implicit(btree, cbt)) - WT_ERR(WT_DUPLICATE_KEY); + goto duplicate; } WT_ERR(__cursor_col_modify(cbt, &cbt->iface.value, WT_UPDATE_STANDARD)); @@ -944,6 +940,18 @@ err: goto retry; } + /* Return the found value for any duplicate key. */ + if (0) { +duplicate: + if (F_ISSET(cursor, WT_CURSTD_DUP_NO_VALUE)) + ret = WT_DUPLICATE_KEY; + else { + __wt_value_return(cbt, cbt->upd_value); + if ((ret = __cursor_localvalue(cursor)) == 0) + ret = WT_DUPLICATE_KEY; + } + } + /* Insert doesn't maintain a position across calls, clear resources. */ if (ret == 0) { done: @@ -952,7 +960,7 @@ done: F_SET(cursor, WT_CURSTD_KEY_EXT); } WT_TRET(__cursor_reset(cbt)); - if (ret != 0) + if (ret != 0 && ret != WT_DUPLICATE_KEY) __cursor_state_restore(cursor, &state); return (ret); diff --git a/src/third_party/wiredtiger/src/cursor/cur_table.c b/src/third_party/wiredtiger/src/cursor/cur_table.c index e95c1a5e4ae..c456ae06888 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_table.c +++ b/src/third_party/wiredtiger/src/cursor/cur_table.c @@ -505,29 +505,31 @@ __curtable_insert(WT_CURSOR *cursor) JOINABLE_CURSOR_UPDATE_API_CALL(cursor, session, insert); WT_ERR(__curtable_open_indices(ctable)); + cp = ctable->cg_cursors; + primary = *cp++; + /* * Split out the first insert, it may be allocating a recno. * * If the table has indices, we also need to know whether this record is replacing an existing * record so that the existing index entries can be removed. We discover if this is an overwrite * by configuring the primary cursor for no-overwrite, and checking if the insert detects a - * duplicate key. + * duplicate key. By default, when insert finds a duplicate, it returns the value it found. We + * don't want that value to overwrite our own, override that behavior. */ - cp = ctable->cg_cursors; - primary = *cp++; - flag_orig = F_MASK(primary, WT_CURSTD_OVERWRITE); - if (ctable->table->nindices > 0) + if (ctable->table->nindices > 0) { F_CLR(primary, WT_CURSTD_OVERWRITE); + F_SET(primary, WT_CURSTD_DUP_NO_VALUE); + } ret = primary->insert(primary); /* - * !!! - * WT_CURSOR.insert clears the set internally/externally flags - * but doesn't touch the items. We could make a copy each time - * for overwrite cursors, but for now we just reset the flags. + * WT_CURSOR.insert clears the set internally/externally flags but doesn't touch the items. We + * could make a copy each time for overwrite cursors, but for now we just reset the flags. */ F_SET(primary, flag_orig | WT_CURSTD_KEY_EXT | WT_CURSTD_VALUE_EXT); + F_CLR(primary, WT_CURSTD_DUP_NO_VALUE); if (ret == WT_DUPLICATE_KEY && F_ISSET(cursor, WT_CURSTD_OVERWRITE)) { WT_ERR(__curtable_update(cursor)); diff --git a/src/third_party/wiredtiger/src/include/wiredtiger.in b/src/third_party/wiredtiger/src/include/wiredtiger.in index e91773e72d5..29db28a0b69 100644 --- a/src/third_party/wiredtiger/src/include/wiredtiger.in +++ b/src/third_party/wiredtiger/src/include/wiredtiger.in @@ -446,7 +446,9 @@ struct __wt_cursor { * * If the cursor was not configured with "overwrite=true", both the key * and value must be set and the record must not already exist; the - * record will be inserted. + * record will be inserted. If the record already exists, the + * ::WT_DUPLICATE_KEY error is returned and the value found in the tree + * can be retrieved using WT_CURSOR::get_value. * * @snippet ex_all.c Insert a new record and fail if the record exists * @@ -464,7 +466,8 @@ struct __wt_cursor { * with "append=true", the cursor ends with no key set and a subsequent * call to the WT_CURSOR::get_key method will fail. The cursor ends with * no value set and a subsequent call to the WT_CURSOR::get_value method - * will fail. + * will fail, except for the ::WT_DUPLICATE_KEY error return, in which + * case the value currently stored for the key can be retrieved. * * Inserting a new record after the current maximum record in a * fixed-length bit field column-store (that is, a store with an @@ -709,34 +712,35 @@ struct __wt_cursor { const char *internal_uri; /* AUTOMATIC FLAG VALUE GENERATION START 0 */ -#define WT_CURSTD_APPEND 0x0000001u -#define WT_CURSTD_BULK 0x0000002u -#define WT_CURSTD_CACHEABLE 0x0000004u -#define WT_CURSTD_CACHED 0x0000008u -#define WT_CURSTD_DEAD 0x0000010u -#define WT_CURSTD_DEBUG_COPY_KEY 0x0000020u -#define WT_CURSTD_DEBUG_COPY_VALUE 0x0000040u -#define WT_CURSTD_DEBUG_RESET_EVICT 0x0000080u -#define WT_CURSTD_DUMP_HEX 0x0000100u -#define WT_CURSTD_DUMP_JSON 0x0000200u -#define WT_CURSTD_DUMP_PRETTY 0x0000400u -#define WT_CURSTD_DUMP_PRINT 0x0000800u -#define WT_CURSTD_HS_READ_ALL 0x0001000u -#define WT_CURSTD_HS_READ_COMMITTED 0x0002000u -#define WT_CURSTD_IGNORE_TOMBSTONE 0x0004000u -#define WT_CURSTD_JOINED 0x0008000u -#define WT_CURSTD_KEY_EXT 0x0010000u /* Key points out of tree. */ -#define WT_CURSTD_KEY_INT 0x0020000u /* Key points into tree. */ -#define WT_CURSTD_KEY_ONLY 0x0040000u -#define WT_CURSTD_META_INUSE 0x0080000u -#define WT_CURSTD_OPEN 0x0100000u -#define WT_CURSTD_OVERWRITE 0x0200000u -#define WT_CURSTD_PREFIX_SEARCH 0x0400000u -#define WT_CURSTD_RAW 0x0800000u -#define WT_CURSTD_RAW_SEARCH 0x1000000u -#define WT_CURSTD_VALUE_EXT 0x2000000u /* Value points out of tree. */ -#define WT_CURSTD_VALUE_INT 0x4000000u /* Value points into tree. */ -#define WT_CURSTD_VERSION_CURSOR 0x8000000u /* Version cursor. */ +#define WT_CURSTD_APPEND 0x00000001u +#define WT_CURSTD_BULK 0x00000002u +#define WT_CURSTD_CACHEABLE 0x00000004u +#define WT_CURSTD_CACHED 0x00000008u +#define WT_CURSTD_DEAD 0x00000010u +#define WT_CURSTD_DEBUG_COPY_KEY 0x00000020u +#define WT_CURSTD_DEBUG_COPY_VALUE 0x00000040u +#define WT_CURSTD_DEBUG_RESET_EVICT 0x00000080u +#define WT_CURSTD_DUMP_HEX 0x00000100u +#define WT_CURSTD_DUMP_JSON 0x00000200u +#define WT_CURSTD_DUMP_PRETTY 0x00000400u +#define WT_CURSTD_DUMP_PRINT 0x00000800u +#define WT_CURSTD_DUP_NO_VALUE 0x00001000u +#define WT_CURSTD_HS_READ_ALL 0x00002000u +#define WT_CURSTD_HS_READ_COMMITTED 0x00004000u +#define WT_CURSTD_IGNORE_TOMBSTONE 0x00008000u +#define WT_CURSTD_JOINED 0x00010000u +#define WT_CURSTD_KEY_EXT 0x00020000u /* Key points out of tree. */ +#define WT_CURSTD_KEY_INT 0x00040000u /* Key points into tree. */ +#define WT_CURSTD_KEY_ONLY 0x00080000u +#define WT_CURSTD_META_INUSE 0x00100000u +#define WT_CURSTD_OPEN 0x00200000u +#define WT_CURSTD_OVERWRITE 0x00400000u +#define WT_CURSTD_PREFIX_SEARCH 0x00800000u +#define WT_CURSTD_RAW 0x01000000u +#define WT_CURSTD_RAW_SEARCH 0x02000000u +#define WT_CURSTD_VALUE_EXT 0x04000000u /* Value points out of tree. */ +#define WT_CURSTD_VALUE_INT 0x08000000u /* Value points into tree. */ +#define WT_CURSTD_VERSION_CURSOR 0x10000000u /* Version cursor. */ /* AUTOMATIC FLAG VALUE GENERATION STOP 32 */ #define WT_CURSTD_KEY_SET (WT_CURSTD_KEY_EXT | WT_CURSTD_KEY_INT) #define WT_CURSTD_VALUE_SET (WT_CURSTD_VALUE_EXT | WT_CURSTD_VALUE_INT) diff --git a/src/third_party/wiredtiger/test/suite/test_cursor20.py b/src/third_party/wiredtiger/test/suite/test_cursor20.py new file mode 100644 index 00000000000..3ff29695e7f --- /dev/null +++ b/src/third_party/wiredtiger/test/suite/test_cursor20.py @@ -0,0 +1,66 @@ +#!/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_cursor18.py +# Test dupicate key return values. + +from suite_subprocess import suite_subprocess +from wtdataset import SimpleDataSet +import wiredtiger, wttest +from wtscenario import make_scenarios + +class test_cursor18(wttest.WiredTigerTestCase, suite_subprocess): + format_values = [ + ('row', dict(key_format = 'S', value_format='S')), + ('var', dict(key_format = 'r', value_format='S')), + ('fix', dict(key_format = 'r', value_format='8t')), + ] + reopen = [ + ('in-memory', dict(reopen=False)), + ('on-disk', dict(reopen=True)), + ] + scenarios = make_scenarios(format_values, reopen) + + def test_dup_key(self): + uri = 'table:dup_key' + ds = SimpleDataSet(self, uri, 100, + key_format=self.key_format, value_format=self.value_format) + ds.populate() + + if self.reopen: + self.reopen_conn() + + c = self.session.open_cursor(uri, None, 'overwrite=false') + c.set_key(ds.key(10)) + c.set_value(ds.value(20)) + self.assertRaisesHavingMessage( + wiredtiger.WiredTigerError, lambda:c.insert(), '/WT_DUPLICATE_KEY/') + self.assertEqual(c.get_value(), ds.value(10)) + +if __name__ == '__main__': + wttest.run() |