Commit 2db02904 authored by Rich Prohaska's avatar Rich Prohaska

DB-759 test and fix alter table bug with cardinality data

parent 2b13aba8
This diff is collapsed.
# test that add index keeps cardinality for older indexes
source include/have_tokudb.inc;
set default_storage_engine='tokudb';
disable_warnings;
drop table if exists tt;
enable_warnings;
create table tt (a int, b int, c int, primary key(a), key(b), key(c));
let $a=0;
while ($a < 500) {
eval insert into tt values ($a, $a, 0), ($a+1, $a, 0), ($a+2, $a, 0), ($a+3, $a, 0);
inc $a; inc $a; inc $a; inc $a;
}
select count(*) from tt;
# compute cardinality
show indexes from tt;
analyze table tt;
show indexes from tt;
# drop key b
alter table tt drop key b;
show indexes from tt;
# drop key c
alter table tt drop key c;
show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
drop table tt;
......@@ -528,7 +528,7 @@ bool ha_tokudb::inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha
error = alter_table_expand_blobs(altered_table, ha_alter_info);
if (error == 0 && ctx->reset_card) {
error = tokudb::set_card_from_status(share->status_block, ctx->alter_txn, table->s, altered_table->s);
error = tokudb::alter_card(share->status_block, ctx->alter_txn, table->s, altered_table->s);
}
if (error == 0 && ctx->optimize_needed) {
error = do_optimize(ha_thd());
......
......@@ -118,7 +118,7 @@ static void test_no_keys(DB_ENV *env) {
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 };
......@@ -143,7 +143,7 @@ static void test_keys(DB_ENV *env) {
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;
......@@ -190,7 +190,7 @@ static void test_drop_0(DB_ENV *env) {
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;
......@@ -249,7 +249,7 @@ static void test_drop_1(DB_ENV *env) {
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;
......@@ -308,7 +308,7 @@ static void test_drop_2(DB_ENV *env) {
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;
......@@ -357,6 +357,65 @@ static void test_drop_2(DB_ENV *env) {
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;
......@@ -367,7 +426,7 @@ static void test_add_0(DB_ENV *env) {
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;
......@@ -426,7 +485,7 @@ static void test_add_1(DB_ENV *env) {
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;
......@@ -485,7 +544,7 @@ static void test_add_2(DB_ENV *env) {
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;
......@@ -503,7 +562,7 @@ static void test_add_2(DB_ENV *env) {
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*/,
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" },
......@@ -534,6 +593,65 @@ static void test_add_2(DB_ENV *env) {
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;
......@@ -547,7 +665,7 @@ int main() {
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);
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);
......@@ -555,12 +673,14 @@ int main() {
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;
}
......@@ -174,9 +174,14 @@ namespace tokudb {
return false;
}
static void copy_card(uint64_t *dest, uint64_t *src, size_t n) {
for (size_t i = 0; i < n; i++)
dest[i] = src[i];
}
// Altered table cardinality = select cardinality data from current table cardinality for keys that exist
// in the altered table and the current table.
int set_card_from_status(DB *status_db, DB_TXN *txn, TABLE_SHARE *table_share, TABLE_SHARE *altered_table_share) {
int alter_card(DB *status_db, DB_TXN *txn, TABLE_SHARE *table_share, TABLE_SHARE *altered_table_share) {
int error;
// read existing cardinality data from status
uint table_total_key_parts = tokudb::compute_total_key_parts(table_share);
......@@ -201,7 +206,7 @@ namespace tokudb {
uint ith_key_parts = get_key_parts(&altered_table_share->key_info[i]);
uint orig_key_index;
if (find_index_of_key(altered_table_share->key_info[i].name, table_share, &orig_key_index)) {
memcpy(&altered_rec_per_key[next_key_parts], &rec_per_key[orig_key_offset[orig_key_index]], ith_key_parts);
copy_card(&altered_rec_per_key[next_key_parts], &rec_per_key[orig_key_offset[orig_key_index]], ith_key_parts);
}
next_key_parts += ith_key_parts;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment