/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: #ident "$Id$" /*====== This file is part of TokuDB Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. TokuDBis is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. TokuDB is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with TokuDB. If not, see . ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." // test tokudb cardinality in status dictionary #include #include #include #include #include #include #include #include typedef unsigned long long ulonglong; #include #include #include "fake_mysql.h" #if __APPLE__ typedef unsigned long ulong; #endif #include static void test_no_keys(DB_ENV *env) { int error; DB_TXN *txn = NULL; error = env->txn_begin(env, NULL, &txn, 0); assert(error == 0); DB *status_db = NULL; error = tokudb::create_status(env, &status_db, "status_no_keys", txn); assert(error == 0); const uint keys = 0; const uint key_parts = 0; TABLE_SHARE s = { MAX_KEY, keys, key_parts, NULL }; error = tokudb::alter_card(status_db, txn, &s, &s); assert(error == 0); error = txn->commit(txn, 0); assert(error == 0); error = tokudb::close_status(&status_db); assert(error == 0); } static void test_keys(DB_ENV *env) { int error; DB_TXN *txn = NULL; error = env->txn_begin(env, NULL, &txn, 0); assert(error == 0); DB *status_db = NULL; error = tokudb::create_status(env, &status_db, "status_keys", txn); assert(error == 0); // define tables const uint ta_keys = 3; const uint ta_key_parts = 1; const int ta_rec_per_keys = ta_keys * ta_key_parts; uint64_t ta_rec_per_key[ta_rec_per_keys] = { 1000, 2000, 3000, }; KEY_INFO ta_key_info[ta_rec_per_keys] = { { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_a" }, { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_b" }, { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_c" }, }; TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; // set initial cardinality error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); assert(error == 0); error = tokudb::alter_card(status_db, txn, &ta, &ta); assert(error == 0); // verify uint64_t current_rec_per_key[ta_rec_per_keys]; error = tokudb::get_card_from_status(status_db, txn, ta_rec_per_keys, current_rec_per_key); assert(error == 0); for (uint i = 0; i < ta_rec_per_keys; i++) { assert(current_rec_per_key[i] == ta_rec_per_key[i]); } error = txn->commit(txn, 0); assert(error == 0); error = tokudb::close_status(&status_db); assert(error == 0); } static void test_drop_0(DB_ENV *env) { int error; DB_TXN *txn = NULL; error = env->txn_begin(env, NULL, &txn, 0); assert(error == 0); DB *status_db = NULL; error = tokudb::create_status(env, &status_db, "status_drop_0", txn); assert(error == 0); // define tables const uint ta_keys = 3; const uint ta_key_parts = 1; const uint ta_rec_per_keys = ta_keys * ta_key_parts; uint64_t ta_rec_per_key[ta_rec_per_keys] = { 1000, 2000, 3000, }; KEY_INFO ta_key_info[ta_rec_per_keys] = { { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_a" }, { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_b" }, { 0, ta_key_parts, &ta_rec_per_key[2], (char *) "key_c" }, }; TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; const uint tb_keys = 2; const uint tb_key_parts = 1; const int tb_rec_per_keys = tb_keys * tb_key_parts; uint64_t tb_rec_per_key[tb_rec_per_keys] = { 2000, 3000, }; KEY_INFO tb_key_info[tb_rec_per_keys] = { { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_b" }, { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_c" }, }; TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; // set initial cardinality error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); assert(error == 0); error = tokudb::alter_card(status_db, txn, &ta, &tb); assert(error == 0); // verify uint64_t current_rec_per_key[tb_rec_per_keys]; error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); assert(error == 0); for (uint i = 0; i < tb_rec_per_keys; i++) { assert(current_rec_per_key[i] == tb_rec_per_key[i]); } error = txn->commit(txn, 0); assert(error == 0); error = tokudb::close_status(&status_db); assert(error == 0); } static void test_drop_1(DB_ENV *env) { int error; DB_TXN *txn = NULL; error = env->txn_begin(env, NULL, &txn, 0); assert(error == 0); DB *status_db = NULL; error = tokudb::create_status(env, &status_db, "status_drop_1", txn); assert(error == 0); // define tables const uint ta_keys = 3; const uint ta_key_parts = 1; const uint ta_rec_per_keys = ta_keys * ta_key_parts; uint64_t ta_rec_per_key[ta_rec_per_keys] = { 1000, 2000, 3000, }; KEY_INFO ta_key_info[ta_rec_per_keys] = { { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_a" }, { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_b" }, { 0, ta_key_parts, &ta_rec_per_key[2], (char *) "key_c" }, }; TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; const uint tb_keys = 2; const uint tb_key_parts = 1; const int tb_rec_per_keys = tb_keys * tb_key_parts; uint64_t tb_rec_per_key[tb_rec_per_keys] = { 1000, 3000, }; KEY_INFO tb_key_info[tb_rec_per_keys] = { { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_a" }, { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_c" }, }; TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; // set initial cardinality error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); assert(error == 0); error = tokudb::alter_card(status_db, txn, &ta, &tb); assert(error == 0); // verify uint64_t current_rec_per_key[tb_rec_per_keys]; error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); assert(error == 0); for (uint i = 0; i < tb_rec_per_keys; i++) { assert(current_rec_per_key[i] == tb_rec_per_key[i]); } error = txn->commit(txn, 0); assert(error == 0); error = tokudb::close_status(&status_db); assert(error == 0); } static void test_drop_2(DB_ENV *env) { int error; DB_TXN *txn = NULL; error = env->txn_begin(env, NULL, &txn, 0); assert(error == 0); DB *status_db = NULL; error = tokudb::create_status(env, &status_db, "status_drop_2", txn); assert(error == 0); // define tables const uint ta_keys = 3; const uint ta_key_parts = 1; const uint ta_rec_per_keys = ta_keys * ta_key_parts; uint64_t ta_rec_per_key[ta_rec_per_keys] = { 1000, 2000, 3000, }; KEY_INFO ta_key_info[ta_rec_per_keys] = { { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_a" }, { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_b" }, { 0, ta_key_parts, &ta_rec_per_key[2], (char *) "key_c" }, }; TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; const uint tb_keys = 2; const uint tb_key_parts = 1; const int tb_rec_per_keys = tb_keys * tb_key_parts; uint64_t tb_rec_per_key[tb_rec_per_keys] = { 1000, 2000, }; KEY_INFO tb_key_info[tb_rec_per_keys] = { { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_a" }, { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_b" }, }; TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; // set initial cardinality error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); assert(error == 0); error = tokudb::alter_card(status_db, txn, &ta, &tb); assert(error == 0); // verify uint64_t current_rec_per_key[tb_rec_per_keys]; error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); assert(error == 0); for (uint i = 0; i < tb_rec_per_keys; i++) { assert(current_rec_per_key[i] == tb_rec_per_key[i]); } error = txn->commit(txn, 0); assert(error == 0); error = tokudb::close_status(&status_db); assert(error == 0); } static void test_drop_1_multiple_parts(DB_ENV *env) { int error; DB_TXN *txn = NULL; error = env->txn_begin(env, NULL, &txn, 0); assert(error == 0); DB *status_db = NULL; error = tokudb::create_status(env, &status_db, "status_drop_1_multiple_parts", txn); assert(error == 0); // define tables const uint ta_keys = 3; const uint ta_key_parts = 1+2+3; const uint ta_rec_per_keys = ta_key_parts; uint64_t ta_rec_per_key[ta_rec_per_keys] = { 1000, 2000, 2001, 3000, 3001, 3002, }; KEY_INFO ta_key_info[ta_rec_per_keys] = { { 0, 1, &ta_rec_per_key[0], (char *) "key_a" }, { 0, 2, &ta_rec_per_key[0+1], (char *) "key_b" }, { 0, 3, &ta_rec_per_key[0+1+2], (char *) "key_c" }, }; TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; const uint tb_keys = 2; const uint tb_key_parts = 1+3; const int tb_rec_per_keys = tb_key_parts; uint64_t tb_rec_per_key[tb_rec_per_keys] = { 1000, 3000, 3001, 3002, }; KEY_INFO tb_key_info[tb_rec_per_keys] = { { 0, 1, &tb_rec_per_key[0], (char *) "key_a" }, { 0, 3, &tb_rec_per_key[0+1], (char *) "key_c" }, }; TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; // set initial cardinality error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); assert(error == 0); error = tokudb::alter_card(status_db, txn, &ta, &tb); assert(error == 0); // verify uint64_t current_rec_per_key[tb_rec_per_keys]; error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); assert(error == 0); for (uint i = 0; i < tb_rec_per_keys; i++) { assert(current_rec_per_key[i] == tb_rec_per_key[i]); } error = txn->commit(txn, 0); assert(error == 0); error = tokudb::close_status(&status_db); assert(error == 0); } static void test_add_0(DB_ENV *env) { int error; DB_TXN *txn = NULL; error = env->txn_begin(env, NULL, &txn, 0); assert(error == 0); DB *status_db = NULL; error = tokudb::create_status(env, &status_db, "status_add_0", txn); assert(error == 0); // define tables const uint ta_keys = 2; const uint ta_key_parts = 1; const uint ta_rec_per_keys = ta_keys * ta_key_parts; uint64_t ta_rec_per_key[ta_rec_per_keys] = { 2000, 3000, }; KEY_INFO ta_key_info[ta_rec_per_keys] = { { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_b" }, { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_c" }, }; TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; const uint tb_keys = 3; const uint tb_key_parts = 1; const int tb_rec_per_keys = tb_keys * tb_key_parts; uint64_t tb_rec_per_key[tb_rec_per_keys] = { 0 /*not computed*/, 2000, 3000, }; KEY_INFO tb_key_info[tb_rec_per_keys] = { { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_a" }, { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_b" }, { 0, tb_key_parts, &tb_rec_per_key[2], (char *) "key_c" }, }; TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; // set initial cardinality error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); assert(error == 0); error = tokudb::alter_card(status_db, txn, &ta, &tb); assert(error == 0); // verify uint64_t current_rec_per_key[tb_rec_per_keys]; error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); assert(error == 0); for (uint i = 0; i < tb_rec_per_keys; i++) { assert(current_rec_per_key[i] == tb_rec_per_key[i]); } error = txn->commit(txn, 0); assert(error == 0); error = tokudb::close_status(&status_db); assert(error == 0); } static void test_add_1(DB_ENV *env) { int error; DB_TXN *txn = NULL; error = env->txn_begin(env, NULL, &txn, 0); assert(error == 0); DB *status_db = NULL; error = tokudb::create_status(env, &status_db, "status_add_1", txn); assert(error == 0); // define tables const uint ta_keys = 2; const uint ta_key_parts = 1; const uint ta_rec_per_keys = ta_keys * ta_key_parts; uint64_t ta_rec_per_key[ta_rec_per_keys] = { 2000, 3000, }; KEY_INFO ta_key_info[ta_rec_per_keys] = { { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_b" }, { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_c" }, }; TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; const uint tb_keys = 3; const uint tb_key_parts = 1; const int tb_rec_per_keys = tb_keys * tb_key_parts; uint64_t tb_rec_per_key[tb_rec_per_keys] = { 2000, 0 /*not computed*/, 3000, }; KEY_INFO tb_key_info[tb_rec_per_keys] = { { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_b" }, { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_a" }, { 0, tb_key_parts, &tb_rec_per_key[2], (char *) "key_c" }, }; TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; // set initial cardinality error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); assert(error == 0); error = tokudb::alter_card(status_db, txn, &ta, &tb); assert(error == 0); // verify uint64_t current_rec_per_key[tb_rec_per_keys]; error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); assert(error == 0); for (uint i = 0; i < tb_rec_per_keys; i++) { assert(current_rec_per_key[i] == tb_rec_per_key[i]); } error = txn->commit(txn, 0); assert(error == 0); error = tokudb::close_status(&status_db); assert(error == 0); } static void test_add_2(DB_ENV *env) { int error; DB_TXN *txn = NULL; error = env->txn_begin(env, NULL, &txn, 0); assert(error == 0); DB *status_db = NULL; error = tokudb::create_status(env, &status_db, "status_add_2", txn); assert(error == 0); // define tables const uint ta_keys = 2; const uint ta_key_parts = 1; const uint ta_rec_per_keys = ta_keys * ta_key_parts; uint64_t ta_rec_per_key[ta_rec_per_keys] = { 2000, 3000, }; KEY_INFO ta_key_info[ta_rec_per_keys] = { { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_b" }, { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_c" }, }; TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; const uint tb_keys = 3; const uint tb_key_parts = 1; const int tb_rec_per_keys = tb_keys * tb_key_parts; uint64_t tb_rec_per_key[tb_rec_per_keys] = { 2000, 3000, 0 /*not computed*/, }; KEY_INFO tb_key_info[tb_rec_per_keys] = { { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_b" }, { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_c" }, { 0, tb_key_parts, &tb_rec_per_key[2], (char *) "key_a" }, }; TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; // set initial cardinality error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); assert(error == 0); error = tokudb::alter_card(status_db, txn, &ta, &tb); assert(error == 0); // verify uint64_t current_rec_per_key[tb_rec_per_keys]; error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); assert(error == 0); for (uint i = 0; i < tb_rec_per_keys; i++) { assert(current_rec_per_key[i] == tb_rec_per_key[i]); } error = txn->commit(txn, 0); assert(error == 0); error = tokudb::close_status(&status_db); assert(error == 0); } static void test_add_0_multiple_parts(DB_ENV *env) { int error; DB_TXN *txn = NULL; error = env->txn_begin(env, NULL, &txn, 0); assert(error == 0); DB *status_db = NULL; error = tokudb::create_status(env, &status_db, "status_add_0_multiple_parts", txn); assert(error == 0); // define tables const uint ta_keys = 2; const uint ta_key_parts = 3+4; const uint ta_rec_per_keys = ta_key_parts; uint64_t ta_rec_per_key[ta_rec_per_keys] = { 2000, 2001, 2002, 3000, 3001, 3002, 3003, }; KEY_INFO ta_key_info[ta_rec_per_keys] = { { 0, 3, &ta_rec_per_key[0], (char *) "key_b" }, { 0, 4, &ta_rec_per_key[3], (char *) "key_c" }, }; TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; const uint tb_keys = 3; const uint tb_key_parts = 2+3+4; const int tb_rec_per_keys = tb_key_parts; uint64_t tb_rec_per_key[tb_rec_per_keys] = { 0, 0 /*not computed*/, 2000, 2001, 2002, 3000, 3001, 3002, 3003, }; KEY_INFO tb_key_info[tb_rec_per_keys] = { { 0, 2, &tb_rec_per_key[0], (char *) "key_a" }, { 0, 3, &tb_rec_per_key[0+2], (char *) "key_b" }, { 0, 4, &tb_rec_per_key[0+2+3], (char *) "key_c" }, }; TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; // set initial cardinality error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); assert(error == 0); error = tokudb::alter_card(status_db, txn, &ta, &tb); assert(error == 0); // verify uint64_t current_rec_per_key[tb_rec_per_keys]; error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); assert(error == 0); for (uint i = 0; i < tb_rec_per_keys; i++) { assert(current_rec_per_key[i] == tb_rec_per_key[i]); } error = txn->commit(txn, 0); assert(error == 0); error = tokudb::close_status(&status_db); assert(error == 0); } int main() { int error; error = system("rm -rf " __FILE__ ".testdir"); assert(error == 0); error = mkdir(__FILE__ ".testdir", S_IRWXU+S_IRWXG+S_IRWXO); assert(error == 0); DB_ENV *env = NULL; error = db_env_create(&env, 0); assert(error == 0); error = env->open(env, __FILE__ ".testdir", DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(error == 0); test_no_keys(env); test_keys(env); test_drop_0(env); test_drop_1(env); test_drop_2(env); test_drop_1_multiple_parts(env); test_add_0(env); test_add_1(env); test_add_2(env); test_add_0_multiple_parts(env); error = env->close(env, 0); assert(error == 0); return 0; }