summaryrefslogtreecommitdiff
path: root/test/csuite/wt2447_join_main_table/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/csuite/wt2447_join_main_table/main.c')
-rw-r--r--test/csuite/wt2447_join_main_table/main.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/test/csuite/wt2447_join_main_table/main.c b/test/csuite/wt2447_join_main_table/main.c
new file mode 100644
index 00000000000..a6f19cb0858
--- /dev/null
+++ b/test/csuite/wt2447_join_main_table/main.c
@@ -0,0 +1,189 @@
+/*-
+ * Public Domain 2014-2016 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.
+ */
+#include "test_util.h"
+
+/*
+ * JIRA ticket reference: WT-2447
+ *
+ * Test case description: This test case is adapted from the submitted test
+ * program in the JIRA ticket. We create a database of 10,000 entries, with
+ * every key i having pair of values (i, i). Create indices on both values,
+ * and establish a join: table.v1 >= 5000 AND table.v2 < 5001. There's a
+ * Bloom filter on v2. We expect that although we iterate from 5000 to
+ * 10000, we'll only have accesses to the main table for key 5000, as
+ * 5001-10000 will generally not be in the Bloom filter. For key 5000,
+ * we technically have two accesses to the main table - one occurs when we
+ * see key 5000 is in the Bloom filter, and we need to do a full test, we
+ * make an access to the projection table:tablename(v2), that's just to get
+ * the value of v2, which we'll check by comparison to the cursor at 5001.
+ * That counts as a main table access, and when we see it is satisfied and
+ * return the complete set of values, we'll access the main table with the
+ * full projection (that's the second main table access).
+ *
+ * Failure mode: Before fixes of WT-2447, we saw lots of accesses to the main
+ * table.
+ */
+
+void (*custom_die)(void) = NULL;
+
+#define N_RECORDS 10000
+
+static void
+get_stat_total(WT_SESSION *session, WT_CURSOR *jcursor, const char *descmatch,
+ uint64_t *pval)
+{
+ WT_CURSOR *statcursor;
+ uint64_t val;
+ int ret;
+ bool match;
+ char *desc, *valstr;
+
+ match = false;
+ *pval = 0;
+ testutil_check(session->open_cursor(session, "statistics:join", jcursor,
+ NULL, &statcursor));
+
+ while ((ret = statcursor->next(statcursor)) == 0) {
+ testutil_assert(statcursor->get_value(
+ statcursor, &desc, &valstr, &val) == 0);
+
+ printf("statistics: %s: %s: %" PRIu64 "\n", desc, valstr, val);
+
+ if (strstr(desc, descmatch) != NULL) {
+ *pval += val;
+ match = true;
+ }
+ }
+ testutil_assert(ret == WT_NOTFOUND);
+ testutil_check(statcursor->close(statcursor));
+ testutil_assert(match);
+}
+
+int
+main(int argc, char *argv[])
+{
+ TEST_OPTS *opts, _opts;
+ WT_CURSOR *cursor1, *cursor2, *jcursor;
+ WT_ITEM d;
+ WT_SESSION *session;
+ uint64_t maincount;
+ int half, i, j;
+ const char *tablename;
+ char bloom_cfg[128], index1uri[256], index2uri[256], joinuri[256];
+
+ opts = &_opts;
+ memset(opts, 0, sizeof(*opts));
+ testutil_check(testutil_parse_opts(argc, argv, opts));
+ testutil_make_work_dir(opts->home);
+
+ tablename = strchr(opts->uri, ':');
+ testutil_assert(tablename != NULL);
+ tablename++;
+ snprintf(index1uri, sizeof(index1uri), "index:%s:index1", tablename);
+ snprintf(index2uri, sizeof(index2uri), "index:%s:index2", tablename);
+ snprintf(joinuri, sizeof(joinuri), "join:%s", opts->uri);
+
+ testutil_check(wiredtiger_open(opts->home, NULL,
+ "statistics=(all),create", &opts->conn));
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &session));
+
+ testutil_check(session->create(session, opts->uri,
+ "key_format=i,value_format=iiu,columns=(k,v1,v2,d)"));
+ testutil_check(session->create(session, index1uri, "columns=(v1)"));
+ testutil_check(session->create(session, index2uri, "columns=(v2)"));
+
+ testutil_check(session->open_cursor(session, opts->uri, NULL, NULL,
+ &cursor1));
+
+ d.size = 4100;
+ d.data = dmalloc(d.size);
+ memset((char *)d.data, 7, d.size);
+
+ for (i = 0; i < N_RECORDS; ++i)
+ {
+ cursor1->set_key(cursor1, i);
+ cursor1->set_value(cursor1, i, i, &d);
+ testutil_check(cursor1->insert(cursor1));
+ }
+
+ free((void*)d.data);
+
+ testutil_check(opts->conn->close(opts->conn, NULL));
+ testutil_check(wiredtiger_open(opts->home, NULL,
+ "statistics=(all),create,cache_size=1GB", &opts->conn));
+ testutil_check(opts->conn->open_session(opts->conn, NULL, NULL,
+ &session));
+
+ testutil_check(session->open_cursor(session, index1uri, NULL, NULL,
+ &cursor1));
+ testutil_check(session->open_cursor(session, index2uri, NULL, NULL,
+ &cursor2));
+
+ half = N_RECORDS / 2;
+ cursor1->set_key(cursor1, half);
+ testutil_check(cursor1->search(cursor1));
+
+ cursor2->set_key(cursor2, half + 1);
+ testutil_check(cursor2->search(cursor2));
+
+ sprintf(bloom_cfg, "compare=lt,strategy=bloom,count=%d", half);
+
+ testutil_check(session->open_cursor(session, joinuri, NULL, NULL,
+ &jcursor));
+ testutil_check(session->join(session, jcursor, cursor1, "compare=ge"));
+ testutil_check(session->join(session, jcursor, cursor2, bloom_cfg));
+
+ /* Expect one value returned */
+ testutil_assert(jcursor->next(jcursor) == 0);
+ i = 0;
+ testutil_assert(jcursor->get_key(jcursor, &i) == 0);
+ testutil_assert(i == (int)half);
+ i = j = 0;
+ memset(&d, 0, sizeof(d));
+ testutil_assert(jcursor->get_value(jcursor, &i, &j, &d) == 0);
+ testutil_assert(i == (int)half);
+ testutil_assert(j == (int)half);
+ testutil_assert(d.size == 4100);
+ for (i = 0; i < 4100; i++)
+ testutil_assert(((char *)d.data)[i] == 7);
+
+ testutil_assert(jcursor->next(jcursor) == WT_NOTFOUND);
+
+ /*
+ * Make sure there have been 2 accesses to the main table,
+ * explained in the discussion above.
+ */
+ get_stat_total(session, jcursor, "accesses to the main table",
+ &maincount);
+ testutil_assert(maincount == 2);
+
+ testutil_cleanup(opts);
+
+ return (0);
+}