diff options
-rw-r--r-- | dist/s_string.ok | 1 | ||||
-rw-r--r-- | examples/c/ex_all.c | 13 | ||||
-rw-r--r-- | examples/java/com/wiredtiger/examples/ex_all.java | 13 | ||||
-rw-r--r-- | lang/python/wiredtiger.i | 36 | ||||
-rw-r--r-- | src/btree/bt_cursor.c | 49 | ||||
-rw-r--r-- | src/cursor/cur_backup.c | 1 | ||||
-rw-r--r-- | src/cursor/cur_config.c | 1 | ||||
-rw-r--r-- | src/cursor/cur_ds.c | 1 | ||||
-rw-r--r-- | src/cursor/cur_dump.c | 1 | ||||
-rw-r--r-- | src/cursor/cur_file.c | 40 | ||||
-rw-r--r-- | src/cursor/cur_index.c | 1 | ||||
-rw-r--r-- | src/cursor/cur_log.c | 1 | ||||
-rw-r--r-- | src/cursor/cur_metadata.c | 1 | ||||
-rw-r--r-- | src/cursor/cur_stat.c | 1 | ||||
-rw-r--r-- | src/cursor/cur_table.c | 58 | ||||
-rw-r--r-- | src/include/cursor.h | 2 | ||||
-rw-r--r-- | src/include/extern.h | 1 | ||||
-rw-r--r-- | src/include/wiredtiger.in | 19 | ||||
-rw-r--r-- | src/lsm/lsm_cursor.c | 1 | ||||
-rw-r--r-- | test/suite/test_cursor_compare.py | 115 |
20 files changed, 305 insertions, 51 deletions
diff --git a/dist/s_string.ok b/dist/s_string.ok index d3717d27331..956b4061c62 100644 --- a/dist/s_string.ok +++ b/dist/s_string.ok @@ -581,6 +581,7 @@ enum's env eof eop +equalityp errhandler errno errv diff --git a/examples/c/ex_all.c b/examples/c/ex_all.c index 31ad812e6f6..6fe5296ea58 100644 --- a/examples/c/ex_all.c +++ b/examples/c/ex_all.c @@ -242,6 +242,19 @@ cursor_ops(WT_SESSION *session) } { + WT_CURSOR *other = NULL; + /*! [Cursor equality] */ + int equal; + ret = cursor->compare_equal(cursor, other, &equal); + if (equal == 0) { + /* Cursors reference the same key */ + } else { + /* Cursors don't reference the same key */ + } + /*! [Cursor equality] */ + } + + { /*! [Search for an exact match] */ const char *key = "some key"; cursor->set_key(cursor, key); diff --git a/examples/java/com/wiredtiger/examples/ex_all.java b/examples/java/com/wiredtiger/examples/ex_all.java index 4c30b893e06..5b1b0f58efa 100644 --- a/examples/java/com/wiredtiger/examples/ex_all.java +++ b/examples/java/com/wiredtiger/examples/ex_all.java @@ -215,6 +215,19 @@ public static int cursor_ops(Session session) } { + Cursor other = null; + /*! [Cursor equality] */ + int equal; + equal = cursor.compare_equal(other); + if (equal == 0) { + /* Cursors reference the same key */ + } else { + /* Cursors don't reference the same key */ + } + /*! [Cursor equality] */ + } + + { /*! [Search for an exact match] */ String key = "some key"; cursor.putKeyString(key); diff --git a/lang/python/wiredtiger.i b/lang/python/wiredtiger.i index 8eb1c59ee1e..f4a2801ed4c 100644 --- a/lang/python/wiredtiger.i +++ b/lang/python/wiredtiger.i @@ -381,6 +381,7 @@ NOTFOUND_OK(__wt_cursor::search) NOTFOUND_OK(__wt_cursor::update) COMPARE_OK(__wt_cursor::compare) +COMPARE_OK(__wt_cursor::compare_equal) COMPARE_OK(__wt_cursor::search_near) /* Lastly, some methods need no (additional) error checking. */ @@ -415,6 +416,7 @@ COMPARE_OK(__wt_cursor::search_near) /* Next, override methods that return integers via arguments. */ %ignore __wt_cursor::compare(WT_CURSOR *, WT_CURSOR *, int *); +%ignore __wt_cursor::compare_equal(WT_CURSOR *, WT_CURSOR *, int *); %ignore __wt_cursor::search_near(WT_CURSOR *, int *); /* SWIG magic to turn Python byte strings into data / size. */ @@ -673,7 +675,7 @@ typedef int int_void; return (ret); } - /* compare and search_near need special handling. */ + /* compare: special handling. */ int compare(WT_CURSOR *other) { int cmp = 0; int ret = 0; @@ -691,12 +693,37 @@ typedef int int_void; * Map less-than-zero to -1 and greater-than-zero to 1 * to avoid colliding with other errors. */ - ret = ((ret != 0) ? ret : - (cmp < 0) ? -1 : (cmp == 0) ? 0 : 1); + ret = (ret != 0) ? ret : + ((cmp < 0) ? -1 : (cmp == 0) ? 0 : 1); } return (ret); } + /* compare_equal: special handling. */ + int compare_equal(WT_CURSOR *other) { + int cmp = 0; + int ret = 0; + if (other == NULL) { + SWIG_Error(SWIG_NullReferenceError, + "in method 'Cursor_compare_equal', " + "argument 1 of type 'struct __wt_cursor *' " + "is None"); + ret = EINVAL; /* any non-zero value will do. */ + } + else { + ret = $self->compare_equal($self, other, &cmp); + + /* + * Compare-equal is documented to return 0 and !0, map + * less-than-zero and greater-than-zero to 1 to avoid + * colliding with other errors. + */ + ret = (ret != 0) ? ret : (cmp == 0 ? 0 : 1); + } + return (ret); + } + + /* search_near: special handling. */ int search_near() { int cmp = 0; int ret = $self->search_near($self, &cmp); @@ -704,8 +731,7 @@ typedef int int_void; * Map less-than-zero to -1 and greater-than-zero to 1 to avoid * colliding with WT_NOTFOUND. */ - return ((ret != 0) ? ret : - (cmp < 0) ? -1 : (cmp == 0) ? 0 : 1); + return ((ret != 0) ? ret : (cmp < 0) ? -1 : (cmp == 0) ? 0 : 1); } int _freecb() { diff --git a/src/btree/bt_cursor.c b/src/btree/bt_cursor.c index 4aee1883ae0..71bdd0dc7c5 100644 --- a/src/btree/bt_cursor.c +++ b/src/btree/bt_cursor.c @@ -800,16 +800,19 @@ err: if (ret != 0) int __wt_btcur_compare(WT_CURSOR_BTREE *a_arg, WT_CURSOR_BTREE *b_arg, int *cmpp) { - WT_BTREE *btree; WT_CURSOR *a, *b; WT_SESSION_IMPL *session; a = (WT_CURSOR *)a_arg; b = (WT_CURSOR *)b_arg; - btree = a_arg->btree; session = (WT_SESSION_IMPL *)a->session; - switch (btree->type) { + /* Confirm both cursors reference the same object. */ + if (a_arg->btree != b_arg->btree) + WT_RET_MSG( + session, EINVAL, "Cursors must reference the same object"); + + switch (a_arg->btree->type) { case BTREE_COL_FIX: case BTREE_COL_VAR: /* @@ -826,7 +829,7 @@ __wt_btcur_compare(WT_CURSOR_BTREE *a_arg, WT_CURSOR_BTREE *b_arg, int *cmpp) break; case BTREE_ROW: WT_RET(__wt_compare( - session, btree->collator, &a->key, &b->key, cmpp)); + session, a_arg->btree->collator, &a->key, &b->key, cmpp)); break; WT_ILLEGAL_VALUE(session); } @@ -837,7 +840,7 @@ __wt_btcur_compare(WT_CURSOR_BTREE *a_arg, WT_CURSOR_BTREE *b_arg, int *cmpp) * __cursor_equals -- * Return if two cursors reference the same row. */ -static int +static inline int __cursor_equals(WT_CURSOR_BTREE *a, WT_CURSOR_BTREE *b) { switch (a->btree->type) { @@ -867,6 +870,42 @@ __cursor_equals(WT_CURSOR_BTREE *a, WT_CURSOR_BTREE *b) } /* + * __wt_btcur_compare_equal -- + * Return an equality comparison between two cursors. + */ +int +__wt_btcur_compare_equal( + WT_CURSOR_BTREE *a_arg, WT_CURSOR_BTREE *b_arg, int *cmpp) +{ + WT_CURSOR *a, *b; + WT_SESSION_IMPL *session; + + a = (WT_CURSOR *)a_arg; + b = (WT_CURSOR *)b_arg; + session = (WT_SESSION_IMPL *)a->session; + + /* Confirm both cursors reference the same object. */ + if (a_arg->btree != b_arg->btree) + WT_RET_MSG( + session, EINVAL, "Cursors must reference the same object"); + + /* + * The reason for a compare-equal method is because we can avoid doing + * a full key comparison in some cases. If both cursors point into the + * tree, take the fast path, otherwise fall back to the slower compare + * method. + */ + if (F_ISSET(a, WT_CURSTD_KEY_INT) && F_ISSET(b, WT_CURSTD_KEY_INT)) + *cmpp = !__cursor_equals(a_arg, b_arg); + else { + WT_RET(__wt_btcur_compare(a_arg, b_arg, cmpp)); + if (*cmpp != 0) + *cmpp = 1; + } + return (0); +} + +/* * __cursor_truncate -- * Discard a cursor range from row-store or variable-width column-store * tree. diff --git a/src/cursor/cur_backup.c b/src/cursor/cur_backup.c index 3c4c5322534..2ef6f8e9274 100644 --- a/src/cursor/cur_backup.c +++ b/src/cursor/cur_backup.c @@ -109,6 +109,7 @@ __wt_curbackup_open(WT_SESSION_IMPL *session, __wt_cursor_notsup, /* set-key */ __wt_cursor_notsup, /* set-value */ __wt_cursor_notsup, /* compare */ + __wt_cursor_notsup, /* compare_equal */ __curbackup_next, /* next */ __wt_cursor_notsup, /* prev */ __curbackup_reset, /* reset */ diff --git a/src/cursor/cur_config.c b/src/cursor/cur_config.c index f011f6db126..38f3fc159b5 100644 --- a/src/cursor/cur_config.c +++ b/src/cursor/cur_config.c @@ -32,6 +32,7 @@ __wt_curconfig_open(WT_SESSION_IMPL *session, __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __wt_cursor_notsup, /* compare */ + __wt_cursor_notsup, /* compare_equal */ __wt_cursor_notsup, /* next */ __wt_cursor_notsup, /* prev */ __wt_cursor_noop, /* reset */ diff --git a/src/cursor/cur_ds.c b/src/cursor/cur_ds.c index c8b8f6c4547..ef8d1725a28 100644 --- a/src/cursor/cur_ds.c +++ b/src/cursor/cur_ds.c @@ -454,6 +454,7 @@ __wt_curds_open( __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __curds_compare, /* compare */ + __curds_compare, /* compare_equal */ __curds_next, /* next */ __curds_prev, /* prev */ __curds_reset, /* reset */ diff --git a/src/cursor/cur_dump.c b/src/cursor/cur_dump.c index 2be1d91f0f3..ac3bc0cf5d2 100644 --- a/src/cursor/cur_dump.c +++ b/src/cursor/cur_dump.c @@ -352,6 +352,7 @@ __wt_curdump_create(WT_CURSOR *child, WT_CURSOR *owner, WT_CURSOR **cursorp) __curdump_set_key, /* set-key */ __curdump_set_value, /* set-value */ __wt_cursor_notsup, /* compare */ + __wt_cursor_notsup, /* compare_equal */ __curdump_next, /* next */ __curdump_prev, /* prev */ __curdump_reset, /* reset */ diff --git a/src/cursor/cur_file.c b/src/cursor/cur_file.c index 10d1151c30c..fbedfe6d032 100644 --- a/src/cursor/cur_file.c +++ b/src/cursor/cur_file.c @@ -46,10 +46,11 @@ __curfile_compare(WT_CURSOR *a, WT_CURSOR *b, int *cmpp) CURSOR_API_CALL(a, session, compare, cbt->btree); /* - * Confirm both cursors refer to the same source and have keys, then - * call the underlying object to compare them. + * Check both cursors are a "file:" type then call the underlying + * function, it can handle cursors pointing to different objects. */ - if (strcmp(a->internal_uri, b->internal_uri) != 0) + if (!WT_PREFIX_MATCH(a->internal_uri, "file:") || + !WT_PREFIX_MATCH(b->internal_uri, "file:")) WT_ERR_MSG(session, EINVAL, "Cursors must reference the same object"); @@ -63,6 +64,38 @@ err: API_END_RET(session, ret); } /* + * __curfile_compare_equal -- + * WT_CURSOR->compare_equal method for the btree cursor type. + */ +static int +__curfile_compare_equal(WT_CURSOR *a, WT_CURSOR *b, int *cmpp) +{ + WT_CURSOR_BTREE *cbt; + WT_DECL_RET; + WT_SESSION_IMPL *session; + + cbt = (WT_CURSOR_BTREE *)a; + CURSOR_API_CALL(a, session, compare_equal, cbt->btree); + + /* + * Check both cursors are a "file:" type then call the underlying + * function, it can handle cursors pointing to different objects. + */ + if (!WT_PREFIX_MATCH(a->internal_uri, "file:") || + !WT_PREFIX_MATCH(b->internal_uri, "file:")) + WT_ERR_MSG(session, EINVAL, + "Cursors must reference the same object"); + + WT_CURSOR_CHECKKEY(a); + WT_CURSOR_CHECKKEY(b); + + ret = __wt_btcur_compare_equal( + (WT_CURSOR_BTREE *)a, (WT_CURSOR_BTREE *)b, cmpp); + +err: API_END_RET(session, ret); +} + +/* * __curfile_next -- * WT_CURSOR->next method for the btree cursor type. */ @@ -356,6 +389,7 @@ __wt_curfile_create(WT_SESSION_IMPL *session, __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __curfile_compare, /* compare */ + __curfile_compare_equal, /* compare_equal */ __curfile_next, /* next */ __curfile_prev, /* prev */ __curfile_reset, /* reset */ diff --git a/src/cursor/cur_index.c b/src/cursor/cur_index.c index 007f3a5ae5b..dd7b965642d 100644 --- a/src/cursor/cur_index.c +++ b/src/cursor/cur_index.c @@ -343,6 +343,7 @@ __wt_curindex_open(WT_SESSION_IMPL *session, __wt_cursor_set_key, /* set-key */ __curindex_set_value, /* set-value */ __wt_cursor_notsup, /* compare */ + __wt_cursor_notsup, /* compare_equal */ __curindex_next, /* next */ __curindex_prev, /* prev */ __curindex_reset, /* reset */ diff --git a/src/cursor/cur_log.c b/src/cursor/cur_log.c index 04ab1e2a14a..346b6bf5172 100644 --- a/src/cursor/cur_log.c +++ b/src/cursor/cur_log.c @@ -315,6 +315,7 @@ __wt_curlog_open(WT_SESSION_IMPL *session, __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __curlog_compare, /* compare */ + __curlog_compare, /* compare_equal */ __curlog_next, /* next */ __wt_cursor_notsup, /* prev */ __curlog_reset, /* reset */ diff --git a/src/cursor/cur_metadata.c b/src/cursor/cur_metadata.c index 618c678558a..55205e02f8e 100644 --- a/src/cursor/cur_metadata.c +++ b/src/cursor/cur_metadata.c @@ -409,6 +409,7 @@ __wt_curmetadata_open(WT_SESSION_IMPL *session, __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __curmetadata_compare, /* compare */ + __curmetadata_compare, /* compare_equal */ __curmetadata_next, /* next */ __curmetadata_prev, /* prev */ __curmetadata_reset, /* reset */ diff --git a/src/cursor/cur_stat.c b/src/cursor/cur_stat.c index f7effb87a4f..c017c50e360 100644 --- a/src/cursor/cur_stat.c +++ b/src/cursor/cur_stat.c @@ -485,6 +485,7 @@ __wt_curstat_open(WT_SESSION_IMPL *session, __curstat_set_key, /* set-key */ __curstat_set_value, /* set-value */ __wt_cursor_notsup, /* compare */ + __wt_cursor_notsup, /* compare_equal */ __curstat_next, /* next */ __curstat_prev, /* prev */ __curstat_reset, /* reset */ diff --git a/src/cursor/cur_table.c b/src/cursor/cur_table.c index 4eb362cfcd4..2a314f342b0 100644 --- a/src/cursor/cur_table.c +++ b/src/cursor/cur_table.c @@ -77,20 +77,21 @@ __curextract_insert(WT_CURSOR *cursor) { static int __apply_idx(WT_CURSOR_TABLE *ctable, size_t func_off, int skip_immutable) { WT_CURSOR_STATIC_INIT(iface, - __wt_cursor_get_key, /* get-key */ - __wt_cursor_get_value, /* get-value */ - __wt_cursor_set_key, /* set-key */ - __wt_cursor_set_value, /* set-value */ - __wt_cursor_notsup, /* compare */ - __wt_cursor_notsup, /* next */ - __wt_cursor_notsup, /* prev */ - __wt_cursor_notsup, /* reset */ - __wt_cursor_notsup, /* search */ - __wt_cursor_notsup, /* search-near */ - __curextract_insert, /* insert */ - __wt_cursor_notsup, /* update */ - __wt_cursor_notsup, /* remove */ - __wt_cursor_notsup); /* close */ + __wt_cursor_get_key, /* get-key */ + __wt_cursor_get_value, /* get-value */ + __wt_cursor_set_key, /* set-key */ + __wt_cursor_set_value, /* set-value */ + __wt_cursor_notsup, /* compare */ + __wt_cursor_notsup, /* compare_equal */ + __wt_cursor_notsup, /* next */ + __wt_cursor_notsup, /* prev */ + __wt_cursor_notsup, /* reset */ + __wt_cursor_notsup, /* search */ + __wt_cursor_notsup, /* search-near */ + __curextract_insert, /* insert */ + __wt_cursor_notsup, /* update */ + __wt_cursor_notsup, /* remove */ + __wt_cursor_notsup); /* close */ WT_CURSOR **cp; WT_CURSOR_EXTRACTOR extract_cursor; WT_DECL_RET; @@ -832,20 +833,21 @@ __wt_curtable_open(WT_SESSION_IMPL *session, const char *uri, const char *cfg[], WT_CURSOR **cursorp) { WT_CURSOR_STATIC_INIT(iface, - __wt_curtable_get_key, /* get-key */ - __wt_curtable_get_value, /* get-value */ - __wt_curtable_set_key, /* set-key */ - __wt_curtable_set_value, /* set-value */ - __curtable_compare, /* compare */ - __curtable_next, /* next */ - __curtable_prev, /* prev */ - __curtable_reset, /* reset */ - __curtable_search, /* search */ - __curtable_search_near, /* search-near */ - __curtable_insert, /* insert */ - __curtable_update, /* update */ - __curtable_remove, /* remove */ - __curtable_close); /* close */ + __wt_curtable_get_key, /* get-key */ + __wt_curtable_get_value, /* get-value */ + __wt_curtable_set_key, /* set-key */ + __wt_curtable_set_value, /* set-value */ + __curtable_compare, /* compare */ + __curtable_compare, /* compare_equal */ + __curtable_next, /* next */ + __curtable_prev, /* prev */ + __curtable_reset, /* reset */ + __curtable_search, /* search */ + __curtable_search_near, /* search-near */ + __curtable_insert, /* insert */ + __curtable_update, /* update */ + __curtable_remove, /* remove */ + __curtable_close); /* close */ WT_CONFIG_ITEM cval; WT_CURSOR *cursor; WT_CURSOR_TABLE *ctable; diff --git a/src/include/cursor.h b/src/include/cursor.h index 0fc4b883a16..cd523274d77 100644 --- a/src/include/cursor.h +++ b/src/include/cursor.h @@ -15,6 +15,7 @@ set_key, \ set_value, \ compare, \ + compare_equal, \ next, \ prev, \ reset, \ @@ -34,6 +35,7 @@ (void (*)(WT_CURSOR *, ...))(set_key), \ (void (*)(WT_CURSOR *, ...))(set_value), \ (int (*)(WT_CURSOR *, WT_CURSOR *, int *))(compare), \ + (int (*)(WT_CURSOR *, WT_CURSOR *, int *))(compare_equal), \ next, \ prev, \ reset, \ diff --git a/src/include/extern.h b/src/include/extern.h index d8ed3f5cef1..3c737eb3188 100644 --- a/src/include/extern.h +++ b/src/include/extern.h @@ -96,6 +96,7 @@ extern int __wt_btcur_remove(WT_CURSOR_BTREE *cbt); extern int __wt_btcur_update(WT_CURSOR_BTREE *cbt); extern int __wt_btcur_next_random(WT_CURSOR_BTREE *cbt); extern int __wt_btcur_compare(WT_CURSOR_BTREE *a_arg, WT_CURSOR_BTREE *b_arg, int *cmpp); +extern int __wt_btcur_compare_equal( WT_CURSOR_BTREE *a_arg, WT_CURSOR_BTREE *b_arg, int *cmpp); extern int __wt_btcur_range_truncate(WT_CURSOR_BTREE *start, WT_CURSOR_BTREE *stop); extern int __wt_btcur_close(WT_CURSOR_BTREE *cbt); extern int __wt_debug_set_verbose(WT_SESSION_IMPL *session, const char *v); diff --git a/src/include/wiredtiger.in b/src/include/wiredtiger.in index c8b242b8f14..a76ab67ae1a 100644 --- a/src/include/wiredtiger.in +++ b/src/include/wiredtiger.in @@ -270,7 +270,8 @@ struct __wt_cursor { */ /*! * Return the ordering relationship between two cursors: both cursors - * must have the same data source and have valid keys. + * must have the same data source and have valid keys. (When testing + * only for equality, WT_CURSOR::compare_equality may be faster.) * * @snippet ex_all.c Cursor comparison * @@ -286,6 +287,22 @@ struct __wt_cursor { int __F(compare)(WT_CURSOR *cursor, WT_CURSOR *other, int *comparep); /*! + * Return the ordering relationship between two cursors, testing only + * for equality: both cursors must have the same data source and have + * valid keys. + * + * @snippet ex_all.c Cursor equality + * + * @param cursor the cursor handle + * @param other another cursor handle + * @param equalityp the status of the comparison: 0 if the cursors + * refer to the same key, otherwise not 0. + * @errors + */ + int __F(compare_equal) + (WT_CURSOR *cursor, WT_CURSOR *other, int *equalityp); + + /*! * Return the next record. * * @snippet ex_all.c Return the next record diff --git a/src/lsm/lsm_cursor.c b/src/lsm/lsm_cursor.c index 52bd3e9373d..257c7dee449 100644 --- a/src/lsm/lsm_cursor.c +++ b/src/lsm/lsm_cursor.c @@ -1431,6 +1431,7 @@ __wt_clsm_open(WT_SESSION_IMPL *session, __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __clsm_compare, /* compare */ + __clsm_compare, /* compare_equal */ __clsm_next, /* next */ __clsm_prev, /* prev */ __clsm_reset, /* reset */ diff --git a/test/suite/test_cursor_compare.py b/test/suite/test_cursor_compare.py index 227505b14ce..536f5cb0c3f 100644 --- a/test/suite/test_cursor_compare.py +++ b/test/suite/test_cursor_compare.py @@ -35,8 +35,9 @@ class test_cursor_comparison(wttest.WiredTigerTestCase): name = 'test_compare' types = [ - ('file', dict(type='file:')), - ('table', dict(type='table:')) + ('file', dict(type='file:', config='')), + ('lsm', dict(type='table:', config=',type=lsm')), + ('table', dict(type='table:', config='')) ] keyfmt = [ ('integer', dict(keyfmt='i')), @@ -47,32 +48,128 @@ class test_cursor_comparison(wttest.WiredTigerTestCase): def test_cursor_comparison(self): uri = self.type + 'compare' + uriX = self.type + 'compareX' # Build the object. if self.type == 'file:': - simple_populate(self, uri, 'key_format=' + self.keyfmt, 100) + simple_populate(self, uri, + 'key_format=' + self.keyfmt + self.config, 100) + simple_populate(self, uriX, + 'key_format=' + self.keyfmt + self.config, 100) else: - complex_populate(self, uri, 'key_format=' + self.keyfmt, 100) + complex_populate(self, uri, + 'key_format=' + self.keyfmt + self.config, 100) + complex_populate(self, uriX, + 'key_format=' + self.keyfmt + self.config, 100) c1 = self.session.open_cursor(uri, None) c2 = self.session.open_cursor(uri, None) - # Confirm the method fails unless the keys are set. + # Confirm failure unless the keys are set. msg = '/requires key be set/' self.assertRaisesWithMessage( wiredtiger.WiredTigerError, lambda: c1.compare(c2), msg) self.assertRaisesWithMessage( wiredtiger.WiredTigerError, lambda: c2.compare(c1), msg) - # Test cursors in all three orders. + # Test cursors before they're positioned. c1.set_key(key_populate(c1, 10)) - self.assertEquals(c1.search(), 0) c2.set_key(key_populate(c2, 20)) - self.assertEquals(c2.search(), 0) self.assertGreater(c2.compare(c1), 0) self.assertLess(c1.compare(c2), 0) c2.set_key(key_populate(c2, 10)) - self.assertEquals(c1.compare(c2), 0) + self.assertEqual(c1.compare(c2), 0) + self.assertEqual(c2.compare(c1), 0) + + # Confirm failure for different objects. + cX = self.session.open_cursor(uriX, None) + cX.set_key(key_populate(cX, 10)) + msg = '/must reference the same object/' + self.assertRaisesWithMessage( + wiredtiger.WiredTigerError, lambda: cX.compare(c1), msg) + + # Test cursors after they're positioned (shouldn't matter for compare). + c1.set_key(key_populate(c1, 10)) + self.assertEqual(c1.search(), 0) + c2.set_key(key_populate(c2, 20)) + self.assertEqual(c2.search(), 0) + self.assertGreater(c2.compare(c1), 0) + self.assertLess(c1.compare(c2), 0) + c2.set_key(key_populate(c2, 10)) + self.assertEqual(c2.search(), 0) + self.assertEqual(c1.compare(c2), 0) + self.assertEqual(c2.compare(c1), 0) + + # Confirm failure for different objects. + cX = self.session.open_cursor(uriX, None) + cX.set_key(key_populate(cX, 10)) + self.assertEqual(cX.search(), 0) + msg = '/must reference the same object/' + self.assertRaisesWithMessage( + wiredtiger.WiredTigerError, lambda: cX.compare(c1), msg) + + def test_cursor_equality(self): + uri = self.type + 'equality' + uriX = self.type + 'compareX' + + # Build the object. + if self.type == 'file:': + simple_populate(self, uri, + 'key_format=' + self.keyfmt + self.config, 100) + simple_populate(self, uriX, + 'key_format=' + self.keyfmt + self.config, 100) + else: + complex_populate(self, uri, + 'key_format=' + self.keyfmt + self.config, 100) + complex_populate(self, uriX, + 'key_format=' + self.keyfmt + self.config, 100) + + c1 = self.session.open_cursor(uri, None) + c2 = self.session.open_cursor(uri, None) + + # Confirm failure unless the keys are set. + msg = '/requires key be set/' + self.assertRaisesWithMessage( + wiredtiger.WiredTigerError, lambda: c1.compare_equal(c2), msg) + self.assertRaisesWithMessage( + wiredtiger.WiredTigerError, lambda: c2.compare_equal(c1), msg) + + # Test cursors before they're positioned. + c1.set_key(key_populate(c1, 10)) + c2.set_key(key_populate(c2, 20)) + self.assertNotEqual(c1.compare_equal(c2), 0) + self.assertNotEqual(c2.compare_equal(c1), 0) + c2.set_key(key_populate(c2, 10)) + self.assertEqual(c1.compare_equal(c2), 0) + self.assertEqual(c2.compare_equal(c1), 0) + + # Confirm failure for different objects. + cX = self.session.open_cursor(uriX, None) + cX.set_key(key_populate(cX, 10)) + msg = '/must reference the same object/' + self.assertRaisesWithMessage( + wiredtiger.WiredTigerError, lambda: cX.compare(c1), msg) + + # Test cursors after they're positioned (internally, it's a different + # search path if keys are positioned in the tree). + c1.set_key(key_populate(c1, 10)) + self.assertEqual(c1.search(), 0) + c2.set_key(key_populate(c2, 20)) + self.assertEqual(c2.search(), 0) + self.assertNotEqual(c1.compare_equal(c2), 0) + self.assertNotEqual(c2.compare_equal(c1), 0) + c2.set_key(key_populate(c2, 10)) + self.assertEqual(c2.search(), 0) + self.assertEqual(c1.compare_equal(c2), 0) + self.assertEqual(c2.compare_equal(c1), 0) + + # Confirm failure for different objects. + cX = self.session.open_cursor(uriX, None) + cX.set_key(key_populate(cX, 10)) + self.assertEqual(cX.search(), 0) + msg = '/must reference the same object/' + self.assertRaisesWithMessage( + wiredtiger.WiredTigerError, lambda: cX.compare(c1), msg) if __name__ == '__main__': |