summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger
diff options
context:
space:
mode:
authorWill Korteland <will.korteland@mongodb.com>2022-01-25 05:44:35 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-01-25 06:13:47 +0000
commit1ee0f0d306a35ec87654ae7f651571efebb3f624 (patch)
tree0ea68128a9e47951a7f1d8ff7ae8817504194663 /src/third_party/wiredtiger
parent37201537844c11d477db81a308a36448c174f71d (diff)
downloadmongo-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.data2
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_cursor.c28
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_table.c20
-rw-r--r--src/third_party/wiredtiger/src/include/wiredtiger.in64
-rw-r--r--src/third_party/wiredtiger/test/suite/test_cursor20.py66
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()